p2p-pingpong-clickbutton
Dependencies: PingPong-P2P-ClickButtonToWork-SX1272 Lora_SX1272_Coragem
Diff: main.cpp
- Revision:
- 0:9859cc8476f2
- Child:
- 1:9f961d34dd8d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Nov 05 14:32:09 2017 +0000 @@ -0,0 +1,668 @@ +/* + * 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); + +}