Do you have an oscilloscope or logic analyzer that you can use to verify signals? Viewing CANH/CANL and TX/RX signals would make quick work of troubleshooting.
FIFO Disabled
Mailboxes:
MB0 code: RX_EMPTY (Standard Frame)
MB1 code: RX_EMPTY (Standard Frame)
MB2 code: RX_EMPTY (Standard Frame)
MB3 code: RX_EMPTY (Standard Frame)
MB4 code: RX_EMPTY (Extended Frame)
MB5 code: RX_EMPTY (Extended Frame)
MB6 code: RX_EMPTY (Extended Frame)
MB7 code: RX_EMPTY (Extended Frame)
MB8 code: TX_INACTIVE
MB9 code: TX_INACTIVE
MB10 code: TX_INACTIVE
MB11 code: TX_INACTIVE
MB12 code: TX_INACTIVE
MB13 code: TX_INACTIVE
MB14 code: TX_INACTIVE
MB15 code: TX_INACTIVE
FIFO Disabled
Mailboxes:
MB0 code: RX_FULL
MB1 code: RX_FULL
MB2 code: RX_FULL
MB3 code: RX_OVERRUN
MB4 code: RX_EMPTY (Extended Frame)
MB5 code: RX_EMPTY (Extended Frame)
MB6 code: RX_EMPTY (Extended Frame)
MB7 code: RX_EMPTY (Extended Frame)
MB8 code: TX_INACTIVE
MB9 code: TX_INACTIVE
MB10 code: TX_INACTIVE
MB11 code: TX_INACTIVE
MB12 code: TX_INACTIVE
MB13 code: TX_INACTIVE
MB14 code: TX_INACTIVE
MB15 code: TX_INACTIVE
#include <FlexCAN_T4.h>
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> Can0;
void setup(void) {
Serial.begin(115200); delay(400);
pinMode(2, OUTPUT); digitalWrite(2, LOW); // enable tranceiver
Can0.begin();
Can0.setBaudRate(500000);
Can0.setMaxMB(16); // up to 64 max for T4, not important in FIFO mode, unless you want to use additional mailboxes with FIFO
Can0.enableFIFO();
Can0.enableFIFOInterrupt();
Can0.onReceive(canSniff);
Can0.mailboxStatus();
}
void canSniff(const CAN_message_t &msg) {
Serial.print("MB "); Serial.print(msg.mb);
Serial.print(" OVERRUN: "); Serial.print(msg.flags.overrun);
Serial.print(" LEN: "); Serial.print(msg.len);
Serial.print(" EXT: "); Serial.print(msg.flags.extended);
Serial.print(" TS: "); Serial.print(msg.timestamp);
Serial.print(" ID: "); Serial.print(msg.id, HEX);
Serial.print(" Buffer: ");
for ( uint8_t i = 0; i < msg.len; i++ ) {
Serial.print(msg.buf[i], HEX); Serial.print(" ");
} Serial.println();
}
void loop() {
Can0.events();
static uint32_t timeout = millis();
if ( millis() - timeout > 20 ) { // send random frame every 20ms
CAN_message_t msg;
msg.id = random(0x1,0x7FE);
for ( uint8_t i = 0; i < 8; i++ ) msg.buf[i] = i + 1;
Can0.write(msg);
timeout = millis();
}
}
FIFO Enabled --> Interrupt Enabled
FIFO Filters in use: 8
Remaining Mailboxes: 8
MB8 code: TX_INACTIVE
MB9 code: TX_INACTIVE
MB10 code: TX_INACTIVE
MB11 code: TX_INACTIVE
MB12 code: TX_INACTIVE
MB13 code: TX_INACTIVE
MB14 code: TX_INACTIVE
MB15 code: TX_INACTIVE
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 40290 ID: 7E8 Buffer: 3 7F 2 31 55 55 55 55
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 34684 ID: 7E8 Buffer: 3 7F 2 31 55 55 55 55
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 44981 ID: 7DF Buffer: 2 1 0 0 0 0 0 0
MB 99 OVERRUN: 0 LEN: 7 EXT: 0 TS: 55476 ID: 7E8 Buffer: 6 41 0 FF FF FF FF
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 40179 ID: 7DF Buffer: 2 1 0 0 0 0 0 0
MB 99 OVERRUN: 0 LEN: 7 EXT: 0 TS: 49934 ID: 7E8 Buffer: 6 41 0 FF FF FF FF
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 13198 ID: 7DF Buffer: 2 1 0 0 0 0 0 0
MB 99 OVERRUN: 0 LEN: 7 EXT: 0 TS: 23311 ID: 7E8 Buffer: 6 41 0 FF FF FF FF
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 34185 ID: 7DF Buffer: 2 1 20 0 0 0 0 0
MB 99 OVERRUN: 0 LEN: 7 EXT: 0 TS: 45268 ID: 7E8 Buffer: 6 41 20 FF FF FF FF
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 50372 ID: 7DF Buffer: 2 1 40 0 0 0 0 0
MB 99 OVERRUN: 0 LEN: 7 EXT: 0 TS: 62225 ID: 7E8 Buffer: 6 41 40 FF FF FF FE
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 42899 ID: 7DF Buffer: 2 9 A 0 0 0 0 0
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 54184 ID: 7E8 Buffer: 10 17 49 A 1 45 43 4D
MB 99 OVERRUN: 0 LEN: 8 EXT: 0 TS: 54317 ID: 7E0 Buffer: 30 0 0 0 0 0 0 0
oh, yeah. that could explain it. i just got a sample book in so i'll try 33pF. C6 was chosen fairly large as it shouldn't be switched during normal opperation, should i use a smaller cap there?
Edit: placed the 10k back and a C5 as an 33pF cap and it works!!!!!
While browsing this thread I have seen someone working with MS.
https://forum.pjrc.com/threads/5603...sy-4?p=231492&highlight=Megasquirt#post231492
Got a fresh bare SN65HVD230 working. 10k from RS to ground, 100R across CANH and CANL. That was all. Seems that the breakout board I originally bought was duff.
Tempted to try out the TN330/332 as that seems newer and... probably better? Also saves me a 10k resistor by the looks of it.
I have a question regards mailboxes and what's the real use case for them.
MegaSquirt spits out data - e.g byte 2 and 3 from ID 1520 is RPM - for instance. IDs have multiple pieces of information. What's the most efficient way of processing this?
I presume I setup mailboxes filtered or each ID that I want to capture, and then in the interrupt routine I then parse the frame into my programs variables?
The other option would be to just keep a cache of can messages in an array - 1520 -> [0], 1521 -> [1] etc - and only process them when I need them (I don't need all of the variables all of the time, I only need them when I want to display them)
Regarding adding the 'new data' flag, that's a good idea. If your msg unpacking routine is intensive, you might just copy your message from the interrupt to a global, set a 'new msg 1501' flag, then later unpack it in loop().
void setup() {
Serial.begin(115200);
can.begin();
can.setBaudRate(500000);
can.enableFIFO();
can.enableFIFOInterrupt();
can.onReceive(decodeCAN);
}
void loop() {
if (update) {
update = false;
Serial.println(ms.rpm);
}
}
void decodeCAN(const CAN_message_t &msg) {
MSCAN.getBCastData(msg.id, msg.buf, ms);
update = true;
}
If you are using a library like MegaCAN, which will parse the message IDs and data, fifo with interrupt probably makes the most sense.
if you don't use events(), message reception is fired directly to callbacks. I too use CAN button counting for OEM keyfob to control windows and sunroof, obviously you need to count them not in the callback scope only, I used a circular buffer to store the count, you could also use a volatile variable, I used a queue because i can look into the buffer to see the last button pressed (not only count) to engage the feature I want
int volatile clickCounter = 0;
int checkNumClicks(void){
static unsigned long max_delay = 800;
int returnVal = 0;
//Serial.print("before Adding to Counter");
//Serial.println(clickCounter);
clickCounter += 1;
//Serial.print("After Adding to Counter");
//Serial.println(clickCounter);
lastButtonPress = millis();
while((millis() - lastButtonPress < max_delay) && clickCounter == 1){
can1.events(); //NEED to CHECK FOR CAN MESSAGES WHILE YOU ARE WAITING FOR COUNTER TO INCREMENT!
if (clickCounter == 2){
Serial.println("Button pressed twice!");
returnVal = 2;
clickCounter = 0;
lastButtonPress = millis();
break;
return(returnVal); //I don't think this actually does anything.
}
}
if (clickCounter == 1){
Serial.println("Button pressed once!");
clickCounter = 0;
returnVal = 1;
lastButtonPress = millis();
return(returnVal);
}
return (returnVal);
}