Logger to USB stick running on KL25Z
Dependencies: F401RE-USBHost FastAnalogIn RTC mbed tsi_sensor2 mbed-rtos2
Fork of ReadSendData by
main.cpp
00001 /* low power data logger. [FRDM-KL25Z] 00002 00003 Periodically read data from ADC and when present write it in JSON format to USB Stick 00004 00005 Copyright http://www.apache.org/licenses/LICENSE-2.0 00006 and all subsystems per their own licenses which are believed to be GPL 2.0 00007 00008 [c]Record an analoge value to an internal buffer 00009 [p]and when a USB stick is plugged in store the values on the USB stick in JSON format 00010 (currently requires USB stick at reset) 00011 [c]Debug output the events as they happen. 00012 [c]The ticker delay sets the sampling rate. 00013 [F]Date is set when user sets it, 00014 [c]or elapsed time used in the beginning 00015 00016 [F]If OpenSDA USB power supplied, then flash LEDs to indicate activity as follows 00017 [c]1) the Blue led when taking a sample 00018 [c]2) the green led when delivering samples to the USB stick 00019 [F]3)no led shall be on at same time for clear colours 00020 00021 [F] when not doing anything else sleep to conserve power. 00022 00023 To modify this for your application, assuming a ratiometric input to the Vref=3.3V 00024 1) Determine physical pins ADC performed on and type of conversion, 00025 1) Determine the "multiplier" from the incoming 16bit ADC wrt to 3.3V to your units. 00026 2) Write the output code changing the JSON headers to define your headers, dataConversion and units 00027 00028 Thanks to other authors for setting up KL25z for 00029 * FastAnalogIn Library mbed.org/users/Sissors/code/FastAnalogIn/ 00030 * USB Host mbed.org/users/va009039/code/F401RE-USBHost/ 00031 00032 [] 1st three character nomeclature. 00033 [x] indicates implemented state of feature 00034 [c] - complete and unit tested 00035 [p] - partial in progress or not unit tested 00036 [f] - future idea 00037 00038 Testing: Basic tests performed, see attached file logger_tests.docx 00039 00040 Modifications to Hardware 00041 1) FRDM-KL25z add J21 and R8 per the instruction manual for USB host 00042 00043 Issues: 00044 1) FRDM-KL25z hardware not designed to switch the USB power so saving power on a connected USB device. 00045 Solution: Add switched 5V power. 00046 2) FRDM-KL25z Hardware not designed for low power accurate wall time clock - wastes power keeping the 8Mhz going. 00047 Solution: add an external low power 32KHz oscilator into hardware pin RTC_IN (An osc is the next step up from a raw Xtal) 00048 00049 00050 */ 00051 00052 #include "mbed.h" 00053 //#include "rtos.h" 00054 #include "rtc_api.h" 00055 #include "FastAnalogIn.h" 00056 #include "USBHostMSD.h" 00057 #include "board_cust.h" 00058 00059 00060 #if defined(TARGET_K20D50M) 00061 #define TsiActive 0 00062 00063 #elif defined (TARGET_KL25Z) || defined (TARGET_KL46Z) 00064 #define TsiActive 1 00065 #include "tsi_sensor.h" 00066 //Cap Sensor B0=CH0, B1=CH6 00067 #define ELEC0 0 00068 #define ELEC1 6 00069 //FRDM_KL25x slider electrodes - TSI0_CH9=PTB16, CH10=B17 00070 // #define ELEC0 9 00071 // #define ELEC1 10 00072 TSIAnalogSlider tsi(ELEC0, ELEC1, 40); 00073 //TSIElectrode tsiElec0(ELEC0); 00074 //TSIElectrode tsiElec1(ELEC1); 00075 //#define TsiRead() tsi.readDistance() - has problesm 00076 #define TsiRead() tsi.readPercentage() 00077 00078 #elif defined (TARGET_KL05Z) 00079 #define TsiActive 0 00080 #include "TSISensor.h" 00081 00082 #define ELEC0 9 00083 #define ELEC1 8 00084 TSIAnalogSlider tsi(ELEC0, ELEC1, 40); 00085 //#define TsiRead(void) tsi.Distance() 00086 #else 00087 #define TsiActive 0 00088 #error TARGET NOT DEFINED 00089 #endif 00090 00091 00092 //size of Customer ADC sample buffer 00093 #define BuffSize 16 //16 to test, upto kl25z spare ram of about xxxx?, !2000, linker warns if too large, but also fails 00094 #define SAMPLE_WIN 8 // Should be less than BuffSize 00095 #if BuffSize < SAMPLE_WIN 00096 #error Buffsize < SAMPLE_WIN 00097 #endif 00098 //set the delay used by the ticker 00099 const int sysTockInit_sec = 1; //Test 1, Real life 15minutes or 900sec 00100 00101 using namespace mbed; 00102 00103 00104 //Device Init - per FRDM-KL25Z 00105 DigitalOut ledRed(LED1); 00106 //DigitalOut ledGrn(LED2); 00107 PwmOut ledPwmGrn(LED2); 00108 DigitalOut ledBlue(LED3); 00109 FastAnalogIn ainPinAA(PTC2); ///AnalogAin pin 00110 00111 Serial pc(USBTX, USBRX); 00112 00113 //Samples stored here - needs to be compact as can use a lot of internal ram 00114 unsigned short sample_u16[BuffSize]; //critical resource for number of samples 00115 unsigned short publish_u16[BuffSize]; //value published 00116 unsigned short sampleInst_raw, sampleAvg_raw; 00117 float tsiSlider_dist; 00118 uint32_t elec0p,electr[BuffSize]; 00119 //uint32_t elec1p; 00120 unsigned int time_[BuffSize]; 00121 00122 00123 00124 bool UsbPresent=0; 00125 bool warmBoot = rtc_isenabled(); 00126 long lp2i =0; 00127 bool sysEventA=0; //Local event 00128 unsigned int tmrE_evt; //Elapsed 00129 Ticker tock; //periodic tick 00130 00131 00132 #if defined(TARGET_K20D50M) 00133 const char meProc[] = "K20D50M"; 00134 #elif defined(TARGET_KL25Z) 00135 const char meProc[]= "KL25Z"; 00136 #else //#if defined(TARGET_KL46Z)||defined(TARGET_K64F) 00137 #error Undef processor 00138 #endif // 00139 00140 00141 00142 00143 00144 //-------------------------------------------------------------- 00145 void tockEvent() 00146 { 00147 tmrE_evt++; 00148 sysEventA=1; 00149 } 00150 00151 //-------------------------------------------------------------- 00152 /* Process output Header to USB, 00153 return !0 if valid USB present 00154 */ 00155 bool outputHeaderUsb(FILE* fpUsb) { 00156 // JSON {"headings":{"time":{"elapsed":"seconds"}, "adcN":"normalized_to_1.0", "adcV":"Volts"}} 00157 00158 if (!UsbPresent) 00159 { 00160 if (1/*ToDo msd.connect()*/) //Attempt to find a device 00161 {//USB Event: newly connected so attempt write header 00162 if (NULL !=(fpUsb = fopen("/usbAa/test1.txt", "a"))) 00163 { 00164 pc.printf("USB File test1.txt opened.\n\r"); 00165 fprintf(fpUsb,"{\"headings\":{\"time\":{\"elapsed\":\"seconds\"}, \"adcN\":\"normalized_to_1.0\", \"adcV\":\"Volts\"}" 00166 #if TsiActive 00167 "\"tsi\":\"[0-40]\"" 00168 #endif 00169 "}}\n"); 00170 UsbPresent=1; 00171 fclose(fpUsb); fpUsb=NULL; 00172 } else { 00173 //Can't find a file for some reason. Could be USB full or failed software 00174 pc.printf(" Error: USB File not opened.\n\r"); 00175 UsbPresent=0; 00176 } 00177 } //else //Can't find USB device 00178 } else { 00179 // UsbPresent and assume headers written 00180 if (1/*ToDo !msd.connected()*/) 00181 { 00182 pc.printf(" USB Flash drive removed.\n\r"); 00183 UsbPresent=0; 00184 } 00185 } 00186 00187 return UsbPresent; 00188 } 00189 //-------------------------------------------------------------- 00190 void outputHeaders(void) { 00191 //ToDo - outputHeaderUsb(*fp); 00192 pc.printf(" Time(S) depthR(norm) Volts Idx %d\n\r",(unsigned int) rtc_read()); 00193 }//outputHeaders 00194 00195 00196 00197 //-------------------------------------------------------------- 00198 /* Manage the write to USB stick 00199 [FUT] detect USB stick and if not present write it when inserted 00200 00201 JSON output json.org 00202 {key:value, key:value, key:value} 00203 {time:[elapsed:<secs 0-2**32>, epoch2014:<secs 0-2**32>,wall:[date:<>,clock:<>],], 00204 adcNorm:<float number 0.0-1.0>, 00205 adcV:<Volts 0-VRef> 00206 */ 00207 bool manageUsbWrite(FILE* fpUsb) { 00208 #define ADC_NORMALIZE (1.0f/65535.0f) 00209 #define ADC_NORM_VREF 3.3 00210 float data_n=( ((float)sample_u16[lp2i]) * ADC_NORMALIZE); 00211 bool writeUsb=0; 00212 //Future redesign to use USBHALHost::wait_attach() 00213 if (outputHeaderUsb(fpUsb)) 00214 { 00215 if (NULL !=(fpUsb = fopen("/usbAa/test1.txt", "a"))) 00216 { 00217 #if TsiActive 00218 //del pc.printf("%10d %5.4f (%6.4fV) %i\n\r",time_[lp2i],data_n,(ADC_NORM_VREF*data_n),lp2i); 00219 fprintf(fpUsb, "{\"time\":{\"elapsed\":%10d},\"adcN\": %5.4f, \"adcV\":%6.4f, \"e0\":%i }\n",time_[lp2i], 00220 data_n,(ADC_NORM_VREF*data_n), 00221 elec0p); 00222 #else 00223 fprintf(fpUsb, "{\"time\":{\"elapsed\":%10d},\"adcN\": %5.4f, \"adcV\":%6.4f}\n",time_[lp2i],data_n,(ADC_NORM_VREF*data_n)); 00224 #endif 00225 fclose(fpUsb); fpUsb=NULL; 00226 writeUsb=1; 00227 } else { 00228 //Potential Error 00229 UsbPresent=0; //Can't say its dissappeared as will cause USB find problem. 00230 pc.printf(" Error: USB unexpected can't write!!\n\r"); 00231 //writeUsb=0; 00232 } 00233 } 00234 return writeUsb; 00235 } 00236 //-------------------------------------------------------------- 00237 /* Manage the sample 00238 - store it 00239 - and write it to USB stick 00240 [FUT] detect USB stick and if not present write it when inserted 00241 00242 JSON output json.org 00243 {key:value, key:value, key:value} 00244 {time:[elapsed:<secs 0-2**32>, epoch2014:<secs 0-2**32>,wall:[date:<>,clock:<>],], 00245 adcNorm:<float number 0.0-1.0>, 00246 adcV:<Volts 0-VRef>} 00247 */ 00248 void manageSample() { 00249 float data_n; 00250 int i_lp,idx; 00251 int publishInst_raw; 00252 bool noisey=0; 00253 00254 /* WaterDepth eTape sensor is noisey - average input for noise and compare against changes by capactive sensor 00255 * Average published sensor and check if new reading changes by more than 1/300 of fsd if it does check against capacitive sensor and see if it is trending same direction 00256 */ 00257 publishInst_raw = sample_u16[lp2i]; //over X previous 00258 sampleInst_raw = sample_u16[lp2i]; //over X previous 00259 elec0p = electr[lp2i]; 00260 for (i_lp =1; i_lp< SAMPLE_WIN; i_lp++) { 00261 idx = lp2i-i_lp; 00262 if (idx <0) idx+= BuffSize; 00263 publishInst_raw += publish_u16[i_lp]; //over X previous 00264 sampleInst_raw += sample_u16[i_lp]; //over X previous 00265 elec0p += electr[i_lp]; 00266 } 00267 publishInst_raw /= SAMPLE_WIN; 00268 sampleInst_raw /= SAMPLE_WIN; 00269 elec0p /= SAMPLE_WIN; 00270 #if 0 //future 00271 #define SAMPLES_ABS_CNT 5 00272 if (SAMPLES_ABS_CNT < abs(sampleInst_raw - publishInst_raw) ) { 00273 //Need to check if this is noise 00274 //if ( abs(abs(elec0p) - electr[lp21]); 00275 noisey = 1; 00276 } 00277 #endif //0 00278 data_n=sampleInst_raw * ADC_NORMALIZE; 00279 pc.printf("\n\r%10d %5.4f (%6.4fV) %i %i N%i %i",time_[lp2i],data_n,(ADC_NORM_VREF*data_n), 00280 electr[lp2i],elec0p, noisey, 00281 lp2i); 00282 00283 //ledGrn = !(lp2i&0x01);//!ledGrn; syncs with blue led flashing 00284 //ledPwmGrn = ((lp2i&0x01) ? (1.0-? ? ?) : 1.0 ); //LEDGrn=1 off, =0 On 00285 if (lp2i&0x01) {//Only write every two times 00286 if (1/*ToDo==manageUsbWrite(*fp)*/) { 00287 ledBlue = !ledBlue; //(lp2i&0x03); 00288 } else {ledBlue =1;}//off 00289 } 00290 00291 }//end manageSample 00292 00293 //-------------------------------------------------------------- 00294 /* Manage the sample 00295 - take an ADC sample and 00296 */ 00297 void manageAdcIn(void){ 00298 //Take samples and store in buffer 00299 if (++lp2i >= BuffSize) lp2i=0; 00300 sample_u16[lp2i]=ainPinAA.read_u16(); 00301 time_[lp2i]=(unsigned int)tmrE_evt; //TODO - replace with wall time 00302 #if TsiActive 00303 tsiSlider_dist = TsiRead(); 00304 electr[lp2i]= tsi.getDelta0(); 00305 #endif //TsiActive 00306 00307 //elec1p = tsi.getDelta1(); 00308 //tsiSlider_dist = (float)tsi.readPercentage(); 00309 00310 }//manageAdcIn 00311 00312 //-------------------------------------------------------------- 00313 void UsbHostMsd_task(void const *) { 00314 USBHostMSD msd("usbAa"); //defines the file system access 00315 int i = 0; 00316 00317 while(1) { 00318 00319 // try to connect a MSD device 00320 while(!msd.connect()) { 00321 //Thread::wait(500); 00322 } 00323 00324 // in a loop, append a file 00325 // if the device is disconnected, we try to connect it again 00326 while(1) { 00327 00328 // append a file 00329 FILE * fp = fopen("/usb/test1.txt", "a"); 00330 00331 if (fp != NULL) { 00332 fprintf(fp, "Hello fun SD Card World: %d!\r\n", i++); 00333 printf("Goodbye World!\r\n"); 00334 fclose(fp); 00335 } else { 00336 printf("FILE == NULL\r\n"); 00337 } 00338 00339 //Thread::wait(500); 00340 00341 // if device disconnected, try to connect again 00342 if (!msd.connected()) 00343 break; 00344 } 00345 00346 } 00347 } 00348 /* Input parser from usb - but how large is buffer 00349 char buffer[128]; 00350 pc.gets(buffer, 4); 00351 pc.printf("I got '%s'\n", buffer); 00352 */ 00353 //-------------------------------------------------------------- 00354 int main() { 00355 00356 //TODO: check RCM_SRS0 &RS1 00357 warmBoot = rtc_isenabled(); 00358 if (!warmBoot) { 00359 //TODO figure out how to manage wall time 00360 rtc_init(); //Assumes external clock - TODO: options int32Khz RTC_CLKIN ext32KhzXtal 00361 rtc_write(0x0); //Init to some default; 00362 } 00363 00364 ledRed =0;//ON 00365 //ledGrn =1; //off 00366 ledPwmGrn =1.0; //off 00367 ledBlue = 1; //on 00368 00369 //Thread msdTask(UsbHostMsd_task, NULL, osPriorityNormal, 1024 * 4); 00370 00371 wait_ms(5000); 00372 //Thread::wait(2000); 00373 ledRed =1;//Off 00374 //ledGrn =1; //off 00375 ledPwmGrn =1.0; //off 00376 ledBlue = 0; //on 00377 pc.baud(115200);//Opt 57600 00378 00379 pc.printf("\n\r%s Logger v0.1 \n\r Sample [time=%dsec, size=%d] Clock=%d\n\r",meProc, sysTockInit_sec,BuffSize,SystemCoreClock); 00380 00381 outputHeaders(); 00382 00383 tock.attach(&tockEvent,sysTockInit_sec); 00384 00385 while (true) { 00386 if(sysEventA) 00387 { 00388 sysEventA=0; 00389 manageAdcIn(); 00390 manageSample(); 00391 }//else 00392 // TODO go into power down till next event 00393 } 00394 00395 }
Generated on Wed Jul 13 2022 19:41:09 by 1.7.2