-
Originally Posted by IdahoMtnSpyder
OK, your .pl address did reject the zip file. Let me know if the .eu one comes through.
Thank you again. This is huge help.
I already see there is a difference in message id between my model 2011 and yours 2014.
What is probably the same: TCM (0x220, 0x222), SAS (0x0C3)
Difference: YRS (mine 0x303, yours I don't know
VCM is sending 0x230, 0x430 and 0x020, but I don't see 0x580 and 0x581 (might be before log started)
Because of difference in YRS sensor data (which is used by ABS) it is possible that moving ABS/VCM unit from newer model to older might require installing newer YRS as well.
ABS, 3xVSS, YRS and SAS are linked together in one system. Probably newer ABS unit will not be able to read old YRS data (0x303).
0x330 - resposible for DPS, always sends same data which means that torque values are in different message.
I've tried to analyze all messages and I came up with 3 different messages (0x122, 0x150, 0x343) and one of them might be DPS torque sensor data.
To indicate precisely which one is from DPS I would need to understand how DPS works. Basically, when DPS motor is turned on and how it feels on steering.
I would expect that DPS will turn the assistance when torque is sensed, and it will try to minimize torque required to steer left or right. This would mean that I will see spike in torque applied, steering angle starts to change
and afterwards torque starts to get lower when DPS assistance is turned on. I don't see that unfortunately.
What I see is that within timespan of 12s steering is moved to right, left, right left and so on.
Data which looks like torque (0x150) changes in first 4s and later is mostly the same.
There is one bit in 0x150 which changes after 0,5s when steering is sensed, and after 2s it is back to old state.
IdahoMtnSpyder - are you able to say when DPS assist is turned on?
It would be interesting to see how my VCM will behave when I will introduce 0x150 in my CAN bus.
-
Very Active Member
My nephew has a 2010 RT. I'll see if I can get him to let me record what his machine does. My understanding of the DPS is the amount and timing of the assist depends on what the torque sensor detects for turning torque. That may be tough to measure while the bike is parked and running. It's winter time so I won't be able to record anything while I'm riding until about March or
April.
2014 Copper RTS
Tri-Axis bars, CB, BajaRon sway bar & shock adjusters, SpyderPop's Bumpskid, NBV peg brackets, LED headlights and modulator, Wolo trumpet air horns, trailer hitch, custom trailer harness, high mount turn signals, Custom Dynamics brake light, LED turn signal lights on mirrors, LED strip light for a dash light, garage door opener, LED lights in frunk, trunk, and saddlebags, RAM mounts and cradles for tablet (for GPS) and phone (for music), and Smooth Spyder belt tensioner.
-
No need to go that far and make further recordings. I already have lots of data to analize.
My question was about how do you "feel" DPS is working and if it works instantly from the start, but I think I know the answer and I should make deeper analysis.
I will get back to this topic later. Now I need to prepare everything for inspection and first registration.
-
-
I don't have cable for glove box, but I have cable for front trunk which will be made by me. So I used front trunk cable for glove box. It is a bit short and needs to be carefully placed under glove box, but it works.
I've had to add proper ending for cable (universal cable end) to keep it in place.
-
While I was working on cables I added trunk latch from minicooper (10$) which already has electric actuator.
Again, some modifications needs to be done and universal ending for cable is used to make it work.
-
-
Same problem with belt cover. Broken in half. Welded on both sides, additional weld inside to make part stronger and 100, then 200 grit sandpaper on "visible" surface.
-
-
-
-
That looks fantastic already. Well done sir.
-
Very Active Member
Originally Posted by megagame
My question was about how do you "feel" DPS is working and if it works instantly from the start, but I think I know the answer and I should make deeper analysis.
My experience is that about the only time you can tell when DPS is working, is when it is not! The application of assistive torque is so smooth and gradual, and variable, there is no way to detect by feel when and if the DPS is assisting. I'm going to guess that as you go around a curve the torque the rider applies to the handlebar is maybe 30 to 40% of the total turning torque. At the start of a turn the torque is close to zero so the DPS adds zero torque. But as the torque requirement goes up, the amount added by the DPS goes up. When the DPS in my 2013 RT was acting up, and kicking in and out, I could really tell when it kicked in. If I was in a hard turn, like a freeway exit loop, and the DPS wasn't working, and then all of a sudden it did start working, the extra torque I was applying to the handlebar would make me suddenly turn so much I almost went off the road to the inside of the curve. A DPS that kicks in and out can actually be dangerous.
Hope this helps.
2014 Copper RTS
Tri-Axis bars, CB, BajaRon sway bar & shock adjusters, SpyderPop's Bumpskid, NBV peg brackets, LED headlights and modulator, Wolo trumpet air horns, trailer hitch, custom trailer harness, high mount turn signals, Custom Dynamics brake light, LED turn signal lights on mirrors, LED strip light for a dash light, garage door opener, LED lights in frunk, trunk, and saddlebags, RAM mounts and cradles for tablet (for GPS) and phone (for music), and Smooth Spyder belt tensioner.
-
Thanks. This means it will be hard to determinate precisely algorithm responsible for amount of assist. But, it sure works all the time when torque is applied.
-
Very Active Member
megagame, thank you for this! I really enjoy the reading and all the sweat you've put into this old spyder plus keeping all of us up to date.
I have my fingers crossed that it will be a success, But from what you've shown us I don't think you need any luck.
Team effort
-
-
Very Active Member
New to Sue and I
2021, LTD, Asphalt Gray, 22,000 miles
Gone but not forgotten
RTS 2011 SM5, 95,000 miles
-
So, winter has ended and finally it started to get warmer here where I live.
I didn't touch the issue regarding programming the bypass for ABS. This topic is a little bit bigger because of modifications in braking system. I'm planning to have front brake lever on handlebar and both brakes working in foot brake. All parts are already waiting to be installed but I'm working on something else now.
Since I didn't have some smaller parts, I've started designing them in Fusion 360 and learn 3d printing with PETG.
First, I've designed handle for trunk hood. Printing it took around 18h. Fortunately everything was measured correctly, and I've only had to drill holes in correct places.
Now I'm working on base plate and front shield for my custom mirrors which are coming from 90s Fiat Uno :P.
I've had to print 4 base plates, and modify the model slightly after each print, before final version was (almost) perfectly aligned. I still have to design front guard on which I will place front blinkers.
Base plate is gray, but guard will be pearl gold. Maybe I will print base plate again if it will not look good, or I will put carbon fiber skin on it - I have some laying around.
Oh, and finally my seat is working correctly. I've made new bracket to hold it in place.
Back is also almost finished. I still need to design base plates for blinkers which will be on covers for side cases, but mirrors are most important now. Once this is finished finally I'll be able to register the bike and go for a short ride.
Last edited by Peter Aawen; 07-13-2023 at 02:29 AM.
Reason: Fixed attach display ;-)
-
Very Active Member
WOW, you are doing an amazing job. Looks good. Keep us posted.
New to Sue and I
2021, LTD, Asphalt Gray, 22,000 miles
Gone but not forgotten
RTS 2011 SM5, 95,000 miles
-
-
I know there are people out there that switch to Rotax engines on their Ultralight aircraft. They buy used Rotax snowmobile engines to do this. Some make harnesses that do away with most of the electronic crap the snowmobiles have on them. Just a thought.
-
Active Member
Originally Posted by megagame
I've bought this one for 2,5k USD. My goal was to keep within 5k USD but ABS unit did not allow that.
To be honest when I bought this spyder I didn't know how many things could fail because of bad engineering. Normally I don't use cars/bikes with too much electronics. I have older Hilux, Honda from 93 and old bikes like KLX 650 from 94. They all run great. If something happens you can fix them with simple tools. This is not the case with spyder and this is bad judgement from my side. But, I still want to learn how things are done and want to be first to fix problems which are giving people headache.
Also, I hate when things (expensive and cheap) are thrown to garbage.
Looks great on you!!!! Well done!
Who says that you have to have a reason besides just wanting to do it. You will learn a lot and from a completely different viewpoint than 99.9 % of the rest of us.
Keep up the great work!
Tim
Current - 2010 Spyder RTS
1) Experience is something you don't get until after you need it.
2) A closed mouth gathers no foot.
3) IF YOU DON'T HAVE TIME TO DO IT RIGHT, WHEN WILL YOU HAVE TIME TO DO IT OVER??
___
Horsepower is an illusory mathematical equation; Torque is REAL, and is the source of all good things in the world.
The problem is not the problem. The problem is your attitude about the problem. Do you understand?
Please check out my pics!!
-
Very Active Member
Incredible work and great attention to detail.
I will be watching for further reports.
Cheers, David C.
David C
2016 F3T
DIY Garage Door Opener & GPS Mount
Battery tender cable
Rear IPS Pack Rack
-
I've been busy with another project for some time, but fortunately I've had free 2 weeks to analyze all can bus communication with my software which makes Man in the middle attack on bus communication. With that these are the results for older RT:
message |
constant |
device |
module |
comment |
b0 |
b1 |
b2 |
b3 |
b4 |
b5 |
b6 |
b7 |
example |
020 |
|
VCM |
|
|
bits informing about error in module: vss, vss, -, abs, no parking brake |
default 00, different number if error exists |
|
|
|
|
|
|
00 00 FF FF 00 00 00 00 |
0C3 |
|
steering angle sensor |
|
|
|
|
|
|
|
|
|
|
02 01 81 01 00 00 00 01 |
102 |
|
ECM |
|
|
rpm / 64 |
something related to RPM |
|
engine temp from -60*C |
ambient temp from -60*C |
kPa * 2 (max 126 kPa) |
counter |
crc8 |
|
103 |
|
ECM |
throttle lever |
first byte is throttle lever value 00-FF, rest is empty |
|
|
|
|
|
|
counter |
crc8 |
|
120 |
|
ECM |
|
|
|
|
|
|
|
|
|
|
|
220 |
yes |
TCM |
|
|
|
|
|
|
|
|
counter |
crc8 |
0B FE FE FF FE 02 0C 04 |
222 |
|
TCM |
|
have only two values |
|
|
|
|
|
|
|
|
|
230 |
|
VCM |
|
ABS speed values |
|
|
|
|
b5 continuation |
km/h * 10 |
|
|
|
300 |
yes |
ECM |
|
|
|
00 -> D3 after moto start |
|
|
|
|
|
|
00 00 FF FF 00 00 00 00 |
303 |
|
YRS |
|
|
|
|
|
|
|
counter |
|
|
|
308 |
|
ECM |
|
|
bits: low bat, -, -, -, engine hi temp, -, oil switch |
|
|
|
|
|
|
|
|
310 |
|
ECM |
|
|
gears: 1-6, 7 neutral, 8 reverse |
changes to 2 when there is ABS pressure and 3 when BLS engages |
|
|
|
|
counter |
crc8 |
|
330 |
|
DPS |
|
|
|
error code, 99 99 - no error |
|
|
|
|
counter |
crc8 |
|
340 |
|
left buttons |
|
|
|
bits: up, down, left, right, menu, set, fron button (com?) |
|
bits: windshield up, windshield down |
bits: gear up, gear down |
|
|
|
|
341 |
|
|
|
one time after cluster is connected but probably not cluster itself, more like buttons |
|
|
|
|
|
|
|
|
|
342 |
|
ECM |
|
|
|
|
|
probably vsm error, shows 40 6c after 5s when vcp reports 4044 (C0044) |
|
|
|
|
|
400 |
|
CLUSTER |
|
byte 6: value from 1 to 3 after parking brake sensor is "closed". BUDS shows that parking brake sensor is "closed" even without cluster so there must be conneciton to sensor in more than one place |
|
|
|
|
|
|
counter |
crc8 |
|
401.0 |
|
CLUSTER |
|
probably time after system energized |
0 |
ss (in hex not dec) |
mm (in hex not dec) |
hh (in hex not dec) |
|
|
|
|
|
401.1 |
|
CLUSTER |
|
|
1 |
|
|
|
|
|
|
|
|
401.2 |
|
CLUSTER |
|
total distance, m/10 on four bytes |
2 |
dist b3 |
disc b2 |
dist b1 |
dist b0 |
|
|
|
|
401.3 |
|
CLUSTER |
|
trip a |
3 |
|
|
|
|
sec/10, higher bits |
sec/10, lower bits |
|
|
401.4 |
|
CLUSTER |
|
trip b |
4 |
|
|
|
|
sec/10, higher bits |
sec/10, lower bits |
|
|
401.5 |
|
CLUSTER |
|
|
5 |
|
|
|
|
|
|
|
|
401.6 |
|
CLUSTER |
|
|
6 |
|
"ACS level:
0011 1110 lowest
0110 1100
1001 1010
[1100 1000
1111 0110 highest" |
ACS height, higher bits |
ACS height, lower bits |
|
|
ACS buttons, 32/16/8 -> not pressed/down/up |
|
402 |
|
LCD |
|
shown after lcd is ready, probably required for starting the motor |
|
|
|
|
|
|
|
|
|
430 |
|
VCM |
|
contains brake pressure value (ss ss 00 00 3E 01 0x 3x where 3e rises with pressure, ss ss - 99 99 default, otherwise error code np. 40 44) |
|
|
|
|
|
|
counter |
crc8 |
|
460 |
|
PBM |
|
|
|
|
|
|
|
|
|
|
|
514 |
|
CLUSTER |
|
|
|
|
|
|
|
|
|
|
|
515 |
yes |
|
|
|
|
|
|
|
|
|
|
|
|
516 |
|
ECM |
|
|
|
|
|
|
|
|
|
|
|
580,581 |
|
VCM |
|
only once when VCM is starting |
|
|
|
|
|
|
|
|
|
591 |
|
LCD |
|
shown after menu is pressed, probably required for starting the motor |
|
|
|
|
|
|
|
|
|
0x713 CLUSTER tx - removing active errors 04 03 14 00 00 00 00 00 14 - function
0x71C WMP tx - removing active errors 0D 03 14 00 00 00 00 00
0x710 ECM tx - removing active errors 01 03 14 00 00 00 00 00
0x715 VCM tx - removing active errors 06 03 14 FF 00 00 00 00
0x717 probably ECM tx - removing active errors 06 03 14 00 00 00 00 00
0x715 VCM tx - active error cchanged to occured 06 02 10 89 00 00 00 00 this one must be present with next one
0x715 VCM tx - active error cchanged to occured 06 02 10 81 00 00 00 00
Last edited by megagame; 05-05-2023 at 04:38 AM.
-
05-04-2023, 05:19 AM
#100
With information above I've succesfully finished my first trip yesterday without any errors and in fact without ABS, DPS and with my own LCD in cluster -> no limp mode off course .
Without nanny this is a drift beast. TBH it's better for drifting than normal riding. For uneven roads it's constantly a bit wobbly with passanger present. For drifting it's pure fun.
So, let's start technical.
After removing motor from DPS to remove any resistance in steering system I've had to pretend there is working DPS by constantly putting message 0x330 with data 0x00, 0x99, 0x99, 0x00, 0xFF, 0xFF, 0x00, 0x00 to can bus and it works. No DPS and no errors
Because ABS was also partly fauly (all can bus data correct but going into error above 10km/h), I've had to remove any traces of errors going from ABS. To do that ABS in on separate CAN bus and messages are forwarded to main bus but with removed errors. This also is succesfull.
Unfortunately after key is turned there is a delay between ABS working and my program which causes errors in ECM. To clear errors I'm sending diagnostic messages after 5s from when key is turned:
msg_error_clear[0].id = 0x713;
msg_error_clear[1].id = 0x71C;
msg_error_clear[2].id = 0x710;
msg_error_clear[3].id = 0x715;
msg_error_clear[4].id = 0x717;
msg_error_clear[5].id = 0x715;
msg_error_clear[6].id = 0x715;
uint8_t tmp_buf_0[8] = { 0x04, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_1[8] = { 0x0D, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_2[8] = { 0x01, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_3[8] = { 0x06, 0x03, 0x14, 0xFF, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_4[8] = { 0x06, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_5[8] = { 0x06, 0x02, 0x10, 0x89, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_6[8] = { 0x06, 0x02, 0x10, 0x81, 0x00, 0x00, 0x00, 0x00 };
There is also a matter of menu button which must be pressed before every ride. I'm sending 0x519 together with 0x402:
0x591: 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x402: { /* three types of data */
{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x03, 0x21, 0x13, 0x61, 0x20, 0x11, 0x09, 0x00 },
{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 }
}
Below is the code for can bus commmunication which sends, changes and retrieves data to/from can bus:
Code:
#pragma once
#include <FlexCAN_T4.h>
#include <globalVar.h>
extern void can_changer_modify(CAN_message_t &msg);
FlexCAN_T4<CAN1, RX_SIZE_1024, TX_SIZE_32> can1; // internal
FlexCAN_T4<CAN2, RX_SIZE_1024, TX_SIZE_32> can2; // external
CAN_message_t msg1;
bool hasMsg1;
CAN_message_t msg2;
bool hasMsg2;
#define msg_changer_id 0xAA
CAN_message_t msg_changer0; // b0 - 0/1/2 no action/change/new, b1 b2 - message id, b3 len, b4 type - 0/1/2/3 set exactly/set/reset/toggle
CAN_message_t msg_changer1; // b0-b7 - toggle
CAN_message_t msg_changer_new;
uint16_t ready_delay_ms = 5000; // delay for isok message and error cleaning
CAN_message_t msg_dps;
CAN_message_t msg_lcd[3];
uint8_t msg_lcd_cnt;
CAN_message_t msg_isok;
CAN_message_t msg_error_clear[7];
uint8_t msg_error_clear_repeat_cntdn = 2;
uint8_t msg_error_clear_cnt;
uint8_t btn_buf_prev;
void can_setup()
{
can1.begin();
can1.setBaudRate(500000);
can2.begin();
can2.setBaudRate(500000);
}
void can_calcCrc8(CAN_message_t &msg)
{
switch (msg.len)
{
case 8: msg.buf[7] = msg.buf[0] ^ msg.buf[1] ^ msg.buf[2] ^ msg.buf[3] ^ msg.buf[4] ^ msg.buf[5] ^ msg.buf[6]; break;
case 7: msg.buf[6] = msg.buf[0] ^ msg.buf[1] ^ msg.buf[2] ^ msg.buf[3] ^ msg.buf[4] ^ msg.buf[5]; break;
case 6: msg.buf[5] = msg.buf[0] ^ msg.buf[1] ^ msg.buf[2] ^ msg.buf[3] ^ msg.buf[4]; break;
case 5: msg.buf[4] = msg.buf[0] ^ msg.buf[1] ^ msg.buf[2] ^ msg.buf[3]; break;
case 4: msg.buf[3] = msg.buf[0] ^ msg.buf[1] ^ msg.buf[2]; break;
}
}
void can_incCounter0F(CAN_message_t &msg)
{
// assumption that if counter exists, it is before last byte
msg.buf[msg.len - 2]++;
if (msg.buf[msg.len - 2] == 0x10)
msg.buf[msg.len - 2] = 0x00;
}
void can_changer_modify(CAN_message_t &msg)
{
if (msg_changer0.buf[3] > 8)
msg.len = msg_changer0.buf[3] & 0xFF;
else
msg.len = 8; // default to 8
if (msg_changer0.buf[4] == 0)
{
msg.buf[0] = msg_changer1.buf[0];
msg.buf[1] = msg_changer1.buf[1];
msg.buf[2] = msg_changer1.buf[2];
msg.buf[3] = msg_changer1.buf[3];
msg.buf[4] = msg_changer1.buf[4];
msg.buf[5] = msg_changer1.buf[5];
msg.buf[6] = msg_changer1.buf[6];
msg.buf[7] = msg_changer1.buf[7];
}
else if (msg_changer0.buf[4] == 1)
{
msg.buf[0] |= msg_changer1.buf[0];
msg.buf[1] |= msg_changer1.buf[1];
msg.buf[2] |= msg_changer1.buf[2];
msg.buf[3] |= msg_changer1.buf[3];
msg.buf[4] |= msg_changer1.buf[4];
msg.buf[5] |= msg_changer1.buf[5];
msg.buf[6] |= msg_changer1.buf[6];
msg.buf[7] |= msg_changer1.buf[7];
}
else if (msg_changer0.buf[4] == 2)
{
msg.buf[0] &= ~msg_changer1.buf[0];
msg.buf[1] &= ~msg_changer1.buf[1];
msg.buf[2] &= ~msg_changer1.buf[2];
msg.buf[3] &= ~msg_changer1.buf[3];
msg.buf[4] &= ~msg_changer1.buf[4];
msg.buf[5] &= ~msg_changer1.buf[5];
msg.buf[6] &= ~msg_changer1.buf[6];
msg.buf[7] &= ~msg_changer1.buf[7];
}
else if (msg_changer0.buf[4] == 3)
{
msg.buf[0] ^= msg_changer1.buf[0];
msg.buf[1] ^= msg_changer1.buf[1];
msg.buf[2] ^= msg_changer1.buf[2];
msg.buf[3] ^= msg_changer1.buf[3];
msg.buf[4] ^= msg_changer1.buf[4];
msg.buf[5] ^= msg_changer1.buf[5];
msg.buf[6] ^= msg_changer1.buf[6];
msg.buf[7] ^= msg_changer1.buf[7];
}
}
/*void can_testchange_401(CAN_message_t &msg)
{
switch (msg.buf[0])
{
case 1:
msg.buf[1] = 0;
msg.buf[2] = 3;
msg.buf[3] = 0xe7;
msg.buf[4] = 0;
msg.buf[5] = 0;
msg.buf[6] = 0;
msg.buf[7] = 0;
break;
case 3:
msg.buf[1] = 0;
msg.buf[2] = 0;
msg.buf[3] = 6;
msg.buf[4] = 149;
msg.buf[5] = 13;
msg.buf[6] = 107;
msg.buf[7] = 0;
break;
case 4:
msg.buf[1] = 0;
msg.buf[2] = 0;
msg.buf[3] = 6;
msg.buf[4] = 204;
msg.buf[5] = 19;
msg.buf[6] = 170;
msg.buf[7] = 0;
break;
}
}*/
void can_send_changer_new()
{
msg_changer_new.id = msg_changer0.buf[2];
msg_changer_new.id = msg_changer_new.id << 8;
msg_changer_new.id += msg_changer0.buf[1];
can_changer_modify(msg_changer_new);
can1.write(msg_changer_new);
}
void can_save_msg_keys(CAN_message_t &msg)
{
if (btn_buf_prev == msg.buf[1])
return;
// store bits changed to 1
uint8_t tmp = (btn_buf_prev ^ msg.buf[1]) & msg.buf[1];
if (tmp & 0x1)
key_up = true;
if (tmp & 0x2)
key_down = true;
if (tmp & 0x4)
key_left = true;
if (tmp & 0x8)
key_right = true;
if (tmp & 0x10)
key_menu = true;
if (tmp & 0x20)
key_set = true;
if (tmp & 0x40)
key_back = true;
btn_buf_prev = msg.buf[1];
}
void can_save_data_cluster_401(CAN_message_t &msg)
{
/* Serial.println(
String(msg.buf[1]).append( " ")
.append(msg.buf[2]).append(" ")
.append(msg.buf[3]).append(" ")
.append(msg.buf[4]).append(" ")
.append(msg.buf[5]).append(" ")
.append(msg.buf[6]).append(" ")
.append(msg.buf[7]).append(" "));
*/
switch (msg.buf[0])
{
case 0:
break;
case 1:
break;
case 2:
can_triptotal = ((uint32_t)msg.buf[1] << 24) + ((uint32_t)msg.buf[2] << 16) + ((uint32_t)msg.buf[3] << 8) + msg.buf[4];
break;
case 3:
can_tripa = ((uint32_t)msg.buf[1] << 24) + ((uint32_t)msg.buf[2] << 16) + ((uint32_t)msg.buf[3] << 8) + msg.buf[4];
break;
case 4:
can_tripb = ((uint32_t)msg.buf[1] << 24) + ((uint32_t)msg.buf[2] << 16) + ((uint32_t)msg.buf[3] << 8) + msg.buf[4];
break;
case 5:
break;
case 6:
can_acslevel = B1000 - ((msg.buf[2] & B1110) >> 1);
can_acsheight = ((uint16_t)msg.buf[3] << 8) + msg.buf[4];
break;
}
}
void can_save_data(CAN_message_t &msg)
{
switch (msg.id)
{
case 0x102:
can_tempengine = msg.buf[3];
can_tempair = msg.buf[4];
break;
case 0x308:
// B0: bity: low bat, -, -, -, engine hi temp, -, oil switch
can_islowbat = msg.buf[0] & 1;
can_i****emp = msg.buf[0] >> 4 & 1;
can_isoilswitch = msg.buf[0] >> 6 & 1;
break;
case 0x310:
can_gearbyte = msg.buf[0] & 0xF; // b0: bieg 1-6, 7 neutral, 8 reverse
break;
case 0x430:
can_abspressure = msg.buf[4]; // stosunek 1:33 kpa, 0x3E == 0, 0xFF == 6369 kPa
break;
}
}
void can_send_dps()
{
// initialize dps message
if (msg_dps.id == 0)
{
msg_dps.id = 0x330;
uint8_t tmp_buf[8] = { 0x00, 0x99, 0x99, 0x00, 0xFF, 0xFF, 0x00, 0x00 };
memcpy(msg_dps.buf, tmp_buf, 8);
}
// send dps data to both buses
can1.write(msg_dps);
can2.write(msg_dps);
// set new values for counter and crc8 bytes
can_incCounter0F(msg_dps);
msg_dps.buf[7] = msg_dps.buf[6]; // copy counter to crc because crc in this case is the same as counter
}
void can_send_lcd()
{
// initialize lcd message
if (msg_lcd[0].id == 0)
{
msg_lcd[0].id = 0x402;
msg_lcd[1].id = 0x402;
msg_lcd[2].id = 0x402;
uint8_t tmp_buf[3][8] = {
{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x03, 0x21, 0x13, 0x61, 0x20, 0x11, 0x09, 0x00 },
{ 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00 } };
memcpy(msg_lcd[0].buf, tmp_buf[0], 8);
memcpy(msg_lcd[1].buf, tmp_buf[1], 8);
memcpy(msg_lcd[2].buf, tmp_buf[2], 8);
}
if (msg_lcd_cnt == 11)
can1.write(msg_lcd[2]);
else if (msg_lcd_cnt == 10)
can1.write(msg_lcd[1]);
else
can1.write(msg_lcd[0]);
msg_lcd_cnt++;
if (msg_lcd_cnt == 12)
msg_lcd_cnt = 0;
}
void can_send_isok()
{
// initialize lcd message
if (msg_isok.id == 0)
{
msg_isok.id = 0x591;
msg_isok.len = 1;
uint8_t tmp_buf[8] = { 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(msg_isok.buf, tmp_buf, 8);
}
can1.write(msg_isok);
}
void can_send_error_clear()
{
// initialize lcd message
if (msg_error_clear[0].id == 0)
{
msg_error_clear[0].id = 0x713;
msg_error_clear[1].id = 0x71C;
msg_error_clear[2].id = 0x710;
msg_error_clear[3].id = 0x715;
msg_error_clear[4].id = 0x717;
msg_error_clear[5].id = 0x715;
msg_error_clear[6].id = 0x715;
uint8_t tmp_buf_0[8] = { 0x04, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_1[8] = { 0x0D, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_2[8] = { 0x01, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_3[8] = { 0x06, 0x03, 0x14, 0xFF, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_4[8] = { 0x06, 0x03, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_5[8] = { 0x06, 0x02, 0x10, 0x89, 0x00, 0x00, 0x00, 0x00 };
uint8_t tmp_buf_6[8] = { 0x06, 0x02, 0x10, 0x81, 0x00, 0x00, 0x00, 0x00 };
memcpy(msg_error_clear[0].buf, tmp_buf_0, 8);
memcpy(msg_error_clear[1].buf, tmp_buf_1, 8);
memcpy(msg_error_clear[2].buf, tmp_buf_2, 8);
memcpy(msg_error_clear[3].buf, tmp_buf_3, 8);
memcpy(msg_error_clear[4].buf, tmp_buf_4, 8);
memcpy(msg_error_clear[5].buf, tmp_buf_5, 8);
memcpy(msg_error_clear[6].buf, tmp_buf_6, 8);
}
can1.write(msg_error_clear[msg_error_clear_cnt]);
can2.write(msg_error_clear[msg_error_clear_cnt]);
msg_error_clear_cnt++;
if (msg_error_clear_cnt == 7)
{
msg_error_clear_repeat_cntdn--;
msg_error_clear_cnt = 0;
}
}
void can_handle_msg_post(CAN_message_t &msg)
{
switch (msg.id)
{
// store message changer data
case (msg_changer_id+0): msg_changer0 = msg; break;
case (msg_changer_id+1): msg_changer1 = msg; break;
//case 0x401: can_testchange_401(msg); break;
case 0x102: can_save_data(msg); break;
case 0x308: can_save_data(msg); break;
case 0x310: can_save_data(msg); break;
case 0x401: can_save_data_cluster_401(msg); break;
case 0x340: can_save_msg_keys(msg); break;
case 0x430: // remove error from vcm message
can_save_data(msg); break;
break;
}
}
void can_handle_msg_pre(CAN_message_t &msg)
{
switch (msg.id)
{
case 0x020: // remove error from vcm message
msg.buf[0] = msg.buf[0] & 0xF0;
msg.buf[1] = 0x00;
can_calcCrc8(msg);
break;
case 0x430: // remove error from vcm message
msg.buf[0] = msg.buf[1] = 0x99;
can_calcCrc8(msg);
break;
}
// change message
if (msg_changer0.buf[0] == 1)
{
// match id
if ((msg.id & 0xFF) == msg_changer0.buf[1] && ((msg.id >> 8) & 0xFF) == msg_changer0.buf[2])
can_changer_modify(msg);
}
}
void can_handle()
{
// send custom messages with minimum 1ms offset
if (event1ms && timer1msCounterStored > 10) // skip first few ms because of -n in checks
{
if (ready_delay_ms > 0)
ready_delay_ms--;
// send dps every 34ms
if (!((timer1msCounterStored -0) & (0x20-1)))
can_send_dps();
// send lcd every 128ms
if (!((timer1msCounterStored -1) & (0x80-1)))
can_send_lcd();
// send isok every 128ms
// start sending after moto is ready
if (ready_delay_ms == 0 && !((timer1msCounterStored -2) & (0x80-1)))
can_send_isok();
// send error clear every 128ms
// start sending after moto is ready
// send only once
if (ready_delay_ms == 0 && msg_error_clear_repeat_cntdn > 0 && !((timer1msCounterStored -2) & (0x80-1)))
can_send_error_clear();
// send test message every 128ms
if (!((timer1msCounterStored -4) & (0x80-1)))
{
// new test message
if (msg_changer0.buf[0] == 2)
can_send_changer_new();
}
}
// read messages
hasMsg1 = can1.read(msg1);
hasMsg2 = can2.read(msg2);
// don't change message going from ecu to external bus
if (hasMsg1)
{
if (msg1.id < 0x700) // skip diagnostic messages
can_handle_msg_pre(msg1);
can2.write(msg1);
if (msg1.id < 0x700) // skip diagnostic messages
can_handle_msg_post(msg1);
}
if (hasMsg2)
{
if (msg2.id < 0x700) // skip diagnostic messages
can_handle_msg_pre(msg2);
can1.write(msg2);
if (msg2.id < 0x700) // skip diagnostic messages
can_handle_msg_post(msg2);
}
}
Below is code responsible for lcd screen with LVGL library:
Code:
#pragma once
#include <lvgl.h>
#include <types.h>
#include <globalVar.h>
#include <gui.h>
class scr_main : public screen_base
{
// styles
lv_style_t box_style_box;
lv_style_t box_style_box_checked;
lv_style_t bar_style_temp;
// controls
lv_obj_t* rol_gearpos;
lv_obj_t* lbl_tempair;
lv_obj_t* lbl_tripa;
lv_obj_t* lbl_triptotal;
lv_obj_t* lbl_tempengine;
lv_obj_t* bar_tempengine;
lv_obj_t* bar_abspressure;
lv_obj_t* lbl_acslevel;
lv_obj_t* bar_acsheight;
lv_obj_t* box_islowbat;
lv_obj_t* box_i****emp;
lv_obj_t* box_isoilswitch;
uint32_t gui_tripa;
uint32_t gui_triptotal;
uint16_t gui_tempair;
uint16_t gui_tempengine;
uint16_t gui_acslevel;
uint16_t gui_abspressure;
uint16_t gui_acsheight;
lv_obj_t* build()
{
lv_obj_t* ret = lv_obj_create(NULL);
//lv_obj_set_style_bg_color(ret, lv_palette_lighten(LV_PALETTE_BLUE, 4), LV_PART_MAIN);
lv_obj_set_style_bg_color(ret, lv_color_black(), LV_PART_MAIN);
lv_obj_set_style_text_color(ret, lv_color_white(), LV_PART_MAIN);
// create styles
lv_style_init(&box_style_box);
lv_style_set_border_color(&box_style_box, lv_palette_main(LV_PALETTE_RED));
lv_style_set_border_width(&box_style_box, 3);
lv_style_init(&box_style_box_checked);
lv_style_set_border_color(&box_style_box_checked, lv_palette_main(LV_PALETTE_RED));
lv_style_set_border_width(&box_style_box_checked, 3);
lv_style_set_bg_color(&box_style_box_checked, lv_palette_main(LV_PALETTE_RED));
lv_style_init(&bar_style_temp);
lv_style_set_bg_opa(&bar_style_temp, LV_OPA_COVER);
lv_style_set_bg_color(&bar_style_temp, lv_palette_main(LV_PALETTE_RED));
lv_style_set_bg_grad_color(&bar_style_temp, lv_palette_main(LV_PALETTE_BLUE));
lv_style_set_bg_grad_dir(&bar_style_temp, LV_GRAD_DIR_VER);
// lv_style_set_bg_grad_color(&style_btn, lv_palette_main(LV_PALETTE_GREY));
// lv_style_set_bg_grad_dir(&style_btn, LV_GRAD_DIR_VER);
lv_obj_t * panel;
lv_obj_t * obj;
// gear pos
rol_gearpos = lv_roller_create(ret);
lv_roller_set_options(rol_gearpos, " \n1\n2\n3\n4\n5\n6\nN\nR", LV_ROLLER_MODE_INFINITE);
lv_roller_set_visible_row_count(rol_gearpos, 5);
lv_obj_set_width(rol_gearpos, 40);
lv_obj_set_pos(rol_gearpos, 0, 0);
// air temp
lbl_tempair = lv_label_create(ret);
lv_label_set_text(lbl_tempair, "AIR T");
lv_obj_set_pos(lbl_tempair, 50, 0);
// Trip A
obj = lv_label_create(ret);
lv_label_set_text(obj, "Trip");
lv_obj_set_style_text_font(obj, &lv_font_montserrat_20, LV_PART_MAIN);
lv_obj_set_pos(obj, 50, 41);
lbl_tripa = lv_label_create(ret);
// lv_obj_set_style_text_align(lbl_triptotal, LV_TEXT_ALIGN_RIGHT, 0); // crashing
lv_obj_set_width(lbl_tripa, 120);
lv_obj_set_pos(lbl_tripa, 110, 40);
// Total
obj = lv_label_create(ret);
lv_label_set_text(obj, "Total");
lv_obj_set_style_text_font(obj, &lv_font_montserrat_20, LV_PART_MAIN);
lv_obj_set_pos(obj, 50, 81);
lbl_triptotal = lv_label_create(ret);
//lv_obj_set_style_text_align(lbl_triptotal, LV_TEXT_ALIGN_RIGHT, 0); // crashing
lv_obj_set_width(lbl_triptotal, 120);
lv_obj_set_pos(lbl_triptotal, 110, 80);
// right side bars
// engine temp
lbl_tempengine = lv_label_create(ret);
lv_label_set_text(lbl_tempengine, "ENG T");
lv_obj_set_pos(lbl_tempengine, 215, 0);
bar_tempengine = lv_bar_create(ret);
lv_obj_add_style(bar_tempengine, &bar_style_temp, LV_PART_INDICATOR);
lv_obj_set_size(bar_tempengine, 30, 180);
lv_bar_set_range(bar_tempengine, 40, 130);
lv_obj_set_pos(bar_tempengine, 235, 30);
// abs pressure
bar_abspressure = lv_bar_create(ret);
lv_obj_set_style_bg_color(bar_abspressure, lv_palette_main(LV_PALETTE_RED), LV_PART_INDICATOR);
lv_obj_set_size(bar_abspressure, 20, 180);
lv_bar_set_range(bar_abspressure, 0x3e, 0xCA); // 140 * 33 = 4620kPa
lv_obj_set_pos(bar_abspressure, 270, 30);
// acs level
lbl_acslevel = lv_label_create(ret);
lv_label_set_text(lbl_acslevel, "-");
lv_obj_set_pos(lbl_acslevel, 295, 0);
// acs height
bar_acsheight = lv_bar_create(ret);
lv_obj_set_size(bar_acsheight, 20, 180);
lv_bar_set_range(bar_acsheight, 250, 650);
lv_obj_set_pos(bar_acsheight, 295, 30);
// checkboxes
panel = lv_obj_create(ret);
lv_obj_set_size(panel, 320, 30);
lv_obj_set_pos(panel, 0, 210);
lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(panel, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER);
box_islowbat = lv_checkbox_create(panel);
lv_checkbox_set_text(box_islowbat, "Bat");
lv_obj_add_style(box_islowbat, &box_style_box, LV_PART_INDICATOR);
lv_obj_add_style(box_islowbat, &box_style_box_checked, LV_PART_INDICATOR | LV_STATE_CHECKED);
box_i****emp = lv_checkbox_create(panel);
lv_checkbox_set_text(box_i****emp, "Temp");
lv_obj_add_style(box_i****emp, &box_style_box, LV_PART_INDICATOR);
lv_obj_add_style(box_i****emp, &box_style_box_checked, LV_PART_INDICATOR | LV_STATE_CHECKED);
box_isoilswitch = lv_checkbox_create(panel);
lv_checkbox_set_text(box_isoilswitch, "Oil");
lv_obj_add_style(box_isoilswitch, &box_style_box, LV_PART_INDICATOR);
lv_obj_add_style(box_isoilswitch, &box_style_box_checked, LV_PART_INDICATOR | LV_STATE_CHECKED);
lv_obj_update_layout(box_isoilswitch);
return ret;
}
void open()
{
}
void close()
{
}
// 100us main
void event()
{
// only one at a time for optimization purposes starting from highest priority
if (gui_abspressure != can_abspressure)
{
gui_abspressure = can_abspressure;
lv_bar_set_value(bar_abspressure, gui_abspressure, LV_ANIM_OFF);
}
else if (gui_acsheight != can_acsheight)
{
gui_acsheight = can_acsheight;
lv_bar_set_value(bar_acsheight, gui_acsheight, LV_ANIM_OFF);
}
else if (gui_tempair != can_tempair)
{
gui_tempair = can_tempair;
int temp = gui_tempair-60;
lv_label_set_text(lbl_tempair, String((temp)).append("*C").c_str());
}
else if (gui_tripa != can_tripa)
{
gui_tripa = can_tripa;
String tripastr = String(gui_tripa >= 10 ? gui_tripa : 10); // co najmniej 100m zeby bylo co wyswietlac
String tripadec = tripastr.substring(tripastr.length()-2, tripastr.length());
tripastr.remove(tripastr.length()-2, 2);
tripastr.append(",").append(tripadec);
lv_label_set_text(lbl_tripa, tripastr.c_str());
}
else if (gui_triptotal != can_triptotal)
{
gui_triptotal = can_triptotal;
String triptotalstr = String(gui_triptotal);
String triptotaldecstr = triptotalstr.substring(triptotalstr.length()-2, triptotalstr.length());
triptotalstr.remove(triptotalstr.length()-2, 2);
triptotalstr.append(",").append(triptotaldecstr);
lv_label_set_text(lbl_triptotal, triptotalstr.c_str());
}
else if (gui_tempengine != can_tempengine)
{
gui_tempengine = can_tempengine;
int temp = gui_tempengine-60;
lv_label_set_text(lbl_tempengine, String((temp)).append("*C").c_str());
lv_bar_set_value(bar_tempengine, temp, LV_ANIM_OFF);
}
else if (gui_acslevel != can_acslevel)
{
gui_acslevel = can_acslevel;
lv_label_set_text(lbl_acslevel, String(gui_acslevel).c_str());
}
else
{
lv_roller_set_selected(rol_gearpos, (uint16_t)can_gearbyte, LV_ANIM_OFF);
if (can_islowbat) lv_obj_add_state(box_islowbat, LV_STATE_CHECKED);
else lv_obj_clear_state(box_islowbat, LV_STATE_CHECKED);
if (can_i****emp) lv_obj_add_state(box_i****emp, LV_STATE_CHECKED);
else lv_obj_clear_state(box_i****emp, LV_STATE_CHECKED);
if (can_isoilswitch) lv_obj_add_state(box_isoilswitch, LV_STATE_CHECKED);
else lv_obj_clear_state(box_isoilswitch, LV_STATE_CHECKED);
}
}
};
global variables:
Code:
// can bus data
bool can_islowbat, can_i****emp, can_isoilswitch;
uint16_t can_tempengine, can_tempair;
uint16_t can_gearbyte;
uint16_t can_abspressure;
uint16_t can_acsheight;
uint16_t can_acslevel;
uint32_t can_triptotal;
uint32_t can_tripa;
uint32_t can_tripb;
main loop:
Code:
void loop()
{
// critical code
can_handle();
// catch volatile timer
event1ms = timer1msCounterStored != timer1msCounter;
if (!event1ms)
return;
// 1ms code
timer1msCounterStored = timer1msCounter;
event4ms = !(timer1msCounterStored & 0x3);
// GUI code every 4ms
if (event4ms)
{
gui_update();
}
}
gui_update() basically calls event() on current screen.
I have two screens:
- main for brake pressure, trip, ACS height, gear position, temp and some other stuff
- snake game for playing while my wife goes for shopping
Last edited by megagame; 05-04-2023 at 05:44 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|