Stops sending after 4 hours

Started by ShadowGrass, March 09, 2014, 10:03:52 AM

ShadowGrass

My sending Moteino stops sending after what appears to be exactly 4 hours.  I have run it 3 times now and all three times my receiving Moteino stops getting a signal.  I have isolated it to the sender, since once I reset it, I begin getting radio data again.  This is bizarre to me, since I don't have a RTC connected to it or anything, and all it is doing is checking a few sensors then sending the data.  I don't have references to time, so the only thing I can figure is that it has something to do with this part of the default sending program:

int currPeriod = millis()/TRANSMITPERIOD;
  if (currPeriod != lastPeriod)
  {
    lastPeriod=currPeriod;
    photoSensor = analogRead(A2);
    delay(100);   


Anyone else experience this oddity?  I thought I wouuld post it here before I really dug into what 'TRANSMITPERIOD' is.  Only thing I can think of is that this IF statement above is not being satisfied and it is not sending.

Thanks!

Felix

Could you try to use the Send sketch with that node and see if it stops sending after a while...
The Send sketch is set to 300ms intervals. Try something closer to what you need, and let it send for 4 hours and see what it does. Don't do anything else on it, we're just trying to identify if the radio is OK or not.

ShadowGrass

I can do that, but I do have to set one pin high so my lamp stays on in my well house (cold here).  Other than that I will leave it alone and report.

Thanks Felix. 

Felix

Ideally it would be isolated from anything. Maybe you could keep the light on without the Moteino?
Either way let us know what's the outcome... Thanks

kobuki

#4
millis() returns unsigned long (32 bits), and putting the result of the division into a 16-bit signed int leads to all kinds of funky stuff happening. I'd suggest declaring currPeriod as unsigned long, and additionally, instead of the quirky integer division check use it for storing the last transmit time and check if elapsed millis() has passed the last value + TRANSMITPERIOD.

Tomme

I second what kobuki says, it's worth remembering that millis is not always incremented by 1 so checking for exact values is dangerous. Might be worth toggling the LED as part of your sketch so you can see if its still running after 3 hours or a more serious problem.

john k2ox

Two things. 

Check that the current time is greater than the past time.  That will let you know if it rolled over.  If I remember correctly, that shouldn't happen for 47 days.

Look up wdt, the 'watch dog timer'.  If something in your code hangs up, it will automatically reset the Moteino.

OK, a third thing, pay attention to when it happens.  Is it always at night?  After sunset?  Does it start up again the next day if left alone?  Is it close to your 'heater'?

I think it could be a frequency drift with a change in temperature.

Regards,
John

Felix

All great points guys, thanks for helping debug this. Any of the mentioned pointers are potential issues.

ShadowGrass

Wow, thanks guys. 
I have also thought about time of day, temp, etc as well.  The "heater" is a 125 watt heat lamp.  It is about 3' away.  However it has been on constantly.  Last night I reset the sender because it stopped.  After about 30 seconds it stopped again.  This was at night, about 24 degrees F.  I reset it again and it ran for about 3 hours and stopped.  I reset it this morning at about 7:30am and it ran until 12:33pm.  So what I thought originally was 4 hours, is not true, it is sporadic .  Back on Saturday it ran from about 9:33am until about 8:15pm, almost 11 hours before stopping.  During this time, nothing else was going on.  The relay for the heater (lightbulb) has been on.  The only thing that is happening constantly is a couple sensor reads and a couple simple calculations.  No definite pattern that I can tell.

Before it quit this afternoon was the first time the heater shut off, which seemed to go fine as it did in my testing.  As the temp rose above freezing and up to about 40 everything seems to go fine until it quit.  So, I am thinking I am going to start by changing the code and see if that helps as recommended by kobuki and Tomme and go from there.  I was going to change to this, I think this makes sense....?

BTW, I did have the LED blinking during sending and when i stop receiver both the sender and receiver stop blinking.

void setup() {
   unsigned long lastPeriod = -1;
}
void loop(){
   unsigned long currPeriod = millis(); 
   if ((currPeriod + TRANSMITPERIOD) >= lastPeriod)
  {
    lastPeriod=currPeriod;  
    sprintf(buf,"%d,%d,%d,%d,%d :\n",pumpAlarm,lightAlarm,photoSensor,floatSwitch,tempSensor);  //Build string
    //radio.send(GATEWAYID, buf, sendSize);
    radio.send(GATEWAYID, buf, 30);
    Blink(LED,3);
    Serial.print (buf);
  }


If anyone noticed, I moved that sensor read out of the if statement.  Not that it mattered, it just wasn't necessary to be in there.

One further question, why go through all the trouble of a calculation to see if x time has passed and not just put a manual delay in there? Say 500ms.  It is not necessary for me to control it to a finite time for this project.
Like 
delay(500);
sprintf(buf,"%d,%d,%d,%d,%d :\n",pumpAlarm,lightAlarm,photoSensor,floatSwitch,tempSensor);  //Build string
radio.send(GATEWAYID, buf, 30);
    Blink(LED,3);
    Serial.print (buf);
  }


I will test the first code tonight and report back.  Thanks for all the help I really appreciate it.

ShadowGrass

So far so good.  On the sender I made the unsigned long changes.  Been running for about 4 hours so far.  Keeping my fingers crossed.  If you want to see the progress, you can see my data on my Exosite Dashboard.     
https://portals.exosite.com/views/1557739845/3656177209


KanyonKris

You should be fine using delay(500). Looks like you've got it working.

As John said, millis() rollover (start counting from zero) after 49 days. To deal with rollover, subtract the more recent time from the older time. More info here

Another troubleshooting technique is to make a sketch of only the chunk of code you suspect, add print statements to tell you when the code entered sections of code and print values of key variables. Load this sketch to a Moteino connected to a an FTDI cable so you can see the print outs in the serial monitor.

john k2ox


kobuki

Quote from: ShadowGrass on March 10, 2014, 10:04:56 PM
So far so good.  On the sender I made the unsigned long changes.  Been running for about 4 hours so far.  Keeping my fingers crossed.  If you want to see the progress, you can see my data on my Exosite Dashboard.     
https://portals.exosite.com/views/1557739845/3656177209

Good you resolved this. BTW, the fixed delay you mentioned is the simplest and useful when you can do every scheduled task in a single run when it times out. Obviously, you can't do anything else while you wait on a delay(), unless you use interrupts, for example.

ShadowGrass

It looks like I celebrated a bit too early.  It ran from about 6pm last night until 10:20am this morning.  The heat (light bulb) turned off about 20 minutes prior to it failing, so I don't think that is an issue. I am starting to think I may have a faulty radio.  Why else would it run for 16 hours then just stop, or 4 hours, or 15 minutes, 1 minute, etc.  On my receiver I have a test for signal, so if it does not get data for roughly 30 seconds it sounds a buzzer.  If I leave it sit, it never resumes sending.  The LED on the sender does not flash, so I know it is not even attempting to send.  It's as if the radio shuts off completely, but at that point the code appears to stop as well, otherwise the LED would still blink.  So, I am at a loss again.  This is my entire code, be kind.

// Well Monitor V1.3
// Sender Unit

#include <RFM69.h>
#include <SPI.h>
#include <VirtualWire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define NODEID 2 //unique for each node on same network
#define NETWORKID 100 //the same on all nodes that talk to each other
#define GATEWAYID 1
//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 ONE_WIRE_BUS 4          
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
int temp;  // define variable for the temperature to be stored
int photoSensor;  //define variable for photoresistor
int floatSwitch;  //define variable for float switch
int tempSensor;  //define variable for temp sensor
int pumpTimer; //define variable to monitor pump run time
int pumpAlarm;
int lightAlarm;
#define pumpRelay 3
#define lightRelay 5
unsigned long TRANSMITPERIOD = 1000; //transmit a packet to gateway so often (in ms)
char buf[30];
byte sendSize=0;
boolean requestACK = false;
RFM69 radio;

void setup() {
  pinMode(A0,INPUT);
  pinMode(A2,INPUT);
  pinMode(4,INPUT);
  pinMode(lightRelay,OUTPUT);
  pinMode(pumpRelay,OUTPUT);

  pumpTimer = 0;
  pumpAlarm = 0;
  lightAlarm = 0;
  sensors.begin();            // Start up the library
  Serial.begin(SERIAL_BAUD);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //uncomment only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  //  char buff[50];
  //  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  //  Serial.println(buff);
}


void loop() {
  //read sensors
  floatSwitch = digitalRead(A0);  // Read Float Switch pin A0
  delay(100);
  sensors.requestTemperatures();  // Get Temp pin 4
  temp = (sensors.getTempCByIndex(0));
  delay(100);
  tempSensor = (temp * 9)/5.0 + 32.0;  //convert to F
  photoSensor = analogRead(A2);  // Read light sensor
  delay(100);

  // check for standing water and turn on pump if req
  if (floatSwitch==1) {
    digitalWrite(pumpRelay,HIGH);
    delay(100);
    pumpTimer++;
    //Check to see if pump has run too long, 600 cycles, approx 20 minutes
    if (pumpTimer >= 600)
      pumpAlarm = 1;
  }
  // Turn pump off and reset alarms 
  else {
    pumpTimer = 0;
    pumpAlarm = 0;
    digitalWrite(pumpRelay,LOW);
    delay(100);
  }

  // check to see if we need to turn on light/ heat
  if (tempSensor <= 38 ) {
    digitalWrite(lightRelay,HIGH);
    delay(100);
  }
  else {
    digitalWrite(lightRelay,LOW);
    delay(100);
  }

  // check to make sure bulb is good
  if (digitalRead(lightRelay) == HIGH) {
    if (photoSensor < 400) {
      lightAlarm = 1;
    }
    else {
      lightAlarm = 0;
    }
  }

  delay(500);  // make sure I am not sending too fast
  sprintf(buf,"%d,%d,%d,%d,%d :\n",pumpAlarm,lightAlarm,photoSensor,floatSwitch,tempSensor);  //Build string
  radio.send(GATEWAYID, buf, 30); // send it
  Blink(LED,3);
  Serial.print (buf);

}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

kobuki

I'm wondering about one thing. The Moteinos are clocked at 16 MHz, while powered with 3.3V, and thus out of Atmel's spec, overclocked a bit. Could it be the cause? OTOH, I had receptions problems powering my Moteino from USB, probably caused by noise picked up from the PC. This might be a problem with my setup, but it might worth a try to power yours from a battery and try again. I understand that  you have transmit problems, but still worth a try, IMO.