p2p-pingpong-clickbutton
Dependencies: PingPong-P2P-ClickButtonToWork-SX1272 Lora_SX1272_Coragem
main.cpp
- Committer:
- cdupaty
- Date:
- 2017-11-05
- Revision:
- 0:9859cc8476f2
- Child:
- 1:9f961d34dd8d
File content as of revision 0:9859cc8476f2:
/* * 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 */ #include "mbed.h" #include <SPI.h> // Include the SX1272 #include "SX1272.h" // IMPORTANT /////////////////////////////////////////////////////////////////////////////////////////////////////////// // please uncomment only 1 choice // #define ETSI_EUROPE_REGULATION //#define FCC_US_REGULATION //#define SENEGAL_REGULATION /////////////////////////////////////////////////////////////////////////////////////////////////////////// // IMPORTANT /////////////////////////////////////////////////////////////////////////////////////////////////////////// // please uncomment only 1 choice #define BAND868 //#define BAND900 //#define BAND433 /////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifdef ETSI_EUROPE_REGULATION #define MAX_DBM 14 // previous way for setting output power // char powerLevel='M'; #elif defined SENEGAL_REGULATION #define MAX_DBM 10 // previous way for setting output power // 'H' is actually 6dBm, so better to use the new way to set output power // char powerLevel='H'; #elif defined FCC_US_REGULATION #define MAX_DBM 14 #endif #ifdef BAND868 #ifdef SENEGAL_REGULATION const uint32_t DEFAULT_CHANNEL=CH_04_868; #else const uint32_t DEFAULT_CHANNEL=CH_10_868; #endif #elif defined BAND900 const uint32_t DEFAULT_CHANNEL=CH_05_900; #elif defined BAND433 const uint32_t DEFAULT_CHANNEL=CH_00_433; #endif // IMPORTANT /////////////////////////////////////////////////////////////////////////////////////////////////////////// // // uncomment if your radio is an HopeRF RFM92W, HopeRF RFM95W, Modtronix inAir9B, NiceRF1276 // or you known from the circuit diagram that output use the PABOOST line instead of the RFO line //#define PABOOST /////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // COMMENT OR UNCOMMENT TO CHANGE FEATURES. // ONLY IF YOU KNOW WHAT YOU ARE DOING!!! OTHERWISE LEAVE AS IT IS //#define WITH_EEPROM // tous uncomment a l origine sauf WITH_ACK #define WITH_APPKEY #define FLOAT_TEMP #define NEW_DATA_FIELD //#define LOW_POWER //#define LOW_POWER_HIBERNATE //#define WITH_ACK /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // ADD HERE OTHER PLATFORMS THAT DO NOT SUPPORT EEPROM NOR LOW POWER #if defined ARDUINO_SAM_DUE || defined __SAMD21G18A__ || defined TARGET_NUCLEO_L073RZ #undef WITH_EEPROM #endif #if defined ARDUINO_SAM_DUE || defined TARGET_NUCLEO_L073RZ #undef LOW_POWER #endif /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // 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_0 // use digital 9 to power the temperature sensor if needed #define TEMP_PIN_POWER PA_1 /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// // CHANGE HERE THE TIME IN MINUTES BETWEEN 2 READING & TRANSMISSION unsigned int idlePeriodInMin = 2; /////////////////////////////////////////////////////////////////// #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 // we wrapped Serial.println to support the Arduino Zero or M0 #if defined __SAMD21G18A__ && not defined ARDUINO_SAMD_FEATHER_M0 #define PRINTLN SerialUSB.println("") #define PRINT_CSTSTR(fmt,param) SerialUSB.print(F(param)) #define PRINT_STR(fmt,param) SerialUSB.print(param) #define PRINT_VALUE(fmt,param) SerialUSB.print(param) #define FLUSHOUTPUT SerialUSB.flush(); #else #define PRINTLN Serial.println("") #define PRINT_CSTSTR(fmt,param) Serial.print(F(param)) #define PRINT_STR(fmt,param) Serial.print(param) #define PRINT_VALUE(fmt,param) Serial.print(param) #define FLUSHOUTPUT Serial.flush(); #endif #ifdef WITH_EEPROM #include <EEPROM.h> #endif #define DEFAULT_DEST_ADDR 1 #ifdef WITH_ACK #define NB_RETRIES 2 #endif #if defined ARDUINO_AVR_PRO || defined ARDUINO_AVR_MINI || defined ARDUINO_SAM_DUE || defined __MK20DX256__ || defined __MKL26Z64__ || defined __MK64FX512__ || defined __MK66FX1M0__ || defined __SAMD21G18A__ // if you have a Pro Mini running at 5V, then change here // these boards work in 3.3V // Nexus board from Ideetron is a Mini // __MK66FX1M0__ is for Teensy36 // __MK64FX512__ is for Teensy35 // __MK20DX256__ is for Teensy31/32 // __MKL26Z64__ is for TeensyLC // __SAMD21G18A__ is for Zero/M0 and FeatherM0 (Cortex-M0) #define TEMP_SCALE 3300.0 #else // ARDUINO_AVR_NANO || defined ARDUINO_AVR_UNO || defined ARDUINO_AVR_MEGA2560 // also for all other boards, so change here if required. #define TEMP_SCALE 5000.0 #endif #ifdef LOW_POWER // this is for the Teensy36, Teensy35, Teensy31/32 & TeensyLC // need v6 of Snooze library #if defined __MK20DX256__ || defined __MKL26Z64__ || defined __MK64FX512__ || defined __MK66FX1M0__ #define LOW_POWER_PERIOD 60 #include <Snooze.h> SnoozeTimer timer; SnoozeBlock sleep_config(timer); //#elif defined ARDUINO_AVR_FEATHER32U4 //#define LOW_POWER_PERIOD 8 //#include "Adafruit_SleepyDog.h" #else // for all other boards based on ATMega168, ATMega328P, ATMega32U4, ATMega2560, ATMega256RFR2, ATSAMD21G18A #define LOW_POWER_PERIOD 8 // you need the LowPower library from RocketScream // https://github.com/rocketscream/Low-Power #include "LowPower.h" #ifdef __SAMD21G18A__ // use the RTC library #include "RTCZero.h" /* Create an rtc object */ RTCZero rtc; #endif #endif unsigned int nCycle = idlePeriodInMin*60/LOW_POWER_PERIOD; #endif double temp; unsigned long nextTransmissionTime=0L; char float_str[20]; uint8_t message[100]; int loraMode=LORAMODE; #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 // ajoute par C.Dupaty //Serial pcmain(USBTX, USBRX); // tx, rx DigitalOut temp_pin_power(TEMP_PIN_POWER); AnalogIn temp_pin_read(TEMP_PIN_READ); void setup() { int e; // for the temperature sensor //pinMode(TEMP_PIN_READ, INPUT); // and to power the temperature sensor //pinMode(TEMP_PIN_POWER,OUTPUT); #ifdef LOW_POWER #ifdef __SAMD21G18A__ rtc.begin(); #endif #else // digitalWrite(TEMP_PIN_POWER,HIGH); temp_pin_power=1; #endif wait_ms(3000); /* // Open serial communications and wait for port to open: #if defined __SAMD21G18A__ && not defined ARDUINO_SAMD_FEATHER_M0 SerialUSB.begin(38400); #else Serial.begin(38400); #endif */ // Print a start message printf("%s","Simple LoRa temperature sensor\n"); printf("%s","--------------------------------\n"); printf("%s","---- VERSION NUCLEO STM32-------\n"); printf("%s","--------------------------------\n"); #ifdef ARDUINO_AVR_PRO printf("%s","Arduino Pro Mini detected\n"); #endif #ifdef ARDUINO_AVR_NANO printf("%s","Arduino Nano detected\n"); #endif #ifdef ARDUINO_AVR_MINI printf("%s","Arduino Mini/Nexus detected\n"); #endif #ifdef ARDUINO_AVR_MEGA2560 printf("%s","Arduino Mega2560 detected\n"); #endif #ifdef ARDUINO_SAM_DUE printf("%s","Arduino Due detected\n"); #endif #ifdef __MK66FX1M0__ printf("%s","Teensy36 MK66FX1M0 detected\n"); #endif #ifdef __MK64FX512__ printf("%s","Teensy35 MK64FX512 detected\n"); #endif #ifdef __MK20DX256__ printf("%s","Teensy31/32 MK20DX256 detected\n"); #endif #ifdef __MKL26Z64__ printf("%s","TeensyLC MKL26Z64 detected\n"); #endif #ifdef ARDUINO_SAMD_ZERO printf("%s","Arduino M0/Zero detected\n"); #endif #ifdef ARDUINO_AVR_FEATHER32U4 printf("%s","Adafruit Feather32U4 detected\n"); #endif #ifdef ARDUINO_SAMD_FEATHER_M0 printf("%s","Adafruit FeatherM0 detected\n"); #endif // See http://www.nongnu.org/avr-libc/user-manual/using_tools.html // for the list of define from the AVR compiler #ifdef __AVR_ATmega328P__ printf("%s","ATmega328P detected\n"); #endif #ifdef __AVR_ATmega32U4__ printf("%s","ATmega32U4 detected\n"); #endif #ifdef __AVR_ATmega2560__ printf("%s","ATmega2560 detected\n"); #endif #ifdef __SAMD21G18A__ printf("%s","SAMD21G18A ARM Cortex-M0 detected\n"); #endif #ifdef __SAM3X8E__ printf("%s","SAM3X8E ARM Cortex-M3 detected\n"); #endif #ifdef TARGET_NUCLEO_L073RZ printf("%s","NUCLEO L073RZ detected\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("%s","Get back previous sx1272 config\n"); // set sequence number for SX1272 library sx1272._packetNumber=my_sx1272config.seq; printf("%s","Using packet sequence number of "); printf("%d", sx1272._packetNumber); printf("\n"); } 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 printf("%s","\n-------------------------DEBUT Setting mode -----------> \n"); e = sx1272.setMode(loraMode); printf("%s","\n-------------------------FIN Setting mode -----------> \n"); if (e) error_config_sx1272=1; printf("%s","Setting Mode: state "); printf("%d", e); printf("\n"); // enable carrier sense sx1272._enableCarrierSense=true; #ifdef LOW_POWER // TODO: with low power, when setting the radio module in sleep mode // there seem to be some issue with RSSI reading sx1272._RSSIonSend=false; #endif // Select frequency channel e = sx1272.setChannel(DEFAULT_CHANNEL); if (e) error_config_sx1272=1; printf("%s","Setting Channel: state "); printf("%d", e); printf("\n"); // 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("%s","Setting Power: state "); printf("%d", e); printf("\n"); // Set the node address and print the result e = sx1272.setNodeAddress(node_addr); if (e) error_config_sx1272=1; printf("%s","Setting node addr: state "); printf("%d", e); printf("\n"); // Print a success message if (!error_config_sx1272) printf("%s","SX1272 successfully configured\n"); else printf("%s","ERREUR DE CONFIGURATION DU SX1272\n"); wait_ms(500); } char *ftoa(char *a, double f, int precision) { long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000}; char *ret = a; long heiltal = (long)f; //modifie pa C.Dupaty // itoa(heiltal, a, 10); sprintf(a,"%d",heiltal); while (*a != '\0') a++; *a++ = '.'; long desimal = abs((long)((f - heiltal) * p[precision])); if (desimal < p[precision-1]) { *a++ = '0'; } //modifie pa C.Dupaty // itoa(desimal, a, 10); sprintf(a,"%d",desimal); return ret; } ////////////////////////////////////////////////////////////// // programme principal , loop sur Arduino ////////////////////////////////////////////////////////////// int main(void) { long startSend; long endSend; uint8_t app_key_offset=0; int e; setup(); while(1) { /////////////// debut boucle //printf("%s","\n-------------------------BOUCLE SANS FIN -----------> \n"); //while(1); #ifndef LOW_POWER // 600000+random(15,60)*1000 if (millis() > nextTransmissionTime) { #endif #ifdef LOW_POWER // digitalWrite(TEMP_PIN_POWER,HIGH); temp_pin_power=1; // security? wait_ms(200); #endif temp = 0; int value; for (int i=0; i<10; i++) { // change here how the temperature should be computed depending on your sensor type // value = temp_pin_read; temp += (value*TEMP_SCALE/1024.0)/10; printf("%s","Reading "); printf("%d", value); printf("\n"); wait_ms(100); } #ifdef LOW_POWER //digitalWrite(TEMP_PIN_POWER,LOW); temp_pin_ower=0; #endif printf("%s","Mean temp is "); temp = temp/10; printf("%f", temp); printf("\n"); #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; #ifdef FLOAT_TEMP ftoa(float_str,temp,2); #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 #else #ifdef NEW_DATA_FIELD r_size=sprintf((char*)message+app_key_offset, "\\!#%d#TC/%d", field_index, (int)temp); #else r_size=sprintf((char*)message+app_key_offset, "\\!#%d#%d", field_index, (int)temp); #endif #endif printf("%s","Sending "); printf("%s",(char*)(message+app_key_offset)); printf("\n"); printf("%s","Real payload size is "); printf("%d", r_size); printf("\n"); 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("%s","No ACK"); n_retry--; if (n_retry) printf("%s","Retry"); else printf("%s","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("%s","LoRa pkt size "); printf("%d", pl); printf("\n"); printf("%s","LoRa pkt seq "); printf("%d", sx1272.packet_sent.packnum); printf("\n"); printf("%s","LoRa Sent in "); printf("%ld", endSend-startSend); printf("\n"); printf("%s","LoRa Sent w/CAD in "); printf("%ld", endSend-sx1272._startDoCad); printf("\n"); printf("%s","Packet sent, state "); printf("%d", e); printf("\n"); printf("%s","Remaining ToA is "); printf("%d", sx1272.getRemainingToA()); printf("\n"); #if defined LOW_POWER && not defined ARDUINO_SAM_DUE printf("%s","Switch to power saving mode\n"); e = sx1272.setSleepMode(); if (!e) printf("%s","Successfully switch LoRa module in sleep mode\n"); else printf("%s","Could not switch LoRa module in sleep mode\n"); FLUSHOUTPUT wait_ms(50); #ifdef __SAMD21G18A__ // For Arduino M0 or Zero we use the built-in RTC //LowPower.standby(); rtc.setTime(17, 0, 0); rtc.setDate(1, 1, 2000); rtc.setAlarmTime(17, idlePeriodInMin, 0); // for testing with 20s //rtc.setAlarmTime(17, 0, 20); rtc.enableAlarm(rtc.MATCH_HHMMSS); //rtc.attachInterrupt(alarmMatch); rtc.standbyMode(); printf("%s","SAMD21G18A wakes up from standby\n"); FLUSHOUTPUT #else nCycle = idlePeriodInMin*60/LOW_POWER_PERIOD + random(2,4); #if defined __MK20DX256__ || defined __MKL26Z64__ || defined __MK64FX512__ || defined __MK66FX1M0__ // warning, setTimer accepts value from 1ms to 65535ms max timer.setTimer(LOW_POWER_PERIOD*1000 + random(1,5)*1000);// milliseconds nCycle = idlePeriodInMin*60/LOW_POWER_PERIOD; #endif for (int i=0; i<nCycle; i++) { #if defined ARDUINO_AVR_PRO || defined ARDUINO_AVR_NANO || defined ARDUINO_AVR_UNO || defined ARDUINO_AVR_MINI || defined __AVR_ATmega32U4__ // ATmega328P, ATmega168, ATmega32U4 LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); //LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, // SPI_OFF, USART0_OFF, TWI_OFF); #elif defined ARDUINO_AVR_MEGA2560 // ATmega2560 LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); //LowPower.idle(SLEEP_8S, ADC_OFF, TIMER5_OFF, TIMER4_OFF, TIMER3_OFF, // TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART3_OFF, // USART2_OFF, USART1_OFF, USART0_OFF, TWI_OFF); #elif defined __MK20DX256__ || defined __MKL26Z64__ || defined __MK64FX512__ || defined __MK66FX1M0__ // Teensy31/32 & TeensyLC #ifdef LOW_POWER_HIBERNATE Snooze.hibernate(sleep_config); #else Snooze.deepSleep(sleep_config); #endif #else // use the wait_ms function wait_ms(LOW_POWER_PERIOD*1000); #endif printf("%s","."); FLUSHOUTPUT wait_ms(10); } wait_ms(50); #endif #else printf("%ld ", nextTransmissionTime); printf("%s","Will send next value at "); // use a random part also to avoid collision nextTransmissionTime=millis()+(unsigned long)idlePeriodInMin*60*1000+(unsigned long)(rand()%60+15)*1000; printf("%ld", nextTransmissionTime); printf("\n"); } #endif }// fin boucle //return (0); }