Unit 4: Microcontrollers (Arduino) Overview Digital I/O
Unit 4: Microcontrollers (Arduino) Overview Digital I/O
Unit 4
Arduino Uno
• Arduino
– An Italian company which produces the printed circuit boards that
integrate processor, power sources, USB connector, etc.
– Hardware and software are open source.
– Very popular with hobbyists and engineers, due in a large part to their
low cost.
http://arduino.cc/en/Main/Products
4.5
Arduino Uno
• What’s on an Arduino Uno board?
Connectors for I/O lines D0 – D13
(Can be connected to other HW devices)
Reset button
USB interface
Atmel ATmega328P
16MHz oscillator
microcontroller
(i.e. clock signal
generator)
Power connector
(for use when not
connected to USB) Power and I/O lines A0 – A5
ground pins (Can be connected to other HW
devices)
4.6
Arduino Uno
• Arduino Unos can be stacked with "shield"
boards to add additional capabilities (Ethernet,
wireless, D/A, LCDs, sensors, motor control, etc.)
4.7
Arduino IDE
• Arduino provides an Integrated
Development Environment
(IDE) with libraries of code to
simplify use of integrated or
connected hardware devices
• Our goal is for you to learn
how to write that code from
scratch and how to develop
firmware, hardware device
drivers, etc.
– Thus, we will not use the IDE but This Photo by Unknown Author is licensed under CC BY-SA
Flashback to Week 1
• Recall the computer interacts with any input or output (I/O)
device by simply doing reads/writes to the memory locations
(often called registers) in the I/O interfaces…
• The Arduino has many of these I/O interfaces all connected via
the data bus
Processor Memory
0
…
3FF
A D C
Video
Interface 800
FE may 800 FE FE
signify a WRITE
…
white dot at
a particular 01
location
Keyboard
Interface
Atmel ATmega328P
• The Arduino Uno is based on
an Atmel ATmega328P 8-bit
microcontroller, which has Mem.
many useful hardware devices
integrated with the processor Processor
– 32kb of FLASH ROM
– 2048 bytes of RAM
– 3 timer/counters
– Serial/SPI/I2C interfaces
– A/D converter
– 23 I/O lines for connecting other
custom components Data Bus
4.10
Group D Group B
• Thus to deal with our digital inputs we
will put the bits into 3 groups: Group B,
Group C
C, and D
– We often refer to these groups as "ports"
but you'll see that "port" is used in multiple
places so we'll generally use "group"
Software to Arduino Name Mapping
Group B bit5-bit0 = DIG13-DIG8
Group C bit5-bit0 = A5-A0
Group D bit7-bit0 = DIG7-DIG0
4.12
Main Point: Each pin has a name the software uses (Portx) and a name used on the Arduino circuit board (Anx or DIGx)
4.13
A button
Arduino A0 GroupC bit 0
4.14
BIT FIDDLING
4.15
Bit-Fiddling Introduction
• The primary way that software (device drivers,
firmware, etc.) controls hardware is by manipulating
individual bits in certain hardware registers (memory
locations)
• Thus, we need to learn how to:
– Set a bit to a 1
– Clear a bit to a 0
– Check the value of a given bit (is it 0 or 1)
• Because computers do not access anything smaller
than a byte (8-bits) we must use logic operations to
manipulate individual bits within a byte
– These bit manipulations are often referred to as bit fiddling
4.16
Force Pass
Invert Pass
'0'
0 0 0 0 0 0 0 0 0
0 1 0 0 1 1 0 1 1
1 0 0 1 0 1 1 0 1
'1'
1 1 1 1 1 1 1 1 0
0 AND x = 0 0 OR x = x 0 XOR x = x
1 AND x = x 1 OR x = 1 1 XOR x = NOT x
x AND x = x x OR x = x x XOR x = 0
You already T1 X+0=X T1' X•1=X
knew the above T2 X+1=1 T2' X•0=0
ideas. It is just
T1-T3. T3 X+X=X T3' X•X=X
4.19
Bitwise Operations
• The C AND, OR, XOR, NOT bitwise operations perform
the operation on each pair of bits of 2 numbers
#include <stdio.h> // C-Library
0xF0 1111 0000 // for printf()
AND 0x3C AND 0011 1100 int main()
0x30 0011 0000 {
char a = 0xf0;
char b = 0x3c;
fiddling" v ? ? ? ? ? ? ? ?
– Change the value of a bit in a register w/o affecting
other bits & _________________
• Determine appropriate constant bit patterns v ? ? ? ? ? ? ? 0
(aka masks) that will change some bits while
leaving others unchanged
• Masks can be written in binary, hex, or even decimal (it v ? ? ? ? ? ? ? ?
is the programmer's choice…whatever is easiest)
| _________________
• Examples (Assume an 8-bit variable, v)
– Clear the LSB to '0' w/o affecting other bits v 1 ? ? ? ? ? ? ?
• v = v & 0xfe; or equivalently
• v = v & ~(0x01); v ? ? ? ? ? ? ? ?
– Set the MSB to '1' w/o affecting other bits
• v = v | 0x80; ^ 0 0 0 0 1 1 1 1
– Flip the LS 4-bits w/o affecting other bits v ? ? ? ? ? ? ? ?
• v = v ^ 0x0f;
4.21
v ? ? ? ? ? ? ? ?
• Some practice problems: | _________________
– Set bit 0 of v to a ‘1’
v = v | 0x01;
– Clear the 4 upper bits in v to ‘0’s v ? ? ? ? ? ? ? ?
^ _________________
v ? ? ? ? ? ? ? ?
• To check for a given set of bits we use a
bitwise-AND to isolate just those bits & 1 0 0 0 0 0 0 0
– The result will then have 0's in the bit locations not
of interest
– The result will keep the bit values of interest v ? ? ? ? ? ? ? ?
• Examples & 0 0 0 0 0 1 0 0
– Check if bit 7 of v = '1'
if ( (v & 0x80) == 0x80) { code } or
if (v & 0x80) { code } v ? ? ? ? ? ? ? ?
– Check if bit 2 of v = '0' & 0 0 0 0 0 1 1 1
if ( (v & 0x04) == 0x00) { code } or
if ( ! (v & 0x04) ) { code }
– Check if bit 2:0 of v = "101" v ? ? ? ? ? ? ? ?
if ( (v & 0b00000111) == 0b00000101) {..}
& 0 0 1 1 0 0 0 0
– Check if bit 5-4 of v = "01"
if ( (v & 0x30) == 0x10) { code }
4.23
Overview
• In the next few slides you will learn
– What your software needs to do to setup
#include <avr/io.h>
the pins for use as digital inputs and/or int main()
{
outputs // check input Group C
// bit 0 value
– To set bits (to 1) and clear bits (to 0) using // set output Group B
// bit 2 to Logic 1=5V
bitwise operations (AND, OR, NOT) to // ...
control individual I/O pins }
PORTD PORTB
PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT PORT
D7 D6 D5 D4 D3 D2 D1 D0 B5 B4 B3 D2 D1 D0
PIND PINB
PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0 PINB5 PINB4 PINB3 PIND2 PIND1 PIND0
4.28
http://www.toro.com/en-
us/homeowner/yard-
PD[7:4] PD[3:0] PB[5] tools/blowers-
vacs/pages/series.aspx?sid
=gasblowervacsseries
4.29
PORTD PORTB
PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0 PORTB5 PORTB4 PORTB3 PORTB2 PORTB1 PORTB0
1 1 0 0 1 0 0 1 0 0 0 0 1 0
uProc.
== PINx
Address Addr
Data
(bit n) 1 = closed
== DDRx
DDRxn 0 = open
Addr
== PORTx
Addr PORTxn
I/O Pin
AVR Microcontroller
4.31
uProc. uProc.
== PINx == PINx
Address Addr Address Addr
Data Data
(bit n) (bit n)
== DDRx == DDRx
DDRxn DDRxn
Addr Addr
1 1
== PORTx
Addr PORTxn 5V == PORTx
Addr PORTxn 0V
1 0
I/O Pin I/O Pin
4.32
uProc. uProc.
1 1
== PINx == PINx
Address Addr Address Addr
Data Data
(bit n) (bit n)
Vdd Vdd
== DDRx == DDRx
DDRxn DDRxn
Addr Addr
0 0
== PORTx
Addr PORTxn == PORTx
Addr PORTxn 0V
I/O Pin I/O Pin
4.34
EXAMPLES
4.37
Can be
discrete
LED is on when LED is on when gate or
gate outputs '1' gate outputs '0' Arduino
output pin
4.38
Vin R ≈ inf.
Blinking an LED
• Hardware and software to make an LED connected to D7 blink
#include <avr/io.h> DDRD
#include <util/delay.h>
int main() ? ? ? ? ? ? ? ?
{
// Init. D7 to output | _________________
DDRD |= 0x80;
// Repeat forever 1 ? ? ? ? ? ? ?
while(1){
// PD7 = 1 (LED on)
PORTD |= 0x80;
PORTD
_delay_ms(500);
? ? ? ? ? ? ? ?
// PD7 = 0 (LED off)
PORTD &= ~(0x80);
_delay_ms(500);
| _________________
}
// Never reached
1 ? ? ? ? ? ? ?
return 0;
}
& _________________
0 ? ? ? ? ? ? ?
4.40
Vdd Vdd
PB Arduino + V -
PD4 PD7
LED
GND
4.41
Pull Up Resistors
• Adding and wiring pull-up resistors for input buttons can be time
consuming…
• Thankfully, each Arduino input bit has an optional internal “pull-
up resistor” associated with it.
– If the pull-up is enabled, in the absence of an input signal, the input bit
will be “pulled” up to a logical one.
– The pull-up has no effect on the input if an active signal is attached.
This pull-up resistor can be
built separately on your
circuit board OR there is one
on each pin of the Arduino
that can be enabled
Arduino
Arduino Arduino
PORTD
PORTD7 PORTD6 PORTD5 PORTD4 PORTD3 PORTD2 PORTD1 PORTD0
1 1 1 1 0 0 1 1
Enable Pull-Up Resistors Actual output values from PD3-0
PIND
PIND7 PIND6 PIND5 PIND4 PIND3 PIND2 PIND1 PIND0
0 1 1 0 ? ? ? ? PD[7:4] PD[3:0]
Made-up values read from the push- (connected
buttons (which don't require you to to buttons) 0011
wire up external pull-up resistors)
4.44
uProc. uProc.
== PINx == PINx
Address Addr Address Addr
Data
0 Data
1
(bit n) (bit n)
Vdd
== DDRx == DDRx
DDRxn DDRxn
Addr Addr
0 0
== PORTx
Addr PORTxn 5V == PORTx
Addr PORTxn 5V
0 I/O Pin
1 I/O Pin
4.45
Arduino
Arduino
Arduino
Enabled in the Arduino
Built Separately
4.46
Shift Operations
• In C, operators '<<' and '>>' are the shift operators
<< = Left shift
>> = Right shift
• Format: data << bit_places_to_shift_by
• Bits shifted out and dropped on one side
• Usually (but not always) 0’s are shifted in on the other side
x = x >> 2; x = x << 2;
Right Shift by 2 bits: Left Shift by 2 bits:
x 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 x
Original x Original x
0’s shifted in… 0’s shifted in…
0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0
x x
x Shifted by 2 bits x Shifted by 2 bits
4.50
Another Example
• To get a 1 in a particular bit location it is easier to
shift the constant 1 some number of places than try
to think of the hex or binary constant
0x01
0 0 0 0 0 0 0 1 = +1
1 << 3 1 << 5
0’s shifted in… 0’s shifted in…
0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0
0x08 0x20
Suppose we want a 1 in bit Suppose we want a 1 in bit
location 3. Just take the value location 5. Shift 1 5 spots to
1 and shift it 3 spots to the left the left. Easier than coming
up with 0x20…
4.51
DEBOUNCING SWITCHES
4.55
Counting Presses
• Consider trying to build a system that #include <avr/io.h>
counted button presses on PC2 int main()
{
(increment once per button press) PORTC |= (1 << PC2);
int cnt = 0;
while(1){
• We can write code to check if the char pressed = (PINC & 0x04);
if( pressed == 0 ){
button is pressed (==0) and then cnt++;
}
increment 'cnt' }
return 0;
• But remember, your code executes }
PC2
PC2 Arduino
cnt 0 0 1 2 3 3
4.56
PC2
PC2 Arduino
cnt 0 0 0 0 0 1 1
4.57
Arduino
Button Button
Press Release
4.58
bouncing
PC2
PC2 Arduino
cnt 0 0 0 0 0 1 1
4.59
char pc2Pressed()
work to do just to recognize a button {
char pressed = (PINC & 0x04);
press, you may want to extract those if( pressed == 0 ){
_delay_ms(5);
to functions you can call over and while( (PINC & 0x04) == 0 ) { }
_delay_ms(5);
over again return 1;
}
else
return 0;
}
int main()
{
PORTC |= (1 << PC2);
int cnt = 0;
while(1){
if( pc2Pressed() )
cnt++;
}
return 0;
}
4.60
Exercise 1
• We want to use Group C (Port C) bit 5 as an
output. Show how you should initialize your
program then write a statement to turn the
output 'ON' to 5V.
4.62
Exercise 2
• Now turn write a statement to turn that
same output ‘OFF’ (i.e. to output 0V)
4.63
Exercise 3
• We want to use Group B (Port B) bit 3 as an input connected
to a switch. You have no separate resistors available to you.
Show how you should initialize your program and then write
an if statement to check if the input voltage is HIGH (5V).
4.64
Common Mistakes
// Clearing a bit to 0
// Right
the result of the ANDing is if( (PIND & (1 << 3)) != 0)
not-equal to 0
4.65
7 6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
TCCR0B WGM03 WGM02 CS02 CS01 CS00
ADCH WGM23 WGM22 CS22 CS21 CS20
TCCR2B
(8-bit ADC res.)
7 6 5 4 3 2 1 0
15 14 13 12 11 10 9 8 TIMSK0 OCIE0B OCIE0A
I/O tasks
0 0 0 0 0 0 TIMSK2 OCIE2B OCIE2A
ADC
(10-bit ADC res. / 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
OCR0A / OCR2A
16-bit value) (8-bit value)
Timer MAX or PWM
After ADCSRA |= (1 << ADSC); 7 6 5 4 3 2 1 0
initialization, while( (ADCSRA & (1 << ADSC)) != 0 ) { } OCR0B / OCR2B
start, poll, unsigned char result = ADCH; (8-bit value) for PWM
capture // if 10-bit result (ADLAR = 0) use this 7 6 5 4 3 2 1 0
// unsigned int result = ADC; TCNT0 / TCNT2