ElectricMotorcycleForum.com

  • November 27, 2024, 08:37:38 AM
  • Welcome, Guest
Please login or register.

Login with username, password and session length
Advanced search  

News:

Electric Motorcycle Forum is live!

Pages: [1] 2 3

Author Topic: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus  (Read 5853 times)

remmie

  • Sr. Member
  • ****
  • Posts: 318
    • View Profile
Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« on: March 10, 2019, 09:47:00 PM »

Impressed with the new dash of the Zero SR/F dashboard with the TFT screen I tried to create a similar screen for my 2018 Zero SR.

Hardware used :
* Adafruit ESP32 Feather (arduino like microcontroller) https://www.adafruit.com/product/3405
* Adafruit 3.5" TFT Featherwing (3.5" display specially tailored for the Adafruit Feather Series https://www.adafruit.com/product/3651
* SKPANG Can-Bus Feather http://skpang.co.uk/catalog/canbus-featherwing-for-esp32-p-1556.html
* OBD-II Cable to Dsub9 connector http://www.hobbytronics.co.uk/obd-ii-db9-cable
* 3D printed housing that secures the unit to my TomTom Rider mount (Self designed and printed)

Special Thanks to user CrashCash in this Thread : http://electricmotorcycleforum.com/boards/index.php?topic=6809.msg56423#msg56423 that gave me the idea to snoop the Canbus en getting me started on most of the CanId's. I found a few more than in this thread and in a following post i will sum up all the CanId's I've found and or used up till now so others can take advantage of it.

Upside of this project is that i don't need the Zero App any more to display some data i like to know during a ride.
Downsides are there is a heep of information on the screen now so distraction lurks :) and the display is nowhere near waterproof but i don't ride in the rain anyways.

This first (and second) post will probably be updated as i find more CanId's and their information

I've only ridden with this dash for 1 ride now, but it works very well. The speed and the colored "speed ring" update every 0.1 seconds and the other values every 0.5 seconds. This is more than fast enough. Sunlight glare is an issue so you have to position the display so the reflection of the display doesn't project the sky but it projects your body, that way the display stays readable.

I also introduced a few additional values by calcualtions from some of the gahtered values:
* Stint Time and Kilometers
* surplus Range. Which is the extra range i have left compared to a 150 km run using the Trip 1 meter. 150 km is an "average range" i want to get during a longer tour. so if the trip 1 reads 50 and the range is 120 kilometers the surplus is (150-120+50 = 20 kilometers.
* battery cell voltage. By dividing the Total battery voltage with 28 you get the individual cell voltage. It is not critical information but is easier to understand than what 102 Volt for the entire pack is.
* by using the Amps in and out of the pack I have made a "Coulomb Counter" to see if I can make the SOC "Guess-O-Meter" a bit more accurate. The 2018 14.4 kWh pack is supposed to have 124Ah of energy in it, so with this gauge I hope to get the actual SOC better.

To Do :
* To make the base for the surplus range adjustable through the touchscreen. This would allow me to make a route to the next charging station on the TomTom and set the surplus range calculator value to the kilometers to go of the TomTom. That way i only have to keep the surplus positive to be able to get there. (it avoids constant calculations in your head : Am i gonna make it, i have 54 km and the range is 65 so I have eeeeeh 11 km Surplus. and a minute later the same calculation with 52 and 61 km which yields only 9 kilometers surplus)
* to make a 3D printed housing that exactly covers the existing Dash.

Any other idea's you guys (and girls) have ??

P.S. I'm not writing anything to the Canbus, I'm just snooping values of it. Also i use the ODB connector which is accesable under the seat, So i don't have to cut into the wiring harness in any way.

Forgot to mention that the ESP32 has both bluetooth and WIFI capabilities, a 240 Mhz DUAL CORE processor so there is a LOT to explore there :)
« Last Edit: March 11, 2019, 03:08:37 AM by remmie »
Logged
Current : Red Premium Zero SR/F (ordered May 25, delivered August 23 2019) with Rapid charger for 12kW charging
Former : White Zero SR 2018 ZF14.4 kWh (17.500 km)
Former : Black Zero SR 2014 ZF11.4 kWh (25.000 km)
SR's outfitted with Homemade "Supercharger" 6x eltek Flatpack S (12 kW)

remmie

  • Sr. Member
  • ****
  • Posts: 318
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #1 on: March 10, 2019, 09:47:21 PM »

CanID's (and a picture of the startup screen :)

Here's a snippet of my Arduino Code where the CanId's are converted to values

   if (canId == 0x0188)
   {
      SOC2 = buf[0];                                                                       
      // ?? byte 1 (always 0)
      // ?? byte 2 (always 66, but 3 while charging in another session)
      ChargeCycles = buf[3] + 256 * buf[4];                                                   // byte 3 is number of charge cycles (probably byte 4 as well (highbyte)
      CellBalance = buf[5];                                                                   // byte 5 could be Cel Balance value
      // ?? byte 6 (always 0)
      // ?? byte 7 (always 4 maybe number of bricks ?)
   }
   if (canId == 0x01C0)
   {
      // ?? byte 0 (fixed at 32)
      // ?? byte 1 (fixed at 0)
      DashTimeHours = buf[2];                                                              // byte 2 is Dash Time Hours
      DashTimeMinutes = buf[3];                                                            // byte 3 is Dash Time Minutes
      DashTimeSeconds = buf[4];                                                            // byte 4 is Dash Time Seconds
      NumberOfCanMessageSets = buf[5] + 258 * buf[6] + 256 * 256 * buf[7];                 // byte 5 - 7 is number of canbus message SETS received since power on ??
   }

   if (canId == 0x0206)                                                                // this canID only appears during charging !!
   {
      // ?? byte 0 (batterypack temperature ??)
      // ?? byte 1 (fixed at 2 during charging)
      ChargerVoltage = buf[2] * 0.001 + buf[3] * 0.256 + buf[4] * 65.535;              // byte 2-3-4 Charger voltage in mV (division by 1000 gets Volts)
      // ?? byte 5 (fixed at 1)
      // ?? byte 6 (fixed at 0)
      // ?? byte 7 (fixed at 0)
   }

   if (canId == 0x240)
   {
      if (bitRead(buf[0],2) == 1) Mode = "Sport ";         //A5                                        // CanID 0x0240 byte 0 = Mode
      if (bitRead(buf[0],3) == 1) Mode = "Eco   ";        // A9
      if (bitRead(buf[0],4) == 1) Mode = "Custom";     // B1
      // ?? byte 1 = always 0F : unknown
      Speed = (buf[2] * 0.01) + (buf[3] * 2.56);                                          // byte 2 and 3 is Speed in kph
      PowerBar = buf[4];                                                                  // ?? byte 4 is Power bar on dash ?? (It is power related)
      TorqueBar = buf[5];                                                                 // ?? byte 5 is Torque bar on dash ?? (It is Torque related)
      SOC = buf[6];                                                                       // byte 6 is State Of Charge on dash in %
      // no Byte 7
   }
   if (canId == 0x0281)
   {
      MotorRPM = buf[0] + 256 * buf[1];                                                // ?? byte 0, 1 is motor RPM (same as canID 0x0340 byte 4 and 5)
      // ?? byte 2 (fixed at 0)
      // ?? byte 3 (fixed at 0)
      ThrottlePosition = buf[4] + 256 * buf[5];                                        // ?? byte 4, 5 is throttle position (around 125 is closed, aroud 1200 is fully open)
      MotorTemp = buf[6];                                                              // ?? byte 6 is motor temperature (second time) this time in 1 byte , not 2 as in canid 440
      // ?? byte 7 (fixed at 0)
   }
   if (canId == 0x0288)
   {
      Power = buf[0] + 256 * buf[1];                                                      // byte 0, 1 Power in Watts
      // ?? byte 2 (fixed at 231)
      // ?? byte 3 (fixed at 0)
      // ?? byte 4 (fixed at 50)
      // ?? byte 5 (fixed at 114)
      // ?? byte 6 (fixed at 0)
      // ?? byte 7 (fixed at 18 not any temperature))
   }

   if (canId == 0x340)
   {
      Trip1 = buf[0] * 0.01 + buf[1] * 2.56;                                              // byte 0, 1 is Trip 1
      // ?? byte 2 (always 0)
      // ?? byte 3 (always 0)
      RPM =  buf[4] + 256 * buf[5];                                                       // byte 4, 5 is motor RPM
      ErrorCode = buf[6];                                                                 // byte 6 (error code on dash, 44 is killswitch, 45 is kickstand etc)
      // ?? byte 7 (always 0)
   }

   if (canId == 0x0381)
   {
      // ?? byte 0
      // ?? byte 1
      ControllerTemp = buf[2];
      // ?? byte 3
      // ?? byte 4
      // ?? byte 6
      // ?? byte 7
   }


   if (canId == 0x0388)
   {
      // ?? byte 0 (very random ?? 0-25 when speed = 0 , goes higher/lower when powering or regen)
      // ?? byte 1 (very reandom ?? 246-248 when speed = 0, goes higher/lower when powering or regen)
      // ?? byte 2 (always 15)
      Vbatt = 0.001 * buf[3] + 0.256 * buf[4] + 65.535 * buf[5];                          // byte 3, 4 and 5 are Vbatt in units of mV (divide by 1000 to get Volts)
      // ?? byte 6 (always zero)
      // ?? byte 7 (increases with torque/power and is negative with regen : could be power/torque/battery or motor amps
   }

   if (canId == 0x0408)
   {
      // byte 0
      BatteryTemp = buf[1];                                                               // byte 1 is battery temp in celcius
      // byte 2 (same as byte 1) could be second temp sensor ?? needs change in battery temp)
      BatteryAmps = buf[3] + 256 * buf[4];                                                // byte 3 battery amps, both when charging and
      // byte 5 (fixed at 131)
      // byte 6 (fixed at 0)
      // byte 7 (fixed at 255)
   }

   if (canId == 0x0440)
   {
      Trip2 = buf[0] * 0.01 + buf[1] * 2.56;                                              // byte 0, 1 is Trip 2 in units of 10 mtrs (divided by 100 to get KM)
      // byte 2 (fixed at 0)
      // byte 3 (fixed at 0)
      Range = buf[4] * 0.01 + buf[5] * 2.56;                                              // byte 4, 5 is range in units of 10 mtrs (divided by 100 to get KM)
      MotorTemperature = buf[6] * 0.01 + buf[7] * 2.56;                                   // byte 6, 7 is motortemperature in 0.01 degrees but only 2200, 2300, 2400 (divsion by 100 is immediate integer value)
   }
   if (canId == 0x0508)
   {
      // ?? byte 0,1 ,2 are number of seconds used or maybe even lifetime possibly bytes 3 and on also included (at feb-2019 bytes are (xxx,223,114,92,10,0,75,0)
      // ?? byte 1
      // ?? byte 2
      // ?? byte 3
      // ?? byte 4
      // ?? byte 5
      // ?? byte 6
      // ?? byte 7
   }
   if (canId == 0x02C0)
   {
      ODO = 0.1 * buf[0] + 25.6 * buf[1] + 6553.5 * buf[2];                               // byte 0, 1 and 2 are ODO in units of 100 mtrs (divided by 10 to get KM)
      // ?? byte 3 (fixed at 0)
      // ?? byte 4 (fixed at 0)
      // ?? byte 5 (fixed at 0)
      // ?? byte 6 (fixed at 16)
      // ?? byte 7 (fixed at 0)
   }
}
« Last Edit: March 10, 2019, 10:40:02 PM by remmie »
Logged
Current : Red Premium Zero SR/F (ordered May 25, delivered August 23 2019) with Rapid charger for 12kW charging
Former : White Zero SR 2018 ZF14.4 kWh (17.500 km)
Former : Black Zero SR 2014 ZF11.4 kWh (25.000 km)
SR's outfitted with Homemade "Supercharger" 6x eltek Flatpack S (12 kW)

NEW2elec

  • Hero Member
  • *****
  • Posts: 2659
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #2 on: March 11, 2019, 12:26:08 AM »

Niiiccce!
Logged

alko

  • Sr. Member
  • ****
  • Posts: 376
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #3 on: March 11, 2019, 12:53:38 AM »

I wish I had your brain!
Until that happens, I'd just like to be able swap out my 2017 DSR dash out for the sr/F dash.
« Last Edit: March 11, 2019, 12:57:37 AM by alko »
Logged

GrantMeStrength

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #4 on: March 11, 2019, 01:28:58 AM »

Brilliant! Where/how do you tap into the CANBUS data?
Logged

BrianTRice@gmail.com

  • Unofficial Zero Manual Editor
  • Hero Member
  • *****
  • Posts: 4014
  • Nerdy Adventurer
    • View Profile
    • Personal site
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #5 on: March 11, 2019, 02:11:33 AM »

Great work, and thanks for documenting your findings! I’ll try to have a deeper look later but this means a lot for increasing the visibility of the system state.
Logged
Current: 2020 DSR, 2012 Suzuki V-Strom
Former: 2016 DSR, 2013 DS

remmie

  • Sr. Member
  • ****
  • Posts: 318
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #6 on: March 11, 2019, 02:54:08 AM »

Brilliant! Where/how do you tap into the CANBUS data?

Under the seat there is a OBD-II Connector. By using a OBD to Dsub cable (4th item in the hardware list) the canbus is available on pins 3 (Can-high) and pin 5 (Can-Low) and pin 2 (Can GND)

Because the Featherwing display and the ESP 32 Feather and the Canbus Featherwing all have the same pinout and can be stacked there is just a little bit of basic soldering to do before the programming starts. In the picture you can see how the inside of the box looks like

Pin Description       OBDII         DB9
J1850 BUS+         2            7
Chassis Ground         4            2
Signal Ground         5            1
CAN High J-2284      6            3
ISO 9141-2 K Line    7            4
J1850 BUS-         10            6
CAN Low J-2284       14            5
ISO 9141-2 L Line    15            8
Battery Power         16            9

So the canbus is the J-2284 bus


« Last Edit: March 11, 2019, 03:00:29 AM by remmie »
Logged
Current : Red Premium Zero SR/F (ordered May 25, delivered August 23 2019) with Rapid charger for 12kW charging
Former : White Zero SR 2018 ZF14.4 kWh (17.500 km)
Former : Black Zero SR 2014 ZF11.4 kWh (25.000 km)
SR's outfitted with Homemade "Supercharger" 6x eltek Flatpack S (12 kW)

neographikal

  • Newbie
  • *
  • Posts: 13
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #7 on: March 11, 2019, 06:22:37 AM »

Nice work :) You could make a github repo for this, that would be helpful. :)

Also thinking about a project like this, in doubt whether I'm going the canbus route of the serial route, but I don't know if the serial is active during charging yet. My main goal is to control the charging by my domotica so the bike doesn't always charge to 100%. So report SOC and some other stuff through lora/wifi (if available) to Home Assistant and then control a relay.
Logged

GrantMeStrength

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #8 on: March 11, 2019, 08:17:07 AM »

Brilliant! Where/how do you tap into the CANBUS data?

Under the seat there is a OBD-II Connector. By using a OBD to Dsub cable (4th item in the hardware list) the canbus is available on pins 3 (Can-high) and pin 5 (Can-Low) and pin 2 (Can GND)


Thanks!
Logged

BrianTRice@gmail.com

  • Unofficial Zero Manual Editor
  • Hero Member
  • *****
  • Posts: 4014
  • Nerdy Adventurer
    • View Profile
    • Personal site
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #9 on: March 11, 2019, 09:52:46 PM »

Re: GitHub, there is an organization I'd be glad to invite you to, which hosts forks or original repos for posterity and maintenance:
https://github.com/zero-motorcycle-community
Logged
Current: 2020 DSR, 2012 Suzuki V-Strom
Former: 2016 DSR, 2013 DS

remmie

  • Sr. Member
  • ****
  • Posts: 318
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #10 on: March 19, 2019, 08:06:22 PM »

Second iteration with a 3d printed housing which covers the original dash.
Also some improvements in the value and now includes a 0-100 kph meter :)

I’look into github to upload the entire code into the zero motorcycles section you pointed out Richard, thanks.

Today was the first ride with this new dash. Very good visibility for the speed. All other values like temperatures, voltages, distances and times are very nice to see.

Still to do is proper weatherproofing :) for the occasional rain shower we have here in the netherlands

Another thing added is the errorcodes and their (short) explanations are now also shown at the top
« Last Edit: March 19, 2019, 08:08:27 PM by remmie »
Logged
Current : Red Premium Zero SR/F (ordered May 25, delivered August 23 2019) with Rapid charger for 12kW charging
Former : White Zero SR 2018 ZF14.4 kWh (17.500 km)
Former : Black Zero SR 2014 ZF11.4 kWh (25.000 km)
SR's outfitted with Homemade "Supercharger" 6x eltek Flatpack S (12 kW)

BrianTRice@gmail.com

  • Unofficial Zero Manual Editor
  • Hero Member
  • *****
  • Posts: 4014
  • Nerdy Adventurer
    • View Profile
    • Personal site
Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #11 on: March 19, 2019, 09:40:28 PM »

Very nice progress! I wonder whether a board with a premade weatherproof enclosure is available to program similarly.

I found that there are at least some tidy printable solutions like:
https://learn.adafruit.com/3d-printed-case-for-adafruit-feather/tft-feather-wing
« Last Edit: March 19, 2019, 09:50:45 PM by BrianTRice »
Logged
Current: 2020 DSR, 2012 Suzuki V-Strom
Former: 2016 DSR, 2013 DS

NEW2elec

  • Hero Member
  • *****
  • Posts: 2659
    • View Profile
Logged

remmie

  • Sr. Member
  • ****
  • Posts: 318
    • View Profile
Logged
Current : Red Premium Zero SR/F (ordered May 25, delivered August 23 2019) with Rapid charger for 12kW charging
Former : White Zero SR 2018 ZF14.4 kWh (17.500 km)
Former : Black Zero SR 2014 ZF11.4 kWh (25.000 km)
SR's outfitted with Homemade "Supercharger" 6x eltek Flatpack S (12 kW)

pacificcricket

  • Sr. Member
  • ****
  • Posts: 293
    • View Profile
Re: Zero SR/F Dashboard on a Zero (D)S(R) using CanBus
« Reply #14 on: April 08, 2019, 03:29:49 AM »

A few general recommendations regarding your code...

Use a switch statement, something like :

Quote
switch(canId) {

  case 0: break;
  case 0x0181: {
           memcpy(canID181, buf, 8);
           break;
     }
  case 0x0188: {
   // .....
       break;
     }
}
 

Define macros for common expressions. Instead of

Quote
      outerRingColor = ((0 >> 3) << 11) | ((128 >> 2) << 5) | (0 >> 3);
      innerRingColor = ((0 >> 3) << 11) | ((255 >> 2) << 5) | (0 >> 3);

Do something like :

Quote
#define COLOR_X  (((0 >> 3) << 11) | ((128 >> 2) << 5) | (0 >> 3))
#define COLOR_Y (((0 >> 3) << 11) | ((255 >> 2) << 5) | (0 >> 3))

outerRingColor = COLOR_X;
innerRingColor = COLOR_Y;

Same for parameterized ones.

Quote
BatteryAmps = buf[3] + 256 * buf[4];

Becomes :

Quote
#define MAGIC(buf,x,y) ( buf[ x ] + 256 * buf[ y ])

BatteryAmps = MAGIC(buf, 3, 4);


And minor style things like

Quote
NumberOfCanMessageSets = buf[5] + 258 * buf[6] + 256 * 256 * buf[7];

to :

Quote
NumberOfCanMessageSets = buf[5] + (258 * buf[6]) + (256 * 256 * buf[7]);

Obviously no change in arithmetic precedence, but the reader clearly understands the intent and bugs will less likely sneak in

Quote
ChargerVoltage = buf[2] * 0.001 + buf[3] * 0.256 + buf[4] * 65.535;

I'd refactor that to use integer arithmetic, especially since your result is a long. This is both to reduce loss in precision and account for possibility of emulated floating point arithmetic.



 
« Last Edit: April 08, 2019, 03:34:49 AM by pacificcricket »
Logged
Pages: [1] 2 3