Help figuring out what is going on in a sketch, and how to add things to it

Click here to show a long text explaining the background to my project

I'm connecting real vehicle (German MAN NG272 bus) parts like a dashboard, ticket machine, next stop displays etc to a computer that is running a simulator / game called Omsi 2, which is a bus driving simulator (naturally :slight_smile:

The game has a plugins folder where you place a .dll and a .opl file,
the .dll runs when the game is started and requests data then sends it as a text string via the com port to the arduino, which has connected to it led's, gauges, LCD's etc.

So when a dashboard light turns on or off in the game, the the led / light bulb in the real dashboard does the same, or text that is shown on a ticket printer screen in game is sent to the arduino to display on an LCD in the real ticket machine.

.

The .dll / plugin has to be written by people who want to use this feature, and in the past people have done this, but when ever a new piece of data wants reading the writer of the .dll needs to make changes and re-compile it, along with updating the arduino sketch and the entry in the .opl file.

The .opl file is just a text file that has a list of the names of the data names you want to read.

This means that when people move onto other things and give up on their plugin, we are not able to update things when new data is needed....
usually due to a new bus or map being released for the main game that uses a different name for the function to turn lights on and off etc.

.

A few weeks ago i discovered someone has written a plugin .dll (called Bus Board Interface 2) where he's uploaded the source code to git hub (so if i knew enough about programming i could change it to suit my needs)

But that is not needed so much because he has written it in such a way that it can sort of auto update itself, by reading any new entries you put in the .opl file (and change the arduino code to suit)

The git hub page is here if you want to read it:
https://github.com/Anonim17PL/BBI2

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Can someone have a look through an arduino sketch and help me figure out what is happening in it better please?

The sketch makes the arduino listen to the com port, and when a bus driving simulator game is running it reads text strings sent from the game when a value you want to read changes,
The arduino then reads the text from the string to turn led's on and off, display text on lcd's etc,
and it can also send data from the arduino to the game for switch inputs etc.

The sketch is provided with the .dll that reads out the data from the game, and it's sort of a starter sketch we are to build on to suit our needs.

I got the sketch from : GitHub - Anonim17PL/BBI2: Bus Board Interface 2 (Threaded Edition) for OMSI 2

I've figured out how to add extra triggers to send simple button presses to the game, and how to add more outputs for turning led's on and off,

I'd like to add an LCD to display the text data that comes in the string '$V:0:' amongst other things,

But before i do that, i want to better understand what is going on throughout the sketch, i am very bad at programming / coding, but trying to learn (memory issues do not help me here)

The sketch had zero comments when i got it, so all comment's in the sketch i've added myself to try and figure it out, so i have likely got things very wrong.

I also know that strings and arduino's do not play together well, so i want to switch over to using something like SafeStrings once i know what's going on.

The sketch... all the LCD stuff i added, but i got stuck with where to add the 'LCD.print' functions

// LCD setup stuff
const byte cols = 40;    // columns/characters per row
const byte rows = 2;     // how many rows
const byte addr = 0x25;  // set the LCD address to 0x3F or 0x27

#include <NoiascaLiquidCrystal.h>  // use the adopted library downloaded from https://werner.rothschopf.net/202003_arduino_liquid_crystal_umlaute.htm
#include <NoiascaHW/lcd_i2c.h>     // include the proper IO interface

LiquidCrystal_I2C_Special lcd(addr, cols, rows);  // prints Ä Ö Ü, also activate lcd.createUml() in setup!
// End LCD setup stuff

float varlist[10];
bool prevtriglist[10];
unsigned long buff1;
unsigned long buff2;
float floatroz;

void setup() {
  //LCD setup
  Wire.begin();                         // start I2C library
  lcd.begin();                          // initialize the LCD
  lcd.createUml();                      // needed for LiquidCrystal_I2C_Special only - custom characters 5, 6, 7 used for Ä Ö Ü
  lcd.backlight();                      // turn on backlight
  lcd.setCursor(0, 0);                  // Position cursor top left
  lcd.print(F("testing 1..2...3..."));  // Print text just to show LCD is working
  // End LCD setup

  Serial.begin(74800);  // Start serial coms
  Serial.setTimeout(25);

  // Set up pins
  //    Lights
  pinMode(2, OUTPUT);   // Indicators
  pinMode(3, OUTPUT);   // Middle / Rear Door Open
  pinMode(4, OUTPUT);   // Rear Door Open (bendy Bus)
  pinMode(5, OUTPUT);   // Stop Req 1
  pinMode(6, OUTPUT);   // Stop req 2
  pinMode(7, OUTPUT);   // High Beam light
  pinMode(8, OUTPUT);   // Battery / No Charge
  pinMode(9, OUTPUT);   // Low air / Master Failure
  pinMode(10, OUTPUT);  // Parking Brake
  pinMode(11, OUTPUT);  // Kneeling

  //    Switches
  pinMode(22, INPUT_PULLUP);  // Station Brake
  pinMode(23, INPUT_PULLUP);  // Door 0
  pinMode(24, INPUT_PULLUP);  // Door 1
  pinMode(25, INPUT_PULLUP);  // High Beam
  pinMode(26, INPUT_PULLUP);  // Kinderwagen Sw
  pinMode(27, INPUT_PULLUP);  // Horn 1
  pinMode(28, INPUT_PULLUP);  // Horn 2
  // End of set up pins

  delay(1000);              // Wait 1 second
  Serial.write("REFRESH");  // Write to serial
  readstr();                // Read initial strings?
}


void sendrequest() {  // Not sure
  //Serial.print("SL:0");
}

void loop() {

  unsigned long currentMillis = millis();  // Millisecond timer

  if (currentMillis - buff1 > 2000) {  // 2 second timeout, seems to go back to send on change if a switch is held down
    buff1 = currentMillis;
    sendrequest();
  }

  while (Serial.available() > 0) {  // Do stuff only when serial stream detected?
    readstr();                      // Read the incoming strings
  }

  //  Read varlist in .opl file, turn relevent led on or off for matching item
  analogWrite(2, varlist[0] * 255);   // Indicators
  analogWrite(3, varlist[1] * 255);   // Middle / Rear door open
  analogWrite(4, varlist[2] * 255);   // Rear Door Open (Bendy Bus)
  analogWrite(5, varlist[3] * 255);   // Stop Req 1
  analogWrite(6, varlist[4] * 255);   // Stop Req 2
  analogWrite(7, varlist[5] * 255);   // High Beam Light
  analogWrite(8, varlist[6] * 255);   // Battery / No Charge
  analogWrite(9, varlist[7] * 255);   // Low Air / Master Failure
  analogWrite(10, varlist[8] * 255);  // Parking Brake
  analogWrite(11, varlist[9] * 255);  // Kneeling

  if (currentMillis - buff2 > 500) {  // 1/2 second timeout, to allow sent data to stabilise perhaps?
    buff2 = currentMillis;
    sendfloatauto();  // Send position of potentiometer on A1, changes position of heater blower speed knob
  }

  //      Buttons / Switches:
  // Station brake
  if (prevtriglist[0] != !digitalRead(22)) {  // Check if data has changed for this trigger
    prevtriglist[0] = !digitalRead(22);       // If data has changed...
    sendtrig(0, prevtriglist[0]);             // ....Send new data for this trigger
  }
  // Door 0
  if (prevtriglist[1] != !digitalRead(23)) {
    prevtriglist[1] = !digitalRead(23);
    sendtrig(1, prevtriglist[1]);
  }
  // Door 1
  if (prevtriglist[2] != !digitalRead(24)) {
    prevtriglist[2] = !digitalRead(24);
    //sendtrig(2,1);
    //delay(60);
    //sendtrig(2,0);
    sendtrig(2, prevtriglist[2]);
  }
  // High Beam
  if (prevtriglist[3] != !digitalRead(25)) {
    prevtriglist[3] = !digitalRead(25);
    sendtrig(3, prevtriglist[3]);
  }
  // Kinderwagen Switch
  if (prevtriglist[4] != !digitalRead(26)) {
    prevtriglist[4] = !digitalRead(26);
    sendtrig(4, prevtriglist[4]);
  }
  // Horn
  if (prevtriglist[5] != !digitalRead(27)) {
    prevtriglist[5] = !digitalRead(27);
    sendtrig(5, prevtriglist[5]);
  }
  //
  if (prevtriglist[6] != !digitalRead(28)) {
    prevtriglist[6] = !digitalRead(28);
    sendtrig(6, prevtriglist[6]);
  }
}

void readstr() {
  String string1 = Serial.readStringUntil('\n');                   // Not sure, is this splitting the strings up to read them??
  if (string1.substring(0, 2) == "LV") {                           // If string starts with LV...
    int varpos = string1.indexOf(":", 3);                          // Move to the 3rd item in the string?
    int varindex = atoi(string1.substring(3, varpos).c_str());     // Convert string to integer (i think)
    float varstate = atof(string1.substring(varpos + 1).c_str());  // Converts integer to float value
    varlist[varindex] = varstate;                                  // adds the float value to the correct varlist item?
  }

  if (string1.substring(0, 2) == "SV") {  // If substring starts with SV, read it
    int varpos = string1.indexOf(":", 3);
    int varindex = atoi(string1.substring(3, varpos).c_str());
    float varstate = atof(string1.substring(varpos + 1).c_str());
    if (varindex == 0) {  // turning onboard led on and off... not sure why, it just stays on.
      if (varstate == 1) {
        digitalWrite(13, HIGH);
      } else {
        digitalWrite(13, LOW);
      }
    }
  }
}

void sendtrig(int index, float var) {                       // When button pressed, send the string
  Serial.print("TV:" + String(index) + ":" + String(var));  // I think this is the bit sending the data as a string
}

void sendvar(int index, float var) {
  Serial.print("LV:" + String(index) + ":" + String(var));
}

void sendfloatauto() {
  float temp = analogRead(A0);  // Read potentiometer on A0
  temp = temp / 1024;
  temp = min(temp, 0.99);
  if (abs(temp - floatroz) > 0.05) {
    floatroz = temp;
    sendvar(10, temp);  // Send heater fan speed knob position data to Omsi
  }
}

sounds like some sort of SimHub

very unprofessional
better:
digitalWrite(2, varlist[0]);

I have updated the comments for the readstr() function to better reflect what it is doing.
This is also where you want to put your lcd.prints. I would print "string1, varindex and varstate".

void readstr() {
  String string1 = Serial.readStringUntil('\n');                   // Read String from Serial store it in string1
  if (string1.substring(0, 2) == "LV") {                           // If string starts with LV...
    int varpos = string1.indexOf(":", 3);                          // Move to the 3rd item in the string
    int varindex = atoi(string1.substring(3, varpos).c_str());     // and read 3 char's. convert to int. this is the index data.
    float varstate = atof(string1.substring(varpos + 1).c_str());  // read the remaining char's. convert to float. this is the state data
    varlist[varindex] = varstate;                                  // go to indexed position of varlist and store the state data there.
  }
1 Like

i see

// LCD setup stuff
const byte cols = 40;    // columns/characters per row
const byte rows = 2;     // how many rows
const byte addr = 0x25;  // set the LCD address to 0x3F or 0x27

#include <NoiascaLiquidCrystal.h>  // use the adopted library downloaded from https://werner.rothschopf.net/202003_arduino_liquid_crystal_umlaute.htm
#include <NoiascaHW/lcd_i2c.h>     // include the proper IO interface

LiquidCrystal_I2C_Special lcd(addr, cols, rows);  // prints Ä Ö Ü, also activate lcd.createUml() in setup!
// End LCD setup stuff
const byte Ten = 10;
byte varlist[Ten];
uint16_t prevtriglist;                  // <-----  here was list of 10 triggers but we have only 7 switches, confusing... now it's storge for 16 triggers, if you need more use uint32_t
unsigned long buff1;
unsigned long buff2;
const byte lPin[Ten] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
const byte sPin[] = {22, 23, 24, 25, 26, 27, 28};

void setup() {
  //LCD setup
  Wire.begin();                         // start I2C library
  lcd.begin();                          // initialize the LCD
  lcd.createUml();                      // needed for LiquidCrystal_I2C_Special only - custom characters 5, 6, 7 used for Ä Ö Ü
  lcd.backlight();                      // turn on backlight
  lcd.setCursor(0, 0);                  // Position cursor top left
  lcd.print(F("testing 1..2...3..."));  // Print text just to show LCD is working
  // End LCD setup

  Serial.begin(74800);  // Start serial coms
  Serial.setTimeout(25);

  // Set up pins
  /*/    Lights
    pinMode(2, OUTPUT);   // Indicators
    pinMode(3, OUTPUT);   // Middle / Rear Door Open
    pinMode(4, OUTPUT);   // Rear Door Open (bendy Bus)
    pinMode(5, OUTPUT);   // Stop Req 1
    pinMode(6, OUTPUT);   // Stop req 2
    pinMode(7, OUTPUT);   // High Beam light
    pinMode(8, OUTPUT);   // Battery / No Charge
    pinMode(9, OUTPUT);   // Low air / Master Failure
    pinMode(10, OUTPUT);  // Parking Brake
    pinMode(11, OUTPUT);  // Kneeling

    //    Switches
    pinMode(22, INPUT_PULLUP);  // Station Brake
    pinMode(23, INPUT_PULLUP);  // Door 0
    pinMode(24, INPUT_PULLUP);  // Door 1
    pinMode(25, INPUT_PULLUP);  // High Beam
    pinMode(26, INPUT_PULLUP);  // Kinderwagen Sw
    pinMode(27, INPUT_PULLUP);  // Horn 1
    pinMode(28, INPUT_PULLUP);  // Horn 2
    // End of set up pins
  */
  for (byte i = 0; i < Ten; i++)pinMode(lPin[i], OUTPUT);
  for (byte i = 0; i < sizeof(sPin); i++)pinMode(sPin[i], INPUT_PULLUP);

  delay(1000);              // Wait 1 second
  Serial.write(F("REFRESH"));  // Write to serial
  Serial.readStringUntil('\n');
}

void sendrequest() {  // Not sure
  //Serial.print("SL:0");
}

void loop() {

  unsigned long currentMillis = millis();  // Millisecond timer

  //  if (currentMillis - buff1 > 2000) {  // 2 second timeout, seems to go back to send on change if a switch is held down
  //    buff1 = currentMillis;
  //    sendrequest();
  //  }

  if (currentMillis - buff2 > 500) {  // 1/2 second timeout, to allow sent data to stabilise perhaps?
    buff2 = currentMillis;
    sendfloatauto();  // Send position of potentiometer on A1, changes position of heater blower speed knob
  }

  while (Serial.available() > 0) {  // Do stuff only when serial stream detected?
    readstr();                      // Read the incoming stream
  }

  //  Read varlist in .opl file, turn relevent led on or off for matching item
  for (byte i = 0; i < Ten; i++)analogWrite(lPin[i], varlist[i]); // Indicators

  for (byte i = 0; i < sizeof(sPin); i++) {
    bool Tr = digitalRead(sPin[i]);
    if ((prevtriglist & 1 << i) == Tr) { // Check if data has changed for this trigger
      prevtriglist ^= 1 << i;   // If data has changed...
      sending('T', i, Tr);            // ....Send new data for this trigger
    }
  }
}

void readstr() {
  String string1 = Serial.readStringUntil(':');
  int var = Serial.parseInt();
  if (string1 == "SV" || string1 == "LV") {
    varlist[var] = min(255, int(Serial.parseFloat() * 255.0));
  }
  else if (string1 == "$V") {
    String str = Serial.readStringUntil('\n');
    lcd.setCursor(0, var);
    lcd.print(str);
  }
}

void sending(char c, int index, byte var) {
  Serial.print(c) ;
  Serial.print("V:");
  Serial.print(index) ;
  Serial.print(':');
  Serial.print((float)var / 255.0, 2);
  Serial.print('\n');
}

void sendfloatauto() {
  static int roz = 0;
  int temp = analogRead(A0);  // Read potentiometer on A0
  if (abs(temp - roz) > 51) {
    roz = temp;
    sending('L', 10, temp >> 2); // Send heater fan speed knob position data to Omsi
  }
}

UPD optimized now
UPD2 repaired now :sweat_smile:

I thought that at first,

But it is actually intentional, it is so the led's / bulbs brightness varies depending on the 'battery voltage' which is simulated in Omsi... the output numbers for the dashboard lights are not simply 0 or 1, but a value between 0 and 1, like 0.850 etc.

So when you press the starter button in the game, the dash lights on the real dashboard dim and flicker just like the do in the game, and in real life due to voltage drop,
and when the engine has started, the lights get brighter than they were before as the alternator charges the battery back up.

Only problem is i would run out of PWM outputs for all the dashboards lights with a mega, so one thing i want to look into later is using multiple arduino's on different com ports, one for just the dash lights, one for the guages, one for LCD's etc.

it is,

But SimHub does not support Omsi 2 very well and can get hardly any data out of it,
where as a plugin written in the way the writers of Omsi intended can access almost any data there is.

Tried to run that sketch but getting a couple of errors,

One on line 60 'Serial.write(F("REFRESH")); '

I changed that to 'Serial.print(F("REFRESH")); ' and the compiler is happy with that.

:

But it's complaining that on line 120 and 122, 'index' and 'var' was not declared in this scope.

Do these names need to be declared at the top of the sketch or something?

how was is compiled earlier?

ah, yes of course... :sweat_smile:
repaired now

Ahh, just noticed that,
I think it doesn't like the 'F' bit in 'Serial.write(F("REFRESH"));'

It is happy if i remove the '(F' and last bracket that goes with that,
or if i change 'write' to 'print' and keep the F.... which from what i remember makes the memory used for writing serial and LCD stuff use a different memory type.

:

... an answer to the comment in the sketch

I am playing with this on a breadboard for now, and i ran out of room with 7 switches :grimacing:

But also, the way the .dll is written, you can add more triggers, or read things like lights, gauges, text to display on LCD's etc,
it just reads from the '.opl file' (which is a simple text file) the names of the data calls, and you just tell the arduino sketch where on the lists they are.

The author claims says it can read :

But that would be rather hard to do with a single board... lots of port expanders / shift registers would be needed.

Here is my .opl file just to show what i mean when i mention it:

.OPL file text

[dll]
BBI2.dll

[varlist]
11
lights_blinkgeber
cockpit_light_tuerkontrolle
cockpit_light_tuerkontrolle_2
haltewunschlampe
haltewunschlampe_all
lights_fern
cockpit_light_batterie
cockpit_light_masterfailure
cockpit_light_feststellbremse
cockpit_light_kneeling
cp_klimator_sw

[triggers]
7
bus_dooraft
bus_doorfront1
bus_doorfront0
kw_fernlicht_toggle
cp_schalter_kinderwagen
horn
horn

[stringvarlist]
1
IBIS_cabindisplay

[systemvarlist]
1
Time

[BBI]
COMx=09
BAUD_RATE=74880

what room do you mean? pins?

important?

just room on the single breadboard,
When i get it working well and transfer it to my driving rig, i'll have about 40 switches / buttons, and about 50 or more bulbs / led's,
Plus at least 2 LCD's etc.

That's why i want to try and split the data between multiple arduino's... but that's an idea for later.

The baud rate? i don't think so, just needs to be fast enough to not miss inputs when a lot of things change at once i guess,
i've always used 115200 with my arduinos... no idea why i chose that number.

The guy who wrote the 'starter sketch' for BBI2 chose 74800,

:

Just tried your updated sketch, it's complaining about 'floatroz' not being declared,
i tried adding 'float floatroz;' at the top of the sketch, it compiled and loaded onto the arduino,

But it is sending :

23:21:38.355 -> TV:0:0.00
23:21:38.355 -> TV:1:0.00
23:21:38.355 -> TV:2:0.00
23:21:38.355 -> TV:3:0.00
23:21:38.355 -> TV:4:0.00
23:21:38.355 -> TV:5:0.00
23:21:38.355 -> TV:6:0.00

over and over as fast as it can, pressing buttons does not change any of the data and it's not reading any data from Omsi.

i mean both numbers, they are little different.

oh god... give me a sec...

try now
n-now

Doh! i didn't notice that, would have been me mistyping it, changed them both to 115200, a number i am used to typing :smiley:

:

The sketch compiled and ran (after removing that '(F...) bit from 'serial.write'

and i am getting text on the LCD :money_mouth_face:
there's a few problems tho.

The LCD... i see the code is just searching for '$V'
it needs to search for the variable index too like the other variables, as there can be more than 1 LCD, or thing that uses the '$V' bit .... which means 'string variables' i've just noticed on the BBI2 wiki:

BBI2 explanation of what is sent / received

If i type '$V:0:text' in the serial monitor, it displays ':text' on the lcd... i.e. including the : bit,
if i enter '$V:1:text2' it puts the text on the 2nd line of the LCD.

:

When sending TV's and LV's from the arduino, no newline is used it seems, so i commented out the 'Serial.print('\n');' at the bottom of the 'void.sending' code.

But either way It's only sending button zero, and it sends :
'TV:0:0.00TV:0:0.00',
the first TV bit is button down, and should be TV:0:1.00'
I can press the other buttons, they will send just once and only sending say : 'TV:2:0.00' the button down event, no button up event is sent and they stop responding.

:

And the led's... they turn on, but do not turn off until i reset the arduino.

no poblem at all, i will say it proves that it works

new one

// LCD setup stuff
const byte cols = 40;    // columns/characters per row
const byte rows = 2;     // how many rows
const byte addr = 0x25;  // set the LCD address to 0x3F or 0x27

#include <NoiascaLiquidCrystal.h>  // use the adopted library downloaded from https://werner.rothschopf.net/202003_arduino_liquid_crystal_umlaute.htm
#include <NoiascaHW/lcd_i2c.h>     // include the proper IO interface
LiquidCrystal_I2C_Special lcd(addr, cols, rows);  // prints Ä Ö Ü, also activate lcd.createUml() in setup!
// End LCD setup stuff
const byte Ten = 10;
byte varlist[Ten];
uint16_t prevtriglist;                  // <-----  here was list of 10 triggers but we have only 7 switches, confusing... now it's storge for 16 triggers, if you need more use uint32_t
unsigned long buff1;
unsigned long buff2;
const byte lPin[Ten] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
const byte sPin[] = {22, 23, 24, 25, 26, 27, 28};

void setup() {
  //LCD setup
    Wire.begin();                         // start I2C library
    lcd.begin();                          // initialize the LCD
    lcd.createUml();                      // needed for LiquidCrystal_I2C_Special only - custom characters 5, 6, 7 used for Ä Ö Ü
    lcd.backlight();                      // turn on backlight
    lcd.setCursor(0, 0);                  // Position cursor top left
    lcd.print(F("testing 1..2...3..."));  // Print text just to show LCD is working
  // End LCD setup

  Serial.begin(74800);  // Start serial coms
  Serial.setTimeout(25);

  // Set up pins
  for (byte i = 0; i < Ten; i++)pinMode(lPin[i], OUTPUT);
  for (byte i = 0; i < sizeof(sPin); i++)pinMode(sPin[i], INPUT_PULLUP);

  delay(1000);              // Wait 1 second
  Serial.print(F("REFRESH\n"));  // Write to serial
  Serial.readStringUntil('\n');
}

void sendrequest() {  // Not sure
  //Serial.print("SL:0");
}

void loop() {

  unsigned long currentMillis = millis();  // Millisecond timer

  //  if (currentMillis - buff1 > 2000) {  // 2 second timeout, seems to go back to send on change if a switch is held down
  //    buff1 = currentMillis;
  //    sendrequest();
  //  }

  if (currentMillis - buff2 > 500) {  // 1/2 second timeout, to allow sent data to stabilise perhaps?
    buff2 = currentMillis;
    sendfloatauto();  // Send position of potentiometer on A1, changes position of heater blower speed knob
  }

  while (Serial.available() > 0) {  // Do stuff only when serial stream detected?
    readstr();                      // Read the incoming stream
  }

  //  Read varlist in .opl file, turn relevent led on or off for matching item
  for (byte i = 0; i < Ten; i++)analogWrite(lPin[i], varlist[i]); // Indicators

  uint16_t List = prevtriglist;
  for (byte i = 0; i < sizeof(sPin); i++) {
    bool Tr = !digitalRead(sPin[i]);
    if ((List & 1) != Tr) { // Check if data has changed for this trigger
      prevtriglist ^= ((uint16_t)1 << i);   // If data has changed...
      sending('T', i, Tr * 255);          // ....Send new data for this trigger
    }
    List >>= 1;
  }
}

void readstr() {
  String string1 = Serial.readStringUntil(':');
  if (Serial.peek()== ':')Serial.read();
  int var = Serial.parseInt();
  if (Serial.peek()== ':')Serial.read();
  if (string1 == "SV" || string1 == "LV") {
    varlist[var] = min(255, int(Serial.parseFloat() * 255.0));
  }
  else if (string1 == "$V") {
    String str = Serial.readStringUntil('\n');
    lcd.setCursor(0, var);
    lcd.print(str);
  }
  if (Serial.peek()== '\n')Serial.read();
}

void sending(char c, int index, byte var) {
  Serial.print(c) ;
  Serial.print("V:");
  Serial.print(index) ;
  Serial.print(':');
  Serial.print((float)var / 255.0, 2);
  Serial.print('\n');
}

void sendfloatauto() {
  static int roz = 0;
  int temp = analogRead(A0);  // Read potentiometer on A0
  if (abs(temp - roz) > 51) {
    roz = temp;
    sending('L', 10, temp >> 2); // Send heater fan speed knob position data to Omsi
  }
}

buttons are now working,
led's still turn on but not off.

I am noticing that when any LV is sent from omsi to the arduino to turn led's on or off, i get the following sent from the game to the arduino:


LV:6:0.888339
LV:7:0.888339
LV:8:0.888339
LV:6:0.888340
LV:7:0.888340
LV:8:0.888340
LV:6:0.888340
LV:7:0.888340
LV:8:0.888340
LV:6:0.888340
LV:7:0.888340
LV:8:0.888340

this repeats for about 2 seconds then stops, but does it again next time i do something that sends the LV to turn an led on or off.

why game send this to any LEDs? LED will light at 89% of max brightness

btw. added Serial.read(); to readout the '\n' symbol from buffer.

The led's brightness varies depending on the bus's battery state, so the 89% brightness is when the engine is not running, and it will go lower as the battery discharges, say if i leave the headlights on.

When i start the engine, the led's should dim even more, and when the engine is running they will go to 100% brightness.


I think the way the switches and outputs (leds for now, but could be other things like servo's, tone outputs to run real gauges etc) are handled needs changing,

i can see that it is a very efficient way using :

  for (byte i = 0; i < Ten; i++)pinMode(lPin[i], OUTPUT);
  for (byte i = 0; i < sizeof(sPin); i++)pinMode(sPin[i], INPUT_PULLUP);

But that makes it hard to assign individual settings to things, like button de-bouncing, sending a pulse when a toggle switch it turned on and the same pulse again when it's turned off etc.

So a long list of individual inputs / outputs may be better for that? even if it looks awful in the code.