Displaying weigh scale data

I have been working with my UNO for a little while now and making progress.

I am trying via RS232 to read a string of data from my weigh scale and display it through an LCD display connected to my UNO.

I have a TTL converter and null modem adapter connected to my UNO as well as an LCD display.

The Serial Monitor reads the data properly from the scale. I need to display only part of the data stream on my LCD. It sends the data as a string.

While it reads data from the scale, I CAN print various messages to my LCD along with reading the data from the scale at the same time, just not the actual Serial Monitor data.

My Serial Monitor displays:

Uno Input

This is how the scale sends the data:

IMG_20220410_0002.pdf (209.3 KB)

I have tried a few versions of parsing the data and nothing works yet, I am not sure if I even should be trying to parse the data. It SEEMS like what I should be doing, but it's not working so far.

Here is my code with some notations I added along the way as I tried a few things.

scaletry5.ino (1.7 KB)

Take a look at strtok() to separate the parts of the string.
A lot of ppl (me included) won’t download your code from a 3rd party site.
Check the posting guidelines, and you’ll get a lot more help.

The weight data can include a decimal point. Can you provide an example of non integer readings?

OP's code

// include the library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// Set a string to add the "LBS" after the weight.  Not sure needed.

String msg = "<< Left Tank >> ";
String msg1 = " LBS";

//int scaleWeight = Serial.parseInt();

//Copied from SoftwareSerialExample
#include <SoftwareSerial.h>

SoftwareSerial mySerial(6, 7); // RX, TX

void setup() {
  // **********  put your setup code here, to run once:
  //Open Serial port to computer to monitor on Serial Monitor
  Serial.begin(9600);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);

  // Put display to the top left box
  lcd.setCursor(0, 0);
  // Display <<Left Tank>>
  lcd.println(msg);


  //Set scale input rate
  mySerial.begin(9600);

}

void loop() {
  // put your main code here, to run repeatedly:

  //Copied form SoftwareSerialExample
  if (mySerial.available()) {
    Serial.write(mySerial.read());

    if (Serial.available()) {
      //   mySerial.write(Serial.read());

      //If I have my LCD instructions here, I get nothing on the LCD

    }

    //If I have my LCD instructions here, still nothing

  }

  lcd.setCursor(0, 1);

  // lcd.println(scaleWeight);
  //when change to Serial.read, it shows -1 on the LCD
  //when change to parseint, it SLOWS down
  //when change to mySerial.read, Serial monitor changes to "11S,S+"
  lcd.print(msg); // If i change thie tp println, it messes with the serial monitor
}

I do not see any attempt to parse the input string, or even read it in completely. As long as you are reading characters from mySerial and sending them directly to Serial there will never be anything left to parse, much less display on the LCD.

It's terribly unclear how the UNO handles data.

You state that I haven't read it in completely, what function does that? I was under the (wrong) impression that once it's in the Serial Monitor , you then separate the data and do with as you need?

Am I just reading the data to the Serial Monitor only and not actually into the UNO?

I am more at a loss of the actual functions I need to be using to do what I want rather than actually figuring out the exact code.

I was under the impression that setting up an integer at the beginning of my code such as:

int dataIn = Serial.parseInt();

Then later printing that data to the LCD would do what I am wanting to do, but when I add this definition to my code at the top, the board slows down and is now reading in data one byte from the scale every few seconds, instead of once every say 50ms. It slows the UNO down, so I know I have done something wrong.

Once I read it from mySerial, what do I do with the information?

None of the information I have found is real specific on exactly HOW the UNO handles information. Sure, there's a million tutorials on LED lighting, and setting up an LCD to display what a user types into the Serial Monitor, but very few that are understandable for taking data IN, getting what you want from a string of data, then printing to an LCD that data.

Here is a copy of the scale manual that displays how it sends the data out. It's the same as the PDF file I posted with my OP, my home computer scanner was being a putz last night.

In my OP, the window that shows the Serial Monitor is the data as the UNO sees it from the scale, it matches what the manual says it's outputting. I do not believe there is any decimal point, my scale reads in pounds form 0-5000#.

This:

 if (mySerial.available()) {
    Serial.write(mySerial.read());

Reads data from one serial port and immediately sends it to another. So it came from the scale and went to your PC. The Uno just passes it on and as far as it is concerned, it's gone.

You need to read the data into a local buffer and parse the data out of it there. You can echo it to serial too so you can see what you got.

With some outside help, they pointed me to the Arduino page that has the Serial to Display example. I adapted it to my code by switching Serial with mySerial because I am pulling data off of pins 6 and 7.

NOW I am receiving the data that I was looking at on my Serial Monitor on my LCD. So it's usable if I have to, I would just like now to know how to strip off the unnecessary parts of the data coming in and just display the weight information part of it.

Post the code you have now developed and someone will help you strip off the extraneous data.

// include the library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);



// Set a string to tell me which Tank I am using
String msg="<< Left Tank >> ";



#include <SoftwareSerial.h>

SoftwareSerial mySerial(6, 7); // RX, TX


void setup() {
// **********  put your setup code here, to run once:

Serial.begin(9600);

// set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  

 lcd.setCursor(0, 0);
// Display <<Left Tank>>
   lcd.println(msg);

//Set scale input rate
mySerial.begin(9600);

}

void loop() {
// put your main code here, to run repeatedly:
  

//Copied form SoftwareSerialExample AND Serial To Display examples form the Arduino Forum

  if (mySerial.available()) {

// wait a bit for the entire message to arrive
    delay(150);

    lcd.setCursor(0,1); 
// read all the available characters
    while (mySerial.available() > 0) {
// display each character to the LCD
      lcd.write(mySerial.read());
    }
  }
}

Here is a copy of my code.

Here is an image of what my display is actually showing me:

The exact same data as what I was seeing yesterday through the serial monitor in my earlier attempt at this code.

It is giving me the entire data string from the scale head.

It would be great to strip off the ST, the GS, the + sign, some of the spaces and have the ability to add a space between the scale data and LB and/or add an LBS of my own to the display line. Not mandatory, but would be nice.

It would also be nice (but not really necessary) to echo the data, either raw or just the parts I want on the Serial Monitor.

As things are right now, I CAN use this enough to get me through the planting season, I just want it to look a little nicer.

Thanks for any help!

As reference:
string - Arduino Reference

You just need a char array[18] and as you read the char by char from the scale, increment an integer pointer and stuff that char into the array element. When you hit CR (ASCII 13) just send S3 and Data and S4 to display.

for (int iPoint =6, iPoint < 16, iPoint++)
{
LCD.write( array[iPoint]) ;
}

When you read a LF from scale, reset the array pointer to 0, and do it all again. You will need to add display positioning, clear, etc.

I think that should be [19] because of the null terminator. Or did I count wrong?

As we are stuffing the array character-by-character and inspecting received character as we go,

Depending on our CR/LF test logic, those 2 chars really do not need stuffing, but I sized it to accommodate testing LF after stuffing so that the array pointer could be reset to 0.

A way to test for both CR/LF before stuffing:


  if (Serial1.available())
  {
    char c = Serial1.read() ;
    if (c)                            // non-Null character
    {
      // if ( c == 10 ) c = 13 ;      // translate LF to CR and implement as CR+LF
      if( c > 31 && c < 127)          // keep non-printables off LCD
      {
        if ( c == cWatchChar )

Full code:
The QBF - "The Quick Brown Fox..." For Serial Diags - Community / Exhibition / Gallery - Arduino Forum

Is this any closer??

It compiles without error, and I will check it in the morning to see what happens.
What I am trying to do (if I understood what you were referring to) is define the array, then start at point 6.

At point 6, grab the data from that point in the array and make it the int "weighChar".
Then write "weighChar" to the LCD starting at point 0,1.
It is supposed to then move the cursor over one digit on the display.
It's supposed to loop until it reaches point 16 of the data stream.

I of course am more concerned on how I handled the array and printed each character vs getting the display cursor location correct.

// include the library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);



// Set a string to tell me which Tank I am using
String msg = "<< Left Tank >> ";




#include <SoftwareSerial.h>

SoftwareSerial mySerial(6, 7); // RX, TX

int strIng[18];     //Initializes an 18 character array
int i;              //the counter for the Array
int weighChar;      //the temporary data of the string
int c;              //LCD display cursor mover


void setup() {
  // **********  put your setup code here, to run once:

  Serial.begin(9600);

  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);


  lcd.setCursor(0, 0);
  // Display <<Left Tank>>
  lcd.println(msg);

  //Set scale input rate
  mySerial.begin(9600);


}

void loop() {
  // put your main code here, to run repeatedly:
  
  c=0;
  lcd.setCursor(c, 1);
  
  if (mySerial.available()) {

    // wait a bit for the entire message to arrive
    delay(150);

    // read all the available characters
    while (mySerial.available() > 0) {

      for (int i = 6; i < 16; i++) {
      strIng[i] = weighChar;  //makes my weigh character the next data point in the array
      lcd.write(weighChar);   //writes the data point of the array to LCD
      lcd.setCursor(0,c+1);   //moves the cursor over 1
      }
    }
  }
}

@fingers77

Do you want see something as follows on the Serial Monitor/LCD?

Output on LCD

Received Weight: 
13 lbs

Output on Serial Monitor

Received Weight: 13 lbs
Received Weight: 13 lbs

Then the following is the receiver sketch (tested on UNO using MEGA as simulator) to see output on Serial Monitor and LCD:

#include<SoftwareSerial.h>
#include<LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
SoftwareSerial mySerial(6, 7); //SRX = 6, STX = 7
char myData[20] = {0};
int wt;

void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
  lcd.begin();
  lcd.backlight(); //Light at the back of LCD is ON
}

void loop()
{
  byte n = mySerial.available();
  if (n != 0 )
  {
    byte m = mySerial.readBytesUntil('\r', myData, 20);
    myData[m] = '\0';
    wt = strtoul(myData + 8, NULL, 10);
    //---------------------
    showSM();  //show weight on Serial Monitor
    showLcd();  //show weight on LCD
  }
}

void showSM()
{
  Serial.print("Received Weight: ");
  Serial.print(wt);
  Serial.print(' ');
  Serial.println("lbs");
}

void showLcd()
{
  lcd.setCursor(0, 0); //DP0 position of Top Line
  lcd.print("Received Weight:");
  lcd.setCursor(0, 1);
  lcd.print(wt);
  lcd.print(" lbs");
}

Simulator Sketch:

char myData[] =
{
  'S', 'T', ',', 'G', 'S', '+', '0', '0', '0', 
  '0', '1', '3', ' ', 'l', 'b', '\r', '\n', '\0'
};

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop()
{
  Serial1.print(myData);
  Serial.println(myData);
  delay(1000);
}

Thanks for the code!!

I was able to make the LCD definitions fit my LCD and it's doing EXACTLY what I was hoping for!!

Thanks to all that helped.

Now I have to figure out exactly HOW your code works vs what I was trying to do. I think I was on the right track after it was suggested yesterday using an array, I just failed in implementation.

1 Like

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