Sensor Network
(IoT)
Solution Architecture
Session 5
IOT Arduino
PWM-ADC-Serial
Communication
Ramesh Loganathan
Sunil Jardosh
Layers of IOT Solution Architecture
Information
Application
Application Layer
Information
Processing
Event Processing Layer
Information
Transmission
Collector & Integrator Layer
Information
Generation Event Producer Layer
Devices
• Arudino Uno
• Rasberry Pi
• BeagleBoard
Sensors/
Memory
Actuator
Power
Controller
Supply
Communication
DC Motor
• They draw more current than USB/Arduino can supply
(40mA per pin) so need another power supply:
batteries / wall-wart
Current through in 1 direction
turns them in 1 direction 6v
PWM
More voltage = More speed, control?
Use electronically controlled switch (transistor) Motor
between motor and batteries
Use PWM pin to control switch
Analog Sensors
Sensors Variables
Mic soundVolume
Photoresistor lightLevel
Potentiometer dialPosition
Temp Sensor temperature
Flex Sensor bend
Accelerometer tilt/acceleration
Analog Out (PWM) Concept
• Explain what is meant by Pulse Width
Modulation (PWM)
• Explain how a microcontroller can output a
pseudo-analog signal using PWM
Analog Out (PWM) Concept
• No facility exists on most microcontrollers to
directly output an analog voltage (i.e., a
voltage that varies continuously over the
range of 0 to 5V)
– Use Pulse Width Modulation (PWM) to
approximate
• Digital outputs are capable of 0V or 5V
• Over a fraction (ton) of a time period tcycle, keep pin at
5V, the rest of the time, at 0V
– Average voltage is proportional to ton/tcycle, called the ‘Duty
Cycle’
Analog Out (PWM) Concept
• Output voltage is averaged from on vs. off
time
Servo Motor
• Moves to desired position and stops,
limited range of 180° in 2 directions
3 wires: power = red
ground = brown
control = yellow
• Control circuit + potentiometer +
DC motor + position shaft with gears
Control signal uses PWM,
pulse width = position
Arduino analogWrite( )
• analogWrite(pin, value);
– 0 value 255
• 0% duty cycle --> 0 V --> analogWrite(pin, 0);
• 100% duty cycle --> 5 V --> analogWrite(pin, 255);
10% average
50% average
90% average
TIMER0 (8BIT PWM)
Manual PWM
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, HIGH);
delayMicroseconds(100);
// Approximately 10% duty cycle @ 1KHz
digitalWrite(13, LOW);
delayMicroseconds(1000 - 100);
}
7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TCCR0A COM0A COM0A COM0B COM0B - - WGM0 WGM00
1 0 1 0 1
Timer/Counter Control Register 0 A
COM0B1 COM0B0 DESCRIPTION
0 0 OC0B disabled
0 1 Reserved
1 0 None-inverted mode (HIGH at bottom, LOW on Match)
1 1 Inverted mode (LOW at bottom, HIGH on Match)
COM0A1 COM0A0 DESCRIPTION
0 0 OC0A disabled
0 1 WGM02 = 0: Normal Port Operation, OC0A Disconnected
WGM02 = 1: Toggle OC0A on Compare Match
1 0 None-inverted mode (HIGH at bottom, LOW on Match)
1 1 Inverted mode (LOW at bottom, HIGH on Match)
7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TIMSK0 - - - - - OCIE0B OIE0A TOIE0
Timer/Counter Interrupt Mask Register
7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TIFR0 - - - - - OCF0B OCF0A TOV0
Timer/Counter Interrupt Flag Register
7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
TCNT0
Timer/Counter Register (stores the counter value)
7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
OCR0A
Output Compare Register A-B (stores the compare value)
7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 bit
OCR0B
DDRD |= (1 << DDD6);
// PD6 is now an output
OCR0A = 128;
// set PWM for 50% duty cycle
TCCR0A |= (1 << COM0A1);
// set none-inverting mode
TCCR0A |= (1 << WGM01) | (1 << WGM00);
// set fast PWM Mode
TCCR0B |= (1 << CS01);
// set prescaler to 8 and starts PWM
TIMER1 (16BIT PWM)
TIMER2 (8BIT PWM)
Analog Input
To computers, analog is chunky
Analog Input
• Many states, not just two (HIGH/LOW)
• Number of states (or values, or “bins”) is
resolution
• Common computer resolutions:
– 8-bit = 256 values
– 16-bit = 65,536 values
– 32-bit = 4,294,967,296 values
Analog Input
• Arduino (ATmega168) has six ADC
inputs
• (ADC = Analog to Digital Converter)
• Reads voltage between 0 to 5 volts
• Resolution is 10-bit (1024 values)
• In other words, 5/1024 = 4.8 mV
smallest voltage change you can
measure
• sensorReading = analogRead(pin);
Analog Input
Sure sure, but how to make a varying voltage?
With a potentiometer. Or just pot.
+5V–
50k
measure–
gnd–
The pot you have
pots also look like this
Potentiometers
Moving the knob is like moving
where the arrow taps the voltage on the resistor
What good are pots?
• Anytime you need a ranged input
– (we’re used to knobs)
• Measure rotational position
– steering wheel, robotic joint, etc.
• But more importantly for us, potentiometers are a good example of a
resistive sensor
Arduino Analog Input
Plug pot directly into breadboard
Two “legs” plug into +5V & Gnd
(red + & blue -) buses
Middle “post” plugs into a row
(row 7 here)
Run a wire from that row to
Analog In 2
Pot & LED Circuit
This is what your board should have on it now
In schematics, inputs are usually on the left, outputs on the right
Also, more positive voltages are on the top, more negative on the bottom
ADC
ADMUX – ADC Multiplexer Selection Register
Bits 4:0 – MUX4:0 – Analog Channel and Gain Selection Bits
Bit 5 – ADLAR – ADC Left Adjust Result
Bits 7:6 – REFS1:0 – Reference Selection Bits
ADCSRA – ADC Control and Status Register A
Bit 7 – ADEN – ADC Enable
Bit 6 – ADSC – ADC Start Conversion
Bit 5 – ADATE – ADC Auto Trigger Enable
Bit 4 – ADIF – ADC Interrupt Flag
Bit 3 – ADIE – ADC Interrupt Enable
Bits 2:0 – ADPS2:0 – ADC Prescaler Select Bits
ADCL and ADCH – ADC Data Registers
SFIOR – Special Function I/O Register
Bits 7:5 – ADC Auto Trigger Source
ADC Programming
void adc_init()
{
// AREF = AVcc
ADMUX = (1<<REFS0);
// ADC Enable and prescaler of 128
// 16000000/128 = 125000
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
uint16_t adc_read(uint8_t ch)
{
// select the corresponding channel 0~7
// ANDing with ’7′ will always keep the value
// of ‘ch’ between 0 and 7
ch &= 0b00000111; // AND operation with 7
ADMUX = (ADMUX & 0xF8)|ch;
// clears the bottom 3 bits before ORing
// start single convertion
// write ’1′ to ADSC
ADCSRA |= (1<<ADSC);
// wait for conversion to complete
// ADSC becomes ’0′ again
// till then, run loop continuously
while(ADCSRA & (1<<ADSC));
return (ADC);
}
Serial Communication
Arduino Communications
is just serial communications
• Psst, Arduino doesn’t really do USB
• It really is “serial”, like old RS-232 serial
• All microcontrollers can do serial
• Not many can do USB
• Serial is easy, USB is hard
serial terminal from the olde days
Serial Communications
• “Serial” because data is broken down into bits, each
sent one after the other down a single wire.
• The single ASCII character ‘B’ is sent as:
‘B’ = 0 1 0 0 0 0 1 0
= L H L L L L H L
HIGH
=
LOW
• Toggle a pin to send data, just like blinking an LED
• You could implement sending serial data with
digitalWrite() and delay()
• A single data wire needed to send data. One other to receive.
Arduino & USB-to-serial
Arduino board is really two circuits
Arduino Mini
Arduino Mini separates the two circuits
Arduino Mini USB adapter Arduino Mini
Arduino to Computer
chip
USB is totally optional for Arduino
But it makes things easier
Arduino & USB
• Since Arduino is all about serial
• And not USB,
• Interfacing to things like USB flash drives,
USB hard disks, USB webcams, etc. is not
possible
Controlling the Computer
• Can send sensor data from Arduino to
computer with [Link]()
• There are many different variations to
suite your needs:
UCSR0A Name Description
bit 7 RXC0 USART Receive Complete. Set when data is available and the
data register has not be read yet.
bit 6 TXC0 USART Transmit Complete. Set when all data has transmitted.
bit 5 UDRE0 USART Data Register Empty. Set when the UDR0 register is
empty and new data can be transmitted.
bit 4 FE0 Frame Error. Set when next byte in the UDR0 register has a
framing error.
bit 3 DOR0 Data OverRun. Set when the UDR0 was not read before the
next frame arrived.
bit 2 UPE0 USART Parity Error. Set when next frame in the UDR0 has a
parity error.
bit 1 U2X0 USART Double Transmission Speed. When set decreases the bit
time by half doubling the speed.
bit 0 MPCM0 Multi-processor Communication Mode. When set incoming
data is ignored if no addressing information is provided.
UCSR0B Name Description
bit 7 RXCIE0 RX Complete Interrupt Enable. Set to allow receive complete
interrupts.
bit 6 TXCIE0 TX Complete Interrupt Enable. Set to allow transmission
complete interrupts.
bit 5 UDRIE0 USART Data Register Empty Interrupt Enable. Set to allow
data register empty interrupts.
bit 4 RXEN0 Receiver Enable. Set to enable receiver.
bit 3 TXEN0 Transmitter enable. Set to enable transmitter.
bit 2 UCSZ20 USART Character Size 0. Used together
with UCSZ01 and UCSZ00 to set data frame size. Available
sizes are 5-bit (000), 6-bit (001), 7-bit (010), 8-bit (011) and 9-
bit (111).
bit 1 RXB80 Receive Data Bit 8. When using 8 bit transmission the 8th bit
received.
bit 0 TXB80 Transmit Data Bit 8. When using 8 bit transmission the 8th bit
to be submitted.
UCSR0C Name Description
bit 7 UMSEL01 USART Mode Select 1 and 0. UMSEL01 and UMSEL00 combined
bit 6 UMSEL00 select the operating mode. Available modes are asynchronous
(00), synchronous (01) and master SPI (11).
bit 5 UPM01 USART Parity Mode 1 and 0. UPM01 and UPM00 select the
bit 4 UPM00 parity. Available modes are none (00), even (10) and odd (11).
bit 3 USBS0 USART Stop Bit Select. Set to select 1 stop bit. Unset to select 2
stop bits.
bit 2 UCSZ01 USART Character Size 1 and 0. Used together with
bit 1 UCSZ00 with UCSZ20 to set data frame size. Available sizes are 5-bit
(000), 6-bit (001), 7-bit (010), 8-bit (011) and 9-bit (111).
bit 0 UCPOL0 USART Clock Polarity. Set to transmit on falling edge and
sample on rising edge. Unset to transmit on rising edge and
sample on falling edge.
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU/(USART_BAUDRATE*16UL)))-1)
int main(void)
{
char recieved_byte;
UCSR0B |= (1<<RXEN0) | (1<<TXEN0);
UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
UBRR0H = (BAUD_PRESCALE >> 8);
UBRR0L = BAUD_PRESCALE;
for(;;)
{
// wait until a byte is ready to read
while( ( UCSR0A & ( 1 << RXC0 ) ) == 0 ){}
// grab the byte from the serial port
recieved_byte = UDR0;
// wait until the port is ready to be written to
while( ( UCSR0A & ( 1 << UDRE0 ) ) == 0 ){}
// write the byte to the serial port
UDR0 = recieved_byte;
}
return 0; /* never reached */
}
Serial Devices
to Wi-Fi to Ethernet
to graphic LCD
to 8-servo controller
Serial Communication
Asynchronous communication Synchronous communication
asynchronous – no clock Synchronous – with clock
Data represented by setting Data represented by setting
HIGH/LOW at given times HIGH/LOW when “clock” changes
A single clock wire & data wire for
Separate wires for transmit & receive
each direction like before
Neither needs good rhythm, but one is the
Each device must have good “rhythm”
conductor
I2C, aka “Two-wire”
Synchronous serial bus with shared a data line
a little network for your gadgets
• Up to 127 devices on one bus
• Up to 1Mbps data rate
• Really simple protocol (compared to USB,Ethernet,etc)
• Most microcontrollers have it built-in
Many I2C devices
non-volatile
memory
touch sensor compass
fm transmitter
And many others
(gyros,keyboards, motors,...)
temperature &
LCD display humidity sensor
Nunchuck Accelerometer
Z
X
Wii Remote & Nunchuck
accelerometer axes
I2C on Arduino
• I2C built-in on Arduino’s
ATmega168 chip
• Use “Wire” library to access it
• Analog In 4 is SDA signal
• Analog In 5 is SCK signal
SDA
SCK
Arduino “Wire” library
Writing Data
Load Wire library
Join I2C bus
(as master)
Start sending
Send data
Stop sending
Arduino “Wire” library
Reading Data
Join I2C bus
(as master)
Request data from device
Get data
What kinds of interactions you can have depends on
the device you’re talking to
Most devices have several “commands”
Thanks