Arduino UNO Wifi R4 project

I am in the early planning stages of a project to record engine RPM, engine vacuum, and AFR data from an existing Autometer AFR gauge / O2 sensor. The car is carbureted and does not have an ECM so I have to measure the signals on my own.

This is my first ever Arduino project, so sorry for any dumb questions.

The UNO R4 with WIFI version that just came on the market has onboard Bluetooth and WIFI, I was wondering if anyone has an idea of how this will affect the logic / libraries needed to send data from the UNO to RaceChrono? Will it be limited to Bluetooth only, or would I be able to broadcast data faster using the embedded WIFI module?

Does anyone have any tips for the best way to read the RPM signal from an MSD 6AL ignition box? It is supposed to send out a 12v, 20% duty cycle square wave, and I'm debating between using a proto screw terminal type shield to make a voltage divider, and using some sort of optocoupler module, potentially one of the Mikroe Click boards, since I was planning on going with the Vacuum Click board to read manifold vacuum. I'm trying to make it as plug and play, and robust as possible, as this will be going in a fairly stiffly sprung HPDE car.

Comments

  • 5V logic, ESP32 and CAN onboard?! Looks very interesting for DIY data logging applications. Thanks for sharing!
  • edited August 2023
    @timurrrr , I downloaded your github code, but when I try to compile the "PrintRaceChronoRequestsToSerial" example (Edit: all examples generate the same errors), I am getting the following errors:

    C:\Users\***\AppData\Local\Temp\arduino_build_889957\sketch\sketch_aug13_RaceChronoBLE_Example.ino.cpp.o: In function `waitForConnection()':
    C:\Users\***\Documents\Arduino\sketch_aug13_RaceChronoBLE_Example/sketch_aug13_RaceChronoBLE_Example.ino:63: undefined reference to `RaceChronoBle'
    C:\Users\***\AppData\Local\Temp\arduino_build_889957\sketch\sketch_aug13_RaceChronoBLE_Example.ino.cpp.o: In function `loop':
    C:\Users\***\Documents\Arduino\sketch_aug13_RaceChronoBLE_Example/sketch_aug13_RaceChronoBLE_Example.ino:71: undefined reference to `RaceChronoBle'
    C:\Users\***\AppData\Local\Temp\arduino_build_889957\sketch\sketch_aug13_RaceChronoBLE_Example.ino.cpp.o: In function `setup':
    C:\Users\***\Documents\Arduino\sketch_aug13_RaceChronoBLE_Example/sketch_aug13_RaceChronoBLE_Example.ino:43: undefined reference to `RaceChronoBle'
    collect2.exe: error: ld returned 1 exit status

    Anyone have any suggestions? I did have to go through an exercise to load new firmware onto the ESP32 chip and downloaded an updated BLE library that has R4 Wifi support. I was able to run an example from one of those and the BLE working as far as being able to connect it to my phone.
  • I have made quite a bit of progress on this project so far, and have used a WIFI print along with a wifi version of serial terminal app to read data onto my phone.

    Now, however, I would like to get the data into Racechrono.

    Are there any examples out there of how to create the raw RC2/RC3 / NEMA messages using the print command so I can convert it over to WIFI? Or is there a better way to send data to RaceChrono over WIFI?

    Here is the working code that I have so far (still in progess so ignore all the comments)

    #include "WiFiS3.h" //WIFI LIBRARY FOR UNO R4 WIFI
    #include "arduino_secrets.h" //WIFI SSID & PW FILE

    //enter your sensitive data in the Secret tab/arduino_secrets.h

    char ssid[] = SECRET_SSID; // your network SSID (name)
    char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) USING WPA
    int keyIndex = 0; // your network key index number (needed only for WEP)

    int led = LED_BUILTIN; //LED ON ARDUINO BOARD, OUTPUT 13
    int status = WL_IDLE_STATUS;
    WiFiServer server(80); //USE THIS PORT ADDRESS (80) IN ANDROID APP WITH RAW DATA SETTING

    const int RPMpin = 2; //input pin for RPM signal from ignition
    char buffer[40];
    volatile unsigned long last_microsec = 0;
    volatile long period = 0; //was unsigned long 10/4/23
    volatile float freq = 0.0; //FREQUENCY OF RPM SIGNAL IN Hz
    volatile float Engine_RPM = 0.0;
    volatile boolean RPM_flag = 0; //RPM INPUT PIN REGISTERED A PULSE AND EXECUTED INTERRUPT FUNCTION
    volatile boolean RPM_invalid_flag = 0; //RPM INPUT TIME INVALID FOR CURRENT SAMPLE DUE TO INTERRUPTS BEING DISABLED
    volatile boolean Print_flag = 0; //READY TO PRINT DATA FLAG
    volatile unsigned long Tmr1 = 0;
    volatile boolean Tmr1_dn = 0; //Tmr1 DONE / COMPLETE FLAG
    volatile long period_prnt = 0; //was unsigned long 10/4/23
    volatile float freq_prnt = 0.0; //FREQUENCY OF RPM SIGNAL IN Hz FOR PRINTING
    volatile float Engine_RPM_prnt = 0.0; //CALCULATED RPM SIGNAL FOR PRINTING
    volatile float vacuum =0.0; //CALCULATED INTAKE MANIFOLD VACUUM
    volatile float AFR=0.0; //CALCULATED AIR FUEL RATIO FROM OXYGEN SENSOR
    volatile int ambient_vac_int=0;
    const unsigned int maxReadings = 60;
    unsigned long period_array[maxReadings];
    unsigned int i = 0;
    WiFiClient client=0;
    void RPM_Count() //RUN THIS FUNCTION WHEN RPM PULSE FROM IGNITION SYSTEM GOES HIGH
    {
    unsigned long t = micros();
    //measure time between pulse and previous pulse
    if (RPM_invalid_flag==0)
    {
    period = (t - last_microsec);
    }
    else
    {
    period = 1;
    }
    last_microsec = t;
    RPM_flag=1;
    }
    void Data_Record() //logic for recording engine data (previously in loop routine)
    {
    if (((micros() - Tmr1) >= 100000) && Tmr1_dn==false) // 100,000uS = 100mS intervals
    {
    Tmr1_dn=true;
    Tmr1=micros();
    }
    if ((period>=1500) && (RPM_flag==true) && (RPM_invalid_flag==false)) // && ((((period_prnt-period)>=-100) && ((period_prnt-period)<=100 )) || (period_prnt==0))) //fix period test logic, only runs once
    {
    Serial.println("Valid RPM period");
    freq = (1000000.0/period); //1,000,000uS = 1 SECOND
    }
    else //INVALID DATA WAS DETECTED
    {
    RPM_flag=false;
    RPM_invalid_flag=false;
    period_prnt=period;
    }
    if ( Tmr1_dn==true) //RUN THIS EVERY TIME TMR1 IS DONE (100mS), client.print = wifi data transmission
    {
    vacuum = ((map(analogRead(A0), 0, ambient_vac_int,-3610,0))/100.0); //divide by 100 to get 2 decimal places
    AFR = ((map(analogRead(A1), 0, 4095,1000,1800))/100.0);
    Engine_RPM = ((freq * 60.0)/4.0);
    Engine_RPM_prnt=Engine_RPM;
    client.print(",");
    client.print(Engine_RPM_prnt);
    client.print(",RPM,");
    client.print(vacuum);
    client.print(",inHg,");
    client.print(AFR);
    client.println(",:1 AFR,");
    Print_flag=false;
    RPM_flag=false;
    RPM_invalid_flag=true;
    Tmr1_dn=false;
    //interrupts(); //11/18/23:DO NOT USE, CAUSING CPU TO FREEZE. TURNS INTERRUPTS BACK ON TO RESUME CHECKING FOR RPM PULSES
    }
    }

    void printWiFiStatus() {
    // print the SSID of the network you're attached to:
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());

    // print your WiFi shield's IP address:
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    Serial.println(ip);
    }

    void setup() {
    // put your setup code here, to run once:
    pinMode(RPMpin , INPUT);
    //pinMode(3 , OUTPUT);
    pinMode(A0, INPUT);
    analogReadResolution(12);
    delay(1000);
    ambient_vac_int = analogRead(A0); //take reading of ambient pressure w/o engine running for barometric zero
    pinMode(A1, INPUT);
    analogReadResolution(12);
    attachInterrupt(digitalPinToInterrupt(RPMpin), RPM_Count, RISING); //ASSIGNS INTERRUPT TO RPM_PIN ON RISING EDGE

    Serial.begin(115200);
    //analogWrite(3,75); //OUTPUT PWM ON PIN 3 FOR RPM_PIN TO MEASURE FOR TESTING PURPOSES
    Tmr1 = micros();

    //********** WIFI COMMS LOGIC: **********
    pinMode(led, OUTPUT); // set the LED pin mode
    // check for the WiFi module:
    if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
    }

    String fv = WiFi.firmwareVersion();
    if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
    }

    // by default the local IP address will be 192.168.4.1
    // you can override it with the following:
    WiFi.config(IPAddress(192,168,1,2));

    // print the network name (SSID);
    Serial.print("Creating access point named: ");
    Serial.println(ssid);

    // Create open network. Change this line if you want to create an WEP network:
    status = WiFi.beginAP(ssid, pass);
    delay(100); //PTP
    if (status != WL_AP_LISTENING) {
    Serial.println("Creating access point failed");
    while (true);
    }

    delay(10000);
    // start the web server on port 80
    server.begin();
    printWiFiStatus();
    }
    void loop() {
    // main code here, to run repeatedly:

    //********** WIFI COMMS LOGIC: **********
    // compare the previous status to the current status
    if (status != WiFi.status()) {
    // it has changed update the variable
    status = WiFi.status();

    if (status == WL_AP_CONNECTED) {
    // a device has connected to the AP
    Serial.println("Device connected to AP");
    } else {
    // a device has disconnected from the AP, and we are back in listening mode
    Serial.println("Device disconnected from AP");
    }
    }

    client = server.available(); // listen for incoming clients, PTP removed WiFiClient declaration to make global variable

    if (client) { // if you get a client,
    Serial.println("new client");
    client.println("Connected to UnoR4!");
    Tmr1=micros();
    while (client.connected()) { // loop while the client's connected
    Data_Record(); //run data recording routine
    } //while loop end
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
    }
    //Serial.println("client lost");
    }
  • @Paul351W Apologies for the delay, I didn't see the tag. Assuming that your issue is with my arduino-RaceChrono library, please use https://github.com/timurrrr/arduino-RaceChrono/issues if you have issues in the future.

    If you look at the files in the src/ directory of that library, you can see that there's an #ifdef trick to automatically pick the right implementation for the board you're compiling for. I can totally imagine those conditions to not handle a previously-unknown board correctly, so the code needs to be updated. Try changing the #if defined(ARDUINO_ARCH_ESP32) condition at the top of RaceChronoESP32.cpp to "#if true" ?

    As for the Wi-Fi idea, I don't think RaceChrono has a protocol for DIY devices to connect via Wi-Fi, but I might be wrong.
Sign In or Register to comment.