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
main.cpp
- Committer:
- bobgiesberts
- Date:
- 2016-09-21
- Revision:
- 21:b96a3de88002
- Parent:
- 20:1c5ea04a3b2a
- Child:
- 22:ac26f52ebaf8
File content as of revision 21:b96a3de88002:
/** * @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 = false; // Serial pc( USBTX, USBRX ); // SETTINGS uint8_t C = 120; // Capacitor (in pF) uint8_t f_CLKIN = 40; // Oscillator frequency (in MHz) const uint8_t sensors = 2; // number of attached sensors uint16_t INTERVAL_FIRST = 900; // 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 = PTB0; // Green led PinName _LED_ERROR = PTB1; // Red led // 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_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 _ENABLE = PTC3; // enables SD card and Crystal PinName _BATTERY = PTC2; // voltage // old = new: PTC2 PinName _BUTTON = PTA4; // load libraries Bob bob( _LED_PROCESS, _LED_ERROR, _BUTTON, _ENABLE, _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 float T; // 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]; // LHR_DATA } collected; uint8_t counter = 0; uint8_t SKIPPING = 3; uint8_t skip = 0; // 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 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, "%.2f;%.4f\r\n", bob.battery(), T ); // write to file } fclose( fp ); // close file // write to screen // pc.printf( "%.2f;", (float) collected.t[counter-1]/100.0); // write to file // for(int sensor = 0; sensor < sensors; sensor++) // pc.printf( "%d;", collected.L[sensor][counter-1]); // write to file // pc.printf( "%.2f;%.4f\r\n", bob.battery(), T ); // write to file bob.no_processing(); // Reset data memset(collected.t, 0, counter); memset(collected.L, 0, counter); counter = 0; } int main(void) { if( DEBUG ) { Serial pc( USBTX, USBRX ); bob.wakeup_periphery( ); LDC1614 ldc( _LDC_SDA, _LDC_SCL, _LDC_SD, f_CLKIN, sensors, C ); DS1825 thermometer( _Tpin ); while( 1 ) { prev = now; now = (uint32_t) clock(); bob.processing(); for(int sensor = 0; sensor < sensors; 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 ) ) { pc.printf( "[%.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{ bob.error(); } } bob.no_processing(); } } // 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 ...) // 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 ); } } if( fp == NULL ) { // THIS ERROR IS NOT CATCHED PROPERLY!!! bob.error( 4 ); // error: file 00 - 99 already exists } // Unload SD File system delete sd; sd = NULL; // LDC1614 *ldc = new LDC1614(_LDC_SDA, _LDC_SCL, _LDC_SD, f_CLKIN, sensors, C); // load LDC1614 libray 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 if ( sensor == 0 ) { collected.t[counter] = t; counter++; } }else{ skip++; } }else{ bob.error(); } } // Write a full package of data points to the SD card if( counter >= package_size-1 ) { storeit( thermometer->getTemperature() ); } bob.no_error(); } skip = 0; // Write remaining data to the SD card if( counter > 0 ) { storeit( thermometer->getTemperature() ); } // 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 // 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 ); } }