can bus programming question

hey guys,

i'm running a citroen race car where i'd like to mount a ford fiesta electronic power steering unit into.
now the ford EPAS need can messages, i have the CAN ID's and data, no problem there, i was able to read these with the arduino with sparkfun canbus shield.

now i need to send the can messages which the EPAS needs.
i have an example sketch to use, but this only sends 1 ID and its messages.

void loop()
{
tCAN message;

message.id = 0x631; //formatted in HEX
message.header.rtr = 0;
message.header.length = 8; //formatted in DEC
message.data[0] = 0x40;
message.data[1] = 0x05;
message.data[2] = 0x30;
message.data[3] = 0xFF; //formatted in HEX
message.data[4] = 0x00;
message.data[5] = 0x40;
message.data[6] = 0x00;
message.data[7] = 0x00;

mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message);

delay(1000);

most of it understand and know how to adjust them to my needs. but this part

mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message);

is unclear to me...
the thing is i, need to send more then one ID and its messages. and i was wondering what the above part means and what it does, and if i need to replicate it when adding additional messages?

looking forward to learn more about the whole process and programming. i plan to add switches in the future coupled to different can messages. but i first would like to get it working in a very basic form :wink:

thanks!

There is an old thread to which this is a reply;

I realise this thread is ooolllddddd..... but, I'm sure you have to

mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);

before EVERY message. So...

mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message1);
...
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message2);
...
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message3);

??

If that post is correct the you can build lots of differnet messages then send them as above.
You should look up the documentation for;
mcp2515_bit_modify(CANCTRL,MODE_MASK,CAN_SETUP_MODE);

and print out the values for REQOP1, REQOP1 and REQOP2 as well as the result of the expression
(1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0)
so that you understand what the call does.

You would be best to fully test and debug your code before sending controls to an actual engine.

ok thanks!

where would i be looking for the documentation for mcp2515_bit_modify(CANCTRL,MODE_MASK,CAN_SETUP_MODE); ?

i dont have a second board to use as a sniffer but i guess my scope might be able to tell me if it's actually sending anything or not

hfcworks:
ok thanks!

where would i be looking for the documentation for mcp2515_bit_modify(CANCTRL,MODE_MASK,CAN_SETUP_MODE); ?

i dont have a second board to use as a sniffer but i guess my scope might be able to tell me if it's actually sending anything or not

You got the shield from Sparkfun so they should have links to the documentation for the library that you are using. Also just Google tutorials, manuals, spec sheets etc.

If you are going to send control commands to an engine then you need to consider what the worst thing that could happen, if your code goes wrong, might be. My code never works first time :disappointed_relieved: Before sending controls to a live system I would always setup something to play the part of the machinery (as far as possible) to make sure the coms were right. A test rig also gives you far more diagnostics about what is going wrong.

ok thanks!

not much can go wrong really, the motor's module only reads these codes to then go ahead and actually "activate" the software inside, all other things such as torque sensors and actually sending power to the electromotor are programmed inside the epas's module. so if it doesn't work nothing will actually happen.

well since we all have some spare time on our hands i decided to order another arduino and canbus shield so i could check wether the program is functioning as i'd like it or not and good thing i did. because i would have had quite some problems as it turns out

/****************************************************************************
CAN Write Demo for the SparkFun CAN Bus Shield.

Written by Stephen McCoy.
Original tutorial available here: http://www.instructables.com/id/CAN-Bus-Sniffing-and-Broadcasting-with-Arduino
Used with permission 2016. License CC By SA.

Distributed as-is; no warranty is given.
*************************************************************************/

#include <Canbus.h>
#include <defaults.h>
#include <global.h>
#include <mcp2515.h>
#include <mcp2515_defs.h>

//Setup Loop*//

void setup() {
Serial.begin(9600);
Serial.println("CAN Write - Testing transmission of CAN Bus messages");
delay(1000);

if(Canbus.init(CANSPEED_500)) //Initialise MCP2515 CAN controller at the specified speed
Serial.println("CAN Init ok");
else
Serial.println("Can't init CAN");

delay(1000);
}

//Main Loop*//

void loop()
{
tCAN message;

message.id = 0x631; //formatted in HEX
message.header.rtr = 0;
message.header.length = 8; //formatted in DEC
message.data[0] = 0x40;
message.data[1] = 0x05;
message.data[2] = 0x30;
message.data[3] = 0xFF; //formatted in HEX
message.data[4] = 0x00;
message.data[5] = 0x40;
message.data[6] = 0x00;
message.data[7] = 0x00;
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message);

delay(1000);
}

is the write demo.
this works and sends can ID 631 with the messages.

but i need to send at least 3 id's and their messages
so i change the code to

{
/****************************************************************************
CAN Write Demo for the SparkFun CAN Bus Shield.

Written by Stephen McCoy.
Original tutorial available here: http://www.instructables.com/id/CAN-Bus-Sniffing-and-Broadcasting-with-Arduino
Used with permission 2016. License CC By SA.

Distributed as-is; no warranty is given.
*************************************************************************/

#include <Canbus.h>
#include <defaults.h>
#include <global.h>
#include <mcp2515.h>
#include <mcp2515_defs.h>

//Setup Loop*//

void setup() {
Serial.begin(9600);
Serial.println("CAN Write - Testing transmission of CAN Bus messages");
delay(1000);

if(Canbus.init(CANSPEED_500)) //Initialise MCP2515 CAN controller at the specified speed
Serial.println("CAN Init ok");
else
Serial.println("Can't init CAN");

delay(1000);
}

//Main Loop*//

void loop()
{
tCAN message;

message.id = 0x631; //formatted in HEX
message.header.rtr = 0;
message.header.length = 8; //formatted in DEC
message.data[0] = 0x40;
message.data[1] = 0x05;
message.data[2] = 0x30;
message.data[3] = 0xFF; //formatted in HEX
message.data[4] = 0x00;
message.data[5] = 0x40;
message.data[6] = 0x00;
message.data[7] = 0x00;
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message);

message.id = 0x632; //formatted in HEX
message.header.rtr = 0;
message.header.length = 8; //formatted in DEC
message.data[0] = 0x40;
message.data[1] = 0x05;
message.data[2] = 0x30;
message.data[3] = 0xFF; //formatted in HEX
message.data[4] = 0x00;
message.data[5] = 0x40;
message.data[6] = 0x00;
message.data[7] = 0x00;
mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
mcp2515_send_message(&message);

delay(1000);

that also works and it sends both ID 631 and 632 with 1s delay. which is good

but if i add another one the same way it still only sends 631 and 632.
why is it not also sending the 633 then ? am i missing something here?

CAN_Write_Demo.ino (1.55 KB)

I do not use CAN bus so I am just looking at this cold.
If 161 and 162 go okay I would just change one of those to 163 to see what happens.

Also it seems like everything in 161 and 162 is the same apart from the message ID is that right?
If it is why to you reinitialise all the data each time, is something being returned in the message array?

Normally when you send instructions you get some kind of feedback to tell you what happened.
So when you call mcp2515_send_message is there not some way to determine if the call was successful or identify why it failed?

The reason for testing before sending to a real machine is the problem of accidentally sending a correct but unintended message. Imagine your CAN bus is controlling the "Nostromo". It sends a a garbage command to the Nostromo. Mother replies "WTF was that it was gibberish". Your CAN bus sends another message to the Nostromo. This time it is not what you intended to send but perfectly formatted and correct in every way. Mother relies "Command accept, self-destruct sequence initiated" - oops.

the messages from the ID's is indeed the same, but for the moment it's just for testing purpose. i'll get to filling in the correct ID's and messages when i get the code working as i like it

anyhow a friend suggested me to send the setup and code to his brother.
he then returned to me with the idea of adding a delay after each code since the canbus shield can only buffer 2 ID's.

and this solved the problem :slight_smile:

thanks for your time and honest opinion!

It depends on what your sketch needs to do but be aware that if you use the delay() function then your microprocessor is doing nothing else during that time.

If you need to do more than one thing at a time then it is best to avoid delay() and you should take a look at this code to see how to do that;