Resolve issue with Teensy not sending CAN msgs

This commit is contained in:
Josh Stewart 2023-12-21 13:40:36 +11:00
parent 5d6440f00d
commit 7d817e3cde
7 changed files with 404 additions and 368 deletions

View File

@ -8,12 +8,15 @@
#include "timers.h"
#include "comms_secondary.h"
/*
//These are declared locally in comms_CAN now due to this issue: https://github.com/tonton81/FlexCAN_T4/issues/67
#if defined(__MK64FX512__) // use for Teensy 3.5 only
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
#elif defined(__MK66FX1M0__) // use for Teensy 3.6 only
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
#endif
*/
void initBoard()
{
@ -22,6 +25,7 @@ void initBoard()
* General
*/
pSecondarySerial = &Serial2;
//Can0.setBaudRate(500000);
/*
***********************************************************************************************************

View File

@ -160,12 +160,16 @@
#define SECONDARY_SERIAL_T HardwareSerial
#include <FlexCAN_T4.h>
/*
//These are declared locally in comms_CAN now due to this issue: https://github.com/tonton81/FlexCAN_T4/issues/67
#if defined(__MK64FX512__) // use for Teensy 3.5 only
extern FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
#elif defined(__MK66FX1M0__) // use for Teensy 3.6 only
extern FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
extern FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
#endif
*/
#define NATIVE_CAN_AVAILABLE
#endif //CORE_TEENSY
#endif //TEENSY35_H

View File

@ -16,9 +16,48 @@ This is for handling the data broadcasted to various CAN dashes and instrument c
CAN_message_t inMsg;
CAN_message_t outMsg;
//These are declared locally for Teensy due to this issue: https://github.com/tonton81/FlexCAN_T4/issues/67
#if defined(CORE_TEENSY35) // use for Teensy 3.5 only
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
#elif defined(CORE_TEENSY41) // use for Teensy 3.6 only
FlexCAN_T4<CAN0, RX_SIZE_256, TX_SIZE_16> Can0;
FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> Can1;
#endif
// Forward declare
void DashMessage(uint16_t DashMessageID);
void initCAN()
{
#if defined (NATIVE_CAN_AVAILABLE)
configPage9.intcan_available = 1; // device has internal canbus
//Teensy uses the Flexcan_T4 library to use the internal canbus
//enable local can interface
//setup can interface to 500k
Can0.begin();
Can0.setBaudRate(500000);
Can0.enableFIFO();
/* Note: This must come after the call to setPinMapping() or else pins 29 and 30 will become unusable as outputs.
* Workaround for: https://github.com/tonton81/FlexCAN_T4/issues/14 */
#if defined(CORE_TEENSY35) // use for Teensy 3.5 only
Can0.setRX(DEF);
Can0.setTX(DEF);
#endif
#endif
}
int CAN_read()
{
return Can0.read(inMsg);
}
void CAN_write()
{
Can0.write(outMsg);
}
void sendBMWCluster()
{
DashMessage(CAN_BMW_DME1);
@ -127,42 +166,40 @@ void DashMessage(uint16_t DashMessageID)
void can_Command(void)
{
//int currentcanCommand = inMsg.id;
// currentStatus.canin[12] = (inMsg.id);
if ( (inMsg.id == uint16_t(configPage9.obd_address + TS_CAN_OFFSET)) || (inMsg.id == 0x7DF))
if ( (inMsg.id == uint16_t(configPage9.obd_address + TS_CAN_OFFSET)) || (inMsg.id == 0x7DF))
{
// The address is the speeduino specific ecu canbus address
// or the 0x7df(2015 dec) broadcast address
if (inMsg.buf[1] == 0x01)
{
// PID mode 0 , realtime data stream
obd_response(inMsg.buf[1], inMsg.buf[2], 0); // get the obd response based on the data in byte2
outMsg.id = (0x7E8); //((configPage9.obd_address + 0x100)+ 8);
Can0.write(outMsg); // send the 8 bytes of obd data
}
{
// PID mode 0 , realtime data stream
obd_response(inMsg.buf[1], inMsg.buf[2], 0); // get the obd response based on the data in byte2
outMsg.id = (0x7E8); //((configPage9.obd_address + 0x100)+ 8);
Can0.write(outMsg); // send the 8 bytes of obd data
}
if (inMsg.buf[1] == 0x22)
{
// PID mode 22h , custom mode , non standard data
obd_response(inMsg.buf[1], inMsg.buf[2], inMsg.buf[3]); // get the obd response based on the data in byte2
outMsg.id = (0x7E8); //configPage9.obd_address+8);
Can0.write(outMsg); // send the 8 bytes of obd data
}
{
// PID mode 22h , custom mode , non standard data
obd_response(inMsg.buf[1], inMsg.buf[2], inMsg.buf[3]); // get the obd response based on the data in byte2
outMsg.id = (0x7E8); //configPage9.obd_address+8);
Can0.write(outMsg); // send the 8 bytes of obd data
}
}
if (inMsg.id == uint16_t(configPage9.obd_address + TS_CAN_OFFSET))
if (inMsg.id == uint16_t(configPage9.obd_address + TS_CAN_OFFSET))
{
// The address is only the speeduino specific ecu canbus address
if (inMsg.buf[1] == 0x09)
{
// PID mode 9 , vehicle information request
if (inMsg.buf[2] == 02)
{
// PID mode 9 , vehicle information request
if (inMsg.buf[2] == 02)
{
//send the VIN number , 17 char long VIN sent in 5 messages.
}
else if (inMsg.buf[2] == 0x0A)
{
//code 20: send 20 ascii characters with ECU name , "ECU -SpeeduinoXXXXXX" , change the XXXXXX ONLY as required.
}
//send the VIN number , 17 char long VIN sent in 5 messages.
}
else if (inMsg.buf[2] == 0x0A)
{
//code 20: send 20 ascii characters with ECU name , "ECU -SpeeduinoXXXXXX" , change the XXXXXX ONLY as required.
}
}
}
}
@ -182,341 +219,341 @@ void obd_response(uint8_t PIDmode, uint8_t requestedPIDlow, uint8_t requestedPID
outMsg.len = 8;
if (PIDmode == 0x01)
if (PIDmode == 0x01)
{
//currentStatus.canin[13] = therequestedPIDlow;
switch (requestedPIDlow)
{
case 0: //PID-0x00 PIDs supported 01-20
outMsg.buf[0] = 0x06; // sending 6 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x00; // PID code
outMsg.buf[3] = 0x08; //B0000 1000 1-8
outMsg.buf[4] = B01111110; //9-16
outMsg.buf[5] = B10100000; //17-24
outMsg.buf[6] = B00010001; //17-32
outMsg.buf[7] = B00000000;
break;
case 5: //PID-0x05 Engine coolant temperature , range is -40 to 215 deg C , formula == A-40
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x05; // pid code
outMsg.buf[3] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //the data value A
outMsg.buf[4] = 0x00; //the data value B which is 0 as unused
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 10: // PID-0x0A , Fuel Pressure (Gauge) , range is 0 to 765 kPa , formula == A / 3)
uint16_t temp_fuelpressure;
// Fuel pressure is in PSI. PSI to kPa is 6.89475729, but that needs to be divided by 3 for OBD2 formula. So 2.298.... 2.3 is close enough, so that in fraction.
temp_fuelpressure = (currentStatus.fuelPressure * 23) / 10;
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; //
outMsg.buf[2] = 0x0A; // pid code
outMsg.buf[3] = lowByte(temp_fuelpressure);
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 11: // PID-0x0B , MAP , range is 0 to 255 kPa , Formula == A
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; //
outMsg.buf[2] = 0x0B; // pid code
outMsg.buf[3] = lowByte(currentStatus.MAP); // absolute map
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 12: // PID-0x0C , RPM , range is 0 to 16383.75 rpm , Formula == 256A+B / 4
uint16_t temp_revs;
temp_revs = currentStatus.RPM << 2 ; //
outMsg.buf[0] = 0x04; // sending 4 byte
outMsg.buf[1] = 0x41; //
outMsg.buf[2] = 0x0C; // pid code
outMsg.buf[3] = highByte(temp_revs); //obdcalcB; A
outMsg.buf[4] = lowByte(temp_revs); //obdcalcD; B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 13: //PID-0x0D , Vehicle speed , range is 0 to 255 km/h , formula == A
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x0D; // pid code
outMsg.buf[3] = lowByte(currentStatus.vss); // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 14: //PID-0x0E , Ignition Timing advance, range is -64 to 63.5 BTDC , formula == A/2 - 64
int8_t temp_timingadvance;
temp_timingadvance = ((currentStatus.advance + 64) << 1);
//obdcalcA = ((timingadvance + 64) <<1) ; //((timingadvance + 64) *2)
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x0E; // pid code
outMsg.buf[3] = temp_timingadvance; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 15: //PID-0x0F , Inlet air temperature , range is -40 to 215 deg C, formula == A-40
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x0F; // pid code
outMsg.buf[3] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 17: // PID-0x11 ,
// TPS percentage, range is 0 to 100 percent, formula == 100/256 A
uint16_t temp_tpsPC;
temp_tpsPC = currentStatus.TPS;
obdcalcA = (temp_tpsPC <<8) / 100; // (tpsPC *256) /100;
if (obdcalcA > 255){ obdcalcA = 255;}
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x11; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 19: //PID-0x13 , oxygen sensors present, A0-A3 == bank1 , A4-A7 == bank2 ,
uint16_t O2present;
O2present = B00000011 ; //realtimebufferA[24]; TEST VALUE !!!!!
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x13; // pid code
outMsg.buf[3] = O2present ; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 28: // PID-0x1C obd standard
uint16_t obdstandard;
obdstandard = 7; // This is OBD2 / EOBD
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x1C; // pid code
outMsg.buf[3] = obdstandard; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 32: // PID-0x20 PIDs supported [21-40]
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x20; // pid code
outMsg.buf[3] = B00011000; // 33-40
outMsg.buf[4] = B00000000; //41 - 48
outMsg.buf[5] = B00100000; //49-56
outMsg.buf[6] = B00000001; //57-64
outMsg.buf[7] = 0x00;
break;
case 36: // PID-0x24 O2 sensor2, AB: fuel/air equivalence ratio, CD: voltage , Formula == (2/65536)(256A +B) , 8/65536(256C+D) , Range is 0 to <2 and 0 to >8V
//uint16_t O2_1e ;
//int16_t O2_1v ;
obdcalcH16 = configPage2.stoich/10 ; // configPage2.stoich(is *10 so 14.7 is 147)
obdcalcE32 = currentStatus.O2/10; // afr(is *10 so 25.5 is 255) , needs a 32bit else will overflow
obdcalcF32 = (obdcalcE32<<8) / obdcalcH16; //this is same as (obdcalcE32/256) / obdcalcH16 . this calculates the ratio
obdcalcG16 = (obdcalcF32 *32768)>>8;
obdcalcA = highByte(obdcalcG16);
obdcalcB = lowByte(obdcalcG16);
obdcalcF32 = currentStatus.O2ADC ; //o2ADC is wideband volts to send *100
obdcalcG16 = (obdcalcF32 *20971)>>8;
obdcalcC = highByte(obdcalcG16);
obdcalcD = lowByte(obdcalcG16);
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x24; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = obdcalcB; // B
outMsg.buf[5] = obdcalcC; // C
outMsg.buf[6] = obdcalcD; // D
outMsg.buf[7] = 0x00;
break;
case 37: //O2 sensor2, AB fuel/air equivalence ratio, CD voltage , 2/65536(256A +B) ,8/65536(256C+D) , range is 0 to <2 and 0 to >8V
//uint16_t O2_2e ;
//int16_t O2_2V ;
obdcalcH16 = configPage2.stoich/10 ; // configPage2.stoich(is *10 so 14.7 is 147)
obdcalcE32 = currentStatus.O2_2/10; // afr(is *10 so 25.5 is 255) , needs a 32bit else will overflow
obdcalcF32 = (obdcalcE32<<8) / obdcalcH16; //this is same as (obdcalcE32/256) / obdcalcH16 . this calculates the ratio
obdcalcG16 = (obdcalcF32 *32768)>>8;
obdcalcA = highByte(obdcalcG16);
obdcalcB = lowByte(obdcalcG16);
obdcalcF32 = currentStatus.O2_2ADC ; //o2_2ADC is wideband volts to send *100
obdcalcG16 = (obdcalcF32 *20971)>>8;
obdcalcC = highByte(obdcalcG16);
obdcalcD = lowByte(obdcalcG16);
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x25; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = obdcalcB; // B
outMsg.buf[5] = obdcalcC; // C
outMsg.buf[6] = obdcalcD; // D
outMsg.buf[7] = 0x00;
break;
case 51: //PID-0x33 Absolute Barometric pressure , range is 0 to 255 kPa , formula == A
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x33; // pid code
outMsg.buf[3] = currentStatus.baro ; // A
outMsg.buf[4] = 0x00; // B which is 0 as unused
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 64: // PIDs supported [41-60]
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x40; // pid code
outMsg.buf[3] = B01000100; // 65-72dec
outMsg.buf[4] = B00000000; // 73-80
outMsg.buf[5] = B01000000; // 81-88
outMsg.buf[6] = B00010000; // 89-96
outMsg.buf[7] = 0x00;
break;
case 66: //control module voltage, 256A+B / 1000 , range is 0 to 65.535v
uint16_t temp_ecuBatt;
temp_ecuBatt = currentStatus.battery10; // create a 16bit temp variable to do the math
obdcalcA = temp_ecuBatt*100; // should be *1000 but ecuBatt is already *10
outMsg.buf[0] = 0x04; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x42; // pid code
outMsg.buf[3] = highByte(obdcalcA) ; // A
outMsg.buf[4] = lowByte(obdcalcA) ; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 70: //PID-0x46 Ambient Air Temperature , range is -40 to 215 deg C , formula == A-40
uint16_t temp_ambientair;
temp_ambientair = 11; // TEST VALUE !!!!!!!!!!
obdcalcA = temp_ambientair + 40 ; // maybe later will be (byte)(currentStatus.AAT + CALIBRATION_TEMPERATURE_OFFSET)
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x46; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 82: //PID-0x52 Ethanol fuel % , range is 0 to 100% , formula == (100/255)A
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x52; // pid code
outMsg.buf[3] = currentStatus.ethanolPct; // A
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 92: //PID-0x5C Engine oil temperature , range is -40 to 210 deg C , formula == A-40
uint16_t temp_engineoiltemp;
temp_engineoiltemp = 40; // TEST VALUE !!!!!!!!!!
obdcalcA = temp_engineoiltemp+40 ; // maybe later will be (byte)(currentStatus.EOT + CALIBRATION_TEMPERATURE_OFFSET)
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x5C; // pid code
outMsg.buf[3] = obdcalcA ; // A
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 96: //PIDs supported [61-80]
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x60; // pid code
outMsg.buf[3] = 0x00; // B0000 0000
outMsg.buf[4] = 0x00; // B0000 0000
outMsg.buf[5] = 0x00; // B0000 0000
outMsg.buf[6] = 0x00; // B0000 0000
outMsg.buf[7] = 0x00;
break;
default:
break;
}
}
else if (PIDmode == 0x22)
switch (requestedPIDlow)
{
// these are custom PID not listed in the SAE std .
if (requestedPIDhigh == 0x77)
{
if ((requestedPIDlow >= 0x01) && (requestedPIDlow <= 0x10))
{
// PID 0x01 (1 dec) to 0x10 (16 dec)
// Aux data / can data IN Channel 1 - 16
outMsg.buf[0] = 0x06; // sending 8 bytes
outMsg.buf[1] = 0x62; // Same as query, except that 40h is added to the mode value. So:62h = custom mode
outMsg.buf[2] = requestedPIDlow; // PID code
outMsg.buf[3] = 0x77; // PID code
outMsg.buf[4] = lowByte(currentStatus.canin[requestedPIDlow]); // A
outMsg.buf[5] = highByte(currentStatus.canin[requestedPIDlow]); // B
outMsg.buf[6] = 0x00; // C
outMsg.buf[7] = 0x00; // D
}
}
// this allows to get any value out of current status array.
else if (requestedPIDhigh == 0x78)
{
int16_t tempValue;
tempValue = ProgrammableIOGetData(requestedPIDlow);
outMsg.buf[0] = 0x06; // sending 6 bytes
outMsg.buf[1] = 0x62; // Same as query, except that 40h is added to the mode value. So:62h = custom mode
outMsg.buf[2] = requestedPIDlow; // PID code
outMsg.buf[3] = 0x78; // PID code
outMsg.buf[4] = lowByte(tempValue); // A
outMsg.buf[5] = highByte(tempValue); // B
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
case 0: //PID-0x00 PIDs supported 01-20
outMsg.buf[0] = 0x06; // sending 6 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x00; // PID code
outMsg.buf[3] = 0x08; //B0000 1000 1-8
outMsg.buf[4] = B01111110; //9-16
outMsg.buf[5] = B10100000; //17-24
outMsg.buf[6] = B00010001; //17-32
outMsg.buf[7] = B00000000;
break;
case 5: //PID-0x05 Engine coolant temperature , range is -40 to 215 deg C , formula == A-40
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x05; // pid code
outMsg.buf[3] = (byte)(currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); //the data value A
outMsg.buf[4] = 0x00; //the data value B which is 0 as unused
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 10: // PID-0x0A , Fuel Pressure (Gauge) , range is 0 to 765 kPa , formula == A / 3)
uint16_t temp_fuelpressure;
// Fuel pressure is in PSI. PSI to kPa is 6.89475729, but that needs to be divided by 3 for OBD2 formula. So 2.298.... 2.3 is close enough, so that in fraction.
temp_fuelpressure = (currentStatus.fuelPressure * 23) / 10;
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; //
outMsg.buf[2] = 0x0A; // pid code
outMsg.buf[3] = lowByte(temp_fuelpressure);
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 11: // PID-0x0B , MAP , range is 0 to 255 kPa , Formula == A
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; //
outMsg.buf[2] = 0x0B; // pid code
outMsg.buf[3] = lowByte(currentStatus.MAP); // absolute map
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 12: // PID-0x0C , RPM , range is 0 to 16383.75 rpm , Formula == 256A+B / 4
uint16_t temp_revs;
temp_revs = currentStatus.RPM << 2 ; //
outMsg.buf[0] = 0x04; // sending 4 byte
outMsg.buf[1] = 0x41; //
outMsg.buf[2] = 0x0C; // pid code
outMsg.buf[3] = highByte(temp_revs); //obdcalcB; A
outMsg.buf[4] = lowByte(temp_revs); //obdcalcD; B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 13: //PID-0x0D , Vehicle speed , range is 0 to 255 km/h , formula == A
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x0D; // pid code
outMsg.buf[3] = lowByte(currentStatus.vss); // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 14: //PID-0x0E , Ignition Timing advance, range is -64 to 63.5 BTDC , formula == A/2 - 64
int8_t temp_timingadvance;
temp_timingadvance = ((currentStatus.advance + 64) << 1);
//obdcalcA = ((timingadvance + 64) <<1) ; //((timingadvance + 64) *2)
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x0E; // pid code
outMsg.buf[3] = temp_timingadvance; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 15: //PID-0x0F , Inlet air temperature , range is -40 to 215 deg C, formula == A-40
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x0F; // pid code
outMsg.buf[3] = (byte)(currentStatus.IAT + CALIBRATION_TEMPERATURE_OFFSET); // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 17: // PID-0x11 ,
// TPS percentage, range is 0 to 100 percent, formula == 100/256 A
uint16_t temp_tpsPC;
temp_tpsPC = currentStatus.TPS;
obdcalcA = (temp_tpsPC <<8) / 100; // (tpsPC *256) /100;
if (obdcalcA > 255){ obdcalcA = 255;}
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x11; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 19: //PID-0x13 , oxygen sensors present, A0-A3 == bank1 , A4-A7 == bank2 ,
uint16_t O2present;
O2present = B00000011 ; //realtimebufferA[24]; TEST VALUE !!!!!
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x13; // pid code
outMsg.buf[3] = O2present ; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 28: // PID-0x1C obd standard
uint16_t obdstandard;
obdstandard = 7; // This is OBD2 / EOBD
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x1C; // pid code
outMsg.buf[3] = obdstandard; // A
outMsg.buf[4] = 0x00; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 32: // PID-0x20 PIDs supported [21-40]
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x20; // pid code
outMsg.buf[3] = B00011000; // 33-40
outMsg.buf[4] = B00000000; //41 - 48
outMsg.buf[5] = B00100000; //49-56
outMsg.buf[6] = B00000001; //57-64
outMsg.buf[7] = 0x00;
break;
case 36: // PID-0x24 O2 sensor2, AB: fuel/air equivalence ratio, CD: voltage , Formula == (2/65536)(256A +B) , 8/65536(256C+D) , Range is 0 to <2 and 0 to >8V
//uint16_t O2_1e ;
//int16_t O2_1v ;
obdcalcH16 = configPage2.stoich/10 ; // configPage2.stoich(is *10 so 14.7 is 147)
obdcalcE32 = currentStatus.O2/10; // afr(is *10 so 25.5 is 255) , needs a 32bit else will overflow
obdcalcF32 = (obdcalcE32<<8) / obdcalcH16; //this is same as (obdcalcE32/256) / obdcalcH16 . this calculates the ratio
obdcalcG16 = (obdcalcF32 *32768)>>8;
obdcalcA = highByte(obdcalcG16);
obdcalcB = lowByte(obdcalcG16);
obdcalcF32 = currentStatus.O2ADC ; //o2ADC is wideband volts to send *100
obdcalcG16 = (obdcalcF32 *20971)>>8;
obdcalcC = highByte(obdcalcG16);
obdcalcD = lowByte(obdcalcG16);
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x24; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = obdcalcB; // B
outMsg.buf[5] = obdcalcC; // C
outMsg.buf[6] = obdcalcD; // D
outMsg.buf[7] = 0x00;
break;
case 37: //O2 sensor2, AB fuel/air equivalence ratio, CD voltage , 2/65536(256A +B) ,8/65536(256C+D) , range is 0 to <2 and 0 to >8V
//uint16_t O2_2e ;
//int16_t O2_2V ;
obdcalcH16 = configPage2.stoich/10 ; // configPage2.stoich(is *10 so 14.7 is 147)
obdcalcE32 = currentStatus.O2_2/10; // afr(is *10 so 25.5 is 255) , needs a 32bit else will overflow
obdcalcF32 = (obdcalcE32<<8) / obdcalcH16; //this is same as (obdcalcE32/256) / obdcalcH16 . this calculates the ratio
obdcalcG16 = (obdcalcF32 *32768)>>8;
obdcalcA = highByte(obdcalcG16);
obdcalcB = lowByte(obdcalcG16);
obdcalcF32 = currentStatus.O2_2ADC ; //o2_2ADC is wideband volts to send *100
obdcalcG16 = (obdcalcF32 *20971)>>8;
obdcalcC = highByte(obdcalcG16);
obdcalcD = lowByte(obdcalcG16);
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x25; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = obdcalcB; // B
outMsg.buf[5] = obdcalcC; // C
outMsg.buf[6] = obdcalcD; // D
outMsg.buf[7] = 0x00;
break;
case 51: //PID-0x33 Absolute Barometric pressure , range is 0 to 255 kPa , formula == A
outMsg.buf[0] = 0x03; // sending 3 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x33; // pid code
outMsg.buf[3] = currentStatus.baro ; // A
outMsg.buf[4] = 0x00; // B which is 0 as unused
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 64: // PIDs supported [41-60]
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x40; // pid code
outMsg.buf[3] = B01000100; // 65-72dec
outMsg.buf[4] = B00000000; // 73-80
outMsg.buf[5] = B01000000; // 81-88
outMsg.buf[6] = B00010000; // 89-96
outMsg.buf[7] = 0x00;
break;
case 66: //control module voltage, 256A+B / 1000 , range is 0 to 65.535v
uint16_t temp_ecuBatt;
temp_ecuBatt = currentStatus.battery10; // create a 16bit temp variable to do the math
obdcalcA = temp_ecuBatt*100; // should be *1000 but ecuBatt is already *10
outMsg.buf[0] = 0x04; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x42; // pid code
outMsg.buf[3] = highByte(obdcalcA) ; // A
outMsg.buf[4] = lowByte(obdcalcA) ; // B
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 70: //PID-0x46 Ambient Air Temperature , range is -40 to 215 deg C , formula == A-40
uint16_t temp_ambientair;
temp_ambientair = 11; // TEST VALUE !!!!!!!!!!
obdcalcA = temp_ambientair + 40 ; // maybe later will be (byte)(currentStatus.AAT + CALIBRATION_TEMPERATURE_OFFSET)
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x46; // pid code
outMsg.buf[3] = obdcalcA; // A
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 82: //PID-0x52 Ethanol fuel % , range is 0 to 100% , formula == (100/255)A
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x52; // pid code
outMsg.buf[3] = currentStatus.ethanolPct; // A
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 92: //PID-0x5C Engine oil temperature , range is -40 to 210 deg C , formula == A-40
uint16_t temp_engineoiltemp;
temp_engineoiltemp = 40; // TEST VALUE !!!!!!!!!!
obdcalcA = temp_engineoiltemp+40 ; // maybe later will be (byte)(currentStatus.EOT + CALIBRATION_TEMPERATURE_OFFSET)
outMsg.buf[0] = 0x03; // sending 3 byte
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x5C; // pid code
outMsg.buf[3] = obdcalcA ; // A
outMsg.buf[4] = 0x00;
outMsg.buf[5] = 0x00;
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
break;
case 96: //PIDs supported [61-80]
outMsg.buf[0] = 0x06; // sending 4 bytes
outMsg.buf[1] = 0x41; // Same as query, except that 40h is added to the mode value. So:41h = show current data ,42h = freeze frame ,etc.
outMsg.buf[2] = 0x60; // pid code
outMsg.buf[3] = 0x00; // B0000 0000
outMsg.buf[4] = 0x00; // B0000 0000
outMsg.buf[5] = 0x00; // B0000 0000
outMsg.buf[6] = 0x00; // B0000 0000
outMsg.buf[7] = 0x00;
break;
default:
break;
}
}
else if (PIDmode == 0x22)
{
// these are custom PID not listed in the SAE std .
if (requestedPIDhigh == 0x77)
{
if ((requestedPIDlow >= 0x01) && (requestedPIDlow <= 0x10))
{
// PID 0x01 (1 dec) to 0x10 (16 dec)
// Aux data / can data IN Channel 1 - 16
outMsg.buf[0] = 0x06; // sending 8 bytes
outMsg.buf[1] = 0x62; // Same as query, except that 40h is added to the mode value. So:62h = custom mode
outMsg.buf[2] = requestedPIDlow; // PID code
outMsg.buf[3] = 0x77; // PID code
outMsg.buf[4] = lowByte(currentStatus.canin[requestedPIDlow]); // A
outMsg.buf[5] = highByte(currentStatus.canin[requestedPIDlow]); // B
outMsg.buf[6] = 0x00; // C
outMsg.buf[7] = 0x00; // D
}
}
// this allows to get any value out of current status array.
else if (requestedPIDhigh == 0x78)
{
int16_t tempValue;
tempValue = ProgrammableIOGetData(requestedPIDlow);
outMsg.buf[0] = 0x06; // sending 6 bytes
outMsg.buf[1] = 0x62; // Same as query, except that 40h is added to the mode value. So:62h = custom mode
outMsg.buf[2] = requestedPIDlow; // PID code
outMsg.buf[3] = 0x78; // PID code
outMsg.buf[4] = lowByte(tempValue); // A
outMsg.buf[5] = highByte(tempValue); // B
outMsg.buf[6] = 0x00;
outMsg.buf[7] = 0x00;
}
}
}
void readAuxCanBus()
{
for (int i = 0; i < 16; i++)
{
if (inMsg.id == (configPage9.caninput_source_can_address[i] + TS_CAN_OFFSET)) //Filters frame ID
uint16_t channelAddress = (configPage9.caninput_source_can_address[i] + TS_CAN_OFFSET);
if (inMsg.id == channelAddress ) //Filters frame ID
{
if (!BIT_CHECK(configPage9.caninput_source_num_bytes, i))
@ -524,10 +561,8 @@ void readAuxCanBus()
// Gets the one-byte value from the Data Field.
currentStatus.canin[i] = inMsg.buf[configPage9.caninput_source_start_byte[i]];
}
else
{
if (configPage9.caninputEndianess == 1)
{
//Gets the two-byte value from the Data Field in Litlle Endian.

View File

@ -16,6 +16,9 @@
#define TS_CAN_OFFSET 0x100
void initCAN();
int CAN_read();
void CAN_write();
void sendBMWCluster();
void sendVAGCluster();
void DashMessages(uint16_t DashMessageID);

View File

@ -207,7 +207,7 @@ void sendCancommand(uint8_t cmdtype, uint16_t canaddress, uint8_t candata1, uint
outMsg.buf[5] = 0x70;
outMsg.buf[6] = 0x9E;
outMsg.buf[7] = 0x4D;
Can0.write(outMsg);
CAN_write();
#endif
break;

View File

@ -8,6 +8,7 @@
#include "speeduino.h"
#include "timers.h"
#include "comms_secondary.h"
#include "comms_CAN.h"
#include "utilities.h"
#include "scheduledIO.h"
#include "scheduler.h"
@ -291,15 +292,7 @@ void initialiseAll(void)
//Setup the calibration tables
loadCalibration();
#if defined (NATIVE_CAN_AVAILABLE)
configPage9.intcan_available = 1; // device has internal canbus
//Teensy uses the Flexcan_T4 library to use the internal canbus
//enable local can interface
//setup can interface to 500k
Can0.begin();
Can0.setBaudRate(500000);
Can0.enableFIFO();
#endif
//Set the pin mappings
if((configPage2.pinMapping == 255) || (configPage2.pinMapping == 0)) //255 = EEPROM value in a blank AVR; 0 = EEPROM value in new FRAM
@ -310,11 +303,8 @@ void initialiseAll(void)
}
else { setPinMapping(configPage2.pinMapping); }
/* Note: This must come after the call to setPinMapping() or else pins 29 and 30 will become unusable as outputs.
* Workaround for: https://github.com/tonton81/FlexCAN_T4/issues/14 */
#if defined(CORE_TEENSY35)
Can0.setRX(DEF);
Can0.setTX(DEF);
#if defined(NATIVE_CAN_AVAILABLE)
initCAN();
#endif
//Must come after setPinMapping() as secondary serial can be changed on a per board basis

View File

@ -122,7 +122,7 @@ void loop(void)
{
//check local can module
// if ( BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ) or (CANbus0.available())
while (Can0.read(inMsg) )
while (CAN_read())
{
can_Command();
readAuxCanBus();