Sorry, i am useless at software things, i'm a mechanical type of guy, i'm learning to TIG weld atm and i have picked that up way easier than i learnt a tiny portion of how to use the dreaded Strings with the Arduino.
So, it's a data stream of text? (would that be a packet of data?) separated by commas, so CSV's.
What happens is:
A bus simulator game is running on the PC, and a communications interface runs also on the same pc which reads variables in the game and sends them out over the serial ports at a fixed speed of 115200,
Then arduino's receive and use the data in the streams / packets.
Unfortunately, the person who wrote the communications interface has moved onto other things, so the issues with it are stuck, like data stream 5 isnt even active, there's no terminator on stream 3, that text ''noch nicht mit leben gefüllt'' is German for 'not yet filled with life' and is supposed to be where the bus interior temperature would go and so on.
There are a total of 5 'data streams' on 5 (usb) serial ports (4 working)
The one i'm interested in is for the IBIS lcd (IBIS = 'Integrated Bus Information System' it runs the passenger info displays, makes announcements, monitors if running late etc)
That stream or packet is plain text, and unfortunately it does not have any terminator character at all, things like \r, \n, do nothing, there's no special terminator character like there is on some of the other data streams.
There is a very clunky way of changing that text in the last string to a ';' but it needs doing every time the bus sim is started, involves using the task manager and is a royal pain in the ass, not something i want to do when i am building a replic bus drivers cab, and want to press a button that starts the pc up, hides windows and loads straight into the simulator with the communications program running and arduino's working.
The one good this is that data is on com3 i set to be 'refreshed' every 200 milliseconds (that is the one variable that can be changed easily)
The arduino reads this data stream, then separates it into 'strings' where the commas are,
These strings are then used to write text in certain places on the lcd.
For my use i only need the 6th and 7th string, so for this, one 'packet' of data that would be :
1,76,2,0,15:23,- 8.3,E.-dorf Krkhaus @076 02 107 24 B ,24,107,1,Krankenhaus,noch nicht mit leben gefüllt
I just need to read and use '- 8.3' and 'E.-dorf Krkhaus @076 02 107 24 B'
That data will change as the next bus stop name changes and the delay time changes, or other things are shown on the IBIS lcd, like setting it up.
Here's my code i use atm, i need all the comments in it to help me figure out what's going on, i may have some functions commented wrong, and i know Strings are bad, but i want to get this code working properly before working on better methods of doing this, and try to learn was i go, and if i write the code i can hopefully change it myself if requirements change.
/* Text to use with serial monitor to test , a typical output from the 'IBIS' com port with everything set up on the IBIS:
* 1,76,1,0,14:36,- 4.2,E.-dorf Krkhaus @076 01 105 6 A ,6,105,0,Krankenhaus,noch nicht mit leben gefüllt,
*
* Output when bus electricity is off, and hence IBIS display is blank / off:
* 1,0,0,0,12:45,.,,0,0,-1,,noch nicht mit leben gefüllt,
*
* I plan on checking for empty 'strings' later, as an empty 'delay' string currently prints weird characters on the LCD.
* And turning the bus electric off leaves the last text on the LCD instead of clearing it */
#include <LiquidCrystal.h> // use lcd library
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // lcd pins
String inputString = ""; // string to hold incoming csv's
String split_lines = ""; // string to hold data for splitting the lines on lcd
boolean stringComplete = false; // is the string complete, at this point - no?
// Set up string index, comments are What the individual strings mean
String text1; // '1' Delay yes / no
String text2; // '76' Bus line number - 3 digits
String text3; // '1' Route
String text4; // '0' Bus stop index
String text5; // '14:36' Time
String text6; // '- 4.2' Delay in minutes and 10ths of a minute, '-xx.x' is early, '+xx.x' is late, ' 0.0' is on time
String text7; // 'E.-dorf Krkhaus @076 01 105 6 A ' Bus stop name, i have changed this with a bodge in Komsi to output 'IBIS lcd contents' 2 lines seperated by @
String text8; // '6' Zone
String text9; // '105' Destination
String text10; // '0' Direction (0 = A, 1 = B, -1 = not set)
String text11; // 'Krankenhaus' Line number - upto 5 digits, another bodge in komsi makes this 'interior display text'
String text12; // 'noch nicht mit leben gefüllt' Interior temp, not working so it displays that text, translated from German = 'not yet filled with life'
void setup() {
Serial.begin(115200); // start serial coms at the speed indicated
inputString.reserve(200); // reserve 200 bytes for data in string
lcd.begin(24, 2); // start using lcd, set lcd paramiters, number of colums, rows.
}
void loop() {
if (stringComplete) { // run the following code
String split = inputString; // split up the line of text from serial data stream
text6 = getValue(split, ',', 5); // get data between commas from string 6, which is for delay
text7 = getValue(split, ',', 6); // get data between commas from string 7, which i've set to IBIS screen contents
inputString = ""; // place to store string data
stringComplete = false; // string is still not yet complete
String line1, line2; //String for IBIS text to be split in 2 lines {
split_lines = text7; // Split off the ibis text line
int a = split_lines.indexOf('@'); // Seperator character for the 2 lines
if (a >= 0) { // If text in the buffer, split it
line1 = split_lines.substring(0, a); // substring for line1, text befoer the @
line2 = split_lines.substring(a + 1); // substring for line2, text after the @
}
// start printing text to the LCD
lcd.setCursor(0, 0); // Sets cursor on the LCD, column, row.
lcd.print(line1); // Displays the first line of text
lcd.setCursor(0, 1);
lcd.print(line2); // Displays last line of text
lcd.setCursor(21, 0); // move cursor here, print the delay -, or + symbol above the numbers as on the real IBIS.
lcd.print(text6.charAt(0)); // print the +, -, or nothing, for running late, running early, on time.
lcd.setCursor(20, 1); //bottom row, 21st column
lcd.print(text6.charAt(1)); // first number of delay time, 10's of minutes
lcd.setCursor(21, 1);
lcd.print(text6.charAt(2)); // 2nd number, 1's of minutes
lcd.setCursor(22, 1);
lcd.print(text6.charAt(3)); // 3rd number.. actually a dot.
lcd.setCursor(23, 1);
lcd.print(text6.charAt(4)); // final number, tenths of a minute, i.e. 0 to 60 seconds but shown with with numbers 0 to 9... metric time?!
// i know i could do the above an easier way, something about read everything from the 1st character to the end of that string?
}
}
void serialEvent() {
while (Serial.available()) { // Only do things when serial is active
char inChar = (char)Serial.read(); //read the serial on charecter at a time?
inputString += inChar; // Add the characters together to make the stirng?
if (inChar == ';') { //new line charecter, if seen means string is complete.. dosent exist on this data stream, so i clunkilly change it to ';' every time i start the bus sim, i want to avoid this.
stringComplete = true; // Tells the first bit of code in loop to process the data now
}
}
}
String getValue(String data, char separator, int index) // stuff for splitting strings for the index and that?.
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length() - 1; // not sure
for (int i = 0; i <= maxIndex && found <= index; i++) {
if (data.charAt(i) == separator || i == maxIndex) {
found++;
strIndex[0] = strIndex[1] + 1;
strIndex[1] = (i == maxIndex) ? i + 1 : i;
}
}
return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}