[Solved] Problem reading six digit string sent from raspberry pi

Hello, I’m trying to receive a six digit string from a pi via serial but am unable to do so. I have hooked up a OLED for troubleshooting. I am able to send a five digit number fine. The OLED reads the number no problem. However, when I send a six digit number the OLED reads a negative number. Both codes are configured to a 19200 baud rate. I have tried 115200 as well. I’m thinking it may have to do with byte/data issues, but am unsure. I’ve included the necessary libraries. Here’s the part of the code with the serial. If my python code is necessary I can gladly post it. The numbers end goal is for the numbers to be displayed numerically on nixie tubes. Thanks for any help.

int NumberArray[6]={10,10,10,10,10,10};
const int MaxChars = 6;
char strValue[MaxChars+1];
int index = 0;
int stock_price = 0;
int d5, d4, d3, d2, d1, d0 = 0;

void loop()     
{
  if (Serial.available()) 
  { 
    display.clearDisplay();               //clear I2C display
    char ch = Serial.read();
    delay(1);    //read char data from RPi via USB serial cable
    if (ch > '9')
    {
      Serial.println("'A' received");     // received command to blank display
      NumberArray[6]=(10,10,10,10,10,10); // '10' blanks a digit
      DisplayNumberString(NumberArray);
      delay(1000);
    }
    if (index < MaxChars && ch >= '0' && ch <= '9') 
    { 
      strValue[index++] = ch;            //build string
    }
    else
    {
      strValue[index] = 0;       
      stock_price=atoi(strValue);            //convert ascii to integer
      index = 0;                             //reset index for next time
//      Serial.print("the stock price is "); //print to debug console
//      Serial.println(stock_price);
      d5 = stock_price % 10;                 // use modulo math to separate integer into indiv. digits
      d4 = (stock_price / 10) % 10;
      d3 = ((stock_price / 10) / 10) % 10;
      d2 = (((stock_price / 10) / 10) / 10) % 10;
      d1 = ((((stock_price / 10) / 10) / 10) / 10) % 10;
      d0 = (((((stock_price / 10) / 10) / 10) / 10) /10) % 10;
      display.setCursor(0,18);     // print stuff to OLED display (was used for debug)
      display.println(stock_price);
      display.display();           // this actually prints what was just set up to OLED
    }
  }
  NumberArray[0] = d0;             // print each digit to a tube (ordering depends on tube board)
  NumberArray[4] = d1;
  NumberArray[2] = d2;
  NumberArray[3] = d3;
  NumberArray[1] = d4;
  NumberArray[5] = d5;             // MSB
  DisplayNumberString(NumberArray);
}

We really need to see all of your code. Also, where are setup() and DisplayNumberString()? Finally, this line:

  • NumberArray[6]=(10,10,10,10,10,10); // '10' blanks a digit*

seems very suspect. What are you trying to do here?

An “int” on an Arduino is only 16bits long, so it can only hold 5-digit numbers (and relatively small 5-bit numbers at that - only up to 32767 if “signed.”) Change your “stock_price” variable to a “long” and use “atol” instead of “atoi”, and you should be OK.

(Your algorithm for converting back to individual digits is pretty awful, but that’s not what you asked about. There are standard algorithms using repeated divisions that are “well known and widely published”; look them up if you want.)

I’ll give the long and atol a shot. That makes sense because it’s reading out the same numbers in a loop with a five digit limit. What should I search under for those standard algorithms? I’m sure it’s pretty ugly to a professional. Would like to learn to be more clean and simple. Thanks for the feedback. I’ll let you know.

Nixie_Ticker.ino (6.25 KB)

What should I search under for those standard algorithms?

Well, rats. It was a lot more difficult to find what I was thinking of than I thought it would be. The web is full of "academic" examples using recursion, or pow() or long discussions of the theory. Sigh.

The key point is that "num % 10" always gives you the least significant digit of num, and "num/10" gives you everything EXCEPT the least significant digit, so you can loop with just the two operations to get as many digits as you want. Also, since division algorithms and/or instructions often give you quotient and remainder at the same time, this can be a lot more efficient.

/*
 * Convert n digits of a number x into individual digits in the char
 * array NumberArray, including leading zeros.
 * Note that x is destroyed.
 */

  n = 6;  // six digits
  x = stock_price;
  while (n > 0) {
    n = n-1;  // one less digit to go (adjust array index, too.)
    NumberArray[n] = x % 10;  // extract the least sig digit.
    x = x / 10;               // keep remaining digits.
  }

Do I need to create a serial flush or end line?

Yes. probably in DisplayNumberString()

Thanks for the guidance. I'll get at that. Now that I look at it the numbers aren't compounding they are just getting mixed up. The first number it correct, 624492, but then its 244926, 449262, 492624, 926244, till it loops back to the first. Maybe your code can help with that.