Logger to USB stick running on KL25Z

Dependencies:   F401RE-USBHost FastAnalogIn RTC mbed tsi_sensor2 mbed-rtos2

Fork of ReadSendData by Stuart Scott

Homepage for kXX_logger(was kl25x_usb_logger)

2014Nov12 - Added TSI - only works for kl25z, and fails after 4287seconds

Tests sequences for freezing 4287seconds 4287 4287 - Changed to USB write update every two seconds and lasted 4283seconds. Added mbed TSI_sensor - kudos to mbed as it turns out to be complex to do capacitive touch sensing. Kinetis L series Cortex-M0 (kl25z) has simpler capacitive sensing hardware which mbed/TSI_sensor lib uses, but doesn't support Cortex-M4 versions. K20D is older more complex interface. TSS hasn't had an open source support by Freescale in the past however that has changed. Currently I found KDS1.1.1 has a Processor Expert TSSlib that can be imported - but I'm getting a weird compile/include error - and not found any examples of how to make it work.

2014Oct05 - Published simple kl25z_usb_logger

Testing: Version (2:f06fbf86887e) has run over 28days starting 2014Sept07, reading a sensor data every seconds and then on the USB stick open file, write record, close file

This is over 2,419,200seconds ( 28days*24hrs*3600seconds) The stick data reflected 2,447,633 seconds, but only had 1,776,366 data records. After 407,650 data records started missing updates - analysis: the file could not be opened and read to the end in the allocated 1 second, and therefore missed the next ADC deadline.

By the end of the test period with 1,776,366 records on the USB Stick, ever read then write was causing it to miss two/three ADC updates - ie taking longer than two seconds.

Analysis: this was an aggressive test, and normally would not be opening, writing, closing every 1 second. However big plus the file mechanism held up and the program continued to operate, with a graceful failure of a missed ADC readings. The output used JSON, which reads nicely but turns out not to be supported by Excel (2014?) I was using.

Conclusion: Overall the USB Mechanisms and file read is stable. However the USB stack used doesn't have an event based management for stick insertion and removal, or OTG power management . This KL25Z has been a very useful test to prove the configuration of clocks for USB Stack is possible and stable. The target processor being looked at is the MK20 and is similar in clocks, but slightly more comprehensive USB OTG Next step is to investigate the full Freescale Kinetis USB OTG Stack with power management on a custom K20 board, using Kinetis Design Studio, and very low power capability.

Example https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/FRDM-K20D50M/FRDM-K20_MSD_Host http://mcuoneclipse.com/2014/10/25/usb-cdc-with-the-frdm-k64f-finally/#comment-37727 - Commentary on Freescale USB versions

Files at this revision

API Documentation at this revision

Comitter:
neilh20
Date:
Sun Oct 05 21:04:14 2014 +0000
Parent:
1:c424a90749e1
Child:
3:d94384ab6f12
Commit message:
Logger to USB stick on KL25z

Changed in this revision

F401RE-USBHost.lib Show annotated file Show diff for this revision Revisions of this file
FastAnalogIn.lib Show annotated file Show diff for this revision Revisions of this file
RTC.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F401RE-USBHost.lib	Sun Oct 05 21:04:14 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/va009039/code/F401RE-USBHost/#47978c25c9b8
--- a/FastAnalogIn.lib	Wed Jul 23 16:58:23 2014 +0000
+++ b/FastAnalogIn.lib	Sun Oct 05 21:04:14 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/Sissors/code/FastAnalogIn/#31184aa1449c
+http://developer.mbed.org/users/neilh20/code/FastAnalogIn/#e671743d1b91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RTC.lib	Sun Oct 05 21:04:14 2014 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/neilh20/code/RTC/#b61676bcc5c0
--- a/main.cpp	Wed Jul 23 16:58:23 2014 +0000
+++ b/main.cpp	Sun Oct 05 21:04:14 2014 +0000
@@ -1,64 +1,225 @@
-#include "mbed.h"
-#include "FastAnalogIn.h"
+/* low power data logger. [FRDM-KL25Z]
+
+Periodically read data from ADC and when present write it in JSON format to USB Stick
+
+Copyright  http://www.apache.org/licenses/LICENSE-2.0
+and all subsystems per their own licenses which are believed to be GPL 2.0
+
+[c]Record an analoge value to an internal buffer 
+[p]and when a USB stick is plugged in store the values on the USB stick in JSON format
+   (currently requires USB stick at reset)
+[c]Debug output the events as they happen.
+[c]The ticker delay sets the sampling rate. 
+[F]Date is set when user sets it, 
+[c]or elapsed time used in the beginning 
+
+[F]If OpenSDA USB power supplied, then flash LEDs to indicate activity as follows
+[c]1) the Blue led when taking a sample
+[c]2) the green led when delivering samples to the USB stick
+[F]3)no led shall be on at same time for clear colours
+
+[F] when not doing anything else sleep to conserve power.
 
-/*
-Simple program which uses a ticker object to record and analoge value and store it in a cicular buffer.
-The ticker delay sets the sampling rate. 
+ To modify this for your application, assuming a ratiometric input to the Vref=3.3V
+ 1) Determine physical pins ADC performed on and type of conversion,
+ 1) Determine the "multiplier" from the incoming 16bit ADC wrt to 3.3V to your units.
+ 2) Write the output code changing the JSON headers to define your headers, dataConversion and units
+ 
+Thanks to other authors for setting up KL25z for 
+* FastAnalogIn Library  mbed.org/users/Sissors/code/FastAnalogIn/
+* USB Host mbed.org/users/va009039/code/F401RE-USBHost/
+ 
+ [] 1st three character nomeclature.
+[x] indicates implemented state of feature 
+[c] - complete and unit tested
+[p] - partial in progress or not unit tested
+[f] - future idea
 
-The FastAnalogIn Library is used (http://mbed.org/users/Sissors/code/FastAnalogIn/) to rapidly sample 
-a single channel. 
+Testing: Basic tests performed, see attached file logger_tests.docx
+
+Modifications to Hardware
+1) FRDM-KL25z add J21 and R8 per the instruction manual for USB host
 
-In the main loop a busy loop is used to send read the data from the cicular buffer and send down the serial line
+Issues: 
+1) FRDM-KL25z hardware not designed to switch the USB power so saving power on a connected USB device.
+Solution: Add switched 5V power.
+2) FRDM-KL25z Hardware not designed for low power accurate wall time clock - wastes power keeping the 8Mhz going.
+Solution: add an external low power 32KHz oscilator into hardware pin RTC_IN (An osc is the next step up from a raw Xtal)
 
 
 */
 
-//size of cicular buffer
-#define BuffSize 255
+#include "mbed.h"
+#include "rtc_api.h"
+#include "FastAnalogIn.h"
+#include "USBHostMSD.h"
+
+//size of sample  buffer 
+#define BuffSize 16  //16 to test, upto kl25z spare ram of about xxxx?, !2000, linker warns if too large, but also fails
+//set the delay used by the ticker
+const int sysTockInit_sec = 1; //Test 1, Real life 15minutes or 900sec
 
 using namespace mbed;
 
-FastAnalogIn Ain(PTC2);
+//Device Init - per FRDM-KL25Z
+DigitalOut ledRed(LED1); 
+DigitalOut ledGrn(LED2); 
+DigitalOut ledBlue(LED3); 
+FastAnalogIn ainPinAA(PTC2); ///AnalogAin pin
 
 Serial pc(USBTX, USBRX);
-Timer t;
-Ticker tock;
 
-//set the delay used by the ticker
-float delay = 0.01;
-
-//some circular buffers
+//Samples stored here - needs to be compact as can use a lot of internal ram
+ unsigned short sample_u16[BuffSize]; //critical resource for number of samples
+ unsigned int time_[BuffSize];
 
-float data[BuffSize];
-float time_[BuffSize];
-long i =0;
-int j=0;
-long k =0;
- 
-void ana()
+ FILE* fpUsb;
+ bool UsbPresent=0;
+ bool warmBoot = rtc_isenabled(); 
+ long lp2i =0;
+ bool sysEventA=0; //Local event
+ unsigned int tmrE_evt; //Elapsed
+ Ticker tock; //periodic tick
+
+ USBHostMSD  msd("usbAa"); //defines the file system access
+    
+//--------------------------------------------------------------
+void tockEvent()
 {
-   if(i<k+BuffSize)
-    {j = i%BuffSize;
-    //time_[j]=t.read();
-    data[j]=Ain.read();
-    time_[j]=t.read();
-    i++;
-    }
+    tmrE_evt++;
+    sysEventA=1;
 }
 
+//--------------------------------------------------------------
+/* Process output Header to USB, 
+return !0 if valid USB present
+*/
+ bool outputHeaderUsb() {
+    // JSON {"headings":{"time":{"elapsed":"seconds"},  "adcN":"normalized_to_1.0", "adcV":"Volts"}}
+    
+    if (!UsbPresent) 
+    {
+      if (msd.connect()) //Attempt to find a device
+      {//USB Event: newly connected so attempt write header
+        if (NULL !=(fpUsb = fopen("/usbAa/test1.txt", "a"))) 
+        {
+            pc.printf("USB File test1.txt opened.\n\r");
+            fprintf(fpUsb,"{\"headings\":{\"time\":{\"elapsed\":\"seconds\"},  \"adcN\":\"normalized_to_1.0\", \"adcV\":\"Volts\"}}\n");
+            UsbPresent=1;
+            fclose(fpUsb); fpUsb=NULL;
+        } else {
+            //Can't find a file for some reason. Could be USB full or failed software
+            pc.printf(" Error: USB File not opened.\n\r");
+            UsbPresent=0;
+        }
+      } //else //Can't find USB device
+    } else {
+        // UsbPresent and assume headers written
+        if (!msd.connected()) 
+        {
+          pc.printf("  USB Flash drive removed.\n\r");
+          UsbPresent=0;
+        }
+    }
+    
+    return UsbPresent;
+}
+//--------------------------------------------------------------
+ void outputHeaders(void) {
+    outputHeaderUsb();
+    pc.printf("  Time(S)   depthR(norm) Volts Idx %d\n\r",(unsigned int) rtc_read());
+}//outputHeaders
 
+
+
+//--------------------------------------------------------------
+/* Manage the write to USB stick
+[FUT] detect USB stick and if not present write it when inserted
+
+JSON output json.org
+{key:value, key:value, key:value}
+{time:[elapsed:<secs 0-2**32>, epoch2014:<secs 0-2**32>,wall:[date:<>,clock:<>],],
+ adcNorm:<float number 0.0-1.0>, 
+ adcV:<Volts 0-VRef>
+ */
+void manageUsbWrite() {
+#define ADC_NORMALIZE (1.0f/65535.0f)
+#define ADC_NORM_VREF 3.3
+    float data_n=( ((float)sample_u16[lp2i]) * ADC_NORMALIZE);
+    if (outputHeaderUsb()) 
+    {
+      if (NULL !=(fpUsb = fopen("/usbAa/test1.txt", "a"))) 
+      {  
+           fprintf(fpUsb, "{\"time\":{\"elapsed\":%10d},\"adcN\":  %5.4f, \"adcV\":%6.4f}\n",time_[lp2i],data_n,(ADC_NORM_VREF*data_n));
+           fclose(fpUsb); fpUsb=NULL;
+           ledGrn = !ledGrn;    
+       } else {
+           //Potential Error
+           UsbPresent=0; //Can't say its dissappeared as will cause USB find problem.
+           pc.printf("  Error: USB unexpected can't write!!\n\r");
+       }
+    } 
+ } 
+//--------------------------------------------------------------
+/* Manage the sample
+- store it 
+- and write it to USB stick
+[FUT] detect USB stick and if not present write it when inserted
+
+JSON output json.org
+{key:value, key:value, key:value}
+{time:[elapsed:<secs 0-2**32>, epoch2014:<secs 0-2**32>,wall:[date:<>,clock:<>],],
+ adcNorm:<float number 0.0-1.0>, 
+ adcV:<Volts 0-VRef>}
+*/
+void manageSample() {
+    float data_n=( ((float)sample_u16[lp2i]) * ADC_NORMALIZE);
+    pc.printf("%10d  %5.4f (%6.4fV) %i\n\r",time_[lp2i],data_n,(ADC_NORM_VREF*data_n),lp2i);
+    ledBlue = !ledBlue;   
+    
+    manageUsbWrite();
+
+}//end manageSample
+
+//--------------------------------------------------------------
+/* Manage the sample
+- take an ADC sample and 
+*/
+void manageAdcIn(void){
+    //Take samples and store in buffer
+    if (++lp2i >= BuffSize) lp2i=0;
+    sample_u16[lp2i]=ainPinAA.read_u16();
+    time_[lp2i]=(unsigned int)tmrE_evt; //TODO - replace with wall time
+ }//manageAdcIn
+ 
+//--------------------------------------------------------------
 int main()
-{
-    pc.baud(57600);
-    t.start();
-    tock.attach(&ana,delay); 
+
+//TODO: check RCM_SRS0 &RS1
+    warmBoot = rtc_isenabled(); 
+    if (!warmBoot) {
+        //TODO figure out how to manage wall time
+        rtc_init(); //Assumes external clock - TODO: options int32Khz  RTC_CLKIN ext32KhzXtal 
+        rtc_write(0x0); //Init to some default;
+    }
+    ledRed =1;//Off
+    ledGrn =1; //off
+    ledBlue = 0; //on
+    pc.baud(115200);//Opt 57600
+    pc.printf("\n\rkl25z Logger v0.1 \n\r Sample [time=%dsec, size=%d] Clock=%d\n\r", sysTockInit_sec,BuffSize,SystemCoreClock);
+
+    outputHeaders();
+
+    tock.attach(&tockEvent,sysTockInit_sec); 
+
     while (true) {        
-       if(k<i)
-        {
-        pc.printf("%f,%f\n",time_[k%BuffSize],data[k%BuffSize]);
-        k++;
-        }
-        
-  
+     if(sysEventA)
+     {
+       sysEventA=0;
+       manageAdcIn();
+       manageSample();
+      }//else 
+      // TODO go into power down till next event
     }
+   
 }
--- a/mbed.bld	Wed Jul 23 16:58:23 2014 +0000
+++ b/mbed.bld	Sun Oct 05 21:04:14 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/04dd9b1680ae
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/9327015d4013
\ No newline at end of file