0% found this document useful (0 votes)
41 views36 pages

3 Physical Output

This document discusses physical output from Arduino, including controlling various types of motors. It describes how to control servos, solenoids, relays, brushed DC motors, brushless motors, and stepper motors. Servos can be positioned accurately by varying the width of control pulses. Solenoids and relays require more current than Arduino pins can provide, so external circuits are needed. Brushed DC motors require transistors or H-bridges for adequate current control. Troubleshooting tips note the importance of connecting all grounds together when using external power. Recipes then provide code examples for controlling different motor types.

Uploaded by

Adrian Jidveian
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views36 pages

3 Physical Output

This document discusses physical output from Arduino, including controlling various types of motors. It describes how to control servos, solenoids, relays, brushed DC motors, brushless motors, and stepper motors. Servos can be positioned accurately by varying the width of control pulses. Solenoids and relays require more current than Arduino pins can provide, so external circuits are needed. Brushed DC motors require transistors or H-bridges for adequate current control. Troubleshooting tips note the importance of connecting all grounds together when using external power. Recipes then provide code examples for controlling different motor types.

Uploaded by

Adrian Jidveian
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

CHAPTER 8

Physical Output

8.0 Introduction
<RX FDQ PDNH WKLQJV PRYH E\ FRQWUROOLQJ PRWRUV ZLWK $UGXLQR 'LIIHUHQW W\SHV RI
PRWRUVVXLWGLIIHUHQWDSSOLFDWLRQVDQGWKLVFKDSWHUVKRZVKRZ$UGXLQRFDQGULYHPDQ\
GLIIHUHQWNLQGVRIPRWRUV

Motion Control Using Servos


6HUYRV HQDEOH \RX WR DFFXUDWHO\ FRQWURO SK\VLFDO PRYHPHQW EHFDXVH WKH\ JHQHUDOO\
PRYHWRDSRVLWLRQLQVWHDGRIFRQWLQXRXVO\URWDWLQJ7KH\DUHLGHDOIRUPDNLQJVRPH
WKLQJURWDWHRYHUDUDQJHRIWRGHJUHHV6HUYRVDUHHDV\WRFRQQHFWDQGFRQWURO
EHFDXVHWKHPRWRUGULYHULVEXLOWLQWRWKHVHUYR
6HUYRVFRQWDLQDVPDOOPRWRUFRQQHFWHGWKURXJKJHDUVWRDQRXWSXWVKDIW7KHRXWSXW
VKDIWGULYHVDVHUYRDUPDQGLVDOVRFRQQHFWHGWRDSRWHQWLRPHWHUWRSURYLGHSRVLWLRQ
IHHGEDFNWRDQLQWHUQDOFRQWUROFLUFXLW VHH)LJXUH 
<RXFDQJHWFRQWLQXRXVURWDWLRQVHUYRVWKDWKDYHWKHSRVLWLRQDOIHHGEDFNGLVFRQQHFWHG
VRWKDW\RXFDQLQVWUXFWWKHVHUYRWRURWDWHFRQWLQXRXVO\FORFNZLVHDQGFRXQWHUFORFN
ZLVHZLWKVRPHFRQWURORYHUWKHVSHHG7KHVHIXQFWLRQDOLWWOHOLNHWKHEUXVKHGPRWRUV
FRYHUHGLQ5HFLSHH[FHSWWKDWFRQWLQXRXVURWDWLRQVHUYRVXVHWKHVHUYROLEUDU\FRGH
LQVWHDGRIanalogWrite
6HUYRVUHVSRQGWRFKDQJHVLQWKHGXUDWLRQRIDSXOVH$VKRUWSXOVHRIPVRUOHVVZLOO
FDXVHWKHVHUYRWRURWDWHWRRQHH[WUHPHDSXOVHGXUDWLRQRIPVRUVRZLOOURWDWHWKH
VHUYRWRWKHRWKHUH[WUHPH VHH)LJXUH 3XOVHVUDQJLQJEHWZHHQWKHVHYDOXHVZLOO
URWDWHWKHVHUYRWRDSRVLWLRQSURSRUWLRQDOWRWKHSXOVHZLGWK7KHUHLVQRVWDQGDUGIRU
WKHH[DFWUHODWLRQVKLSEHWZHHQSXOVHVDQGSRVLWLRQDQG\RXPD\QHHGWRWLQNHUZLWK
WKHFRPPDQGVLQ\RXUVNHWFKWRDGMXVWIRUWKHUDQJHRI\RXUVHUYRV

261
)LJXUH(OHPHQWVLQVLGHDKREE\VHUYR
$OWKRXJK WKH GXUDWLRQ RI WKH SXOVH LV PRGXODWHG FRQWUROOHG  VHUYRV
UHTXLUH SXOVHV WKDW DUH GLIIHUHQW IURP WKH 3XOVH :LGWK 0RGXODWLRQ
3:0 RXWSXWIURP analogWrite<RXFDQGDPDJHDKREE\VHUYRE\
FRQQHFWLQJ LW WR WKH RXWSXW IURP analogWriteXVH WKH 6HUYR OLEUDU\
LQVWHDG

Solenoids and Relays


$OWKRXJKPRVWPRWRUVSURGXFHURWDU\PRWLRQDVROHQRLGSURGXFHVOLQHDUPRYHPHQW
ZKHQSRZHUHG$VROHQRLGKDVDPHWDOOLFFRUHWKDWLVPRYHGE\DPDJQHWLFILHOGWKDWLV
FUHDWHGZKHQFXUUHQWLVSDVVHGWKURXJKDFRLO$PHFKDQLFDOUHOD\LVDW\SHRIVROHQRLG
WKDW FRQQHFWV RU GLVFRQQHFWV HOHFWULFDO FRQWDFWV LWV D VROHQRLG RSHUDWLQJ D VZLWFK 
5HOD\VDUHFRQWUROOHGMXVWOLNHVROHQRLGV5HOD\VDQGVROHQRLGVOLNHPRVWPRWRUVUHTXLUH
PRUHFXUUHQWWKDQDQ$UGXLQRSLQFDQVDIHO\SURYLGHDQGWKHUHFLSHVLQWKLVFKDSWHU
VKRZKRZ\RXFDQXVHDWUDQVLVWRURUH[WHUQDOFLUFXLWWRGULYHWKHVHGHYLFHV

Brushed and Brushless Motors


0RVWORZFRVWGLUHFWFXUUHQW '& PRWRUVDUHVLPSOHGHYLFHVZLWKWZROHDGVFRQQHFWHG
WREUXVKHV FRQWDFWV WKDWFRQWUROWKHPDJQHWLFILHOGRIWKHFRLOVWKDWGULYHVDPHWDOOLF
FRUH DUPDWXUH 7KHGLUHFWLRQRIURWDWLRQFDQEHUHYHUVHGE\UHYHUVLQJWKHSRODULW\RI
WKHYROWDJHRQWKHFRQWDFWV'&PRWRUVDUHDYDLODEOHLQPDQ\GLIIHUHQWVL]HVEXWHYHQ
WKHVPDOOHVW VXFKDVYLEUDWLRQPRWRUVXVHGLQFHOOSKRQHV UHTXLUHDWUDQVLVWRURURWKHU
H[WHUQDO FRQWURO WR SURYLGH DGHTXDWH FXUUHQW 7KH UHFLSHV WKDW IROORZ VKRZ KRZ WR
FRQWUROPRWRUVXVLQJDWUDQVLVWRURUDQH[WHUQDOFRQWUROFLUFXLWFDOOHGDQ+%ULGJH

262 | Chapter 8: Physical Output


)LJXUH5HODWLRQVKLSEHWZHHQWKHSXOVHZLGWKDQGWKHVHUYRDQJOHWKHVHUYRRXWSXWDUPPRYHV
SURSRUWLRQDOO\DVWKHSXOVHZLGWKLQFUHDVHVIURPPVWRPV
7KHSULPDU\FKDUDFWHULVWLFLQVHOHFWLQJDPRWRULVWRUTXH7RUTXHGHWHUPLQHVKRZPXFK
ZRUNWKHPRWRUFDQGR7\SLFDOO\KLJKHUWRUTXHPRWRUVDUHODUJHUDQGKHDYLHUDQG
GUDZPRUHFXUUHQWWKDQORZHUWRUTXHPRWRUV
%UXVKOHVVPRWRUVXVXDOO\DUHPRUHSRZHUIXODQGHIILFLHQWIRUDJLYHQVL]HWKDQEUXVKHG
PRWRUVEXWWKH\UHTXLUHPRUHFRPSOLFDWHGHOHFWURQLFFRQWURO:KHUHWKHSHUIRUPDQFH
EHQHILWRIDEUXVKOHVVPRWRULVGHVLUHGFRPSRQHQWVFDOOHGHOHFWURQLFVVSHHGFRQWURO
OHUVLQWHQGHGIRUKREE\UDGLRFRQWUROXVHFDQEHHDVLO\FRQWUROOHGE\$UGXLQREHFDXVH
WKH\DUHFRQWUROOHGPXFKOLNHDVHUYRPRWRU

Stepper Motors
6WHSSHUVDUHPRWRUVWKDWURWDWHDVSHFLILFQXPEHURIGHJUHHVLQUHVSRQVHWRFRQWURO
SXOVHV7KHQXPEHURIGHJUHHVLQHDFKVWHSLVPRWRUGHSHQGHQWUDQJLQJIURPRQHRU
WZRGHJUHHVSHUVWHSWRGHJUHHVRUPRUH
7ZRW\SHVRIVWHSSHUVDUHFRPPRQO\XVHGZLWK$UGXLQRELSRODU W\SLFDOO\ZLWKIRXU
OHDGVDWWDFKHGWRWZRFRLOV DQGXQLSRODU ILYHRUVL[OHDGVDWWDFKHGWRWZRFRLOV 7KH
DGGLWLRQDOZLUHVLQDXQLSRODUVWHSSHUDUHLQWHUQDOO\FRQQHFWHGWRWKHFHQWHURIWKHFRLOV
LQWKHILYHOHDGYHUVLRQHDFKFRLOKDVDFHQWHUWDSDQGERWKFHQWHUWDSVDUHFRQQHFWHG
WRJHWKHU 7KHUHFLSHVFRYHULQJELSRODUDQGXQLSRODUVWHSSHUVKDYHGLDJUDPVLOOXVWUDWLQJ
WKHVHFRQQHFWLRQV

8.0 Introduction | 263


Troubleshooting Sidebar
7KHPRVWFRPPRQFDXVHRISUREOHPVZKHQFRQQHFWLQJGHYLFHVWKDWUHTXLUHH[WHUQDO
SRZHULVQHJOHFWLQJWRFRQQHFWDOOWKHJURXQGVWRJHWKHU<RXU$UGXLQRJURXQGPXVWEH
FRQQHFWHGWRWKHH[WHUQDOSRZHUVXSSO\JURXQGDQGWKHJURXQGVRIH[WHUQDOGHYLFHV
EHLQJSRZHUHG

8.1 Controlling the Position of a Servo


Problem
<RXZDQWWRFRQWUROWKHSRVLWLRQRIDVHUYRXVLQJDQDQJOHFDOFXODWHGLQ\RXUVNHWFK
)RUH[DPSOH\RXZDQWDVHQVRURQDURERWWRVZLQJWKURXJKDQDUFRUPRYHWRDSRVLWLRQ
\RXVHOHFW

Solution
8VHWKH6HUYROLEUDU\GLVWULEXWHGZLWK$UGXLQR&RQQHFWWKHVHUYRSRZHUDQGJURXQG
WR D VXLWDEOH SRZHU VXSSO\ D VLQJOH KREE\ VHUYR FDQ XVXDOO\ EH SRZHUHG IURP WKH
$UGXLQR9OLQH 5HFHQWYHUVLRQVRIWKHOLEUDU\HQDEOH\RXWRFRQQHFWWKHVHUYRVLJQDO
OHDGVWRDQ\$UGXLQRGLJLWDOSLQ
+HUH LV WKH H[DPSOH 6ZHHS VNHWFK GLVWULEXWHG ZLWK $UGXLQR )LJXUH  VKRZV WKH
FRQQHFWLRQV
#include <Servo.h>

Servo myservo; // create servo object to control a servo

int angle = 0; // variable to store the servo position

void setup()
{
myservo.attach(9); // attaches the servo on pin 10 to the servo object
}

void loop()
{
for(angle = 0; angle < 180; angle += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(angle); // tell servo to go to position in variable 'angle'
delay(20); // waits 20ms between servo commands
}
for(angle = 180; angle >= 1; angle -= 1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(20); // waits 20ms between servo commands
}
}

264 | Chapter 8: Physical Output


)LJXUH&RQQHFWLQJDVHUYRIRUWHVWLQJZLWKWKHH[DPSOH6ZHHSVNHWFK

Discussion
7KLVH[DPSOHVZHHSVWKHVHUYREHWZHHQDQGGHJUHHV<RXPD\QHHGWRWHOOWKH
OLEUDU\WRDGMXVWWKHPLQLPXPDQGPD[LPXPSRVLWLRQVVRWKDW\RXJHWWKHUDQJHRI
PRYHPHQW\RXZDQW&DOOLQJServo.attachZLWKRSWLRQDODUJXPHQWVIRUPLQLPXPDQG
PD[LPXPSRVLWLRQVZLOODGMXVWWKHPRYHPHQW
myservo.attach(9,1000,2000 ); // use pin 9, set min to 1000us, max to 2000us

%HFDXVHW\SLFDOVHUYRVUHVSRQGWRSXOVHVPHDVXUHGLQPLFURVHFRQGVDQGQRWGHJUHHV
WKHDUJXPHQWVIROORZLQJWKHSLQQXPEHULQIRUPWKH6HUYROLEUDU\KRZPDQ\PLFUR
VHFRQGVWRXVHZKHQGHJUHHVRUGHJUHHVDUHUHTXHVWHG1RWDOOVHUYRVZLOOPRYH
RYHUDIXOOGHJUHHUDQJHVR\RXPD\QHHGWRH[SHULPHQWZLWK\RXUVWRJHWWKHUDQJH
\RXZDQW
7KHSDUDPHWHUVIRUservo.attach(pin,min,max)DUHWKHIROORZLQJ
pin
7KHSLQQXPEHUWKDWWKHVHUYRLVDWWDFKHGWR PXVWEHRU
min RSWLRQDO
7KHSXOVHZLGWKLQPLFURVHFRQGVFRUUHVSRQGLQJWRWKHPLQLPXP GHJUHH DQJOH
RQWKHVHUYR GHIDXOWVWR
max RSWLRQDO
7KHSXOVHZLGWKLQPLFURVHFRQGVFRUUHVSRQGLQJWRWKHPD[LPXP GHJUHH
DQJOHRQWKHVHUYR GHIDXOWVWR
3RZHUUHTXLUHPHQWVYDU\GHSHQGLQJRQWKHVHUYRDQGKRZPXFKWRUTXHLVQHHGHGWR
URWDWHWKHVKDIW

8.1 Controlling the Position of a Servo | 265


<RXPD\QHHGDQH[WHUQDOVRXUFHRIRUYROWVZKHQFRQQHFWLQJPXO
WLSOHVHUYRV)RXU$$FHOOVZRUNZHOOLI\RXZDQWWRXVHEDWWHU\SRZHU
5HPHPEHU WKDW \RX PXVW FRQQHFW WKH JURXQG RI WKH H[WHUQDO SRZHU
VRXUFHWR$UGXLQRJURXQG

8.2 Controlling One or Two Servos with a Potentiometer


or Sensor
Problem
<RXZDQWWRFRQWUROWKHURWDWLRQDOGLUHFWLRQDQGVSHHGRIRQHRUWZRVHUYRVZLWKD
SRWHQWLRPHWHU)RUH[DPSOH\RXZDQWWRFRQWUROWKHSDQDQGWLOWRIDFDPHUDRUVHQVRU
FRQQHFWHGWRWKHVHUYRV7KLVUHFLSHFDQZRUNZLWKDQ\YDULDEOHYROWDJHIURPDVHQVRU
Download from Wow! eBook <www.wowebook.com>

WKDWFDQEHUHDGIURPDQDQDORJLQSXW

Solution
7KHVDPHOLEUDU\FDQEHXVHGDVLQ5HFLSHZLWKWKHDGGLWLRQRIFRGHWRUHDGWKH
YROWDJHRQDSRWHQWLRPHWHU7KLVYDOXHLVVFDOHGVRWKDWWKHSRVLWLRQRIWKHSRW IURP
0WR1023 LVPDSSHGWRDYDOXHEHWZHHQDQGGHJUHHV7KHRQO\GLIIHUHQFHLQWKH
ZLULQJLVWKHDGGLWLRQRIWKHSRWHQWLRPHWHUVHH)LJXUH
#include <Servo.h>

Servo myservo; // create servo object to control a servo

int potpin = 0; // analog pin used to connect the potentiometer


int val; // variable to read the value from the analog pin

void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo
myservo.write(val); // sets position to the scaled value
delay(15); // waits for the servo to get there
}

266 | Chapter 8: Physical Output


)LJXUH&RQWUROOLQJDVHUYRZLWKDSRWHQWLRPHWHU

Discussion
$Q\WKLQJWKDWFDQEHUHDGIURPanalogRead VHH&KDSWHUDQG&KDSWHU FDQEHXVHG
IRUH[DPSOHWKHJ\URDQGDFFHOHURPHWHUUHFLSHVLQ&KDSWHUFDQEHXVHGVRWKDWWKH
DQJOHRIWKHVHUYRLVFRQWUROOHGE\WKH\DZRIWKHJ\URRUDQJOHRIWKHDFFHOHURPHWHU

8.3 Controlling the Speed of Continuous Rotation Servos


Problem
<RXZDQWWRFRQWUROWKHURWDWLRQDOGLUHFWLRQDQGVSHHGRIVHUYRVPRGLILHGIRUFRQWLQ
XRXVURWDWLRQ)RUH[DPSOH\RXDUHXVLQJWZRFRQWLQXRXVURWDWLRQVHUYRVWRSRZHUD
URERWDQG\RXZDQWWKHVSHHGDQGGLUHFWLRQWREHFRQWUROOHGE\\RXUVNHWFK

Solution
&RQWLQXRXVURWDWLRQVHUYRVDUHDIRUPRIJHDUUHGXFHGPRWRUZLWKIRUZDUGDQGEDFN
ZDUG VSHHG DGMXVWPHQW &RQWURO RI FRQWLQXRXV URWDWLRQ VHUYRV LV VLPLODU WR QRUPDO
VHUYRV7KHVHUYRURWDWHVLQRQHGLUHFWLRQDVWKHDQJOHLVLQFUHDVHGIURPGHJUHHVLW
URWDWHVLQWKHRWKHUGLUHFWLRQZKHQWKHDQJOHLVGHFUHDVHGIURPGHJUHHV7KHDFWXDO
GLUHFWLRQ IRUZDUG RU EDFNZDUG GHSHQGV RQ KRZ \RX KDYH WKH VHUYRV DWWDFKHG )LJ
XUHVKRZVWKHFRQQHFWLRQVIRUFRQWUROOLQJWZRVHUYRV
7KLVH[DPSOHVZHHSVWKHVHUYRVIURPWRGHJUHHVVRLIWKHVHUYRVZHUHFRQQHFWHG
WRZKHHOVWKHYHKLFOHZRXOGPRYHIRUZDUGDWDVORZO\LQFUHDVLQJSDFHDQGWKHQVORZ

8.3 Controlling the Speed of Continuous Rotation Servos | 267


)LJXUH&RQWUROOLQJWZRVHUYRV
GRZQWRDVWRS%HFDXVHWKHVHUYRFRQWUROFRGHLVLQloopWKLVZLOOFRQWLQXHIRUDVORQJ
DVWKHUHLVSRZHU
#include <Servo.h>

Servo myservoLeft; // create servo object to control a servo


Servo myservoRight; // create servo object to control a servo

int pos = 0; // variable to store the servo position

void setup()
{
myservoLeft.attach(9); // attaches left servo on pin 9 to servo object
myservoRight.attach(10); // attaches right servo on pin 10 to servo object
}

void loop()
{
for(angle = 90; angle < 180; angle += 1) // goes from 90 to 180 degrees
{ // in steps of 1 degree
// 90 degrees is stopped
myservoLeft.write(angle); // rotate servo at speed given by 'angle'
myservoRight.write(180-angle); // go in the opposite direction

delay(20); // waits 20ms between servo commands


}
for(angle = 180; angle >= 90; angle -= 1) // goes from 180 to 90 degrees
{
myservoLeft.write(angle); // rotate at a speed given by 'angle'
myservoRight.write(180-angle); // other servo goes in opposite direction
}
}

268 | Chapter 8: Physical Output


Discussion
<RXFDQXVHVLPLODUFRGHIRUFRQWLQXRXVURWDWLRQDQGQRUPDOVHUYRVEXWEHDZDUHWKDW
FRQWLQXRXV URWDWLRQ VHUYRV PD\ QRW VWRS URWDWLQJ ZKHQ ZULWLQJ H[DFWO\  GHJUHHV
6RPHVHUYRVKDYHDVPDOOSRWHQWLRPHWHU\RXFDQWULPWRDGMXVWIRUWKLVRU\RXFDQDGG
RUVXEWUDFWDIHZGHJUHHVWRVWRSWKHVHUYR)RUH[DPSOHLIWKHOHIWVHUYRVWRSVURWDWLQJ
DWGHJUHHV\RXFDQFKDQJHWKHOLQHVWKDWZULWHWRWKHVHUYRVDVIROORZV
myservoLeft.write(angle+TRIM); // declare int TRIM=2; at beginning of sketch

8.4 Controlling Servos from the Serial Port


Problem
<RXZDQWWRSURYLGHFRPPDQGVWRFRQWUROVHUYRVIURPWKHVHULDOSRUW3HUKDSV\RX
ZDQWWRFRQWUROVHUYRVIURPDSURJUDPUXQQLQJRQ\RXUFRPSXWHU

Solution
<RXFDQXVHVRIWZDUHWRFRQWUROWKHVHUYRV7KLVKDVWKHDGYDQWDJHWKDWDQ\QXPEHURI
VHUYRVFDQEHVXSSRUWHG+RZHYHU\RXUVNHWFKQHHGVWRFRQVWDQWO\DWWHQGWRUHIUHVKLQJ
WKHVHUYRSRVLWLRQVRWKHORJLFFDQJHWFRPSOLFDWHGDVWKHQXPEHURIVHUYRVLQFUHDVHV
LI\RXUSURMHFWQHHGVWRSHUIRUPDORWRIRWKHUWDVNV
7KLVUHFLSHGULYHVIRXUVHUYRVDFFRUGLQJWRFRPPDQGVUHFHLYHGRQWKHVHULDOSRUW7KH
FRPPDQGVDUHRIWKHIROORZLQJIRUP
180aZULWHVWRVHUYRD
90bZULWHVWRVHUYRE
0cZULWHVWRVHUYRF
17dZULWHVWRVHUYRG
+HUHLVWKHVNHWFKWKDWGULYHVIRXUVHUYRVFRQQHFWHGRQSLQVWKURXJK
#include <Servo.h> // the servo library

#define SERVOS 4 // the number of servos


int servoPins[SERVOS] = {7,8,9,10}; // servos on pins 7 through 10

Servo myservo[SERVOS];

void setup()
{
Serial.begin(9600);
for(int i=0; i < SERVOS; i++)
myservo[i].attach(servoPins[i]);
}

void loop()

8.4 Controlling Servos from the Serial Port | 269


{
serviceSerial();
}

// serviceSerial checks the serial port and updates position with received data
// it expects servo data in the form:
// "180a" writes 180 to servo a
// "90b writes 90 to servo b
void serviceSerial()
{
static int pos = 0;

if ( Serial.available()) {
char ch = Serial.read();

if(ch >= '0' && ch <= '9') // is ch a number?


pos = pos * 10 + ch - '0'; // yes, accumulate the value
else if(ch >= 'a' && ch <= 'a'+ SERVOS) // is ch a letter for our servos?
myservo[ch - 'a'].write(pos); // yes, save position in position array
}
}

Discussion
&RQQHFWLQJWKHVHUYRVLVVLPLODUWRWKHSUHYLRXVUHFLSHV(DFKVHUYROLQHZLUHJHWVFRQ
QHFWHGWRDGLJLWDOSLQ$OOVHUYRJURXQGVDUHFRQQHFWHGWR$UGXLQRJURXQG7KHVHUYR
SRZHUOLQHVDUHFRQQHFWHGWRJHWKHUDQG\RXPD\QHHGDQH[WHUQDO9RU9SRZHU
VRXUFHLI\RXUVHUYRVUHTXLUHPRUHFXUUHQWWKDQWKH$UGXLQRSRZHUVXSSO\FDQSURYLGH
$QDUUD\QDPHGmyservo VHH5HFLSH LVXVHGWRKROGUHIHUHQFHVIRUWKHIRXUVHUYRV
$forORRSLQsetupDWWDFKHVHDFKVHUYRLQWKHDUUD\WRFRQVHFXWLYHSLQVGHILQHGLQWKH
servoPinsDUUD\
,IWKHFKDUDFWHUUHFHLYHGIURPVHULDOLVDGLJLW WKHFKDUDFWHUZLOOEHJUHDWHUWKDQRUHTXDO
WR]HURDQGOHVVWKDQRUHTXDOWR LWVYDOXHLVDFFXPXODWHGLQWKHYDULDEOHpos,IWKH
FKDUDFWHULVWKHOHWWHUDWKHSRVLWLRQLVZULWWHQWRWKHILUVWVHUYRLQWKHDUUD\ WKHVHUYR
FRQQHFWHGWRSLQ 7KHOHWWHUVEFDQGGFRQWUROWKHVXEVHTXHQWVHUYRV

See Also
6HH&KDSWHUIRUPRUHRQKDQGOLQJYDOXHVUHFHLYHGRYHUVHULDO

270 | Chapter 8: Physical Output


8.5 Driving a Brushless Motor (Using a Hobby Speed Controller)
Problem
<RXKDYHDKREE\EUXVKOHVVPRWRUDQG\RXZDQWWRFRQWUROLWVVSHHG

Solution
7KLVVNHWFKXVHVWKHVDPHFRGHDV5HFLSH7KHZLULQJLVVLPLODUH[FHSWIRUWKHVSHHG
FRQWUROOHUDQGPRWRU%UXVKOHVVPRWRUVKDYHWKUHHZLQGLQJVDQGWKHVHVKRXOGEHFRQ
QHFWHGIROORZLQJWKHLQVWUXFWLRQVIRU\RXUVSHHGFRQWUROOHU VHH)LJXUH 

)LJXUH&RQQHFWLQJDQHOHFWURQLFVVSHHGFRQWUROOHU

Discussion
&RQVXOWWKHGRFXPHQWDWLRQIRU\RXUVSHHGFRQWUROOHUWRFRQILUPWKDWLWLVVXLWDEOHIRU
\RXUEUXVKOHVVPRWRUDQGWRYHULI\WKHZLULQJ%UXVKOHVVPRWRUVKDYHWKUHHFRQQHFWLRQV
IRUWKHWKUHHPRWRUZLUHVDQGWZRFRQQHFWLRQVIRUSRZHU0DQ\VSHHGFRQWUROOHUVSUR
YLGHSRZHURQWKHFHQWHUSLQRIWKHVHUYRFRQQHFWRU8QOHVV\RXZDQWWRSRZHUWKH
$UGXLQRERDUGIURPWKHVSHHGFRQWUROOHU\RXPXVWGLVFRQQHFWRUFXWWKLVFHQWHUZLUH

,I\RXUVSHHGFRQWUROOHUKDVDIHDWXUHWKDWSURYLGHV9SRZHUWRVHUYRV
DQGRWKHUGHYLFHV FDOOHGDEDWWHU\HOLPLQDWRUFLUFXLWRU%(&IRUVKRUW 
\RXPXVWGLVFRQQHFWWKLVZLUHZKHQDWWDFKLQJWKH$UGXLQRWRWKHVSHHG
FRQWUROOHU VHH)LJXUH 

8.5 Driving a Brushless Motor (Using a Hobby Speed Controller) | 271


8.6 Controlling Solenoids and Relays
Problem
<RXZDQWWRDFWLYDWHDVROHQRLGRUUHOD\XQGHUSURJUDPFRQWURO6ROHQRLGVDUHHOHFWUR
PDJQHWVWKDWFRQYHUWHOHFWULFDOHQHUJ\LQWRPHFKDQLFDOPRYHPHQW$QHOHFWURPDJQHWLF
UHOD\LVDVZLWFKWKDWLVDFWLYDWHGE\DVROHQRLG

Solution
0RVWVROHQRLGVUHTXLUHPRUHSRZHUWKDQDQ$UGXLQRSLQFDQSURYLGHVRDWUDQVLVWRU
LVXVHGWRVZLWFKWKHFXUUHQWQHHGHGWRDFWLYDWHDVROHQRLG$FWLYDWLQJWKHVROHQRLGLV
DFKLHYHGE\XVLQJdigitalWriteWRVHWWKHSLQHIGH
7KLVVNHWFKWXUQVRQDWUDQVLVWRUFRQQHFWHGDVVKRZQLQ)LJXUH7KHVROHQRLGZLOO
EHDFWLYDWHGIRURQHVHFRQGHYHU\KRXU
int solenoidPin = 2; // Solenoid connected to transitor on pin 2

void setup()
{
pinMode(ledPin, OUTPUT);
}

void loop()
{
long interval = 1000 * 60 * 60 ; // interval = 60 minutes
digitalWrite(solenoidPin, HIGH); // activates the solenoid
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // deactivates the solenoid
delay(interval); // waits one hour
}

Discussion
7KHFKRLFHRIWUDQVLVWRULVGHSHQGHQWRQWKHDPRXQWRIFXUUHQWUHTXLUHGWRDFWLYDWHWKH
VROHQRLG RU UHOD\ 7KH GDWD VKHHW PD\ VSHFLI\ WKLV LQ PLOOLDPSHUHV P$  RU DV WKH
UHVLVWDQFHRIWKHFRLO7RILQGWKHFXUUHQWQHHGHGE\\RXUVROHQRLGRUUHOD\GLYLGHWKH
YROWDJHRIWKHFRLOE\LWVUHVLVWDQFHLQRKPV)RUH[DPSOHD9UHOD\ZLWKDFRLORI
RKPVGUDZVP$ YROWV  RKPV  DPSVZKLFKLVP$
6PDOOWUDQVLVWRUVVXFKDVWKH1DUHVXIILFLHQWIRUVROHQRLGVUHTXLULQJXSWRDIHZ
KXQGUHGPLOOLDPSV/DUJHUVROHQRLGVZLOOUHTXLUHDKLJKHUSRZHUWUDQVLVWRUOLNHWKH
7,37,3RUVLPLODU7KHUHDUHPDQ\VXLWDEOHWUDQVLVWRUDOWHUQDWLYHVVHH$SSHQ
GL[%IRUKHOSUHDGLQJDGDWDVKHHWDQGFKRRVLQJWUDQVLVWRUV
7KHSXUSRVHRIWKHGLRGHLVWRSUHYHQWUHYHUVH(0)IURPWKHFRLOIURPGDPDJLQJWKH
WUDQVLVWRU UHYHUVH(0)LVDYROWDJHSURGXFHGZKHQFXUUHQWWKURXJKDFRLOLVVZLWFKHG

272 | Chapter 8: Physical Output


)LJXUH'ULYLQJDVROHQRLGZLWKDWUDQVLVWRU
RII  7KH SRODULW\ RI WKH GLRGH LV LPSRUWDQW WKHUH LV D FRORUHG EDQG LQGLFDWLQJ WKH
FDWKRGHWKLVVKRXOGEHFRQQHFWHGWRWKHVROHQRLGSRVLWLYHSRZHUVXSSO\
(OHFWURPDJQHWLFUHOD\VDUHDFWLYDWHGMXVWOLNHVROHQRLGV$VSHFLDOUHOD\FDOOHGDVROLG
VWDWHUHOD\ 665 KDVLQWHUQDOHOHFWURQLFVWKDWFDQEHGULYHQGLUHFWO\IURPDQ$UGXLQR
SLQZLWKRXWWKHQHHGIRUWKHWUDQVLVWRU&KHFNWKHGDWDVKHHWIRU\RXUUHOD\WRVHHZKDW
YROWDJHDQGFXUUHQWLWUHTXLUHVDQ\WKLQJPRUHWKDQP$DWYROWVZLOOUHTXLUHDFLUFXLW
VXFKDVWKHRQHVKRZQLQ)LJXUH

8.7 Making an Object Vibrate


Problem
<RXZDQWVRPHWKLQJWRYLEUDWHXQGHU$UGXLQRFRQWURO)RUH[DPSOH\RXZDQW\RXU
SURMHFWWRVKDNHIRURQHVHFRQGHYHU\PLQXWH

Solution
&RQQHFWDYLEUDWLRQPRWRUDVVKRZQLQ)LJXUH

8.7 Making an Object Vibrate | 273


)LJXUH&RQQHFWLQJDYLEUDWLRQPRWRU

7KHIROORZLQJVNHWFKZLOOWXUQRQWKHYLEUDWLRQPRWRUIRURQHVHFRQGHDFKPLQXWH
/*
* Vibrate sketch
* Vibrate for one second every minute
*
*/

const int motorPin = 3; // vibration motor transistor is connected to pin 3

void setup()
{
pinMode(motorPin, OUTPUT);
}

void loop()
{
digitalWrite(motorPin, HIGH); //vibrate
delay(1000); // delay one second
digitalWrite(motorPin, LOW); // stop vibrating
delay(59000); // wait 59 seconds.
}

Discussion
7KLVUHFLSHXVHVDPRWRUGHVLJQHGWRYLEUDWHVXFKDVWKH6SDUN)XQ52%,I\RX
KDYHDQROGFHOOSKRQH\RXQRORQJHUQHHGLWPD\FRQWDLQWLQ\YLEUDWLRQPRWRUVWKDW
ZRXOG EH VXLWDEOH 9LEUDWLRQ PRWRUV UHTXLUH PRUH SRZHU WKDQ DQ $UGXLQR SLQ FDQ
SURYLGHVRDWUDQVLVWRULVXVHGWRVZLWFKWKHPRWRUFXUUHQWRQDQGRII$OPRVWDQ\131
WUDQVLVWRUFDQEHXVHG)LJXUHVKRZVWKHFRPPRQ1 VHHWKLVERRNVZHE
VLWHIRUVXSSOLHULQIRUPDWLRQRQWKLVDQGWKHRWKHUFRPSRQHQWVXVHG $NLORKPUH
VLVWRUFRQQHFWVWKHRXWSXWSLQWRWKHWUDQVLVWRUEDVHWKHYDOXHLVQRWFULWLFDODQG\RX
FDQXVHYDOXHVXSWRNLORKPRUVR WKHUHVLVWRUSUHYHQWVWRRPXFKFXUUHQWIORZLQJ

274 | Chapter 8: Physical Output


WKURXJKWKHRXWSXWSLQ 7KHGLRGHDEVRUEV RUVQXEVLWVVRPHWLPHVFDOOHGDVQXEEHU
GLRGH YROWDJHVSURGXFHGE\WKHPRWRUZLQGLQJVDVLWURWDWHV7KHFDSDFLWRUDEVRUEV
YROWDJHVSLNHVSURGXFHGZKHQWKHEUXVKHV FRQWDFWVFRQQHFWLQJHOHFWULFFXUUHQWWRWKH
PRWRUZLQGLQJV RSHQDQGFORVH7KHRKPUHVLVWRULVQHHGHGWROLPLWWKHDPRXQWRI
FXUUHQWIORZLQJWKURXJKWKHPRWRU
7KLVVNHWFKVHWVWKHRXWSXWSLQHIGHIRURQHVHFRQG PLOOLVHFRQGV DQGWKHQZDLWV
IRUVHFRQGV7KHWUDQVLVWRUZLOOWXUQRQ FRQGXFW ZKHQWKHSLQLV HIGHDOORZLQJ
FXUUHQWWRIORZWKURXJKWKHPRWRU
+HUHLVDYDULDWLRQRIWKLVVNHWFKWKDWXVHVDVHQVRUWRPDNHWKHPRWRUYLEUDWH7KH
ZLULQJLVVLPLODUWRWKDWVKRZQLQ)LJXUHZLWKWKHDGGLWLRQRIDSKRWRFHOOFRQQHFWHG
WRDQDORJSLQ VHH5HFLSH 
/*
* Vibrate_Photocell sketch
* Vibrate when photosensor detects light above ambient level
*
*/

const int motorPin = 3; // vibration motor transistor is connected to pin 3


const int sensorPin = 0; // Photodetector connected to analog input 0
int sensorAmbient = 0; // ambient light level (calibrated in setup)
const int thresholdMargin = 100; // how much above ambient needed to vibrate

void setup()
{
pinMode(motorPin, OUTPUT);
sensorAmbient = analogRead(sensorPin); // get startup light level;
}

void loop()
{
int sensorValue = analogRead(sensorPin);
if( sensorValue > sensorAmbient + thresholdMargin)
{
digitalWrite(motorPin, HIGH); //vibrate
}
else
{
digitalWrite(motorPin, LOW); // stop vibrating
}
}

+HUHWKHRXWSXWSLQLVWXUQHGRQZKHQDOLJKWVKLQHVRQWKHSKRWRFHOO:KHQWKHVNHWFK
VWDUWV WKH EDFNJURXQG OLJKW OHYHO RQ WKH VHQVRU LV UHDG DQG VWRUHG LQ WKH YDULDEOH
sensorAmbient /LJKW OHYHOV UHDG LQ loop WKDW DUH KLJKHU WKDQ WKLV ZLOO WXUQ RQ WKH
YLEUDWLRQPRWRU

8.7 Making an Object Vibrate | 275


8.8 Driving a Brushed Motor Using a Transistor
Problem
<RXZDQWWRWXUQDPRWRURQDQGRII<RXPD\ZDQWWRFRQWUROLWVVSHHG7KHPRWRU
RQO\QHHGVWRWXUQLQRQHGLUHFWLRQ

Solution
7KLVVNHWFKWXUQVWKHPRWRURQDQGRIIDQGFRQWUROVLWVVSHHGIURPFRPPDQGVUHFHLYHG
RQWKHVHULDOSRUW )LJXUHVKRZVWKHFRQQHFWLRQV 
/*
* SimpleBrushed sketch
* commands from serial port control motor speed
* digits '0' through '9' are valid where '0' is off, '9' is max speed
*/

const int motorPins = 3; // motor driver is connected to pin 3

void setup()
{
Serial.begin(9600);
}

void loop()
{
if ( Serial.available()) {
char ch = Serial.read();

if(ch >= '0' && ch <= '9') // is ch a number?


{
int speed = map(ch, '0', '9', 0, 255);
analogWrite(3, speed);
Serial.println(speed);
}
else
{
Serial.print("Unexpected character ");
Serial.println(ch);
}
}
}

Discussion
7KLVUHFLSHLVVLPLODUWR5HFLSHWKHGLIIHUHQFHLVWKDWanalogWriteLVXVHGWRFRQWURO
WKHVSHHGRIWKHPRWRU6HH$QDORJ2XWSXWRQSDJHLQ&KDSWHUIRUPRUHRQ
analogWriteDQG3XOVH:LGWK0RGXODWLRQ 3:0 

276 | Chapter 8: Physical Output


)LJXUH'ULYLQJDEUXVKHGPRWRU

8.9 Controlling the Direction of a Brushed Motor


with an H-Bridge
Problem
<RXZDQWWRFRQWUROWKHGLUHFWLRQRIDEUXVKHGPRWRUIRUH[DPSOH\RXZDQWWRFDXVH
DPRWRUWRURWDWHLQRQHGLUHFWLRQRUWKHRWKHUIURPVHULDOSRUWFRPPDQGV

Solution
$Q+%ULGJHFDQFRQWUROWZREUXVKHGPRWRUV)LJXUHVKRZVWKHFRQQHFWLRQVIRU
WKH/'+%ULGJH,&\RXFDQDOVRXVHWKH61ZKLFKKDVWKHVDPHSLQOD\RXW
/*
* Brushed_H_Bridge_simple sketch
* commands from serial port control motor direction
* + or - set the direction, any other key stops the motor
*/

const int in1Pin = 5; // H-Bridge input pins


const int in2Pin = 4;

void setup()
{
Serial.begin(9600);
pinMode(in1Pin, OUTPUT);
pinMode(in2Pin, OUTPUT);
Serial.println("+ - to set direction, any other key stops motor");
}

8.9 Controlling the Direction of a Brushed Motor with an H-Bridge | 277


void loop()
{
if ( Serial.available()) {
char ch = Serial.read();
if (ch == '+')
{
Serial.println("CW");
digitalWrite(in1Pin,LOW);
digitalWrite(in2Pin,HIGH);
}
else if (ch == '-')
{
Serial.println("CCW");
digitalWrite(in1Pin,HIGH);
digitalWrite(in2Pin,LOW);
}
else
{
Serial.print("Stop motor");
digitalWrite(in1Pin,LOW);
digitalWrite(in2Pin,LOW);
}
}
}

)LJXUH&RQQHFWLQJWZREUXVKHGPRWRUVXVLQJDQ/'+%ULGJH

278 | Chapter 8: Physical Output


Discussion
7DEOHVKRZVKRZWKHYDOXHVRQWKH+%ULGJHLQSXWDIIHFWWKHPRWRU,QWKHVNHWFK
LQWKLVUHFLSHV6ROXWLRQDVLQJOHPRWRULVFRQWUROOHGXVLQJWKH,1DQG,1SLQVWKH
(1SLQLVSHUPDQHQWO\HIGHEHFDXVHLWLVFRQQHFWHGWR9
7DEOH/RJLFWDEOHIRU+%ULGJH
EN IN1 IN2 Function
HIGH LOW HIGH Turn clockwise
HIGH HIGH LOW Turn counterclockwise
HIGH LOW LOW Motor stop
HIGH HIGH HIGH Motor stop
LOW Ignored Ignored Motor stop

)LJXUHVKRZVKRZDVHFRQGPRWRUFDQEHFRQQHFWHG7KHIROORZLQJVNHWFKFRQWUROV
ERWKPRWRUVWRJHWKHU
/*
* Brushed_H_Bridge_simple2 sketch
* commands from serial port control motor direction
* + or - set the direction, any other key stops the motors
*/

const int in1Pin = 5; // H-Bridge input pins


const int in2Pin = 4;

const int in3Pin = 3; // H-Bridge pins for second motor


const int in4Pin = 2;

void setup()
{
Serial.begin(9600);
pinMode(in1Pin, OUTPUT);
pinMode(in2Pin, OUTPUT);
pinMode(in3Pin, OUTPUT);
pinMode(in4Pin, OUTPUT);
Serial.println("+ - sets direction of motors, any other key stops motors");
}

void loop()
{
if ( Serial.available()) {
char ch = Serial.read();
if (ch == '+')

8.9 Controlling the Direction of a Brushed Motor with an H-Bridge | 279


{
Serial.println("CW");
// first motor
digitalWrite(in1Pin,LOW);
digitalWrite(in2Pin,HIGH);
//second motor
digitalWrite(in3Pin,LOW);
digitalWrite(in4Pin,HIGH);
}
else if (ch == '-')
{
Serial.println("CCW");
digitalWrite(in1Pin,HIGH);
digitalWrite(in2Pin,LOW);

digitalWrite(in3Pin,HIGH);
digitalWrite(in4Pin,LOW);
}
else
{
Serial.print("Stop motors");
digitalWrite(in1Pin,LOW);
digitalWrite(in2Pin,LOW);
digitalWrite(in3Pin,LOW);
digitalWrite(in4Pin,LOW);
}
}
}

8.10 Controlling the Direction and Speed of a Brushed Motor


with an H-Bridge
Problem
<RX ZDQW WR FRQWURO WKH GLUHFWLRQ DQG VSHHG RI D EUXVKHG PRWRU 7KLV H[WHQGV WKH
IXQFWLRQDOLW\ RI 5HFLSH  E\ FRQWUROOLQJ ERWK PRWRU GLUHFWLRQ DQG VSHHG WKURXJK
FRPPDQGVIURPWKHVHULDOSRUW

Solution
&RQQHFWDEUXVKHGPRWRUWRWKHRXWSXWSLQVRIWKH+%ULGJHDVVKRZQLQ)LJXUH

280 | Chapter 8: Physical Output


)LJXUH&RQQHFWLQJDEUXVKHGPRWRUXVLQJDQDORJ:ULWHIRUVSHHGFRQWURO

7KLVVNHWFKXVHVFRPPDQGVIURPWKH6HULDO0RQLWRUWRFRQWUROWKHVSHHGDQGGLUHFWLRQ
RI WKH PRWRU 6HQGLQJ  ZLOO VWRS WKH PRWRU DQG WKH GLJLWV  WKURXJK  ZLOO
FRQWUROWKHVSHHG6HQGLQJDQGZLOOVHWWKHPRWRUGLUHFWLRQ
/*
* Brushed_H_Bridge sketch
* commands from serial port control motor speed and direction
* digits '0' through '9' are valid where '0' is off, '9' is max speed
* + or - set the direction
*/

const int enPin = 5; // H-Bridge enable pin


const int in1Pin = 7; // H-Bridge input pins
const int in2Pin = 4;

void setup()
{
Serial.begin(9600);
pinMode(in1Pin, OUTPUT);
pinMode(in2Pin, OUTPUT);
Serial.println("Speed (0-9) or + - to set direction");
}

void loop()
{
if ( Serial.available()) {
char ch = Serial.read();

8.10 Controlling the Direction and Speed of a Brushed Motor with an H-Bridge | 281
if(ch >= '0' && ch <= '9') // is ch a number?
{
int speed = map(ch, '0', '9', 0, 255);
analogWrite(enPin, speed);
Serial.println(speed);
}
else if (ch == '+')
{
Serial.println("CW");
digitalWrite(in1Pin,LOW);
digitalWrite(in2Pin,HIGH);
}
else if (ch == '-')
{
Serial.println("CCW");
digitalWrite(in1Pin,HIGH);
digitalWrite(in2Pin,LOW);
}
else
{
Serial.print("Unexpected character ");
Serial.println(ch);
}
}
}

Discussion
7KLVUHFLSHLVVLPLODUWR5HFLSHLQZKLFKPRWRUGLUHFWLRQLVFRQWUROOHGE\WKHOHYHOV
RQWKH,1DQG,1SLQV%XWLQDGGLWLRQVSHHGLVFRQWUROOHGE\WKHanalogWriteYDOXH
RQWKH(1SLQ VHH&KDSWHUIRUPRUHRQ3:0 :ULWLQJDYDOXHRI 0ZLOOVWRSWKH
PRWRUZULWLQJ255ZLOOUXQWKHPRWRUDWIXOOVSHHG7KHPRWRUVSHHGZLOOYDU\LQSUR
SRUWLRQWRYDOXHVZLWKLQWKLVUDQJH

8.11 Using Sensors to Control the Direction and Speed of


Brushed Motors (L293 H-Bridge)
Problem
<RXZDQWWRFRQWUROWKHGLUHFWLRQDQGVSHHGRIEUXVKHGPRWRUVZLWKIHHGEDFNIURP
VHQVRUV)RUH[DPSOH\RXZDQWWZRSKRWRVHQVRUVWRFRQWUROPRWRUVSHHGDQGGLUHFWLRQ
WRFDXVHDURERWWRPRYHWRZDUGDEHDPRIOLJKW

Solution
7KLV6ROXWLRQXVHVVLPLODUPRWRUFRQQHFWLRQVWRWKRVHVKRZQLQ)LJXUHEXWZLWK
WKHDGGLWLRQRIWZROLJKWGHSHQGHQWUHVLVWRUVDVVKRZQLQ)LJXUH

282 | Chapter 8: Physical Output


)LJXUH7ZRPRWRUVFRQWUROOHGXVLQJVHQVRUV

7KHVNHWFKPRQLWRUVWKHOLJKWOHYHORQWKHVHQVRUVDQGGULYHVWKHPRWRUVWRVWHHUWRZDUG
WKHVHQVRUGHWHFWLQJWKHEULJKWHUOLJKWOHYHO
/*
* Brushed_H_Bridge_Direction sketch
* uses photo sensors to control motor direction
* robot moves in the direction of a light
*/

int leftPins[] = {5,7,4}; // on pin for PWM, two pins for motor direction
int rightPins[] = {6,3,2};

const int leftSensorPin = 0; // analog pins with sensors


const int rightSensorPin = 1;

int sensorThreshold = 0; // must have this much light on a sensor to move


int looks = 0; // the number of attempts to turn and find light

void setup()
{
for(int i=1; i < 3; i++)
{
pinMode(leftPins[i], OUTPUT);
pinMode(rightPins[i], OUTPUT);
}
}

void loop()
{
int leftVal = analogRead(leftSensorPin);

8.11 Using Sensors to Control the Direction and Speed of Brushed Motors (L293 H-Bridge) | 283
int rightVal = analogRead(rightSensorPin);
if(sensorThreshold == 0) // have the sensors been calibrated ?
sensorThreshold = (leftVal + rightVal) / 2; // no, calibrate sensors

if( leftVal < sensorThreshold && rightVal < sensorThreshold)


{
if(looks < 4) // limit the number of consecutive looks
{
lookAround();
looks = looks + 1;
}
}
else
{
// if there is adequate light to move ahead
setSpeed(rightPins, map( rightVal,0,1023, 0,255));
setSpeed(leftPins, map(leftVal,0,1023,0,255));
looks = 0; // reset the looks counter
}
}

void lookAround()
{
// rotate left for half a second
setSpeed(leftPins, -127 );
setSpeed(rightPins, 127 );
delay(500);
setSpeed(rightPins, 0 );
setSpeed(leftPins, 127 );
}

void setSpeed(int pins[], int speed )


{
if(speed < 0)
{
digitalWrite(pins[1],HIGH);
digitalWrite(pins[2],LOW);
speed = -speed;
}
else
{
digitalWrite(pins[1],LOW);
digitalWrite(pins[2],HIGH);
}
analogWrite(pins[0], speed);
}

Discussion
7KLVVNHWFKFRQWUROVWKHVSHHGRIWZRPRWRUVLQUHVSRQVHWRWKHDPRXQWRIOLJKWGHWHFWHG
E\WZRSKRWRFHOOV7KHSKRWRFHOOVDUHDUUDQJHGVRWKDWDQLQFUHDVHLQOLJKWRQRQHVLGH
ZLOOLQFUHDVHWKHVSHHGRIWKHPRWRURQWKHRWKHUVLGH7KLVFDXVHVWKHURERWWRWXUQ
WRZDUGWKHVLGHZLWKWKHEULJKWHUOLJKW/LJKWVKLQLQJHTXDOO\RQERWKFHOOVPDNHVWKH

284 | Chapter 8: Physical Output


URERWPRYHIRUZDUGLQDVWUDLJKWOLQH,QVXIILFLHQWOLJKWFDXVHVWKHURERWWRVWRSDQG
ORRNDURXQGWRVHHLIWKHUHLVDOLJKWVRXUFHFRPLQJIURPDQ\RWKHUGLUHFWLRQ
/LJKWLVVHQVHGWKURXJKDQDORJLQSXWVDQG VHH5HFLSH :KHQWKHSURJUDP
VWDUWVWKHDPELHQWOLJKWLVPHDVXUHGDQGWKLVWKUHVKROGLVXVHGWRGHWHUPLQHWKHPLQL
PXP OLJKW OHYHO QHHGHG WR PRYH WKH URERW :KHQ OLJKW GURSV EHORZ WKH WKUHVKROG
WKHlookAroundIXQFWLRQLVFDOOHGWRURWDWHWKHURERWWRVHDUFKIRUPRUHOLJKW
0RWRUVSHHGLVFRQWUROOHGLQWKH setSpeedIXQFWLRQ7ZRSLQVDUHXVHGWRFRQWUROWKH
GLUHFWLRQIRUHDFKPRWRUDQGZLWKDQRWKHUSLQWRFRQWUROVSHHG7KHSLQQXPEHUVDUH
KHOGLQWKHleftPinsDQGrightPinsDUUD\V7KHILUVWSLQLQHDFKDUUD\LVWKHVSHHGSLQ
WKHRWKHUWZRSLQVDUHIRUGLUHFWLRQ
$QDOWHUQDWLYHWRWKH/LVWKH7RVKLED)%)1*7KLVFDQEHXVHGLQDQ\RIWKH
UHFLSHVVKRZLQJWKH/')LJXUHVKRZVWKHZLULQJIRUWKH)%DVXVHGRQ
WKH3ROROXEUHDNRXWERDUG 6SDUN)XQ52% 

)LJXUH+%ULGJHZLULQJIRUWKH3ROROXEUHDNRXWERDUG

<RXFDQUHGXFHWKHQXPEHURISLQVQHHGHGE\DGGLQJDGGLWLRQDOKDUGZDUHWRFRQWURO
WKHGLUHFWLRQSLQV7KLVLVGRQHE\XVLQJRQO\RQHSLQSHUPRWRUIRUGLUHFWLRQZLWKD
WUDQVLVWRURUORJLFJDWHWRLQYHUWWKHOHYHORQWKHRWKHU+%ULGJHLQSXW<RXFDQILQG
FLUFXLWGLDJUDPVIRUWKLVLQWKH$UGXLQRZLNLEXWLI\RXZDQWVRPHWKLQJDOUHDG\ZLUHG
XS\RXFDQXVHDQ+%ULGJHVKLHOGVXFKDVWKH)UHHGXLQR0RWRUFRQWUROVKLHOG 1.&

8.11 Using Sensors to Control the Direction and Speed of Brushed Motors (L293 H-Bridge) | 285
(OHFWURQLFV$5' RUWKH$UGXPRWRIURP6SDUN)XQ '(9 7KHVHVKLHOGV
SOXJGLUHFWO\LQWR$UGXLQRDQGRQO\UHTXLUHFRQQHFWLRQVWRWKHPRWRUSRZHUVXSSO\
DQGZLQGLQJV
+HUHLVWKHVNHWFKUHYLVHGIRUWKH$UGXPRWRVKLHOG
/*
* Brushed_H_Ardumoto sketch
* uses photo sensors to control motor direction
* robot moves in the direction of a light
*/

int leftPins[] = {10,12}; // one pin for PWM, one pin for motor direction
int rightPins[] = {11,13};

const int leftSensorPin = 0; // analog pins with sensors


const int rightSensorPin = 1;

int sensorThreshold = 0; // must have this much light on a sensor to move


int looks = 0; // the number of attempts to turn and find light

void setup()
{
pinMode(leftPins[1], OUTPUT);
pinMode(rightPins[1], OUTPUT);
Serial.begin(9600);
}

7KHloopDQGlookAroundIXQFWLRQVDUHLGHQWLFDOWRWKHSUHFHGLQJVNHWFKsetSpeedKDV
OHVVFRGHEHFDXVHKDUGZDUHRQWKHVKLHOGDOORZVDVLQJOHSLQWRFRQWUROPRWRUGLUHFWLRQ
void setSpeed(int pins[], int speed )
{
if(speed < 0)
{
digitalWrite(pins[1],HIGH);
speed = -speed;
}
else
{
digitalWrite(pins[1],LOW);
}
analogWrite(pins[0], speed);
}

7KHSLQDVVLJQPHQWVIRUWKH)UHHGXLQRVKLHOGDUHDVIROORZV
int leftPins[] = {10,13}; // PWM, Direction
int rightPins[] = {9,12}; // PWM, Direction

,I\RXKDYHDGLIIHUHQWVKLHOG\RXZLOOQHHGWRVHHWKHGDWDVKHHWDQGPDNHVXUHWKH
YDOXHVLQWKHVNHWFKPDWFKWKHSLQVXVHGIRU3:0DQGGLUHFWLRQ

286 | Chapter 8: Physical Output


See Also
7KHGDWDVKHHWIRUWKH3ROROXERDUGKWWSZZZSROROXFRPILOH-7%)1*SGI
7KH SURGXFW SDJH IRU WKH )UHHGXLQR VKLHOG KWWSZZZQNFHOHFWURQLFVFRPIUHHGXLQR
DUGXLQRPRWRUFRQWUROVKLHOGNLWKWPO
7KHSURGXFWSDJHIRUWKH$UGXPRWRVKLHOGKWWSZZZVSDUNIXQFRPFRPPHUFHSURG
XFWBLQIRSKS"SURGXFWVBLG 

8.12 Driving a Bipolar Stepper Motor


Problem
<RXKDYHDELSRODU IRXUZLUH VWHSSHUPRWRUDQG\RXZDQWWRVWHSLWXQGHUSURJUDP
FRQWUROXVLQJDQ+%ULGJH

Solution
7KLVVNHWFKVWHSVWKHPRWRULQUHVSRQVHWRVHULDOFRPPDQGV$QXPHULFYDOXHIROORZHG
E\DVWHSVLQRQHGLUHFWLRQDVWHSVLQWKHRWKHU)RUH[DPSOHVWHSVDVWHS
PRWRUWKURXJKRQHFRPSOHWHUHYROXWLRQLQRQHGLUHFWLRQDQGVWHSVKDOIDUHYROXWLRQ
LQWKHRWKHUGLUHFWLRQ)LJXUHVKRZVWKHFRQQHFWLRQVWRDIRXUZLUHELSRODUVWHSSHU
XVLQJWKH/+%ULGJH
/*
* Stepper_bipolar sketch
*
* stepper is controlled from the serial port.
* a numeric value followed by '+' or '-' steps the motor
*
*
* http://www.arduino.cc/en/Reference/Stepper
*/

#include <Stepper.h>

// change this to the number of steps on your motor


#define STEPS 24

// create an instance of the stepper class, specifying


// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 2, 3, 4, 5);

int steps = 0;

void setup()
{
// set the speed of the motor to 30 RPMs

8.12 Driving a Bipolar Stepper Motor | 287


stepper.setSpeed(30);
Serial.begin(9600);
}

void loop()
{
if ( Serial.available()) {
char ch = Serial.read();

if(ch >= '0' && ch <= '9'){ // is ch a number?


steps = steps * 10 + ch - '0'; // yes, accumulate the value
}
else if(ch == '+'){
stepper.step(steps);
steps = 0;
}
else if(ch == '-'){
stepper.step(steps * -1);
steps = 0;
}
}
}

)LJXUH)RXUZLUHELSRODUVWHSSHUXVLQJ/+%ULGJH

Discussion
,I\RXUVWHSSHUUHTXLUHVDKLJKHUFXUUHQWWKDQWKH/FDQSURYLGH P$IRUWKH
/' \RXFDQXVHWKH61FKLSWKDWKDQGOHVXSWRDPS)RUFXUUHQWXSWR
DPSV\RXFDQXVHWKH/FKLS7KH/FDQXVHWKHVDPHVNHWFKDVVKRZQLQWKLV
UHFLSHV6ROXWLRQDQGLWVKRXOGEHFRQQHFWHGDVVKRZQLQ)LJXUH

288 | Chapter 8: Physical Output


)LJXUH8QLSRODUVWHSSHUZLWK/

$VLPSOHZD\WRFRQQHFWDQ/WR$UGXLQRLVWRXVHWKH6SDUN)XQ$UGXPRWRVKLHOG
'(9 7KLVSOXJVRQWRSRIDQ$UGXLQRERDUGDQGRQO\UHTXLUHVH[WHUQDOFRQ
QHFWLRQWRWKHPRWRUZLQGLQJVWKHPRWRUSRZHUFRPHVIURPWKH$UGXLQR9LQ H[WHUQDO
9ROWDJH,QSXW SLQ,QLVFRQWUROOHGE\SLQDQG(1$LVSLQ,QLVFRQQHFWHG
WRSLQDQG(1%LVRQSLQ0DNHWKHIROORZLQJFKDQJHVWRWKHFRGHWRXVHWKH
SUHFHGLQJVNHWFKZLWK$UGXPRWR
Stepper stepper(STEPS, 12,13);
int steps = 0;

,Qsetup
pinMode(10, OUTPUT);
digitalWrite(10, LOW); // enable A
// set the speed of the motor to 30 RPMs
stepper.setSpeed(30);
Serial.begin(9600);
pinMode(11, OUTPUT);
digitalWrite(11, LOW); // enable B

7KHloopFRGHLVWKHVDPHDVWKHSUHYLRXVVNHWFK

8.12 Driving a Bipolar Stepper Motor | 289


8.13 Driving a Bipolar Stepper Motor (Using the EasyDriver
Board)
Problem
<RXKDYHDELSRODU IRXUZLUH VWHSSHUPRWRUDQG\RXZDQWWRVWHSLWXQGHUSURJUDP
FRQWUROXVLQJWKH(DV\'ULYHUERDUG

Solution
7KLV 6ROXWLRQ LV VLPLODU WR 5HFLSH  EXW LW XVHV WKH SRSXODU (DV\'ULYHU ERDUG
)LJXUHVKRZVWKHFRQQHFWLRQV

)LJXUH&RQQHFWLQJWKH(DV\'ULYHUERDUG

7KHIROORZLQJVNHWFKFRQWUROVWKHVWHSGLUHFWLRQDQGFRXQWIURPWKHVHULDOSRUW8QOLNH
WKHFRGHLQ5HFLSHLWGRHVQRWUHTXLUHWKHVWHSSHUOLEUDU\EHFDXVHWKH(DV\'ULYHU
ERDUGKDQGOHVWKHFRQWURORIWKHPRWRUFRLOVLQKDUGZDUH
/*
* Stepper_Easystepper sketch
*
* stepper is controlled from the serial port.
* a numeric value followed by '+' or '-' steps the motor

290 | Chapter 8: Physical Output


*
*/

const int dirPin = 2;


const int stepPin = 3;

int speed = 100; // desired speed in steps per second


int steps = 0; // the number of steps to make

void setup()
{
pinMode(dirPin, OUTPUT);
pinMode(stepPin, OUTPUT);
Serial.begin(9600);
}

void loop()
{
if ( Serial.available()) {
char ch = Serial.read();

if(ch >= '0' && ch <= '9'){ // is ch a number?


steps = steps * 10 + ch - '0'; // yes, accumulate the value
}
else if(ch == '+'){
step(steps);
steps = 0;
}
else if(ch == '-'){
step(-steps);
steps = 0;
}
else if(ch == 's'){
speed = steps;
Serial.print("Setting speed to ");
Serial.println(steps);
steps = 0;
}
}
}

void step(int steps)


{
int stepDelay = 1000 / speed; //delay in ms for speed given as steps per sec
int stepsLeft;

// determine direction based on whether steps_to_mode is + or -


if (steps > 0)
{
digitalWrite(dirPin, HIGH);
stepsLeft = steps;
}
if (steps < 0)
{
digitalWrite(dirPin, LOW);

8.13 Driving a Bipolar Stepper Motor (Using the EasyDriver Board) | 291
stepsLeft = -steps;
}
// decrement the number of steps, moving one step each time
while(stepsLeft > 0)
{
digitalWrite(stepPin,HIGH);
delayMicroseconds(1);
digitalWrite(stepPin,LOW);
delay(stepDelay);
stepsLeft--; // decrement the steps left
}
}

Discussion
7KH(DV\'ULYHUERDUGLVSRZHUHGWKURXJKWKHSLQVPDUNHG0DQG*QG VKRZQ
LQWKHXSSHUULJKWRI)LJXUH 7KHERDUGRSHUDWHVZLWKYROWDJHVEHWZHHQYROWV
Download from Wow! eBook <www.wowebook.com>

DQGYROWVFKHFNWKHVSHFLILFDWLRQVRI\RXUVWHSSHUPRWRUIRUWKHFRUUHFWRSHUDWLQJ
YROWDJH,I\RXDUHXVLQJD9VWHSSHU\RXPXVWSURYLGHYROWVWRWKHSLQVPDUNHG
*QGDQG9 WKHVHSLQVDUHRQWKHORZHUOHIWRIWKH(DV\'ULYHUERDUG DQGFXW
WKHMXPSHURQ WKH SULQWHG FLUFXLW ERDUG PDUNHG$3:5 WKLVGLVFRQQHFWVWKHRQ
ERDUG UHJXODWRU DQG SRZHUV WKH PRWRU DQG (DV\'ULYHU ERDUG IURP DQ H[WHUQDO 9
VXSSO\ 
<RXFDQUHGXFHFXUUHQWFRQVXPSWLRQZKHQWKHPRWRULVQRWVWHSSLQJE\FRQQHFWLQJ
WKH(QDEOHSLQWRDVSDUHGLJLWDORXWSXWDQGVHWWLQJWKLV HIGHWRGLVDEOHRXWSXW D LOW
YDOXHHQDEOHVRXWSXW 
6WHSSLQJRSWLRQVDUHVHOHFWHGE\FRQQHFWLQJWKH06DQG06SLQVWR9 HIGH RU
*QG LOW DVVKRZQLQ7DEOH7KHGHIDXOWRSWLRQVZLWKWKHERDUGFRQQHFWHGDV
VKRZQLQ)LJXUHZLOOXVHHLJKWKVWHSUHVROXWLRQ 06DQG06DUHHIGH5HVHWLV
HIGHDQG(QDEOHLVLOW 

7DEOH0LFURVWHSRSWLRQV
Resolution MS1 MS2
Full step LOW LOW
Half step HIGH LOW
Quarter step LOW HIGH
Eighth step HIGH HIGH

<RXFDQPRGLI\WKHFRGHVRWKDWWKHVSHHGYDOXHGHWHUPLQHVWKHUHYROXWLRQVSHUVHFRQG
DVIROORZV
// use the following for speed given in RPM
int speed = 100; // desired speed in RPM
int stepsPerRevolution = 200; // this line sets steps for one revolution

292 | Chapter 8: Physical Output


&KDQJHWKHVWHSIXQFWLRQVRWKDWWKHILUVWOLQHLVDVIROORZV
int stepDelay = 60L * 1000L / stepsPerRevolution / speed; // speed as RPM

(YHU\WKLQJHOVHFDQUHPDLQWKHVDPHEXWQRZWKHVSHHGFRPPDQG\RXVHQGZLOOEH
WKH530RIWKHPRWRUZKHQLWVWHSV

8.14 Driving a Unipolar Stepper Motor (ULN2003A)


Problem
<RXKDYHDXQLSRODU ILYHRUVL[ZLUH VWHSSHUPRWRUDQG\RXZDQWWRFRQWUROLWXVLQJ
D8/1$'DUOLQJWRQGULYHUFKLS

Solution
&RQQHFWDXQLSRODUVWHSSHUDVVKRZQLQ)LJXUH7KH9FRQQHFWLRQJRHVWRDSRZHU
VXSSO\UDWHGIRUWKHYROWDJHDQGFXUUHQWQHHGHGE\\RXUPRWRU

)LJXUH8QLSRODUVWHSSHUFRQQHFWHGXVLQJ8/1GULYHU

8.14 Driving a Unipolar Stepper Motor (ULN2003A) | 293


7KHIROORZLQJVNHWFKVWHSVWKHPRWRUXVLQJFRPPDQGVIURPWKHVHULDOSRUW$QXPHULF
YDOXHIROORZHGE\DVWHSVLQRQHGLUHFWLRQDVWHSVLQWKHRWKHU
/*
* Stepper sketch
*
* stepper is controlled from the serial port.
* a numeric value followed by '+' or '-' steps the motor
*
*
* http://www.arduino.cc/en/Reference/Stepper
*/

#include <Stepper.h>

// change this to the number of steps on your motor


#define STEPS 24

// create an instance of the stepper class, specifying


// the number of steps of the motor and the pins it's
// attached to
Stepper stepper(STEPS, 2, 3, 4, 5);

int steps = 0;

void setup()
{
stepper.setSpeed(30); // set the speed of the motor to 30 RPMs
Serial.begin(9600);
}

void loop()
{
if ( Serial.available()) {
char ch = Serial.read();

if(ch >= '0' && ch <= '9'){ // is ch a number?


steps = steps * 10 + ch - '0'; // yes, accumulate the value
}
else if(ch == '+'){
stepper.step(steps);
steps = 0;
}
else if(ch == '-'){
stepper.step(steps * -1);
steps = 0;
}

294 | Chapter 8: Physical Output


else if(ch == 's'){
stepper.setSpeed(steps);
Serial.print("Setting speed to ");
Serial.println(steps);
steps = 0;
}
}
}

Discussion
7KLVW\SHRIPRWRUKDVWZRSDLUVRIFRLOVDQGHDFKFRLOKDVDFRQQHFWLRQWRWKHFHQWHU
0RWRUVZLWKRQO\ILYHZLUHVKDYHERWKFHQWHUFRQQHFWLRQVEURXJKWRXWRQDVLQJOHZLUH
,I WKH FRQQHFWLRQV DUH QRW PDUNHG \RX FDQ LGHQWLI\ WKH ZLULQJ XVLQJ D PXOWLPHWHU
0HDVXUHWKHUHVLVWDQFHDFURVVSDLUVRIZLUHVWRILQGWKHWZRSDLUVRIZLUHVWKDWKDYHWKH
PD[LPXPUHVLVWDQFH7KHFHQWHUWDSZLUHVKRXOGKDYHKDOIWKHUHVLVWDQFHRIWKHIXOOFRLO
$VWHSE\VWHSSURFHGXUHLVDYDLODEOHDWKWWSWHFKUHIPDVVPLQGRUJWHFKUHILRVWHSSHU
ZLUHVDVS

8.14 Driving a Unipolar Stepper Motor (ULN2003A) | 295

You might also like