Counting Problems

I replaced the USB adapter which came with my Samsung Camcorder (rated at 750ma) with the 2A adapter that came with the Raspberry Pi 2 and there was no reset in the past 24 hours, whereas previously it would do that after not more than 5 hours. So I think it is safe to assume that the root problem was the power adapter. I understand that, as @ScruffR suggested, the power rating alone is not an indicator of whether an adapter is suitable or not. I’m just surprised Samsung would not provide a quality adapter with their products.

Thank you all for your assistance and for introducing me to new concepts (for me) such as retained variables, the dashboard, time formatting, curl, Semi automatic modes, safe mode, interrupts and threading.

The quality of the product should be measured against the intended use, and for just charging a camcorder you don't need highly filtered DC.
But Samsung (or any other manufacturer) should not be "blamed" for providing you with a charger that can't do all the things you want to use it for, but they didn't intend it for.

2 Likes

Touché

1 Like

Happy to see that you figured out what may be causing/contributing to your problem.

I guess that’s all part of the ‘fun’ of electronics… Tracking down difficult-to-isolate problems which can manifest themselves in software or hardware!!!

:smirk:

2 Likes

With the power problem out of the way, now I need to figure out how to handle the problem of the counter resetting when the WiFi is temporarily switched off. My current method of handling a WiFi disconnections is this:

if(millis() - old_time >= 2000){        
    if(retry_count < 10){
        if(!WiFi.ready()){
            WiFi.connect();
            retry_count++;

        }
        else if (!Particle.connected()){
            Particle.connect();
            retry_count++;
        }
    }
    else{
        WiFi.off();
        retry_count = 0;
        WiFi.on();
    }
    old_time = millis();
}

It has already been pointed out that this is not the best method, but I have not yet found an alternative. As it stands, the pulse counter is resetting every time there is a WiFi blackout, instead of keeping the count and then uploading the value as soon as a connection to the web is re-established.

You tried System.enableFeature(FEATURE_RETAINED_MEMORY) and noticed that it is not surviving when loss of cloud connection causes a reconnect/restart. I guess it may be possible that the fuzzy power supply, coupled with the WiFi re-connect process caused a power blip that affected the storage into Backup RAM....

also, please try changing this:

retained uint32_t PulseCount = 0;
retained uint32_t TotalPulseCount = 0;

to this:

retained int PulseCount = 0;
retained int TotalPulseCount = 0;

Let's rule that out. Data type: uint32_t has been deprecated in other functions, so let's stick to the API.

Finally, if you have a Pushover account (or similar texting/notification process) add a restart message in setup() that tells you time and date and returns PulseCount and TotalPulseCount like this:

char pushoverMessage[125];
sprintf(pushoverMessage, "Counter Restart at %d:%02d%s with %d pulses and %d total pulses", Time.hourFormat12(), Time.minute(), Time.isAM()? "am" : "pm", PulseCount, TotalPulseCount);
Particle.publish("pushover", pushoverMessage, 60, PRIVATE);

It could help since you seemed to reduce the likeliness of the event with improving the power situation. [EDIT] changing power supplies (i.e. hooking your rig to the USB port of your computer to get the above serially) won't really tell you the whole story... hence the Pushover approach.

Of course, you could simply shut off your WiFi access point to test!!!

I remain concerned by statements like this:

I'll reiterate that I do not believe that external events such as WiFi or internet connectivity should be resulting in resets of the photon, unless you explicitly desire that behaviour and code it into your application.

So if you are indeed seeing this happen, even though you now have a trustworthy power source, then I would regard this as a bug.

2 Likes

There might be a misunderstanding.
This data type is not and will not be deprecated, since it's a fundamental type.
The point with the referenced "API" was that due to some tightening of type checks on the build farm side unsafe implicit type cast were not accepted anymore.
Unless a fitting overload for that "API" is provided, you'd need to do explicit casting, but the data type is still allowed and used for all other uses.

@osprey: Unless you are experiencing power cuts, there should not be any need for retaining data if you settle for the correct SYSTEN_MODE and handle reconnections properly.
I've actually never had to perform WiFi.off() - WiFi,on() resets the way you do it in your snippet above.
If this is required there might be up with your other code that just "kills" the connection.
The only thing I might do is to check for Particle.connected() and if needed (since auto reconnect fails) call Particle.connect() while making sure that you don't do multiple connect atempts while any previous atempt hasn't finished.

@ScruffR I did not write that code and I don’t know how it works. I got it from this thread. All I want is something that stops the device from trying to connect when the wifi goes down. Then, after say, a minute, it tries to connect again. If it fails, it will retry again once a minute.

Doesn’t using threading with SYSTEM_THREAD(ENABLED) solve the issue? From my understanding the wifi reconnects on its own on the background thread then you just need to check if the connection is available in the loop, say every second, and if it is then you can use it to do whatever is required for your app.

I just did a router restart and one photon running SYSTEM_THREAD(ENABLED) on 0.4.6 did restart after an SOS whereas two other photons running on 0.4.5 (or maybe 0.4.4) reconnected to the cloud without restart. I tried a second time with the same result. All three were powered by an iPhone/iPad charger.

The photon that restarted was running a different program however. Maybe someone can try something similar with two photons running the same programs on different firmware and with and without SYSTEM_THREAD(ENABLED)?

2 Likes

It seems to me that if it is selectively un-useful or even not fully supported to use the int32_t than it has been deprecated by proxy.

so @osprey back to your issue:

this test code continues to count and save its values to backup RAM even when I turned off the router with the counter at 210:

retained uint32_t value = 10;
int retry_count = 0;
unsigned long old_time = 0;

void setup() {
    delay(10000);
    Serial.begin(9600);
}

void loop() 
{
    static unsigned long myTimer = 0;
    if(millis() - old_time >= 2000)
    {        
    if(retry_count < 10)
    {
        if(!WiFi.ready())
        {
            WiFi.connect();
            retry_count++;
        }
        else if (!Particle.connected())
        {
            Particle.connect();
            retry_count++;
        }
    }
    else
    {
        WiFi.off();
        retry_count = 0;
        WiFi.on();
    }
    old_time = millis();
}
    if (millis() - myTimer > 5000)
    {
      Serial.println(value);
      value += 10;
      Serial.println(value);
      myTimer = millis();
    }
}

it eventually recovered and reconnected (breathing cyan) at 310:

so... maybe you are resetting your counter somewhere else in your code, or somehow your old power supply was causing a power cycle.

can you perform your wifi test with the code above?

Then that is a regression in 0.4.6, and it will be addressed, there should be no compelling reason to code around that behaviour.

I’m not saying that retained variables won’t be useful for this app, just that they should not be considered an alternative to eradicating the regression.

1 Like

Just to try to clarify here

Particle.variable() supports int, double and char* and char[] other data types will at present result in a compile time error. This is because we need strict adherence to the types of the actual variables in both precision and signed-ness. Going forward, we may open up additional types (int32_t being the most likely), but at present these are the ones supported.

For all other uses, including backup RAM, all primitive types are supported - uint32_t included. The rationale for using type of specific precision is especially with backup RAM since it allows you to know exactly how many bytes will be allocated in memory for that variable.

I hope that clears up the confusion! Onward! :smile:

Cheers,
mat.

1 Like

And just a little tip, Backup ram does not work until the device has deep slept at least once after power has been applied. took me a while to work that one out.

I tried the code with a minor change (see code below) and it appeared as though it was working fine. Then I turned off the wifi access point for 24 minutes and when I turned it back on the counter had reset. I replaced the part where it sends readings by serial to one that uploads via http request.

#include "HttpClient/HttpClient.h"
#include "application.h"

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);
STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

//Settings
String DeviceID = System.deviceID();
String TargetHostName = "www.mydomain.com";

retained uint32_t value = 10;
int retry_count = 0;
unsigned long old_time = 0;

String DeviceTime = "";
double AveragePower = 0;
String PacketData = "";
int ResponseStatus = 0;

HttpClient http;
http_header_t headers[] = {
    { "Accept" , "*/*"},
    { NULL, NULL }
};
http_request_t request;
http_response_t response;

void setup() {
    delay(10000);
    Serial.begin(9600);
}

void loop() {
    static unsigned long myTimer = 0;
    if(millis() - old_time >= 2000) {
        if(retry_count < 10) {
            if(!WiFi.ready()) {
                WiFi.connect();
                retry_count++;
            }
            else if (!Particle.connected()) {
                Particle.connect();
                retry_count++;
            }
        }
        else {
            WiFi.off();
            retry_count = 0;
            WiFi.on();
        }
        old_time = millis();
    }
    if (millis() - myTimer > 60000) {
        Serial.println(value);
        value += 10;
        SendHttpRequest();
        myTimer = millis();
    }
}

void SendHttpRequest() {
        PacketData = DeviceID + ";" + String(0) + ";" + DeviceTime + ";" + String(value) + ";" + String(AveragePower);
        request.hostname = TargetHostName;
        request.port = 80;
        request.path = "/spark_receiver.ashx?PD=" + PacketData;
        http.get(request, response, headers);
        ResponseStatus = response.status;
}

Did you sleep the device at least once, as @Hootie81 recommended?

At the time of my previous post I had not. Then I changed the code as shown below (in case the problem was with the http library) but we’re still not there yet. After a twelve minute wifi blackout, the counter did not reset, but it did not increment either. When wifi was restored, the counting was resumed from where it was at the time of wifi switch off.

#include "application.h"

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);
STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

//Settings
String DeviceID = System.deviceID();

retained uint32_t value = 0;
int retry_count = 0;
unsigned long old_time = 0;
bool success = false;
retained bool WentToDeepSleep = false;

void setup() {
    delay(10000);
    if(!WentToDeepSleep) {
        WentToDeepSleep = true;
        System.sleep(SLEEP_MODE_DEEP,10);
    }
}

void loop() {
    static unsigned long myTimer = 0;
    if(millis() - old_time >= 2000) {
        if(retry_count < 10) {
            if(!WiFi.ready()) {
                WiFi.connect();
                retry_count++;
            }
            else if (!Particle.connected()) {
                Particle.connect();
                retry_count++;
            }
        }
        else {
            WiFi.off();
            retry_count = 0;
            WiFi.on();
        }
        old_time = millis();
    }
    if (millis() - myTimer > 60000) {
        value += 10;
        if (value >= 1000000) {
            value = 0;
        }
        success = Particle.publish("value", String(value) , 60, PRIVATE);
        myTimer = millis();
    }
}

I could be wrong but I think the problem occurs when the Photon keeps trying to connect to the wifi when it is unavailable. Is there a way to stop the device from trying to connect to wifi when there is none, keep doing its counting, and then look for wifi again after a set period of time? Say, a minute?

I have to agree with @AndyW there should not be any reason for your counter to stop counting and even less to reset just because the WiFi conks out.
Unless there is something going on that causes a reset to the system - e.g. hard fault, TCP issue, …

I’d drop the code you got there, especially since you don’t quite know why you have it in the first place and start anew.

So I’ll try to whip up some easy to understand test code that will survive a longer lasting WiFi drop out with as little “special features” as possible on a Photon with 0.4.6.

1 Like