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 Semtech

Revision:
6:3758685f4b75
Parent:
5:1b2fcc2582e8
Child:
7:8ffc2f64b0f8
--- a/main.cpp	Thu Nov 26 17:20:53 2015 +0000
+++ b/main.cpp	Mon Apr 02 12:16:01 2018 +0000
@@ -1,290 +1,434 @@
-/* 
- / _____)             _              | |
-( (____  _____ ____ _| |_ _____  ____| |__
- \____ \| ___ |    (_   _) ___ |/ ___)  _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
-    (C)2015 Semtech
-
-Description: MBED LoRaWAN example application
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
-#include "mbed.h"
+/*******************************************************************************
+ * 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 "lmic.h"
-#include "debug.h"
+#include <mbed.h>
+#include <lmic.h>
+#include <hal.h>
+#include <SPI.h>
+#include <DHT.h>
+#include <debug.h>
 
-/*!
- * When set to 1 the application uses the Over-the-Air activation procedure
- * When set to 0 the application uses the Personalization activation procedure
- */
-#define OVER_THE_AIR_ACTIVATION                     0
+///////////////////////////////////////////////////
+// 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)
 
-#if( OVER_THE_AIR_ACTIVATION == 0 )
+///////////////////////////////////////////////////
+// GLOBAL VARIABLES DECLARATIONS                //
+/////////////////////////////////////////////////
+
+// Transmit interval in seconds.
+uint16_t transmit_interval = TRANSMIT_INTERVAL;
 
-/*!
- * Defines the network ID when using personalization activation procedure
- */
-#define LORAWAN_NET_ID                              ( uint32_t )0x00000000
+// Playload frame length of size 8. 
+uint8_t LMIC_FRAME_LENGTH = 8;
+
+#if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied.
 
-/*!
- * Defines the device address when using personalization activation procedure
- */
-#define LORAWAN_DEV_ADDR                            ( uint32_t )0x12345678
+// 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
 
-/*!
- * Defines the application data transmission duty cycle
- */
-#define APP_TX_DUTYCYCLE                            5000 // 5 [s] value in ms
-#define APP_TX_DUTYCYCLE_RND                        1000 // 1 [s] value in ms
+// Acquired activation method
+#if ACTIVATION_METHOD == 0 // if ABP (Activation By Personalization) is applied.
 
-/*!
- * LoRaWAN Adaptative Data Rate
- */
-#define LORAWAN_ADR_ON                              1
+// 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 confirmed messages
- */
-#define LORAWAN_CONFIRMED_MSG_ON                    1
+// 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 application port
- */
-#define LORAWAN_APP_PORT                            15
-
-/*!
- * User application data buffer size
- */
-#if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
-#define LORAWAN_APP_DATA_SIZE                       6
-
-#else
-#define LORAWAN_APP_DATA_SIZE                       1
+// LoRaWAN end-device address (DevAddr) associated with The Things Network Cloud Server.
+static const u4_t DEVADDR = 0x26011B39 ;
 
 #endif
 
-//////////////////////////////////////////////////
-// CONFIGURATION (FOR APPLICATION CALLBACKS BELOW)
-//////////////////////////////////////////////////
+/*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);
 
-// application router ID (LSBF)
-static const uint8_t AppEui[8] =
-{
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
+///////////////////////////////////////////////////
+// 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) {
 
-// unique device ID (LSBF)
-static const u1_t DevEui[8] =
-{
-    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
-};
-
-// device-specific AES key (derived from device EUI)
-static const uint8_t DevKey[16] = 
-{
-    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
-    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
-};
-
-#if( OVER_THE_AIR_ACTIVATION == 0 )
-// network session key
-static uint8_t NwkSKey[] = 
-{ 
-    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
-    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
-};
+    // 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.
 
-// application session key
-static uint8_t ArtSKey[] = 
-{ 
-    0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
-    0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
-};
-
-#endif
-
-// LEDs and Frame jobs
-osjob_t rxLedJob;
-osjob_t txLedJob;
-osjob_t sendFrameJob;
-
-// LED state
-static bool AppLedStateOn = false;
+/* 
+ * 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.
 
-//////////////////////////////////////////////////
-// Utility functions
-//////////////////////////////////////////////////
-/*!
- * \brief Computes a random number between min and max
+/* 
+ * 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
  *
- * \param [IN] min range minimum value
- * \param [IN] max range maximum value
- * \retval random random value in range min..max
- */
-int32_t randr( int32_t min, int32_t max )
-{
-    return ( int32_t )rand( ) % ( max - min + 1 ) + min;
-}
+ */ 
+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.
 
-//////////////////////////////////////////////////
-// APPLICATION CALLBACKS
-//////////////////////////////////////////////////
+///////////////////////////////////////////////////
+// LMiC APPLICATION CALLBACKS                   //
+/////////////////////////////////////////////////
+static osjob_t sendjob;
+unsigned int xmit_count = 1;
 
 // provide application router ID (8 bytes, LSBF)
-void os_getArtEui( uint8_t *buf )
-{
-    memcpy( buf, AppEui, 8 );
+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( uint8_t *buf )
-{
-    memcpy( buf, DevEui, 8 );
+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( uint8_t *buf )
-{
-    memcpy( buf, DevKey, 16 );
-}
-
-//////////////////////////////////////////////////
-// MAIN - INITIALIZATION AND STARTUP
-//////////////////////////////////////////////////
-
-static void onRxLed( osjob_t* j )
-{
-    debug_val("LED2 = ", 0 );
-}
-
-static void onTxLed( osjob_t* j )
-{
-    debug_val("LED1 = ", 0 );
+void os_getDevKey (u1_t* buf) {
+    memcpy(buf, NWKSKEY, 16);
 }
 
-static void prepareTxFrame( void )
-{
-    LMIC.frame[0] = AppLedStateOn;
-#if ( LORAWAN_CONFIRMED_MSG_ON == 1 )
-    LMIC.frame[1] = LMIC.seqnoDn >> 8;
-    LMIC.frame[2] = LMIC.seqnoDn;
-    LMIC.frame[3] = LMIC.rssi >> 8;
-    LMIC.frame[4] = LMIC.rssi;
-    LMIC.frame[5] = LMIC.snr;
-#endif    
-}
+
+void onEvent (ev_t ev) {
+    debug_event(ev);
 
-void processRxFrame( void )
-{
-    switch( LMIC.frame[LMIC.dataBeg - 1] ) // Check Rx port number
-    {
-        case 1: // The application LED can be controlled on port 1 or 2
-        case 2:
-            if( LMIC.dataLen == 1 )
+    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)
             {
-                AppLedStateOn = LMIC.frame[LMIC.dataBeg] & 0x01;
-                debug_val( "LED3 = ", AppLedStateOn );
+                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;
-        default:
+        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;
     }
 }
 
-static void onSendFrame( osjob_t* j )
-{
-    prepareTxFrame( );
-    LMIC_setTxData2( LORAWAN_APP_PORT, LMIC.frame, LORAWAN_APP_DATA_SIZE, LORAWAN_CONFIRMED_MSG_ON );
-
-    // Blink Tx LED
-    debug_val( "LED1 = ", 1 );
-    os_setTimedCallback( &txLedJob, os_getTime( ) + ms2osticks( 25 ), onTxLed );
-}
 
-// Initialization job
-static void onInit( osjob_t* j )
-{
-    // reset MAC state
-    LMIC_reset( );
-    LMIC_setAdrMode( LORAWAN_ADR_ON );
-#if defined(CFG_eu868)
-    LMIC_setDrTxpow( DR_SF12, 14 );
-#elif defined(CFG_us915)    
-    LMIC_setDrTxpow( DR_SF10, 14 );
-#endif
+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); 
 
-    // start joining
-#if( OVER_THE_AIR_ACTIVATION != 0 )
-    LMIC_startJoining( );
-#else
-    LMIC_setSession( LORAWAN_NET_ID, LORAWAN_DEV_ADDR, NwkSKey, ArtSKey );
-    onSendFrame( NULL );
-#endif
-    // init done - onEvent( ) callback will be invoked...
-}
+      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);
 
-int main( void )
-{
-    osjob_t initjob;
-
-    // initialize runtime env
-    os_init( );
-    // setup initial job
-    os_setCallback( &initjob, onInit );
-    // execute scheduled jobs and events
-    os_runloop( );
-    // (not reached)
 }
 
-//////////////////////////////////////////////////
-// LMIC EVENT CALLBACK
-//////////////////////////////////////////////////
-void onEvent( ev_t ev )
-{
-    bool txOn = false;
-    debug_event( ev );
+void setUp() {
+
+  //printf("IoT smart monitoring device for agriculture using LoRaWAN technology\n\n");
+  //printf("setting up\n");
 
-    switch( ev ) 
-    {
-    // network joined, session established
-    case EV_JOINED:
-        debug_val( "Net ID = ", LMIC.netid );
-        txOn = true;
-        break;
-    // scheduled data sent (optionally data received)
-    case EV_TXCOMPLETE:
-        debug_val( "Datarate = ", LMIC.datarate );
-        // Check if we have a downlink on either Rx1 or Rx2 windows
-        if( ( LMIC.txrxFlags & ( TXRX_DNW1 | TXRX_DNW2 ) ) != 0 )
-        {
-            debug_val( "LED2 = ", 1 );
-            os_setTimedCallback( &rxLedJob, os_getTime( ) + ms2osticks( 25 ), onRxLed );
+  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");
 
-            if( LMIC.dataLen != 0 )
-            { // data received in rx slot after tx
-                debug_buf( LMIC.frame + LMIC.dataBeg, LMIC.dataLen );
-                processRxFrame( );
-            }
-        }
-        txOn = true;
-        break;
-    default:
-        break;
-    }
-    if( txOn == true )
-    {
-        //Sends frame every APP_TX_DUTYCYCLE +/- APP_TX_DUTYCYCLE_RND random time (if not duty cycle limited)
-        os_setTimedCallback( &sendFrameJob,
-                             os_getTime( ) + ms2osticks( APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ) ),
-                             onSendFrame );
-        
-        ////Sends frame as soon as possible (duty cylce limitations)
-        //onSendFrame( NULL );
-    }
+  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();
+    }
\ No newline at end of file