CongducPham / LowCostLoRaGw

Low-cost LoRa IoT & gateway with SX12XX (SX1261/62/68; SX1272/76/77/78/79; SX1280/81), RaspberryPI and Arduino boards
694 stars 352 forks source link

Low-power mode #86

Open namsontr opened 7 years ago

namsontr commented 7 years ago

Hi Mr Pham Cong Duc, I used Arduino Pro Mini in its 3.3v, 8MHz which connected the HopeRF RFM 92W (Low-cost LoRa Iot Device: A step-by-step tutorial). But when i removed the power led and the board was put in <>, Wakes-up every 10 min, take a measure (temp) and send to GW 45 mA in sleep mode (expected 160uA in deep sleep mode) , 160 mA when active and sending. Do you have any ideal this situation? Thank you so much in advance for your valuable help.

CongducPham commented 7 years ago

Which example are you compiling?

Regards,

Le 22/03/2017 à 18:26, namsontr a écrit :

Hi Mr Pham Cong Duc, I used Arduino Pro Mini in its 3.3v, 8MHz which connected the HopeRF RFM 92W (Low-cost LoRa Iot Device: A step-by-step tutorial). But when i removed the power led and the board was put in <>, Wakes-up every 10 min, take a measure (temp) and send to GW 45 mA in sleep mode (expected 160uA in deep sleep mode) , 160 mA when active and sending. Do you have any ideal this situation? Thank you so much in advance for your valuable help.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/CongducPham/LowCostLoRaGw/issues/86, or mute the thread https://github.com/notifications/unsubscribe-auth/ABNEN-u6UJ9jTt28fZ3HzEmxkUDvwJVMks5roVm7gaJpZM4Mljzr.

C. Pham.

-- ------------ Congduc PHAM - Professor -------------------------- LIUPPA - Equipe T2I U.P.P.A. Pau http://liuppa.univ-pau.fr/ http://www.univ-pau.fr
UPPA, LIUPPA laboratory, UFR Sciences et Techniques
Avenue de l'Université - BP 1155
64013 PAU CEDEX, FRANCE
phone: [33] (0) 5 59 40 75 94
fax: [33] (0) 5 59 40 76 54
Congduc.Pham@univ-pau.fr http://www.univ-pau.fr/~cpham
----------------------------------------------------------------
namsontr commented 7 years ago

I'm compiling Arduino_Lora_temp & Arduino_Lora_Simple_temp. Uncomment Paboost, powerlevel='x'. Thank you for your quickly answer.

CongducPham commented 7 years ago

is LOW_POWER uncommented?

Le 22/03/2017 à 21:55, namsontr a écrit :

I'm compiling Arduino_Lora_temp & Arduino_Lora_Simple_temp. Uncomment Paboost, powerlevel='x'. Thank you for your quickly answer.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/CongducPham/LowCostLoRaGw/issues/86#issuecomment-288536630, or mute the thread https://github.com/notifications/unsubscribe-auth/ABNEN0KvvReEFfpHp-gVO_qIWII-rm2_ks5roYq3gaJpZM4Mljzr.

C. Pham.

-- ------------ Congduc PHAM - Professor -------------------------- LIUPPA - Equipe T2I U.P.P.A. Pau http://liuppa.univ-pau.fr/ http://www.univ-pau.fr
UPPA, LIUPPA laboratory, UFR Sciences et Techniques
Avenue de l'Université - BP 1155
64013 PAU CEDEX, FRANCE
phone: [33] (0) 5 59 40 75 94
fax: [33] (0) 5 59 40 76 54
Congduc.Pham@univ-pau.fr http://www.univ-pau.fr/~cpham
----------------------------------------------------------------
namsontr commented 7 years ago

Yes, uncomment Low_power. Successfully switch Lora module in sleep mode. This is your code:

/*

// 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='x';

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

if not defined _VARIANT_ARDUINO_DUEX && not defined SAMD21G18A

define WITH_EEPROM

endif

define WITH_APPKEY

define FLOAT_TEMP

//#define NEW_DATA_FIELD

define LOW_POWER

define LOW_POWER_HIBERNATE

//#define WITH_ACK ///////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////// // CHANGE HERE THE LORA MODE, NODE ADDRESS

define LORAMODE 1

define node_addr 10

//////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////// // 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 A0

// use digital 8 to power the temperature sensor if needed

define TEMP_PIN_POWER 8

///////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////// // CHANGE HERE THE TIME IN MINUTES BETWEEN 2 READING & TRANSMISSION unsigned int idlePeriodInMin = 3; ///////////////////////////////////////////////////////////////////

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

endif

define DEFAULT_DEST_ADDR 1

ifdef WITH_ACK

define NB_RETRIES 2

endif

if defined ARDUINO_AVR_PRO || defined ARDUINO_AVR_MINI || 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

SnoozeTimer timer; SnoozeBlock sleep_config(timer);

else

define LOW_POWER_PERIOD 8

// you need the LowPower library from RocketScream // https://github.com/rocketscream/Low-Power

include

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

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);

endif

delay(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 PRINT_CSTSTR("%s","Simple LoRa temperature sensor\n");

ifdef ARDUINO_AVR_PRO

PRINT_CSTSTR("%s","Arduino Pro Mini detected\n");

endif

ifdef ARDUINO_AVR_NANO

PRINT_CSTSTR("%s","Arduino Nano detected\n");

endif

ifdef ARDUINO_AVR_MINI

PRINT_CSTSTR("%s","Arduino MINI/Nexus detected\n");

endif

ifdef MK20DX256

PRINT_CSTSTR("%s","Teensy31/32 detected\n");

endif

ifdef SAMD21G18A

PRINT_CSTSTR("%s","Arduino M0/Zero 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) { PRINT_CSTSTR("%s","Get back previous sx1272 config\n");

// set sequence number for SX1272 library
sx1272._packetNumber=my_sx1272config.seq;
PRINT_CSTSTR("%s","Using packet sequence number of ");
PRINT_VALUE("%d", sx1272._packetNumber);
PRINTLN;

} else { // otherwise, write config and start over my_sx1272config.flag1=0x12; my_sx1272config.flag2=0x34; my_sx1272config.seq=sx1272._packetNumber; }

endif

// Set transmission mode and print the result e = sx1272.setMode(loraMode); PRINT_CSTSTR("%s","Setting Mode: state "); PRINT_VALUE("%d", e); PRINTLN;

// 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); PRINT_CSTSTR("%s","Setting Channel: state "); PRINT_VALUE("%d", e); PRINTLN;

// 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); PRINT_CSTSTR("%s","Setting Power: state "); PRINT_VALUE("%d", e); PRINTLN;

// Set the node address and print the result e = sx1272.setNodeAddress(node_addr); PRINT_CSTSTR("%s","Setting node addr: state "); PRINT_VALUE("%d", e); PRINTLN;

// Print a success message PRINT_CSTSTR("%s","SX1272 successfully configured\n");

delay(500); }

if not defined _VARIANT_ARDUINO_DUEX && defined FLOAT_TEMP

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; itoa(heiltal, a, 10); while (a != '\0') a++; a++ = '.'; long desimal = abs((long)((f - heiltal) p[precision])); itoa(desimal, a, 10); return ret; }

endif

void loop(void) { long startSend; long endSend; uint8_t app_key_offset=0; int e;

ifndef LOW_POWER

// 600000+random(15,60)*1000 if (millis() > nextTransmissionTime) {

endif

ifdef LOW_POWER

  digitalWrite(TEMP_PIN_POWER,HIGH);
  // security?
  delay(200);    
  int value = analogRead(TEMP_PIN_READ);
  digitalWrite(TEMP_PIN_POWER,LOW);

else

  int value = analogRead(TEMP_PIN_READ);

endif

  // change here how the temperature should be computed depending on your sensor type
  //  
  temp = value*TEMP_SCALE/1024.0;

  PRINT_CSTSTR("%s","Reading ");
  PRINT_VALUE("%d", value);
  PRINTLN;

  //temp = temp - 0.5;
  temp = temp / 10.0;

  PRINT_CSTSTR("%s","Temp is ");
  PRINT_VALUE("%f", temp);
  PRINTLN;

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;

  // then use app_key_offset to skip the app key

ifdef _VARIANT_ARDUINO_DUEX

ifdef NEW_DATA_FIELD

  r_size=sprintf((char*)message+app_key_offset, "\\!#%d#TC/%.2f", field_index, temp);

else

  r_size=sprintf((char*)message+app_key_offset, "\\!#%d#%.2f", field_index, temp);

endif

else

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

endif

  PRINT_CSTSTR("%s","Sending ");
  PRINT_STR("%s",(char*)(message+app_key_offset));
  PRINTLN;

  PRINT_CSTSTR("%s","Real payload size is ");
  PRINT_VALUE("%d", r_size);
  PRINTLN;

  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)
      PRINT_CSTSTR("%s","No ACK");

    n_retry--;

    if (n_retry)
      PRINT_CSTSTR("%s","Retry");
    else
      PRINT_CSTSTR("%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

  PRINT_CSTSTR("%s","LoRa pkt size ");
  PRINT_VALUE("%d", pl);
  PRINTLN;

  PRINT_CSTSTR("%s","LoRa pkt seq ");
  PRINT_VALUE("%d", sx1272.packet_sent.packnum);
  PRINTLN;

  PRINT_CSTSTR("%s","LoRa Sent in ");
  PRINT_VALUE("%ld", endSend-startSend);
  PRINTLN;

  PRINT_CSTSTR("%s","LoRa Sent w/CAD in ");
  PRINT_VALUE("%ld", endSend-sx1272._startDoCad);
  PRINTLN;

  PRINT_CSTSTR("%s","Packet sent, state ");
  PRINT_VALUE("%d", e);
  PRINTLN;

  PRINT_CSTSTR("%s","Remaining ToA is ");
  PRINT_VALUE("%d", sx1272.getRemainingToA());
  PRINTLN;

ifdef LOW_POWER

  PRINT_CSTSTR("%s","Switch to power saving mode\n");

  e = sx1272.setSleepMode();

  if (!e)
    PRINT_CSTSTR("%s","Successfully switch LoRa module in sleep mode\n");
  else  
    PRINT_CSTSTR("%s","Could not switch LoRa module in sleep mode\n");

  FLUSHOUTPUT
  delay(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();

  PRINT_CSTSTR("%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 || ARDUINO_AVR_UNO || ARDUINO_AVR_MINI

      // ATmega328P, ATmega168
      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 delay function
      delay(LOW_POWER_PERIOD*1000);

endif

      PRINT_CSTSTR("%s",".");
      FLUSHOUTPUT; 
      delay(10);                        
  }

  delay(50);

endif

else

  PRINT_VALUE("%ld", nextTransmissionTime);
  PRINTLN;
  PRINT_CSTSTR("%s","Will send next value at\n");
  // use a random part also to avoid collision
  nextTransmissionTime=millis()+(unsigned long)idlePeriodInMin*60*1000+(unsigned long)random(15,60)*1000;
  PRINT_VALUE("%ld", nextTransmissionTime);
  PRINTLN;

}

endif

delay(50); }

namsontr commented 7 years ago

I'm so sorry Mr Duc because i connected wrong pin VCC of HopeRF RFM 92W. I fixed this situation.

CongducPham commented 7 years ago

Great to hear that the issue is fixed.

Regards.

Envoyé de mon iPhone

Le 4 avr. 2017 à 21:39, namsontr notifications@github.com a écrit :

I'm so sorry Mr Duc because i connected wrong pin VCC of HopeRF RFM 92W. I fixed this situation.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

thecockroach commented 5 years ago

Hi, I have the same problem, in sleep mode the power consumption is 5 mA. I made my own board, based on Pro Mini (3v3 8MHz), I don't understand the PABOOST define and his relation with pin DIO0, I have the SX1278 module and I'm using it with the Arduino_Lora_Generic_DHT.

CongducPham commented 5 years ago

Check that there is no led active and that the voltage regulator is removed. See this tutorial: https://www.youtube.com/watch?v=2_VQpcCwdd8

thecockroach commented 5 years ago

Thanks, It is the LDO the problem, now I have 18 uA in sleep Mode.