You are on page 1of 10

21/6/2016 ArduinoTutorialsEthernet+SD

Home About Projects Learn Library Blog Store Forums

ladyada.net Search

ArduinoEthernet+SD December19,201113:28

UsingtheArduinotobrowsefilesonanSDcardremotely

Intro
Starting
Lesson0
Lesson1
Lesson2
Lesson3
Lesson4
Lesson5
#6LEDs
LCDs
Eth+SD
HELP!!!
Buystuff Whatsit?
Forums WejustgotthelatestversionoftheArduinoEthernetshieldwithaMicroSDcardslot
[http://www.adafruit.com/index.php?main_page=product_info&cPath=17_21&products_id=201]andIpromisedBill
GreimanI'dtryoutthelatestversionofhisSdFatLiblibrary[http://code.google.com/p/sdfatlib/downloads/list]soI
decidedtocodeupasimpleWebifiedfilebrowser.Itsaquickyprojectanddemonstrateswhatyoucando,but
itisn't100%perfectsoyoushouldbereadytomodifyitifyou'dliketodootherstuff,'K?

Thisisagoodbeginningtoaloggingwebmonitor,orremotestoragesystem.

Getfamiliar

Beforeyoudothistutorialyou'llwanttogetfamiliarwithwhatyou'reworkingon.Thisisn'tabeginner
tutorial,itsbestusedbythosewhoalreadyhavequiteabitArduinoormicrocontrollerexperienceandare
'fluent'inC/C++/Java!

Also,readuponhowtousetheEthernetshield[http://www.arduino.cc/en/Main/ArduinoEthernetShield]and
Ethernetlibrary[http://www.arduino.cc/en/Reference/Ethernet].ThenreviewmynotesonSDcardusageand
installingthelibrarywe'llbeusing[http://www.ladyada.net/learn/../make/logshield/sd.html]

YoushouldhavealreadygottentheEthernetshieldworkingwithyournetworksetup,too.

Whilewe'rehappytosharethiscode,pleasenotethatthisprojectisjustexamplecode.Itiscompletely
unsupported.Enjoyit!Modit!Hackit!Butpleasedon'texpectmorethanwhatispostedhere!Youcan
downloadthelatestcodefromGitHub(clickDownloadSourceinthetopright)
[http://github.com/adafruit/SDWebBrowse]

InitializingMicroSDcardonanEthernetshield

http://www.ladyada.net/learn/arduino/ethfiles.html 1/10
21/6/2016 ArduinoTutorialsEthernet+SD

ThelatestArduinoEthernetshield[http://www.adafruit.com/index.php?
main_page=product_info&cPath=17_21&products_id=201]comeswithahandyMicroSDcardslotsothatyoucan
storeandretrievedatathroughtheshield.Veryhandy!Letsshowhowtotalktothecard.

BesuretohavetheverylatestversionofSdFatLib[http://code.google.com/p/sdfatlib/downloads/list],asyou'll
needsomeofthenewercapabilities!

FirstthingtonoteisthattheSS(SlaveSelect)pinforthecardisdigital4(althoughasofthewritingofthis
minitutorial,theschematic[http://arduino.cc/en/uploads/Main/arduinoethernetshieldschematic.pdf]hasn'tbeen
updated,you'llhavetotrustme!)

OpenuptheSdFatInfoexamplesketchandchangethelineinloop()from

uint8_tr=card.init(SPI_HALF_SPEED);

To:

pinMode(10,OUTPUT);//settheSSpinasanoutput(necessary!)
digitalWrite(10,HIGH);//butturnofftheW5100chip!
uint8_tr=card.init(SPI_HALF_SPEED,4);//Usedigital4astheSDSSline

Besuretoaddthosetwoextralinesrightbeforehand!TheyEnabletheSPIinterface.Ifyou'reonaMega,use
pin53insteadof10

Nowuploadandtestthecard,youshouldseesomethinglikethis:

http://www.ladyada.net/learn/arduino/ethfiles.html 2/10
21/6/2016 ArduinoTutorialsEthernet+SD

Indicatingyoutalkedtothecardallright

Listfiles

PutsometextfilesonyourSDcard,usingacomputer,sothatyouhavedatatoread.Makesuretheyareinthe
rootdirectory,andnotinafolder

ThenruntheSdFatLsexamplesketchfromtheSdFatlibrary,youshouldseeitlistallthefilesyouhaveonthe
card,again,you'llhavetomakethechangesfromabovetoupdatethecard.init()parttothenewSSpin

Forexample,thecardI'llbeusinghastwofilesonitfromsomepreviousdatalogging.

MergeWebServer+SdFatLs

We'llbeginbycombiningWebServer(theexamplesketchthatcomeswiththeEthernetlib)andSdFatLsto
makeawebserverthatliststhefilesontheSDcard.Youcandownloadthefilehere
[http://github.com/adafruit/SDWebBrowse/blob/46a7d6a28f8b44d1a00bfddec987cf71d24da79a/SDWebBrowse.pde](you'll
needtocopy&pasteit,dosocarefully!)thenfollowalong!

PartoneistheEthernetandSDcardobjectsandasimpleerrorfunction(voiderror_P(constchar*str))that
printsouterrorsandhaltstheprogramifthereareseriousproblems.

http://www.ladyada.net/learn/arduino/ethfiles.html 3/10
21/6/2016 ArduinoTutorialsEthernet+SD
Youshould,ofcousre,setyourmacandipasnecessary,usetheipandmacthatworkedfromyourprevious
Ethernetshieldexplorations!

Thecard,volume,androotareobjectsthathelpustraversethecomplexstructureofanSDcard

Theerrorfunctionisnottooexciting,itjustprintsouttheerrorandsitsinawhile(1)loopforever

/*
*Thissketchwilllistallfilesintherootdirectoryand
*thendoarecursivelistofalldirectoriesontheSDcard.
*
*/

#include<SdFat.h>
#include<SdFatUtil.h>
#include<Ethernet.h>

/%%**%%%%**%%%%**%%%%**%%%%**%%%%**%%ETHERNETSTUFF%%**%%%%**%%%%**%%%%**%%%%**%%%%**%%/
bytemac[]={0xDE,0xAD,0xBE,0xEF,0xFE,0xED};
byteip[]={192,168,1,177};
Serverserver(80);

/%%**%%%%**%%%%**%%%%**%%%%**%%%%**%%SDCARDSTUFF%%**%%%%**%%%%**%%%%**%%%%**%%%%**%%/
Sd2Cardcard;
SdVolumevolume;
SdFileroot;

//storeerrorstringsinflashtosaveRAM
#defineerror(s)error_P(PSTR(s))

voiderror_P(constchar*str){
PgmPrint("error:");
SerialPrintln_P(str);
if(card.errorCode()){
PgmPrint("SDerror:");
Serial.print(card.errorCode(),HEX);
Serial.print(',');
Serial.println(card.errorData(),HEX);
}
while(1);
}

Part2isthesetup()function.ItsetsuptheSerialobjectsowecandebugtheconnectioninrealtime.Itthen
printsouttheRAMusage.You'llneedaAtmega328Arduinoforthisexperiment,andyoushouldseeatleat
1000bytesofRAMfree.Oncethisgetstounder250bytes,youmayberunningtoolow!

ThenwedothetrickwherewemakethehardwareSSpin#10toanOUTPUTandHIGHtodisablethewiznet
chipwhilewecheckthecardcontents.Ifyou'reonaMega,changethisto53.Thenweinitializethecard
whichshouldgofinesinceyoualreadytestedthisbefore

Thenweverifythecardstructure,printoutallthefiles,andprint"Done!".FinallywestucktheEthernet
initializationcodeattheendhere!NowwehaveboththeEthernetandSDcardworking

voidsetup(){
Serial.begin(9600);

PgmPrint("FreeRAM:");
Serial.println(FreeRam());

//initializetheSDcardatSPI_HALF_SPEEDtoavoidbuserrorswith
//breadboards.useSPI_FULL_SPEEDforbetterperformance.
pinMode(10,OUTPUT);//settheSSpinasanoutput(necessary!)
digitalWrite(10,HIGH);//butturnofftheW5100chip!

if(!card.init(SPI_HALF_SPEED,4))error("card.initfailed!");

//initializeaFATvolume
if(!volume.init(&card))error("vol.initfailed!");

PgmPrint("VolumeisFAT");
Serial.println(volume.fatType(),DEC);
Serial.println();

if(!root.openRoot(&volume))error("openRootfailed");

//listfileinrootwithdateandsize
PgmPrintln("Filesfoundinroot:");
root.ls(LS_DATE|LS_SIZE);

http://www.ladyada.net/learn/arduino/ethfiles.html 4/10
21/6/2016 ArduinoTutorialsEthernet+SD
Serial.println();

//Recursivelistofalldirectories
PgmPrintln("Filesfoundinalldirs:");
root.ls(LS_R);

Serial.println();
PgmPrintln("Done");

//Debuggingcomplete,westarttheserver!
Ethernet.begin(mac,ip);
server.begin();
}

We'llskipaheadtotheloop()wherewewaitforclients(checkingviaserver.available())andthenreadthe
clientrequestbeforeresponding.ThisisbasicallycopyandpastedfromtheWebserverexamplesketchthat
comeswiththeEthernetlibrary(well,thefirstandlastpartsoftheloopareatleast).

There'salittletrickwheretosimplifythecode,thewriterofthissketchdoesn'tactuallychecktoseewhatfile
thewebbrowserwants,italwaysspitsoutthesamething.Inthiscase,we'regoingtohaveitspitoutthefiles
byusingahelperfunctioncalledListFiles(client,0)whichweskippedoverbutwillshownext.The0inthe
secondargumenttothefunctionjusttellsthefunctionwhethertoprintoutthefilesizes

voidloop()
{
Clientclient=server.available();
if(client){
//anhttprequestendswithablankline
booleancurrent_line_is_blank=true;
while(client.connected()){
if(client.available()){
charc=client.read();
//ifwe'vegottentotheendoftheline(receivedanewline
//character)andthelineisblank,thehttprequesthasended,
//sowecansendareply
if(c=='\n'&&current_line_is_blank){
//sendastandardhttpresponseheader
client.println("HTTP/1.1200OK");
client.println("ContentType:text/html");
client.println();

//printallthefiles,useahelpertokeepitclean
//ListFiles(client,0);
client.println("<h2>Files:</h2>");
ListFiles(client,0);

break;
}
if(c=='\n'){
//we'restartinganewline
current_line_is_blank=true;
}elseif(c!='\r'){
//we'vegottenacharacteronthecurrentline
current_line_is_blank=false;
}
}
}
//givethewebbrowsertimetoreceivethedata
delay(1);
client.stop();
}
}

Nowwe'llgobackandexampinetheListFilesfunction.Thisisabittedious,butworthlookingat.We've
simplifieditbyremovingrecursivelisting,whichmeanswedon'tlistfilesinanysubdirectories.

Thedir_tpobjectisa"DirectoryEntry"holder.Itwillstoretheinformationforeachentryinthedirectory.

Wefirstresettherootdirectorybyrewind()'ingit.Thenwereadthedirectoryfilebyfile.Somefilesare
unusedorarethe"."and".."(updirectory)links,whichweignore.WealsoonlylistFILEsor
SUBDIRectories.

Thenweprintthenameoutbygoingthroughall11characters(rememberthefilenamesarein8.3format)and
ignorethespace.Wealsostickthe'.'betweenthefirst8andlast3characters.

Ifitsadirectorytypefile,weputaslashattheendtoindicateit.Ifitsnot,wecanprintoutthefilesizein
bytes.

http://www.ladyada.net/learn/arduino/ethfiles.html 5/10
21/6/2016 ArduinoTutorialsEthernet+SD
Finally,aftereachfilenamewestickina"<br>"whichwillgotothenextlineinawebbrowser

voidListFiles(Clientclient,uint8_tflags){
//ThiscodeisjustcopiedfromSdFile.cppintheSDFatlibrary
//andtweakedtoprinttotheclientoutputinhtml!
dir_tp;

root.rewind();
while(root.readDir(p)>0){
//doneifpastlastusedentry
if(p.name[0]==DIR_NAME_FREE)break;

//skipdeletedentryandentriesfor.and..
if(p.name[0]==DIR_NAME_DELETED||p.name[0]=='.')continue;

//onlylistsubdirectoriesandfiles
if(!DIR_IS_FILE_OR_SUBDIR(&p))continue;


//printfilenamewithpossibleblankfill
//root.printDirName(*p,flags&(LS_DATE|LS_SIZE)?14:0);


for(uint8_ti=0;i<11;i++){
if(p.name[i]=='')continue;
if(i==8){
client.print('.');
}
client.print(p.name[i]);
}
if(DIR_IS_SUBDIR(&p)){
client.print('/');
}

//printmodifydate/timeifrequested
if(flags&LS_DATE){
root.printFatDate(p.lastWriteDate);
client.print('');
root.printFatTime(p.lastWriteTime);
}
//printsizeifrequested
if(!DIR_IS_SUBDIR(&p)&&(flags&LS_SIZE)){
client.print('');
client.print(p.fileSize);
}
client.println("<br>");
}
}

OKafterallthatwork,letsuploadthatsketchtotheArduino!Makesureyouhavethecorrectipaddressfor
yournetwork,thenuseabrowseronthesamenetworktovisityourwebsite.HereiswhatIgottherearethose
twofilesfrommypreviousdataloggingexperiments!

Browsingfiles!

Obviously,weshouldmakeitsoyoucanclickythosefilenames,eh?Well!Thatsthenextsketch,youcan
downloadthelatestversionfromgithubhere [http://github.com/adafruit/SDWebBrowse](clickDownloadSource)
inthetoprighthandcorner!

Fixtheipaddresstomatchyournetwork,andSSpin(ifyou'reonaMega)

Notalothaschangedbetweenthepreviouscode,thesetupisthesame,thebigchangesareintheloop()code.
Thebonesarethesamewelookfornewclientconnections.Butthistimewereadtheclientrequestintoa

http://www.ladyada.net/learn/arduino/ethfiles.html 6/10
21/6/2016 ArduinoTutorialsEthernet+SD
characterbuffer(clientline)untilwegetanewlinecharacter(suchas\nor\r).Thisindicateswehavereadan
entirelineoftext.To'finish'thestring,weputanullcharacter(0)attheend.

Wethenusestrstrwhichwilllookforsubstrings.Ifwehavea"GET/HTTP"requestfortherootdirectory,
wedothesameasbefore,printingoutthelistoffiles.

Ifwehavenospaceafter"GET/"thatmeansitssomethinglike"GET/file"whichmeanswewillhaveto
extractthefilename.Wemakeapointertothestringandstartitrightafterthefirstslash.Thenwelookforthe
beginningofthe"HTTP/1.1"stringwhichfollowsthefilenamerequestandturnthefirstcharacterintoa
stringterminator.Nowwehavethenameofthefilewhichwecantrytoopen.

Ifwefailtoopenthefile,wewillreturna404.Otherwise,weprintoutallofthefilecontents.

//Howbigourlinebuffershouldbe.100isplenty!
#defineBUFSIZ100

voidloop()
{
charclientline[BUFSIZ];
intindex=0;

Clientclient=server.available();
if(client){
//anhttprequestendswithablankline
booleancurrent_line_is_blank=true;

//resettheinputbuffer
index=0;

while(client.connected()){
if(client.available()){
charc=client.read();

//Ifitisn'tanewline,addthecharactertothebuffer
if(c!='\n'&&c!='\r'){
clientline[index]=c;
index++;
//arewetoobigforthebuffer?starttossingoutdata
if(index>=BUFSIZ)
index=BUFSIZ1;

//continuetoreadmoredata!
continue;
}

//gota\nor\rnewline,whichmeansthestringisdone
clientline[index]=0;

//Printitoutfordebugging
Serial.println(clientline);

//Lookforsubstringsuchasarequesttogettherootfile
if(strstr(clientline,"GET/")!=0){
//sendastandardhttpresponseheader
client.println("HTTP/1.1200OK");
client.println("ContentType:text/html");
client.println();

//printallthefiles,useahelpertokeepitclean
client.println("<h2>Files:</h2>");
ListFiles(client,LS_SIZE);
}elseif(strstr(clientline,"GET/")!=0){
//thistimenospaceafterthe/,soasubfile!
char*filename;

filename=clientline+5;//lookafterthe"GET/"(5chars)
//alittletrick,lookforthe"HTTP/1.1"stringand
//turnthefirstcharacterofthesubstringintoa0toclearitout.
(strstr(clientline,"HTTP"))[0]=0;

//printthefilewewant
Serial.println(filename);

if(!file.open(&root,filename,O_READ)){
client.println("HTTP/1.1404NotFound");
client.println("ContentType:text/html");
client.println();

http://www.ladyada.net/learn/arduino/ethfiles.html 7/10
21/6/2016 ArduinoTutorialsEthernet+SD
client.println("<h2>FileNotFound!</h2>");
break;
}

Serial.println("Opened!");

client.println("HTTP/1.1200OK");
client.println("ContentType:text/plain");
client.println();

int16_tc;
while((c=file.read())>0){
//uncommenttheserialtodebug(slow!)
//Serial.print((char)c);
client.print((char)c);
}
file.close();
}else{
//everythingelseisa404
client.println("HTTP/1.1404NotFound");
client.println("ContentType:text/html");
client.println();
client.println("<h2>FileNotFound!</h2>");
}
break;
}
}
//givethewebbrowsertimetoreceivethedata
delay(1);
client.stop();
}
}

Letslookatthenewfilelistingcodeaswell,itsverysimilar,butnowwe'veaddedabitofHTMLsothateach
fileispartofa<ul>listandthenameisaURLlink.

voidListFiles(Clientclient,uint8_tflags){
//ThiscodeisjustcopiedfromSdFile.cppintheSDFatlibrary
//andtweakedtoprinttotheclientoutputinhtml!
dir_tp;

root.rewind();
client.println("<ul>");
while(root.readDir(p)>0){
//doneifpastlastusedentry
if(p.name[0]==DIR_NAME_FREE)break;

//skipdeletedentryandentriesfor.and..
if(p.name[0]==DIR_NAME_DELETED||p.name[0]=='.')continue;

//onlylistsubdirectoriesandfiles
if(!DIR_IS_FILE_OR_SUBDIR(&p))continue;

//printanyindentspaces
client.print("<li><ahref=\"");
for(uint8_ti=0;i<11;i++){
if(p.name[i]=='')continue;
if(i==8){
client.print('.');
}
client.print(p.name[i]);
}
client.print("\">");

//printfilenamewithpossibleblankfill
for(uint8_ti=0;i<11;i++){
if(p.name[i]=='')continue;
if(i==8){
client.print('.');
}
client.print(p.name[i]);
}

client.print("</a>");

if(DIR_IS_SUBDIR(&p)){
client.print('/');

http://www.ladyada.net/learn/arduino/ethfiles.html 8/10
21/6/2016 ArduinoTutorialsEthernet+SD
}

//printmodifydate/timeifrequested
if(flags&LS_DATE){
root.printFatDate(p.lastWriteDate);
client.print('');
root.printFatTime(p.lastWriteTime);
}
//printsizeifrequested
if(!DIR_IS_SUBDIR(&p)&&(flags&LS_SIZE)){
client.print('');
client.print(p.fileSize);
}
client.println("</li>");
}
client.println("</ul>");
}

OKuploadthesketchalready!

Nowyou'llseethatthefilenameshaveturnedintolinks(wealsoaddedthefilesizeinbytes)

Clickonafilenametoviewit

Ifyoutrytoviewafilethatisnotonthecard,you'llgeta404error(filenotfound)

Thispagewasautogeneratedfromhttp://www.ladyada.net/wiki//tutorials/learn/arduino/ethfiles.html
Pleaseeditthewikitocontributeanyupdatesorcorrections.

http://www.ladyada.net/learn/arduino/ethfiles.html 9/10
21/6/2016 ArduinoTutorialsEthernet+SD

http://www.ladyada.net/learn/arduino/ethfiles.html 10/10

You might also like