Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DHT11 LMiC SX1272Lib mbed
Fork of LoRaWAN-lmic-app by
main.cpp
- Committer:
- GTsapparellas
- Date:
- 2018-04-02
- Revision:
- 6:3758685f4b75
- Parent:
- 5:1b2fcc2582e8
- Child:
- 7:8ffc2f64b0f8
File content as of revision 6:3758685f4b75:
/******************************************************************************* * Internet of Things (IoT) smart monitoring * device for agriculture using LoRaWAN technology. * * LoRa Gateway: Single-channel Dragino LG01-P LoRa Gateway * * Measurement parameters: Temperature (Celcius) * Humidity (Relative Humidity %) * Light Intenisty (Volts) * Soil Moisture (Volts) * * Evaluation board: FRDM-K64F ARM mbed board * * LoRa shield: Semtech SX1272MB2xAS * * IoT Cloud Server: The Things Network (Europe EU-868.1 frequency band) * * API Platform: All Things Talk Maker * * - Time-triggered program periodically sends playload data (including * temperature, humidity, light intensity and soil moisture sensor parameters) * by using FRDM-K64F ARM mbed board and Semtech SX1272MB2xAS as the LoRa Node. * * - DHT library and Digital Input pin used for the successful measurement * of temperature and humidity sensor parameters. * * - Analog Input pins used for the successful employement of soil moisture and * light intensity sensor parameters. * * - Semtech's SX1272Lib used for the successful configuration and set up of * of SX1272MB2xAS LoRa shield. * * - IBM's LMiC library used for the successful implementation of LoRa modulation. * * - LoRa Node transmitting playload data directly to the single-channel Dragino * LG01-P LoRa Gateway which is connected to The Things Network Cloud Server. * * - ABP (Activation By Personalization) selected as the activation method over * The Things Network Cloud Server. * * - The Things Network Cloud Server makes playload data available online. * * - Through required integration, The Things Network Cloud Server passes * playload data to All Things Talk Maker API which visualizes the data in * a meaningful way for end-user's reference. * * @Author: Giorgos Tsapparellas * @Revisions: * v0.1 -- sensors gathering on FRDM-K64F * v0.2 -- attach sx1272 and take as a transmitter * v0.3 -- * * Porgram available at: 1) GITHUB LINK * 2) MBED LINK * * SEE readME file for instructions of how to compile and run the program. * *******************************************************************************/ // ADD revisions and links above // ADD IFDEF, AND events, comments // ADD LED FLASHING // BUTTON PRESSED-RESET SEND A LORA PACKET // ADD to git hub as well // TEST THE CODE IF OK #include <mbed.h> #include <lmic.h> #include <hal.h> #include <SPI.h> #include <DHT.h> #include <debug.h> /////////////////////////////////////////////////// // DEFINITION DECLARATIONS // ///////////////////////////////////////////////// #define SINGLE_CHANNEL_GATEWAY // Force it to use 868.1 MHz frequency band only due to Dragino LG01-P LoRa Gateway hardware limitation. #define TRANSMIT_INTERVAL 1800 // Transmit interval in seconds, too often may get traffic ignored. #define DEBUG_LEVEL 0 // Set debug level to 1 for outputting messages to the UART Terminal (e.g. Tera Term). #define ACTIVATION_METHOD 0 // Set activation method to 0 for ABP (Activation By Personalization) // Set activation method to 1 for OTAA (Over The Air Activation) /////////////////////////////////////////////////// // GLOBAL VARIABLES DECLARATIONS // ///////////////////////////////////////////////// // Transmit interval in seconds. uint16_t transmit_interval = TRANSMIT_INTERVAL; // Playload frame length of size 8. uint8_t LMIC_FRAME_LENGTH = 8; #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. // LoRaWAN Application identifier (AppEUI) associated with The Things Network Cloud Server. static const u1_t APPEUI[8] = { 0x70, 0xB3, 0xD5, 0x7E, 0xD0, 0x00, 0xA4, 0x54 }; // LoRaWAN unique device ID (DevEUI) associated with The Things Network Cloud Server. static const u1_t DEVEUI[8] = { 0x00, 0x1D, 0x45, 0x32, 0xEC, 0xA8, 0x01, 0x59 }; #endif // Acquired activation method #if ACTIVATION_METHOD == 0 // if ABP (Activation By Personalization) is applied. // LoRaWAN network session key (NwkSKey) associated with The Things Network Cloud Server. static const u1_t NWKSKEY[16] = { 0xDF, 0x9B, 0xB1, 0x30, 0xE8, 0x33, 0x42, 0x76, 0x33, 0x0C, 0x88, 0xBB, 0x30, 0xE2, 0xC2, 0xE9 }; // LoRaWAN application session key (AppSKey) associated with The Things Network Cloud Server. static const u1_t APPSKEY[16] = { 0xE0, 0x52, 0x18, 0x15, 0x0B, 0xE1, 0xEF, 0x1F, 0xAF, 0x8C, 0x8A, 0x31, 0x09, 0xB9, 0xAB, 0x9C }; // LoRaWAN end-device address (DevAddr) associated with The Things Network Cloud Server. static const u4_t DEVADDR = 0x26011B39 ; #endif /*On board's LEDs Declaration DigitalOut RED_LED(PTB22); // PTB22 = Red pin -- Indicates an error occur DigitalOut GREEN_LED(PTE26); // PTE26 = Green pin -- Indicates transmission is in progress DigitalOut BLUE_LED(PTB21); // PTB21 = Blue pin -- Indicates MCU is sleeping */ // Digital Input pin of temperature and humidity sensor set to D6. DHT sensorTempHum(D6, DHT11); // Analog Input pin of light intensity sensor set to A1. AnalogIn sensorLight(A1); // Analog Input pin of soil moisture sensor set to A3. AnalogIn sensorSoilMoisture(A3); /////////////////////////////////////////////////// // LOCAL FUNCTIONS DECLARATIONS // ///////////////////////////////////////////////// /* * getTemperatureHumidity function of type void. * * Gets temperature (celcius) and humidity (relative humidity %) * measurements using DHT library. Otherwise, print an error. * * Input parameters: float temperature * float humidity * */ void getTemperatureHumidity(float& temperature, float& humidity) { // Set err variable to 0 (none). uint8_t err = ERROR_NONE; // Set humidity variable to 0. humidity = 0.0f; // Set temperature variable to 0. temperature = 0.0f; // Store sensor data (40 bits(16-bit temperature, 16-bit humidity and 8-bit // CRC checksum)) into err variable. err = sensorTempHum.readData(); if (err == ERROR_NONE) // if err equals to 0. { // Store float temperature value in celcius. temperature = sensorTempHum.ReadTemperature(CELCIUS); // Store float humidity value. humidity = sensorTempHum.ReadHumidity(); // Output temperature and humidity values on UART Terminal #if DEBUG_LEVEL == 1 printf("Temperature: %4.2f Celsius \r\n", temperature); printf("Humidity: %4.2f % Relative Humidity \r\n", humidity); #endif } else // if err occurs. { // Output error message on UART Terminal and flash the RED LED. #if DEBUG_LEVEL == 1 printf("Error: %d\r\n", err); //RED_LED = !RED_LED; #endif } }// end of getTemperatureHumidity function. /* * getLightIntensity function of type void. * * Gets the light's intensity analogue value at first instance * and then converts it using 16-bit ADC converter into voltage * counting from 0.0 to 5.0. * * Input parameters: float lightIntensityVoltage * */ void getLightIntensity(float& lightIntensityVoltage) { // Set light intensity voltage variable to 0. lightIntensityVoltage = 0.0f; // Set light intensity analogue value to 0. uint16_t lightIntensityAnalogue = 0; // Read light intensity 16-bit analogue value. lightIntensityAnalogue = sensorLight.read_u16(); //Convert the light intensity analog reading (which goes from 0 - 65536) to a voltage (0 - 5V). lightIntensityVoltage = (float) lightIntensityAnalogue*(5.0/65536.0); // Output light intensity voltage as well as resistance value on UART Terminal. #if DEBUG_LEVEL == 1 float resistance = 0.0f; // Groove's calculation for resistance value. resistance = (float)(65536-lightIntensityAnalogue)*10/lightIntensityAnalogue; printf("Light Intensity: %2.2f Volts -- ", lightIntensityVoltage); printf("Resistance: %2.2f Kiloohm \r\n", resistance); #endif }// end of getLightIntensity function. /* * getSoilMoisture function of type void. * * Gets the soil's moisture analogue value at first instance * and then converts it using 16-bit ADC converter into voltage * counting from 0.0 to 5.0. * * Input parameters: float lightOutputVoltage * */ void getSoilMoisture(float& soilMoistureVoltage) { // Set soil moisture voltage variable to 0. soilMoistureVoltage = 0.0f; // Set soil moisture analogue value to 0. uint16_t soilMoistureAnalogue = 0; // Read soil moisture 16-bit analogue value. soilMoistureAnalogue = sensorSoilMoisture.read_u16(); //Convert the soil moisture analog reading (which goes from 0 - 65536) to a voltage (0 - 5V). soilMoistureVoltage = (float) soilMoistureAnalogue*(5.0/65536.0); // Output soil moisture voltage as well as soil moisture analogue value on UART Terminal. #if DEBUG_LEVEL == 1 printf("Soil Moisture: %2.2f Volts -- ", soilMoistureVoltage); printf("Analogue Value: %d \r\n", soilMoistureAnalogue); #endif }// end of getSoilMoisture function. /////////////////////////////////////////////////// // LMiC APPLICATION CALLBACKS // ///////////////////////////////////////////////// static osjob_t sendjob; unsigned int xmit_count = 1; // provide application router ID (8 bytes, LSBF) void os_getArtEui (u1_t* buf) { #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. memcpy(buf, APPEUI, 8); #endif } // provide device ID (8 bytes, LSBF) void os_getDevEui (u1_t* buf) { #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. memcpy(buf, DEVEUI, 8); #endif } // provide device key (16 bytes) void os_getDevKey (u1_t* buf) { memcpy(buf, NWKSKEY, 16); } void onEvent (ev_t ev) { debug_event(ev); switch(ev) { case EV_SCAN_TIMEOUT: printf("EV_SCAN_TIMEOUT\n"); break; case EV_BEACON_FOUND: printf("EV_BEACON_FOUND\n"); break; case EV_BEACON_MISSED: printf("EV_BEACON_MISSED\n"); break; case EV_BEACON_TRACKED: printf("EV_BEACON_TRACKED\n"); break; case EV_JOINING: printf("EV_JOINING\n"); break; case EV_JOINED: printf("EV_JOINED\n"); break; case EV_RFU1: printf("EV_RFU1\n"); break; case EV_JOIN_FAILED: printf("EV_JOIN_FAILED\n"); break; case EV_REJOIN_FAILED: printf("EV_REJOIN_FAILED\n"); break; case EV_TXCOMPLETE: printf("EV_TXCOMPLETE (waiting for RX windows)\n"); if (LMIC.txrxFlags & TXRX_ACK) { printf("Received ack\n"); } if(LMIC.dataLen) { // data received in rx slot after tx printf("Received "); printf("%u", LMIC.dataLen); printf(" bytes of payload\n"); } break; case EV_LOST_TSYNC: printf("EV_LOST_TSYNC\n"); break; case EV_RESET: printf("EV_RESET\n"); break; case EV_RXCOMPLETE: // data received in ping slot printf("EV_RXCOMPLETE\n"); break; case EV_LINK_DEAD: printf("EV_LINK_DEAD\n"); break; case EV_LINK_ALIVE: printf("EV_LINK_ALIVE\n"); break; default: printf("Unknown event\n"); break; } } void transmit(osjob_t* j){ //printf("txCnhl: %u , Channel Ready? ", LMIC.txChnl); if (LMIC.opmode & (1 << 7)) { printf("NO, waiting...\n\n"); } else { //printf("YES, sensor readings...\n\n"); // Prepare upstream data transmission at the next possible time. // LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0); float temperature, humidity, lightIntensity, soilMoisture; getTemperatureHumidity(temperature, humidity); getLightIntensity(lightIntensity); getSoilMoisture(soilMoisture); int16_t temp = temperature*100; int16_t hum = humidity*100; int16_t light = lightIntensity*100; int16_t soil = soilMoisture*100; //printf(" ----->Preparing packet...\n"); LMIC.frame[0] = temp >> 8; LMIC.frame[1] = temp & 0xFF; LMIC.frame[2] = hum >> 8; LMIC.frame[3] = hum & 0xFF; LMIC.frame[4] = light >> 8; LMIC.frame[5] = light & 0xFF; LMIC.frame[6] = soil >> 8; LMIC.frame[7] = soil & 0xFF; //printf(" ----->Packet READY\n\n"); LMIC_setTxData2(1, LMIC.frame, 8, 0); //printf(" ----->Sending packet %u of byte size %u\n\n", xmit_count++, LMIC_FRAME_LENGTH); } // Schedule a timed job to run at the given timestamp (absolute system time) os_setTimedCallback(j, os_getTime()+sec2osticks(TRANSMIT_INTERVAL), transmit); } void setUp() { //printf("IoT smart monitoring device for agriculture using LoRaWAN technology\n\n"); //printf("setting up\n"); os_init(); //printf("MBED_OS_INIT\n\n"); //printf("os_init\n"); // Reset the MAC state. Session and pending data transfers will be discarded. LMIC_reset(); // Set static session parameters. Instead of dynamically establishing a session // by joining the network, precomputed session parameters are be provided. LMIC_setSession (0x1, DEVADDR, (uint8_t*)NWKSKEY, (uint8_t*)APPSKEY); // Disable data rate adaptation LMIC_setAdrMode(0); // Disable link check validation LMIC_setLinkCheckMode(0); // Disable beacon tracking LMIC_disableTracking (); // Stop listening for downstream data (periodical reception) LMIC_stopPingable(); // Set data rate and transmit power (note: txpow seems to be ignored by the library) LMIC_setDrTxpow(DR_SF7,14); //printf("LMiC_LoRa_MAC_INIT\n\n"); fflush(stdout); #ifdef SINGLE_CHANNEL_GATEWAY //printf(" ----->Disabling all channels but 0 (868.1 MHz) for single-channel gateway compatibility\n\n\n"); for (int i=1; i<16; i++) LMIC_disableChannel(i); #endif //printf("//////////Entering into TIME-TRIGGERED packet sending through LoRaWAN//////////\n"); //printf("---------------------Packets to be sent every %u seconds----------------------\n\n", transmit_interval); } void loop() { transmit(&sendjob); while(1) { os_runloop_once(); wait_ms(20); } } int main(int argc, char **argv) { setUp(); while(1) loop(); }