Changing baud rate interactively

At the bottom of an instruction page I put 4 boxes (buttons) to select baud rate. I have a scale set at 4800. If the Mega 2560 Serial1 happens to be set to 2400 and I "click" 4800, everything works ok. If it's set to 4800 and I select 2400, I expect the data stream to be garbage, but it's not. It's valid data. It appears that the baud rate didn't change. It appears to work if the change is faster but not slower.

Compared to most people here I am sub-beginner. Not looking for the most elegant or compact code. Maybe I'll get there someday but at 77 I'm not holding my breath.

This was added to setup(). I probably could have put the baud rate directly into 2 bytes of EEPROM, but I didn't.

void setup() {
  // put your setup code here, to run once: 
  Serial.begin(9600);               // when communicating with serial monitor
  
  Baud_ndx = EEPROM.read(ep_start_P + 46);
    switch (Baud_ndx)
    {
      case 1:
      Baud = 1200;
      break;
      case 2:
      Baud = 2400;
      break;
      case 3:
      Baud = 4800;
      break;
      case 4:
      Baud = 9600;
      break;
    }
  Serial1.begin(Baud);

This is what I added to the last instruction page.

tmyGLCD.setFont(Retro8x16);
  myGLCD.setColor(0xffffaa);
  myGLCD.print("Baud Rate", CENTER, 220);       // display baud choices
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (9, 240, 49, 265);
  myGLCD.drawRoundRect (69, 240, 109, 265);
  myGLCD.drawRoundRect (129, 240, 169, 265);
  myGLCD.drawRoundRect (189, 240, 229, 265);
  myGLCD.print("1200", 13, 246);
  myGLCD.print("2400", 73, 246);
  myGLCD.print("4800", 133, 246);
  myGLCD.print("9600", 193, 246);
  Baud_ndx = EEPROM.read(ep_start_P + 46);
  myGLCD.setColor(255, 0, 0);                   // change current baud box to red
  if(Baud_ndx == 1)
    myGLCD.drawRoundRect (9, 240, 49, 265);
  if(Baud_ndx == 2)
    myGLCD.drawRoundRect (69, 240, 109, 265);
  if(Baud_ndx == 3)
    myGLCD.drawRoundRect (129, 240, 169, 265);
  if(Baud_ndx == 4)
    myGLCD.drawRoundRect (189, 240, 229, 265);

  while(true)
  {
    myTouch.read();
    x=myTouch.getX();
    y=myTouch.getY();

    if (y >= 240 && y <= 265){
      myGLCD.setColor(255, 0, 0);
      if(x >= 9 && x <= 49){
        Baud_ndx = 1;
        Baud = 1200;
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.drawRoundRect (129, 240, 169, 265);
        myGLCD.drawRoundRect (189, 240, 229, 265);
      }
      if(x >= 69 && x <= 109){
        Baud_ndx = 2;
        Baud = 2400;
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.drawRoundRect (129, 240, 169, 265);
        myGLCD.drawRoundRect (189, 240, 229, 265);
      }
      if(x >= 129 && x <= 169){
        Baud_ndx = 3;
        Baud = 4800;
        myGLCD.drawRoundRect (129, 240, 169, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.drawRoundRect (189, 240, 229, 265);
      }
      if(x >= 189 && x <= 229){
        Baud_ndx = 4;
        Baud = 9600;
        myGLCD.drawRoundRect (189, 240, 229, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.drawRoundRect (129, 240, 169, 265);
      }
    }
    if (((x >= 86) && (x <= 152)) && ((y >= 298) && (y <= 317))) {    // EXIT
      EEPROM.update((ep_start_P + 46), Baud_ndx);
      Serial1.end();
      Serial1.begin(Baud);

Just curious, does the baud rate change work if you change it, then power cycle the Arduino so it gets the new rate outta EEPROM in setup()?

That's what it looks like you were going for, so I ask if that way works before thinking about why what on-the-fly isn't work yet.

a7

I wanted the baud rate to be loaded from EEPROM upon power up but I didn’t want to HAVE to do a power cycle.
When baud rates match you get good data transmission. When they don’t match you get garbage. I consider both conditions as working properly. I don’t understand why the rate changes properly going from 2400 to 4800 but apparently doesn’t change at all going from 4800 to 2400.

usually

Use a scope if you want a real test.

What type of Arduino are we talking about? That's a pretty important detail. If it's using USB serial then the change will be detected on both ends IINM.

1 Like

I realize you get garbage when they don’t match. That’s what I expected to see.
I’m using the Mega 2560 with display shield, touchscreen and a custom board using a MAX3221 to interface between Tx1/Rx1 and RS-232 for the scale. The scale is only transmitting. I’m not sending anything to the scale.
I have a scope and the scale transmits correctly at its different baud rates. It’s the Mega that doesn’t appear to downshift without a reboot.

Just briefly looking at the code I see the baud rate setting is in the setup function. This, as your comment suggests runs once at start up.

I can't see the setup function being called again from the body of the code. But then you have only posted a portion of the code where as

Does tell you to post all your code.

I don’t call setup again but the last line of my first post shows a Serial1.begin(Baud);

The total program is 3,000 lines. I didn’t think anyone would want to wade through all that when most of it has nothing to do with this serial issue.

I suggest that you add some Serial.print statements in the body of that if to check if the EEPROM.update is indeed called and Baud_ndx has the expected value.

    if (((x >= 86) && (x <= 152)) && ((y >= 298) && (y <= 317))) {    // EXIT
      Serial.print("Updating EEPROM: ");
      Serial.println(Baud_ndx);
      EEPROM.update((ep_start_P + 46), Baud_ndx);
      Serial1.end();
      Serial1.begin(Baud);

Note that printing to e.g. Serial Monitor is a valuable debug tool.

Reduce the code to a complete example that does exhibit the serial issue.

Then write a code that just shows the problem.

How do you know that complex if statement actually works? Also there is no closing brace to that if statement, so does it do anything else?

Also if Baud still has the last value it had when you first ran your code, then how is stopping it and starting it again (with the same value) going to do anything? After all that closing salvo doesn't do anything to change Baud does it?

  1. You can strip it down to a basic version that demonstates the issue (see @Delta_G's comment above) .
  2. It's possible that other parts of the code have an effect without you realising it.

BTW, where I'm from we call that a little bit of code. If it's well formatted and well organized then I have no problem with something that big.

But the process of creating an MCVE will help us both. You'll probably find the bug in the process and if you don't then it will make it easier for someone here to help you find it.

1 Like

Here is reduced code that deals with my problem except here it seems to work.
Most of it is UI for my benefit.

#include <UTFT.h>
#include <URTouch.h>
#include <URTouchCD.h>
#include <EEPROM.h>

#define TOUCH_ORIENTATION PORTRAIT

// Initialize display
UTFT myGLCD(CTE32_R2, 38, 39, 40, 41);

// Initialize touchscreen
URTouch  myTouch( 6, 5, 4, 3, 2);
// Declare which fonts we will be using
extern uint8_t SmallFont[];
extern uint8_t Retro8x16[];
extern uint8_t Arial_round_16x24[];
extern uint8_t arial_bold[];
int x, y;  
int strStart;                // valid start of string

char* X;
//
//  ep_start_P allows for EEPROM wear leveling for PWM mode. It defines the start address for the
//  first EEPROM address to be used (actually it will be ep_start_P + 9). It is suggested
//  that the blocks be increased by 40 each time it gets reassigned. EEPROM should
//  be good for 100,000 writes (so a block should be good for a long time).
//  Example: blocks should start at address: 0, 40, 80, 120, 160..... etc.
//
int ep_start_P = 0;           // EEPROM start address for PWM mode
double CurWeight;

const unsigned int MAX_INPUT = 11;
int inByte, Baud, Baud_ndx;
static char input_line [MAX_INPUT];

/**********
*  setup  *
**********/
void setup() {
  
  Serial.begin(9600);               // when communicating with serial monitor
  Baud_ndx = EEPROM.read(ep_start_P + 46);
    switch (Baud_ndx)
    {
      case 1:
      Baud = 1200;
      break;
      case 2:
      Baud = 2400;
      break;
      case 3:
      Baud = 4800;
      break;
      case 4:
      Baud = 9600;
      break;
    }
  Serial1.begin(Baud);
  //Serial1.begin(4800);
  myGLCD.InitLCD(0);    // Portrait
  myGLCD.clrScr();
  myTouch.InitTouch(TOUCH_ORIENTATION);
  myTouch.setPrecision(PREC_MEDIUM);
  
  myGLCD.setFont(arial_bold);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.setColor(255, 255, 170);
  myGLCD.print("Instructions", 20, 118);
  myGLCD.drawRoundRect (20, 118, 214, 134);
}       // end setup  

/*********
*  loop  *
*********/
void loop() {

  if(Serial1.available () > 0) {          // getting data from the scale
      inByte = Serial1.read();
      processIncomingByte(inByte);
    }

    if (myTouch.dataAvailable()){
      myTouch.read();
      delay(100);
      x=myTouch.getX();
      y=myTouch.getY();

  if ((x >= 20) && (x <= 214) && (y>= 118) && (y <= 134))   // go to instructions
        Instr();
}
}

/********************
*    Instructions   *
********************/
  void Instr()
  {
  myGLCD.setFont(arial_bold);
  myGLCD.setColor(0xffffaa);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.drawRoundRect(86, 298, 152, 317);
  myGLCD.setColor(0, 255, 0);
  myGLCD.print("EXIT", CENTER, 300); 
  myGLCD.setFont(Retro8x16);
  myGLCD.setColor(0xffffaa);
  myGLCD.print("Baud Rate", CENTER, 220);       // display baud choices
  myGLCD.setColor(255, 255, 255);
  myGLCD.drawRoundRect (9, 240, 49, 265);
  myGLCD.drawRoundRect (69, 240, 109, 265);
  myGLCD.drawRoundRect (129, 240, 169, 265);
  myGLCD.drawRoundRect (189, 240, 229, 265);
  myGLCD.print("1200", 13, 246);
  myGLCD.print("2400", 73, 246);
  myGLCD.print("4800", 133, 246);
  myGLCD.print("9600", 193, 246);
  Baud_ndx = EEPROM.read(ep_start_P + 46);
  myGLCD.setColor(255, 0, 0);                   // change current baud box to red
  if(Baud_ndx == 1)
    myGLCD.drawRoundRect (9, 240, 49, 265);
  if(Baud_ndx == 2)
    myGLCD.drawRoundRect (69, 240, 109, 265);
  if(Baud_ndx == 3)
    myGLCD.drawRoundRect (129, 240, 169, 265);
  if(Baud_ndx == 4)
    myGLCD.drawRoundRect (189, 240, 229, 265);

  while(true)
  {
    myTouch.read();
    x=myTouch.getX();
    y=myTouch.getY();

    if (y >= 240 && y <= 265){
      myGLCD.setColor(255, 0, 0);
      if(x >= 9 && x <= 49){
        Baud_ndx = 1;
        Baud = 1200;
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.drawRoundRect (129, 240, 169, 265);
        myGLCD.drawRoundRect (189, 240, 229, 265);
      }
      if(x >= 69 && x <= 109){
        Baud_ndx = 2;
        Baud = 2400;
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.drawRoundRect (129, 240, 169, 265);
        myGLCD.drawRoundRect (189, 240, 229, 265);
      }
      if(x >= 129 && x <= 169){
        Baud_ndx = 3;
        Baud = 4800;
        myGLCD.drawRoundRect (129, 240, 169, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.drawRoundRect (189, 240, 229, 265);
      }
      if(x >= 189 && x <= 229){
        Baud_ndx = 4;
        Baud = 9600;
        myGLCD.drawRoundRect (189, 240, 229, 265);
        myGLCD.setColor(255, 255, 255);
        myGLCD.drawRoundRect (9, 240, 49, 265);
        myGLCD.drawRoundRect (69, 240, 109, 265);
        myGLCD.drawRoundRect (129, 240, 169, 265);
      }
    }
    if (((x >= 86) && (x <= 152)) && ((y >= 298) && (y <= 317))) {    // EXIT
      EEPROM.write((ep_start_P + 46), Baud_ndx);
      Serial1.end();
      Serial1.begin(Baud);
      Serial.println(Baud);
      //myGLCD.clrScr();
      myGLCD.setColor(0, 0, 0);
      myGLCD.fillRect(5, 150, 235, 318);
      
      return;
    }
  }
  }

/*************************
 *  processIncomingByte  *
 ************************/
 void processIncomingByte (const byte inBite) {

  static unsigned int input_pos = 0;

  switch (inBite)
  {
    case '\r':            // carriage return means end of text
      CurWeight = strtod(input_line, &X);
      strStart = 0;
      input_pos = 0;      // reset buffer for next time
      Serial.println(CurWeight);
      break;

    case '+':
      strStart = 1;
      input_pos = 0;
      input_line[input_pos++] = inBite;
      break;

    case '-':
      strStart = 1;
      input_pos = 0;
      input_line[input_pos++] = inBite;
      break;
    
    default:              // keep adding if not full ... allow for terminating null byte
      if ((input_pos <= MAX_INPUT) && (strStart == 1))
        input_line[input_pos++] = inBite;
      if(input_pos > 11)
        input_pos = 11;
 
      break;
  }   // end of switch
 }    // end of processIncomingByte

Scale is set to 4800 and has a weight of 16.30 on it. The Mega with the other boards (the "box") is set to 4800. This is the output on the serial monitor -

4800
16.30
16.30
16.30
16.30
16.30
16.30
16.30
16.30
16.30
ad infinitum

I set the box to 2400 and get just this -

2400

and no measurements, which I expect. So, why does it behave properly here and not in the main program? Probably no one can answer that without seeing the main program. I will attempt to stare at the code (until my eyes glaze over) to see if I can find anything.

Found the problem. Since data coming in with a mismatched baud rate is garbage, processIncomingByte() can't update CurWeight so the program uses the last value which messed up the program. My solution is to set CurWeight to -1 right after a Serial1.begin. It will be updated if the baud rates match and -1 provides proper results.

Thank you all for your inputs.

I wish I had kept count. So very true.

a7