Noob needs help - Moteino wakes and send one string then goes back to sleep.

Started by plutonium, July 01, 2015, 02:02:44 PM

plutonium

Hi.

I got my moteino yeasterday and I'm been playing with it for some hours or so, and I love the work that you did Felix.

My project is to monitor my mailbox, I'm using a moteino and a magnetic switch, hocked up lite this link.

I'm also using a monteino and a raspberryPi whit the awsome image that Felix have done, thanks.

Now to my problem, (that I think is a problem).

When the magnetic switch is open, the monteino sending until it closed.
That I want is to send only once and then go to sleep.

And can someone put me in the right direction to clean the code aswell, I think there is a lot that I don't need.

The code:
// **********************************************************************************************************
// A simple button status transmitting sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW
// Can be adapted to use Moteinos using RFM12B
// Ver 1.0
// 2014-05-22 (C) [email protected]
// Adapted from [email protected], http://www.LowPowerLab.com mote.ino
// **********************************************************************************************************
// It uses a button to send a data packet to the receiver stating that button position, making a digital output of the receiver pulse
// **********************************************************************************************************
// Creative Commons Attrib Share-Alike License
// You are free to use/extend this code/library but please abide with the CCSA license:
// http://creativecommons.org/licenses/by-sa/3.0/
// **********************************************************************************************************

#include <RFM69.h>
#include <SPI.h>
#include <LowPower.h>

#define NODEID 2 //unique for each node on same network
#define GATAWAYID 1
#define NETWORKID 100 //the same on all nodes that talk to each other
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
//#define FREQUENCY RF69_433MHZ
#define FREQUENCY RF69_868MHZ
//#define FREQUENCY RF69_915MHZ
#define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
//#define IS_RFM69HW //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ACK_TIME 30 // max # of ms to wait for an ack
#define LED 9 // Moteinos have LEDs on D9
#define SERIAL_BAUD 115200
#define D4 4
#define DESTINATION_NODE 1

RFM69 radio;
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network
int D4Status = 0;

void setup()
{

//Setup the pins
  pinMode(LED, OUTPUT);
  pinMode(D4, INPUT);
   
//Start the Serial
  Serial.begin(SERIAL_BAUD);
  delay(10);

//Initialize the radio
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
    radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);//Turn encryption ON
  radio.promiscuous(promiscuousMode);
  char buff[50];
  sprintf(buff, "\nTransmiting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
}


void loop()
{
  if (digitalRead(D4) == HIGH)//If the button connected to Digital Input pin 4 was pushed,
  {
    delay(10);//wait 10ms for debounce
    Serial.print("Sending a D4 Status to node "); Serial.print(DESTINATION_NODE); Serial.println(" and waiting for ACK...");
    
    if (radio.sendWithRetry(DESTINATION_NODE, "4:1", 3, 2, ACK_TIME))//Send the 3 byte packet to node 1 for processing, try that 2 times and wait 30ms each time for an ACK
    { 
      Serial.println("ACK Received");//If the sent packet was delivered and an ACK received, send this message to the serial monitor
      delay(3);// Allow the the radio to switch to receive mode
      Blink(LED,100);//Blink the transmitter led to show the data was successfully sent
    }
    
  }
  else if (digitalRead(D4) == LOW)
  {
    Serial.println ("Powering down..");
    delay (10);
    radio.sleep();
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 
  }
}

void Blink(byte PIN, int DELAY_MS)//Local led blinking function
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}


Thanks for the help!
New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

TomWS

You need to add a variable, called a 'state' variable, that records the last state change every time you do a send.  Then, before you send again, you check the state of the variable to see if you need to send or not.  So, for high level example:

// define state variable
bool sentOpen=false;   // this should be a global variable, declared outside of setup() or loop()  OR you can make it a local variable inside loop() 
// IF you declare it like:
static bool sentOpen = false;  // either way works, but do only one ;-)
...

// in your loop code, 
  if (digitalRead(D4) == HIGH && sentOpen==false)//If the button connected to Digital Input pin 4 was pushed, AND we haven't sent yet...
  {
     sentOpen = true;  // set the state variable so that you don't report again until closed
...
  else if (digitalRead(D4) == LOW)
  {
     sentOpen = false;   // reset the state variable so that you report the next open.
...


Makes sense?

Normally you would have to debounce a switch, but, in this case, since you are immediately sending a packet, by the time you get to check the switch again, it will be stable.

Also, add
    Serial.flush();

before
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

This will make sure the serial buffer is clear.  If you do this you won't need the delay(10); line...

Tom

Felix


plutonium

Thanks! Your post's helped me a lot.

I think I got it like I want to. One thing I woundering about is my powerdown SLEEP_2S, does it much in batterylife with 2S reather than 8s?

This is my final working code.

// **********************************************************************************************************
// A simple button status transmitting sketch that works with Moteinos equipped with HopeRF RFM69W/RFM69HW
// Can be adapted to use Moteinos using RFM12B
// Ver 1.0
// 2014-05-22 (C) [email protected]
// Adapted from [email protected], http://www.LowPowerLab.com mote.ino
// **********************************************************************************************************
// It uses a button to send a data packet to the receiver stating that button position, making a digital output of the receiver pulse
// **********************************************************************************************************
// Creative Commons Attrib Share-Alike License
// You are free to use/extend this code/library but please abide with the CCSA license:
// http://creativecommons.org/licenses/by-sa/3.0/
// **********************************************************************************************************

#include <RFM69.h>
#include <SPI.h>
#include <LowPower.h>

#define NODEID 2 //unique for each node on same network
#define GATEWAYID 1
#define NETWORKID 100 //the same on all nodes that talk to each other
#define FREQUENCY RF69_868MHZ
#define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define ACK_TIME 30 // max # of ms to wait for an ack
#define LED 9 // Moteinos have LEDs on D9
#define SERIAL_BAUD 115200
#define D4 4

#ifdef SERIAL_EN
  #define DEBUG(input)   {Serial.print(input); delay(1);}
  #define DEBUGln(input) {Serial.println(input); delay(1);}
#else
  #define DEBUG(input);
  #define DEBUGln(input);
#endif

RFM69 radio;
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network
bool sentOpen=true; 
int D4Status = 0;

void setup()
{

//Setup the pins
  pinMode(LED, OUTPUT);
  pinMode(D4, INPUT);
   
//Start the Serial
  Serial.begin(SERIAL_BAUD);
  delay(10);

//Initialize the radio
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
  //radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);//Turn encryption ON
  radio.promiscuous(promiscuousMode);
  char buff[50];
  sprintf(buff, "\nTransmiting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
}


void loop()
{
  
  if (digitalRead(D4) == HIGH && sentOpen == true)//If the button connected to Digital Input pin 4 was pushed,
  {
      delay(10);//wait 10ms for debounce
      Serial.print("Sending a mailboxstatus to gateway..");
      sentOpen = false;
    if (radio.sendWithRetry(GATEWAYID, "MAIL:OPN", 8))
    {
      Serial.println(" ok!");
      Blink(LED,3);
    }
    else
    {
      Serial.println(" nothing...");
    }

      
    
  }
  else if (digitalRead(D4) == LOW)
  {
    delay(10);//wait 10ms for debounce
      if (sentOpen == false)
      {
    if (radio.sendWithRetry(GATEWAYID, "MAIL:CLS", 8))
        Serial.println ("send closed once!");
      }
    sentOpen = true;
    Serial.println ("Powering down..");
    radio.sleep();
    Serial.flush();
    LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
  }
}

void Blink(byte PIN, int DELAY_MS)//Local led blinking function
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}


Cheers from sweden
New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

TomWS

Quote from: plutonium on July 02, 2015, 04:11:11 PM
I think I got it like I want to. One thing I woundering about is my powerdown SLEEP_2S, does it much in batterylife with 2S reather than 8s?
Congratulations and welcome to the forum! 

The thing to ask yourself about trying to conserve power is how often do you need to report something?  And, is there anything else you need to do, in addition to reporting this something else.

In the case of a Mailbox monitor, if that is ALL it is (ie doesn't also track comets, or solar flares, etc), then what you need to report are changes in your mailbox state.  I'm not sure about Sweden, but we're lucky in the US if we get at least one change of state per day, except holidays and Sundays, of course, in which a change of state might be cause for worry!

If this is the case in your territory, then I'd keep sleeping until there is actually a signal change and you can do this using pinChangeInt  (interrupt on pin change - ie, your mailbox door is opened).  pinChangeInt will wake up your system as easily as sleep for 'n' seconds using watchdog timer without any overhead.

I'll let you think about this and research it during your  very long days that you are enjoying right now  :)

Tom

plutonium

Thank you TomWs.

I only need to reaport once, maby I will add some future with batterystatus. But I don't think it will interfere because it can send the battrystatus same as the mailbox open.

I think the pinChangeInt is the answer to the problem, and I have researched a lot today to find a way to implement it to my code, and I do not see the logic really.

If there is not to much ask I woundering if there is someone that can help me a bit, not the hole way to implement pinChangeInt to my code. I have struggled whit this embryos that you planted in my head Tom all day. And you gave me a big brainstorm. Thank's for that ;)

Rarely we have heat in Sweden but now we have, attached a image from my living in nature.
New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

TomWS

Quote from: plutonium on July 03, 2015, 05:05:42 PM
I think the pinChangeInt is the answer to the problem, and I have researched a lot today to find a way to implement it to my code, and I do not see the logic really.
Here is your original code with changes to support pinChangeInterrupt.  Unfortunately I don't have the time or setup to test this, but, given its simplicity, it should work.

Tom
#include <RFM69.h>
#include <SPI.h>
#include <LowPower.h>
#include <PinChangeInt.h>        // TOMWS: add these two lines to include pinChangeInt library
#include <PinChangeIntConfig.h>

#define NODEID 2 //unique for each node on same network
#define GATEWAYID 1
#define NETWORKID 100 //the same on all nodes that talk to each other
#define FREQUENCY RF69_868MHZ
#define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define ACK_TIME 30 // max # of ms to wait for an ack
#define LED 9 // Moteinos have LEDs on D9
#define SERIAL_BAUD 115200
#define D4 4

#ifdef SERIAL_EN
  #define DEBUG(input)   {Serial.print(input); delay(1);}
  #define DEBUGln(input) {Serial.println(input); delay(1);}
#else
  #define DEBUG(input);
  #define DEBUGln(input);
#endif

RFM69 radio;
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network
bool sentOpen=true; 
int D4Status = 0;

// TOMWS: add function to catch interrupt, doesn't need to do anything as the interrupt is all that's needed to wakeup
// (although it might want to disable itself if the switch is really noisy)
void wakeup(void)   
{
}

void setup()
{

//Setup the pins
  pinMode(LED, OUTPUT);
  pinMode(D4, INPUT);   
  
  // TOMWS: Allow wake up pin to trigger interrupt on rising edge.
  PCintPort::attachInterrupt(D4, wakeUp, RISING);  // TOMWS: new code to trap interrupt on pin change
  
   
//Start the Serial
  Serial.begin(SERIAL_BAUD);
  delay(10);

//Initialize the radio
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
  //radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);//Turn encryption ON
  radio.promiscuous(promiscuousMode);
  char buff[50];
  sprintf(buff, "\nTransmiting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
}


void loop()
{
  
  if (digitalRead(D4) == HIGH && sentOpen == true)//If the button connected to Digital Input pin 4 was pushed,
  {
      delay(10);//wait 10ms for debounce
      Serial.print("Sending a mailboxstatus to gateway..");
      sentOpen = false;
    if (radio.sendWithRetry(GATEWAYID, "MAIL:OPN", 8))
    {
      Serial.println(" ok!");
      Blink(LED,3);
    }
    else
    {
      Serial.println(" nothing...");
    }

      
    
  }
  else if (digitalRead(D4) == LOW)
  {
    delay(10);//wait 10ms for debounce
      if (sentOpen == false)
      {
    if (radio.sendWithRetry(GATEWAYID, "MAIL:CLS", 8))
        Serial.println ("send closed once!");
      }
    sentOpen = true;
    Serial.println ("Powering down..");
    radio.sleep();
    Serial.flush();
    
    // TOMWS: Now go to sleep until the pin change wakes us up!
    while (digitalRead(D4) == LOW)  // TOMWS: added in case there are other interrupts spuriously waking the mote
    {
       LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);  // TOMWS: changed to SLEEP_FOREVER so that only interrupts wake up, no WDT used
    }
    
  }
}

void Blink(byte PIN, int DELAY_MS)//Local led blinking function
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

plutonium

Oh Thank you Tom!
Now I see the logic behind it. I will try it out and see how it goes.
Thanks again Tom!
New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

plutonium

Hi again, the code above works like a charm.

My project have been up and running for a week now, until today. I using four AA 1.5 Lithium batteries, and now the are drained.
It looks like something is wrong here and I don't know what it is.

This is how I have done my connections. (I'm not a engineer)  ;D

New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

TomWS

Quote from: plutonium on July 16, 2015, 07:23:36 AM
Hi again, the code above works like a charm.

My project have been up and running for a week now, until today. I using four AA 1.5 Lithium batteries, and now the are drained.
It looks like something is wrong here and I don't know what it is.

This is how I have done my connections. (I'm not a engineer)  ;D


Four AA Lithium batteries should keep your monitor alive for literally years!  So, yes, a couple of things are wrong.

A minor thing is you could increase the 10K from ground to the switch to 33K.  This will save some minor current, but that's not where the bulk of your problem is.  Your batteries can supply over 3000mAH of power.  If they're dying in a week then your average current is about 18mA when it really should be <25uA.  It seems as if your radio isn't sleeping at all from this data. (By the way, you could use 3 of those batteries instead of 4 and get the same battery life).

Are you getting the correct messages when the mailbox is opened and closed?
How much time is your mailbox open (10-20 seconds or more)? 
How many times in the week (approximately)?

There is a way to get your radio to sleep when opened, but first we should resolve the gross problem - why so much current on average.

Tom
PM me if you want to get into details.
UPDATED: target average current to include VR power loss.

plutonium

Quote from: TomWS on July 16, 2015, 08:42:30 AM
Four AA Lithium batteries should keep your monitor alive for literally years!  So, yes, a couple of things are wrong.

A minor thing is you could increase the 10K from ground to the switch to 33K.  This will save some minor current, but that's not where the bulk of your problem is.  Your batteries can supply over 3000mAH of power.  If they're dying in a week then your average current is about 18mA when it really should be <25uA.  It seems as if your radio isn't sleeping at all from this data. (By the way, you could use 3 of those batteries instead of 4 and get the same battery life).

Are you getting the correct messages when the mailbox is opened and closed?
How much time is your mailbox open (10-20 seconds or more)? 
How many times in the week (approximately)?

There is a way to get your radio to sleep when opened, but first we should resolve the gross problem - why so much current on average.

Tom
PM me if you want to get into details.
UPDATED: target average current to include VR power loss.

Hi Tom! Thanks for your fast respons.

I can put a 33k instead of a 10k to ground, I do that right away.

Thanks for the tip, I did not know that I could use three instead of four and get the same endurance. :)

Yes I getting correct messages, it works very well, avarage about 3 times / day excluding weekends and the mailbox is open maby 2-10 seconds.

Now I remember when I see the code you wrote to me in the post above. I have my #include <PinChangeIntConfig.h> commented out in my "sharp" code, because I had trouble loading the file. But I have #include <PinChangeInt.h> activated.
Could this have something to do with that it does not fall asleep? I suspect that it must have both files included for this to work?


Cheers
Anders
New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

TomWS

Quote from: plutonium on July 16, 2015, 09:33:14 AM
Thanks for the tip, I did not know that I could use three instead of four and get the same endurance. :)
The reason you would get the same endurance is that the Voltage Regulator converts Vin to a constant 3.3Volts.   The load at the battery is the total current drawn at Vin, which is a function of the Moteino operating at the constant 3.3V, let's say for example it's 15mA.  Since each battery cell is rated for 3000mAH you will get 200 hours from each battery, regardless of how many batteries you have.  Three of those batteries will easily supply the voltage required at Vin (nominal 1.6V/battery x 3 = 4.8V).  Any voltage over the minimum requirement is simply wasted power.

Our goal is to get the 15mA to 15uA average so that you can get 200000 hours from your batteries (this, of course, won't happen, but fun to think about)   :)
Quote from: plutonium on July 16, 2015, 09:33:14 AM
Yes I getting correct messages, it works very well, avarage about 3 times / day excluding weekends and the mailbox is open maby 2-10 seconds.

Now I remember when I see the code you wrote to me in the post above. I have my #include <PinChangeIntConfig.h> commented out in my "sharp" code, because I had trouble loading the file. But I have #include <PinChangeInt.h> activated.
Could this have something to do with that it does not fall asleep? I suspect that it must have both files included for this to work?


Cheers
Anders
Please zip up your complete sketch and post it.  Something doesn't make sense.  I'll take a look at the code and see what I can find.

Tom

plutonium

Of course, that make sense :) Then I gonna replace a bettery with a cable instead. The lithium battery isn't cheap.

I took a hard look at pinchange lib and i found that in version 1.4, the file pinchangeintconfig.h isn't necessary anymore.

Here it comes, thank for your time Tom!

New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

plutonium

Was wondering about how I can measure the energy consumption with my multimeter. Where do I measure according to my cheamtic above?
just another non engineering question ???
New to moteino but I love it and have three of them and more to come. See my house homepage at www.essunga.org

Felix

You need to interrupt the + from the battery and run it through your multimeter on the A/mA/uA setting.
Then Power = Amps * Volts of the battery
You would also need to measure the volts at the same time between the + and GND of the batt to get an accurate result rather than estimating it is always == to what it was when you started the measurement (that requires another multimeter).