Version 3.0: Switching to newer LDC1614 which is placed on the same PCB.

Dependencies:   Bob DS1825 LDC1614 LDC1101 SDFileSystem mbed

Fork of Inductive_Sensor by Bob Giesberts

main.cpp

Committer:
bobgiesberts
Date:
2016-08-24
Revision:
16:b53721840a38
Parent:
15:5de8394fdb3c
Child:
17:a4700b1c3c37

File content as of revision 16:b53721840a38:

/**
* @file main.cpp
* @brief This file programs the processor for the inductive force sensor
* using the library LDC1614.h and LDC1614.cpp.
* - Green Led: processing communication with LDC1614
* - Red Led: error
*
* Log protocol:
* -  0:30 minutes at 13 Hz
* - 14:30 minutes rest
*
* @author Bob Giesberts
*
* @date 2016-08-23
*/
#include "mbed.h"
#include "LDC1614.h"        // inductive force sensor
#include "SDFileSystem.h"   // control the SD card
#include "Bob.h"            // processorboard
#include "DS1825.h"         // thermometer

#include <iostream>
#include <vector>
#include <string>
using namespace std;

// SETTINGS
bool DEBUG              = false;
float C                 = 120E-12;      // Capacitor in F
int sensors             = 2;            // number of attached sensors
uint16_t INTERVAL_FIRST = 3600;         // First sampling time in seconds.  60:00 minutes = 3600 sec
uint16_t INTERVAL_OFF   = 870;          // Waiting interval in seconds.     14:30 minutes = 870 sec (14*60+30)
uint16_t INTERVAL_ON    = 30;           // Sampling interval in seconds.     0:30 minutes =  30 sec

// Leds
PinName _LED_PROCESS = PTB1; // Green led (PTB0 for the first sensor) // old = new: PTB1
PinName _LED_ERROR   = PTB0; // Red led // new: PTB0;

// Thermometer
PinName _Tpin        = PTC1; // OneWire system (PTB1 for the first sensor) // old = PTB0, new: PTC1

// LDC1614
PinName _LDC_SDA     = PTC5; // I2C: SDA
PinName _LDC_SCL     = PTC4; // I2C: SCL
PinName _LDC_SD      = PTC6; // Shutdown

// SD File system
PinName _SD_ENABLE   = PTC3;
PinName _SD_PRESENT  = PTE0; // card detect // old = new: PTE0
PinName _SD_MOSI     = PTD6; // mosi        // old = new: PTD6
PinName _SD_MISO     = PTD7; // miso        // old = new: PTD7
PinName _SD_SCLK     = PTD5; // sclk        // old = new: PTD5
PinName _SD_CS       = PTD4; // cs          // old = new: PTD4

// Other components
PinName _OSCILLATOR  = PTC3;
PinName _BATTERY     = PTC2;   // voltage   // old = new: PTC2
PinName _BUTTON      = PTA4;


// load libraries
Bob bob( _LED_PROCESS, _LED_ERROR, _BUTTON, _SD_PRESENT, _BATTERY );
Serial pc(USBTX, USBRX);

// timer variables
uint32_t now = 0, next = 0, prev = 0;
uint8_t t_high = 0;
uint32_t t_lost = 0, lost_prev = 0;
uint8_t lost_high = 0;
uint32_t t_sleep = 0;
uint32_t t;

// file variables
FILE *fp;
string filename = "/sd/data00.txt";
const char *fn;

// temperature variables
uint8_t Tdata[9];
int16_t T_bin;
float T;

// temporal storage for data samples
const uint8_t package_size = 60;    // ±12-13 Hz, so 60 would take about 5 sec.
struct mydata {
    uint32_t    t[package_size];    // time (s)
    uint32_t    L[package_size];    // LHR_DATA
} collected;
uint8_t counter = 0;
uint8_t status;

// function to write all data to the SD card
void storeit( float T )
{   
    // TODO: writing to SD card more efficient!
    // t    32-bit  |   0.00    2000000.00     3-10x8-bit |    FFFFFFFF   8x8
    // L    24-bit  |   0       1677216        6- 7x8-bit |      FFFFFF   6x8
    // V     8-bit  |   3.10          4.20        4x8-bit |          FF   2x8
    // T    16-bit  | -20.0000       85.0000      7x8-bit |        FFFF   4x8


    // construct data
    /*
    bob.ledon();
    // fp = fopen( fn, "a" );      // open file (append)
    char buffer[16]; memset(buffer, 0, sizeof(buffer)); 
    char towrite[64]; memset(towrite, 0, sizeof(towrite)); 
    int n = 0, m = 0;
    for( int i = 0; i < counter; i++ )
    {
        for( int j = 0; j < 4; j++ )
        {
            // build up next 'word'
            switch(j)
            {
                case 0: n = sprintf(buffer, "%.2f;", (float) collected.t[i]/100.0); break;
                case 1: n = sprintf(buffer, "%d;", collected.L[i]);                 break;
                case 2: n = sprintf(buffer, "%.2f;", bob.battery());                break;
                case 3: n = sprintf(buffer, "%.4f\r\n", T);                         break;
            }
            
            // calculate if there is still room left for that word
            if( strlen(towrite) + n > 64 )
            {
                
                // pc.printf( "%s", towrite);
                fp = fopen( fn, "a" );      // open file (append)
                fprintf( fp, "%s", towrite);
                fclose( fp ); // close file
                               
                memset(towrite, 0, sizeof(towrite));            
            }
            
            // build up letter with the next word
            m = sprintf(towrite, "%s%s", towrite, buffer);
        }
    }
    if(m > 0)
    {
        fp = fopen( fn, "a" );      // open file (append)
        fprintf( fp, "%s", towrite);
        fclose( fp ); // close file
        //pc.printf( "%s", towrite);
    }   
    //fclose( fp ); // close file
    bob.ledoff();
    */   
    
    // write data to SD card
    bob.ledon();
    fp = fopen( fn, "a" );      // open file (append)
    for( int i = 0; i < counter; i++ )
       fprintf( fp, "%.2f;%d;%.2f;%.4f\r\n", (float) collected.t[i]/100.0, collected.L[i], bob.battery(), T ); // write to file
    fclose( fp );               // close file
    
    // write to screen
    //pc.printf( "%.2f;%d;%.2f;%.4f\r\n", (float) collected.t[counter-1]/100.0, collected.L[counter-1], bob.battery(), T ); // write to screen
    
    bob.ledoff();
                    
    // Reset data
    memset(collected.t, 0, counter);
    memset(collected.L, 0, counter);
    counter = 0;    
}

int main(void)
{
    if( DEBUG )
    {
        Serial pc( USBTX, USBRX );

        LDC1614 ldc( _LDC_SDA, _LDC_SCL, _LDC_SD, _OSCILLATOR, 16E6, sensors, C );
        
        uint8_t status;
        
        while( 1 ) {
            // check the sensor
            status = ldc.get_status();

            // if there is an error turn on the red led
            if( ldc.is_error( status ) )
            {
                // error
                // bob.error();
            }else{
                if( ldc.is_ready( status ) )
                {
                    //bob.no_error();
                    pc.printf( "sensor 1: %d | sensor 2: %d\r\n", ldc.get_Data( 0 ), ldc.get_Data( 1 ) );
                }
            }
        }   
    }    
    
    

    // TODO:
    // - implement this data conversion in writing to SD!!
    // - use T as uint16_t, not float!
    // - use V as uint16_t, not float!
    // - write blocks of 512 bit (4x 32 + 32 + 16 + 16)
    //
    // float temp_a = 127.9375;
    // pc.printf( "A: %.4f (%08x); \r\n", temp_a, * (uint32_t *) &temp_a);

    // Load SD File system
    // - the Raspberry Pie SD cards give a warning here that might just be ignored:
    //      "Not in idle state after sending CMD8 (not an SD card?)
    //       Didn't get a response from the disk
    //       Set 512-byte block timed out"
    // TODO: buy 'better' SD cards from IAPC / the Stores (Kingston ...)
    bob.wakeup();
    SDFileSystem *sd = new SDFileSystem( _SD_MOSI, _SD_MISO, _SD_SCLK, _SD_CS, "sd" );

    // Create a new data file (data00.txt)
    mkdir("/sd", 0777);
    for(uint8_t i = 0; i < 100; i++)
    {
        filename[8] = i/10 + '0';
        filename[9] = i%10 + '0';
        fp = fopen( filename.c_str() , "r" );
        if( fp == NULL ) // read failed so file does not exist
        {
            fp = fopen( filename.c_str(), "w" ); // create it
            if( fp != NULL )
            {
                fn = filename.c_str();
                fclose( fp );
                break;
            } else {
                bob.ledon();  // error: unable to create new file
            }
        } else { // file already exists
            fclose( fp );
        }
    }
    if( fp == NULL )
    {
        bob.ledon();  // error: file 00 - 99 already exists
        // pc.printf( "/sd/data00.txt t/m /sd/data99.txt already exist!\n" );
    }

    // Unload SD File system
    delete sd;
    sd = NULL;
   
    while(1)
    {
        // Wakeup: SD + LDC1101 on
        bob.wakeup();

        // what time is it now?
        prev = now;                                                     // 0 -> 429 496     --> (4 294,96 s)        (71 min)
        now = (uint32_t) clock();                                       // 0 -> 429 496     --> (4 294,96 s)        (71 min)
        if( now < prev )
            t_high++;                                                   // 0 -> 255         --> (255*4 294,96 s)    (12 days)
        t = now + 429496.7296*t_high + t_lost + 429496.7296*lost_high;  // 0 -> 219 901 952 --> (2 199 019,52 s)    (25 days)
        
        // load libraries to take control over the communication
        LDC1614 *ldc = new LDC1614(_LDC_SDA, _LDC_SCL, _LDC_SD, _OSCILLATOR, 16E6, sensors, C);        
        DS1825 *thermometer = new DS1825( _Tpin );                                        // load thermometer (DS1825) library
        SDFileSystem *sd = new SDFileSystem(_SD_MOSI, _SD_MISO, _SD_SCLK, _SD_CS, "sd");  // load SD system
            mkdir("/sd", 0777); // select folder

        // How long should we takes samples?
        if( next == 0 )
        {
            next = t + INTERVAL_FIRST*100;
        } else {
            next = t + INTERVAL_ON*100;                                 // 0 -> 219 904 952 --> (2 199 049,52 s)    (25 days)
        }

        // Take samples for INTERVAL_ON seconds
        while( t < next )
        {
            // what time is it now?
            prev = now;
            now = (uint32_t) clock();
            if( now < prev ) 
                t_high++;
            t = now + 429496.7296*t_high + t_lost + 429496.7296*lost_high;

            status = ldc->get_status();

            // Is there any error?
            if( ldc->is_error(status) )
            {
                // red led on
                // bob.error();
            }else{  
                // red led off
                // bob.no_error();
            
                if( ldc->is_ready(status) ) // data from all sensors is ready
                {
                    // Store data in temporal memory
                    collected.t[counter] = t;
                    collected.L[counter] = ldc->get_Data( 0 );
                    counter++;
                    
                    // Write a full package of data points to the SD card
                    if( counter >= package_size-1  )
                        storeit( thermometer->getTemperature() );
                }
            }
            

        }
        
        // Write remaining data to the SD card
        if( counter > 0 )
            storeit( thermometer->getTemperature() );

        // prepare for sleep, power down the SD and the LDC1101
        delete sd;          sd  = NULL;             // unload library to be able to power down completely
        delete ldc;         ldc = NULL;             // unload library to be able to power down completely
        delete thermometer; thermometer = NULL;     // unload library to be able to power down completely
        bob.beforesleep();
        
        // if the battery is almost empty (Vbatt < 3.10 V), the thermometer stops 
        // working well and L can not be corrected. So just shut down...
        if( bob.battery() < 3.10f )
        {
            bob.ledon();  // error: battery empty
            // pc.printf( "Battery empty (%.1f V), shutting down.\n", bob.battery() );
            exit(0);
        }

        // what time is it now?
        prev = now;
        now = (uint32_t) clock();
        if( now < prev ) 
            t_high++;
        t = now + 429496.7296*t_high + t_lost + 429496.7296*lost_high;

        // Calculate sleeping time (correction to INTERVAL_OFF)
        // t has passed the limit of next. Those few ms are substracted from INTERVAL_OFF.
        t_sleep = INTERVAL_OFF*100 - (t - next);

        // Calculate time that will be lost during sleep
        lost_prev = t_lost;
        t_lost += t_sleep;
        if( t_lost < lost_prev ) 
            lost_high++;
        
        // Sleep now (ms), enter low power mode
        bob.sleep( t_sleep * 10 );

    }




}