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-10-05
Revision:
23:7499936dc144
Parent:
22:ac26f52ebaf8

File content as of revision 23:7499936dc144:

/**
* @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;



bool DEBUG              = true;



// SETTINGS
uint8_t C               = 120;          // Capacitor (in pF)
uint8_t f_CLKIN         = 40;           // Oscillator frequency (in MHz)
const uint8_t sensors   = 1;            // 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

uint8_t SKIPPING        = 2;            // The first how many measurements should be skipped?

// Leds
PinName _LED_PROCESS = PTB1; // Green led 
PinName _LED_ERROR   = PTB0; // Red led

// Thermometer
PinName _Tpin        = PTC1; // OneWire system (PTB1 for the first sensor)

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

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

// Other components
PinName _ENABLE      = PTC3; // enables SD card and Crystal
PinName _BATTERY     = PTC2; // voltage
PinName _BUTTON      = PTA4;


// load libraries
Bob bob( _LED_PROCESS, _LED_ERROR, _BUTTON, _ENABLE, _SD_PRESENT, _BATTERY );


// 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;

// LDC variables
uint32_t L;

// 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[sensors][package_size];   // DATA
    float T;                                // Temperature
} collected;
uint8_t counter = 0;
uint8_t skip = 0;



// function to write all data to the SD card
void storeit( void )
{       
    bob.processing();
    
        // write data to SD card
        fp = fopen( fn, "a" );      // open file (append)
        for( int i = 0; i < counter; i++ )
        {
            fprintf( fp, "%.2f;", (float) collected.t[i]/100.0); // write to file
            for(int sensor = 0; sensor < sensors; sensor++)
                fprintf( fp, "%d;", collected.L[sensor][i]); // write to file
            fprintf( fp, "%.4f;%.4f\r\n", bob.battery(), collected.T ); // write to file
        }
        fclose( fp );               // close file
    
    bob.no_processing();
    
    // write data to screen
    // debug( "Writing to SD: " );
    // debug( "%.2f;", (float) collected.t[0]/100.0); // write to file
    // for(int sensor = 0; sensor < sensors; sensor++)
    //     debug( "%d;", collected.L[sensor][0]); // write to file
    // debug( "%.4f;%.4f\r\n", bob.battery(), collected.T ); // write to file
                    
    // Reset data
    memset(collected.t, 0, counter);
    memset(collected.L, 0, counter);
    collected.T = 0.0;
    counter = 0;    
}



int main(void)
{
    if( DEBUG )
    {           
        while ( 1 ) {
        
            // 5 sec awake
            wait( 5 );
        
            // 5 sec asleep
            bob.sleep( 5 );
        }
        
        /*
        bob.wakeup_periphery( );
        LDC1614 ldc( _LDC_SDA, _LDC_SCL, _LDC_SD, f_CLKIN, sensors, C );  
        DS1825 thermometer( _Tpin );
        
        wait(0.5);
        
        while( 1 ) {          
        
            prev = now;
            now = (uint32_t) clock();
            
            bob.processing();
            for(int sensor = 0; sensor < sensors; sensor++)
            {
                // ldc.autoDriveCurrent( sensor );
                
                // wait for a new conversion to be ready          
                while( !ldc.is_ready( sensor ) ) {  }

                // write to screen
                L = ldc.get_Data( sensor );
                if ( !ldc.get_error( sensor ) )
                {
                    debug( "[%.2f Hz] 0x%08X, %.6f MHz, Vbatt = %.2f V, T = %.2f C\r\n", 1/((now-prev)/100.0), L, ldc.get_fsensor( L )/1000000, bob.battery(), thermometer.getTemperature() );
                    bob.no_error();
                }else{
                    debug( "%d\r\n", L );
                    bob.error();
                }
            }
            debug( "\r\n", L );
            
            bob.no_processing();
            
            wait(0.5);
        }
        */   
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    // This turns enable on, i.e. it powers the SD card system, the crystal and the LDC
    bob.wakeup_periphery();
    
    // check if both leds work
    bob.flash( 1 );
    
    // load SD File System
    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 );
                bob.processing( 1 );
                break;
            } else {
                bob.error( 3 );  // error: unable to create new file
            }
        } else { // file already exists
            fclose( fp );
        }
    }   
    // THIS ERROR IS NOT CATCHED PROPERLY!!! 
    if( fp == NULL )
    {
        bob.error( 4 );  // error: file 00 - 99 already exists
    }








    // Unload SD File system
    delete sd;
    sd = NULL;
   
    while(1)
    {
        // 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)

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


        // Wakeup the periphery (3v3 on. Powers SD, crystal and LDC1614)
        bob.wakeup_periphery();
        
        // load libraries to take control over the communication
        LDC1614 *ldc        = new LDC1614(_LDC_SDA, _LDC_SCL, _LDC_SD, f_CLKIN, sensors, C); // load LDC1614 libray 
        DS1825 *thermometer = new DS1825( _Tpin );                                           // load thermometer (DS1825) library
        SDFileSystem *sd    = new SDFileSystem(_SD_MOSI, _SD_MISO, _SD_SCLK, _SD_CS, "sd");  // load SD File System library
            mkdir("/sd", 0777); // select folder

        // 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;

            // assess all sensors
            for ( int sensor = 0; sensor < sensors; sensor++ )
            {
                // wait for a new conversion to be ready          
                while( !ldc->is_ready( sensor ) ) {  }
    
                // collect data
                L = ldc->get_Data( sensor );
                
                // catch errors (sensor broken / not connected)
                if ( !ldc->get_error( sensor ) )
                {
                    // skip the first few measurements (they are too low)
                    if ( skip >= SKIPPING )
                    {
                        // store data
                        collected.L[sensor][counter] = L;
                        
                        // only store the time once
                        // do this after the last sensor
                        if ( sensor == sensors-1 )
                        {
                            collected.t[counter] = t;
                            counter++;
                        }                        
                    }else{
                        // count the skipper in pairs, so after the last one
                        if ( sensor == sensors-1 )
                            skip++;
                    }
                }else{
                    bob.error();
                }
            }
            
            // Write a full package of data points to the SD card
            if( counter >= package_size-1  )
            {
                // No need to measure temperature with 10+ Hz
                // only calculate the temperature once every time data is stored
                collected.T = thermometer->getTemperature();
                storeit(  );
            }
            
            bob.no_error();
        }
        
        // Reset the skipper
        skip = 0;
        
        // Write remaining data to the SD card
        if( counter > 0 )
        {
            collected.T = thermometer->getTemperature();   
            storeit(  );
        }

        // prepare for sleep: delete and power down the periphery (SD, crystal and LDC1614)
        ldc->shutdown();                // _LDC_SD --> 1
        bob.shutdown_periphery();       // 3V3     --> 0

        // LDC I2C
        delete ldc;         ldc = NULL;             // unload library to be able to power down completely
        bob.shutdown_pin( _LDC_SDA );
        bob.shutdown_pin( _LDC_SCL );
        bob.shutdown_pin( _LDC_SD  );
        
        // SD SPI
        delete sd;          sd  = NULL;             // unload library to be able to power down completely
        bob.shutdown_pin( _SD_PRESENT ); 
        bob.shutdown_pin( _SD_CS );
        bob.shutdown_pin( _SD_MOSI );
        bob.shutdown_pin( _SD_SCLK );
        bob.shutdown_pin( _SD_MISO );
        
        // PC ports (SWD / UARTO)
        bob.shutdown_pin( PTA0 );   // SWD_CLK
        bob.shutdown_pin( PTA1 );   // UARTO_RX
        bob.shutdown_pin( PTA2 );   // UARTO_TX
        bob.shutdown_pin( PTA3 );   // SWD_DIO
        
        // bob.shutdown_pin( PTA20, 1 ); // RESET (does not work properly)
        
        // Thermometer
        delete thermometer; thermometer = NULL;     // unload library to be able to power down completely
        bob.shutdown_pin( _Tpin );
        
        // Button
        bob.shutdown_pin( _BUTTON );

        
        // 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.error( 5 );  // error: battery empty
            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 );

    }
}