Repository: janimm/RealDash-extras
Branch: master
Commit: cedfdf491b53
Files: 75
Total size: 560.9 KB
Directory structure:
gitextract_56dij45d/
├── CanPlayback/
│ ├── canplayback.py
│ └── readme.md
├── Dashboard-animation-examples/
│ ├── Multiview.rd
│ ├── Multiview_anim.xml
│ ├── README.md
│ ├── RealDash_animation_example.rd
│ ├── RealDash_animation_example_anim.xml
│ ├── value_anim_example.rd
│ └── value_anim_example_anim.xml
├── LICENSE
├── OBD2/
│ ├── README.md
│ ├── realdash_obd2.xml
│ ├── realdash_obd2_Itelma_M73_E3.xml
│ ├── realdash_obd2_bosch_mp70.xml
│ ├── realdash_obd2_fiat_precan.xml
│ ├── realdash_obd2_gm_ls.xml
│ ├── realdash_obd2_january_5_1.xml
│ ├── realdash_obd2_mitsubishi_mut.xml
│ ├── realdash_obd2_nissan_generic.xml
│ ├── realdash_obd2_opel_kwp2000.xml
│ ├── realdash_obd2_saab_generic.xml
│ ├── realdash_obd2_toyota_celica_corolla_camry.xml
│ ├── realdash_obd2_toyota_gt86.xml
│ ├── realdash_obd2_toyota_jdm_generic.xml
│ ├── realdash_obd2_toyota_jdm_iso9141.xml
│ ├── realdash_obd2_toyota_rav4_supra_lexus_is.xml
│ ├── realdash_obd2_toyota_vitz.xml
│ ├── realdash_obd2_volvo_noncan1.xml
│ └── realdash_obd2_volvo_noncan2.xml
├── README.md
└── RealDash-CAN/
├── Arduino-examples/
│ ├── README.md
│ ├── RealDash_CAN/
│ │ └── RealDash_CAN.ino
│ ├── RealDash_CAN_2way/
│ │ └── RealDash_CAN_2way.ino
│ ├── realdash_can_arduino_test.rd
│ └── realdash_can_example.xml
├── README.md
├── XML-files/
│ ├── AEM/
│ │ ├── aem_22_unit1.xml
│ │ ├── aem_22_unit2.xml
│ │ ├── aem_6_can.xml
│ │ └── aem_infinity.xml
│ ├── Adaptronic/
│ │ ├── adaptronic_can_full.xml
│ │ └── adaptronic_can_simple.xml
│ ├── BMW/
│ │ ├── BMW335i.xml
│ │ ├── BMW_R1200GS_K25_CAN.xml
│ │ └── bmw_siemens_ms42_can.xml
│ ├── Ecumaster/
│ │ ├── ecumaster_emublack.xml
│ │ └── ecumaster_gps.xml
│ ├── Edelbrock/
│ │ └── edelbrock_proflo4.xml
│ ├── Emerald/
│ │ └── emerald_k3_k6.xml
│ ├── Emtron/
│ │ └── emtron_packet_1.xml
│ ├── Flagtronics/
│ │ └── flagtronics_can_v0_4.xml
│ ├── GM/
│ │ ├── gm_ls7_can.xml
│ │ ├── gm_ls_can.xml
│ │ └── gm_ls_can_full.xml
│ ├── Grayhill/
│ │ └── grayhill_touch_encoder.xml
│ ├── Haltech/
│ │ ├── haltech_v2_can.xml
│ │ └── haltech_v3_can.xml
│ ├── Holley/
│ │ ├── dominator_and_terminator_x_can.xml
│ │ ├── holley_efi_can.xml
│ │ └── sniper_v2_can.xml
│ ├── Life Racing/
│ │ └── life_racing_default_can.xml
│ ├── Link/
│ │ ├── displaylink.xml
│ │ └── link_dash2pro.xml
│ ├── MaxxECU/
│ │ └── maxxecu_default_can.xml
│ ├── Megasquirt/
│ │ ├── megasquirt_dashmode_can.xml
│ │ └── megasquirt_realtime_data_broadcasting_can.xml
│ ├── OBR/
│ │ └── obr_euro_8.xml
│ ├── SCS-Delta/
│ │ └── scs-delta.xml
│ ├── syvecs/
│ │ └── syvecs_default_can.xml
│ ├── toyota/
│ │ ├── toyota_corolla_e150.xml
│ │ └── toyota_fj_can.xml
│ ├── tpms/
│ │ └── tiremagic_tpms.xml
│ └── turbolamik/
│ └── turbolamik_tcu.xml
├── realdash-can-description-file.md
└── realdash-can-protocol.md
================================================
FILE CONTENTS
================================================
================================================
FILE: CanPlayback/canplayback.py
================================================
"""
canplayback.py
This program reads a RealDash CAN log file and streams the CAN frames from log
to RealDash.
Usage:
- Start the canplayback program
$ python3 canplayback.py CSVFILE PORT
- Start RealDash and create 'RealDash CAN' connection
- Configure connection to IP address and port shown by the canplayback program
"""
import socket
import csv
import time
import sys
def get_next_line(csvfile):
line = csvfile.readline()
if not line:
csvfile.seek(0)
_ = csvfile.readline()
line = csvfile.readline()
return line
def send_next_frame(client, csvfile):
line = get_next_line(csvfile)
if line:
values = next(csv.reader([line], delimiter = ',', skipinitialspace=True))
#index = values[0]
#time = values[1]
#channel = values[2]
#direction = values[3]
#frame_id = values[4]
#frame_data = values[5]
print("send:", values[4], values[5])
frame_id = int(values[4], 0)
client.sendall(bytes([0x44, 0x33, 0x22, 0x11]))
client.sendall(frame_id.to_bytes(4, 'little'))
frame_data = [int(value, 16) for value in values[5].split(' ') if value != 'x|']
frame_data.extend([0] * (8 - len(frame_data)))
client.sendall(bytes(frame_data))
#time.sleep(0.01)
def main(filename, port):
with open(filename) as csvfile:
_ = csvfile.readline()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", port))
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.listen(2)
print("Listening at", server.getsockname())
try:
while True:
client, address = server.accept()
print("Connected to ", address)
try:
while True:
send_next_frame(client, csvfile)
except Exception as e:
print(e)
client.close()
csvfile.seek(0)
_ = csvfile.readline()
print("Listening at", server.getsockname())
except (KeyboardInterrupt, Exception):
server.close()
if __name__ == "__main__":
CSV_FILE = sys.argv[1]
port = int(sys.argv[2])
main(CSV_FILE, port)
================================================
FILE: CanPlayback/readme.md
================================================
# **RealDash-extras**
RealDash examples and technical materials
All materials in this repository are licensed with [NoLicense](https://github.com/janimm/RealDash/blob/master/LICENSE)
[realdash.net](https://www.realdash.net)
## **CanPlayback**
This is a simple tool to stream RealDash CAN frames from CAN log files recorded in RealDash CAN Monitor. Usage:
$ python3 canplayback.py CSVFILE PORT
For example:
$ python3 canplayback.py rdcan_2023-03-31_11-33-36.csv 35000
Limitations:
- Only works on <=8 byte frames (0x11223344 frames).
- Frames with less than 8 bytes are padded with zeroes.
- Has no timing, it pushes the frames as quickly as possible.
- Enable 'time.sleep(0.01)' in the code to slow down.
- Has no proper error checking
================================================
FILE: Dashboard-animation-examples/Multiview_anim.xml
================================================
================================================
FILE: Dashboard-animation-examples/README.md
================================================
# **Dashboard animation examples**
How to create animated dashboards with RealDash.
- Name the animation XML file as *dashboardname_anim.xml*
- Place the animation XML file into same folder with *.rd* file
- On Windows version of RealDash, use *File* menu *Import* option to import the XML file (in edit mode).
* This is required since Windows Store apps are not allowed to access files without user interaction.
- When XML has changed, reload the .rd file, or press *F2* on Windows to reload the dash and apply changes.
- Every time .rd file is saved it also contains all animations, there is no need to distribute the XML with .rd file.
**NOTE**
The *groups* and *group* attributes will not be supported in future versions of RealDash. To animate multiple gauges with one animation, use a Container Gauge in RealDash. Container gauge accepts all animation types and applies the animation to all contained gauges. Removal of the support for *groups* in XML does not affect the functionality of previously published dashboards.
## **Files**
| file | description |
|:--------|:----------:|
| RealDash_animation_example.rdRealDash_animation_example_anim.xml | Example dashboard that demonstrates most common animation techniques. |
| value_anim_example.rdvalue_anim_example_anim.xml | Example of how to animate gauges based on input values. Requires RealDash version 2.4.7 or newer. |
| Multiview.rdMultiview_anim.xml | Multiview dashboard and associated animation XML file. Multiview is available for free in RealDash gallery. |
## **Animations**
### **Animation types**
| type | description |
|:--------|:----------:|
| morph | animate the area of the gauge. Use CTRL+Q in RealDash to copy gauge area to clipboard. |
| position | animate gauge position. Use SHIFT+Q in RealDash to copy gauge center position to clipboard. |
| fade | fade gauge |
| value-morph | animate the area of the gauge based on input value. Requires RealDash version 2.4.7 or newer. |
| value-fade | fade gauge based on input value. Requires RealDash version 2.4.7 or newer. |
### **Animation easing types**
Animations use easing. Multiple easing types are available for animations.
Each easing type may have postfix In, Out, or InOut. Default for all is InOut.
Default easing for all animations is SineInOut.
Examples of easing in action: [https://matthewlein.com/tools/ceaser]
| type |
|:--------|
| Back(In, Out, InOut) |
| Bounce(In, Out, InOut) |
| Circ(In, Out, InOut) |
| Cubic(In, Out, InOut) |
| Elastic(In, Out, InOut) |
| Expo(In, Out, InOut) |
| Linear(In, Out, InOut) |
| Quad(In, Out, InOut) |
| Quart(In, Out, InOut) |
| Quint(In, Out, InOut) |
| Sine(In, Out, InOut) |
[realdash.net](https://www.realdash.net)
================================================
FILE: Dashboard-animation-examples/RealDash_animation_example_anim.xml
================================================
================================================
FILE: Dashboard-animation-examples/value_anim_example_anim.xml
================================================
================================================
FILE: LICENSE
================================================
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
================================================
FILE: OBD2/README.md
================================================
# **RealDash-extras**
[realdash.net](https://www.realdash.net)
## **OBD2**
This folder contains OBD2 XML description files used by default in RealDash. These can be used as starting points for custom modifications.
| file | description |
|:--------|:----------:|
| realdash_obd2.xml | RealDash default OBD2 description file.This file is bundled with RealDash app and used as a default. |
| realdash_obd2_bosch_mp70.xml | Description file for 'Bosch mp7.0' ECU |
| realdash_obd2_january_5_1.xml | Description file for 'January 5.1' ECU |
## **OBD2 XML description file**
The communication between OBD2 (via ELM327 compatible adapter) is described for RealDash in a XML text file and is fully customizable.
Note that while there are some similarities, the OBD2 XML file is **not** in same format as [RealDash CAN XML file](../RealDash-CAN/README.md).
The XML file starts and ends with **OBD2** tags and contains two main sections, **init** and **rotation**.
## **The 'init' section**
The commands in init section are send after RealDash has connected to ELM327 adapter. In case you need to activate custom headers or other initialization, this is the correct section to add required commands. Here is the **init** section from RealDash default OBD2 XML:
The **init** section contains list of commands to send. Note that **atl0**, **ate0**, and **ats0** commands are required for RealDash to correctly parse the replys.
The commands **0100** and **0120** are the first ones that expect reply from the vehicle. Their reply contains information on vehicle supported PIDs. When RealDash sends these commands, you will see the *Checking PID support* message in RealDash.
There is good info on standard OBD2 PIDs on [Wikipedia](https://en.wikipedia.org/wiki/OBD-II_PIDs) page.
## **The 'rotation' section**
After commands in init section are sent and responses received, RealDash starts sending the commands in rotation section. These commands are sent to OBD2 until connection is terminated. Here is one command in rotation section as an example:
**command** tag parameters are:
### **send**
This is the command to send to adapter. In above example **010c**, which is command to request engine RPM.
### **skipCount**
Number of times to skip sending this command. This value can be used to request a certain values less frequently and therefore get more time critical data faster. For example, using 5 as **skipCount** would send the command and later skip sending the command 5 times before sending it again. For some values like ambient temperature **skipCount** can be relatively large value, like 60. Default skipCount is 0.
### **targetId**
This value links the received value into RealDash input. The **targetId="37"** writes the received value to RealDash RPM input. Check out full listing of [RealDash targetIds](https://www.realdash.net/manuals/targetid.php).
### **name [optional to targetId]**
Instead of mapping the value to existing RealDash input, **name** parameter can be used to create new input into RealDash *ECU Specific* category. Name parameter is used only if **targetId** is not present in command. Example:
Note that above example do not use the **targetId**, but **name** instead. When RealDash reads the XML file, a new custom input is created into *ECU Specific* category called **MYECU: Special RPM**. New custom input can be used like any other input in RealDash for gauges and triggers/actions.
Note: if you make your own dashboard that links into custom inputs, remember that other users need to have same XML available for the dashboard to work correctly. Another solution would be to make the dashboard use [RealDash build-in inputs](https://www.realdash.net/manuals/targetid.php) and use the *Input Mapping* feature in RealDash *Settings->Units & Values->Input Mapping*.
### **conversion [optional]**
The **conversion** is a formula that is applied to received value. For example, **conversion="V/4"** takes incoming value and divides it by 4 before writing the value to its input. Conversion can be any valid mathematical formula with these variables:
* V (VALUE). This is the entire returned value as is (all received bytes).
* B0 - First byte of the reply (reading from left)
* B1 - Second byte of the reply
* ...
* B256
* ...
### **conversionABC [optional]**
The **conversionABC** is otherwise identical with **conversion**, but bytes are identified with **A,B,C,...,AA,AB,AC,...**, etc. This makes it easier to convert the Equation from other popular apps. For example **conversion="B0+15*(B1-43)"** and **conversionABC="A+15*(B-43)"** produce the same result.
### **Conversion examples**
conversion="V/10"
- result is incoming value / 10
conversion="B0+15*(B1-43)"
- result is first byte + 15 * (second byte - 43)
### **units [optional]**
Optional info to apply automatic unit conversions. Valid values are **units="C"**, **units="F"**, **units="km/h"**, **units="mph"**, **units="bar"**, **units="psi"**, **units="text"**, **units="bit"**.
If units is set to **bit** the value is considered to be an on/off (0 or 1) valued. RealDash reads the **bit** value from the lowest bit. Therefore there is a need for a bitshift to the right on conversion. For example **conversion="(V>>1)"** will read second bit on incoming value.
The **units="text"** can be used to see the OBD2 reply 'as-is' in RealDash text gauge. This is mainly for development/debug purposes.
### **header [optional]**
Header to set before sending the command. The full AT command to set the header must be specified. If all commands use same header, its best to be placed in **init** section. If rotation uses two or more headers, set the header for every command. Examples of **header** usage:
### **ecu [optional]**
The **ecu** parameter specifies which ECU reply to use as the value in case multiple ECUs are replying to the request. Possible values are *first* (default value), *last*, or the ECU identifier, for example *7E8*. Values *first* and *last* takes the according ECU reply in alphabetical order.
The above example uses **ecu** to read GM transmission fluid temperature. As typical LS vehicle sends this info from two ECUs (7E8 and 7EA), the **ecu** parameter is used to specify that we want to read the value from ECU 7E8.
### **enum [optional]**
With **enum** parameter, the values in data can be directly interpreted as a text or another value. **enum** is a list of comma separated *value:display value* pairs. For example:
The above example uses **enum** to show shifter position as a character in RealDash. If value is 72, the character '**P**' is shown. If value is 24, the character '**R**' is shown, and so on. The hash tag **#** is used as default value, which in above example would show text **err**.
In addition, **enum** supports a range of values with *tilde* **~** operator. For example:
### **rawReply [optional]**
If **command** section contains attribute **rawReply="true"**, every reply byte, including any header bytes are regarded as data bytes. This allows to use custom commands on which the reply does not follow typical ELM327 reply.
### **keepInRotation [optional] (from RealDash 2.4.2)**
RealDash has a feature that removes commands from the rotation if there is no valid response from the vehicle with multiple attempts on the row. Removing invalid/non-supported PID will help respond faster to other PID requests. **keepInRotation="true"** attribute allows to disable automatic removal of commands from the rotation.
### **Receive multiple values on one command**
It is possible to receive multiple values for one sent command. The individual values are listed in **command** as **values**. The parameters for the **value** are the same as with command with only one target value.
## **How to import customized XML to RealDash**
1. Save your XML file to a place that is accessible from your device running RealDash.
2. Open RealDash Go to Garage, open vehicle door and tap the instrument cluster
3. On the *Connections* list, tap your OBD2 connection.
4. Tap *Select Vehicle* button and then scroll down to find *Custom Channel Description File* and browse to your XML file.
5. Tap the upper left corner *Done* button and exit the Garage.
6. RealDash will reconnect and use your custom XML file for communications.
## **OBD2 communication optimization settings**
RealDash has two settings that may increase the data rate on some vehicles. You can access these settings:
### **Use Multipid Request**
This setting works if you have relatively new vehicle with CAN bus. When this option is enabled, RealDash constructs a *multipid* request command and if supported by vehicle can receive multiple values in one reply. This will considerably increase the data rate. On older vehicles this setting may slow down the time to connect to vehicle and therefore its disabled by default.
### **Request Only First Reply**
On newer vehicles some requested information may be contained in several modules. For example engine RPM may be stored in ECU and TCU of the vehicle. Enabling this option will instruct the adapter to respond with first available value and not wait until all modules have responeded to the request. This may increase the data rate in some cases.
================================================
FILE: OBD2/realdash_obd2.xml
================================================
================================================
FILE: OBD2/realdash_obd2_Itelma_M73_E3.xml
================================================
================================================
FILE: OBD2/realdash_obd2_bosch_mp70.xml
================================================
================================================
FILE: OBD2/realdash_obd2_fiat_precan.xml
================================================
================================================
FILE: OBD2/realdash_obd2_gm_ls.xml
================================================
================================================
FILE: OBD2/realdash_obd2_january_5_1.xml
================================================
================================================
FILE: OBD2/realdash_obd2_mitsubishi_mut.xml
================================================
================================================
FILE: OBD2/realdash_obd2_nissan_generic.xml
================================================
================================================
FILE: OBD2/realdash_obd2_opel_kwp2000.xml
================================================
================================================
FILE: OBD2/realdash_obd2_saab_generic.xml
================================================
================================================
FILE: OBD2/realdash_obd2_toyota_celica_corolla_camry.xml
================================================
================================================
FILE: OBD2/realdash_obd2_toyota_gt86.xml
================================================
================================================
FILE: OBD2/realdash_obd2_toyota_jdm_generic.xml
================================================
================================================
FILE: OBD2/realdash_obd2_toyota_jdm_iso9141.xml
================================================
================================================
FILE: OBD2/realdash_obd2_toyota_rav4_supra_lexus_is.xml
================================================
================================================
FILE: OBD2/realdash_obd2_toyota_vitz.xml
================================================
================================================
FILE: OBD2/realdash_obd2_volvo_noncan1.xml
================================================
================================================
FILE: OBD2/realdash_obd2_volvo_noncan2.xml
================================================
================================================
FILE: README.md
================================================
# **RealDash-extras**
RealDash examples and technical materials
All materials in this repository are licensed with [NoLicense](https://github.com/janimm/RealDash/blob/master/LICENSE)
[realdash.net](https://www.realdash.net)
## **Folders**
### **[Dashboard-animation-examples](./Dashboard-animation-examples/README.md)**
This folder contains description and examples on how to create scripted animations to RealDash dashboards.
### **[OBD2](./OBD2/README.md)**
Folder contains OBD2 related information and default XML files used by RealDash.
### **[RealDash-CAN](./RealDash-CAN/README.md)**
Folder contains RealDash-CAN protocol related information and default XML files used by RealDash.
================================================
FILE: RealDash-CAN/Arduino-examples/README.md
================================================
# **RealDash CAN Arduino examples**
[www.realdash.net](https://www.realdash.net)
First, see information about [RealDash CAN protocol and XML description file](../README.md)
### **RealDash_CAN example**
A simple Arduino sketch that pushes 3 'hand-build' CAN frames from Arduino
into RealDash. CAN frames contain static data for RPM, MAP,
Coolant temperature, and TPS. Next two frames contain the statuses of
Arduino digital and analog pins.
### **RealDash_CAN_2way example**
An extension of first example reads **SET_FRAME** commands from RealDash and sets
Arduino digital and analog pins accordingly.
These examples uses 115200 baud rate as default value. Change the value to
match your serial setup.
### **How to run Arduino Examples**
1. Upload the example sketch into Arduino.
2. Open RealDash and go to 'Garage->Connections' and add new connection.
3. Select 'RealDash CAN'.
4. Next steps select which ever way you connect to Arduino, be it Bluetooth, Serial port, or WiFi. If using serial port, the example sketch uses 115200 baud.
5. For last page, the "Custom Channel Description File", select the 'realdash_can_example.xml'.
6. Tap upper left corner 'DONE' until back in dashboard.
7. Wait for couple of seconds for the Arduino to connect to RealDash.
This folder also includes simple test dashboard 'realdash_can_arduino_test.rd'. If Arduino is uploaded with 'RealDash_CAN_2way' example,
the buttons in dashboard change the digital and some analog pin values in Arduino.
================================================
FILE: RealDash-CAN/Arduino-examples/RealDash_CAN/RealDash_CAN.ino
================================================
/**
* ============================================================================
* Name : RealDash_CAN.ino
* Part of : RealDash
* Author : Jani Immonen
* Created : 15.10.2017
*
* Arduino example sketch of how to use RealDash CAN protocol.
*
* This example code is free for any use.
*
* www.realdash.net
* ============================================================================
**/
// Arduino digital and analog pins
unsigned int digitalPins = 0;
int analogPins[7] = {0};
unsigned int rpm = 0;
unsigned int kpa = 992; // 99.2
unsigned int tps = 965; // 96.5
unsigned int clt = 80; // 80 - 100
unsigned int textCounter = 0;
void setup()
{
// init serial
Serial.begin(115200);
delay(100);
}
void loop()
{
ReadDigitalStatuses();
ReadAnalogStatuses();
SendCANFramesToSerial();
// just some dummy values for simulated engine parameters
if (rpm++ > 10000)
{
rpm = 500;
}
if (kpa++ > 2500)
{
kpa = 10;
}
if (tps++ > 1000)
{
tps = 0;
}
if (clt++ > 230)
{
// all values in frame are handled as unsigned values. To have negative values,
// offset actual value and write corresponding conversion to xml file imported to RealDash
clt = 0;
}
if (textCounter++ > 4000)
{
textCounter = 0;
}
delay(5);
}
void ReadDigitalStatuses()
{
// read status of digital pins (1-13)
digitalPins = 0;
int bitposition = 0;
for (int i=1; i<14; i++)
{
if (digitalRead(i) == HIGH) digitalPins |= (1 << bitposition);
bitposition++;
}
}
void ReadAnalogStatuses()
{
// read analog pins (0-7)
for (int i=0; i<7; i++)
{
analogPins[i] = analogRead(i);
}
}
void SendCANFramesToSerial()
{
byte buf[8];
// build & send CAN frames to RealDash.
// a CAN frame payload is always 8 bytes containing data in a manner
// described by the RealDash custom channel description XML file
// all multibyte values are handled as little endian by default.
// endianess of the values can be specified in XML file if it is required to use big endian values
// build 1st CAN frame, RPM, MAP, CLT, TPS (just example data)
memcpy(buf, &rpm, 2);
memcpy(buf + 2, &kpa, 2);
memcpy(buf + 4, &clt, 2);
memcpy(buf + 6, &tps, 2);
// write first CAN frame to serial
SendCANFrameToSerial(3200, buf);
// build 2nd CAN frame, Arduino digital pins and 2 analog values
memcpy(buf, &digitalPins, 2);
memcpy(buf + 2, &analogPins[0], 2);
memcpy(buf + 4, &analogPins[1], 2);
memcpy(buf + 6, &analogPins[2], 2);
// write 2nd CAN frame to serial
SendCANFrameToSerial(3201, buf);
// build 3rd CAN frame, rest of Arduino analog values
memcpy(buf, &analogPins[3], 2);
memcpy(buf + 2, &analogPins[4], 2);
memcpy(buf + 4, &analogPins[5], 2);
memcpy(buf + 6, &analogPins[6], 2);
// write 3rd CAN frame to serial
SendCANFrameToSerial(3202, buf);
// build 4th frame, this is a text extension frame
// only send once at 1000 loops
if (textCounter == 0)
{
SendTextExtensionFrameToSerial(3203, "Hello RealDash, this is Arduino sending some text data");
}
else if (textCounter == 1000)
{
SendTextExtensionFrameToSerial(3203, "Tomorrow's forecast: Lots of sun and 30 degrees centigate");
}
else if (textCounter == 2000)
{
SendTextExtensionFrameToSerial(3203, "Now Playing: Insert your favorite song info here");
}
else if (textCounter == 3000)
{
SendTextExtensionFrameToSerial(3203, "Message from Arduino: All systems running at nominal efficiency");
}
}
void SendCANFrameToSerial(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 };
Serial.write(serialBlockTag, 4);
// the CAN frame id number (as 32bit little endian value)
Serial.write((const byte*)&canFrameId, 4);
// CAN frame payload
Serial.write(frameData, 8);
}
void SendTextExtensionFrameToSerial(unsigned long canFrameId, const char* text)
{
if (text)
{
// 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 textExtensionBlockTag[4] = { 0x55, 0x33, 0x22, 0x11 };
Serial.write(textExtensionBlockTag, 4);
// the CAN frame id number (as 32bit little endian value)
Serial.write((const byte*)&canFrameId, 4);
// text payload
Serial.write(text, strlen(text) + 1);
}
}
================================================
FILE: RealDash-CAN/Arduino-examples/RealDash_CAN_2way/RealDash_CAN_2way.ino
================================================
/**
* ============================================================================
* Name : RealDash_CAN_2way.ino
* Part of : RealDash
* Author : Jani Immonen
* Created : 15.10.2017
*
* Arduino example sketch of how to use RealDash CAN protocol.
* This example code is free for any use.
*
* www.realdash.net
* ============================================================================
**/
// Arduino digital and analog pins
// digital pin statuses are stored as bits in one variable
unsigned int digitalPins = 0;
// analog pin values are stored in array of ints
int analogPins[7] = {0};
unsigned int rpm = 0;
unsigned int kpa = 992; // 99.2
unsigned int tps = 965; // 96.5
unsigned int clt = 80; // 80 - 100
unsigned int textCounter = 0;
// incoming data
byte incomingFrame[17] = { 0 };
unsigned int incomingFramePos = 0;
// if READWRITE_PINS is defined, the values are read from and written to Arduino
// digital and analog pins.
//#define READWRITE_PINS
void setup()
{
#if defined (READWRITE_PINS)
// set digital pins as outputs
for (int i=1; i<14; i++)
{
pinMode(i, OUTPUT);
}
#endif
// init serial
Serial.begin(115200);
delay(100);
}
void loop()
{
ReadDigitalStatuses();
ReadAnalogStatuses();
SendCANFramesToSerial();
ReadIncomingSerialData();
// just some dummy values for simulated engine parameters
if (rpm++ > 10000)
{
rpm = 500;
}
if (kpa++ > 2500)
{
kpa = 10;
}
if (tps++ > 1000)
{
tps = 0;
}
if (clt++ > 230)
{
// all values in frame are handled as unsigned values. To use negative values,
// offset actual value and write corresponding conversion to XML file imported to RealDash
// From RealDash 1.7.6 its also possible to specify value as signed="true" in XML file.
clt = 0;
}
// simple counter for sending the text frame to avoid sending it too often.
if (textCounter++ > 4000)
{
textCounter = 0;
}
delay(5);
}
void ReadDigitalStatuses()
{
#if defined (READWRITE_PINS)
// read status of digital pins (1-13)
digitalPins = 0;
int bitposition = 0;
for (int i=1; i<14; i++)
{
if (digitalRead(i) == HIGH) digitalPins |= (1 << bitposition);
bitposition++;
}
#endif
}
void ReadAnalogStatuses()
{
#if defined (READWRITE_PINS)
// read analog pins (0-7)
for (int i=0; i<7; i++)
{
analogPins[i] = analogRead(i);
}
#endif
}
void SendCANFramesToSerial()
{
byte frameData[8];
// build & send CAN frames to RealDash.
// a CAN frame payload is always 8 bytes containing data in a manner
// described by the RealDash custom channel description XML file
// all multibyte values are handled as little endian by default.
// endianess of the values can be specified in XML file if it is required to use big endian values
// build 1st CAN frame, RPM, MAP, CLT, TPS (just example data)
memcpy(frameData, &rpm, 2);
memcpy(frameData + 2, &kpa, 2);
memcpy(frameData + 4, &clt, 2);
memcpy(frameData + 6, &tps, 2);
// write first CAN frame to serial
SendCANFrameToSerial(3200, frameData);
// build 2nd CAN frame, Arduino digital pins and 2 analog values
memcpy(frameData, &digitalPins, 2);
memcpy(frameData + 2, &analogPins[0], 2);
memcpy(frameData + 4, &analogPins[1], 2);
memcpy(frameData + 6, &analogPins[2], 2);
// write 2nd CAN frame to serial
SendCANFrameToSerial(3201, frameData);
// build 3rd CAN frame, rest of Arduino analog values
memcpy(frameData, &analogPins[3], 2);
memcpy(frameData + 2, &analogPins[4], 2);
memcpy(frameData + 4, &analogPins[5], 2);
memcpy(frameData + 6, &analogPins[6], 2);
// write 3rd CAN frame to serial
SendCANFrameToSerial(3202, frameData);
// build 4th frame, this is a text extension frame
// only send once at 1000 loops
if (textCounter == 0)
{
SendTextExtensionFrameToSerial(3203, "Hello RealDash, this is Arduino sending some text data");
}
else if (textCounter == 1000)
{
SendTextExtensionFrameToSerial(3203, "Tomorrow's forecast: Lots of sun and 30 degrees centigate");
}
else if (textCounter == 2000)
{
SendTextExtensionFrameToSerial(3203, "Now Playing: Insert your favorite song info here");
}
else if (textCounter == 3000)
{
SendTextExtensionFrameToSerial(3203, "Message from Arduino: All systems running at nominal efficiency");
}
}
void SendCANFrameToSerial(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 };
Serial.write(serialBlockTag, 4);
// the CAN frame id number (as 32bit little endian value)
Serial.write((const byte*)&canFrameId, 4);
// CAN frame payload
Serial.write(frameData, 8);
}
void SendTextExtensionFrameToSerial(unsigned long canFrameId, const char* text)
{
if (text)
{
// 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 textExtensionBlockTag[4] = { 0x55, 0x33, 0x22, 0x11 };
Serial.write(textExtensionBlockTag, 4);
// the CAN frame id number (as 32bit little endian value)
Serial.write((const byte*)&canFrameId, 4);
// text payload
Serial.write(text, strlen(text) + 1);
}
}
void ReadIncomingSerialData()
{
while (Serial.available() > 0)
{
// little bit of extra effort here, since especially Bluetooth connections
// may leave unsent/received data in internal buffer for a long time
// therefore, we cannot be sure that incoming byte stream really starts at
// where we expect it to start.
// read one byte from serial stream
incomingFrame[incomingFramePos++] = Serial.read();
// check the first incoming bytes tag (0x44, 0x33, 0x22, 0x11)
if (incomingFrame[0] != 0x44)
{
// first incoming byte is not 0x44,
// the tag at the beginning of the frame does not match, this is an invalid frame
// just zero the incomingFrame buffer and start expecting first byte again
memset(incomingFrame, 0, 17);
incomingFramePos = 0;
}
if (incomingFramePos >= 17)
{
// frame complete, process it
ProcessIncomingFrame(incomingFrame);
// zero the incomingFrame buffer and start expecting first byte again
memset(incomingFrame, 0, 17);
incomingFramePos = 0;
}
}
}
void ProcessIncomingFrame(const byte* frame)
{
// first four bytes contain set value frame separator bytes, always 0x44,0x33,0x22,x11
// check that first 4 bytes match the tag
if (frame[0] != 0x44 ||
frame[1] != 0x33 ||
frame[2] != 0x22 ||
frame[3] != 0x11)
{
// frame tag does not match, wait for another frame
return;
}
// next four bytes contain set value CAN frame id in little endian form
unsigned long canFrameId = 0;
memcpy(&canFrameId, frame + 4, 4);
// next 8 bytes are the frame data
// ...
// last byte is check byte calculated as sum of previous 13 bytes (ignore overflow)
byte checkByte = 0;
for (int i=0; i<16; i++)
{
checkByte += frame[i];
}
if (frame[16] == checkByte)
{
// checksum match, this is a valid set value-frame:
// the frame payload data is in frame + 8 bytes
HandleIncomingSetValueFrame(canFrameId, frame + 8);
}
}
void HandleIncomingSetValueFrame(unsigned long canFrameId, const byte* frameData)
{
if (canFrameId == 3201)
{
memcpy(&digitalPins, frameData, 2);
memcpy(&analogPins[0], frameData + 2, 2);
memcpy(&analogPins[1], frameData + 4, 2);
memcpy(&analogPins[2], frameData + 6, 2);
#if defined (READWRITE_PINS)
// write digital pins
for (int i=0; i<13; i++)
{
digitalWrite(i + 1, (digitalPins & (1 << i)) ? HIGH : LOW);
}
analogWrite(0, analogPins[0]);
analogWrite(1, analogPins[1]);
analogWrite(2, analogPins[2]);
#endif
}
else if (canFrameId == 3202)
{
memcpy(&analogPins[3], frameData + 0, 2);
memcpy(&analogPins[4], frameData + 2, 2);
memcpy(&analogPins[5], frameData + 4, 2);
memcpy(&analogPins[6], frameData + 6, 2);
#if defined (READWRITE_PINS)
analogWrite(3, analogPins[3]);
analogWrite(4, analogPins[4]);
analogWrite(5, analogPins[5]);
analogWrite(6, analogPins[6]);
#endif
}
}
================================================
FILE: RealDash-CAN/Arduino-examples/realdash_can_example.xml
================================================
================================================
FILE: RealDash-CAN/README.md
================================================
# **RealDash-extras**
[realdash.net](https://www.realdash.net)
## **RealDash CAN protocol**
[See the full specification of RealDash CAN protocol here](./realdash-can-protocol.md).
## **Channel Description File (XML)**
[See the full specification of RealDash CAN XML description file here](./realdash-can-description-file.md).
## **RealDash CAN Arduino examples**
[RealDash CAN Arduino examples](./Arduino-examples/README.md).
================================================
FILE: RealDash-CAN/XML-files/AEM/aem_22_unit1.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/AEM/aem_22_unit2.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/AEM/aem_6_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/AEM/aem_infinity.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Adaptronic/adaptronic_can_full.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Adaptronic/adaptronic_can_simple.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/BMW/BMW335i.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/BMW/BMW_R1200GS_K25_CAN.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/BMW/bmw_siemens_ms42_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Ecumaster/ecumaster_emublack.xml
================================================
-->
================================================
FILE: RealDash-CAN/XML-files/Ecumaster/ecumaster_gps.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Edelbrock/edelbrock_proflo4.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Emerald/emerald_k3_k6.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Emtron/emtron_packet_1.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Flagtronics/flagtronics_can_v0_4.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/GM/gm_ls7_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/GM/gm_ls_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/GM/gm_ls_can_full.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Grayhill/grayhill_touch_encoder.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Haltech/haltech_v2_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Haltech/haltech_v3_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Holley/dominator_and_terminator_x_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Holley/holley_efi_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Holley/sniper_v2_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Life Racing/life_racing_default_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Link/displaylink.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Link/link_dash2pro.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/MaxxECU/maxxecu_default_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Megasquirt/megasquirt_dashmode_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/Megasquirt/megasquirt_realtime_data_broadcasting_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/OBR/obr_euro_8.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/SCS-Delta/scs-delta.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/syvecs/syvecs_default_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/toyota/toyota_corolla_e150.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/toyota/toyota_fj_can.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/tpms/tiremagic_tpms.xml
================================================
================================================
FILE: RealDash-CAN/XML-files/turbolamik/turbolamik_tcu.xml
================================================
================================================
FILE: RealDash-CAN/realdash-can-description-file.md
================================================
# **Channel Description File (XML)**
The RealDash CAN XML file describes how data in CAN frames are interpreted by RealDash.
XML file starts with tag **RealDashCAN** including the file format version **version="2"**. Next in file is a list of **frames**.
## **'baseId' attribute [optional]**
**frames** may optionally contain a attribute **baseId** that is used for the enclosed **frame** tags. Example:
Specifies the **baseId** as 3200 decimal. Any id value in later **frame** is added to the base id. For example, if **frames baseId** is 3200 and it contains a frame with **id** 1, then the frame is considered to have an **id** of 3201.
The **baseId** and the **id** in **frame** can also be specified as hexadecimal value with prefix of **0x**. Example:
## **frame**
**frames** contain a list of **frame** tags. Each **frame** specifies an *id* number for the frame and other optional parameters. Each **frame** also contains a list of **value** tags that describe how data in frame is interpreted and linked to RealDash inputs. An example **frame**:
## **frame 'id' attribute**
Every **frame** must have an **id** number, specified either in decimal or hexadecimal number (with **0x** prefix). Note that if enclosing **frames** have a **baseId** specified, the resulting id number will be **baseId + id**.
or
### **Composite ID support (optional)**
RealDash XML format supports composite IDs where CAN frame contain varying data and a **running** id value to identify the frame. The composite ID is specified as:
* CAN_ID: the frame CAN ID.
* COMPOSITE_ID: Composite ID that is read from frame data.
* COMPOSITE_ID_OFFSET: Offset (in bytes) where Composite ID is in frame data.
* COMPOSITE_ID_LENGTH: Length (in bytes) of the Composite ID in frame data.
---
The above example specifies a frame with CAN ID of 3E8 hexadecimal, composite id of 5533 decimal. Composite id is read from frame data starting from first (0) byte and its length is 2 bytes.
Note that if composite id consists of multiple bytes, it is assumed to be in little endian format. For example, if composite id in CAN frame is in big endian:
CAN frame data: 000007e8: f4 49 db 00 00 00 00 00
The composite id in XML must be defined in little endian by swapping the byte order:
## **frame 'endianness' attribute (optional)**
Each **frame** can optionally specify the *endianness* of how multibyte values are interpreted in frame data. Accepted values for **endianness** are **endianness="big"** or **endianness="little"** (the default setting). The endianness attribute can also be specified individually for each **value**. An example of how to specify all values in frame to be considered *big endian*:
**NOTE:** Until version 2.3.9, RealDash used the word 'endianess' instead of correct spelling of 'endianness'. From version 2.3.9 RealDash accepts both as an attribute name.
## **frame 'signed' attribute (optional)**
Each **frame** can optionally specify the frame values as *signed* to force RealDash to handle the data as signed values. The signed attribute can also be specified individually for each **value**. By default bytes are handled as *unsigned*. An example of how to specify all values in frame to be *signed*:
## **frame 'writeInterval' attribute (optional)**
**writeInterval** attribute is used to specify a case when RealDash is requested to write this frame back to the device on certain interval. The value in **writeInterval** is milliseconds. For example, to specify that RealDash should write frame 0xc80 to CAN once a second, use:
## **frame 'size' attribute (optional)**
Typically CAN frames contain 8 byte payload. When connecting directly to a CAN device with supported [CAN Adapters](http://realdash.net/manuals/supported_can_lin_analyzers.php), a CAN frame may contain less than standard 8 bytes. Also, when using *RealDash CAN* protocol CAN frame may contain up to 64 bytes of payload data. While it is not required to set the **size** attribute when using *RealDash CAN* protocol and frame is larger than 8 bytes, it is a good practise to ensure compatibility with possible CAN FD compatible adapters.
The **size** attribute can be used to specify a custom number (1-64) of bytes contained by CAN frame:
## **frame 'readOnly' attribute (optional)**
Frames can be marked as read only. This assures that frame is not accidently written from RealDash by any malfunctioning or badly configured action. Read only attribute can also be used to prevent circular update when multiple RealDash instances are connected to same CAN bus.
## **frame 'timeout' attribute (optional)**
This attribute allows to set timeout for the frame. Timeout is specified in milliseconds. If CAN frame is not received in specified timeout, all values in the frame will be set to their 'offline' values. This can be used to prevent values for sticking when connection to the CAN bus is lost. For example, 2 second timeout use:
## **values in a frame**
A **frame** contains a list of **value** tags that specify individual values in one frame and how they are interpreted and linked to RealDash inputs. An example of one **value**:
## **value 'targetId' attribute**
This attribute links the received value into RealDash input. The **targetId="37"** writes the received value to RealDash RPM input. Check out full listing of [RealDash targetIds](www.realdash.net/manuals/targetid.php).
## **value 'name' (optional to targetId)**
Instead of mapping the value to existing RealDash input, **name** attribute can be used to create new input into RealDash *ECU Specific* category. Name attribute is used only if **targetId** is not present in command. Example:
Note that above example do not use the **targetId**, but **name** instead. When RealDash reads the XML file, a new custom input is created into *ECU Specific* category called **MYECU: Special RPM**. New custom input can be used like any other input in RealDash for gauges and triggers/actions.
Note: if you make your own dashboard that links into custom inputs, remember that other users need to have same XML available for the dashboard to work correctly. Another solution would be to make the dashboard use [RealDash build-in inputs](www.realdash.net/manuals/targetid.php) and use the *Input Mapping* feature in RealDash *Settings->Units & Values->Input Mapping*.
## **value 'offset' attribute**
**offset** attribute specifies where in frame data the value data begins. Value is specified in bytes. To specify that value data begins from 3rd byte in frame, use **offset="2"**:
## **value 'length' attribute**
**length** attribute specifies how many bytes is used for value data. Combined with **offset** attribute, the corresponding bytes are read as a value. In previous example we read the data beginning 3rd byte of the frame (**offset="2"**) and read 2 bytes (**length="2"**) to form a value:
## **value 'startbit' and 'bitcount' attributes (optional)**
In addition to **offset** and **length** attributes, the **startbit** and **bitcount** can be used to specify from where the value is read in frame data. The **startbit** is the index of the first bit of the value, and **bitcount** is a number of bits used by the value. These can be combined with **offset** parameter, but **bitcount** will override the **length** if present.
## **value 'endianness' attribute (optional)**
Value can optionally specify the *endianness* of how multibyte values are interpreted in value data. Accepted values for **endianness** are **endianness="big"** or **endianness="little"** (the default setting). The endianness parameter can also be specified in enclosing **frame** to apply it to all values. An example of how to specify the value to be considered *big endian*:
**NOTE:** Until version 2.3.9, RealDash used the word 'endianess' instead of correct spelling of 'endianness'. From version 2.3.9 RealDash accepts both as an attribute name.
## **value 'signed' attribute (optional)**
Each **value** can optionally specify the *signed* of the frame values to force RealDash to handle the bytes as signed values. The signed attribute can also be specified in enclosing **frame** to apply it to all values. By default bytes are handled as *unsigned*. An example of how to specify a value to be handled as *signed*:
## **value 'rangeMin' and 'rangeMax' attributes (optional)**
if **name** is used instead of **targetId**, these attributes specify a recommended value range in RealDash.
## **value 'initialValue' attribute (optional)**
If this attribute is present, value is written to CAN after connection has been made to the CAN bus. Examples:
## **value 'conversion' (optional)**
The **conversion** attribute is a formula that is applied to received value. For example, **conversion="V/4"** takes incoming value and divides it by 4 before writing the value to its input. Conversion can be any valid mathematical formula with these variables:
* V (VALUE). This is the value itself, specified by parameters in **value** tag.
* B0 - First byte of the value (reading from left)
* B1 - Second byte of the value
* ...
* B256
* ...
* ID#. Reference to other value where '#' is the RealDash targetId number. [See list of targetIds here](https://realdash.net/manuals/targetid.php)
* 'Custom value name'. Reference to other value where text in single quotas is the value name. This can be used with custom values specified by 'name' attribute.
## **value 'conversionABC' (optional)**
The **conversionABC** is otherwise identical with **conversion**, but bytes are identified with **A,B,C,...,AA,AB,AC,...**, etc. This makes it easier to convert the Equation from other popular apps. For example **conversion="B0+15*(B1-43)"** and **conversionABC="A+15*(B-43)"** produce the same result.
## **Conversion examples**
conversion="V/10"
- result is incoming value / 10
conversion="B0+15*(B1-43)"
- result is first byte + 15 * (second byte - 43)
conversion="ID64+V"
- result is vehicle speed (targetId 64) + incoming value.
conversion="'MYECU: Special RPM'+B1"
- result is value from 'MYECU: Special RPM' + value from second byte.
conversion="V>>6"
- result is value bitshifted 6 to the right.
conversion="V << 3"
- result is value bitshifted 3 to the left.
Note that character '<' is reserved in XML and must be written as <
conversion="V & 15"
- result is value with bitwise AND with 15. In essence, this uses 4 lowest bits of the value.
Note that character '&' is reserved in XML and must be written as &
Available functions:
abs, acos, asin, atan, atan2, ceil, cos, cosh, e, exp, fac, floor, ln, log, log10,
max, min, ncr, not, npr, pi, pow, sin, sinh, sqrt, tan, tanh
Available operators:
=, <, >, !, !=, <>, <=, >=, <<, >>, &&, ||, &, |, +, -, *, /, ^, %, (, )
## **value 'conversionOut' (optional)**
The **conversionOut** attribute is a formula that is applied to a value when its transmitted out from RealDash. Parameters and usage are the same as with **conversion** attribute.
## **value 'units' attribute (optional)**
Optional info to apply automatic unit conversions. Valid values are **units="C"**, **units="F"**, **units="K"**, **units="km/h"**, **units="mph"**, **units="bar"**, **units="psi"**, **units="time"**, **units="bit"**.
If units is set to **bit** the value is considered to be an on/off (0 or 1) valued. RealDash reads the **bit** value from the lowest bit. Therefore there is a need for a bitshift to the right on conversion. For example **conversion="(V>>1)"** will read second bit on incoming value.
The **units="time"** expects a value to be in seconds and its converted into displayable time in RealDash. The GPS Timezone setting in RealDash is applied.
## **value 'float' and 'double' attributes (optional)**
Value can be specified to be IEEE754 4 or 8 byte floating point value:
## **value 'enum' attribute (optional)**
With **enum** attribute, the values in data can be directly interpreted as a text or another value. **enum** is a list of comma separated *value:display value* pairs. For example:
The above example uses **enum** to show shifter position as a character in RealDash. If value is 72, the character '**P**' is shown. If value is 24, the character '**R**' is shown, and so on. The hash tag **#** is used as default value, which in above example would show text **err**.
In addition, **enum** supports a range of values with *tilde* **~** operator. For example:
From RealDash version 2.4.8, the underscore character '_' in enum can be used to completely discard a value:
================================================
FILE: RealDash-CAN/realdash-can-protocol.md
================================================
# **RealDash CAN protocol**
The *RealDash CAN* protocol was designed to easily connect to existing CAN network and transfer the data to RealDash. However, this protocol can also be used with custom and DIY devices.
A single *RealDash CAN* frame uses 8 byte header that specifies the frame identification tag, and CAN frame ID number. The header is followed by frame payload data, and on some frame types the CRC check value.
Three different frame types can be received by RealDash. In all frame types, first 4 bytes identify the frame type. This *tag* is also required for RealDash to 'catch-up' and synchronize on ongoing stream of protocol data.
Each frame payload can contain *any data* in *any arrangement/format*. How data is arranged and how RealDash interprets it is described in XML file that is imported to RealDash connection settings. The RealDash CAN XML description file is explained in detail [here](./realdash-can-description-file.md).
## **The CAN *44* frame**
The *44* frame is a simple, constant size frame that contains 8 byte header and 8 bytes of payload data. Name *44* is from first header byte *0x44* that identifies the frame. This frame type allows easily pass CAN device data to RealDash, just by setting the header and copying the 8 CAN frame bytes.
RealDash CAN '44' frame:
4 bytes - 0x44,0x33,0x22,0x11
4 bytes - CAN frame id number (32bit little endian value)
8 bytes - CAN frame payload (data)
Payload size is always 8 bytes. In case of transferring CAN data with less than 8 bytes, pad the payload with zeroes.
## **The CAN FD *66* frame**
The *66* frame allows to send more than 8 bytes in a single frame and contains 32 bit CRC value. This frame type can be used to transfer [CAN FD](https://en.wikipedia.org/wiki/CAN_FD) frame data, as CAN FD is capable of variable payload size.
RealDash CAN '66' frame:
3 bytes - 0x66,0x33,0x22
1 byte - payload size identifier
4 bytes - CAN frame id number (32bit little endian value)
# bytes - CAN frame payload (data), number of bytes identified by frame 4th byte
4 bytes - CRC32 checksum (32bit little endian value)
4th byte (payload size identifier) in frame header describes the payload size by following table.
| Header 4th byte | payload size (bytes) |
|:--------|:----------:|
| 0x11 | 8 |
| 0x12 | 12 |
| 0x13 | 16 |
| 0x14 | 20 |
| 0x15 | 24 |
| 0x16 | 28 |
| 0x17 | 32 |
| 0x18 | 36 |
| 0x19 | 40 |
| 0x1a | 44 |
| 0x1b | 48 |
| 0x1c | 52 |
| 0x1d | 56 |
| 0x1e | 60 |
| 0x1f | 64 |
----
This frame ends with 4 byte little endian CRC32 checksum value. Checksum is calculated from all frame bytes, except for the CRC value itself. Following function is used to calculate the checksum:
uint32_t Crc32(const uint8_t* data, size_t numBytes)
{
static const uint32_t table[256] = {
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,
0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,
0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,
0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,
0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,
0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,
0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC,
0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,
0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,
0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,
0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,
0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,
0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,
0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE,
0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,
0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,
0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,
0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,
0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,
0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268,
0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,
0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,
0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,
0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,
0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,
0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,
0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,
0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,
0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,
0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,
0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,
0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,
0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,
0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D };
uint32_t crc32 = 0xFFFFFFFF;
for (size_t i = 0; i < numBytes; i++) {
crc32 = (crc32 >> 8) ^ table[(crc32 ^ data[i]) & 0xFF];
}
return (crc32 ^ 0xFFFFFFFF);
}
## **The *55* frame**
The *Text Extension Frame* allows easy transfer of text from device to RealDash. The text payload in this frame must be UTF8 compatible string terminated by 0-byte. A text extension frame contains one, and only one text string. It always consumes the entire frame.
RealDash CAN '55' text extension frame:
4 bytes - 0x55,0x33,0x22,0x11
4 bytes - CAN frame id number (32bit little endian value)
# bytes - text in UTF8 format, including null-terminator
## **The *67* config frame**
Sending of config frames can be enabled from connection settings of RealDash CAN protocol. After connection is established, RealDash will send two config frames to CAN bus containing current CAN settings.
RealDash CAN '67' config frame for CAN speed:
5 bytes - 0x67,0x33,0x22,0x02,0x15
1 byte - CAN speed: 0x01 = 20000, 0x02 = 50000, 0x03 = 100000, 0x04 = 125000, 0x06 = 500000, 0x07 = 800000, 0x08 = 1000000
4 bytes - CRC32 checksum (32bit little endian value)
RealDash CAN '67' config frame for CAN mode:
4 bytes - 0x67,0x33,0x22,0x01
1 byte - CAN mode: 0x11 = normal, 0x12 = loopback, 0x13 = silent, 0x14 = loopback silent
4 bytes - CRC32 checksum (32bit little endian value)
## **Writing CAN frames from RealDash to device**
RealDash sends a *SET VALUE* frame to the connected device when value is updated based on RealDash actions, like buttons or data triggers. RealDash uses two different frames to send data from RealDash. Frames are equivalent of *44* and *66* incoming frames, with the exception that *SET VALUE 44* frame contains single byte checksum.
*SET VALUE 44* frame is always 17 bytes with following layout:
4 bytes - always 0x44,0x33,0x22,0x11
4 bytes - CAN frame id number (32bit little endian value)
8 bytes - CAN frame payload (data)
1 byte - checksum byte (unsigned)
- First 4 bytes are RealDash CAN protocol identification tag.
- Next 4 bytes are CAN frame id number.
- Next 8 bytes are the can frame payload data containing values to write.
- Last byte is a unsigned checksum of preceeding 16 bytes. Checksum value overflow is ignored.
*SET VALUE 66* frame has variable payload size. Frame structure is identical to the *66* frame received by RealDash:
3 bytes - always 0x66,0x33,0x22
1 byte - payload size identifier (same as *66* frame described earlier)
4 bytes - CAN frame id number (32bit little endian value)
# bytes - CAN frame payload (data), number of bytes identified by frame 4th byte
4 bytes - CRC32 checksum (32bit little endian value)