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
Diff: main.cpp
- Revision:
- 7:8ffc2f64b0f8
- Parent:
- 6:3758685f4b75
- Child:
- 8:f307640ed331
--- a/main.cpp Mon Apr 02 12:16:01 2018 +0000 +++ b/main.cpp Mon Apr 02 16:09:01 2018 +0000 @@ -42,26 +42,25 @@ * * - 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. + * a meaningful way for end-user's reference. + * + * - Fully reset device through RESET BUTTON pressed. * * @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 + * Code available at: 1) GITHUB LINK + * 2) MBED LINK * - * SEE readME file for instructions of how to compile and run the program. + * SEE readME.txt file for instructions of how to compile and run the program. * *******************************************************************************/ - // ADD revisions and links above - // ADD IFDEF, AND events, comments + // ADD links above // ADD LED FLASHING - // BUTTON PRESSED-RESET SEND A LORA PACKET + // ADD to mbed // ADD to git hub as well + // write readME.txt file // TEST THE CODE IF OK + // fill in logbook #include <mbed.h> #include <lmic.h> @@ -74,6 +73,7 @@ // DEFINITION DECLARATIONS // ///////////////////////////////////////////////// +#define MAX_EU_CHANNELS 16 // Frequency channels automatically initialized for EU reqion. #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). @@ -87,8 +87,37 @@ // Transmit interval in seconds. uint16_t transmit_interval = TRANSMIT_INTERVAL; +// Static osjob_t sendjob variable used by loop function +static osjob_t sendjob; + +// Unsigned integer packet counter used by transmit function. +unsigned int packetCounter = 1; + +// Disable data rate adaption. +// Set to 1 in order to enable data rate adaption. +static const bit_t disableAdrMode = 0; + +// Disable link check validadtion. +// Set to 1 in order to enable link check validation. +static const bit_t disableLinkCheck = 0; + +// Set LoRa Node's transmission power to 14 dBm. +static const s1_t txPower = 14; + +// Set LoRa Node's network id to 0x1. +static const u4_t NETID = 0x1; + +/* LMiC frame initializations. */ + // Playload frame length of size 8. -uint8_t LMIC_FRAME_LENGTH = 8; +static const u1_t LMIC_FRAME_LENGTH = 8; + +// Set listening port to 1. +static const u1_t LMIC_PORT = 1; + +// Disable confirmation of transmitted LMiC data. +// Set to 1 in order to enable confirmation of transmitted LMiC data. +static const u1_t LMIC_CONFIRMED = 0; #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. @@ -120,6 +149,8 @@ DigitalOut BLUE_LED(PTB21); // PTB21 = Blue pin -- Indicates MCU is sleeping */ +/* Sensor declarations. */ + // Digital Input pin of temperature and humidity sensor set to D6. DHT sensorTempHum(D6, DHT11); @@ -130,10 +161,201 @@ AnalogIn sensorSoilMoisture(A3); /////////////////////////////////////////////////// +// LMiC APPLICATION CALLBACKS // +///////////////////////////////////////////////// + +/* + * os_getArtEui callback of type void. + * + * Copies application ID (8 bytes) of The Things Network Cloud Server into + * memory if OTAA(Over The Air Activation) is applied. + * + * Input parameters: unsigned char buf of APPEUI. + * + */ +void os_getArtEui (u1_t* buf) { + #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. + memcpy(buf, APPEUI, 8); + #endif +}// end of os_getArtEui callback. + +/* + * os_getDevEui callback of type void. + * + * Copies device ID (8 bytes) of The Things Network Cloud Server into + * memory if OTAA(Over The Air Activation) is applied. + * + * Input parameters: unsigned char buf of DEVEUI. + * + */ +void os_getDevEui (u1_t* buf) { + #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied. + memcpy(buf, DEVEUI, 8); + #endif +}// end of os_getDevEui callback. + +/* + * os_getDevKey callback of type void. + * + * Copies device network session ID (16 bytes) of The Things Network Cloud Server + * into memory. + * + * Input parameters: unsigned char buf of NWKSKEY. + * + */ +void os_getDevKey (u1_t* buf) { + memcpy(buf, NWKSKEY, 16); +}// end of os_getDevKey callback. + +/* + * onEvent callback of type void. + * + * Outputs UART message depending on + * related event. + * + * NOTICE THAT: Not all events are being + * used due to significant set up + * of LMiC environment. + * + * Input parameters: ev_t event. + * + */ +void onEvent (ev_t ev) { + //debug_event(ev); + + switch(ev) { // Switch events. + case EV_SCAN_TIMEOUT: + printf("EV_SCAN_TIMEOUT\n"); // Scan timeout. + break; + case EV_BEACON_FOUND: + printf("EV_BEACON_FOUND\n"); // Beacon found. + break; + case EV_BEACON_MISSED: + printf("EV_BEACON_MISSED\n"); // Beacon missed. + break; + case EV_BEACON_TRACKED: + printf("EV_BEACON_TRACKED\n"); // Beacon tracked. + break; + case EV_JOINING: + printf("EV_JOINING\n"); // Joining the network. + break; + case EV_JOINED: + printf("EV_JOINED\n"); // Network joined. + break; + case EV_RFU1: + printf("EV_RFU1\n"); // RFU1 event. + break; + case EV_JOIN_FAILED: + printf("EV_JOIN_FAILED\n"); // Joining failed. + break; + case EV_REJOIN_FAILED: + printf("EV_REJOIN_FAILED\n"); // Re-joining failed. + break; + case EV_TXCOMPLETE: + printf("EV_TXCOMPLETE (waiting for RX windows)\n"); // Transmission complete. + if (LMIC.txrxFlags & TXRX_ACK) // Check if acknowledgment received. + { + printf("Received ack\n"); + } + if(LMIC.dataLen) // Output playload's data length. + { + printf("Received "); + printf("%u", LMIC.dataLen); + printf(" bytes of payload\n"); + } + break; + case EV_LOST_TSYNC: + printf("EV_LOST_TSYNC\n"); // Lost transmision sync. + break; + case EV_RESET: + printf("EV_RESET\n"); // Reset. + break; + case EV_RXCOMPLETE: + printf("EV_RXCOMPLETE\n"); // Reception complete. + break; + case EV_LINK_DEAD: + printf("EV_LINK_DEAD\n"); // Link dead. + break; + case EV_LINK_ALIVE: + printf("EV_LINK_ALIVE\n"); // Link alive. + break; + default: + printf("Unknown event\n"); // Default unknown event. + break; + } +}// end of onEvent callback. + +/////////////////////////////////////////////////// // LOCAL FUNCTIONS DECLARATIONS // ///////////////////////////////////////////////// /* + * setUp function of type void. + * + * Initializes mbed OS, LMiC OS as well as + * disabling all channels but 0 (868.1 MHz) for single-channel + * gateway compatibility. + * + * Input parameters: None. + * + */ +void setUp() { + + #if DEBUG_LEVEL == 1 + printf("IoT smart monitoring device for agriculture using LoRaWAN technology\n\n"); + #endif + // Initializes OS. + os_init(); + + #if DEBUG_LEVEL == 1 + printf("OS_INIT\n\n"); + #endif + + // Reset the MAC state. Session and pending data transfers are being 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 (NETID, DEVADDR, (uint8_t*)NWKSKEY, (uint8_t*)APPSKEY); + + // Disable data rate adaptation. + LMIC_setAdrMode(disableAdrMode); + + // Disable link check validation. + LMIC_setLinkCheckMode(disableLinkCheck); + + // Disable beacon tracking. + LMIC_disableTracking(); + + // Stop listening for downstream data (periodical reception) as LoRa Node + // is only transmitting data to the Gateway. + LMIC_stopPingable(); + + // Set data rate and transmit power. + LMIC_setDrTxpow(DR_SF7,txPower); + + //fflush(stdout); + + // If single-channel gateway is being used disable + // all the other channels except channel 0. + #ifdef SINGLE_CHANNEL_GATEWAY + #if DEBUG_LEVEL == 1 + printf(" ----->Disabling all channels but 0 (868.1 MHz) for single-channel gateway compatibility\n\n\n"); + #endif + + for (int i=1; i < MAX_EU_CHANNELS; i++) + { + LMIC_disableChannel(i); + } + #endif + + #if DEBUG_LEVEL == 1 + printf("//////////Entering into TIME-TRIGGERED packet sending through LoRaWAN//////////\n"); + printf("---------------------Packets to be sent every %u seconds----------------------\n\n", transmit_interval); + #endif +}// end of setUp function. + +/* * getTemperatureHumidity function of type void. * * Gets temperature (celcius) and humidity (relative humidity %) @@ -230,7 +452,7 @@ // 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). + // 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. @@ -240,195 +462,135 @@ #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); +/* + * transmit function of type void. + * + * Checking if channel is ready. + * If no, waiting until channel becomes free. + * If yes, calling getTemperatureHumidity, + * getLightIntensity and getSoilMoisture functions + * to gather measuring parameters. Then, prepares + * the LoRa packet and finally sending the packet + * using os_setTimedCallback LMiC callback. + * + * Input parameters: osjob_t* j + * + */ +void transmit(osjob_t* j) +{ + // Define sensor measuring parameters. + float temperature, humidity, lightIntensity, soilMoisture; + + #if DEBUG_LEVEL == 1 + printf("txChannel: %u , Channel Ready? ", LMIC.txChnl); #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)) + + if (LMIC.opmode & (1 << 7)) // Is channel ready for transmission? { 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; + #if DEBUG_LEVEL == 1 + printf("YES, sensor readings...\n\n"); + #endif + + // Gather sensor readings. + getTemperatureHumidity(temperature, humidity); + getLightIntensity(lightIntensity); + getSoilMoisture(soilMoisture); - //printf(" ----->Preparing packet...\n"); + #if DEBUG_LEVEL == 1 + printf(" ----->Preparing LoRa packet...\n"); + #endif + + // Prepare upstream data transmission at the next possible time. + // Multiply all sensor readings by 100. + int16_t temp = temperature*100; + int16_t hum = humidity*100; + int16_t light = lightIntensity*100; + int16_t soil = soilMoisture*100; - 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; + // Allocate measurements into LMIC frame array ready for transmission. + // Each sensor measurement allocates 2 positions in frame array. + // First, value is right shifted for 8 bits, while on the next + // array's position least significant bits are taken as the desired + // value for each sensor measurement. + // This procedure is required in order to send playload data + // to The Things Network Cloud Server. + // Data will then be converted in a meaningful way through + // All Things Talk ABCL custom JSON binary conversion script. + 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); + // Set the transmission data. + LMIC_setTxData2(LMIC_PORT, LMIC.frame, LMIC_FRAME_LENGTH, LMIC_CONFIRMED); + + #if DEBUG_LEVEL == 1 + printf(" ----->LoRa Packet READY\n\n"); + printf(" ----->Sending LoRa packet %u of byte size %u\n\n", packetCounter++, LMIC_FRAME_LENGTH); + #endif } - // Schedule a timed job to run at the given timestamp (absolute system time) + // Schedule a time-triggered job to run based on TRANSMIT_INTERVAL time value. 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"); + +}// end of transmit function. - 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"); +/* + * loop function of type void. + * + * Calling transmit as well as os_runloop_once functions + * for a repeatedly time-triggered behaviour + * program execution. + * + * Input parameters: None. + * + */ +void loop() +{ + // Calling transmit local function for acquiring next transmission + // job of LoRa Node. + transmit(&sendjob); - 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() { + // Super loop running os_runloop_once LMiC callback in a time-triggered behaviour. + while(1) + { + // Calling LMiC os_runloop_once callback. + os_runloop_once(); + // Delay of 20 ms. + wait_ms(20); + } + // Never arives here! + +}// end of loop function. -transmit(&sendjob); - -while(1) { - os_runloop_once(); - wait_ms(20); - } - } - -int main(int argc, char **argv) { +/* + * main function of type integer. + * + * Calling setUp as well as loop functions + * for a repeatedly time-triggered behaviour + * program execution. + * + * Input parameters: integer argc. + * char **argv. + * + */ +int main(int argc, char **argv) +{ + // Calling setUp local function for OS initialization. setUp(); - while(1) loop(); - } \ No newline at end of file + + // Super loop running loop local funcion in a time-triggered behaviour. + while(1) + { + loop(); + } + // Never arrives here! + +} // end of main function. \ No newline at end of file