I have a pc controller at my work that is outputting about 30 hexadecimal bytes repeatedly with the first 9 bytes being control info and the latter being 19 bytes for a message and an end byte for another control character. I need to output those 19 message bytes to a LED marquee, but it also has to be structured to display with the marquee. I'm in my initial research stages but it looks like i'm looking at an Arduino Mega for multiple TX RX inputs/outputs and the TTL to RS232 converters to get me from 12v pc voltage to 5v. And then, just some modified c programming to the Arduino. Am I on the right track here. Will I be able to read that serial port and store the 30 bytes in some kind of byte array and then read what I need and append a few control characters and address for use with a LED Marquee? Any recommended reading will be helpful.
Seems workable. You should figure out the level shifting specs and schematic before you hook anything to 12v.
Maybe take a look at:
information needed:
-
What protocol does the LED marquee expect (e.g., serial communication, TCP/IP)?
-
Does the marquee need special control characters for message boundaries? Are there any specific formatting rules or requirements for the message structure?
-
To address your issue, it sounds like you need to extract the relevant message bytes from the controller’s output and reformat them for display on an LED marquee.
Here's a general approach that you can take:
Steps:
Extract the Message Bytes:
The first 9 bytes are control information, and you entioned that the last 19 bytes represent the message plus an end byte.
Extract the 19 bytes from the message portion of the hexadecimal output.
Format the Message for the Marquee:
Depending on the marquee, it could require certain formatting (e.g., scrolling text, specific spacing, or encoding).
Ensure that the message bytes are encoded properly for the LED display (usually this involves converting from hex to ASCII or another readable format).
Integrate Control Characters:
If the LED marquee needs certain control characters (e.g., start of message, end of message, new line, etc.), those characters must be added accordingly.
You may need to append or prepend these control characters as specified by your LED marquee documentation.
**Output to the LED Marquee:**
Send the formatted message to the LED marquee, making sure the communication interface (likely a serial or TCP/IP connection) is correctly set up.
Spot on. My marquee wants the 02 (STX), an address "01", the message, and then 03 (ETX). Funny thing was whether in Hexadecimal or ASCII DEC, STX and ETX seem to be the same binary output & numbers so I was hoping to be able to send the message HEX back out to marquee with the control characters appended. Marquee tech documentation was using ASCII DECIMAL though. I am completely new to the programming the arduino side. I have bought the beginners guide, an arduino mega, and a couple TTL to RS232 conversion chips. If I can figure out the programming to read the next 19 hex characters after "1B" or store all 30 hex characters in maybe a byte array and pluck out the ones i need and then append, then hopefully output wouldn't be too difficult. SAMPLE: 04 0A 30 31 04 18 04 09 1B 45 4E 54 45 52 20 4E 45 57 20 4D 4F 44 45 20 20 20 20 20 20 20 12
First 9 always repeat. And message is padded with spaces. Still wonder how arduino would know when to start reading the full 30 bytes though. Hope I figure it out. (Baud rate =1200)
Check out this link, it should show way you are seeing what you are. https://www.asciitable.com/
Did you check out:
Reading a byte 0x12 ( Form Feed/ New Page) as the end of record, an then you reset to fill up a new message.
Or better -- treat 0x04 (EOT) as the end of message, and ignore the messages that don't start with 0x09.
Getting ready to start hooking up and creating sketches to upload. How does this look?
byte msg[29]; //byte array to store hexadecimal values not including ending control character 0x12
void setup() {
Serial0.begin(1200); // opens input serial port, sets data rate to 1200 bps
Serial1.begin(1200); // opens output serial port
delay(100);
}
void loop() {
if (Serial0.available() > 0) { // check if data is available
Serial0.readBytesUntil('0x12', msg, 29);
}
Serial1.print(2, DEC); //STX
Serial1.print(48, DEC); //"0" addressing for LCD Marquee
Serial1.print(49, DEC); //"1" addressing for LCD Marquee
Serial1.print(msg[10], DEC); //from Array position 10-29
Serial1.print(msg[11], DEC);
Serial1.print(msg[12], DEC);
Serial1.print(msg[13], DEC);
Serial1.print(msg[14], DEC);
Serial1.print(msg[15], DEC);
Serial1.print(msg[16], DEC);
Serial1.print(msg[17], DEC);
Serial1.print(msg[18], DEC);
Serial1.print(msg[19], DEC);
Serial1.print(msg[20], DEC);
Serial1.print(msg[21], DEC);
Serial1.print(msg[22], DEC);
Serial1.print(msg[23], DEC);
Serial1.print(msg[24], DEC);
Serial1.print(msg[25], DEC);
Serial1.print(msg[26], DEC);
Serial1.print(msg[27], DEC);
Serial1.print(msg[28], DEC);
Serial1.print(msg[29], DEC);
Serial1.print(3, DEC);
}
Hi @eperic,
please use the code tags (from the menue bar of the editor window):
It makes reading and handling of code much easier in the forum, see here:
byte msg[29]; //byte array to store hexadecimal values not including ending control character 0x12
void setup() {
Serial0.begin(1200); // opens input serial port, sets data rate to 1200 bps
Serial1.begin(1200); // opens output serial port
delay(100);
}
void loop() {
if (Serial0.available() > 0) { // check if data is available
Serial0.readBytesUntil('0x12', msg, 29);
}
Serial1.print(2, DEC); //STX
Serial1.print(48, DEC); //"0" addressing for LCD Marquee
Serial1.print(49, DEC); //"1" addressing for LCD Marquee
Serial1.print(msg[10], DEC); //from Array position 10-29
Serial1.print(msg[11], DEC);
Serial1.print(msg[12], DEC);
Serial1.print(msg[13], DEC);
Serial1.print(msg[14], DEC);
Serial1.print(msg[15], DEC);
Serial1.print(msg[16], DEC);
Serial1.print(msg[17], DEC);
Serial1.print(msg[18], DEC);
Serial1.print(msg[19], DEC);
Serial1.print(msg[20], DEC);
Serial1.print(msg[21], DEC);
Serial1.print(msg[22], DEC);
Serial1.print(msg[23], DEC);
Serial1.print(msg[24], DEC);
Serial1.print(msg[25], DEC);
Serial1.print(msg[26], DEC);
Serial1.print(msg[27], DEC);
Serial1.print(msg[28], DEC);
Serial1.print(msg[29], DEC);
Serial1.print(3, DEC);
}
I guess you did not try to compile your code for a MEGA ... ?!
- There is not Serial0 device, the MEGA has
- Serial
- Serial1
- Serial2 and
- Serial3
As Serial is connected to the USB which is used for uploads of code and (probably helpful) for debugging purposes you might choose one of the other serial ports for your purposes.
- As you know how many bytes the PC controller sends you could use the number of bytes read to make sure that you only write information to Serial1 if you have a complete message:
Serial.readBytesUntil()
returns the number of characters read into the buffer. A 0 means that thelength
parameter <= 0, a time out occurred before any other input, or a termination character was found before any other input.
- To send the data from msg[10] to msg[29] you could use a for loop instead of one line per byte:
for (int i=10;i<=29;i++){
Serial1.print(msg[i],DEC);
}
- Remove the single quote ' from
Seria02.readBytesUntil('0x12', msg, 29);
as '0x12' is not the same as 0x12 (Hex 12 = Dec 18) and you want to read until the value 0x12 or decimal 18 appears. (And change from Serial0 to Serial2 or Serial3 of course)
Hope it helps
ec2021
P.S.:
You supplied the following example (here with the array index in the top line):
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
04 0A 30 31 04 18 04 09 1B 45 4E 54 45 52 20 4E 45 57 20 4D 4F 44 45 20 20 20 20 20 20 20 12
If this is what you receive there are 30 characters (0 ... 29) before the delimiter 0x12. And as you are already addressing msg[29] your array must have a size of 30 bytes.
Here is a sketch that may show a possibility to handle messages of known length between a start and a stop character:
https://wokwi.com/projects/409852867075662849
Sketch:
/*
Forum: https://forum.arduino.cc/t/reading-hex-binary-from-pc-serial-then-output/1302803/9
Wokwi: https://wokwi.com/projects/409852867075662849
Copy one of the following lines to Serial input and press return to test the routines:
01234567890123456789<#This part is okay #>
Test<- This part is okay->EndOfTest
01234567890123456789<A01234567890123456GFGFGF>
01234567890123456789<This part is okay !!>01234567890123456789<A01234567890123456GFGFGF>
Be aware that < and > are used as START and STOPCHARACTER.
There must be exactly messageLen characters between these brackets to be considered a valid
message.
*/
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
const byte STARTCHARACTER = '<'; // Replace by 0x1B
const byte STOPCHARACTER = '>'; // Replace by 0x12
const byte bufferLen = 21; // Allows to read more than the message length to detect length errors
const byte messageLen = 20; // This is the length of a valid message
byte msg[bufferLen]; //byte array to store values not including the STOPCHARACTER
int bytesRead = 0; // Counts the numbers of bytes read
boolean msgBegin = false; // Becomes true if STARTCHARACTER was recveived
boolean msgFound = false; // Becomes true if a valid message was found
// means: messageLen characters between START- and STOPCHARACTER
boolean error = false; // Becomes true if more or less that messageLen characters were received
// between START- and STOPCHARACTER
void setup() {
setupLCD();
Serial.begin(115200); // opens input serial port, sets data rate to 1115200 bps
Serial.println("Start");
}
void loop() {
if (Serial.available() > 0) { // check if data is available
byte aChar = Serial.read();
if (aChar == STOPCHARACTER) {
msgBegin = false;
msgFound = (bytesRead == messageLen);
error = !msgFound;
bytesRead = 0;
}
if (msgBegin && bytesRead < bufferLen) {
msg[bytesRead] = aChar;
bytesRead++;
}
if (aChar == STARTCHARACTER) {
msgBegin = true;
bytesRead = 0;
}
}
if (msgFound) {
writeToLCD();
msgFound = false;
}
if (error) {
Serial.println("Wrong message length");
error = false;
}
}
void setupLCD() {
lcd.init();
lcd.backlight();
}
void writeToLCD() {
Serial.println("Message found!");
lcd.clear();
lcd.print("STX");
lcd.print("0");
lcd.print("1");
lcd.setCursor(0, 1);
for (int i = 0; i < messageLen; i++) {
lcd.print(char(msg[i]));
}
lcd.setCursor(0, 2);
lcd.print("ETX");
}
It's far from perfect but shows some principles you could use.
There are some test strings in the header which you can copy and input in the Serial input line of Wokwi for testing.
Good luck!
Thank you ec2021, the code you posted, or wrote for me, was invaluable! I extrapolated so much info from just that alone. I had problems getting the msgFound to become true which led me down a simpler path of just finding the start character and reading it and the next 20 bytes in and then writing them to the serial port sans the start byte of course. For some reason Serial.print would not work but Serial.write did the trick. Also, Serial.write doesn't like to convert byte array into DEC (decimal) for some reason (compiler error). The Serial.write with Hexadecimal uses the same binary output as DEC so Marquee understood it just fine. Last problem was the variable I was using to make the msgFound true, I never reset it so the Arduino was just kept loop blasting the same message to the marquee until a new message came. Poor Marquee. It tried its best to keep up, but it got glitchy. Found that I just needed to reset my bytesRead counter before next loop otherwise it remained true. Thanks for all the help, everyone. Prototype is up and running and it this Arduino business has made coding and electrical building fun and easy!
Keep in mind that all data and communications are binary.
Serial.write() does not interpret any of the binary data bytes that it transmits.
Serial.print() is a vastly different function, which usually does interpret data bytes, as well as performing data representation conversions, like binary to hex or decimal ASCII representation.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.