EIoT LoRa node 3 - Working ok
Dependencies: BufferedSerial SX1276GenericLib-node1 mbed
Fork of DISCO-L072CZ-LRWAN1_LoRa_node by
Revision 13:671d602e700e, committed 2018-10-08
- Comitter:
- sagilar
- Date:
- Mon Oct 08 16:11:17 2018 +0000
- Parent:
- 12:a6a37ba1feff
- Commit message:
- EIoT LoRa node 3
Changed in this revision
--- /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(); }