LoRaWAN smart agriculture application using FRDM-K64F ARM mbed board along with SX1272MB2xAS LoRa shield as the LoRa Node.
Dependencies: DHT11 LMiC SX1272Lib mbed
Fork of LoRaWAN-lmic-app by
main.cpp@6:3758685f4b75, 2018-04-02 (annotated)
- Committer:
- GTsapparellas
- Date:
- Mon Apr 02 12:16:01 2018 +0000
- Revision:
- 6:3758685f4b75
- Parent:
- 5:1b2fcc2582e8
- Child:
- 7:8ffc2f64b0f8
LoRaWAN smart agriculture application using FRDM-K64F ARM mbed board along with SX1272MB2xAS LoRa shield as the LoRa Node.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
GTsapparellas | 6:3758685f4b75 | 1 | /******************************************************************************* |
GTsapparellas | 6:3758685f4b75 | 2 | * Internet of Things (IoT) smart monitoring |
GTsapparellas | 6:3758685f4b75 | 3 | * device for agriculture using LoRaWAN technology. |
GTsapparellas | 6:3758685f4b75 | 4 | * |
GTsapparellas | 6:3758685f4b75 | 5 | * LoRa Gateway: Single-channel Dragino LG01-P LoRa Gateway |
GTsapparellas | 6:3758685f4b75 | 6 | * |
GTsapparellas | 6:3758685f4b75 | 7 | * Measurement parameters: Temperature (Celcius) |
GTsapparellas | 6:3758685f4b75 | 8 | * Humidity (Relative Humidity %) |
GTsapparellas | 6:3758685f4b75 | 9 | * Light Intenisty (Volts) |
GTsapparellas | 6:3758685f4b75 | 10 | * Soil Moisture (Volts) |
GTsapparellas | 6:3758685f4b75 | 11 | * |
GTsapparellas | 6:3758685f4b75 | 12 | * Evaluation board: FRDM-K64F ARM mbed board |
GTsapparellas | 6:3758685f4b75 | 13 | * |
GTsapparellas | 6:3758685f4b75 | 14 | * LoRa shield: Semtech SX1272MB2xAS |
GTsapparellas | 6:3758685f4b75 | 15 | * |
GTsapparellas | 6:3758685f4b75 | 16 | * IoT Cloud Server: The Things Network (Europe EU-868.1 frequency band) |
GTsapparellas | 6:3758685f4b75 | 17 | * |
GTsapparellas | 6:3758685f4b75 | 18 | * API Platform: All Things Talk Maker |
GTsapparellas | 6:3758685f4b75 | 19 | * |
GTsapparellas | 6:3758685f4b75 | 20 | * - Time-triggered program periodically sends playload data (including |
GTsapparellas | 6:3758685f4b75 | 21 | * temperature, humidity, light intensity and soil moisture sensor parameters) |
GTsapparellas | 6:3758685f4b75 | 22 | * by using FRDM-K64F ARM mbed board and Semtech SX1272MB2xAS as the LoRa Node. |
GTsapparellas | 6:3758685f4b75 | 23 | * |
GTsapparellas | 6:3758685f4b75 | 24 | * - DHT library and Digital Input pin used for the successful measurement |
GTsapparellas | 6:3758685f4b75 | 25 | * of temperature and humidity sensor parameters. |
GTsapparellas | 6:3758685f4b75 | 26 | * |
GTsapparellas | 6:3758685f4b75 | 27 | * - Analog Input pins used for the successful employement of soil moisture and |
GTsapparellas | 6:3758685f4b75 | 28 | * light intensity sensor parameters. |
GTsapparellas | 6:3758685f4b75 | 29 | * |
GTsapparellas | 6:3758685f4b75 | 30 | * - Semtech's SX1272Lib used for the successful configuration and set up of |
GTsapparellas | 6:3758685f4b75 | 31 | * of SX1272MB2xAS LoRa shield. |
GTsapparellas | 6:3758685f4b75 | 32 | * |
GTsapparellas | 6:3758685f4b75 | 33 | * - IBM's LMiC library used for the successful implementation of LoRa modulation. |
GTsapparellas | 6:3758685f4b75 | 34 | * |
GTsapparellas | 6:3758685f4b75 | 35 | * - LoRa Node transmitting playload data directly to the single-channel Dragino |
GTsapparellas | 6:3758685f4b75 | 36 | * LG01-P LoRa Gateway which is connected to The Things Network Cloud Server. |
GTsapparellas | 6:3758685f4b75 | 37 | * |
GTsapparellas | 6:3758685f4b75 | 38 | * - ABP (Activation By Personalization) selected as the activation method over |
GTsapparellas | 6:3758685f4b75 | 39 | * The Things Network Cloud Server. |
GTsapparellas | 6:3758685f4b75 | 40 | * |
GTsapparellas | 6:3758685f4b75 | 41 | * - The Things Network Cloud Server makes playload data available online. |
GTsapparellas | 6:3758685f4b75 | 42 | * |
GTsapparellas | 6:3758685f4b75 | 43 | * - Through required integration, The Things Network Cloud Server passes |
GTsapparellas | 6:3758685f4b75 | 44 | * playload data to All Things Talk Maker API which visualizes the data in |
GTsapparellas | 6:3758685f4b75 | 45 | * a meaningful way for end-user's reference. |
GTsapparellas | 6:3758685f4b75 | 46 | * |
GTsapparellas | 6:3758685f4b75 | 47 | * @Author: Giorgos Tsapparellas |
GTsapparellas | 6:3758685f4b75 | 48 | * @Revisions: |
GTsapparellas | 6:3758685f4b75 | 49 | * v0.1 -- sensors gathering on FRDM-K64F |
GTsapparellas | 6:3758685f4b75 | 50 | * v0.2 -- attach sx1272 and take as a transmitter |
GTsapparellas | 6:3758685f4b75 | 51 | * v0.3 -- |
GTsapparellas | 6:3758685f4b75 | 52 | * |
GTsapparellas | 6:3758685f4b75 | 53 | * Porgram available at: 1) GITHUB LINK |
GTsapparellas | 6:3758685f4b75 | 54 | * 2) MBED LINK |
GTsapparellas | 6:3758685f4b75 | 55 | * |
GTsapparellas | 6:3758685f4b75 | 56 | * SEE readME file for instructions of how to compile and run the program. |
GTsapparellas | 6:3758685f4b75 | 57 | * |
GTsapparellas | 6:3758685f4b75 | 58 | *******************************************************************************/ |
GTsapparellas | 6:3758685f4b75 | 59 | // ADD revisions and links above |
GTsapparellas | 6:3758685f4b75 | 60 | // ADD IFDEF, AND events, comments |
GTsapparellas | 6:3758685f4b75 | 61 | // ADD LED FLASHING |
GTsapparellas | 6:3758685f4b75 | 62 | // BUTTON PRESSED-RESET SEND A LORA PACKET |
GTsapparellas | 6:3758685f4b75 | 63 | // ADD to git hub as well |
GTsapparellas | 6:3758685f4b75 | 64 | // TEST THE CODE IF OK |
mluis | 1:60184eda0066 | 65 | |
GTsapparellas | 6:3758685f4b75 | 66 | #include <mbed.h> |
GTsapparellas | 6:3758685f4b75 | 67 | #include <lmic.h> |
GTsapparellas | 6:3758685f4b75 | 68 | #include <hal.h> |
GTsapparellas | 6:3758685f4b75 | 69 | #include <SPI.h> |
GTsapparellas | 6:3758685f4b75 | 70 | #include <DHT.h> |
GTsapparellas | 6:3758685f4b75 | 71 | #include <debug.h> |
mluis | 0:a2929fa6e4f0 | 72 | |
GTsapparellas | 6:3758685f4b75 | 73 | /////////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 74 | // DEFINITION DECLARATIONS // |
GTsapparellas | 6:3758685f4b75 | 75 | ///////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 76 | |
GTsapparellas | 6:3758685f4b75 | 77 | #define SINGLE_CHANNEL_GATEWAY // Force it to use 868.1 MHz frequency band only due to Dragino LG01-P LoRa Gateway hardware limitation. |
GTsapparellas | 6:3758685f4b75 | 78 | #define TRANSMIT_INTERVAL 1800 // Transmit interval in seconds, too often may get traffic ignored. |
GTsapparellas | 6:3758685f4b75 | 79 | #define DEBUG_LEVEL 0 // Set debug level to 1 for outputting messages to the UART Terminal (e.g. Tera Term). |
GTsapparellas | 6:3758685f4b75 | 80 | #define ACTIVATION_METHOD 0 // Set activation method to 0 for ABP (Activation By Personalization) |
GTsapparellas | 6:3758685f4b75 | 81 | // Set activation method to 1 for OTAA (Over The Air Activation) |
mluis | 0:a2929fa6e4f0 | 82 | |
GTsapparellas | 6:3758685f4b75 | 83 | /////////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 84 | // GLOBAL VARIABLES DECLARATIONS // |
GTsapparellas | 6:3758685f4b75 | 85 | ///////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 86 | |
GTsapparellas | 6:3758685f4b75 | 87 | // Transmit interval in seconds. |
GTsapparellas | 6:3758685f4b75 | 88 | uint16_t transmit_interval = TRANSMIT_INTERVAL; |
mluis | 1:60184eda0066 | 89 | |
GTsapparellas | 6:3758685f4b75 | 90 | // Playload frame length of size 8. |
GTsapparellas | 6:3758685f4b75 | 91 | uint8_t LMIC_FRAME_LENGTH = 8; |
GTsapparellas | 6:3758685f4b75 | 92 | |
GTsapparellas | 6:3758685f4b75 | 93 | #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. |
mluis | 1:60184eda0066 | 94 | |
GTsapparellas | 6:3758685f4b75 | 95 | // LoRaWAN Application identifier (AppEUI) associated with The Things Network Cloud Server. |
GTsapparellas | 6:3758685f4b75 | 96 | static const u1_t APPEUI[8] = { 0x70, 0xB3, 0xD5, 0x7E, 0xD0, 0x00, 0xA4, 0x54 }; |
GTsapparellas | 6:3758685f4b75 | 97 | |
GTsapparellas | 6:3758685f4b75 | 98 | // LoRaWAN unique device ID (DevEUI) associated with The Things Network Cloud Server. |
GTsapparellas | 6:3758685f4b75 | 99 | static const u1_t DEVEUI[8] = { 0x00, 0x1D, 0x45, 0x32, 0xEC, 0xA8, 0x01, 0x59 }; |
mluis | 1:60184eda0066 | 100 | |
mluis | 1:60184eda0066 | 101 | #endif |
mluis | 1:60184eda0066 | 102 | |
GTsapparellas | 6:3758685f4b75 | 103 | // Acquired activation method |
GTsapparellas | 6:3758685f4b75 | 104 | #if ACTIVATION_METHOD == 0 // if ABP (Activation By Personalization) is applied. |
mluis | 1:60184eda0066 | 105 | |
GTsapparellas | 6:3758685f4b75 | 106 | // LoRaWAN network session key (NwkSKey) associated with The Things Network Cloud Server. |
GTsapparellas | 6:3758685f4b75 | 107 | static const u1_t NWKSKEY[16] = { 0xDF, 0x9B, 0xB1, 0x30, 0xE8, 0x33, 0x42, 0x76, 0x33, 0x0C, 0x88, 0xBB, 0x30, 0xE2, 0xC2, 0xE9 }; |
mluis | 1:60184eda0066 | 108 | |
GTsapparellas | 6:3758685f4b75 | 109 | // LoRaWAN application session key (AppSKey) associated with The Things Network Cloud Server. |
GTsapparellas | 6:3758685f4b75 | 110 | static const u1_t APPSKEY[16] = { 0xE0, 0x52, 0x18, 0x15, 0x0B, 0xE1, 0xEF, 0x1F, 0xAF, 0x8C, 0x8A, 0x31, 0x09, 0xB9, 0xAB, 0x9C }; |
mluis | 1:60184eda0066 | 111 | |
GTsapparellas | 6:3758685f4b75 | 112 | // LoRaWAN end-device address (DevAddr) associated with The Things Network Cloud Server. |
GTsapparellas | 6:3758685f4b75 | 113 | static const u4_t DEVADDR = 0x26011B39 ; |
mluis | 1:60184eda0066 | 114 | |
mluis | 1:60184eda0066 | 115 | #endif |
mluis | 0:a2929fa6e4f0 | 116 | |
GTsapparellas | 6:3758685f4b75 | 117 | /*On board's LEDs Declaration |
GTsapparellas | 6:3758685f4b75 | 118 | DigitalOut RED_LED(PTB22); // PTB22 = Red pin -- Indicates an error occur |
GTsapparellas | 6:3758685f4b75 | 119 | DigitalOut GREEN_LED(PTE26); // PTE26 = Green pin -- Indicates transmission is in progress |
GTsapparellas | 6:3758685f4b75 | 120 | DigitalOut BLUE_LED(PTB21); // PTB21 = Blue pin -- Indicates MCU is sleeping |
GTsapparellas | 6:3758685f4b75 | 121 | */ |
GTsapparellas | 6:3758685f4b75 | 122 | |
GTsapparellas | 6:3758685f4b75 | 123 | // Digital Input pin of temperature and humidity sensor set to D6. |
GTsapparellas | 6:3758685f4b75 | 124 | DHT sensorTempHum(D6, DHT11); |
GTsapparellas | 6:3758685f4b75 | 125 | |
GTsapparellas | 6:3758685f4b75 | 126 | // Analog Input pin of light intensity sensor set to A1. |
GTsapparellas | 6:3758685f4b75 | 127 | AnalogIn sensorLight(A1); |
GTsapparellas | 6:3758685f4b75 | 128 | |
GTsapparellas | 6:3758685f4b75 | 129 | // Analog Input pin of soil moisture sensor set to A3. |
GTsapparellas | 6:3758685f4b75 | 130 | AnalogIn sensorSoilMoisture(A3); |
mluis | 0:a2929fa6e4f0 | 131 | |
GTsapparellas | 6:3758685f4b75 | 132 | /////////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 133 | // LOCAL FUNCTIONS DECLARATIONS // |
GTsapparellas | 6:3758685f4b75 | 134 | ///////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 135 | |
GTsapparellas | 6:3758685f4b75 | 136 | /* |
GTsapparellas | 6:3758685f4b75 | 137 | * getTemperatureHumidity function of type void. |
GTsapparellas | 6:3758685f4b75 | 138 | * |
GTsapparellas | 6:3758685f4b75 | 139 | * Gets temperature (celcius) and humidity (relative humidity %) |
GTsapparellas | 6:3758685f4b75 | 140 | * measurements using DHT library. Otherwise, print an error. |
GTsapparellas | 6:3758685f4b75 | 141 | * |
GTsapparellas | 6:3758685f4b75 | 142 | * Input parameters: float temperature |
GTsapparellas | 6:3758685f4b75 | 143 | * float humidity |
GTsapparellas | 6:3758685f4b75 | 144 | * |
GTsapparellas | 6:3758685f4b75 | 145 | */ |
GTsapparellas | 6:3758685f4b75 | 146 | void getTemperatureHumidity(float& temperature, float& humidity) { |
mluis | 0:a2929fa6e4f0 | 147 | |
GTsapparellas | 6:3758685f4b75 | 148 | // Set err variable to 0 (none). |
GTsapparellas | 6:3758685f4b75 | 149 | uint8_t err = ERROR_NONE; |
GTsapparellas | 6:3758685f4b75 | 150 | // Set humidity variable to 0. |
GTsapparellas | 6:3758685f4b75 | 151 | humidity = 0.0f; |
GTsapparellas | 6:3758685f4b75 | 152 | // Set temperature variable to 0. |
GTsapparellas | 6:3758685f4b75 | 153 | temperature = 0.0f; |
GTsapparellas | 6:3758685f4b75 | 154 | |
GTsapparellas | 6:3758685f4b75 | 155 | // Store sensor data (40 bits(16-bit temperature, 16-bit humidity and 8-bit |
GTsapparellas | 6:3758685f4b75 | 156 | // CRC checksum)) into err variable. |
GTsapparellas | 6:3758685f4b75 | 157 | err = sensorTempHum.readData(); |
GTsapparellas | 6:3758685f4b75 | 158 | |
GTsapparellas | 6:3758685f4b75 | 159 | if (err == ERROR_NONE) // if err equals to 0. |
GTsapparellas | 6:3758685f4b75 | 160 | { |
GTsapparellas | 6:3758685f4b75 | 161 | // Store float temperature value in celcius. |
GTsapparellas | 6:3758685f4b75 | 162 | temperature = sensorTempHum.ReadTemperature(CELCIUS); |
GTsapparellas | 6:3758685f4b75 | 163 | // Store float humidity value. |
GTsapparellas | 6:3758685f4b75 | 164 | humidity = sensorTempHum.ReadHumidity(); |
GTsapparellas | 6:3758685f4b75 | 165 | |
GTsapparellas | 6:3758685f4b75 | 166 | // Output temperature and humidity values on UART Terminal |
GTsapparellas | 6:3758685f4b75 | 167 | #if DEBUG_LEVEL == 1 |
GTsapparellas | 6:3758685f4b75 | 168 | printf("Temperature: %4.2f Celsius \r\n", temperature); |
GTsapparellas | 6:3758685f4b75 | 169 | printf("Humidity: %4.2f % Relative Humidity \r\n", humidity); |
GTsapparellas | 6:3758685f4b75 | 170 | #endif |
GTsapparellas | 6:3758685f4b75 | 171 | } |
GTsapparellas | 6:3758685f4b75 | 172 | else // if err occurs. |
GTsapparellas | 6:3758685f4b75 | 173 | { |
GTsapparellas | 6:3758685f4b75 | 174 | // Output error message on UART Terminal and flash the RED LED. |
GTsapparellas | 6:3758685f4b75 | 175 | #if DEBUG_LEVEL == 1 |
GTsapparellas | 6:3758685f4b75 | 176 | printf("Error: %d\r\n", err); |
GTsapparellas | 6:3758685f4b75 | 177 | //RED_LED = !RED_LED; |
GTsapparellas | 6:3758685f4b75 | 178 | #endif |
GTsapparellas | 6:3758685f4b75 | 179 | } |
GTsapparellas | 6:3758685f4b75 | 180 | }// end of getTemperatureHumidity function. |
mluis | 0:a2929fa6e4f0 | 181 | |
GTsapparellas | 6:3758685f4b75 | 182 | /* |
GTsapparellas | 6:3758685f4b75 | 183 | * getLightIntensity function of type void. |
GTsapparellas | 6:3758685f4b75 | 184 | * |
GTsapparellas | 6:3758685f4b75 | 185 | * Gets the light's intensity analogue value at first instance |
GTsapparellas | 6:3758685f4b75 | 186 | * and then converts it using 16-bit ADC converter into voltage |
GTsapparellas | 6:3758685f4b75 | 187 | * counting from 0.0 to 5.0. |
GTsapparellas | 6:3758685f4b75 | 188 | * |
GTsapparellas | 6:3758685f4b75 | 189 | * Input parameters: float lightIntensityVoltage |
GTsapparellas | 6:3758685f4b75 | 190 | * |
GTsapparellas | 6:3758685f4b75 | 191 | */ |
GTsapparellas | 6:3758685f4b75 | 192 | void getLightIntensity(float& lightIntensityVoltage) { |
GTsapparellas | 6:3758685f4b75 | 193 | |
GTsapparellas | 6:3758685f4b75 | 194 | // Set light intensity voltage variable to 0. |
GTsapparellas | 6:3758685f4b75 | 195 | lightIntensityVoltage = 0.0f; |
GTsapparellas | 6:3758685f4b75 | 196 | // Set light intensity analogue value to 0. |
GTsapparellas | 6:3758685f4b75 | 197 | uint16_t lightIntensityAnalogue = 0; |
GTsapparellas | 6:3758685f4b75 | 198 | |
GTsapparellas | 6:3758685f4b75 | 199 | // Read light intensity 16-bit analogue value. |
GTsapparellas | 6:3758685f4b75 | 200 | lightIntensityAnalogue = sensorLight.read_u16(); |
GTsapparellas | 6:3758685f4b75 | 201 | //Convert the light intensity analog reading (which goes from 0 - 65536) to a voltage (0 - 5V). |
GTsapparellas | 6:3758685f4b75 | 202 | lightIntensityVoltage = (float) lightIntensityAnalogue*(5.0/65536.0); |
GTsapparellas | 6:3758685f4b75 | 203 | |
GTsapparellas | 6:3758685f4b75 | 204 | // Output light intensity voltage as well as resistance value on UART Terminal. |
GTsapparellas | 6:3758685f4b75 | 205 | #if DEBUG_LEVEL == 1 |
GTsapparellas | 6:3758685f4b75 | 206 | float resistance = 0.0f; |
GTsapparellas | 6:3758685f4b75 | 207 | // Groove's calculation for resistance value. |
GTsapparellas | 6:3758685f4b75 | 208 | resistance = (float)(65536-lightIntensityAnalogue)*10/lightIntensityAnalogue; |
GTsapparellas | 6:3758685f4b75 | 209 | printf("Light Intensity: %2.2f Volts -- ", lightIntensityVoltage); |
GTsapparellas | 6:3758685f4b75 | 210 | printf("Resistance: %2.2f Kiloohm \r\n", resistance); |
GTsapparellas | 6:3758685f4b75 | 211 | #endif |
GTsapparellas | 6:3758685f4b75 | 212 | }// end of getLightIntensity function. |
mluis | 0:a2929fa6e4f0 | 213 | |
GTsapparellas | 6:3758685f4b75 | 214 | /* |
GTsapparellas | 6:3758685f4b75 | 215 | * getSoilMoisture function of type void. |
GTsapparellas | 6:3758685f4b75 | 216 | * |
GTsapparellas | 6:3758685f4b75 | 217 | * Gets the soil's moisture analogue value at first instance |
GTsapparellas | 6:3758685f4b75 | 218 | * and then converts it using 16-bit ADC converter into voltage |
GTsapparellas | 6:3758685f4b75 | 219 | * counting from 0.0 to 5.0. |
GTsapparellas | 6:3758685f4b75 | 220 | * |
GTsapparellas | 6:3758685f4b75 | 221 | * Input parameters: float lightOutputVoltage |
mluis | 1:60184eda0066 | 222 | * |
GTsapparellas | 6:3758685f4b75 | 223 | */ |
GTsapparellas | 6:3758685f4b75 | 224 | void getSoilMoisture(float& soilMoistureVoltage) { |
GTsapparellas | 6:3758685f4b75 | 225 | |
GTsapparellas | 6:3758685f4b75 | 226 | // Set soil moisture voltage variable to 0. |
GTsapparellas | 6:3758685f4b75 | 227 | soilMoistureVoltage = 0.0f; |
GTsapparellas | 6:3758685f4b75 | 228 | // Set soil moisture analogue value to 0. |
GTsapparellas | 6:3758685f4b75 | 229 | uint16_t soilMoistureAnalogue = 0; |
GTsapparellas | 6:3758685f4b75 | 230 | |
GTsapparellas | 6:3758685f4b75 | 231 | // Read soil moisture 16-bit analogue value. |
GTsapparellas | 6:3758685f4b75 | 232 | soilMoistureAnalogue = sensorSoilMoisture.read_u16(); |
GTsapparellas | 6:3758685f4b75 | 233 | //Convert the soil moisture analog reading (which goes from 0 - 65536) to a voltage (0 - 5V). |
GTsapparellas | 6:3758685f4b75 | 234 | soilMoistureVoltage = (float) soilMoistureAnalogue*(5.0/65536.0); |
GTsapparellas | 6:3758685f4b75 | 235 | |
GTsapparellas | 6:3758685f4b75 | 236 | // Output soil moisture voltage as well as soil moisture analogue value on UART Terminal. |
GTsapparellas | 6:3758685f4b75 | 237 | #if DEBUG_LEVEL == 1 |
GTsapparellas | 6:3758685f4b75 | 238 | printf("Soil Moisture: %2.2f Volts -- ", soilMoistureVoltage); |
GTsapparellas | 6:3758685f4b75 | 239 | printf("Analogue Value: %d \r\n", soilMoistureAnalogue); |
GTsapparellas | 6:3758685f4b75 | 240 | #endif |
GTsapparellas | 6:3758685f4b75 | 241 | }// end of getSoilMoisture function. |
mluis | 1:60184eda0066 | 242 | |
GTsapparellas | 6:3758685f4b75 | 243 | /////////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 244 | // LMiC APPLICATION CALLBACKS // |
GTsapparellas | 6:3758685f4b75 | 245 | ///////////////////////////////////////////////// |
GTsapparellas | 6:3758685f4b75 | 246 | static osjob_t sendjob; |
GTsapparellas | 6:3758685f4b75 | 247 | unsigned int xmit_count = 1; |
mluis | 0:a2929fa6e4f0 | 248 | |
mluis | 0:a2929fa6e4f0 | 249 | // provide application router ID (8 bytes, LSBF) |
GTsapparellas | 6:3758685f4b75 | 250 | void os_getArtEui (u1_t* buf) { |
GTsapparellas | 6:3758685f4b75 | 251 | #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. |
GTsapparellas | 6:3758685f4b75 | 252 | memcpy(buf, APPEUI, 8); |
GTsapparellas | 6:3758685f4b75 | 253 | #endif |
mluis | 0:a2929fa6e4f0 | 254 | } |
mluis | 0:a2929fa6e4f0 | 255 | |
mluis | 0:a2929fa6e4f0 | 256 | // provide device ID (8 bytes, LSBF) |
GTsapparellas | 6:3758685f4b75 | 257 | void os_getDevEui (u1_t* buf) { |
GTsapparellas | 6:3758685f4b75 | 258 | #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. |
GTsapparellas | 6:3758685f4b75 | 259 | memcpy(buf, DEVEUI, 8); |
GTsapparellas | 6:3758685f4b75 | 260 | #endif |
mluis | 0:a2929fa6e4f0 | 261 | } |
mluis | 0:a2929fa6e4f0 | 262 | |
mluis | 0:a2929fa6e4f0 | 263 | // provide device key (16 bytes) |
GTsapparellas | 6:3758685f4b75 | 264 | void os_getDevKey (u1_t* buf) { |
GTsapparellas | 6:3758685f4b75 | 265 | memcpy(buf, NWKSKEY, 16); |
mluis | 0:a2929fa6e4f0 | 266 | } |
mluis | 0:a2929fa6e4f0 | 267 | |
GTsapparellas | 6:3758685f4b75 | 268 | |
GTsapparellas | 6:3758685f4b75 | 269 | void onEvent (ev_t ev) { |
GTsapparellas | 6:3758685f4b75 | 270 | debug_event(ev); |
mluis | 0:a2929fa6e4f0 | 271 | |
GTsapparellas | 6:3758685f4b75 | 272 | switch(ev) { |
GTsapparellas | 6:3758685f4b75 | 273 | case EV_SCAN_TIMEOUT: |
GTsapparellas | 6:3758685f4b75 | 274 | printf("EV_SCAN_TIMEOUT\n"); |
GTsapparellas | 6:3758685f4b75 | 275 | break; |
GTsapparellas | 6:3758685f4b75 | 276 | case EV_BEACON_FOUND: |
GTsapparellas | 6:3758685f4b75 | 277 | printf("EV_BEACON_FOUND\n"); |
GTsapparellas | 6:3758685f4b75 | 278 | break; |
GTsapparellas | 6:3758685f4b75 | 279 | case EV_BEACON_MISSED: |
GTsapparellas | 6:3758685f4b75 | 280 | printf("EV_BEACON_MISSED\n"); |
GTsapparellas | 6:3758685f4b75 | 281 | break; |
GTsapparellas | 6:3758685f4b75 | 282 | case EV_BEACON_TRACKED: |
GTsapparellas | 6:3758685f4b75 | 283 | printf("EV_BEACON_TRACKED\n"); |
GTsapparellas | 6:3758685f4b75 | 284 | break; |
GTsapparellas | 6:3758685f4b75 | 285 | case EV_JOINING: |
GTsapparellas | 6:3758685f4b75 | 286 | printf("EV_JOINING\n"); |
GTsapparellas | 6:3758685f4b75 | 287 | break; |
GTsapparellas | 6:3758685f4b75 | 288 | case EV_JOINED: |
GTsapparellas | 6:3758685f4b75 | 289 | printf("EV_JOINED\n"); |
GTsapparellas | 6:3758685f4b75 | 290 | break; |
GTsapparellas | 6:3758685f4b75 | 291 | case EV_RFU1: |
GTsapparellas | 6:3758685f4b75 | 292 | printf("EV_RFU1\n"); |
GTsapparellas | 6:3758685f4b75 | 293 | break; |
GTsapparellas | 6:3758685f4b75 | 294 | case EV_JOIN_FAILED: |
GTsapparellas | 6:3758685f4b75 | 295 | printf("EV_JOIN_FAILED\n"); |
GTsapparellas | 6:3758685f4b75 | 296 | break; |
GTsapparellas | 6:3758685f4b75 | 297 | case EV_REJOIN_FAILED: |
GTsapparellas | 6:3758685f4b75 | 298 | printf("EV_REJOIN_FAILED\n"); |
GTsapparellas | 6:3758685f4b75 | 299 | break; |
GTsapparellas | 6:3758685f4b75 | 300 | case EV_TXCOMPLETE: |
GTsapparellas | 6:3758685f4b75 | 301 | printf("EV_TXCOMPLETE (waiting for RX windows)\n"); |
GTsapparellas | 6:3758685f4b75 | 302 | if (LMIC.txrxFlags & TXRX_ACK) |
mluis | 0:a2929fa6e4f0 | 303 | { |
GTsapparellas | 6:3758685f4b75 | 304 | printf("Received ack\n"); |
GTsapparellas | 6:3758685f4b75 | 305 | } |
GTsapparellas | 6:3758685f4b75 | 306 | if(LMIC.dataLen) |
GTsapparellas | 6:3758685f4b75 | 307 | { // data received in rx slot after tx |
GTsapparellas | 6:3758685f4b75 | 308 | printf("Received "); |
GTsapparellas | 6:3758685f4b75 | 309 | printf("%u", LMIC.dataLen); |
GTsapparellas | 6:3758685f4b75 | 310 | printf(" bytes of payload\n"); |
mluis | 0:a2929fa6e4f0 | 311 | } |
mluis | 0:a2929fa6e4f0 | 312 | break; |
GTsapparellas | 6:3758685f4b75 | 313 | case EV_LOST_TSYNC: |
GTsapparellas | 6:3758685f4b75 | 314 | printf("EV_LOST_TSYNC\n"); |
GTsapparellas | 6:3758685f4b75 | 315 | break; |
GTsapparellas | 6:3758685f4b75 | 316 | case EV_RESET: |
GTsapparellas | 6:3758685f4b75 | 317 | printf("EV_RESET\n"); |
GTsapparellas | 6:3758685f4b75 | 318 | break; |
GTsapparellas | 6:3758685f4b75 | 319 | case EV_RXCOMPLETE: |
GTsapparellas | 6:3758685f4b75 | 320 | // data received in ping slot |
GTsapparellas | 6:3758685f4b75 | 321 | printf("EV_RXCOMPLETE\n"); |
mluis | 0:a2929fa6e4f0 | 322 | break; |
GTsapparellas | 6:3758685f4b75 | 323 | case EV_LINK_DEAD: |
GTsapparellas | 6:3758685f4b75 | 324 | printf("EV_LINK_DEAD\n"); |
GTsapparellas | 6:3758685f4b75 | 325 | break; |
GTsapparellas | 6:3758685f4b75 | 326 | case EV_LINK_ALIVE: |
GTsapparellas | 6:3758685f4b75 | 327 | printf("EV_LINK_ALIVE\n"); |
GTsapparellas | 6:3758685f4b75 | 328 | break; |
GTsapparellas | 6:3758685f4b75 | 329 | default: |
GTsapparellas | 6:3758685f4b75 | 330 | printf("Unknown event\n"); |
GTsapparellas | 6:3758685f4b75 | 331 | break; |
mluis | 0:a2929fa6e4f0 | 332 | } |
mluis | 0:a2929fa6e4f0 | 333 | } |
mluis | 0:a2929fa6e4f0 | 334 | |
mluis | 0:a2929fa6e4f0 | 335 | |
GTsapparellas | 6:3758685f4b75 | 336 | void transmit(osjob_t* j){ |
GTsapparellas | 6:3758685f4b75 | 337 | //printf("txCnhl: %u , Channel Ready? ", LMIC.txChnl); |
GTsapparellas | 6:3758685f4b75 | 338 | if (LMIC.opmode & (1 << 7)) |
GTsapparellas | 6:3758685f4b75 | 339 | { |
GTsapparellas | 6:3758685f4b75 | 340 | printf("NO, waiting...\n\n"); |
GTsapparellas | 6:3758685f4b75 | 341 | } |
GTsapparellas | 6:3758685f4b75 | 342 | else |
GTsapparellas | 6:3758685f4b75 | 343 | { |
GTsapparellas | 6:3758685f4b75 | 344 | //printf("YES, sensor readings...\n\n"); |
GTsapparellas | 6:3758685f4b75 | 345 | // Prepare upstream data transmission at the next possible time. |
GTsapparellas | 6:3758685f4b75 | 346 | // LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0); |
GTsapparellas | 6:3758685f4b75 | 347 | |
GTsapparellas | 6:3758685f4b75 | 348 | float temperature, humidity, lightIntensity, soilMoisture; |
GTsapparellas | 6:3758685f4b75 | 349 | getTemperatureHumidity(temperature, humidity); |
GTsapparellas | 6:3758685f4b75 | 350 | getLightIntensity(lightIntensity); |
GTsapparellas | 6:3758685f4b75 | 351 | getSoilMoisture(soilMoisture); |
mluis | 1:60184eda0066 | 352 | |
GTsapparellas | 6:3758685f4b75 | 353 | int16_t temp = temperature*100; |
GTsapparellas | 6:3758685f4b75 | 354 | int16_t hum = humidity*100; |
GTsapparellas | 6:3758685f4b75 | 355 | int16_t light = lightIntensity*100; |
GTsapparellas | 6:3758685f4b75 | 356 | int16_t soil = soilMoisture*100; |
GTsapparellas | 6:3758685f4b75 | 357 | |
GTsapparellas | 6:3758685f4b75 | 358 | //printf(" ----->Preparing packet...\n"); |
GTsapparellas | 6:3758685f4b75 | 359 | |
GTsapparellas | 6:3758685f4b75 | 360 | LMIC.frame[0] = temp >> 8; |
GTsapparellas | 6:3758685f4b75 | 361 | LMIC.frame[1] = temp & 0xFF; |
GTsapparellas | 6:3758685f4b75 | 362 | LMIC.frame[2] = hum >> 8; |
GTsapparellas | 6:3758685f4b75 | 363 | LMIC.frame[3] = hum & 0xFF; |
GTsapparellas | 6:3758685f4b75 | 364 | LMIC.frame[4] = light >> 8; |
GTsapparellas | 6:3758685f4b75 | 365 | LMIC.frame[5] = light & 0xFF; |
GTsapparellas | 6:3758685f4b75 | 366 | LMIC.frame[6] = soil >> 8; |
GTsapparellas | 6:3758685f4b75 | 367 | LMIC.frame[7] = soil & 0xFF; |
GTsapparellas | 6:3758685f4b75 | 368 | |
GTsapparellas | 6:3758685f4b75 | 369 | //printf(" ----->Packet READY\n\n"); |
GTsapparellas | 6:3758685f4b75 | 370 | LMIC_setTxData2(1, LMIC.frame, 8, 0); |
GTsapparellas | 6:3758685f4b75 | 371 | //printf(" ----->Sending packet %u of byte size %u\n\n", xmit_count++, LMIC_FRAME_LENGTH); |
GTsapparellas | 6:3758685f4b75 | 372 | } |
GTsapparellas | 6:3758685f4b75 | 373 | // Schedule a timed job to run at the given timestamp (absolute system time) |
GTsapparellas | 6:3758685f4b75 | 374 | os_setTimedCallback(j, os_getTime()+sec2osticks(TRANSMIT_INTERVAL), transmit); |
mluis | 1:60184eda0066 | 375 | |
mluis | 0:a2929fa6e4f0 | 376 | } |
mluis | 0:a2929fa6e4f0 | 377 | |
GTsapparellas | 6:3758685f4b75 | 378 | void setUp() { |
GTsapparellas | 6:3758685f4b75 | 379 | |
GTsapparellas | 6:3758685f4b75 | 380 | //printf("IoT smart monitoring device for agriculture using LoRaWAN technology\n\n"); |
GTsapparellas | 6:3758685f4b75 | 381 | //printf("setting up\n"); |
mluis | 0:a2929fa6e4f0 | 382 | |
GTsapparellas | 6:3758685f4b75 | 383 | os_init(); |
GTsapparellas | 6:3758685f4b75 | 384 | //printf("MBED_OS_INIT\n\n"); |
GTsapparellas | 6:3758685f4b75 | 385 | //printf("os_init\n"); |
GTsapparellas | 6:3758685f4b75 | 386 | |
GTsapparellas | 6:3758685f4b75 | 387 | // Reset the MAC state. Session and pending data transfers will be discarded. |
GTsapparellas | 6:3758685f4b75 | 388 | LMIC_reset(); |
GTsapparellas | 6:3758685f4b75 | 389 | |
GTsapparellas | 6:3758685f4b75 | 390 | // Set static session parameters. Instead of dynamically establishing a session |
GTsapparellas | 6:3758685f4b75 | 391 | // by joining the network, precomputed session parameters are be provided. |
GTsapparellas | 6:3758685f4b75 | 392 | LMIC_setSession (0x1, DEVADDR, (uint8_t*)NWKSKEY, (uint8_t*)APPSKEY); |
GTsapparellas | 6:3758685f4b75 | 393 | |
GTsapparellas | 6:3758685f4b75 | 394 | // Disable data rate adaptation |
GTsapparellas | 6:3758685f4b75 | 395 | LMIC_setAdrMode(0); |
GTsapparellas | 6:3758685f4b75 | 396 | |
GTsapparellas | 6:3758685f4b75 | 397 | // Disable link check validation |
GTsapparellas | 6:3758685f4b75 | 398 | LMIC_setLinkCheckMode(0); |
GTsapparellas | 6:3758685f4b75 | 399 | |
GTsapparellas | 6:3758685f4b75 | 400 | // Disable beacon tracking |
GTsapparellas | 6:3758685f4b75 | 401 | LMIC_disableTracking (); |
GTsapparellas | 6:3758685f4b75 | 402 | |
GTsapparellas | 6:3758685f4b75 | 403 | // Stop listening for downstream data (periodical reception) |
GTsapparellas | 6:3758685f4b75 | 404 | LMIC_stopPingable(); |
GTsapparellas | 6:3758685f4b75 | 405 | |
GTsapparellas | 6:3758685f4b75 | 406 | // Set data rate and transmit power (note: txpow seems to be ignored by the library) |
GTsapparellas | 6:3758685f4b75 | 407 | LMIC_setDrTxpow(DR_SF7,14); |
GTsapparellas | 6:3758685f4b75 | 408 | |
GTsapparellas | 6:3758685f4b75 | 409 | //printf("LMiC_LoRa_MAC_INIT\n\n"); |
mluis | 0:a2929fa6e4f0 | 410 | |
GTsapparellas | 6:3758685f4b75 | 411 | fflush(stdout); |
GTsapparellas | 6:3758685f4b75 | 412 | #ifdef SINGLE_CHANNEL_GATEWAY |
GTsapparellas | 6:3758685f4b75 | 413 | //printf(" ----->Disabling all channels but 0 (868.1 MHz) for single-channel gateway compatibility\n\n\n"); |
GTsapparellas | 6:3758685f4b75 | 414 | for (int i=1; i<16; i++) |
GTsapparellas | 6:3758685f4b75 | 415 | LMIC_disableChannel(i); |
GTsapparellas | 6:3758685f4b75 | 416 | #endif |
GTsapparellas | 6:3758685f4b75 | 417 | //printf("//////////Entering into TIME-TRIGGERED packet sending through LoRaWAN//////////\n"); |
GTsapparellas | 6:3758685f4b75 | 418 | //printf("---------------------Packets to be sent every %u seconds----------------------\n\n", transmit_interval); |
mluis | 0:a2929fa6e4f0 | 419 | } |
GTsapparellas | 6:3758685f4b75 | 420 | |
GTsapparellas | 6:3758685f4b75 | 421 | void loop() { |
GTsapparellas | 6:3758685f4b75 | 422 | |
GTsapparellas | 6:3758685f4b75 | 423 | transmit(&sendjob); |
GTsapparellas | 6:3758685f4b75 | 424 | |
GTsapparellas | 6:3758685f4b75 | 425 | while(1) { |
GTsapparellas | 6:3758685f4b75 | 426 | os_runloop_once(); |
GTsapparellas | 6:3758685f4b75 | 427 | wait_ms(20); |
GTsapparellas | 6:3758685f4b75 | 428 | } |
GTsapparellas | 6:3758685f4b75 | 429 | } |
GTsapparellas | 6:3758685f4b75 | 430 | |
GTsapparellas | 6:3758685f4b75 | 431 | int main(int argc, char **argv) { |
GTsapparellas | 6:3758685f4b75 | 432 | setUp(); |
GTsapparellas | 6:3758685f4b75 | 433 | while(1) loop(); |
GTsapparellas | 6:3758685f4b75 | 434 | } |