Help me optimise this arduino code (it runs to slow)

Hello everyone,
I-am trying to create a thermometer with bluetooth to connect with a phone.
The idea is that i code a few functions on the arduino that can be run by a command over bluetooth.

Now the code works and has everything i want so far. however it runs slow as f.
It takes one command "readC" for example every 1.5 ish seconds.
I know it can read the temp over 10 times each second so something goes wrong in figuring out what command has been given i guess.

However i-am a PHP Javascript guy and not so much a C? guy.
So someone PLEASE HELP ME OPTIMISE THIS CODE:

 *  SS:   pin 10                                                               
 *  MOSI: pin 11 (NC)                                                          
 *  MISO: pin 12                                                               
 *  SCK:  pin 13                                                               
 *  VCC:  pin 14                                                               
 *  GND:  pin 15                                                               
 *  arduino>>bluetooth
 *  RX:   PIN 2
 *  TX:   PIN 3                                                                
 * Arduino Pro Mini 328 3.3V/8MHz                                              


#include <SoftwareSerial.h>// import the serial library
#include "Adafruit_MAX31855.h"
#include <SPI.h>  // Included here too due Arduino IDE; Used in above header

SoftwareSerial SoftSerial(3, 2); //arduino RX, TX
String BluetoothData;

#define RPin  5
#define GPin  6
#define BPin  9

#define MAXCS   10
Adafruit_MAX31855 thermocouple(MAXCS);

void setup() {
  SoftSerial.begin(19200);
  while (!Serial) {
   delay(1); // wait for serial port to connect
  }
  pinMode(RPin, OUTPUT);
  pinMode(GPin, OUTPUT);
  pinMode(BPin, OUTPUT);
  SoftSerial.println("Software serial over bluetooth starting");
}

void loop() {
  delay(100);
  if(SoftSerial.available()){
    BluetoothData = SoftSerial.readString();
    BluetoothData.trim();
    //SoftSerial.println(BluetoothData);

    if(BluetoothData.equals("readAll")){
      SoftSerial.print("Internal Temp = ");
      SoftSerial.println(thermocouple.readInternal());
      SoftSerial.print("C = "); 
      SoftSerial.println(thermocouple.readCelsius());
      SoftSerial.print("F = ");
      SoftSerial.println(thermocouple.readFarenheit());
      
     }else if(BluetoothData.equals("setLed")){
      int RedInt = 0;
      int GreenInt = 0;
      int BlueInt = 0;
      float AlphaFloat = 0.0;
      
      SoftSerial.println("send color like this: 255,255,255,1.0 ");
      
      String RedStr = SoftSerial.readStringUntil(',');
      Serial.read();
      String GreenStr = SoftSerial.readStringUntil(',');
      Serial.read();
      String BlueStr = SoftSerial.readStringUntil(',');
      Serial.read();
      String AlphaStr = SoftSerial.readStringUntil('\0');

      RedInt = RedStr.toInt();
      GreenInt = GreenStr.toInt();
      BlueInt = BlueStr.toInt();
      AlphaFloat = AlphaStr.toFloat();
      
      RedInt = constrain(RedInt, 0, 255);
      GreenInt = constrain(GreenInt, 0, 255);
      BlueInt = constrain(BlueInt, 0, 255);
      AlphaFloat = constrain(AlphaFloat, 0.0, 1.0);
      setLED(RedInt, GreenInt, BlueInt, AlphaFloat);
      
     }else if(BluetoothData.equals("readC")){
      SoftSerial.print("C = "); 
      SoftSerial.println(thermocouple.readCelsius());
     }else if(BluetoothData.equals("readF")){
      SoftSerial.print("F = ");
      SoftSerial.println(thermocouple.readFarenheit());
     }else if(BluetoothData.equals("readInternal")){
      SoftSerial.print("Internal Temp = ");
      SoftSerial.println(thermocouple.readInternal());
     }else if(BluetoothData.equals("marco")){
      SoftSerial.println("polo");
     }else{
      SoftSerial.println("i did not understand that");
     }
    SoftSerial.println("send: readAll, readInternal, readC, readF, marco ");
  }
}
void setLED(int Red, int Green, int Blue, float Alpha )
{
  //SoftSerial.println(Red);
  //SoftSerial.println(Green);
  //SoftSerial.println(Blue);
  //SoftSerial.println(Alpha);
  analogWrite(RPin, (Red * Alpha));
  analogWrite(GPin, (Green * Alpha));
  analogWrite(BPin, (Blue * Alpha));
}

First thing you can do to improve performance is to ditch all the if's and use a proper switch-case.

2 Likes

You can't switch strings, unless arduinos have some sort of special support for that.

I didn't dig into much of his code, just saw all the statements, comparing strings and stuff.

Trying to work on it now.

I love switch cases, however i-am indeed not sure if arduino supports it in the way i-am used to and can build upon reliably.

However i think i found the solution, because i saw i made a little booboo at the beginning of the loop.
BluetoothData = SoftSerial.readString();
readString() if i remember correctly keeps on reading until a time-out is reached, now i think that time out is about a second?
that'd explain the slow running code. it waits 1s every time it loops.
I think i can fix it with
BluetoothData = SoftSerial.readStringUntil('\n');
And that should fix the slow running code. sadly i can't try it out at the moment but what do you guys think?

I made a gist.

I just took a quick stab at it, by removing redundent print statements, and using printf instead so I could pass it the return of the thermocouple function. I casted it to a float, just in case it returns just an int (not sure why it would as its temperature data).

1 Like

You are likely correct. I've skimmed over your code and can't see anything obvious that would warrant a one second delay, so I've been expecting to find an accidental "sleep" somewhere.

Switch statements require integers to work. Even if you managed to use strings with them you'd probably just end up comparing the pointers to the strings rather than their contents. Don't do that - it'll work some times, but now every time. Good luck finding such a bug :smiley:

yeah, you could do that or just use the one built into the standard library.

while ( getchar()  != '\n' ) {
   //do stuff
}

I'll test out a couple of things when i get to it again.
Thank you guys for now.
Is there an arduino simulator online somewhere? to see how the arduino reacts to certain code?

Assuming this is the library you are using:
https://www.arduino.cc/en/Serial/SetTimeout

The easiest solution might be to simply set the timeout to 0

I'm going to admin, this isn't really C, gotta be C++ or something based off C.

String don't exist in C, the actual term is character arrays, and you make them statically like this:
char s [] = "I'm a string";

Yeah, I'm not sure something like atoi() would work on an arduino, I don't know if uses the standard library.

We could easily spot the thing sucking up so much time if we throw it into gdb.

When you compile the code give the -g flag and then do gdb program then you can step through it. I'm assuming you're doing this on the device as it has links specific to that system.

That won't work, if you do that it could result into empty or broken strings.

Ideally, you want to avoid comparing strings, as this is insanely slow compared to comparing numbers.

I know, in the future i could just replace the "readC" for "1" and give every command a number.

When I get home today (in 2.5 hours), lets do a collab on this.

That doesn't really make much sense. If it can return garbled strings without timeout it can do the same without.

No need, i-am sorry.
Just a little project i-am working on that hit a snag.
The only thing i wanted was to fix the weird slow running code issue.

I don't have an arduino so I won't be compiling this anytime soon :unamused:

ahh oh well.

Now I wan't to get an arduino to see how it works.

1 Like

have a read
https://www.arduino.cc/en/Serial/ReadString
https://www.arduino.cc/en/Serial/SetTimeout