arduino lecture 3 - making things move and avr programming
DESCRIPTION
Further following up the Arduino set of lectures with topics on Motors, PWM, Trade-offs, and finally an example of directly programming an AVR chip. Part of the Interactive Media Master's program at the University of Limerick.TRANSCRIPT
Making Things Move and AVR Programming
CS4062 - Eoin Brazil - Semester 2 - 2008
Motion linear or
rotary
conversion issues
Types DC
Servo
Stepper
Gearhead
Servos and Motors
Servo
DC Motor
Stepper
Gearhead
2 Connections Continual spin, given current & voltage
Reversing current, reverses the direction
Increasing the voltage, spins faster, decreasing the voltage, slows the spin
High speed but low torque
Gearbox can add torque but at the expense of speed
DC Motor
DC Motor Example
DC Motor Example
DC Motor Example
DC Motor with gearbox Not fast but provide more torque
Servo Motor Gearhead motor with position feedback
Feedback is often from potentiometer
Pulsing the motor moves it to particular position within 180 degree range
Can’t move 360 degrees but can be positioned precisely within the 180 degree range
Gearhead Motor
Servo
Gearhead
Precise positioning & 360 degrees range
Move in discrete steps around a circle
A 200 step motor would move 1.8 degrees per step around the full 360 degrees
Continuous rotation in either direction
Good torque
Complex to connect
Stepper Motor
Linear Motion
Pull or Push
Types Solenoid
Actuator
Microactuator
Solenoids and Actuators
Microactuators
Actuator
Solenoid
Motor Characteristics gears or direct
rated voltage
current (efficiency) - stall / running
speed - spin / rpm, rps, Hz
torque
size, shaft diameter, shaft length
position resolution (Servos & Steppers)
Advanced Mediation Lisa McElligott, 2000 interactive confessional box
used real confessional box
confessor was computer program
interacted using a voice interface.
scripted interactions with random noises to add to immersion
suspension of disbelief
realism
Weave Mirror
Side and back views
Mechanical mirror
Any person standing in front of one of these pieces is instantly reflected on its surface.
Uses video cameras, motors and computers to achieve mirroring
Sound aspect - soothing sound
Daniel Rozin, Weave Mirror, 2007
Weave Mirror Daniel Rozin,
Weave Mirror, 2007
PWM Analog input / output
Duration of the digital pulse of voltage
Microcontroller - HIGH 5V or LOW 0V
``Fake’’ it using PWM
Duty cycle, ratio from low to high to low cycle
LED dimming, DC Motor speed control, Piezo speakers, RC Servo positioning
Pulse Width Modulation
Wiring Diagram
Schematic Diagram
Servo Motor Connections on Arduino
Black wire would go to Grd pin
Red wire would go to 5V power pin
White wire would go to one of the digital pins on the board
Colours can vary, Ground (black or brown), Power (red), Control (orange, yellow or white)
RC Servo Motor
/* * NewSerialServo * -------------- * Servo control from the Serial port * * Alteration of the control interface to use < and > keys * to slew the servo horn left and right. Works best with * the Linux/Mac terminal "screen" program. * * Created 10 December 2007 * copyleft 2007 Brian D. Wendt * http://principialabs.com/ * * Adapted from code by Tom Igoe, http://itp.nyu.edu/physcomp/Labs/Servo */
/** Adjust these values for your servo and setup, if necessary **/ int servoPin = 2; // control pin for servo motor int minPulse = 600; // minimum servo position int maxPulse = 2400; // maximum servo position int turnRate = 100; // servo turn rate increment (larger value, faster rate) int refreshTime = 20; // time (ms) between pulses (50Hz) /** The Arduino will calculate these values for you **/ int centerServo; // center servo position int pulseWidth; // servo pulse width int moveServo; // raw user input long lastPulse = 0; // recorded time (ms) of the last pulse
continuedon next
slide
/* * NewSerialServo * -------------- * Servo control from the Serial port * * Alteration of the control interface to use < and > keys * to slew the servo horn left and right. Works best with * the Linux/Mac terminal "screen" program. * * Created 10 December 2007 * copyleft 2007 Brian D. Wendt * http://principialabs.com/ * * Adapted from code by Tom Igoe, http://itp.nyu.edu/physcomp/Labs/Servo */
/** Adjust these values for your servo and setup, if necessary **/ int servoPin = 2; // control pin for servo motor int minPulse = 600; // minimum servo position int maxPulse = 2400; // maximum servo position int turnRate = 100; // servo turn rate increment (larger value, faster rate) int refreshTime = 20; // time (ms) between pulses (50Hz) /** The Arduino will calculate these values for you **/ int centerServo; // center servo position int pulseWidth; // servo pulse width int moveServo; // raw user input long lastPulse = 0; // recorded time (ms) of the last pulse
continuedon next
slide
Setup the necessary control values and variables to store
information
// Main program setupvoid setup() { pinMode(servoPin, OUTPUT); // Set servo pin as an output pin centerServo = maxPulse - ((maxPulse - minPulse)/2); pulseWidth = centerServo; // Give the servo a starting point (or it floats) Serial.begin(9600); Serial.println(" Arduino Serial Servo Control"); Serial.println("Press < or > to move, spacebar to center"); Serial.println(); }
void loop() { // wait for serial input if (Serial.available() > 0) { // read the incoming byte: moveServo = Serial.read(); // ASCII '<' is 44, ASCII '>' is 46 (comma and period, really) if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; } if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; } if (moveServo == 32) { pulseWidth = centerServo; } // stop servo pulse at min and max if (pulseWidth > maxPulse) { pulseWidth = maxPulse; } if (pulseWidth < minPulse) { pulseWidth = minPulse; } }
continuedon next
slide
// Main program setupvoid setup() { pinMode(servoPin, OUTPUT); // Set servo pin as an output pin centerServo = maxPulse - ((maxPulse - minPulse)/2); pulseWidth = centerServo; // Give the servo a starting point (or it floats) Serial.begin(9600); Serial.println(" Arduino Serial Servo Control"); Serial.println("Press < or > to move, spacebar to center"); Serial.println(); }
void loop() { // wait for serial input if (Serial.available() > 0) { // read the incoming byte: moveServo = Serial.read(); // ASCII '<' is 44, ASCII '>' is 46 (comma and period, really) if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; } if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; } if (moveServo == 32) { pulseWidth = centerServo; } // stop servo pulse at min and max if (pulseWidth > maxPulse) { pulseWidth = maxPulse; } if (pulseWidth < minPulse) { pulseWidth = minPulse; } }
continuedon next
slide
Setup servo its pin, its pulse, and its position. Setup serial connection
for control
// Main program setupvoid setup() { pinMode(servoPin, OUTPUT); // Set servo pin as an output pin centerServo = maxPulse - ((maxPulse - minPulse)/2); pulseWidth = centerServo; // Give the servo a starting point (or it floats) Serial.begin(9600); Serial.println(" Arduino Serial Servo Control"); Serial.println("Press < or > to move, spacebar to center"); Serial.println(); }
void loop() { // wait for serial input if (Serial.available() > 0) { // read the incoming byte: moveServo = Serial.read(); // ASCII '<' is 44, ASCII '>' is 46 (comma and period, really) if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; } if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; } if (moveServo == 32) { pulseWidth = centerServo; } // stop servo pulse at min and max if (pulseWidth > maxPulse) { pulseWidth = maxPulse; } if (pulseWidth < minPulse) { pulseWidth = minPulse; } }
continuedon next
slide
The serial input controls the servo by the ‘<‘ or ‘>’ and keep its speed within the safe range
// pulse the servo every 20 ms (refreshTime) with current pulseWidth // this will hold the servo's position if unchanged, or move it if changed if (millis() - lastPulse >= refreshTime) { digitalWrite(servoPin, HIGH); // start the pulse delayMicroseconds(pulseWidth); // pulse width digitalWrite(servoPin, LOW); // stop the pulse lastPulse = millis(); // save the time of the last pulse } }// END of Main program
// pulse the servo every 20 ms (refreshTime) with current pulseWidth // this will hold the servo's position if unchanged, or move it if changed if (millis() - lastPulse >= refreshTime) { digitalWrite(servoPin, HIGH); // start the pulse delayMicroseconds(pulseWidth); // pulse width digitalWrite(servoPin, LOW); // stop the pulse lastPulse = millis(); // save the time of the last pulse } }// END of Main program
Pulse the servo every 20ms, this is where the desired change actually happens and its based
on the previous serial input
Sketching your work
Bill Verplank Interaction Design
Sketchbook
Bill Buxton
Embodiment using Animatronics
Stefan Marti 2005, Autonomous
Interactive Intermediaries
2005, Physical Embodiments for Mobile Communication Agents
Kinematics Gears and mechanical
models Geometry of pure motion without
reference to force or mass
Cornell University Library, Kinematic Models for Design Digital Library (KMODDL)
Tutorials, models, e-books, e.g. Linkages
Chapter 3 in Building Robot Drive Trains
Examples from www.flying-pig.co.uk
PWM Tutorials
ITP Servo tutorial
Principial Labs Arduino Servo
Driving a Unipolar Stepper Motor
Driving a Bipolar Stepper Motor
Making an RC Servo wall following car
ITP Servo lab, uses a potentiometer to control the servo.
Arduino Library Software Servo Library
attach(int) Turn a pin into a servo driver.
detach() Release a pin from servo driving.
write(int) Set the angle of the servo in degrees, 0 to 180.
read() return that value set with the last write().
attached() return 1 if the servo is currently attached.
refresh() must call once every 50ms to keep servos updated, won't call more than every 20ms
setMinimumPulse(uint16_t) set the duration of the 0 degree pulse in microseconds. (default minimum value is 544 microseconds)
setMaximumPulse(uint16_t) set the duration of the 180 degree pulse in microseconds. (default maximum pluse value is 2400 microsconds)
Need to first send position with write() before you can receive any control signals
Projects and Prototyping Trade-offs
Projects and Prototyping Trade-offs
Re-programmable
Projects and Prototyping Trade-offs
Size matters
Existing Toolkits
Existing Toolkits
Sufficient foralmost all needs
Existing Toolkits
Sufficient foralmost all needs
Chips and PCBs
Arduino Advanced Arduino ATMega168
ATTiny13
Arduino Advanced Arduino ATMega168
Approx. ~$35
ATTiny13
Arduino Advanced Arduino ATMega168
Approx. ~$35
Approx. ~$4 ATTiny13
Arduino Advanced Arduino ATMega168
Approx. ~$35
Approx. ~$4 ATTiny13
Approx.~$1
AVR Programmer
AVR ATTiny13 Blinky
AVR ATTiny13 Blinky
/* Two LEDs, tied to pin b0 and to b1 which correspond to physical pins 5 and 6 on ATTINY13 are turned on for 100ms and then off for 200ms*/
#include <avr/io.h> #define F_CPU 1000000 // set to 1 MHz as delay.h needs F_CPU#include <util/delay.h>#include "pin_macros.h" // Leah Buechley's pin macros for AVRs - very useful
int main(void){ // Set Port B pins for 3 and 4 as outputs
b0_output; //initialize LED pinb1_output; //initialize LED pinb0_high; //LED is offb1_high; //LED is off
DDRB = 0x18; // In binary this is 0001 1000 (note that is bit 3 and 4)
for ( ; 1==1 ; ) // loop while 1 equals 1 - forever - C style loop{
// Set Port B pins for 3 and 4 as HIGH (i.e. turn the LEDs on) b0_low; //LED is on b1_low; //LED is on _delay_loop_2(65535); b0_high; //LED is off b1_high; //LED is off _delay_loop_2(65535);
}return 1;
}
/* Two LEDs, tied to pin b0 and to b1 which correspond to physical pins 5 and 6 on ATTINY13 are turned on for 100ms and then off for 200ms*/
#include <avr/io.h> #define F_CPU 1000000 // set to 1 MHz as delay.h needs F_CPU#include <util/delay.h>#include "pin_macros.h" // Leah Buechley's pin macros for AVRs - very useful
int main(void){ // Set Port B pins for 3 and 4 as outputs
b0_output; //initialize LED pinb1_output; //initialize LED pinb0_high; //LED is offb1_high; //LED is off
DDRB = 0x18; // In binary this is 0001 1000 (note that is bit 3 and 4)
for ( ; 1==1 ; ) // loop while 1 equals 1 - forever - C style loop{
// Set Port B pins for 3 and 4 as HIGH (i.e. turn the LEDs on) b0_low; //LED is on b1_low; //LED is on _delay_loop_2(65535); b0_high; //LED is off b1_high; //LED is off _delay_loop_2(65535);
}return 1;
}
Include the libraries and set the speed of chip
/* Two LEDs, tied to pin b0 and to b1 which correspond to physical pins 5 and 6 on ATTINY13 are turned on for 100ms and then off for 200ms*/
#include <avr/io.h> #define F_CPU 1000000 // set to 1 MHz as delay.h needs F_CPU#include <util/delay.h>#include "pin_macros.h" // Leah Buechley's pin macros for AVRs - very useful
int main(void){ // Set Port B pins for 3 and 4 as outputs
b0_output; //initialize LED pinb1_output; //initialize LED pinb0_high; //LED is offb1_high; //LED is off
DDRB = 0x18; // In binary this is 0001 1000 (note that is bit 3 and 4)
for ( ; 1==1 ; ) // loop while 1 equals 1 - forever - C style loop{
// Set Port B pins for 3 and 4 as HIGH (i.e. turn the LEDs on) b0_low; //LED is on b1_low; //LED is on _delay_loop_2(65535); b0_high; //LED is off b1_high; //LED is off _delay_loop_2(65535);
}return 1;
}
Setup LED pins, Data Direction Register and
turn LEDS off.
/* Two LEDs, tied to pin b0 and to b1 which correspond to physical pins 5 and 6 on ATTINY13 are turned on for 100ms and then off for 200ms*/
#include <avr/io.h> #define F_CPU 1000000 // set to 1 MHz as delay.h needs F_CPU#include <util/delay.h>#include "pin_macros.h" // Leah Buechley's pin macros for AVRs - very useful
int main(void){ // Set Port B pins for 3 and 4 as outputs
b0_output; //initialize LED pinb1_output; //initialize LED pinb0_high; //LED is offb1_high; //LED is off
DDRB = 0x18; // In binary this is 0001 1000 (note that is bit 3 and 4)
for ( ; 1==1 ; ) // loop while 1 equals 1 - forever - C style loop{
// Set Port B pins for 3 and 4 as HIGH (i.e. turn the LEDs on) b0_low; //LED is on b1_low; //LED is on _delay_loop_2(65535); b0_high; //LED is off b1_high; //LED is off _delay_loop_2(65535);
}return 1;
}
Loop - Turn the pins on, wait for 262ms, and
turn off. Repeat.
# Makefile for sample_led_program for ATtiny13 chip# Note: to use makefile with a different chip change all# mmcu statements (-mmcu=attiny13) to reflect new chip # also change the part option (-p t13) for the avrdude install command
# default target when "make" is run w/o argumentsall: sample_led_program.rom
# compile sample_led_program.c into sample_led_program.osample_led_program.o: sample_led_program.c avr-gcc -c -g -O0 -Wall -mmcu=attiny13 sample_led_program.c -o sample_led_program.o
# link up sample_led_program.o into sample_led_program.elfsample_led_program.elf: sample_led_program.o avr-gcc sample_led_program.o -Wall,-nm,-Map=sample_led_program.map,--cref -mmcu=attiny13 -o sample_led_program.elf
# copy ROM (FLASH) object out of sample_led_program.elf into sample_led_program.romsample_led_program.rom: sample_led_program.elf avr-objcopy -O ihex sample_led_program.elf sample_led_program.rom
# command to program chip (invoked by running "make install")install: avrdude -c usbtiny -p t13 -e -U flash:w:sample_led_program.rom
# command to clean up junk (no source files) (invoked by "make clean")clean: rm -f *.o *.rom *.elf *.map *~
# Makefile for sample_led_program for ATtiny13 chip# Note: to use makefile with a different chip change all# mmcu statements (-mmcu=attiny13) to reflect new chip # also change the part option (-p t13) for the avrdude install command
# default target when "make" is run w/o argumentsall: sample_led_program.rom
# compile sample_led_program.c into sample_led_program.osample_led_program.o: sample_led_program.c avr-gcc -c -g -O0 -Wall -mmcu=attiny13 sample_led_program.c -o sample_led_program.o
# link up sample_led_program.o into sample_led_program.elfsample_led_program.elf: sample_led_program.o avr-gcc sample_led_program.o -Wall,-nm,-Map=sample_led_program.map,--cref -mmcu=attiny13 -o sample_led_program.elf
# copy ROM (FLASH) object out of sample_led_program.elf into sample_led_program.romsample_led_program.rom: sample_led_program.elf avr-objcopy -O ihex sample_led_program.elf sample_led_program.rom
# command to program chip (invoked by running "make install")install: avrdude -c usbtiny -p t13 -e -U flash:w:sample_led_program.rom
# command to clean up junk (no source files) (invoked by "make clean")clean: rm -f *.o *.rom *.elf *.map *~
When Make is run, needs a target
# Makefile for sample_led_program for ATtiny13 chip# Note: to use makefile with a different chip change all# mmcu statements (-mmcu=attiny13) to reflect new chip # also change the part option (-p t13) for the avrdude install command
# default target when "make" is run w/o argumentsall: sample_led_program.rom
# compile sample_led_program.c into sample_led_program.osample_led_program.o: sample_led_program.c avr-gcc -c -g -O0 -Wall -mmcu=attiny13 sample_led_program.c -o sample_led_program.o
# link up sample_led_program.o into sample_led_program.elfsample_led_program.elf: sample_led_program.o avr-gcc sample_led_program.o -Wall,-nm,-Map=sample_led_program.map,--cref -mmcu=attiny13 -o sample_led_program.elf
# copy ROM (FLASH) object out of sample_led_program.elf into sample_led_program.romsample_led_program.rom: sample_led_program.elf avr-objcopy -O ihex sample_led_program.elf sample_led_program.rom
# command to program chip (invoked by running "make install")install: avrdude -c usbtiny -p t13 -e -U flash:w:sample_led_program.rom
# command to clean up junk (no source files) (invoked by "make clean")clean: rm -f *.o *.rom *.elf *.map *~
Use avr-gcc to compile ‘c’ program
# Makefile for sample_led_program for ATtiny13 chip# Note: to use makefile with a different chip change all# mmcu statements (-mmcu=attiny13) to reflect new chip # also change the part option (-p t13) for the avrdude install command
# default target when "make" is run w/o argumentsall: sample_led_program.rom
# compile sample_led_program.c into sample_led_program.osample_led_program.o: sample_led_program.c avr-gcc -c -g -O0 -Wall -mmcu=attiny13 sample_led_program.c -o sample_led_program.o
# link up sample_led_program.o into sample_led_program.elfsample_led_program.elf: sample_led_program.o avr-gcc sample_led_program.o -Wall,-nm,-Map=sample_led_program.map,--cref -mmcu=attiny13 -o sample_led_program.elf
# copy ROM (FLASH) object out of sample_led_program.elf into sample_led_program.romsample_led_program.rom: sample_led_program.elf avr-objcopy -O ihex sample_led_program.elf sample_led_program.rom
# command to program chip (invoked by running "make install")install: avrdude -c usbtiny -p t13 -e -U flash:w:sample_led_program.rom
# command to clean up junk (no source files) (invoked by "make clean")clean: rm -f *.o *.rom *.elf *.map *~
Use avr-gcc on `o’ obj file to create `elf ’ file
# Makefile for sample_led_program for ATtiny13 chip# Note: to use makefile with a different chip change all# mmcu statements (-mmcu=attiny13) to reflect new chip # also change the part option (-p t13) for the avrdude install command
# default target when "make" is run w/o argumentsall: sample_led_program.rom
# compile sample_led_program.c into sample_led_program.osample_led_program.o: sample_led_program.c avr-gcc -c -g -O0 -Wall -mmcu=attiny13 sample_led_program.c -o sample_led_program.o
# link up sample_led_program.o into sample_led_program.elfsample_led_program.elf: sample_led_program.o avr-gcc sample_led_program.o -Wall,-nm,-Map=sample_led_program.map,--cref -mmcu=attiny13 -o sample_led_program.elf
# copy ROM (FLASH) object out of sample_led_program.elf into sample_led_program.romsample_led_program.rom: sample_led_program.elf avr-objcopy -O ihex sample_led_program.elf sample_led_program.rom
# command to program chip (invoked by running "make install")install: avrdude -c usbtiny -p t13 -e -U flash:w:sample_led_program.rom
# command to clean up junk (no source files) (invoked by "make clean")clean: rm -f *.o *.rom *.elf *.map *~
Use avr-objcopy to create rom from elf file
# Makefile for sample_led_program for ATtiny13 chip# Note: to use makefile with a different chip change all# mmcu statements (-mmcu=attiny13) to reflect new chip # also change the part option (-p t13) for the avrdude install command
# default target when "make" is run w/o argumentsall: sample_led_program.rom
# compile sample_led_program.c into sample_led_program.osample_led_program.o: sample_led_program.c avr-gcc -c -g -O0 -Wall -mmcu=attiny13 sample_led_program.c -o sample_led_program.o
# link up sample_led_program.o into sample_led_program.elfsample_led_program.elf: sample_led_program.o avr-gcc sample_led_program.o -Wall,-nm,-Map=sample_led_program.map,--cref -mmcu=attiny13 -o sample_led_program.elf
# copy ROM (FLASH) object out of sample_led_program.elf into sample_led_program.romsample_led_program.rom: sample_led_program.elf avr-objcopy -O ihex sample_led_program.elf sample_led_program.rom
# command to program chip (invoked by running "make install")install: avrdude -c usbtiny -p t13 -e -U flash:w:sample_led_program.rom
# command to clean up junk (no source files) (invoked by "make clean")clean: rm -f *.o *.rom *.elf *.map *~
Use avrdube and a usbtiny to copy to the
ATtiny13 chip
# Makefile for sample_led_program for ATtiny13 chip# Note: to use makefile with a different chip change all# mmcu statements (-mmcu=attiny13) to reflect new chip # also change the part option (-p t13) for the avrdude install command
# default target when "make" is run w/o argumentsall: sample_led_program.rom
# compile sample_led_program.c into sample_led_program.osample_led_program.o: sample_led_program.c avr-gcc -c -g -O0 -Wall -mmcu=attiny13 sample_led_program.c -o sample_led_program.o
# link up sample_led_program.o into sample_led_program.elfsample_led_program.elf: sample_led_program.o avr-gcc sample_led_program.o -Wall,-nm,-Map=sample_led_program.map,--cref -mmcu=attiny13 -o sample_led_program.elf
# copy ROM (FLASH) object out of sample_led_program.elf into sample_led_program.romsample_led_program.rom: sample_led_program.elf avr-objcopy -O ihex sample_led_program.elf sample_led_program.rom
# command to program chip (invoked by running "make install")install: avrdude -c usbtiny -p t13 -e -U flash:w:sample_led_program.rom
# command to clean up junk (no source files) (invoked by "make clean")clean: rm -f *.o *.rom *.elf *.map *~
Clean up the files created
Call the Makefile
Call the Install part of Makefile which calls avrdude
Run avrdude, it reads the rom, writes it to the chip and verifies
this process
Sources for Parts Hacking / Disassembly
use existing high-tech, but inexpensive, objects, toys and devices as cheap source of parts for your projects
little specialist knowledge is required, photograph and document the disassembly
``Low tech sensors and actuators for artists and architects’’ provides examples, by Usman Haque and Adam Somlai-Fischer
Purchase / Stores Many parts are available locally in UL, ask.
Online vendors for electronic parts include farnell.com, mouser.com, and digikey.com
Sensors, shields, kits, servos can also be found from sparkfun.com or parallax.com
Many others, just small selection that I’ve used.
Things To Remember Safety first, last, and always
do not take another person’s work about the state of a piece of equipment, always check yourself and make sure its safe for you to work
use the right tool for the job
treat each tool with respect and rack them back in their correct place when they are not in use, don’t leave a dangerous tool loose when it can harm somebody else
don’t leave your safety glasses on the bench or in your pocket
don’t work on a live circuit, turn the power off first
don’t solder in an enclosed area without proper ventilation
read the datasheet first and double check it to be sure
get twice or three times the number of parts that you need for your circuit, you will make mistakes and sometimes you will have to throw an almost finished piece away