EIoT LoRa node 3 - Working ok

Dependencies:   BufferedSerial SX1276GenericLib-node1 mbed

Fork of DISCO-L072CZ-LRWAN1_LoRa_node by Santiago Gil

Files at this revision

API Documentation at this revision

Comitter:
sagilar
Date:
Mon Oct 08 16:11:17 2018 +0000
Parent:
12:a6a37ba1feff
Commit message:
EIoT LoRa node 3

Changed in this revision

ACS712.h Show annotated file Show diff for this revision Revisions of this file
SX1276GenericPingPong/GenericPingPong.cpp Show annotated file Show diff for this revision Revisions of this file
SX1276GenericPingPong/GenericPingPong.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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ACS712.h	Mon Oct 08 16:11:17 2018 +0000
@@ -0,0 +1,93 @@
+#include <mbed.h>
+/** A Hall-Effect sensor for measuring current levels in a given path
+ *
+ * Can be used as a current detector
+ *
+ * Example:
+ * @code
+ * // Periodically read current levels in a circuit and
+ * // send output to PC terminal
+ *
+ * #include "mbed.h"
+ * #include "ACS712.h"
+ *
+ * // Connect the sensor analog output pin to mbed's AnalogIn pin
+ * ACS712 dev(p18);
+ * // Connect mbed to pc's USB port
+ * Serial pc(USBTX, USBRX);
+ *
+ * int main() {
+ *      pc.printf("Sensor Log: \n\n\r");
+ *      while (1) {
+ *          // Read current from sensor and output to pc terminal
+ *          pc.printf("Sensor Value: %2.2f A\n\r", dev);
+ *          wait(0.200);
+ *      }
+ * }
+ * @endcode
+ */
+ 
+class ACS712 { 
+    
+    public:
+        /** Create a hall-effect sensor of the specified type
+         *
+         * @param _pin mbed AnalogIn pin where the analog output of sensor is connected
+         * @param voltDivRatio resistor voltage division ratio at output of the sensor
+         * @param type type of ACS712 sensor used
+         *
+         * @note Supported types of sensors:
+         */
+        ACS712(PinName _pin, float voltDivRatio = 1, short type = 5);
+        
+        /** Read the value of the measured current in amps
+         *
+         * @return current value in amps
+         */
+        float read();
+        ACS712& operator=(const ACS712&);
+        
+        /** Read the value of the measured current in amps
+         *  Allows the ACS712 object to be used in a float context
+         * 
+         * @return current value in amps
+         */
+        operator float() { return read(); }
+        
+    private:
+        AnalogIn sensor;
+        float translate(float);
+        float ratio;
+        short type;
+
+};
+
+ACS712::ACS712(PinName _pin, float voltDivRatio, short sensorType) : sensor(_pin){
+    ratio = voltDivRatio;
+    type = sensorType;    
+}
+
+float ACS712::translate(float val){
+    switch(type){
+        case 5: 
+            return (val*ratio - 2.46*ratio)/(.185*ratio);
+        case 20:
+            return (val*ratio - 2.46*ratio)/(.1*ratio);
+        case 30:
+            return (val*ratio - 2.46*ratio)/(.066*ratio);
+        default:
+            return 999;
+    }
+}
+
+
+float ACS712::read(){
+    return ACS712::translate((sensor) * 3.3);   
+}
+
+ACS712& ACS712::operator=(const ACS712& rhs){
+    sensor = rhs.sensor;
+    ratio = rhs.ratio;
+    type = rhs.type;
+    return *this;
+}
--- a/SX1276GenericPingPong/GenericPingPong.cpp	Wed Aug 08 22:33:19 2018 +0000
+++ b/SX1276GenericPingPong/GenericPingPong.cpp	Mon Oct 08 16:11:17 2018 +0000
@@ -12,6 +12,8 @@
 #include "main.h"
 #include <string>
 #include "rtos.h"
+#include "ACS712.h"
+#include <math.h>
 
 #ifdef FEATURE_LORA
 
@@ -93,11 +95,12 @@
 //const uint8_t PongMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'O', 'N', 'G'};// "PONG";
 //const uint8_t PingMsg[] = { 'M', 'S', 'J', ' ','G','I','L'};// "PING";
 //const uint8_t PongMsg[] = {  'R', 'P', 'T', 'A',' ','G','I','L'};// "PONG";
-const char EUI[] = "0A10";// 4  bytes que definen el identificador del dispositivo (copiar los bytes en string)
+const char EUI[] = "0E30";// 4  bytes que definen el identificador del dispositivo (copiar los bytes en string)
+const char nombreDispoitivo[] = "nodo3_EIoT_LoRa";
 const char AppEUI[] = "AAAA";// 4  bytes que definen el identificador de la aplicacion (copiar los bytes en string)
 const char AppKey[] = "1A1B";// 4  bytes que definen la clave de la aplicacion (copiar los bytes en string) - El protocolo LoRaWAN establece la clave de 16 bytes pero para efectos de prueba se hara de 4
-char MsgTX[64] = "";// Mensaje de transmision, se pueden usar los 52 bytes faltantes para completar el payload de 64 bytes. Se puede poner directamente en string.
-char MsgRX[64] = "";// Mensaje de recepcion, carga el payload entrante a esta cadena.
+char MsgTX[256] = "";// Mensaje de transmision, se pueden usar los 52 bytes faltantes para completar el payload de 64 bytes. Se puede poner directamente en string.
+char MsgRX[256] = "";// Mensaje de recepcion, carga el payload entrante a esta cadena.
 char MsgRet[] = "RECIBIDO";// Para verificar el resultado del envio
 char DestEUI[] = "0A01"; //Gateway Server
 string strRecepcion = "";
@@ -109,24 +112,73 @@
 char *srcEUI;
 char *msjDestEUI;
 char *msjContent;
-AnalogIn analog_value(A0);
+
+//ACS712 cur_sensor(A0,1.0,5);
+//ACS712 cur_sensor(A0);
+Serial serRPi(PA_9, PA_10);
+AnalogIn analog_value_current(A0);
+AnalogIn analog_value_temp(A2);
 //RtosTimer analog_read_timer(readAnalog, osTimerPeriodic);
 
 
-float meas_r;
-float meas_v;
+float meas_r1 = 0.0;
+float meas_v1 = 0.0;
+float meas_r2 = 0.0;
+float meas_v2 = 0.0;
+float inst_current = 0.0;
+float inst_current_d1 = 0.0;
+float mean_current = 0.0;
+float max_inst_current = 0.0;
+int conteoSenal = 0;
+float inst_power = 0.0;
+float mean_power = 0.0;
+float max_power = 0.0;
+float min_power = 0.0;
+float temperature = 0.0;
+const float FACTOR_CUR = 1.48;
+const float RMS_VOLTAGE = 120.0;
+const float SENS = 185.0;
+const float VDC_STATIC_MV = 1540.0;
+Timer tiempo;
+//const int SAMP_RATIO = 50;
+bool sending_temp = false;
+bool sending_electric = false;
+Ticker tick_current;
+Ticker tick_send_electric;
+Ticker tick_temp;
+Ticker tick_gps;
+DigitalOut *led3;
 
-DigitalOut *led3;
+//Filtro peak @ 3000 Hz de muestreo
+double v_sub1 = 0.0;
+double v_sub2 = 0.0;
+double a0= 0.031474551558414499, a1= 0, a2 = -0.031474551558414499, b0 = 1, b1 = -1.9275262288479234, b2 = 0.937050896883171, gc= 1.0;
+// Filtro Pasa alta @ 3000 Hz de muestreo fc = 5Hz;
+double vh_sub1 = 0.0;
+double vh_sub2 = 0.0;
+double ah0= 1, ah1= -2, ah2 =  1, bh0 = 1, bh1 = -1.9851906578962613, bh2 =  0.98529951312821451, gh= 0.99262254275611894;
+//Filtro pasa baja @ 3000 Hz de muestreo, fc = 65Hz;
+double vl_sub1 = 0.0;
+double vl_sub2 = 0.0;
+double al0= 1, al1= 2, al2 =  1, bl0 = 1, bl1 = -0.62020410288672889,bl2 =   0.24040820577345759, gl = 0.1550510257216822;
 
 
 int SX1276PingPong()
 {
-	Ticker tick;
-	tick.attach(&readAnalog,10.0);
+
+    //tick_current.attach(&readCurrent,1.0/(60.0 * SAMP_RATIO));
+    tick_current.attach(&readCurrent,5.0);
 
+    tick_send_electric.attach(&sendElectric,60.0);
+
+    //tick_temp.attach(&readTemperature,120.0);
+
+    tick_gps.attach(&readGPS,100.0);
     uint8_t i;
     bool isMaster = true;
 
+	serRPi.baud(115200);
+    serRPi.format(8);
 
 
 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
@@ -328,17 +380,12 @@
                 State = LOWPOWER;
                 break;
             case RX_TIMEOUT:
-                if( isMaster == true ) {
-                    // Send the next PING frame
-                    memcpy(Buffer, MsgTX, sizeof(MsgTX));
-                    for( i = sizeof(MsgTX); i < BufferSize; i++ ) {
-                        Buffer[i] = i - sizeof(MsgTX);
-                    }
-                    wait_ms( 1000 );
-                    Radio->Send( Buffer, BufferSize );
-                } else {
-                    Radio->Rx( RX_TIMEOUT_VALUE );
+                if(sending_electric == true) {
+                    //sendElectric();
+                } else if(sending_temp == true) {
+                    //readTemperature();
                 }
+
                 State = LOWPOWER;
                 break;
             case RX_ERROR:
@@ -404,14 +451,78 @@
     return strOutput;
 }
 
-void onButtonEvent()
+void readCurrent()
 {
+    float vread;
+    float vfilt = 0.0;
+    float vh_ac = 0.0;
+    int cont = 0;
+    tiempo.start();
+    float sum = 0.0;
+    while(tiempo < 1.0)
+
+    {
+
+        vread = analog_value_current.read();
+        vread = vread * 3300.0;
+
+        //vh_ac = gh*filter2o(vread, vh_sub1,vh_sub2, ah0, ah1, ah2, bh0, bh1, bh2);
+        //vfilt = filter2o(vh_ac, v_sub1,v_sub2, a0, a1, a2, b0, b1, b2);
+        //vfilt = gh*filter2o(vread, vh_sub1,vh_sub2, ah0, ah1, ah2, bh0, bh1, bh2);
+
+        //vfilt = gl*filter2o(vh_ac, vl_sub1,vl_sub2, al0, al1, al2, bl0, bl1, bl2);
+        vfilt = gc*filter2o(vread, v_sub1,v_sub2, a0, a1, a2, b0, b1, b2);
+        //dprintf("%.3f",vfilt);
+        sum = sum + pow(vfilt,2);
+        cont++;
+
+    }
+    float VrmsSensor = sqrt(sum/cont);
+    inst_current = VrmsSensor/SENS;
+    //dprintf("%.3f",inst_current);
+    //dprintf("voltajerms: %.3f, corrientersm: %.3f, vread: %.3f, conteo: %d",VrmsSensor,inst_current,vread, cont);
+    tiempo.stop();
+    tiempo.reset();
+
+    if(mean_current != 0.0) {
+        mean_current = (mean_current + inst_current)/2.0;
+    } else {
+        mean_current = inst_current;
+
+    }
+
+    inst_power = inst_current * RMS_VOLTAGE;
+
+    if(mean_power != 0.0) {
+        mean_power = (mean_power + inst_power)/2.0;
+
+    } else {
+        mean_power = inst_power;
+    }
+
+    if(inst_power > max_power) {
+        max_power = inst_power;
+    }
+    if(min_power != 0) {
+        min_power = inst_power;
+    } else {
+        if(inst_power < min_power) {
+            min_power = inst_power;
+        }
+    }
+}
+
+void sendElectric()
+{
+    tick_current.detach();
+    //dprintf("Voltaje Cin: Vcin=%f", meas_v1);
+    sending_electric = true;
     reintentos=0;
-    float value = 3.478;
     char valueStr[]="";
-    sprintf(valueStr,"%.3f",value);
-    char variable[] = "corriente";
-    char dispositivo[] = "extrusador";
+    sprintf(valueStr,"%.2f",mean_current);
+    //sprintf(valueStr,"%.2f",(float)cur_sensor);
+    char variable[] = "corriente_promedio";
+    //char MsgEnvio[64] = "";
     strcpy(MsgTX, EUI);
     strcat(MsgTX, "|");
     strcat(MsgTX, AppEUI);
@@ -424,32 +535,18 @@
     strcat(MsgTX, " ");
     strcat(MsgTX, variable);
     strcat(MsgTX, " ");
-    strcat(MsgTX, dispositivo);
-    //strcat(MsgTX, ";");
-    //*led = !*led;
-    //dprintf( "Enviando contenido al server" );
+    strcat(MsgTX, nombreDispoitivo);
     memcpy(Buffer, MsgTX, sizeof(MsgTX));
-    // Se llena el buffer con la informacion a enviar
     for( int i = sizeof(MsgTX); i < BufferSize; i++ ) {
         Buffer[i] = i - sizeof(MsgTX);
     }
-    //wait_ms( 100 );
     Radio->Send( Buffer, BufferSize );
     Radio->Rx( RX_TIMEOUT_VALUE );
-
-}
-
-void readAnalog()
-{
+    //dprintf("Enviando corriente: Cmean=%f", mean_current);
+    wait_ms( 4000 );
 
-    //wait(1);
-    meas_r = analog_value.read(); // Read the analog input value (value from 0.0 to 1.0 = full ADC conversion range)
-    meas_v = meas_r * 3.3; // Converts value in the 0V-3.3V range
-    reintentos=0;
-    char valueStr[]="";
-    sprintf(valueStr,"%.2f",meas_v);
-    char variable[] = "voltaje";
-    char dispositivo[] = "nodo1_prueba_LoRa";
+    sprintf(valueStr,"%.2f",mean_power);
+    strcpy(variable,"potencia_promedio");
     //char MsgEnvio[64] = "";
     strcpy(MsgTX, EUI);
     strcat(MsgTX, "|");
@@ -463,22 +560,148 @@
     strcat(MsgTX, " ");
     strcat(MsgTX, variable);
     strcat(MsgTX, " ");
-    strcat(MsgTX, dispositivo);
-    //strcat(MsgTX, ";");
-    //*led = !*led;
-    //dprintf( "Enviando contenido al server" );
+    strcat(MsgTX, nombreDispoitivo);
     memcpy(Buffer, MsgTX, sizeof(MsgTX));
-    // Se llena el buffer con la informacion a enviar
+    for( int i = sizeof(MsgTX); i < BufferSize; i++ ) {
+        Buffer[i] = i - sizeof(MsgTX);
+    }
+    Radio->Send( Buffer, BufferSize );
+    Radio->Rx( RX_TIMEOUT_VALUE );
+    //dprintf("Enviando potencia prom: Pmean=%f", mean_power);
+    wait_ms( 4000 );
+
+    sprintf(valueStr,"%.2f",max_power);
+    strcpy(variable,"potencia_max");
+    //char MsgEnvio[64] = "";
+    strcpy(MsgTX, EUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppKey);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, DestEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, valueStr);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, variable);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, nombreDispoitivo);
+    memcpy(Buffer, MsgTX, sizeof(MsgTX));
+    for( int i = sizeof(MsgTX); i < BufferSize; i++ ) {
+        Buffer[i] = i - sizeof(MsgTX);
+    }
+    Radio->Send( Buffer, BufferSize );
+    Radio->Rx( RX_TIMEOUT_VALUE );
+    //dprintf("Enviando potencia max: Pmax=%f", max_power);
+    wait_ms( 3000 );
+
+    /*sprintf(valueStr,"%.2f",min_power);
+    strcpy(variable,"potencia_min");
+    //char MsgEnvio[64] = "";
+    strcpy(MsgTX, EUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppKey);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, DestEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, valueStr);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, variable);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, nombreDispoitivo);
+    memcpy(Buffer, MsgTX, sizeof(MsgTX));
     for( int i = sizeof(MsgTX); i < BufferSize; i++ ) {
         Buffer[i] = i - sizeof(MsgTX);
     }
-    //wait_ms( 100 );
+    Radio->Send( Buffer, BufferSize );
+    Radio->Rx( RX_TIMEOUT_VALUE );
+    //dprintf("Enviando potencia min: Pmin=%f", min_power);
+    wait_ms( 3000 );*/
+
+    max_power = 0.0;
+    min_power = 0.0;
+    max_inst_current = 0.0;
+    mean_current = 0.0;
+
+    sending_electric = false;
+    tick_current.attach(&readCurrent,5.0);
+}
+
+void readTemperature()
+{
+    tick_current.detach();
+    sending_temp = true;
+    meas_r2 = analog_value_temp.read(); // Read the analog input value (value from 0.0 to 1.0 = full ADC conversion range)
+    meas_v2 = meas_r2 * 3.3;
+    temperature = meas_v2 * 100.0;
+
+    char valueStr[]="";
+    sprintf(valueStr,"%.2f",temperature);
+    char variable[] = "temperatura";
+    strcpy(MsgTX, EUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppKey);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, DestEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, valueStr);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, variable);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, nombreDispoitivo);
+    memcpy(Buffer, MsgTX, sizeof(MsgTX));
+    for( int i = sizeof(MsgTX); i < BufferSize; i++ ) {
+        Buffer[i] = i - sizeof(MsgTX);
+    }
     Radio->Send( Buffer, BufferSize );
     Radio->Rx( RX_TIMEOUT_VALUE );
 
-    //wait(10);
+    //dprintf("Enviando temperatura: T=%f", temperature);
+    sending_temp = false;
+    tick_current.attach(&readCurrent,5.0);
 }
 
+void readGPS()
+{
+    tick_current.detach();
+    char valueStr[]="(,)";
+    
+    char variable[] = "(LAT,LONG)";
+    if(serRPi.readable()) {
+        serRPi.scanf("%s",&valueStr);
+        //sprintf(valueStr,"%s",serRPi.getc());
+    }
+    //dprintf("Enviando gps: [X,Y]=%s", valueStr);
+    
+    strcpy(MsgTX, EUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, AppKey);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, DestEUI);
+    strcat(MsgTX, "|");
+    strcat(MsgTX, valueStr);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, variable);
+    strcat(MsgTX, " ");
+    strcat(MsgTX, nombreDispoitivo);
+    //dprintf("Mensaje a enviar: %s", MsgTX);
+    memcpy(Buffer, MsgTX, sizeof(MsgTX));
+    for( int i = sizeof(MsgTX); i < BufferSize; i++ ) {
+        Buffer[i] = i - sizeof(MsgTX);
+    }
+    Radio->Send( Buffer, BufferSize );
+    Radio->Rx( RX_TIMEOUT_VALUE );
+    
+    tick_current.attach(&readCurrent,5.0);
+}
+
+
 void OnTxDone(void *radio, void *userThisPtr, void *userData)
 {
     Radio->Sleep( );
@@ -527,4 +750,15 @@
         dprintf("> OnRxError");
 }
 
+double filter2o(double u, double &v1, double &v2, const double a0, const double a1, const double a2, const double b0, const double b1, const double b2)
+{
+    //notch 60Hz a 12Hz Frecuencia de muestreo params: [num]/[den] = [ 0.99866961055330528, -1.9963536547718377,  0.99866961055330528]/[ 1,-1.9963536547718377,  0.99733922110661055]
+    double v = b0*u-b1*v1-b2*v2;
+    double y = a0*v+a1*v1+a2*v2;    //Forma directa II
+    v2=v1;
+    v1=v;
+    return y;
+
+}
+
 #endif
--- a/SX1276GenericPingPong/GenericPingPong.h	Wed Aug 08 22:33:19 2018 +0000
+++ b/SX1276GenericPingPong/GenericPingPong.h	Mon Oct 08 16:11:17 2018 +0000
@@ -33,8 +33,11 @@
  * Callback functions prototypes
  */
 char *splitOnPosition(char *msj, int pos);
-void onButtonEvent();
-void readAnalog();
+void readTemperature();
+void readCurrent();
+void sendElectric();
+void readGPS();
+double filter2o(double u, double &v1, double &v2, const double a0, const double a1, const double a2, const double b0, const double b1, const double b2);
 /*!
  * @brief Function to be executed on Radio Tx Done event
  */
--- a/main.cpp	Wed Aug 08 22:33:19 2018 +0000
+++ b/main.cpp	Mon Oct 08 16:11:17 2018 +0000
@@ -17,7 +17,7 @@
     ser->baud(115200);
     ser->format(8);
     myled = 1;
-    btn.fall(&onButtonEvent);
+    //btn.fall(&onButtonEvent);
     SX1276PingPong();
 }