Code:
/* CCM Interaction Test Sketch for Arduino Mega 2560
This sketch pretends to be the PCM for a 1994 to 1995 Chevrolet Corvette.
It listens for the CCM poll request bytes (40 57 XX XX Checksum),
then sends the appropriate diagnostic string upon receipt.
The diagnostic string is idle values except for coolant temp,
which is either static (154C) or variable (based on ADC0 input).
This sketch only works on the 1994 to 1995 Corvette. It may work for 1996.
1990 Corvettes use shorter polls (40 55 6B) and have shorter responses.
To use for a 1990 Corvette, change the sliding window to 3 bytes
and just use the following match code without checksum ifs:
((window[0] == 0x40) && (window[1] == 0x55) && (window[2] == 0x6B))
Then comment out the top lines for output[21] and use output[15].
This sketch only works on the Arduino Mega 2560 family.
This is because we're using Serial1, UCSR1B, RXEN1, RXCIE1.
If you want to try it on a different board, change these accordingly.
*/
#include <avr/io.h>
#include <wiring_private.h>
byte window[5]; //define the 5-byte-wide sliding window
byte output[21]= {0x41, 0x67, 0x02, 0xF5, 0x00, 0xCD, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x48, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x40}; //define the static CTS message
//byte output[21]= {0x41, 0x67, 0x02, 0xF5, 0x00, 0x87, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x48, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x86}; //define the standard message
//byte output[15]= (0x41, 0x61, 0x00, 0xEC, 0x00, 0xCD, 0x39, 0x01, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x39, 0x45); //define 1990 Corvette CTS message
//byte output[15]= (0x41, 0x61, 0x00, 0xEC, 0x00, 0x39, 0x39, 0x01, 0x00, 0x00, 0x00, 0xB4, 0x00, 0x39, 0x12); //define 1990 Corvette standard message
void setup() {
analogReference(DEFAULT); //Switch to default reference explicitly
pinMode(A0, INPUT); //Make sure A0 is an input explicitly
bitSet (DIDR0, ADC0D); //Disable digital buffer on A0
bitSet (DIDR0, ADC1D); //Disable digital buffer on A1
bitSet (DIDR0, ADC2D); //Disable digital buffer on A2
bitSet (DIDR0, ADC3D); //Disable digital buffer on A3
bitSet (DIDR0, ADC4D); //Disable digital buffer on A4
bitSet (DIDR0, ADC5D); //Disable digital buffer on A5
bitSet (DIDR0, ADC6D); //Disable digital buffer on A6
bitSet (DIDR0, ADC7D); //Disable digital buffer on A7
bitSet (DIDR1, AIN0D); //Disable digital buffer on AIN0
bitSet (DIDR1, AIN1D); //Disable digital buffer on AIN1
bitSet (DIDR2, ADC8D); //Disable digital buffer on A8
bitSet (DIDR2, ADC9D); //Disable digital buffer on A9
bitSet (DIDR2, ADC10D); //Disable digital buffer on A10
bitSet (DIDR2, ADC11D); //Disable digital buffer on A11
bitSet (DIDR2, ADC12D); //Disable digital buffer on A12
bitSet (DIDR2, ADC13D); //Disable digital buffer on A13
bitSet (DIDR2, ADC14D); //Disable digital buffer on A14
bitSet (DIDR2, ADC15D); //Disable digital buffer on A15
analogRead(0); //Burn an analog reading on pin0
Serial1.begin(8192); //Open UART1 at 8192 baud
UBRR1H = (uint8_t)(121>>8);
UBRR1L = (uint8_t)121;
cbi(UCSR1A, U2X0); //disable 2x mode
cbi(UCSR1A, MPCM0); //disable multi-processor mode
}
void loop() {
if (Serial1.available()) {
// Slide the 5-byte window
for (uint8_t i = 0; i < 4; i++) {
window[i] = window[i + 1];
}
// Add new bytes as they come in
window[4] = Serial1.read();
// Check the first two bytes for a match
if ((window[0] == 0x40) && (window[1] == 0x57)) {
// Calculate the checksum byte
byte cs = 0;
for (uint8_t i = 0; i < 4; i++) {
cs += window[i];
}
cs = 0xFF - cs;
cs += 0x01;
// If checksum byte matches, send diagnostic data
if (cs == window[4]) {
window[0] = 0x00; //poison the sliding window
Serial1.write(output, sizeof(output));
Serial1.flush(); //wait until transmit completes
}
}
}
//Read A0 to check status of potentiometer, save to cts byte
//output[5] = analogRead(0)>>2;
//Calculate new checksum and save to checksum byte
//byte checksum = 0;
//for (uint8_t i = 0; i < 20; i++) {
//checksum += output[i];
//}
//checksum = 0xFF - checksum;
//checksum += 0x01;
//output[20] = checksum;
}
Bookmarks