Arduino Uno code is being ignored

I have an Uno set up with some code that receives RF on 433MHz (weather station, energy meter), decodes it, and then either prints to serial or publishes to MQTT. I had an issue last week where using the SimpleTimer library to output every 30 seconds would result in the first print to work but the second to be ignored. I assumed this was an issue with the library, so I replaced the code with a basic delta Millis() check. This works for Serial.print, but for some reason when I try to publish to MQTT I get the issue again. I've been trying to narrow down the cause, but I'm at a loss. I didn't want to publish the whole code since it's a bit long, so I'm posting just the relevant segments (I hope). I don't think I'm doing anything exotic, but a second set of eyes would be very much appreciated.

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

#define REPORT_TIME  30000  // 30 seconds

byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte server[] = { 192, 168, 0, 200 };
byte ip[]     = { 192, 168, 0,  70};

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

long previousMillis = 0;

void setup () {
    Serial.begin(38400);
    
    Ethernet.begin(mac, ip);
    if (client.connect("arduinoClient")) {
      client.publish("ookDecoder", "Arduino ookDecoder online");
    }
}

void loop () {

    //will have issues with rollover
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > REPORT_TIME) {
      // save the last time you blinked the LED
      previousMillis = currentMillis;  
      
      blueline.MQTTreport(client);
      acurite5n1.MQTTreport(client);
    }

/* do all the RF receive and decoding here */
}
   void MQTTreport (PubSubClient client) {
      static char data[100];
      String packet = "";

      packet += "Windspeed=" + String(convKphMph(windspeedkph)) + ", ";
      packet += "Winddir=" + String(winddir) + ", ";
      packet += "Rainfall=" + String(rainfall) + ", ";
      
      packet += "TempF=" + String(tempf) + ", ";
      packet += "Humidity=" + String(humidity) + ", ";
      
      packet += "battery=";
      if (batteryok) {
        packet += "OK";
      } else {
        packet += "LOW";
      }
      packet.toCharArray(data,100);
      if (client.connect("arduinoClient"))
        client.publish("acurite5n1",data);
    }
    void MQTTreport (PubSubClient client) {
      static char data[100];
      String packet = "";
      
      packet += "TotalEnergy=" + String(g_RxWattHours) + ", ";
      packet += "CurrentPower=" + String(g_RxWatts) + ", ";
      packet += "TempF=" + String(g_RxTemperature) + ", ";
      
      packet += "battery=";
      if (g_battStatus == true) {
        packet += "OK";
      } else {
        packet += "LOW";
      }
      packet.toCharArray(data,100);
      if (client.connect("arduinoClient"))
        client.publish("blueline",data);
    }

And this is what I see when monitoring MQTT:

...
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
blueline TotalEnergy=19963, CurrentPower=1576, TempF=55, battery=OK
...

If I comment out "blueline.MQTTreport(client);", this is what I see:

acurite5n1 Windspeed=0.00, Winddir=135.00, Rainfall=0.00, TempF=51.80, Humidity=99, battery=OK
acurite5n1 Windspeed=1.14, Winddir=157.50, Rainfall=0.00, TempF=52.00, Humidity=99, battery=OK

This is exactly the same issue I saw when using the SimpleTimer library. I'm at a loss. I can post the full code if that would help.

Moderator edit: CODE TAGS. Why is it so difficult to use CODE TAGS?

ookDecoder-ben4.ino (3.42 KB)

DecodeOOK.h (2.62 KB)

Acurite5n1.h (9.71 KB)

Blueline.h (10.1 KB)

temp_lerp.h (963 Bytes)

I can post the full code if that would help.

It would, but I'm going to guess anyway that you're running short of RAM.

I'll post the full code in a minute. When compiling and uploading the message window indicates 62% memory used.

I can post the full code if that would help.

You appear to have two functions with the same name and the same arguments. So, when you say you comment one out, it is not clear what you are doing. Therefore, I do think you'll need to post ALL of your code - in code tags, not quote tags.

I was trying to simplify the situation. I have several class definitions: DecodeOOK (parent), Blueline (child), Acurite5n1 (child). The two child classes inherit the parent class functions. The MQTTreport functions are for the blueline and acurite classes.

This is what the IDE shows when done uploading:

Sketch uses 21,920 bytes (67%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,249 bytes (60%) of dynamic memory, leaving 799 bytes for local variables. Maximum is 2,048 bytes.

When I didn't have the MQTT code included, I believe the sketch used around 42% but it was still doing the same thing in ignoring the second function call.

The full code with MQTT is attached. I can attach the SimpleTimer version too (I think I have a backup with that somewhere).

This is the version with SimpleTimer. All the header files should work with this ino.

ookDecoder-ben2.ino (2.63 KB)

My original plan was to return a string containing the data I wanted published to MQTT instead of sending the client to the class function. But, I had issues when converting string to char* and found this easier. If returning a pointer to the char array is better, I'm open to that as well.

If returning a pointer to the char array is better, I'm open to that as well.

It might be, if the pointer still points to something valid when the function ends.

The full code with MQTT is attached.

Where? It SHOULD have been attached to the reply I extracted the quote from - not some other reply.

    static word last;

That crappy type has NO place on the Arduino. It is a stupid name that gives no hint as to the size of the value that it can hold. On Redmond doofuses use that crap.

    last += pulse;

Adding time is not a good idea.

    //will have issues with rollover

Your watch rolls over twice a day. Does that cause you issues?

"Last" was the nomenclature extracted from the JeeLabs code I used as a code base. I agree that it isn't quite as clear as it could be.

I sourced the simple millis timer code from another forum post here. It indicated rollover might be a concern so I noted it so I could review it later. I would prefer to use the SimpleTimer code, but that wasn't working so I went simple to move forward for the time being.

I attached the code to the OP since new people to the thread might expect to see it in the first post. I considered whether to attach at OP or reply and decided OP was best. Sorry for the confusion.

You don't like the use of "word" as a type? I assume then that "uint16_t" is preferred? I have no loyalty to either, so it can be switched. Again, much of the code was sourced from other projects. I have been working on cleaning and making things consistent. Perhapse I made it consistent with the wrong standard in some cases.

What I don't understand is the aversion to word when things like int and long which suffer the same issues with differences across platforms seems to be tolerated.

What I don't understand is why word was created in the first place. There were already types, like int and long, that are obvious types. The type word looks like it should be used along with the types letter, paragraph, chapter, etc. When the hell is Microsoft going to try to foist those types off as something new?

Agreed, completely. I had a tough time understanding why word and byte were used interchangably with uint16_t and uint8_t when I started this project (sourcing different code bases). I decided to leave the code unaltered during development to avoid adding in my own errors to working code. When it's all complete, I plan on a major code cleanup.

That being said, anyone have an idea about the second function not being executed? I started stripping everything out of the code that wasn't related to printing so I could find the trigger, but I went too far and deleted some needed code so I trashed the effort. Now that the issue is back even without the SimpleTimer library, I think it needs to be addressed.

Ok, I can give that a look. Is there a way to print available memory to confirm your theory? I had an issue with a pro mini that I was writing at the wrong clock speed accidentally and writing the CPU speed sussed the issue.

Is there a way to print available memory to confirm your theory?

http://playground.arduino.cc/Code/AvailableMemory

I should have searched before posting. I was just looking at that page and think one of the included codes should help. Looks like the 6th option (freeRam) is quite compact so I'll try it first.

It appears that the memory may not be the issue (or I'm not looking at the data correctly). I added the freeRam function and printed the it's output before and after calling the MQTTreport functions. It returned the same value (~600-800 depending on the code at the time).

I modified the code (as attached) so that the MQTTreport function now returns a char array that is constructed using sprintf. It seems to use approximately the same memory after the function call. I assume that if I put the freeRam call inside the MQTTreport function when the "packet" variable still exists, free memory would be lower.

Either way, I have made changes such that the MQTT broker now sees the communication from the Arduino. There is an issue with wind speed being reported as blank when it's zero, but I'm guessing this is some kind of formatting issue. The wind speed sometimes reports 0 the first time but is blank every other time.

pi@raspberrypi ~ $ mosquitto_sub -h localhost -v -t '#'
ookDecoder online
blueline TotalEnergy=0, CurrentPower=1576, TempF=0, Battery=0
acurite5n1 Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=55.80, Humidity=96, Battery=1
blueline TotalEnergy=0, CurrentPower=1576, TempF=0, Battery=0
acurite5n1 Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=55.80, Humidity=96, Battery=1

ookDecoder-ben5.ino (3.79 KB)

Acurite5n1.h (9.93 KB)

Blueline.h (10.4 KB)

DecodeOOK.h (2.62 KB)

temp_lerp.h (963 Bytes)

      char str_windspeedkph[6];
      dtostrf(windspeedkph,4,2,str_windspeedkph);
      sprintf(packet,"Windspeedkph=%s",str_windspeedkph);
      Serial.println(packet);

If the wind speed is 3.5 kph, what do you think str_windspeedkph is going to contain? If it is 10.6?

I'm sorry, I don't understand the question. But, if the wind speed was reported as 3.5 kph, then windspeedkph should hold (float)3.5. Then I would expect the value of str_windspeedkph to be "3.50". If the value in windspeedkph was 10.6, I would expect str_windspeedkph to be "10.60". When I run the code and watch the serial window, I see str_windspeedkph reported correctly so it appears that this code works:

char str_windspeedkph[6];
dtostrf(windspeedkph,4,2,str_windspeedkph);
sprintf(packet,"Windspeedkph=%s",str_windspeedkph);
Serial.println(packet);

The next line in the serial window should be the windspeed in mph but it the output is blank. I only see "Windspeed=". So this code appears to be an issue:

dtostrf(convKphMph(windspeedkph),4,2,str_winds);
...
sprintf(packet,"Windspeed=%s",str_winds);
Serial.println(packet);

NOTE: I copied the serial window output to a file but did not copy it to my USB stick this morning so I don't have it with me.

If the value in windspeedkph was 10.6, I would expect str_windspeedkph to be "10.60"

How can you expect that? You said that the field width was 4. "10.60" has a width of 5. At least, the way I count it does.

The documentation I read indicated that sprintf had 4 parameters.

  • float input
  • minimum length of output string (0.00 = 4)
  • precision (number of digits after decimal)
  • output variable

The issue seems to be something else though. This is the output of the serial window:

TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
Windspeed=0.00
Windspeed=0.00
765
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=0.00, Humidity=0, Battery=0
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=0.00, Humidity=0, Battery=0
connction failed
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
Windspeed=0.00
Windspeed=0.00
713
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
connction failed
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
Windspeed=0.00
Windspeed=0.00
713
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
connction failed
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
Windspeed=0.00
Windspeed=0.00
713
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
Windspeed=0.00, Winddir=0.00, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
connction failed
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
Windspeed=0.00
Windspeed=
713
Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
connction failed
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
Windspeed=0.00
Windspeed=
713
Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
connction failed
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
TotalEnergy=0, CurrentPower=0, TempF=0, Battery=0
Windspeed=0.00
Windspeed=
713
Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
Windspeed=, Winddir=112.50, Rainfall=0.00, TempF=56.80, Humidity=81, Battery=1
connction failed

Generated by the following code:

    char* MQTTreport_c (void) {
      char packet[100];
      float windspeed = convKphMph(windspeedkph);
      char str_temp[6];
      char str_winds[6];
      char str_windd[6];
      char str_rain[6];
      
      dtostrf(tempf,4,2,str_temp);
      dtostrf(windspeed,4,2,str_winds);
      dtostrf(winddir,4,2,str_windd);
      dtostrf(rainfall,4,2,str_rain);
      /*
      char str_windspeedkph[6];
      dtostrf(windspeedkph,4,2,str_windspeedkph);
      sprintf(packet,"Windspeedkph=%s",str_windspeedkph);
      Serial.println(packet);
      */
      Serial.print("Windspeed=");
      Serial.println(windspeed);
      
      sprintf(packet,"Windspeed=%s",str_winds);
      Serial.println(packet);
      
      Serial.println(freeRam());

      sprintf(packet,"Windspeed=%s, Winddir=%s, Rainfall=%s, TempF=%s, Humidity=%u, Battery=%u",
        str_winds, str_windd, str_rain, str_temp, humidity, batteryok);
      
      Serial.println(packet);
      return packet;
    }

In this run, I did not have the Uno hooked up to the network which is why it indicates "connction failed". The integer reported is the output from freeRam at the end of the acurite5n1.MQTTreport_c function. The interesting thing is that the first "windspeed=" statement (output from a println of the float value) always reports correct. The second "windspeed=" is output from the sprintf line starts correct but breaks at some point. However, the windspeed is always 0.00.