Hi all,
I'm having some trouble using the newer Ethernet/Micro SD card shield. My program creates a log file and writes to it once/second. Meanwhile it monitors for and responds to HTTP requests. The HTTP page contains a list of files on the SD card, and when you click on one of the file names, it should open the file.
The web server part works correctly when the logging is disabled, but once I turn on the logging, it fails when I try to download one of the files. Do I need to disable the logging while reading the file?
A very abbreviated portion of the code is below... I basically cut out everything not related to the web server or SD card.
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <Time.h>
#include <Udp.h>
#include <Flash.h>
//define USE_LOG
// ETHERNET SETUP
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 101 };
Server server(80);
// SD CARD SETUP
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;
// setup variables to track interval for logging/temp adjustment
long previousMillis = 0; // will store last time logging/temp adjustment was called
long SECOND = 1000;
long MINUTE = SECOND*60;
long HOUR = MINUTE*60;
long interval = SECOND; // interval at which to log data/adjust temp
int tempProgram[] = {110, 110, 120, 130, 140, 150, 160};
// heating element
int elementStatus = HIGH;
unsigned int elementPin = A5;
//... messages
//store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
PgmPrint("error: ");
SerialPrintln_P(str);
if (card.errorCode()) {
PgmPrint("SD error: ");
Serial.print(card.errorCode(), HEX);
Serial.print(',');
Serial.println(card.errorData(), HEX);
}
}
#define BUFSIZ 120
void setup() {
Serial.begin(9600);
char buffer[BUFSIZ];
Serial.print(welcome_to);
Serial.println(botul9m);
// initialize the SD card at SPI_HALF_SPEED to avoid bus errors with breadboards.
pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
digitalWrite(10, HIGH); // but turn off the W5100 chip!
pinMode(elementPin, OUTPUT);
// start ethernet
Ethernet.begin(mac, ip);
Udp.begin(localPort);
server.begin();
// initialize time
setupTime();
initializeLog();
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you log/adjust temp
previousMillis = currentMillis;
// read temp data
pitTemp = thermister_temp(analogRead(4));
meatTemp = thermister_temp(analogRead(3));
#ifdef USE_LOG
logData();
#endif // USE_LOG
adjustTargetTemp();
adjustHeat();
}
listenForClients();
}
void listenForClients() {
Client client = server.available();
if (client) {
char buffer[BUFSIZ];
Serial.println(web_req);
int index = 0;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c != '\n' && c != '\r') {
buffer[index] = c;
index++;
// are we too big for the buffer? start tossing out data
if (index >= BUFSIZ)
index = BUFSIZ -1;
continue; // continue to read more data!
}
buffer[index] = 0;
if (strstr(buffer, "?") != 0) { // update pit/meat targets if needed
String s = String(buffer);
String p = s.substring(s.indexOf("pit=")+4, s.indexOf("meat=")-1);
char p_char[p.length()+1];
p.toCharArray(p_char, sizeof(p_char));
pitTarget = atoi(p_char);
String m = s.substring(s.indexOf("meat=")+5, s.indexOf("HTTP")-1);
char m_char[m.length()+1];
m.toCharArray(m_char, sizeof(m_char));
meatTarget = atoi(m_char);
}
if (strstr(buffer, "GET /del=") !=0 ) { // handle delete
char filename[13];
for(int i=0; i<=11; i++){
filename[i] = buffer[i+9];
}
filename[12] = 0;
if (!file.open(&root, filename, O_WRITE)) {
Serial.print("Can't open ");
Serial.println(filename);
//error("file.open failed");
}
if (!file.remove()) {
Serial.print("file.remove failed");
}
}else if (strstr(buffer, ".CSV") != 0) { // serve up file
char filename[13];
for(int i=0; i<=11; i++){
filename[i] = buffer[i+5];
}
filename[12] = 0;
Serial.println(filename);
if (! file.open(&root, filename, O_READ)) { // can't read file
client.println(http_404);
client.println(content_html);
client.println();
client.println(file_not_found);
} else { // can read file
client.println(http_ok);
client.println(content_csv);
attachment.copy(buffer);
char buf[55];
sprintf(buf, buffer, filename);
client.println(buf);
client.println();
int16_t c;
while ((c = file.read()) > 0) {
//Serial.print((char)c); // uncomment the serial to debug (slow!)
client.print((char)c);
}
file.close();
}
break;
}
client.println(http_ok);
client.println(content_html);
client.println("");
client.println(html_open);
client.println(h2_files);
ListFiles(client, 0);
client.println(html_close);
break;
}
}
// give the web browser time to receive the data
delay(1);
client.stop();
}
}
int thermister_temp(int aval) {
//
}
void initializeLog() {
if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
// initialize a FAT volume
if (!volume.init(&card)) error("volume.init failed");
// open root directory
if (!root.openRoot(&volume)) error("openRoot failed");
#ifdef USE_LOG
// create a new file
char name[] = "LOGGER00.CSV";
for (uint8_t i = 0; i < 100; i++) {
name[6] = i/10 + '0';
name[7] = i%10 + '0';
if (file.open(&root, name, O_CREAT | O_EXCL | O_WRITE)) break;
}
file.open(&root, name, O_CREAT | O_EXCL | O_WRITE);
if (!file.isOpen()) error ("file.create");
Serial.print(F("Logging to: "));
Serial.println(name);
// write header
file.writeError = 0;
file.print(F("time,pitTemp,pitTarget,meatTemp,meatTarget,elementStatus"));
file.println();
if (file.writeError || !file.sync()) {
error("write header failed");
}
#endif // USE_LOG
}
// log data to the SD card
void logData() {
char line[60];
file.writeError = 0;
sprintf(line, "%2.2d:%2.2d:%2.2d,%3d,%3d,%3d,%3d,%3d", hour(), minute(), second(),pitTemp, pitTarget, meatTemp, meatTarget, elementStatus);
file.print(line);
file.println();
if (!file.sync()) error("sync failed");
}
void ListFiles(Client client, uint8_t flags) {
// This code is just copied from SdFile.cpp in the SDFat library
// and tweaked to print to the client output in html!
dir_t p;
char buffer[15];
root.rewind();
client.println(open_ul);
while (root.readDir(p) > 0) {
// done if past last used entry
if (p.name[0] == DIR_NAME_FREE) break;
// skip deleted entry and entries for . and ..
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') continue;
// only list subdirectories and files
if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
// print any indent spaces
client.println(open_li);
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
client.print('.');
}
client.print(p.name[i]);
}
client.println(end_a);
// print file name with possible blank fill
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
client.print('.');
}
client.print(p.name[i]);
}
client.println(close_a);
if (DIR_IS_SUBDIR(&p)) {
client.print('/');
}
// print modify date/time if requested
if (flags & LS_DATE) {
root.printFatDate(p.lastWriteDate);
client.print(' ');
root.printFatTime(p.lastWriteTime);
}
// print size if requested
if (!DIR_IS_SUBDIR(&p) && (flags & LS_SIZE)) {
client.print(' ');
client.print(p.fileSize);
}
// print file name with possible blank fill
client.print(open_del);
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) {
client.print('.');
}
client.print(p.name[i]);
}
client.print(close_del);
client.println(close_li);
}
client.println(close_ul);
}