Code for the Battery MBED

Dependencies:   NRF2401P mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
dontknowhow
Date:
Fri Jun 12 14:37:27 2015 +0000
Commit message:
Version 1, work in progress

Changed in this revision

NRF2401P.lib Show annotated file Show diff for this revision Revisions of this file
comms.cpp Show annotated file Show diff for this revision Revisions of this file
comms.h 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-rtos.lib 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
diff -r 000000000000 -r 3d91ae4fc885 NRF2401P.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NRF2401P.lib	Fri Jun 12 14:37:27 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/epgmdm/code/NRF2401P/#7e253c677a1f
diff -r 000000000000 -r 3d91ae4fc885 comms.cpp
diff -r 000000000000 -r 3d91ae4fc885 comms.h
diff -r 000000000000 -r 3d91ae4fc885 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Jun 12 14:37:27 2015 +0000
@@ -0,0 +1,291 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "NRF2401P.h"
+
+#define BATTERY_ID "123"
+
+#define CAPACITY 3600 //in Joules (=1000mAh)
+
+#define STORAGE_READINGS 200 //86400
+
+#define READING_INTERVAL 1.0
+
+#define IDLING_POWER 0.001  // 1mW 
+
+// Three different Modes, as explained in the Wiki.
+#define IDLING 1
+#define CHARGING 2
+#define POWERING 3
+
+Serial pc(USBTX, USBRX); // tx, rx
+
+// ADC inputs
+AnalogIn bat_v(PTB0);
+AnalogIn bat_i(PTB1);
+
+// The ADC measurements are run by a ticker
+Ticker get_stats_tick;
+
+// structure for storing our data.
+typedef struct {
+    float voltage;  // instantaneous voltage in V
+    float current;  // instantaneous current in A
+    float power;    // instantaneous power in W
+    
+    double energy;    // total energy into & out of battery in J    
+    double c_count;   // total current in & out "Coulomb count"
+    
+    float charge;   // estimated charge as a percentage
+    int capacity;   // estimated capacity in mJ
+    
+    int powers[STORAGE_READINGS];   // array to hold powers in mW
+    int voltages[STORAGE_READINGS];   // array to hold voltages in mV
+    int currents[STORAGE_READINGS];   // array to hold currents in uA
+    
+    unsigned int readings;      // count of readings taken
+    float idling_time;          // time spent idling
+    
+    char mode;      // current mode of operation
+    bool new_data;  // indicates fresh data ready to be processed,
+                    //  flag set to true by get_stats()
+    
+} stats_t;
+
+// global variable for use in ticker
+stats_t stats;
+
+// Debug function for printing to a serial port
+void print_stats(Serial *out, stats_t *stats);
+
+// Use the ADC0
+void get_stats(stats_t *stats);
+
+// wrapper function, this is called by the ticker.
+void get_stats_w(){
+    get_stats( &stats );    
+}
+
+// used for initializing the structure
+void reset_stats(stats_t *stats);
+
+// seperate thread for communication
+void comms_thread(void const *args);
+
+int main() {
+    
+    // start the comms thread    
+    Thread thread(comms_thread);
+    
+    // start taking measurements
+    get_stats_tick.attach(&get_stats_w, READING_INTERVAL);
+    
+    // initialiye the stats structure
+    reset_stats(&stats);
+            
+    while(true){
+        
+        // get stats has supplied some new data, analyse it.
+        if(stats.new_data){
+            
+            // add the current values to the storage array       
+            stats.powers[stats.readings - 1] = (int)( stats.power * 1000.0 );
+            stats.voltages[stats.readings - 1] = (int)( stats.voltage * 1000.0 );
+            stats.currents[stats.readings - 1] = (int)( stats.current * 1000.0 * 1000.0);
+            
+            // evaluate the current mode by looking at the current
+            if( abs(stats.power)< IDLING_POWER){
+                stats.mode = IDLING;
+            } else if (stats.power < 0){
+                stats.mode = CHARGING;
+            } else{
+                stats.mode = POWERING;
+            }    
+            
+            // measure the time spent idling
+            if(stats.mode==IDLING)
+                stats.idling_time += READING_INTERVAL;
+                           
+            // Coulomb counting and total energy in/out
+            stats.c_count += stats.current * READING_INTERVAL;
+            stats.energy += stats.power * READING_INTERVAL;
+            
+            // estimating SOC
+            // http://liionbms.com/php/wp_soc_estimate.php
+            
+            if(stats.voltage > 3.5){ // Voltage Conversion
+                stats.charge = (stats.voltage - 3.5) * 0.1f + 0.9f;
+            }
+            else if(stats.voltage < 3.0){ // Voltage Conversion
+                stats.charge = (stats.voltage - 3.0) * 0.1f;
+            }
+            else{   // Coulomb Counting
+                stats.charge = stats.c_count / stats.capacity;
+            }
+            
+            // data has been analysed, reset flag
+            stats.new_data = false;
+        }
+        
+        
+        if(stats.readings>=STORAGE_READINGS){   // We have reached the maximum amount of readings, start again!
+        
+            reset_stats(&stats);
+        }
+        
+
+       
+    }
+}
+
+
+void comms_thread(void const *args){
+    
+    // set up nrf radio communication 
+    long long addr1=0xAB12CD; // setup address - any 5 byte number - same as RX
+    int channel = 52;  // [0-126] setup channel, must be same as RX
+    bool txOK;
+    char msg[32];
+    char ackData[32];
+    char len;
+     
+     // Setup 
+    NRF2401P nrf1(PTD2, PTD3, PTD1, PTA13, PTD0); //mosi, miso, sclk, csn, ce)
+    
+    nrf1.quickTxSetup(channel, addr1); // sets nrf24l01+ as transmitter
+     
+    Timer att_t;   // timer for sending attention commands
+    Timer out_t;   // timer for timeouts
+    
+    
+    
+    att_t.start();
+    
+    char c = '0';
+    float voltage, current, voltage_r, current_r;
+    while(true){   
+        
+        // listen to pc serial for debugging
+        if(pc.readable())
+            c = pc.getc();
+            
+        if(c=='p'){
+            print_stats(&pc, &stats);
+        }
+        if(c=='g'){
+            get_stats(&stats);
+        }
+        if(c=='r'){
+            voltage_r = bat_v.read();
+            current_r = bat_i.read();
+            
+            // formulas based on empirical measurements
+            voltage = 10.6 * voltage_r - 4.14f; 
+            current = -1.7574 * current_r + 1.248;
+                    
+            pc.printf("Voltage: %1.3f Current: %1.3f AN0: %1.3f AN1: %1.3f\r\n", voltage, current, voltage_r, current_r); 
+        }
+        c = '0';
+        
+        if(att_t.read()>1.0f){
+            // Send Attention command to locker every second
+            
+            strcpy (msg, "AT"); 
+            txOK = nrf1.transmitData(msg,strlen(msg));
+            
+         
+            while(att_t.read()<2.0f){
+                if (nrf1.isAckData()) { 
+                    len= nrf1.getRxData(ackData); // len is number of bytes in ackData
+                    ackData[len] = '\0';
+                    
+                    
+                    
+                    if (strcmp(ackData, "HELLO") == 0){
+                                       
+                            
+                        
+                        sprintf(msg, "%s1",BATTERY_ID);
+                         
+                        txOK = nrf1.transmitData(msg,strlen(msg));
+                     
+                        
+                    }
+                    
+                    break;
+                }
+            }
+            
+            att_t.reset();
+        }
+        
+      Thread::wait(20);  
+    }
+}
+
+// reset and initialize the structure
+void reset_stats(stats_t *stats){
+   
+    stats->readings = 0;
+    stats->energy = 0;
+    stats->c_count = 0;
+    stats->idling_time = 0.0;
+    stats->capacity = CAPACITY;    
+    stats->new_data = false;
+    
+    for( int i=0; i<STORAGE_READINGS; i++){
+        stats->powers[i] = 0;
+        stats->voltages[i] = 0;
+        stats->currents[i] = 0;        
+    }
+
+}
+
+// print some data
+void print_stats(Serial *out, stats_t *stats){
+    out->printf("\r\n\r\n");
+    for(int i = 0; i < stats->readings; i++){
+        //out->printf("Reading %3d: Voltage: %dmV Current: %duA Power: %dmW \r\n", i, stats->voltages[i], stats->currents[i], stats->powers[i]);         
+    }
+    out->printf("\r\n");
+    out->printf("V: %1.2fV I: %1.2fmA Power: %1.0fmW \r\n", stats->voltage, stats->current * 1000, stats->power * 1000);
+    out->printf("Mode:       %d \r\n", stats->mode);
+    out->printf("Energy:     %1.3fJ \r\n", stats->energy);
+    out->printf("Coulomb C:  %1.3fC \r\n", stats->c_count);
+    out->printf("Time:       %1.3f s \r\n", stats->readings * READING_INTERVAL);
+    out->printf("Readings:   %d \r\n", stats->readings);
+    out->printf("Interval:   %1.3fs \r\n", READING_INTERVAL);
+    out->printf("Idling t:   %ds \r\n", stats->idling_time); 
+    out->printf("Est Charge: %.0f%% \r\n", stats->charge * 100); 
+ 
+}
+
+// every second, read the adc and save it in the structure
+void get_stats(stats_t *stats){
+    
+    if(stats->new_data){ // ERROR: stats have not been processed
+        pc.printf("ERROR: stats not processed\r\n");        
+    }
+    
+    //average over 10 readings
+    float current_r = 0;
+    float voltage_r = 0;
+    
+    for(int i = 0; i<10; i++){
+        voltage_r += bat_v.read();
+        current_r += bat_i.read();
+        //pc.printf("%1.3f %1.3f \r\n",voltage_r, current_r);
+    }
+    
+    
+    current_r /= 10.0;
+    voltage_r /= 10.0;
+    
+    stats->voltage = 10.6f * voltage_r - 4.14f;  
+    stats->current = -1.7574f * current_r + 1.252f;
+    
+    stats->power = stats->voltage * stats->current;
+    
+    stats->readings++;    
+        
+    stats->new_data = true;            
+}
\ No newline at end of file
diff -r 000000000000 -r 3d91ae4fc885 mbed-rtos.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Fri Jun 12 14:37:27 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/mbed_official/code/mbed-rtos/#ed4ff3bea947
diff -r 000000000000 -r 3d91ae4fc885 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Jun 12 14:37:27 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/cbbeb26dbd92
\ No newline at end of file