A simple WIP that logs data from a Grove sensor, and can send and receive information over USB and SMS.
Dependencies: DHT DS_1337 SDFileSystem USBDevice mbed
Diff: Handlers/SdHandler.cpp
- Revision:
- 0:2df78a4443cd
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Handlers/SdHandler.cpp Sun Apr 10 15:47:33 2016 +1000 @@ -0,0 +1,224 @@ +#include "SdHandler.h" + +#include "GroveDht22.h" // for interpreting the result struct +#include "circbuff.h" + +#define SD_BUFFER_LEN 256u // length of circular buffers + +// define pins for communicating with SD card +#define PIN_MOSI P1_22 +#define PIN_MISO P1_21 +#define PIN_SCK P1_20 +#define PIN_CS P1_23 + +#define DATA_FILE_NAME "/sd/data.csv" +#define SYSLOG_FILE_NAME "/sd/log.txt" + +// declare led that will be used to express state of SD card +extern DigitalOut myled2; + +SdHandler::SdHandler(MyTimers * _timer) : AbstractHandler(_timer) +{ + // init file system and files + m_sdfs = new SDFileSystem(PIN_MOSI, PIN_MISO, PIN_SCK, PIN_CS, "sd"); + m_data = NULL; + m_syslog = NULL; + + // initialise circular buffers + m_dataLogBuff = new CircBuff(SD_BUFFER_LEN); + m_sysLogBuff = new CircBuff(SD_BUFFER_LEN); + + mode = sd_Start; + m_lastRequest = sdreq_SdNone; +} + +SdHandler::~SdHandler() +{ + delete m_dataLogBuff; + delete m_sysLogBuff; +} + +void SdHandler::run() +{ + uint16_t tempInt = 0, tempInt2 = 0; + + unsigned char tempBuff[SD_BUFFER_LEN]; + + switch(mode) + { + case sd_Start: /* Set up the state machine */ + // check if card is inserted?? + //m_sdfs->unmount(); + // close both files if necessary + if (m_data != NULL) + fclose(m_data); + if (m_syslog != NULL) + fclose(m_syslog); + + m_data = NULL; + m_syslog = NULL; + + //mkdir("/sd", 0777); + //m_sdfs->mount(); + m_data = fopen(DATA_FILE_NAME, "a"); + m_syslog = fopen(SYSLOG_FILE_NAME, "a"); + + if ((m_data != NULL) && (m_syslog != NULL)) + { + // both opened successfully + fprintf(m_syslog, "Unit booted OK\n"); + fclose(m_syslog); + + // write the header in on startup + fprintf(m_data, "Timestamp, Temperature (degC), Humidity (pc), Dewpoint\n"); + fclose(m_data); + mode = sd_CheckSysLogBuffer; + } + break; + + case sd_CheckSysLogBuffer: /* See if any data should be written to the log file */ + if (m_sysLogBuff->dataAvailable()) + { + tempInt = m_sysLogBuff->read(tempBuff, SD_BUFFER_LEN); + tempInt2 = fprintf(m_syslog, (const char*)tempBuff); + if (tempInt == tempInt2) + { + // success + mode = sd_CheckDataLogBuffer; + } + else + { + // something went wrong + m_timer->SetTimer(MyTimers::tmr_SdWaitError, 2000); + mode = sd_WaitError; + } + } + else { + mode = sd_CheckDataLogBuffer; + } + break; + + case sd_CheckDataLogBuffer: /* See if any data should be written to the data file */ + if (m_dataLogBuff->dataAvailable()) + { + m_data = fopen(DATA_FILE_NAME, "a"); + + if (m_data != NULL) + { + // opened successfully + tempInt = m_dataLogBuff->read(tempBuff, SD_BUFFER_LEN); + tempInt2 = fprintf(m_data, (const char*)tempBuff); + fclose(m_data); + if (tempInt == tempInt2) + { + // success + myled2 = 0; + mode = sd_CheckSysLogBuffer; + } + else + { + // something went wrong + m_timer->SetTimer(MyTimers::tmr_SdWaitError, 2000); + mode = sd_WaitError; + } + } + else + { + // something went wrong + m_timer->SetTimer(MyTimers::tmr_SdWaitError, 2000); + mode = sd_WaitError; + } + } + else { + mode = sd_CheckSysLogBuffer; + } + break; + + case sd_WaitError: /* Many fails, much wow, wait for a while */ + if (!m_timer->GetTimer(MyTimers::tmr_SdWaitError)) + { + // timer has elapsed. go back to start. + mode = sd_Start; + } + break; + } +} + +void SdHandler::setRequest(int request, void *data) +{ + request_t req = (request_t)request; + m_lastRequest = req; + switch(req) { + case sdreq_SdNone: + + break; + case sdreq_LogData: + + myled2 = 1; + // have received the data struct. cast it + Dht22Result *result = (Dht22Result*)data; + + // write things to sd card buffer + char s[50]; // buffer + int temp; // length of buffer + csvStart(result->resultTime); + temp = sprintf(s, "%4.2f", result->lastCelcius); + csvData(s, temp); + temp = sprintf(s, "%4.2f", result->lastHumidity); + csvData(s, temp); + temp = sprintf(s, "%4.2f", result->lastDewpoint); + csvData(s, temp); + csvEnd(); + break; + case sdreq_LogSystem: + char *str = (char*)data; + logEvent(str); + break; + } +} + +void SdHandler::csvStart(time_t _time) +{ + unsigned char sTemp[17]; + + + // extract time_t to time info struct + + struct tm * timeinfo = localtime(&_time); + + // print the formatted timestamp at the start of terminalBuffer, with comma + sprintf((char*)&sTemp[0], "%04d%02d%02d %02d%02d%02d,", (timeinfo->tm_year + 1900), + (timeinfo->tm_mon + 1), + timeinfo->tm_mday, + timeinfo->tm_hour, + timeinfo->tm_min, + timeinfo->tm_sec); + + sTemp[16] = 0; + + m_dataLogBuff->add(sTemp); +} + +void SdHandler::csvData(const char * s, int len) +{ + unsigned char sTemp[50]; + int idx = 0; + // add a column to the buffer + sprintf((char*)&sTemp[idx], s); + idx += len; + sTemp[idx++] = ','; + sTemp[idx] = 0; + m_dataLogBuff->add(sTemp); +} + +void SdHandler::csvEnd() +{ + unsigned char sTemp[2]; + sTemp[0] = '\n'; + sTemp[1] = 0; + m_dataLogBuff->add(sTemp); +} + +void SdHandler::logEvent(const char * s) +{ +}