For any add-on boards such as VR conditioners, optos and OEM interface boards
#50378
Just wanted to share a small project I have been working on, which translates the Serial3 protocol to the NBP protocol used by TrackAddict (https://racerender.com/TrackAddict/docs/Interop.html), allowing for data collection and overlay using RaceRender. Uses an Arduino Nano and a HC-06 Bluetooth module, configured to run at 115200 baud.

Power and ground are connected to the Speeduino 5V and ground respectively of course.
Nano TX goes to the HC-06 RC.
Nano RX goes to Speeduino Serial3 TX.
Nano A5 goes to Speeduino Serial3 RX - the Nano uses software serial to request the data.

Right now I have it running at ~20hz.

Image
Code: Select all
// Speeduino Serial3 to TrackAddict NBP translation
// Uses Arduino Nano + HC-06 Bluetooth module configured to 115200 baud
// 5/15/2021

//SoftwareSerial, dedicated to requesting data from Serial3
#include <SoftwareSerial.h> 
SoftwareSerial Request(18, 19); // RX, TX - D18 is A4, D19 is A5

//Setup Serial3 Data Array
byte S3Data[75];

//Setup Time variables
unsigned long StartTime=0;
unsigned long LoopTime=0;

void setup()
{
// Start serial connections at 115200 Baud
Serial.begin(115200);
Serial.setTimeout(10); //Set Serial3 read timeout to 10ms

//Start softserial for requests
Request.begin(115200);

//Initialize Serial3 Data Array empty
for ( int i = 0; i < 76; ++i ){S3Data[i]=0;} 

}

void loop()
{
  //Set Start Time
  StartTime=millis();
  
  //Read Serial3 Data into buffer, discarding first value as "A" response
  if(Serial.available() > 0){Serial.read();Serial.readBytes(S3Data,75);}

  //Request data using SoftwareSerial for next loop
  Request.println("A");
 //delay(1000);

  //Output NBT
  //Spec: https://racerender.com/TrackAddict/docs/NBP%20Specification.pdf

  // "UPDATEALL" tells our consumers that we're sending fresh sample data for every channel we have
  // "UPDATE" would be used when we only update certain channels but might not include all of our channels
  // "ALL" would be if we send the current valuesfor every channel we have, but it isn't necessarily new data
  // Dummy data for testing
  // Name, Unit, Value  -OR -Name, Value

  //Generate Header 
  static char header[64];sprintf(header, "*NBP1,UPDATEALL,%d.%03d", (int)(StartTime / 1000), (int)(StartTime % 1000));
  
  //Print Header
  Serial.println(header);

  //Print Data - Use bit numbers as array index, see documentation: https://wiki.speeduino.com/en/Secondary_Serial_IO_interface
/*  
 *   0 - currentStatus.secl - secl is simply a counter that increments each second
1 - currentStatus.squirt - Squirt Bitfield
2 - currentStatus.engine - Engine Status Bitfield
3 - (byte)(divu100(currentStatus.dwell)) - Dwell in ms * 10
4 - lowByte(currentStatus.MAP)
5 - highByte(currentStatus.MAP)
6 - (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET) - mat
7 - (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET) - Coolant ADC
8 - currentStatus.batCorrection - Battery voltage correction (%)
9 - currentStatus.battery10 - battery voltage
10 - currentStatus.O2 - primary O2
11 - currentStatus.egoCorrection - Exhaust gas correction (%)
12 - currentStatus.iatCorrection - Air temperature Correction (%)
13 - currentStatus.wueCorrection - Warmup enrichment (%)
14 - lowByte(currentStatus.RPM) - rpm LB
15 - highByte(currentStatus.RPM) - rpm HB
16 - currentStatus.TAEamount - acceleration enrichment (%)
17 - currentStatus.corrections - Total GammaE (%)
18 - currentStatus.VE - Current VE 1 (%)
19 - currentStatus.afrTarget - chosen afr target
20 - lowByte(currentStatus.PW1) - Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
21 - highByte(currentStatus.PW1) - Pulsewidth 1 multiplied by 10 in ms. Have to convert from uS to mS.
22 - currentStatus.tpsDOT - TPS DOT
23 - currentStatus.advance - Current spark advance
24 - currentStatus.TPS - TPS (0% to 100%)
25 - lowByte(currentStatus.loopsPerSecond) - loops per second LB
26 - highByte(currentStatus.loopsPerSecond) - loops per second HB
27 - lowByte(currentStatus.freeRAM) - freeRam LB
28 - highByte(currentStatus.freeRAM) - freeRam HB
29 - currentStatus.boostTarget - Target boost pressure
30 - currentStatus.boostDuty - current pwm boost dutycycle
31 - currentStatus.spark - Spark related bitfield
32 - lowByte(currentStatus.rpmDOT) - rpmDOT must be sent as a signed integer
33 - highByte(currentStatus.rpmDOT) - rpmDOT HB
34 - currentStatus.ethanolPct - Flex sensor value (or 0 if not used)
35 - currentStatus.flexCorrection - Flex fuel correction (% above or below 100)
36 - currentStatus.flexIgnCorrection - Ignition correction (Increased degrees of advance) for flex fuel
37 - currentStatus.idleLoad - idleload
38 - currentStatus.testOutputs - testoutputs bitfield
39 - currentStatus.O2_2 - Second O2
40 - currentStatus.baro - Barometer value
41 - lowByte(currentStatus.canin[0]);
42 - highByte(currentStatus.canin[0]);
43 - lowByte(currentStatus.canin[1]);
44 - highByte(currentStatus.canin[1]);
45 - lowByte(currentStatus.canin[2]);
46 - highByte(currentStatus.canin[2]);
47 - lowByte(currentStatus.canin[3]);
48 - highByte(currentStatus.canin[3]);
49 - lowByte(currentStatus.canin[4]);
50 - highByte(currentStatus.canin[4]);
51 - lowByte(currentStatus.canin[5]);
52 - highByte(currentStatus.canin[5]);
53 - lowByte(currentStatus.canin[6]);
54 - highByte(currentStatus.canin[6]);
55 - lowByte(currentStatus.canin[7]);
56 - highByte(currentStatus.canin[7]);
57 - lowByte(currentStatus.canin[8]);
58 - highByte(currentStatus.canin[8]);
59 - lowByte(currentStatus.canin[9]);
60 - highByte(currentStatus.canin[9]);
61 - lowByte(currentStatus.canin[10]);
62 - highByte(currentStatus.canin[10]);
63 - lowByte(currentStatus.canin[11]);
64 - highByte(currentStatus.canin[11]);
65 - lowByte(currentStatus.canin[12]);
66 - highByte(currentStatus.canin[12]);
67 - lowByte(currentStatus.canin[13]);
68 - highByte(currentStatus.canin[13]);
69 - lowByte(currentStatus.canin[14]);
70 - highByte(currentStatus.canin[14]);
71 - lowByte(currentStatus.canin[15]);
72 - highByte(currentStatus.canin[15]);
73 - currentStatus.tpsADC - TPS (Raw 0-255)
74 - getNextError() - Error codes
 */
  Serial.print("\"RPM\":");Serial.println((S3Data[15] << 8) + S3Data[14]); //Convert 2byte RPM to Int and print
  Serial.print("\"Throttle\",\"%\":");Serial.println(S3Data[24]); //Print TPS
  Serial.print("\"MAP\",\"kpa\":");Serial.println((S3Data[5] << 8) + S3Data[4]);; //Convert 2byte MAP to Int and print
  Serial.print("\"AFR\":");Serial.println(S3Data[10]/10.0,1); //Print AFR
  Serial.print("\"Coolant\",\"deg f\":");Serial.println(((S3Data[7]-40)*1.8)+32,0); //Subtract offset of 40 and convert deg C to F, Print CLT
  Serial.println("#");

  //delay until loop has taken 50ms
  LoopTime=((millis()-StartTime)/10);
  delay(37-LoopTime);// 50ms interval = 20 Hz, custom tuned from results in this case


}

I think possible reasons for that would be: 1) loo[…]

It looks like you have a fuel supply issue. readin[…]

Will this have an updated version about this featu[…]

Perhaps some different points and pictures. Instr[…]

Still can't find what you're looking for?