I have a weird problem while setting up Arduino CAN Bus Communication.
Description follows below, this video shows the result: https://www.youtube.com/watch?v=NnMyC23Fe9s&feature=youtu.be
(Remark: This effect happens with every board I tried)
Hardware:
- Different Arduino or Arduino-Equal boards (currently an AZ-Delivery UNO, also tried with an Arduino Mega and an Arduino UNO.
- CAN Bus Shield (V1.2) from SeedStudio (see https://github.com/Seeed-Studio/CAN_BUS_Shield )
Used software: https://github.com/Seeed-Studio/CAN_BUS_Shield/blob/master/examples/send/send.ino
I started with the full setup with 2 of my Arduinos (not the Mega, it's not compatible) and 2 CAN Bus shields and was wondering, that the initialisation failed and than suddendly succeeded. I guessed it was about soldering the pins so I reworked that but it didn't get better.
After a lot of tests, I came up with the result you see in the video: I don't even need a CAN Bus Shield to initialize a CAN Bus Shield O_o. If I touch the SPI interface, it recognizes me as a CAN Bus Shield.
Going through the CAN BUS Library I checked the function CAN.begin. It uses the ISP pins (those 6 pins in 2 rows) to:
- Write values to an address via SPI
- Read two values from another address via SPI
Code to read via SPI (all from the Library no own code!)
uint8_t MCP2515Class::readRegister(uint8_t address)
{
uint8_t value;
SPI.beginTransaction(_spiSettings);
digitalWrite(_csPin, LOW);
SPI.transfer(0x03);
SPI.transfer(address);
value = SPI.transfer(0x00);
digitalWrite(_csPin, HIGH);
SPI.endTransaction();
return value;
}
And the CAN.begin function
int MCP2515Class::begin(long baudRate)
{
CANControllerClass::begin(baudRate);
pinMode(_csPin, OUTPUT);
// start SPI
SPI.begin();
reset();
writeRegister(REG_CANCTRL, 0x80);
if (readRegister(REG_CANCTRL) != 0x80) {
return 0;
}
const struct {
long clockFrequency;
long baudRate;
uint8_t cnf[3];
} CNF_MAPPER[] = {
{ (long)8E6, (long)1000E3, { 0x00, 0x80, 0x00 } },
{ (long)8E6, (long)500E3, { 0x00, 0x90, 0x02 } },
{ (long)8E6, (long)250E3, { 0x00, 0xb1, 0x05 } },
{ (long)8E6, (long)200E3, { 0x00, 0xb4, 0x06 } },
{ (long)8E6, (long)125E3, { 0x01, 0xb1, 0x05 } },
{ (long)8E6, (long)100E3, { 0x01, 0xb4, 0x06 } },
{ (long)8E6, (long)80E3, { 0x01, 0xbf, 0x07 } },
{ (long)8E6, (long)50E3, { 0x03, 0xb4, 0x06 } },
{ (long)8E6, (long)40E3, { 0x03, 0xbf, 0x07 } },
{ (long)8E6, (long)20E3, { 0x07, 0xbf, 0x07 } },
{ (long)8E6, (long)10E3, { 0x0f, 0xbf, 0x07 } },
{ (long)8E6, (long)5E3, { 0x1f, 0xbf, 0x07 } },
{ (long)16E6, (long)1000E3, { 0x00, 0xd0, 0x82 } },
{ (long)16E6, (long)500E3, { 0x00, 0xf0, 0x86 } },
{ (long)16E6, (long)250E3, { 0x41, 0xf1, 0x85 } },
{ (long)16E6, (long)200E3, { 0x01, 0xfa, 0x87 } },
{ (long)16E6, (long)125E3, { 0x03, 0xf0, 0x86 } },
{ (long)16E6, (long)100E3, { 0x03, 0xfa, 0x87 } },
{ (long)16E6, (long)80E3, { 0x03, 0xff, 0x87 } },
{ (long)16E6, (long)50E3, { 0x07, 0xfa, 0x87 } },
{ (long)16E6, (long)40E3, { 0x07, 0xff, 0x87 } },
{ (long)16E6, (long)20E3, { 0x0f, 0xff, 0x87 } },
{ (long)16E6, (long)10E3, { 0x1f, 0xff, 0x87 } },
{ (long)16E6, (long)5E3, { 0x3f, 0xff, 0x87 } },
};
const uint8_t* cnf = NULL;
for (unsigned int i = 0; i < (sizeof(CNF_MAPPER) / sizeof(CNF_MAPPER[0])); i++) {
if (CNF_MAPPER[i].clockFrequency == _clockFrequency && CNF_MAPPER[i].baudRate == baudRate) {
cnf = CNF_MAPPER[i].cnf;
break;
}
}
if (cnf == NULL) {
return 0;
}
writeRegister(REG_CNF1, cnf[0]);
writeRegister(REG_CNF2, cnf[1]);
writeRegister(REG_CNF3, cnf[2]);
writeRegister(REG_CANINTE, FLAG_RXnIE(1) | FLAG_RXnIE(0));
writeRegister(REG_BFPCTRL, 0x00);
writeRegister(REG_TXRTSCTRL, 0x00);
writeRegister(REG_RXBnCTRL(0), FLAG_RXM1 | FLAG_RXM0);
writeRegister(REG_RXBnCTRL(1), FLAG_RXM1 | FLAG_RXM0);
writeRegister(REG_CANCTRL, 0x00);
if (readRegister(REG_CANCTRL) != 0x00) {
return 0;
}
return 1;
}
2 questions:
- How is this even possible, the system should differentiate between propper reading and a simple error, shouldn't it?
- What can I do to get this thing running?