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

This project is an adaptation of C.Pham project, university of Pau, France. Initially developed for Arduino, the library sx1272 and the test program was focused on NUCLEO STM32 by C.Dupaty, high school Fourcade 13120 Gardanne.

Tested on NUCLEO L073 with

- SX1272MB2xAS SHIELD

/media/uploads/cdupaty/picture3.png.200x200_q85.png

- DRAGINO SHIELD V95 WITH GPS http://wiki.dragino.com/index.php?title=Lora/GPS_Shield For DRAGINO move LORA_CLK LORA_DI LORA_DO straps to the right (arduino 11 12 13)

/media/uploads/cdupaty/lora_gps_shield_1.jpg

ALL CONFIGURATIONS FOR ARDUINO HAVE BEEN REMOVED WORK ONLY IN EUROPE

please visit http://cpham.perso.univ-pau.fr/LORA/LoRaDevices.html for original version for ARDUINO

main.cpp

Committer:
cdupaty
Date:
2018-02-06
Revision:
2:4eef0eca4d26
Parent:
1:9f961d34dd8d

File content as of revision 2:4eef0eca4d26:

/*
 *  temperature sensor on analog 8 to test the LoRa gateway
 *
 *  Copyright (C) 2016 Congduc Pham, University of Pau, France
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.

 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with the program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *****************************************************************************
 * last update: Sep. 29th, 2017 by C. Pham
 * last update: oct 30th , 2017 by C.Dupaty
 * ADAPTATION FOR NUCLEO STM32, TESTED ON NUCLEO-L073RZ WITH 
 * SX1272MB2xAS SHIELD
 * DRAGINO SHIELD V95 WITH GPS  http://wiki.dragino.com/index.php?title=Lora/GPS_Shield 
 *      For DRAGINO move LORA_CLK LORA_DI LORA_DO straps to the right (arduino 11 12 13)
 * ALL CONFIGURATIONS FOR ARDUINO HAVE BEEN REMOVED
 * WORK ONLY IN EUROPE
 * please visit http://cpham.perso.univ-pau.fr/LORA/LoRaDevices.html
 * for original version for ARDUINO 
*/
  
#include "mbed.h"
#include "SX1272.h"
#define BAND868
#define MAX_DBM 14

const uint32_t DEFAULT_CHANNEL=CH_10_868;  // for BAND868

//#define WITH_EEPROM            //  TO DO ON STM32
#define WITH_APPKEY
#define NEW_DATA_FIELD
#define WITH_ACK

///////////////////////////////////////////////////////////////////
// CHANGE HERE THE LORA MODE, NODE ADDRESS 
#define LORAMODE  1
#define node_addr 6
//////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
// CHANGE HERE THE THINGSPEAK FIELD BETWEEN 1 AND 4
#define field_index 1
///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
// CHANGE HERE THE READ PIN AND THE POWER PIN FOR THE TEMP. SENSOR
#define TEMP_PIN_READ  PA_4
// use digital 9 to power the temperature sensor if needed
#define TEMP_PIN_POWER PB_0
///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
// CHANGE HERE THE TIME IN SECONDS BETWEEN 2 READING & TRANSMISSION
#define minTime 120 // 2 minutes
#define maxTime 600 // 10 minutes
///////////////////////////////////////////////////////////////////

#ifdef WITH_APPKEY
///////////////////////////////////////////////////////////////////
// CHANGE HERE THE APPKEY, BUT IF GW CHECKS FOR APPKEY, MUST BE
// IN THE APPKEY LIST MAINTAINED BY GW.
uint8_t my_appKey[4]={5, 6, 7, 8};
///////////////////////////////////////////////////////////////////
#endif

#ifdef WITH_EEPROM
#include <EEPROM.h>
#endif

#define DEFAULT_DEST_ADDR 1

#ifdef WITH_ACK
#define NB_RETRIES 2
#endif

#ifdef WITH_EEPROM
struct sx1272config {

  uint8_t flag1;
  uint8_t flag2;
  uint8_t seq;
  // can add other fields such as LoRa mode,...
};

sx1272config my_sx1272config;
#endif

///////////////////////////////////////
// Globals variables
///////////////////////////////////////
int loraMode=LORAMODE;
// added by C.Dupaty
// For test with LM35DZ temperature captor
DigitalOut temp_pin_power(TEMP_PIN_POWER);
AnalogIn temp_pin_read(TEMP_PIN_READ);

/////////////////////////////////////////
// SETUP SX1272 initialisation
////////////////////////////////////////
void setup()
{
  int e;
  // Print welcome message
  printf("-------------------------------------------------\n");
  printf("------Simple LoRa temperature sensor-------------\n");
  printf("--P.Pharm, adaptation NUCELO STM32 C.Dupaty------\n");
  printf("-------------------------------------------------\n\n");
  printf("!!!!!!!!! During configuration, all states numbers must read at 0\n");
 
#ifdef TARGET_NUCLEO_L073RZ
  printf("NUCLEO L073RZ detected\n");
#else
  printf("WARNING, this software has been tested on NUCLEO L073RZ only !!!\n"); 
#endif

  // Power ON the module
  sx1272.ON();

#ifdef WITH_EEPROM
  // get config from EEPROM
  EEPROM.get(0, my_sx1272config);

  // found a valid config?
  if (my_sx1272config.flag1==0x12 && my_sx1272config.flag2==0x34) {
    printf("Get back previous sx1272 config\n");

    // set sequence number for SX1272 library
    sx1272._packetNumber=my_sx1272config.seq;
    printf("Using packet sequence number of %d\n",sx1272._packetNumber);
  }
  else {
    // otherwise, write config and start over
    my_sx1272config.flag1=0x12;
    my_sx1272config.flag2=0x34;
    my_sx1272config.seq=sx1272._packetNumber;
  }
#endif
  
  int error_config_sx1272=0;
  
  // Set transmission mode and print the result
  e = sx1272.setMode(loraMode);
  if (e) error_config_sx1272=1;
  printf("Setting Mode: state %d\n",e);
  
  // enable carrier sense
  sx1272._enableCarrierSense=true;

  // for LOW POWER
  sx1272._RSSIonSend=false;

    
  // Select frequency channel
  e = sx1272.setChannel(DEFAULT_CHANNEL);
  if (e) error_config_sx1272=1;
  printf("Setting Channel: state %d\n",e);
  
  // Select amplifier line; PABOOST or RFO
#ifdef PABOOST
  sx1272._needPABOOST=true;
  // previous way for setting output power
  // powerLevel='x';
#else
  // previous way for setting output power
  // powerLevel='M';  
#endif

  // previous way for setting output power
  // e = sx1272.setPower(powerLevel); 

  e = sx1272.setPowerDBM((uint8_t)MAX_DBM);
  if (e) error_config_sx1272=1;
  printf("Setting Power: state %d\n",e);
  
  // Set the node address and print the result
  e = sx1272.setNodeAddress(node_addr);
  if (e) error_config_sx1272=1;
  printf("Setting node addr: state %d\n",e);
  
  // Print a success message
  if (!error_config_sx1272) printf("SX1272 successfully configured\n");
  else printf("ERREUR DE CONFIGURATION DU SX1272\n");

  wait_ms(500);
}

//////////////////////////////////////////////////////////////
//  main was named loop on Arduino
//////////////////////////////////////////////////////////////
int main(void)      // return int for cpp compatibility but never ending the program
{
long startSend;
long endSend;
uint8_t app_key_offset=0;
int e;
double temp;            // variable temperature in this demo 
char float_str[20];
uint8_t message[100];   // the message that will be send to the gateway

setup();
 
 // main loop start here 
while(1)  {  

// this demo use a LM35DZ temerature captor
      temp_pin_power=1;         // LM35DZ is powering by a simple GPIO
      wait_ms(200);   
      temp = 0;
      int value;
      for (int i=0; i<10; i++) {
          // compute temperature for LM35DZ captor
          value = temp_pin_read.read_u16();
          temp += ((double)value*50.0/8192.0)/10;
          printf("Reading ADC temperature %d/10 -> %d\n",i,value);
          wait_ms(100);
      } 
      temp_pin_power=0;         // LM35DZ power off
      printf("Mean temp is %f Cent\n",temp);
// we have now temperature in the variable temp      

#ifdef WITH_APPKEY
      app_key_offset = sizeof(my_appKey);
      // set the app key in the payload
      memcpy(message,my_appKey,app_key_offset);
#endif

      uint8_t r_size;
      
        // convert float temp to string ASCII
        sprintf(float_str,"%2.2f",temp);
        #ifdef NEW_DATA_FIELD
              // this is for testing, uncomment if you just want to test, without a real temp sensor plugged
              //strcpy(float_str, "21.55567");
              r_size=sprintf((char*)message+app_key_offset,"\\!#%d#TC/%s",field_index,float_str);
        #else
              // this is for testing, uncomment if you just want to test, without a real temp sensor plugged
              //strcpy(float_str, "21.55567");
              r_size=sprintf((char*)message+app_key_offset,"\\!#%d#%s",field_index,float_str);
        #endif
          
      printf("Sending %s\n",message+app_key_offset);
      printf("Real payload size is %d\n",r_size);
     
      int pl=r_size+app_key_offset;
      sx1272.CarrierSense();
      startSend=millis();

#ifdef WITH_APPKEY
      // indicate that we have an appkey
      sx1272.setPacketType(PKT_TYPE_DATA | PKT_FLAG_DATA_WAPPKEY);
#else
      // just a simple data packet
      sx1272.setPacketType(PKT_TYPE_DATA);
#endif
      
      // Send message to the gateway and print the result
      // with the app key if this feature is enabled
#ifdef WITH_ACK
      int n_retry=NB_RETRIES;
      do {
        e = sx1272.sendPacketTimeoutACK(DEFAULT_DEST_ADDR, message, pl);
        if (e==3) printf("No ACK");
        n_retry--;
        if (n_retry) printf("Retry");
        else printf("Abort"); 
      } while (e && n_retry);          
#else      
      e = sx1272.sendPacketTimeout(DEFAULT_DEST_ADDR, message, pl);
#endif  
      endSend=millis();
#ifdef WITH_EEPROM
      // save packet number for next packet in case of reboot
      my_sx1272config.seq=sx1272._packetNumber;
      EEPROM.put(0, my_sx1272config);
#endif

      printf("LoRa pkt size %d\n",pl);
      printf("LoRa pkt seq %d\n",sx1272.packet_sent.packnum);
      printf("LoRa Sent in %ld\n",endSend-startSend);
      printf("LoRa Sent w/CAD in %ld\n", endSend-sx1272._startDoCad);
      printf("Packet sent, state %d\n",e);
      printf("Remaining ToA is %d\n",sx1272.getRemainingToA());
      
 // compute next time transmission in seconds
      int waitting = rand()%maxTime+minTime;   // waitting in Sec
      printf("Switch to power saving mode\n");
      e = sx1272.setSleepMode();
      if (!e)
        printf("Successfully switch LoRa module in sleep mode\n");
      else  
        printf("Could not switch LoRa module in sleep mode\n");
      // Deep sleep 
      printf("Deep sleep allowed: %i for %d seconds\n", sleep_manager_can_deep_sleep(), waitting);
      wait(waitting);
}//  end loop

//return (0);  useless here, the program never ends

}