[SOLVED] Rain gauge causes Photon to drop Internet

Here’s a weird one. I just discovered that the rain gauge connected to my Sparkfun Weather Shield causes the Photon to disconnect from the Internet every time the bucket tips. The Photon’s LED goes from its normal cyan pattern to eight red blinks, followed by 14 slow red blinks, and the a normal reconnect. Until the next time the rain gauge tips.

All the gauge does when it tips is to temporarily ground D2. I tried grounding D2 on another Photon and of course it had no effect on the Internet connection. Any ideas what could cause this?

Would be interesting to know what the code does when that happens :wink:

Probably the code we can’t see

I guess it’s actually nine initial blinks (SOS … — …) so is it 8 + 14 or 9 + 14 or 9 + 13?

Ah yes, you’re quite right. It is SOS followed by 14 slow red flashes (“TTTTTTTTTTTTTT”).

I can’t see how it’s the code since that hasn’t changed. It was working fine until one day it wasn’t. Unfortunately, it is too big to post. It’s over 3000 lines. I am unable to wrap a bracket-slash-bracket around it because it causes my browser to choke, so I uploaded a copy here:


You did give me an idea though. I tried flashing a blank program onto the weather Photon and then jumpering D2 to ground. This did not cause the net connection to drop. Then I tried flashing my weather code onto my spare Photon (not connected to the Weather Shield) and again jumpering D2 to ground. And in this configuration, it did cause the net to drop. So there must be something in the weather code after all, though for the life of me I can’t imagine how.

You do have a lot of “zombi code” in there :wink:

I have also noticed that you are modifying multiple variables in rainIRQ() that are not marked as volatile.
You should also check in that ISR whether you could ever violate the boundaries of rainHour[] (I’ve added such security in the version below)

Before I looked closer at your code I have rearranged the order of your global declarations (pulled include statements, constants, global object instantiation, pin mappings, forward declarations, … together in blocks, removed superfluous comments like the default // This include was added by Web IDE, …).
I also replaced some of your “excessive” switch() and if() combos with an array based approach.

What is the reason behind this

    dailyrainin = dailyrainin + 0.011 + 0.012; //Each dump is 0.011" of water

Why two additions and not write

    dailyrainin += 0.023; 

You should also consider getting rid of String.

As the comments in your code suggest you are using Web IDE and this would provide the SHARE THIS REVISION feature to share a link to a snapshot of your project (including all the required imported libraries) which would allow someone to directly test your code.


Ah, uh, yep - that’s the other reason I wasn’t too keen on sharing it.

I don’t think so. The variable minutes is incremented in only one place, in the main loop:
if(++minutes > 59) minutes = 0;

I did not write any of the rain code. It comes directly from the Sparkfun Weather Shield repo here: https://github.com/sparkfun/Photon_Weather_Shield/archive/master.zip

However, that particular line originally added 0.011" of rain per bucket tip. I empirically determined (using a calibrated glass tube gauge) that this number was too small for my particular gauge . But I wanted to preserve the original number for reference purposes so I just tacked on my calibration value to what they already had there. That way if at some point I decide I need a different value I can easily see how much I added to the original code.

Shudder I would if I knew anything about C programming. I’m more of a Matlab/Lisp person. That code has Strings everywhere.

So it’s starting to look like the thread is mistitled. I first thought it was just an Internet disconnect. Apparently I’m panicing the device. I looked up SOS code 14 and it says “Heap error”:

SOS+14 signifies:

Semaphore lock timeout
Since 0.8.0 60 seconds expired while trying to acquire a semaphore lock, likely due to dynamic memory allocation
Since 1.2.0 Other heap-related error, such as allocating memory from an ISR

So that makes sense since it always (and only) happens when the rain bucket tips and that calls the rainIRQ ISR. However, I don’t see it doing any of the things they say to avoid:

void rainIRQ()
// Count rain gauge bucket tips as they occur.
// Activated by the magnet and reed switch in the rain gauge, attached to input D2
// For a discussion of errors in tipping bucket rain gauges, see:
// http://journals.ametsoc.org/doi/pdf/10.1175/1520-0426(1997)014%3C1513%3AANMFAD%3E2.0.CO%3B2
// https://www.wmo.int/pages/prog/www/IMOP/publications/IOM-94-TECO2006/P3(15)_Lanza_Italy.pdf
// http://www.ucs.louisiana.edu/~exh5102/Assets/publications/Journal_Papers/14.pdf
Based on the experimental data, simple linear regression equations were developed to correct
the long term rainfall data collected by the TBR models. The following equations were proposed
for corrections in rainfall intensities:
For TR-525: Ia = 1.2667Im – 0.6277
For ISCO-674: Ia = 1.111 Im – 0.3546
Where: Ia is actual

Our simple hack here is to just add 0.01" to each tip based on a 1" rainfall observed on a funnel
gauge that resulted in only 0.45" reported on the TB gauge.  Adding 0.01" to each tip
resulted in a 2" rainfall being reported as 1.5".  Cal. factor changed to 0.0169
  raintime = millis(); // grab current time
  raininterval = raintime - rainlast; // calculate interval between this and last event

    prevHour = curHour ;          // Hours are 0-23.
    curHour = Time.hour () ; 
    if (curHour < prevHour)       // Day rollover at midnight (ie. 0 < 23)
       dailyrainin = 0 ; // reset rain counter at midnight
       snowinToday = 0 ; // reset daily snow counter at midnight
       prevsnowin = 0 ;
    if (raininterval > 12) // ignore switch-bounce glitches less than 10mS after initial edge
    dailyrainin = dailyrainin + 0.011 + 0.012 ; //Each dump is 0.011" of water
    // Add 66% to each dump to compensate for undercatchment while switching buckets.
    rainHour[minutes] += 0.011 + 0.012 ; //Increase this minute's amount of rain

    rainlast = raintime; // set up for next event
}  // end rainIRQ.

Also, this code hasn’t changed in a long time and was working fine until recently. Am I “attempting to allocate memory” anywhere in there? (The reference to this is here: https://docs.particle.io/tutorials/device-os/led/photon/)

I will try to get a SHARE THIS REVISION out but I have to remove the various API keys from it first. Thanks so much for looking at it.

Try upgrading to 1.2.1 or even 1.4.0-rc.1 - IIRC the “heap safety panic” was somewhat overly zealous, so it might be worth a try.

I’m on 1.2.1 right now. Come to think of it, the problem didn’t happen back when I was on 0.89 (or whatever the last number < 1 was).

To deepen the mystery, I noticed that while it didn’t look like the minutes variable could ever go over 59, there was no place where it was ever assigned to zero to begin with. So I did that and full of confidence reflashed the device. But no, invoking RainIRQ still throws a code 14.

How do I get 1.4.0-rc.1? The drop-down menu in the Devices tab only goes up to 1.3.1-rc1.

Strange! I see this

Maybe when you hit CLEAR CACHE in the setup tab.

Although I don’t see any immediate issue with the ISR you can try commenting out the entire body of the function and gradually add back bit by bit to see which exact instruction causes the issue.
For lack of a better candidate I’d remove Time.hour() as first attempt.

BTW, this is how I ensured that the index won’t exceed the allowed range.

  rainHour[constrain(minutes, 0, 59)] += 0.023; // 0.011 default value plus 0.012 calibration
1 Like

Yes, CLEAR CACHE did it. I selected 1.4.0-rc.1 and reflashed my code. It went through the usual multiple colors it does when it’s updating firmware and then started my code. But it still goes to code 14. And the info line for the Photon still says On the device: 1.2.1.

Let me try your other suggestions and get back to you.


Bada bingo!! That was it.:grinning:

I ended up moving this entire section of code from the ISR into the main loop. There was really no reason for it to be there in the first place.

prevHour = curHour ;          // Hours are 0-23.
curHour = Time.hour () ; 
if (curHour < prevHour)       // Day rollover at midnight (ie. 0 < 23)
   dailyrainin = 0 ; // reset rain counter at midnight
   snowinToday = 0 ; // reset daily snow counter at midnight
   prevsnowin = 0 ;

It’s working fine again now. I guess it was the firmware update that triggered the problem. I couldn’t figure out why this code that hadn’t changed suddenly stopped working.

So many thanks. You are truly the Photon Whisperer!