Serial communication changes my frequency output

I'm using an Arduino Uno to output a frequency to move the speedometer gauge from an information cluster.
Every time i send a serial message (to update the speed and such), the gauge gets moved back a little bit
I presume it's because serial communication uses interrupts.
Is there any way to fix this issue? Here's my code in it's entirety.:

//0.7hz per km/h
//0.1hz per 1000rpm


//A0 - right blinker
#define rBlinker A0
#define lBlinker A1
#define lLights A2
#define ABS A3 
#define lowFuel A4
#define speedo 2
#define tacho 3
#define fuel 10
#define temp 5
long speedodelay;
long tachodelay;
long fueldelay;
int currSpeed;
int currRPM;
int currFuel;
unsigned long previousMicros = 0;
unsigned long previousMicrosT = 0;
bool fuelState;

void setup() {
  // put your setup code here, to run once:
  pinMode(rBlinker, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  Serial.begin(115200);
  Serial.setTimeout(50);
}

void loop() {
  // put your main code here, to run repeatedly:
  //digitalWrite(rBlinker, HIGH);
  noInterrupts();
  tachoLoop();
  speedoLoop();
  interrupts();
  if(Serial.available()) {
    String msg = Serial.readString();
    Serial.println(msg.charAt(0));
    switch(msg.charAt(0)) {   
      case 's':
        {
          msg.remove(0, 1);
          
          currSpeed = msg.toInt();
          
          float frequency = currSpeed * 0.7;
          float period = 1 / frequency;
          
          speedodelay = period * 1000000;
        }
        break;

      case 't':
        {
          msg.remove(0, 1);
          currRPM = msg.toInt();
          float frequencyT = currRPM * 0.033;
          float periodT = 1 / frequencyT;
          tachodelay = periodT * 1000000;
        }
        break;

      case 'f':
        {
          msg.remove(0, 1);
          currFuel = msg.toInt();
          float frequencyF = currFuel * 0.04;
          float periodF = 1 / frequencyF;
          fueldelay = periodF * 1000000;
          Serial.println(msg);
        }
        break;
      
      case 'b':
        {
          msg.remove(0, 1);
          int state = msg.charAt(1) == '1' ? 1 : 0;
          if(msg.charAt(0) == 'l') {
            digitalWrite(lBlinker, state);
          }
          else { 
            digitalWrite(rBlinker, state);
          }
          Serial.println(msg.charAt(1));
        }
        break;

    }
  }

  int fuelPWM = map(currFuel, 0, 100, 110, 240);
  
  analogWrite(5, 140); // water temp, 120 is middle, 140 is maax, 100 is 0
  analogWrite(10, fuelPWM); // fuel level, 170 - middle, 240 - full, 110 - empty
}

void speedoLoop() {
  unsigned long currentMicros = micros();
  if(currentMicros - previousMicros >= speedodelay / 2) { 
    previousMicros = currentMicros;
    digitalWrite(speedo, !digitalRead(speedo));
  }
}

void tachoLoop() {
  unsigned long currentMicrosT = micros();
  if(currentMicrosT - previousMicrosT >= tachodelay / 2) {
    previousMicrosT = currentMicrosT;
    digitalWrite(tacho, !digitalRead(tacho));
  }
}

I'm fully aware that it's really ugly, and i'm sorry for that.

The readString() function blocks. The methods for reading serial data in the serial input basics tutorial do not block and they do not use the potentially problematic String class.

1 Like

You don't need to give up the convenience and safety of Strings see
Arduino Software Solutions for a number of simple sketches for reading from Serial (blocking and non-blocking) with their pros and cons.

But you seem to be reading just one char, so try

void loop() {
 .  . . 
 int c = Serial.read(); // note read() returns an int
  if (c != -1) { // read() return -1 if there is nothing to be read. 
    // got a char handle it
    char inChar = c; // need to cast to char c to print it otherwise you get a number instead
    Serial.println(inChar); // echo it if needed
    switch(inChar) {
     case 's':  ///
       // etc
  }

Your minimal use if strings is not a problem but check out my tutorial on Taming Arduino Strings
if you start using a lot of them.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.