Can someone help me reduce this code to get it to work on an Uno?

Hello

I used a piece of code for controlling a BBQ from Homebrew BBQ Temperature Monitor/Controller VERSION 2 but I had to make changes to the code to support a different wifi card. I’m struggling to get the new card to fit into the arduino without a ton of issues especially while it’s running. Something seems to get corrupt and the display shows random garbage. I tried to fix this a few times so now I’m coming to the experts. I’m trying to avoid what I would call the nuclear option of moving to a Mega.

I attached the main file for you. Any help would be appreciated.

Thanks!

BBQ_Controller.ino (14.1 KB)

You say you made changes to the code for a different wifi card. So I assume that 'note 1' at the top of your file doesn't apply. Anyway, your code includes several header files which we would need to be able to check your code.

    Serial.println("Unable to connect to WiFi, retrying in 1 second");

Use the F Macro

String standardMessage() {
  String message = "";

  // output the value of each analog input pin
...
...
  return message;

}

This isn't going to work because message is local to the function and will not exist as soon as the function exits.

Why use String at all? You only use String to create a message string here and in ParseReceivedRequest. Both can be done just as easily with a null-terminated C string which will remove the risk of fragmentation of the heap.

%2.2d:%2.2d:%2.2d

I hadn't seen this before and wasn't sure it would work - but it does! The other way to do it is:

%02d:%02d:%02d

Pete

const char html_open[] PROGMEM = "<html>";

void setup() {
  char line[80];
  Serial.begin(250000);
  Serial.println((__FlashStringHelper*) html_open);
  sprintf_P(line, PSTR("<h2>Setpoint: %d</h2>\n</%S"), 1234, html_open + 1);
  Serial.println(line);
}
void loop() {}
<html>
<h2>Setpoint: 1234</h2>
</html>

Note the sprintf**_P** and the %S format for PROGMEM strings.

quilkin: You say you made changes to the code for a different wifi card. So I assume that 'note 1' at the top of your file doesn't apply. Anyway, your code includes several header files which we would need to be able to check your code.

Correct I didn't change the name of the note but I did change the card code so the flag if I remember still turns on and off wifi.

BulldogLowell:

    Serial.println("Unable to connect to WiFi, retrying in 1 second");

Use the F Macro

I will check this out.

el_supremo:

String standardMessage() {

String message = “”;

// output the value of each analog input pin


 return message;

}



This isn't going to work because message is local to the function and will not exist as soon as the function exits.

Why use String at all? You only use String to create a message string here and in ParseReceivedRequest. Both can be done just as easily with a null-terminated C string which will remove the risk of fragmentation of the heap.



%2.2d:%2.2d:%2.2d



I hadn't seen this before and wasn't sure it would work - but it does!
The other way to do it is:


%02d:%02d:%02d




Pete

My C isn’t excellent so I’ll look into how to do this as a null terminated C string. But I was under the impression you really can’t “build” them by concatenating. like for example in this function

String standardMessage() {
  String message = "";

  // output the value of each analog input pin
  for (int i = 0; i < 6; i++) {
    message += "analog input ";
    message += i;
    message += " is ";
    message += analogRead(i);
    message += "
";
  }
  return message;

}

I’m building the string and I thought I’d have to do that by index?

Whandall:

const char html_open[] PROGMEM = "<html>";

void setup() {
 char line[80];
 Serial.begin(250000);
 Serial.println((__FlashStringHelper*) html_open);
 sprintf_P(line, PSTR(“

Setpoint: %d

\n</%S”), 1234, html_open + 1);
 Serial.println(line);
}
void loop() {}





Setpoint: 1234

> ``` > > > Note the sprintf**_P** and the **%S** format for PROGMEM strings.

I’m not clear what you mean

I'm building the string and I thought I'd have to do that by index?

First, the string (whether it is String or C string) that you use in that function must be global. To use a C string you first declare message to be at least as long as the string you are generating, plus one more for the null on the end. You can build a C string by concatenation (see the strcpy and strcat functions) but for what you are doing you could just use sprintf, which you are already using anyway. Something similar to this:

char message[32];
char * standardMessage(void) {
  sprintf(message,"analog input %d is %d
",i,analogRead(i));
  return(message);
}

Arggghhhhh. I've just realized that you don't call standardMessage anywhere in your code so it's not going to be included in the compiled sketch.

Your only other use of String is in ParseReceivedRequest. That doesn't need to use String either. You can use a for loop to go through buffer looking for the '/' character. It's not difficult to do.

Pete

Something seems to get corrupt and the display shows random garbage.

This is usually caused by code scribbling over memory that it does not own.

Let’s have a look-see …

  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      if (c == '\n')
        break;
      else if (bufferSize < bufferMax)
        buffer[bufferSize++] = c;
      else
        break;
    }
  }

I’m not seeing a ‘\0’ here.

  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      if (c == '\n')
        break;
      else if (bufferSize < bufferMax-1)
        buffer[bufferSize++] = c;
      else
        break;
    }
  }
  buffer[bufferSize] ='\0';
  //Received buffer contains "GET /cmd/param1/param2 HTTP/1.1".  Break it up.
  if (cmdAsString.indexOf("/") == cmdAsString.lastIndexOf("/")) {
    cmdAsString = "/";
  }

There are a variety of things that a client may send to your server, in particular it may send an HTTP “OPTIONS” request, which won’t necessarily have a path. There’s no handling for that here.

In general - don’t use the String class. use arrays of char and the libc String.h functions, which are linked into arduino code by default.

=======

My suggestions:

  • Alter the gear that reads the lines to add a ‘\0’ terminator. This is most probably the issue causing your bug.
  • Don’t use String. Learn to use char arrays and libc. “String” is just a wrapper for these, anyway, so you already know what the functions do.
  • Check that your request line really does start with a GET and end with a HTTP/1.1 . Better still - parse the HTTP headers and request line parameters properly.

DomoArigatoMrRoboto: I'm not clear what you mean

Use sprintf_P() to stop all those format strings consuming RAM, use %S to embed PROGMEM strings in your sprintf output.

Reuse strings whenever possible.