Realdash CAN over wifi

Do you have an example of talking to realdash CAN over wifi?
The can 2 way example is doing the work over Bluetooth serial on arduino.
I’m looking for a way to get some data on a pi over wifi to realdash.
It is unclear how that data communication is intended to happen.

Thanks

The WiFi connection is just a typical TCP/IP connection, so sending end needs to act as a TCP/IP server while RealDash acts as a client. I have never developed a WiFi on Arduino, but you should be able to find example sketches on how to develop networking on Arduino.

Hi guys,

I am using Arduino MKR WiFi 1010 with MKR Can Shield.
Here is an example of code that I am using for RealDash-Can throw WIFI:


#include <CAN.h>
#include <SPI.h>
#include <WiFiNINA.h>

char ssid[] = "APName";        // your network SSID (name)
char pass[] = "APPassword";    // your network password (use for WPA, or use as key for WEP)

int status = WL_IDLE_STATUS;
WiFiServer server(35000);

const unsigned long serialBlockTag = 0x11223344;

void setup() 
{
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) 
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) 
  {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  WiFi.config(IPAddress(192, 168, 4, 100));

  // Create open network. Change this line if you want to create an WEP network:
  status = WiFi.beginAP(ssid, pass);
  if (status != WL_AP_LISTENING) 
  {
    Serial.println("Creating access point failed");
    // don't continue
    while (true);
  }
  
  // wait 1 seconds for connection:
  delay(1000);

  server.begin();

  // you're connected now, so print out the status
  printWiFiStatus();

  
  if (!CAN.begin(500E3)) 
  {
    Serial.println("Starting CAN failed!");
    while (1);
  }

  Serial.println("Setup done");
}

void loop() 
{
   ProcessMessage();
}

void ProcessMessage()
{
   
  int packetSize = CAN.parsePacket();

  if (packetSize) 
  {
    unsigned long canFrameId2 = CAN.packetId();

    int messagesToFilter[9] = {573, 852, 901, 1549, 990, 992, 994, 996, 998};  
    if(canFrameId2 == messagesToFilter[0] || 
      canFrameId2 == messagesToFilter[1] ||
      canFrameId2 == messagesToFilter[2] ||
      canFrameId2 == messagesToFilter[3] ||
      canFrameId2 == messagesToFilter[4] ||
      canFrameId2 == messagesToFilter[5] ||
      canFrameId2 == messagesToFilter[6] ||
      canFrameId2 == messagesToFilter[7] ||
      canFrameId2 == messagesToFilter[8])
    {
        byte buf3[packetSize];
        int i = 0;
    
        // only print packet data for non-RTR packets
          while (CAN.available()) {
            buf3[i] = CAN.read();
            //Serial.print(buf3[i]);
            i++;
          }
          
            //Serial.println();
        //byte buf3[8] = {0x77, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};  
        SendCANFrameToClient(canFrameId2, buf3);
    }
  }
}

   

void SendCANFrameToClient(unsigned long canFrameId, const byte* frameData)
{
    // the 4 byte identifier at the beginning of each CAN frame
    // this is required for RealDash to 'catch-up' on ongoing stream of CAN frames
    server.write((const byte*)&serialBlockTag, 4);
    
    // the CAN frame id number
    server.write((const byte*)&canFrameId, 4);
    
    // CAN frame payload
    server.write(frameData, 8);
}

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

Thanks for the WiFi code, hopefully this will be helpful :thumbs:

Dear Vasiz,
I’m just trying to connect arduino nano to realdash via wifi esp8266-01.
Could you please give me which arduino pin connection to RX and TX on esp8266,
Thank you in advance

Has anyone else done this? The example code given above is too far different to the default Realdash arduino code. Is seems to be using a CAN library instead and I am struggling to convert that over to my application.

I have my code working via a nano USB serial connection using the default realdash arduino code and I am trying to make that work over WiFi now.

I added an ESP01 wifi chip and I have it connecting, establishing an IP address and opening a TCPIP socket with my arduino nano sending the basic AT commands (See my reply below for that part).

Realdash on my tablet connects and disconnects and I can see the port opening and closing in my arduino serial monitor so that is working.

I am stuck there and not seeing any data coming through in the can monitor.

This my attempt at revising the SendCANFrameToSerial part of the code.

I think it would be better to combine serialBlockTag, canFrameId, frameData into a single 16 byte array but am not quite sure how to do that for one.

I also suspect that using websocket is a better option that constantly opening and closing the port with CIPSEND and CIPCLOSE.


void SendCANFrameToWifi(unsigned long canFrameId, const byte* frameData)
{
  // the 4 byte identifier at the beginning of each CAN frame
  // this is required for RealDash to 'catch-up' on ongoing stream of CAN frames
  
  const byte serialBlockTag[4] = { 0x44, 0x33, 0x22, 0x11 };

  mySerial.println("AT+CIPSEND=0,16");

  mySerial.write(serialBlockTag, 4);
  
  // the CAN frame id number (as 32bit little endian value)
  mySerial.write((const byte*)&canFrameId, 4);

  // CAN frame payload
  mySerial.write(frameData, 8);
    
  delay(200);

SendCommand("AT+CIPCLOSE=0","OK");
}

This part of my code works well to send AT commands to the ESP8266wifi chip and open the port

void setup()
{
  // init serial
  Serial.begin(9600);
  mySerial.begin(9600);

  // init wifi, server and port
  SendCommand("AT+RST", "Ready");   // Reset WiFi ready for new connections
  delay(5000); 
  SendCommand("AT+CWMODE=2","OK");  //  ESP8266 to Access point mode
  SendCommand("AT+CIFSR", "OK");    //  Show the IP address of the Access Point
  SendCommand("AT+CWSAP= Dash,1111,0", "OK");  // Set the SSID and pasword for the access point
  SendCommand("AT+CIPMUX=1","OK");              // Set to allow multiple connections
  SendCommand("AT+CIPSERVER=1,35000","OK");     // Start server and assign port
  
  delay(100);
}

SendCommand("AT+CIPCLOSE=0","OK");
}


boolean SendCommand(String cmd, String ack){
  mySerial.println(cmd); // Send "AT+" command to module
  if (!echoFind(ack)) // timed out waiting for ack string
    return true; // ack blank or ack found
}
 
boolean echoFind(String keyword){
 byte current_char = 0;
 byte keyword_length = keyword.length();
 long deadline = millis() + TIMEOUT;
 while(millis() < deadline){
  if (mySerial.available()){
    char ch = mySerial.read();
    Serial.write(ch);
    if (ch == keyword[current_char])
      if (++current_char == keyword_length){
       Serial.println();
       return true;
    }
   }
  }
 return false; // Timed out
}

Just as a heads up for anybody coming after me, I’ve needed to emulate some sensors coming from my computer so I could develop some signals, it wasn’t possible for me to have the device that will generate those signals with me all the time so I needed something that will emulate it on demand (just a simulation in my case won’t cut it). So I developed a TCP Server in Node.JS (Javascript, basically) so I can test and send signals to my RealDash application.

The previous examples posted here were using a CAN library when there is no need to, we only need to send the packets over WIFI in Hex format and whatever was designed on the XML definition.

So here’s the NodeJS code (there are some corrections I need to come up it for the RPM but the essentials are there, like turn signals, high beams, etc.

var socketGLO;
var net = require('net');
var readline = require('readline');

var serialBlockTag = Buffer.from([0x44,0x33,0x22,0x11]);
var BigEndian = Buffer.from([0x0C,0x80,0x00,0x00]);

// Each one of the following bytes represent the information used by RealDash for the values in the offset defined in the XML file. The left two bytes are RPM, next is Blinker Left, Blinker Right, High Beams, Fuel Level, Battery Voltage and last one (the one on the right) is Coolant Temperature.
var data = Buffer.from([0x04,0x01,0x01,0x01,0x11,0x11,0x11,0x11]);

try{
    var server = net.createServer(function(socket) {
    });
}
catch(e){
    console.log(e);
}

readline.emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);
process.stdin.on('keypress', (str, key) => {
  if (key.ctrl && key.name === 'c') {
      process.exit(0);
  } else {
    socketGLO.write(serialBlockTag);
    socketGLO.write(BigEndian);
    socketGLO.write(data);
    console.log(serialBlockTag);
    console.log(BigEndian);
    console.log(data);
    console.log('Sent now');
  }
});

server.on('connection', function(socket) {
    console.log('A new connection has been established, press any key to send RealDash CAN');
    socketGLO = socket;
    // Now that a TCP connection has been established, the server can send data to
    // the client by writing to its socket.
    socket.write(serialBlockTag);
    socket.write(BigEndian);
    socket.write(data);
    
    socket.on('data', function(chunk) {
        console.log('Data received from RealDash: ${chunk.toString()');
    });

    // When the client requests to end the TCP connection with the server, the server
    // ends the connection.
    // For some reason I was getting this a LOT, I need to investigate to see what is going on, server was on Mac RealDash client was Windows.
    
    socket.on('end', function() {
        console.log('Closing connection with the client');
    });

    // Don't forget to catch error, for your own sake.
    socket.on('error', function(err) {
        console.log('Error: ${err}');
    });
});
server.listen(1337, 'your.IP.address.on.the.machine.running.it');  // it could be like 192.168.1.100 and you can also change the port if you need it.

If anybody needs help with this, please ask, I’ll gladly help. The XML definition for this particular command is the following:

<?xml version="1.0" encoding="utf-8"?>
<RealDashCAN version="2">
  <frames>
    <frame id="0x800C" endianess="big" signed="true">
       <value name="RPM_Test" targetId="37" units=" " signed="true" offset="0" length="2"></value>
       <value name="BLR_Test" targetId="160" units=" " signed="true" offset="1" length="1"></value>
       <value name="BLL_Test" targetId="161" units=" " signed="true" offset="2" length="1"></value>
       <value name="HB_Test" targetId="157" units=" " signed="true" offset="3" length="1"></value>
       <value name="FL_Test" targetId="170" units=" " signed="true" offset="4" length="1"></value>
       <value name="BV_Test" targetId="12" units=" " signed="true" offset="5" length="1"></value>
       <value name="CT_Test" targetId="14" units=" " signed="true" offset="6" length="1"></value>       
  </frames>

While this is a work in progress it is already working so if you do find something wrong in your case and is not working, just ask, it could be something I copied wrong in here, do not assume that this isn’t working.

Hope this helps someone out there!
Juan

I’m using Wi-Fi with node-red and RealDash. Code lives on GitHub.
https://github.com/sdc53/RealDash-CAN-MQTT-Node-Red-2-way

Very cool project, thanks for sharing.

@sdc535 This is an awesome project. I was wondering how were you handling the difference for the sensors handling 12v normally and the not linear way of presenting values back to you. Are you creating a table over time with the analog gauge to match the different values presented back to you when the voltage is different?

My understanding of your project is that you disconnect the sensors with the relays, lets take the CTS (Coolant Temperature Sensor) and then you connect it to your ADS and from there you read the values it returns, is this correct? What is your voltage feeding the sensor when you disconnect it with the relay, 5v correct? Then the non-linear values you get back are not the same as the ones you get when you feed the sensors 12v but a new table needs to be defined, how are you mapping those values to actual temperatures?

In my particular case I have sensors that ARE linear and I don’t have to care about the voltage because I can feed them 5v and I get a 10mv/C so I can track that rather easily (granted that a new sensor was needed and all that comes with it.) Just trying to understand how are you dealing with the non-linear nature of those sensors and how long it took you to map them correctly to actual real values.

I just saw the voltage divider you use on the sensors. So you still drive them with 12v, my question still stands, how did you came up with the mapping in between readings and actual real life temperature, psi, etc.

Thanks!

I managed to get my Arduino communicating with realdash over wifi by using the info on this page.

I used the basic ESP-01 module and the code provided in this link. I altered the code so the device created it’s own access point and IP address and my Car tablet wifi connects to it automatically. I set the timeout value in the code to 0 and it streams constantly.

http://www.forward.com.au/pfod/CheapWifiShield/ESP2866_01_WiFi_Shield/index.html

Hello to everyone reading this,

I´m basically trying to get it working in the same configuration as @Vasiz has (MKR 1010 and CAN shield).
Just to explain a little: The CAN library just intends to read out data from any physical CAN line, knowing the IDs, message format and content. So far so good. Anyhow, when trying to run that code, the MRK 1010 is generating the access point properly, I can connect with my Android phone…But: Realdash is trying to connect and is not successful. What I see from the provided code is:

  • Protocol seems to be TCP, not UDP. Is that correct?
  • I´ve tried UDP datastream in the Realdash CAN format too, but also without success.
  • I´ve tried another phone, also not working
  • I´ve connected the Arduinos access point with my Mac and checked the communication with “Packet sender” app and I could see the correct frames broadcasted by the Arduino.

Any ideas what else could be wrong here?


RealDash uses TCP for WiFi connections. I could not find any code where you specify the port of your TCP server, it may be using some default port number. See if you can configure the TCP/IP port in your Arduino code.

The line:

WiFiServer server(35000);

Should do that. Here on Port 35000.

Oh, sorry I missed that. Don’t know what could be wrong, sorry :frowning:

Sorry for the confusion.

I got it working now on a Samsung Galaxy Tab. The code shared above works as it is. Thank you for that!
I figured out that the Realdash App might struggle on phones without GFS Google Framework Services (I have tried with a google-free Vollaphone)

So I assume that was the root cause.

The my.realdash.net version has basically all Google Store integrations removed, it may work better on that sense.

Im going to try the code when i get home, have been trying to get my arduino r4 to send the can messages trough realdash can.

I managed to get wifi accesspoint running on the arduino.

Phone is connected to arduino accesspoint and realdash is trying to connect to the ip adress of the arduino but it cant connect.

In realdash which ip adress should i type in? The arduinos or my phone?