CHAPTER 17
Advanced Coding and
Memory Handling
17.0 Introduction
$V\RXGRPRUHZLWK\RXU$UGXLQR\RXUVNHWFKHVQHHGWREHFRPHPRUHHIILFLHQW7KH
WHFKQLTXHVLQWKLVFKDSWHUFDQKHOS\RXLPSURYHWKHSHUIRUPDQFHDQGUHGXFHWKHFRGH
VL]HRI\RXUVNHWFKHV,I\RXQHHGWRPDNH\RXUVNHWFKUXQIDVWHURUXVHOHVV5$0WKH
UHFLSHVKHUHFDQKHOS7KHUHFLSHVKHUHDUHPRUHWHFKQLFDOWKDQPRVWRIWKHRWKHUUHFLSHV
LQWKLVERRNEHFDXVHWKH\FRYHUWKLQJVWKDWDUHXVXDOO\FRQFHDOHGE\WKHIULHQGO\$UGXLQR
ZUDSSHU
7KH$UGXLQREXLOGSURFHVVZDVGHVLJQHGWRKLGHFRPSOH[DVSHFWVRI&DQG&DVZHOO
DVWKHWRROVXVHGWRFRQYHUWDVNHWFKLQWRWKHE\WHVWKDWDUHXSORDGHGDQGUXQRQDQ
$UGXLQRERDUG%XWLI\RXUSURMHFWKDVSHUIRUPDQFHDQGUHVRXUFHUHTXLUHPHQWVEH\RQG
WKHFDSDELOLW\RIWKHVWDQGDUG$UGXLQRHQYLURQPHQW\RXVKRXOGILQGWKHUHFLSHVKHUH
XVHIXO
7KH$UGXLQRERDUGXVHVPHPRU\WRVWRUHLQIRUPDWLRQ,WKDVWKUHHNLQGVRIPHPRU\
SURJUDPPHPRU\UDQGRPDFFHVVPHPRU\5$0DQG((3520(DFKKDVGLIIHUHQW
FKDUDFWHULVWLFVDQGXVHV0DQ\RIWKHWHFKQLTXHVLQWKLVFKDSWHUFRYHUZKDWWRGRLI\RX
GRQRWKDYHHQRXJKRIRQHNLQGRIPHPRU\
3URJUDPPHPRU\DOVRNQRZQDVIODVKLVZKHUHWKHH[HFXWDEOHVNHWFKFRGHLVVWRUHG
7KHFRQWHQWVRISURJUDPPHPRU\FDQRQO\EHFKDQJHGE\WKHERRWORDGHULQWKHXSORDG
SURFHVVLQLWLDWHGE\WKH$UGXLQRVRIWZDUHUXQQLQJRQ\RXUFRPSXWHU$IWHUWKHXSORDG
SURFHVVLVFRPSOHWHGWKHPHPRU\FDQQRWEHFKDQJHGXQWLOWKHQH[WXSORDG7KHUHLV
IDUPRUHSURJUDPPHPRU\RQDQ$UGXLQRERDUGWKDQ5$0VRLWFDQEHEHQHILFLDOWR
VWRUHYDOXHVWKDWGRQWFKDQJHZKLOHWKHFRGHUXQVHJFRQVWDQWVLQSURJUDPPHPRU\
7KHERRWORDGHUWDNHVXSVRPHVSDFHLQSURJUDPPHPRU\,IDOORWKHUDWWHPSWVWRPLQ
LPL]HWKHFRGHWRILWLQSURJUDPPHPRU\KDYHIDLOHGWKHERRWORDGHUFDQEHUHPRYHG
WRIUHHXSVSDFHEXWDQDGGLWLRQDOKDUGZDUHSURJUDPPHULVWKHQQHHGHGWRJHWFRGH
RQWRWKHERDUG
531
,I\RXUFRGHLVODUJHUWKDQWKHSURJUDPPHPRU\VSDFHDYDLODEOHRQWKHFKLSWKHXSORDG
ZLOOQRWZRUNDQGWKH,'(ZLOOZDUQ\RXWKDWWKHVNHWFKLVWRRELJZKHQ\RXFRPSLOH
5$0LVXVHGE\WKHFRGHDVLWUXQVWRVWRUHWKHYDOXHVIRUWKHYDULDEOHVXVHGE\\RXU
VNHWFKLQFOXGLQJYDULDEOHVLQWKHOLEUDULHVXVHGE\\RXUVNHWFK5$0LVYRODWLOHZKLFK
PHDQVLWFDQEHFKDQJHGE\FRGHLQ\RXUVNHWFK,WDOVRPHDQVDQ\WKLQJVWRUHGLQWKLV
PHPRU\LVORVWZKHQSRZHULVVZLWFKHGRII$UGXLQRKDVPXFKOHVV5$0WKDQSURJUDP
PHPRU\,I\RXUXQRXWRI5$0ZKLOH\RXUVNHWFKUXQVRQWKHERDUGDVYDULDEOHVDUH
FUHDWHGDQGGHVWUR\HGZKLOHWKHFRGHUXQVWKHERDUGZLOOPLVEHKDYHFUDVK
((3520(OHFWULFDOO\(UDVDEOH3URJUDPPDEOH5HDG2QO\0HPRU\LVPHPRU\WKDW
FRGHUXQQLQJRQ$UGXLQRFDQUHDGDQGZULWHEXWLWLVQRQYRODWLOHPHPRU\WKDWUHWDLQV
YDOXHVHYHQZKHQSRZHULVVZLWFKHGRII((3520DFFHVVLVVLJQLILFDQWO\VORZHUWKDQ
IRU5$0VR((3520LVXVXDOO\XVHGWRVWRUHFRQILJXUDWLRQRURWKHUGDWDWKDWLVUHDG
DWVWDUWXSWRUHVWRUHLQIRUPDWLRQIURPWKHSUHYLRXVVHVVLRQ
7RXQGHUVWDQGWKHVHLVVXHVLWLVKHOSIXOWRXQGHUVWDQGKRZWKH$UGXLQR,'(SUHSDUHV
\RXUFRGHWRJRRQWRWKHFKLSDQGKRZ\RXFDQLQVSHFWWKHUHVXOWVLWSURGXFHV
Preprocessor
6RPHRIWKHUHFLSHVKHUHXVHWKHSUHSURFHVVRUWRDFKLHYHWKHGHVLUHGUHVXOW3UHSURFHVVLQJ
LVDVWHSLQWKHILUVWVWDJHRIWKHEXLOGSURFHVVLQZKLFKWKHVRXUFHFRGH\RXUVNHWFKLV
SUHSDUHGIRUFRPSLOLQJ9DULRXVILQGDQGUHSODFHIXQFWLRQVFDQEHSHUIRUPHG3UHSUR
FHVVRUFRPPDQGVDUHLGHQWLILHGE\OLQHVWKDWVWDUWZLWK#<RXKDYHDOUHDG\VHHQWKHP
LQVNHWFKHVWKDWXVHDOLEUDU\#includeWHOOVWKHSUHSURFHVVRUWRLQVHUWWKHFRGHIURP
WKHQDPHGOLEUDU\ILOH6RPHWLPHVWKHSUHSURFHVVRULVWKHRQO\ZD\WRDFKLHYHZKDWLV
QHHGHGEXWLWVV\QWD[LVGLIIHUHQWIURP&DQG&FRGHDQGLWFDQLQWURGXFHEXJVWKDW
DUHVXEWOHDQGKDUGWRWUDFNGRZQVRXVHLWZLWKFDUH
See Also
$95IUHDNVLVDZHEVLWHIRUVRIWZDUHHQJLQHHUVWKDWLVDJRRGVRXUFHIRUWHFKQLFDOGHWDLO
RQWKHFRQWUROOHUFKLSVXVHGE\$UGXLQRKWWSZZZDYUIUHDNVQHW
7HFKQLFDOGHWDLOVRQWKH&SUHSURFHVVRUDUHDYDLODEOHDWKWWSJFFJQXRUJRQOLQHGRFV
JFFFSSBKWPO
17.1 Understanding the Arduino Build Process
Problem
<RXZDQWWRVHHZKDWLVKDSSHQLQJXQGHUWKHFRYHUVZKHQ\RXFRPSLOHDQGXSORDGD
VNHWFK
532 | Chapter 17: Advanced Coding and Memory Handling
Solution
7RVHHDOOWKHFRPPDQGOLQHDFWLYLW\WKDWWDNHVSODFHKROGGRZQWKH6KLIWNH\ZKHQ
\RXFOLFNRQ&RPSLOHRU8SORDG7KHFRQVROHDUHDDWWKHERWWRPRIWKH,'(ZLOOGLVSOD\
GHWDLOVRIWKHFRPSLOHSURFHVV
7R KDYH WKLV GHWDLO DOZD\V YLVLEOH \RX FDQ FKDQJH D YDOXH LQ WKH $UGXLQR SUHIHUHQ
FHVW[WILOH7KLVILOHVKRXOGEHLQWKHIROORZLQJORFDWLRQV
0DF
8VHUV86(51$0(!/LEUDU\$UGXLQRSUHIHUHQFHVW[W
:LQGRZV;3
&?'RFXPHQWV DQG 6HWWLQJV?86(51$0(!?$SSOLFDWLRQ 'DWD?$UGXLQR?SUHIHUHQ
FHVW[W
:LQGRZV9LVWD
F?8VHUV?86(51$0(!?$SS'DWD?5RDPLQJ?$UGXLQR?SUHIHUHQFHVW[W
/LQX[
aDUGXLQRSUHIHUHQFHVW[W
0DNHVXUHWKH$UGXLQR,'(LVQRWUXQQLQJFKDQJHVPDGHWRSUHIHUHQFHVW[WZLOOQRWEH
VDYHGLIWKH,'(LVUXQQLQJ2SHQWKHILOHDQGILQGWKHOLQHbuild.verbose=falseLWLV
QHDUWKHERWWRPRIWKHILOH&KDQJHfalseWRtrueDQGVDYHWKHILOH
Discussion
:KHQ\RXFOLFNRQ&RPSLOHRU8SORDGDORWRIDFWLYLW\KDSSHQVWKDWLVQRWXVXDOO\
GLVSOD\HGRQVFUHHQ7KHFRPPDQGOLQHWRROVWKDWWKH$UGXLQR,'(ZDVEXLOWWRKLGH
DUHXVHGWRFRPSLOHOLQNDQGXSORDG\RXUFRGHWRWKHERDUG
)LUVW \RXU VNHWFK ILOHV DUH WUDQVIRUPHG LQWR D ILOH VXLWDEOH IRU WKH FRPSLOHU $95
*&&WRSURFHVV$OOVRXUFHILOHVLQWKHVNHWFKIROGHUWKDWKDYHQRILOHH[WHQVLRQDUH
MRLQHGWRJHWKHUWRPDNHRQHILOH$OOILOHVWKDWHQGLQFRUFSSDUHFRPSLOHGVHSDUDWHO\
+HDGHUILOHVZLWKDQKH[WHQVLRQDUHLJQRUHGXQOHVVWKH\DUHH[SOLFLWO\LQFOXGHGLQWKH
ILOHVWKDWDUHEHLQJMRLQHG
#include "WProgram.h"LVDGGHGDWWKHWRSRIWKHILOHWRLQFOXGHWKHKHDGHUILOHZLWKDOO
WKH$UGXLQRVSHFLILFFRGHGHILQLWLRQVVXFKDVdigitalWrite()DQGanalogRead(),I\RX
ZDQWWRH[DPLQHLWVFRQWHQWV\RXFDQILQGWKHILOHRQ:LQGRZVXQGHUWKHGLUHFWRU\
ZKHUH $UGXLQR ZDV LQVWDOOHG IURP WKHUH \RX FDQ QDYLJDWH WR
+DUGZDUH$UGXLQR&RUHV $UGXLQR
2QWKH0DF&WUOFOLFNWKH$UGXLQRDSSOLFDWLRQLFRQDQGVHOHFW6KRZ3DFNDJH&RQWHQWV
IURP WKH GURSGRZQ PHQX $ IROGHU ZLOO RSHQ IURP WKH IROGHU QDYLJDWH WR &RQ
WHQWV 5HVRXUFHV -DYD +DUGZDUH $UGXLQR &RUHV $UGXLQR
17.1 Understanding the Arduino Build Process | 533
7KH$UGXLQRGLUHFWRU\VWUXFWXUHPD\FKDQJHLQQHZUHOHDVHVVRFKHFN
WKHGRFXPHQWDWLRQIRUWKHUHOHDVH\RXDUHXVLQJ
7RPDNHWKHFRGHYDOLG&WKHSURWRW\SHVRIDQ\IXQFWLRQVGHFODUHGLQ\RXUFRGHDUH
JHQHUDWHGQH[WDQGLQVHUWHG
)LQDOO\ WKH VHWWLQJ RI WKH ERDUG PHQX LV XVHG WR LQVHUW YDOXHV REWDLQHG IURP WKH
ERDUGVW[WILOHWKDWGHILQHYDULRXVFRQVWDQWVXVHGIRUWKHFRQWUROOHUFKLSVRQWKHVHOHFWHG
ERDUG
7KLVILOHLVWKHQFRPSLOHGE\$95*&&ZKLFKLVLQFOXGHGZLWKLQWKH$UGXLQRPDLQ
GRZQORDGLWLVLQWKHWRROVIROGHU
7KHFRPSLOHUSURGXFHVDQXPEHURIREMHFWILOHVILOHVZLWKDQH[WHQVLRQRIRWKDWZLOO
EHFRPELQHGE\WKHOLQNWRRO7KHVHILOHVDUHVWRUHGLQWPSRQ0DFDQG/LQX[2Q
:LQGRZVWKH\DUHLQWKHDSSOHWGLUHFWRU\DIROGHUEHORZWKH$UGXLQRLQVWDOOGLUHFWRU\
7KHREMHFWILOHVDUHWKHQOLQNHGWRJHWKHUWRPDNHD+(;ILOHWRXSORDGWRWKHERDUG
$YUGXGHDXWLOLW\IRUWUDQVIHUULQJILOHVWRWKH$UGXLQRFRQWUROOHULVXVHGWRXSORDGWR
WKHERDUG
7KH WRROV XVHG WR LPSOHPHQW WKH EXLOG SURFHVV FDQ EH IRXQG LQ WKH KDUGZDUH?WRROV
GLUHFWRU\
$QRWKHU XVHIXO WRRO IRU H[SHULHQFHG SURJUDPPHUV LV DYUREMGXPS DOVR LQ WKH WRROV
IROGHU,WOHWV\RXVHHKRZWKHFRPSLOHUWXUQVWKHVNHWFKLQWRFRGHWKDWWKHFRQWUROOHU
FKLSUXQV7KLVWRROSURGXFHVDGLVDVVHPEO\OLVWLQJRI\RXUVNHWFKZKLFKVKRZVWKH
REMHFWFRGHLQWHUPL[HGZLWKWKHVRXUFHFRGH,WFDQDOVRGLVSOD\DPHPRU\PDSRIDOO
WKHYDULDEOHVXVHGLQ\RXUVNHWFK7RXVHWKHWRROFRPSLOHWKHVNHWFKDQGQDYLJDWHWR
WKHIROGHUFRQWDLQLQJWKH$UGXLQRGLVWULEXWLRQ7KHQQDYLJDWHWRWKHIROGHUZLWKDOOWKH
LQWHUPHGLDWH ILOHV XVHG LQ WKH EXLOG SURFHVV DV H[SODLQHG HDUOLHU 7KH ILOH XVHG E\
DYUREMGXPSLVWKHRQHZLWKWKHH[WHQVLRQHOI)RUH[DPSOHLI\RXFRPSLOHWKH%OLQN
VNHWFK\RXFRXOGYLHZWKHFRPSLOHGRXWSXWWKHPDFKLQHFRGHE\H[HFXWLQJWKHIRO
ORZLQJRQWKHFRPPDQGOLQH
..\hardware\tools\avr\bin\avr-objdump.exe -S blink.cpp.elf
,WLVFRQYHQLHQWWRGLUHFWWKHRXWSXWWRDILOHWKDWFDQEHUHDGLQDWH[WHGLWRU<RXFDQ
GRWKLVDVIROORZV
..\hardware\tools\avr\bin\avr-objdump.exe -S blink.cpp.elf > blink.txt
7KLVYHUVLRQDGGVDOLVWRIVHFWLRQKHDGHUVKHOSIXOIRUGHWHUPLQLQJPHPRU\XVDJH
..\hardware\tools\avr\bin\avr-objdump.exe -S -h blink.cpp.elf > blink.txt
534 | Chapter 17: Advanced Coding and Memory Handling
<RXFDQFUHDWHDEDWFKILOHWRGXPSWKHOLVWLQJLQWRDILOH$GGWKHSDWK
RI\RXU$UGXLQRLQVWDOODWLRQWRWKHIROORZLQJOLQHDQGVDYHLWWRDEDWFK
ILOH
KDUGZDUH?WRROV?DYU?ELQ?DYUREMGXPSH[H6K7GDWD!W[W
See Also
)RULQIRUPDWLRQRQWKH$UGXLQREXLOGSURFHVVVHHKWWSFRGHJRRJOHFRPSDUGXLQR
ZLNL%XLOG3URFHVV
7KH$95IUHDNVZHEVLWHKWWSZZZDYUIUHDNVQHWZLNLLQGH[SKS'RFXPHQWDWLRQ$95
B*&&
17.2 Determining the Amount of Free and Used RAM
Problem
<RXZDQWWREHVXUH\RXKDYHQRWUXQRXWRI5$0$VNHWFKZLOOQRWUXQFRUUHFWO\LI
WKHUHLVLQVXIILFLHQWPHPRU\DQGWKLVFDQEHGLIILFXOWWRGHWHFW
Solution
7KLVUHFLSHVKRZV\RXKRZ\RXFDQGHWHUPLQHWKHDPRXQWRIIUHHPHPRU\DYDLODEOHWR
\RXUVNHWFK7KLVVNHWFKFRQWDLQVDIXQFWLRQFDOOHGmemoryFreeWKDWUHSRUWVWKHDPRXQW
RIDYDLODEOH5$0
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.print(memoryFree()); // print the free memory
Serial.print(' '); // print a space
delay(1000);
}
// variables created by the build process when compiling the sketch
extern int __bss_end;
extern void *__brkval;
// function to return the amount of free RAM
int memoryFree()
{
int freeValue;
17.2 Determining the Amount of Free and Used RAM | 535
if((int)__brkval == 0)
freeValue = ((int)&freeValue) - ((int)&__bss_end);
else
freeValue = ((int)&freeValue) - ((int)__brkval);
return freeValue;
}
Discussion
7KHmemoryFreeIXQFWLRQXVHVV\VWHPYDULDEOHVWRFDOFXODWHWKHDPRXQWRI5$06\VWHP
YDULDEOHVDUHQRWQRUPDOO\YLVLEOHWKH\DUHFUHDWHGE\WKHFRPSLOHUWRPDQDJHLQWHUQDO
UHVRXUFHV,WLVQRWQHFHVVDU\WRXQGHUVWDQGKRZWKHIXQFWLRQZRUNVWRXVHLWVRXWSXW
7KHIXQFWLRQUHWXUQVWKHQXPEHURIE\WHVRIIUHHPHPRU\
7KHQXPEHURIE\WHV\RXUFRGHXVHVFKDQJHVDVWKHFRGHUXQV7KHLPSRUWDQWWKLQJLV
WRHQVXUHWKDW\RXGRQWFRQVXPHPRUHPHPRU\WKDQ\RXKDYH
+HUHDUHWKHPDLQZD\V5$0PHPRU\LVFRQVXPHG
:KHQ\RXLQLWLDOL]HFRQVWDQWV
#define ERROR_MESSAGE "an error has occurred"
:KHQ\RXGHFODUHJOREDOYDULDEOHV
char myMessage[] = "Hello World";
:KHQ\RXPDNHDIXQFWLRQFDOO
void myFunction(int value)
{
int result;
result = value * 2;
return result;
}
:KHQ\RXG\QDPLFDOO\DOORFDWHPHPRU\
String stringOne = "Arduino String";
7KH$UGXLQRStringFODVVXVHVG\QDPLFPHPRU\WRDOORFDWHVSDFHIRUVWULQJV<RXFDQ
VHHWKLVE\DGGLQJWKHIROORZLQJOLQHWRWKHYHU\WRSRIWKHFRGHLQWKH6ROXWLRQ
String s = "\n";
DQGWKHIROORZLQJOLQHVMXVWEHIRUHWKHdelayLQWKHloopFRGH
s = s + "Hello I am Arduino \n";
Serial.println(s); // print the string value
<RXZLOOVHHWKHPHPRU\YDOXHUHGXFHDVWKHVL]HRIWKHVWULQJLVLQFUHDVHGHDFKWLPH
WKURXJKWKHloop,I\RXUXQWKHVNHWFKORQJHQRXJKWKHPHPRU\ZLOOUXQRXWGRQW
HQGOHVVO\WU\WRLQFUHDVHWKHVL]HRIDVWULQJLQDQ\WKLQJRWKHUWKDQDWHVWDSSOLFDWLRQ
:ULWLQJFRGHOLNHWKLVWKDWFUHDWHVDFRQVWDQWO\H[SDQGLQJYDOXHLVDVXUHZD\WRUXQ
RXWRIPHPRU\<RXVKRXOGDOVREHFDUHIXOQRWWRFUHDWHFRGHWKDWG\QDPLFDOO\FUHDWHV
536 | Chapter 17: Advanced Coding and Memory Handling
GLIIHUHQWQXPEHUVRIYDULDEOHVEDVHGRQVRPHSDUDPHWHUZKLOHWKHFRGHUXQVDVLWZLOO
EHYHU\GLIILFXOWWREHVXUH\RXZLOOQRWH[FHHGWKHPHPRU\FDSDELOLWLHVRIWKHERDUG
ZKHQWKHFRGHUXQV
&RQVWDQWVDQGJOREDOYDULDEOHVDUHRIWHQGHFODUHGLQOLEUDULHVDVZHOOVR\RXPD\QRW
EHDZDUHRIWKHPEXWWKH\VWLOOXVHXS5$07KH6HULDOOLEUDU\IRUH[DPSOHKDVD
E\WHJOREDODUUD\WKDWLWXVHVIRULQFRPLQJVHULDOGDWD7KLVDORQHFRQVXPHVRQHHLJKWK
RIWKHWRWDOPHPRU\RIDQROG$UGXLQRFKLS
See Also
$ WHFKQLFDO RYHUYLHZ RI PHPRU\ XVDJH LV DYDLODEOH DW KWWSZZZJQXRUJVDYDQQDK
FKHFNRXWVQRQJQXDYUOLEFXVHUPDQXDOPDOORFKWPO
17.3 Storing and Retrieving Numeric Values in
Program Memory
Problem
<RXKDYHDORWRIFRQVWDQWQXPHULFGDWDDQGGRQWZDQWWRDOORFDWHWKLVWR5$0
Solution
6WRUHQXPHULFYDULDEOHVLQSURJUDPPHPRU\WKHIODVKPHPRU\XVHGWRVWRUH$UGXLQR
SURJUDPV
7KLVVNHWFKDGMXVWVDIDGLQJ/('IRUWKHQRQOLQHDUVHQVLWLYLW\RIKXPDQYLVLRQ,WVWRUHV
WKHYDOXHVWRXVHLQDWDEOHRIYDOXHVLQSURJUDPPHPRU\UDWKHUWKDQ5$0
7KHVNHWFKLVEDVHGRQ5HFLSHVHH&KDSWHUIRUDZLULQJGLDJUDPDQGGLVFXVVLRQ
RQGULYLQJ/('V5XQQLQJWKLVVNHWFKUHVXOWVLQDVPRRWKFKDQJHLQEULJKWQHVVZLWKWKH
/('RQSLQFRPSDUHGWRWKH/('RQSLQ
/* ProgmemCurve sketch
* uses table in Progmem to convert linear to exponential output
* See Recipe 7.2 and Figure 7-2
*/
#include <avr/pgmspace.h> // needed for PROGMEM
// table of exponential values
// generated for values of i from 0 to 255 -> x=round( pow( 2.0, i/32.0) - 1);
const byte table[]PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
17.3 Storing and Retrieving Numeric Values in Program Memory | 537
5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7,
7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10,
10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15,
15, 15, 16, 16, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20, 21, 21,
22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30,
31, 32, 32, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, 58, 59, 60, 62,
63, 64, 66, 67, 69, 70, 72, 73, 75, 77, 78, 80, 82, 84, 86, 88,
90, 91, 94, 96, 98, 100, 102, 104, 107, 109, 111, 114, 116, 119, 122, 124,
127, 130, 133, 136, 139, 142, 145, 148, 151, 155, 158, 161, 165, 169, 172, 176,
180, 184, 188, 192, 196, 201, 205, 210, 214, 219, 224, 229, 234, 239, 244, 250
};
const int rawLedPin = 3; // this LED is fed with raw values
const int adjustedLedPin = 5; // this LED is driven from table
int brightness = 0;
int increment = 1;
void setup()
{
// pins driven by analogWrite do not need to be declared as outputs
}
void loop()
{
if(brightness > 255)
{
increment = -1; // count down after reaching 255
}
else if(brightness < 1)
{
increment = 1; // count up after dropping back down to 0
}
brightness = brightness + increment; // increment (or decrement sign is minus)
// write the brightness value to the LEDs
analogWrite(rawLedPin, brightness); // this is the raw value
int adjustedBrightness = pgm_read_byte(&table[brightness]); // adjusted value
analogWrite(adjustedLedPin, adjustedBrightness);
delay(10); // 10ms for each step change means 2.55 secs to fade up or down
}
Discussion
:KHQ\RXQHHGWRXVHDFRPSOH[H[SUHVVLRQWRFDOFXODWHDUDQJHRIYDOXHVWKDWUHJXODUO\
UHSHDWLWLVRIWHQEHWWHUWRSUHFDOFXODWHWKHYDOXHVDQGLQFOXGHWKHPLQDWDEOHRIYDOXHV
XVXDOO\DVDQDUUD\LQWKHFRGH7KLVVDYHVWKHWLPHQHHGHGWRFDOFXODWHWKHYDOXHV
UHSHDWHGO\ZKHQWKHFRGHUXQV7KHGLVDGYDQWDJHFRQFHUQVWKHPHPRU\QHHGHGWRSODFH
WKHVHYDOXHVLQ5$05$0LVOLPLWHGRQ$UGXLQRDQGWKHPXFKODUJHUSURJUDPPHPRU\
VSDFHFDQEHXVHGWRVWRUHFRQVWDQWYDOXHV7KLVLVSDUWLFXODUO\KHOSIXOIRUVNHWFKHVWKDW
KDYHODUJHDUUD\VRIQXPEHUV
538 | Chapter 17: Advanced Coding and Memory Handling
$WWKHWRSRIWKHVNHWFKWKHWDEOHLVGHILQHGZLWKWKHIROORZLQJH[SUHVVLRQ
const byte table[]PROGMEM = {
0, . . .
PROGMEMWHOOVWKHFRPSLOHUWKDWWKHYDOXHVDUHWREHVWRUHGLQSURJUDPPHPRU\UDWKHU
WKDQ5$07KHUHPDLQGHURIWKHH[SUHVVLRQLVVLPLODUWRGHILQLQJDFRQYHQWLRQDODUUD\
VHH&KDSWHU
7KH ORZOHYHO GHILQLWLRQV QHHGHG WR XVH PROGMEM DUH FRQWDLQHG LQ D ILOH QDPHG
SJPVSDFHKDQGWKHVNHWFKLQFOXGHVWKLVDVIROORZV
#include <avr/pgmspace.h>
7RDGMXVWWKHEULJKWQHVVWRPDNHWKHIDGHORRNXQLIRUPWKLVUHFLSHDGGVWKHIROORZLQJ
OLQHVWRWKH/('RXWSXWFRGHXVHGLQ5HFLSH
int adjustedBrightness = pgm_read_byte(&table[brightness]);
analogWrite(adjustedLedPin, adjustedBrightness);
7KHYDULDEOH adjustedBrightnessLVVHWIURPDYDOXHUHDGIURPSURJUDPPHPRU\7KH
H[SUHVVLRQ pgm_read_byte(&table[brightness]); PHDQV WR UHWXUQ WKH DGGUHVV RI WKH
HQWU\LQWKH tableDUUD\DWWKHLQGH[SRVLWLRQJLYHQE\ brightness(DFKHQWU\LQWKH
WDEOHLVRQHE\WHVRDQRWKHUZD\WRZULWHWKLVH[SUHVVLRQLV
pgm_read_byte(table + brightness);
,ILWLVQRWFOHDUZK\ &table[brightness]LVHTXLYDOHQWWR table + brightnessGRQW
ZRUU\XVHZKLFKHYHUH[SUHVVLRQPDNHVPRUHVHQVHWR\RX
$QRWKHU H[DPSOH LV IURP 5HFLSH ZKLFK XVHG D WDEOH IRU FRQYHUWLQJ DQ LQIUDUHG
VHQVRUUHDGLQJLQWRGLVWDQFH+HUHLVWKHVNHWFKIURPWKDWUHFLSHFRQYHUWHGWRXVHDWDEOH
LQSURJUDPPHPRU\LQVWHDGRI5$0
/* ir-distance_Progmem sketch
* prints distance & changes LED flash rate depending on distance from IR sensor
* uses progmem for table
*/
#include <avr/pgmspace.h> // needed when using Progmem
// table entries are distances in steps of 250 millivolts
const int TABLE_ENTRIES = 12;
const int firstElement = 250; // first entry is 250 mV
const int interval = 250; // millivolts between each element
// the following is the definition of the table in Program Memory
const int distanceP[TABLE_ENTRIES] PROGMEM = { 150,140,130,100,60,50,
40,35,30,25,20,15 };
// This function reads from Program Memory at the given index
int getTableEntry(int index)
{
int value = pgm_read_word(&distanceP[index]);
return value;
}
17.3 Storing and Retrieving Numeric Values in Program Memory | 539
7KHUHPDLQLQJFRGHLVVLPLODUWR5HFLSHH[FHSWWKDWWKHgetTableEntryIXQFWLRQLV
XVHGWRJHWWKHYDOXHIURPSURJUDPPHPRU\LQVWHDGRIDFFHVVLQJDWDEOHLQ5$0+HUH
LVWKHUHYLVHGgetDistanceIXQFWLRQIURPWKDWUHFLSH
int getDistance(int mV)
{
if( mV > interval * TABLE_ENTRIES )
return getTableEntry(TABLE_ENTRIES-1); // the minimum distance
else
{
int index = mV / interval;
float frac = (mV % 250) / (float)interval;
return getTableEntry(index) - ((getTableEntry(index) -
getTableEntry(index+1)) * frac);
}
}
17.4 Storing and Retrieving Strings in Program Memory
Problem
<RXKDYHORWVRIVWULQJVDQGWKH\DUHFRQVXPLQJWRRPXFK5$0<RXZDQWWRPRYH
VWULQJFRQVWDQWVVXFKDVPHQXSURPSWVRUGHEXJJLQJVWDWHPHQWVRXWRI5$0DQGLQWR
SURJUDPPHPRU\
Solution
7KLVVNHWFKFUHDWHVDVWULQJLQSURJUDPPHPRU\DQGSULQWVLWVYDOXHWRWKH6HULDO0RQ
LWRU7KHDPRXQWRIIUHH5$0LVSULQWHGXVLQJWKHIXQFWLRQGHVFULEHGLQ5HFLSH
#include <avr/pgmspace.h> // for progmem
//create a string of 20 characters in progmem
const prog_uchar myText[] = "arduino duemilanove ";
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.print(memoryFree()); // print the free memory
Serial.print(' '); // print a space
printP(myText); // print the string
delay(1000);
}
// function to print a PROGMEM string
void printP(const prog_uchar *str)
540 | Chapter 17: Advanced Coding and Memory Handling
{
char c;
while((c = pgm_read_byte(str++)))
Serial.print(c,BYTE);
}
// variables created by the build process when compiling the sketch
extern int __bss_end;
extern void *__brkval;
// function to return the amount of free RAM
int memoryFree()
{
int freeValue;
if((int)__brkval == 0)
freeValue = ((int)&freeValue) - ((int)&__bss_end);
else
freeValue = ((int)&freeValue) - ((int)__brkval);
return freeValue;
}
Discussion
6WULQJVDUHSDUWLFXODUO\KXQJU\ZKHQLWFRPHVWR5$0(DFKFKDUDFWHUXVHVDE\WHVR
LWLVHDV\WRFRQVXPHODUJHFKXQNVRI5$0LI\RXKDYHORWVRIZRUGVLQVWULQJVLQ\RXU
VNHWFK
7KH#includeDWWKHWRSLVUHTXLUHGIRUWKHFRGHQHHGHGWRDFFHVVSURJUDPPHPRU\
#include <avr/pgmspace.h> // for progmem
3URJUDPPHPRU\VWULQJGHFODUDWLRQVEHJLQZLWKconst prog_ucharIROORZHGE\WKHQDPH
RIWKHVWULQJYDULDEOHDQGWKHQWKHVWULQJFKDUDFWHUV
const prog_uchar myText[] = "arduino duemilanove "; //a string of 20 characters
in progmem
<RXFDQXVHWKHIROORZLQJH[SUHVVLRQWRFUHDWHDSUHSURFHVVRUPDFURWKDWPDNHV\RXU
VWULQJGHFODUDWLRQVHDVLHUWRZULWH$GGWKHIROORZLQJOLQHWRWKHWRSRIWKHVNHWFK
#define P(name) const prog_uchar name[] PROGMEM // declare a PROGMEM string
:KHUHYHU\RXXVHP(name)WKHH[SUHVVLRQZLOOEHUHSODFHGZLWKWKHIXOOH[SDQVLRQ6R
WKHIROORZLQJFRGHZRXOGGHFODUHWKHVDPHVWULQJDVLQWKHHDUOLHUVNHWFK
P(myTextP) = "arduino duemilanove "; //a string of 20 characters in progmem
7KLVXVHVDSUHSURFHVVLQJPDFURDVXEMHFWQRWFRYHUHGLQWKLVERRNEXW\RXFDQILQG
OLQNVWRPRUHLQIRUPDWLRQRQWKHSUHSURFHVVRULQWKLVFKDSWHUVLQWURGXFWLRQVHFWLRQ
17.4 Storing and Retrieving Strings in Program Memory | 541
,I\RXFKDQJHWKHVNHWFKWRXVHDFRQYHQWLRQDO5$0VWULQJ\RXZLOOVHHWKDWWKHIUHH
5$0LQFUHDVHVE\DWOHDVWE\WHV
char myText[] = "arduino duemilanove "; //a string of 20 characters
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.print(memoryFree()); // print the free memory
Serial.print(' '); // print a space
Serial.print(myText); // print the string
delay(1000);
}
17.5 Using #define and const Instead of Integers
Problem
<RXZDQWWRPLQLPL]H5$0XVDJHE\WHOOLQJWKHFRPSLOHUWKDWWKHYDOXHLVFRQVWDQWDQG
FDQEHRSWLPL]HG
Solution
8VHconstWRGHFODUHYDOXHVWKDWDUHFRQVWDQWWKURXJKRXWWKHVNHWFK
)RUH[DPSOHLQVWHDGRI
int ledPin=13;
XVH
const int ledPin=13;
Discussion
:HRIWHQZDQWWRXVHDFRQVWDQWYDOXHLQGLIIHUHQWDUHDVRIFRGH-XVWZULWLQJWKHQXPEHU
LVDUHDOO\EDGLGHD,I\RXODWHUZDQWWRFKDQJHWKHYDOXHXVHGLWVGLIILFXOWWRZRUNRXW
ZKLFKQXPEHUVVFDWWHUHGWKURXJKRXWWKHFRGHDOVRQHHGWREHFKDQJHG,WLVEHVWWRXVH
QDPHGUHIHUHQFHV
+HUHDUHWKUHHGLIIHUHQWZD\VWRGHILQHDYDOXHWKDWLVDFRQVWDQW
int ledPin = 13; // a variable, but this wastes RAM
const int ledPin = 13; // a const does not use RAM
#define ledPin 13 // using a #define
// the preprocessor replaces ledPin with 13
pinMode(ledPin, OUTPUT);
542 | Chapter 17: Advanced Coding and Memory Handling
$OWKRXJKWKHILUVWWZRH[SUHVVLRQVORRNVLPLODUWKHWHUP constWHOOVWKHFRPSLOHUQRW
WRWUHDWledPinDVDQRUGLQDU\YDULDEOH8QOLNHWKHRUGLQDU\intQR5$0LVUHVHUYHGWR
KROGWKHYDOXHIRUWKHconstDVLWLVJXDUDQWHHGQRWWRFKDQJH7KHFRPSLOHUZLOOSURGXFH
H[DFWO\WKHVDPHFRGHDVLI\RXKDGZULWWHQ
pinMode(13, OUTPUT);
<RXZLOOVRPHWLPHVVHH #defineXVHGWRGHILQHFRQVWDQWVLQROGHU$UGXLQRFRGHEXW
constLVDEHWWHUFKRLFHWKDQ#define7KLVLVEHFDXVHDconstYDULDEOHKDVDW\SHZKLFK
HQDEOHVWKHFRPSLOHUWRYHULI\DQGUHSRUWLIWKHYDULDEOHLVEHLQJXVHGLQZD\VQRWDS
SURSULDWHIRUWKDWW\SH7KHFRPSLOHUZLOODOVRUHVSHFW&UXOHVIRUWKHVFRSHRIDconst
YDULDEOH$#defineYDOXHZLOODIIHFWDOOWKHFRGHLQWKHVNHWFKZKLFKPD\EHPRUHWKDQ
\RXLQWHQGHG$QRWKHUEHQHILWRIconstLVWKDWLWXVHVIDPLOLDUV\QWD[#defineGRHVQRW
XVHWKHHTXDOVVLJQDQGQRVHPLFRORQLVXVHGDWWKHHQG
See Also
6HHWKLVFKDSWHUVLQWURGXFWLRQVHFWLRQIRUPRUHRQWKHSUHSURFHVVRU
17.6 Using Conditional Compilations
Problem
<RXZDQWWRKDYHGLIIHUHQWYHUVLRQVRI\RXUFRGHWKDWFDQEHVHOHFWLYHO\FRPSLOHG)RU
H[DPSOH\RXPD\QHHGFRGHWRZRUNGLIIHUHQWO\ZKHQGHEXJJLQJRUZKHQUXQQLQJ
ZLWKGLIIHUHQWERDUGV
Solution
<RXFDQXVHWKHFRQGLWLRQDOVWDWHPHQWVDLPHGDWWKHSUHSURFHVVRUWRFRQWUROKRZ\RXU
VNHWFKLVEXLOW
7KLVH[DPSOHIURPVNHWFKHVLQ&KDSWHULQFOXGHVWKH63,KOLEUDU\ILOHWKDWLVRQO\
DYDLODEOHIRUDQGQHHGHGZLWK$UGXLQRYHUVLRQVUHOHDVHGDIWHU
#if ARDUINO > 18
#include <SPI.h> // needed for Arduino versions later than 0018
#endif
7KLVH[DPSOHXVLQJWKHVNHWFKIURP5HFLSHGLVSOD\VVRPHGHEXJVWDWHPHQWVRQO\
LIDEBUGLVGHILQHG
/*
Pot_Debug sketch
blink an LED at a rate set by the position of a potentiometer
Uses Serial port for debug if DEBUG is defined
*/
const int potPin = 0; // select the input pin for the potentiometer
const int ledPin = 13; // select the pin for the LED
17.6 Using Conditional Compilations | 543
int val = 0; // variable to store the value coming from the sensor
#define DEBUG
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT
}
void loop() {
val = analogRead(potPin); // read the voltage on the pot
digitalWrite(ledPin, HIGH); // turn the ledPin on
delay(val); // blink rate set by pot value
digitalWrite(ledPin, LOW); // turn the ledPin off
delay(val); // turn LED off for same period as it was turned on
#if defined DEBUG
Serial.println(val);
#endif
}
Discussion
7KLVUHFLSHXVHVWKHSUHSURFHVVRUXVHGDWWKHEHJLQQLQJRIWKHFRPSLOHSURFHVVWRFKDQJH
ZKDWFRGHLVFRPSLOHG7KHILUVWH[DPSOHWHVWVLIWKHYDOXHRIWKHFRQVWDQW ARDUINOLV
JUHDWHUWKDQDQGLIVRWKHILOH63,KLVLQFOXGHG7KHYDOXHRIWKH ARDUINOFRQVWDQW
LVGHILQHGLQWKHEXLOGSURFHVVDQGFRUUHVSRQGVWRWKH$UGXLQRUHOHDVHYHUVLRQ7KH
V\QWD[IRUWKLVH[SUHVVLRQLVQRWWKHVDPHDVWKDWXVHGIRUZULWLQJDVNHWFK([SUHVVLRQV
WKDWEHJLQZLWKWKH#V\PERODUHSURFHVVHGEHIRUHWKHFRGHLVFRPSLOHGVHHWKLVFKDS
WHUVLQWURGXFWLRQVHFWLRQIRUPRUHRQWKHSUHSURFHVVRU
<RXKDYHDOUHDG\FRPHDFURVV#include
#include <library.h>
7KH < > EUDFNHWV WHOO WKH FRPSLOHU WR ORRN IRU WKH ILOH LQ WKH ORFDWLRQ IRU VWDQGDUG
OLEUDULHV
#include "header.h"
7KHFRPSLOHUZLOODOVRORRNLQWKHVNHWFKIROGHU
<RXFDQKDYHDFRQGLWLRQDOFRPSLOHEDVHGRQWKHFRQWUROOHUFKLSVHOHFWHGLQWKH,'(
)RUH[DPSOHWKHIROORZLQJFRGHZLOOSURGXFHGLIIHUHQWFRGHZKHQFRPSLOHGIRUD0HJD
ERDUGWKDWUHDGVWKHDGGLWLRQDODQDORJSLQVWKDWLWKDV
/*
* ConditionalCompile sketch
* This sketch recognizes the controller chip using conditional defines
*/
int numberOfSensors;
int val = 0; // variable to store the value coming from the sensor
544 | Chapter 17: Advanced Coding and Memory Handling
void setup()
{
Serial.begin(9600);
#if defined(__AVR_ATmega1280__) // defined when selecting Mega in the IDE
numberOfSensors = 16; // the number of analog inputs on the Mega
#else // if not Mega then assume a standard board
numberOfSensors = 6; // analog inputs on a standard Arduino board
#endif
Serial.print("The number of sensors is ");
Serial.println(numberOfSensors);
}
void loop() {
for(int sensor = 0; sensor < numberOfSensors; sensor++)
{
val = analogRead(sensor); // read the sensor value
Download from Wow! eBook <www.wowebook.com>
Serial.println(val); // display the value
}
Serial.println();
delay(1000); // delay a second between readings
}
See Also
7HFKQLFDOGHWDLOVRQWKH&SUHSURFHVVRUDUHDYDLODEOHDWKWWSJFFJQXRUJRQOLQHGRFV
JFFFSSBKWPO
17.6 Using Conditional Compilations | 545