commit 580615d21f32a0392bead1a38cdadc992d54bdf7 Author: Gabriel Date: Tue May 7 16:09:05 2024 +0200 first commit diff --git a/config.h b/config.h new file mode 100644 index 0000000..610d889 --- /dev/null +++ b/config.h @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------------------------- + ACTIVATION_MODE | ABP or OTAA | # Selection of Activation Method | + SEND_BY_PUSH_BUTTON | true or false | # Sending method (Time or Push Button) | + FRAME_DELAY | Time in ms | # Time between 2 frames (Minimum 7000) | + SPREADING_FACTOR | Number [7;12] | # 7=SF7, 8=SF8, ..., 12=SF12 | + ADAPTIVE_DR | true or false | # Enable Aaptive Data Rate (if true) | + CONFIRMED | true or false | # Frame Confirmed (if true) OR Frame Unconfirmed (if false) | + PORT | Number [0;199] | # Application Port number | + ENABLE_HUMIDITY | true or false | # Enable Humidity Sensor (if true) | + CAYENNE_LPP | true or false | # Enable all sensor and use the CAYENNE LPP format (if true) | + LOW_POWER | true or false | # Enable Low Power mode between two frames (if true) | +---------------------------------------------------------------------------------------------------------------*/ +#define OTAA 0 +#define ABP 1 + + +#define ACTIVATION_MODE OTAA +#define SEND_BY_PUSH_BUTTON false +#define FRAME_DELAY 30000 +#define SPREADING_FACTOR 7 +#define ADAPTIVE_DR false +#define CONFIRMED false +#define PORT 1 +#define ENABLE_HUMIDITY true +#define CAYENNE_LPP true +#define LOW_POWER true + + +// Configuration for ABP Activation Mode +const char devAddr[] = "260BAEF0"; +const char nwkSKey[] = "64E37DA93380811D762C430422590DA6"; +const char appSKey[] = "6CF72CC2B4835C369E6425C049878184"; + + +// Configuration for OTAA Activation Mode +const char appKey[] = "00AA2A215A86B625F343FA6127CB586A"; +const char appEUI[] = "0000000000000000"; \ No newline at end of file diff --git a/lorawanApp.ino b/lorawanApp.ino new file mode 100644 index 0000000..fb00952 --- /dev/null +++ b/lorawanApp.ino @@ -0,0 +1,265 @@ +#include "LoRaWANNode.h" +#include "STM32LowPower.h" +#include "config.h" + +#if ENABLE_HUMIDITY == true || CAYENNE_LPP == true + #include + #include + #include + #include + #include + #define I2C2_SCL D15//PB10 + #define I2C2_SDA D14//PB11 + TwoWire *dev_i2c; + HTS221Sensor *HumTemp; + LPS22HBSensor *PressTemp; + LSM303AGR_ACC_Sensor *Acc; + LSM303AGR_MAG_Sensor *Mag; + // Read humidity, pressure, temperature from LPS22HB, temperature from HTS221 + float pressure, humidity, temperatureFromHTS221, temperatureFromLPS22HB, temperatureFromLSM303AGR; + int32_t accelerometer[3]; + int32_t magnetometer[3]; + int8_t humidityLora =0; + CayenneLPP lpp(51); +#endif + + +HardwareSerial SerialLora(D0, D1); // D0(Rx) D1(TX) +HardwareSerial Serial1(PA10, PA9); + +const int PUSHBUTTON = 2; + +char frameTx[] = "Hello"; +String str; + + +void setup() +{ + Serial1.begin(115200); +#if LOW_POWER == true + LowPower.begin(); +#endif + +#if ENABLE_HUMIDITY == true || CAYENNE_LPP == true + lpp.reset(); // Initialise CAYENNE + dev_i2c = new TwoWire(I2C2_SDA, I2C2_SCL); + dev_i2c->begin(); + HumTemp = new HTS221Sensor (dev_i2c); + HumTemp->Enable(); + PressTemp = new LPS22HBSensor(dev_i2c); + PressTemp->Enable(); + Acc = new LSM303AGR_ACC_Sensor(dev_i2c); + Acc->Enable(); + Acc->EnableTemperatureSensor(); + Mag = new LSM303AGR_MAG_Sensor(dev_i2c); + Mag->Enable(); +#endif + + pinMode(PUSHBUTTON, INPUT); + showConfig(); + infoBeforeActivation(); + if (ACTIVATION_MODE == ABP) activationABP(); + if (ACTIVATION_MODE == OTAA) activationOTAA(); + infoAfterActivation(); +} + +void loop() +{ + if( SEND_BY_PUSH_BUTTON == 1) while(digitalRead(PUSHBUTTON)); // Attente Push Button pour envoyer + else delay((FRAME_DELAY<7000)?0:FRAME_DELAY-7000); // Attente FRAME_DELAY pour envoyer + +#if ENABLE_HUMIDITY == true || CAYENNE_LPP == true + HumTemp->GetHumidity(&humidity); + HumTemp->GetTemperature(&temperatureFromHTS221); + PressTemp->GetPressure(&pressure); + PressTemp->GetTemperature(&temperatureFromLPS22HB); + Acc->GetAxes(accelerometer); + Acc->GetTemperature(&temperatureFromLSM303AGR); + Mag->GetAxes(magnetometer); + lpp.reset(); + + // Channel 1 : Data from HTS221 (Humidity sensor) + lpp.addRelativeHumidity(1, humidity); + lpp.addTemperature(1, temperatureFromHTS221); + + // Channel 2 : Data from LPS22HB (Pressure sensor) + lpp.addBarometricPressure(2, pressure); + lpp.addTemperature(2, temperatureFromLPS22HB); + + // Channel 3 : Data from LSM303AGR (accelerometer/magnetometer/gyroscope) + lpp.addAccelerometer(3, (float)accelerometer[0]/1000, (float)accelerometer[1]/1000, (float)accelerometer[2]/1000); + lpp.addTemperature(2, temperatureFromLSM303AGR); +#endif + + transmit(); + receive(); + +#if LOW_POWER == true + Serial1.print(" Processor and LoRaWAN module go to sleep during "); + Serial1.print(FRAME_DELAY); + Serial1.println(" ms"); + delay(500); + loraNode.sleep(); + LowPower.deepSleep(FRAME_DELAY); + loraNode.wakeup(); + Serial1.println(" Processor and LoRaWAN module wake up !!!!\r\n"); +#endif + +} + +void receive(void) { + uint8_t frameRx[64]; + uint8_t len; + uint8_t port; + + if(loraNode.receiveFrame(frameRx, &len, &port)) { + uint8_t n = 0; + Serial1.print(" Frame received: "); + while(len > 0) { + Serial1.print(frameRx[n], HEX); + Serial1.print("(Hexa) "); + Serial1.print(frameRx[n]); + Serial1.print("(Dec), "); + len--; + n++; + } + Serial1.print(" on port "); Serial1.println(port);Serial1.print("\r\n"); + } else { + Serial1.println(" No data received\r\n\r\n"); + } +} + +void transmit(void) { + int status; + + if(CONFIRMED) Serial1.print(" Uplink CONFIRMED on PORT "); + else Serial1.print(" Uplink UNCONFIRMED on PORT "); + Serial1.println(PORT); + +#if ((ENABLE_HUMIDITY == false) && (CAYENNE_LPP == false)) + Serial1.print(" Sending Text : ");Serial1.print(frameTx);Serial1.print("\r\n"); + status = loraNode.sendFrame(frameTx, sizeof(frameTx), CONFIRMED, PORT); + +#elif ((ENABLE_HUMIDITY == true) && (CAYENNE_LPP == false)) + humidityLora = (uint8_t)humidity; +// Serial1.print(" Sending humidity(%) : ");Serial1.print(humidityLora);Serial1.print("\r\n"); +// status = loraNode.sendFrame((char*)&humidityLora, 1, CONFIRMED); + + char trame[3]; + unsigned char ent, dec; + ent = temperatureFromHTS221; + dec = (temperatureFromHTS221 - ent) * 100; + trame[0] = humidityLora; + trame[1] = ent; + trame[2] = dec; + //int len = sprintf(trame, "%d.%d", ent, dec); + Serial1.print(" Sending humidity(%) : ");Serial1.print(humidityLora);Serial1.print("\r\n"); + Serial1.print(" Sending temperature(°C) : ");Serial1.print(temperatureFromHTS221);Serial1.print("\r\n"); + status = loraNode.sendFrame(trame, 3, CONFIRMED); + +#else + Serial1.println(" Sending all sensor data with CAYENNE LPP (Low Power Payload) "); + status = loraNode.sendFrame((char*)lpp.getBuffer(), lpp.getSize(), CONFIRMED); +#endif + + + if(status == LORA_SEND_ERROR) { + Serial1.println(" Send frame failed!!!"); + } else if(status == LORA_SEND_DELAYED) { + Serial1.println(" Module is busy : \r\n * It's still trying to send data \r\n OR * \r\n * You are over your allowed duty cycle"); + } else { + Serial1.println(" Waiting for Downlink..."); + } +} + + +void showConfig(void){ + Serial1.println("\r\n\r\n\r\n"); + Serial1.println("#######################################"); + Serial1.println("#### LoRaWAN Training Session #########"); + Serial1.println("#####Savoie Mont Blanc University #####\r\n"); + + if(ACTIVATION_MODE == OTAA) {Serial1.println(" * Activation Mode : OTAA");} + else {Serial1.println(" * Activation Mode : ABP");} + + if(SEND_BY_PUSH_BUTTON == true) {Serial1.println(" * Send Frame with Push Button");} + else {Serial1.print(" * Send Frame every ");Serial1.print((FRAME_DELAY<7000)?7000:FRAME_DELAY);Serial1.println("ms");} + + Serial1.print(" * Spreading Factor : SF");Serial1.print(SPREADING_FACTOR);Serial1.print("\r\n"); + + if(ADAPTIVE_DR == true) {Serial1.println(" * Adaptive Data Rate : ON");} + else {Serial1.println(" * Adaptive Data Rate : OFF");} + + if(CONFIRMED == true) {Serial1.println(" * Frame Confirmed");} + else {Serial1.println(" * Frame Unconfirmed");} + + Serial1.print(" * Application PORT Number : ");Serial1.print(PORT);Serial1.print("\r\n"); + + if ( ENABLE_HUMIDITY == false && CAYENNE_LPP == false) { Serial1.print(" * Payload is Text : "); Serial1.println(frameTx);} + else if ( ENABLE_HUMIDITY == true && CAYENNE_LPP == false) { Serial1.println(" * Payload is 1 byte : Humidity sensor");} + else { Serial1.println(" * Payload : All Sensors with CAYENNE LPP Format");} + + if(LOW_POWER == true) {Serial1.println(" * Low Power Mode : ON\r\n");} + else {Serial1.println(" * Low Power Mode : OFF\r\n");} +} + +void infoAfterActivation(void){ + if(SEND_BY_PUSH_BUTTON == 0){ + Serial1.print(" Frame will be sent every ");Serial1.print((FRAME_DELAY<7000)?7000:FRAME_DELAY);Serial1.println("ms\r\n"); + } + else { + Serial1.println(" Press Blue Button to send a Frame\r\n"); + } + +} + + +void infoBeforeActivation(void){ + while(!loraNode.begin(&SerialLora, LORA_BAND_EU_868)) { + Serial1.println("Lora module not ready"); + delay(1000); + } + loraNode.setDutyCycle(DISABLE); + + if (ACTIVATION_MODE == ABP) { + Serial1.print(" * Device Address : 0x "); + Serial1.println(devAddr); + Serial1.print(" * Network Session Key : 0x "); + Serial1.println(nwkSKey); + Serial1.print(" * Application Session Key : 0x "); + Serial1.println(appSKey);Serial1.print("\r\n"); + } + + if (ACTIVATION_MODE == OTAA){ + str = " * Device EUI : 0x "; + loraNode.getDevEUI(&str); + Serial1.println(str); + Serial1.print(" * Application key : 0x "); + Serial1.println(appKey); + Serial1.print(" * Application EUI : 0x "); + Serial1.println(appEUI);Serial1.print("\r\n"); + } + + loraNode.setAdaptativeDataRate(DISABLE); + loraNode.setDataRate(12-SPREADING_FACTOR); + if(ADAPTIVE_DR) loraNode.setAdaptativeDataRate(ENABLE); + loraNode.setDutyCycle(DISABLE); +} + + +void activationABP(void){ + while(!loraNode.joinABP(devAddr, nwkSKey, appSKey)) { + Serial1.println(" The Device is not activated on the Server!!"); + delay(1000); + } +} + +void activationOTAA(void){ + Serial1.println(" JOIN procedure in progress ..."); + + while(!loraNode.joinOTAA(appKey, appEUI)) { + Serial1.println(" JOIN OTAA failed!!! Retry..."); + delay(1000); + } + Serial1.println(" JOIN procedure : SUCCESS !\r\n"); +} \ No newline at end of file