Test LORA NODE with Library SX1272, initially created by C.Pham, University of Pau, France for Arduino. Suitable for MBED / NUCLEO / STM32

Dependencies:   SX1272 mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  *  temperature sensor on analog 8 to test the LoRa gateway
00003  *
00004  *  Copyright (C) 2016 Congduc Pham, University of Pau, France
00005  *
00006  *  This program is free software: you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation, either version 3 of the License, or
00009  *  (at your option) any later version.
00010 
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with the program.  If not, see <http://www.gnu.org/licenses/>.
00018  *
00019  *****************************************************************************
00020  * last update: Sep. 29th, 2017 by C. Pham
00021  * last update: oct 30th , 2017 by C.Dupaty
00022  * ADAPTATION FOR NUCLEO STM32, TESTED ON NUCLEO-L073RZ WITH 
00023  * SX1272MB2xAS SHIELD
00024  * DRAGINO SHIELD V95 WITH GPS  http://wiki.dragino.com/index.php?title=Lora/GPS_Shield 
00025  *      For DRAGINO move LORA_CLK LORA_DI LORA_DO straps to the right (arduino 11 12 13)
00026  * ALL CONFIGURATIONS FOR ARDUINO HAVE BEEN REMOVED
00027  * WORK ONLY IN EUROPE
00028  * please visit http://cpham.perso.univ-pau.fr/LORA/LoRaDevices.html
00029  * for original version for ARDUINO 
00030 */
00031   
00032 #include "mbed.h"
00033 #include "SX1272.h"
00034 #define BAND868
00035 #define MAX_DBM 14
00036 
00037 const uint32_t DEFAULT_CHANNEL=CH_10_868;  // for BAND868
00038 
00039 //#define WITH_EEPROM            //  TO DO ON STM32
00040 #define WITH_APPKEY
00041 #define NEW_DATA_FIELD
00042 #define WITH_ACK
00043 
00044 ///////////////////////////////////////////////////////////////////
00045 // CHANGE HERE THE LORA MODE, NODE ADDRESS 
00046 #define LORAMODE  1
00047 #define node_addr 6
00048 //////////////////////////////////////////////////////////////////
00049 
00050 ///////////////////////////////////////////////////////////////////
00051 // CHANGE HERE THE THINGSPEAK FIELD BETWEEN 1 AND 4
00052 #define field_index 1
00053 ///////////////////////////////////////////////////////////////////
00054 
00055 ///////////////////////////////////////////////////////////////////
00056 // CHANGE HERE THE READ PIN AND THE POWER PIN FOR THE TEMP. SENSOR
00057 #define TEMP_PIN_READ  PA_4
00058 // use digital 9 to power the temperature sensor if needed
00059 #define TEMP_PIN_POWER PB_0
00060 ///////////////////////////////////////////////////////////////////
00061 
00062 ///////////////////////////////////////////////////////////////////
00063 // CHANGE HERE THE TIME IN SECONDS BETWEEN 2 READING & TRANSMISSION
00064 #define minTime 120 // 2 minutes
00065 #define maxTime 600 // 10 minutes
00066 ///////////////////////////////////////////////////////////////////
00067 
00068 #ifdef WITH_APPKEY
00069 ///////////////////////////////////////////////////////////////////
00070 // CHANGE HERE THE APPKEY, BUT IF GW CHECKS FOR APPKEY, MUST BE
00071 // IN THE APPKEY LIST MAINTAINED BY GW.
00072 uint8_t my_appKey[4]={5, 6, 7, 8};
00073 ///////////////////////////////////////////////////////////////////
00074 #endif
00075 
00076 #ifdef WITH_EEPROM
00077 #include <EEPROM.h>
00078 #endif
00079 
00080 #define DEFAULT_DEST_ADDR 1
00081 
00082 #ifdef WITH_ACK
00083 #define NB_RETRIES 2
00084 #endif
00085 
00086 #ifdef WITH_EEPROM
00087 struct sx1272config {
00088 
00089   uint8_t flag1;
00090   uint8_t flag2;
00091   uint8_t seq;
00092   // can add other fields such as LoRa mode,...
00093 };
00094 
00095 sx1272config my_sx1272config;
00096 #endif
00097 
00098 ///////////////////////////////////////
00099 // Globals variables
00100 ///////////////////////////////////////
00101 int loraMode=LORAMODE;
00102 // added by C.Dupaty
00103 // For test with LM35DZ temperature captor
00104 DigitalOut temp_pin_power(TEMP_PIN_POWER);
00105 AnalogIn temp_pin_read(TEMP_PIN_READ);
00106 
00107 /////////////////////////////////////////
00108 // SETUP SX1272 initialisation
00109 ////////////////////////////////////////
00110 void setup()
00111 {
00112   int e;
00113   // Print welcome message
00114   printf("-------------------------------------------------\n");
00115   printf("------Simple LoRa temperature sensor-------------\n");
00116   printf("--P.Pharm, adaptation NUCELO STM32 C.Dupaty------\n");
00117   printf("-------------------------------------------------\n\n");
00118   printf("!!!!!!!!! During configuration, all states numbers must read at 0\n");
00119  
00120 #ifdef TARGET_NUCLEO_L073RZ
00121   printf("NUCLEO L073RZ detected\n");
00122 #else
00123   printf("WARNING, this software has been tested on NUCLEO L073RZ only !!!\n"); 
00124 #endif
00125 
00126   // Power ON the module
00127   sx1272.ON();
00128 
00129 #ifdef WITH_EEPROM
00130   // get config from EEPROM
00131   EEPROM.get(0, my_sx1272config);
00132 
00133   // found a valid config?
00134   if (my_sx1272config.flag1==0x12 && my_sx1272config.flag2==0x34) {
00135     printf("Get back previous sx1272 config\n");
00136 
00137     // set sequence number for SX1272 library
00138     sx1272._packetNumber=my_sx1272config.seq;
00139     printf("Using packet sequence number of %d\n",sx1272._packetNumber);
00140   }
00141   else {
00142     // otherwise, write config and start over
00143     my_sx1272config.flag1=0x12;
00144     my_sx1272config.flag2=0x34;
00145     my_sx1272config.seq=sx1272._packetNumber;
00146   }
00147 #endif
00148   
00149   int error_config_sx1272=0;
00150   
00151   // Set transmission mode and print the result
00152   e = sx1272.setMode(loraMode);
00153   if (e) error_config_sx1272=1;
00154   printf("Setting Mode: state %d\n",e);
00155   
00156   // enable carrier sense
00157   sx1272._enableCarrierSense=true;
00158 
00159   // for LOW POWER
00160   sx1272._RSSIonSend=false;
00161 
00162     
00163   // Select frequency channel
00164   e = sx1272.setChannel(DEFAULT_CHANNEL);
00165   if (e) error_config_sx1272=1;
00166   printf("Setting Channel: state %d\n",e);
00167   
00168   // Select amplifier line; PABOOST or RFO
00169 #ifdef PABOOST
00170   sx1272._needPABOOST=true;
00171   // previous way for setting output power
00172   // powerLevel='x';
00173 #else
00174   // previous way for setting output power
00175   // powerLevel='M';  
00176 #endif
00177 
00178   // previous way for setting output power
00179   // e = sx1272.setPower(powerLevel); 
00180 
00181   e = sx1272.setPowerDBM((uint8_t)MAX_DBM);
00182   if (e) error_config_sx1272=1;
00183   printf("Setting Power: state %d\n",e);
00184   
00185   // Set the node address and print the result
00186   e = sx1272.setNodeAddress(node_addr);
00187   if (e) error_config_sx1272=1;
00188   printf("Setting node addr: state %d\n",e);
00189   
00190   // Print a success message
00191   if (!error_config_sx1272) printf("SX1272 successfully configured\n");
00192   else printf("ERREUR DE CONFIGURATION DU SX1272\n");
00193 
00194   wait_ms(500);
00195 }
00196 
00197 //////////////////////////////////////////////////////////////
00198 //  main was named loop on Arduino
00199 //////////////////////////////////////////////////////////////
00200 int main(void)      // return int for cpp compatibility but never ending the program
00201 {
00202 long startSend;
00203 long endSend;
00204 uint8_t app_key_offset=0;
00205 int e;
00206 double temp;            // variable temperature in this demo 
00207 char float_str[20];
00208 uint8_t message[100];   // the message that will be send to the gateway
00209 
00210 setup();
00211  
00212  // main loop start here 
00213 while(1)  {  
00214 
00215 // this demo use a LM35DZ temerature captor
00216       temp_pin_power=1;         // LM35DZ is powering by a simple GPIO
00217       wait_ms(200);   
00218       temp = 0;
00219       int value;
00220       for (int i=0; i<10; i++) {
00221           // compute temperature for LM35DZ captor
00222           value = temp_pin_read.read_u16();
00223           temp += ((double)value*50.0/8192.0)/10;
00224           printf("Reading ADC temperature %d/10 -> %d\n",i,value);
00225           wait_ms(100);
00226       } 
00227       temp_pin_power=0;         // LM35DZ power off
00228       printf("Mean temp is %f Cent\n",temp);
00229 // we have now temperature in the variable temp      
00230 
00231 #ifdef WITH_APPKEY
00232       app_key_offset = sizeof(my_appKey);
00233       // set the app key in the payload
00234       memcpy(message,my_appKey,app_key_offset);
00235 #endif
00236 
00237       uint8_t r_size;
00238       
00239         // convert float temp to string ASCII
00240         sprintf(float_str,"%2.2f",temp);
00241         #ifdef NEW_DATA_FIELD
00242               // this is for testing, uncomment if you just want to test, without a real temp sensor plugged
00243               //strcpy(float_str, "21.55567");
00244               r_size=sprintf((char*)message+app_key_offset,"\\!#%d#TC/%s",field_index,float_str);
00245         #else
00246               // this is for testing, uncomment if you just want to test, without a real temp sensor plugged
00247               //strcpy(float_str, "21.55567");
00248               r_size=sprintf((char*)message+app_key_offset,"\\!#%d#%s",field_index,float_str);
00249         #endif
00250           
00251       printf("Sending %s\n",message+app_key_offset);
00252       printf("Real payload size is %d\n",r_size);
00253      
00254       int pl=r_size+app_key_offset;
00255       sx1272.CarrierSense();
00256       startSend=millis();
00257 
00258 #ifdef WITH_APPKEY
00259       // indicate that we have an appkey
00260       sx1272.setPacketType(PKT_TYPE_DATA | PKT_FLAG_DATA_WAPPKEY);
00261 #else
00262       // just a simple data packet
00263       sx1272.setPacketType(PKT_TYPE_DATA);
00264 #endif
00265       
00266       // Send message to the gateway and print the result
00267       // with the app key if this feature is enabled
00268 #ifdef WITH_ACK
00269       int n_retry=NB_RETRIES;
00270       do {
00271         e = sx1272.sendPacketTimeoutACK(DEFAULT_DEST_ADDR, message, pl);
00272         if (e==3) printf("No ACK");
00273         n_retry--;
00274         if (n_retry) printf("Retry");
00275         else printf("Abort"); 
00276       } while (e && n_retry);          
00277 #else      
00278       e = sx1272.sendPacketTimeout(DEFAULT_DEST_ADDR, message, pl);
00279 #endif  
00280       endSend=millis();
00281 #ifdef WITH_EEPROM
00282       // save packet number for next packet in case of reboot
00283       my_sx1272config.seq=sx1272._packetNumber;
00284       EEPROM.put(0, my_sx1272config);
00285 #endif
00286 
00287       printf("LoRa pkt size %d\n",pl);
00288       printf("LoRa pkt seq %d\n",sx1272.packet_sent.packnum);
00289       printf("LoRa Sent in %ld\n",endSend-startSend);
00290       printf("LoRa Sent w/CAD in %ld\n", endSend-sx1272._startDoCad);
00291       printf("Packet sent, state %d\n",e);
00292       printf("Remaining ToA is %d\n",sx1272.getRemainingToA());
00293       
00294  // compute next time transmission in seconds
00295       int waitting = rand()%maxTime+minTime;   // waitting in Sec
00296       printf("Switch to power saving mode\n");
00297       e = sx1272.setSleepMode();
00298       if (!e)
00299         printf("Successfully switch LoRa module in sleep mode\n");
00300       else  
00301         printf("Could not switch LoRa module in sleep mode\n");
00302       // Deep sleep 
00303       printf("Deep sleep allowed: %i for %d seconds\n", sleep_manager_can_deep_sleep(), waitting);
00304       wait(waitting);
00305 }//  end loop
00306 
00307 //return (0);  useless here, the program never ends
00308 
00309 }