I'm working on a project where I have to analyze the impact of electromagnetic interferences on the CAN bus protocol.
For this, I just send a message (it is a counter 0 to 255) with one Arduino mega and I receive it in the other Arduino.
Then I put my project in a very high EMI situation (room with motors) and analyze the number of errors that occurred during the emission. For this, I would like to access and show the information in the registers 6-1 (transmit error counter), 6-2 (receiver error counter) and 6-3 (error flag) of the CAN controller.
So my question is: How can I access to this registers and more importantly how do i extract the information via Arduino so that i can maybe print it in the serial monitor like:
Errors ocurred: xxxx
Error type: yyyy
In this project, I am using a mcp2515 CAN bus protocol. You can find the datasheet here:
I'm working on a project where I have to analyze the impact of electromagnetic interferences on the CAN bus protocol.
For this, I just send a message (it is a counter 0 to 255) with one Arduino mega and I receive it in the other Arduino.
Then I put my project in a very high EMI situation (room with motors) and analyze the number of errors that occurred during the emission. For this, I would like to access and show the information in the registers 6-1 (transmit error counter), 6-2 (receiver error counter) and 6-3 (error flag) of the CAN controller.
So my question is: How can I access to this registers and more importantly how do i extract the information via Arduino so that i can maybe print it in the serial monitor like:
Errors ocurred: xxxx
Error type: yyyy
Are your only interested in knowing the number of errors, or also what type of error (stuff bit error, frame error, etc).
For the latter the MCP2515 does not appear capable to discriminate the error types.
If you want more information than that provided by the MCP2515 you could do a real-time 'diff' between the signal going to the sending transceiver and the signal coming out of the receiving transceiver in order to see how badly the bits are getting messed up.
If the bit patterns are different, then by definition there is an error as CAN doesn't do error correction.
sherzaad:
not sure if that is what mikb55 meant but I think a very simple way to achieve this is using a counter on the RX and TX side.
for every tx message counter goes up. same for rx message read
provided the transfer rate is sensible, in an OK condition (ie no error) the counters should match perfectly.
if there are errors in the transmission, messages will start getting dropped on the rx side.
If you are working at the Arduino level then you will need to limit the number of messages to a few hundred per second per second otherwise the SPI interface and the receiving Arduino cannot keep up. The sender will also need to check the return value from every 'send' as sometimes the tx buffer will be full in which case you cannot increment the Tx counter.
Okay so let me see if I keep up with you guys: You are telling me to make a counter on the sender that for each message I send it increase by one the counter. Then the message arrives at the receiver so the receiver counter is increased by one? Finally, I compare these 2 counters to know how many messages were not ok?
Mephirius:
Okay so let me see if I keep up with you guys: You are telling me to make a counter on the sender that for each message I send it increase by one the counter. Then the message arrives at the receiver so the receiver counter is increased by one? Finally, I compare these 2 counters to know how many messages were not ok?
Thanks!
That is one method, however, this hides the underlying CAN behaviour which by default will make multiple attempts to send a message, so a successful send and receive as registered by the Arduinos may actually require multiple send attempts at the CAN level.
Mephirius:
So by doing this method, I would probably not experiment any errors since the CAN will just resend until its a correct message right?
You might get a meaningful result by seeing how many messages per second can be sent and received under different conditions. Pick an achievable number such as 400 per second then see if the rate goes down when interference is present.
Errors and retries will cause the Tx buffer to fill up faster than it is being emptied. Eventually the rate at which the sender is able to send messages will be determined by how often there is a free slot in the Tx buffer.
Hmmm, I understand... I am surprised that there is not a simplest way to read the errors that occurred during the transmission. Reading the MCP2515 datasheet (pages 47-50) I found there are 3 registers (2 of them are counters for the transmit error and the receive error) I would like to know if it is possible to access to this registers and extract the info in them... so this way I will be able to know how many errors ocurred.
Mephirius:
Hmmm, I understand... I am surprised that there is not a simplest way to read the errors that occurred during the transmission. Reading the MCP2515 datasheet (pages 47-50) I found there are 3 registers (2 of them are counters for the transmit error and the receive error) I would like to know if it is possible to access to this registers and extract the info in them... so this way I will be able to know how many errors ocurred.
Sure I think this is what I'm searching for, I have been trying out to implement these functions to my code but as I am an Arduino beginner I can not make them work... any help may be useful!
These are the instructions I am interested to run in my code:
So, where are you placing these functions and what errors do you get?
Because mcp2515_readRegister is a private function, you would need to add the functions to the library code in the mcp_can.cpp file, otherwise you cannot call the readRegister function. You will also need to add the function declaration to the public part of the mcp_can.h file. Then you should be able to call the function from your code.
The MCP2515 is controlled over SPI. SPI can run a lot faster than CAN so you should be able to easily saturate the bus with messages. Whether the SPI port is configured to run fast enough is another question. The Seed library seems to set it to 10MHz, so should not be an issue. If in doubt measure the signal at the SPI CLK pin.
Check out the chapter on errors in the MCP2515 datasheet. If you get too many errors and you do not handle the errors for instance in error interrupt service routine the module will stop sending/receiving messages. This is done to make sure a node that might create these errors will stop taking part in the communication and the other nodes can keep on communicating. When the bus stays idle for a while the MCP2515 will try to continue its duty.
Regarding the errors, you should do two things. Read the error registers and count the messages per second. This will give you a way of verifying your results. When the number of messages go down you should see more errors in your TEC/REC counter.
You can verify the error handling by adding a third CAN node that will send messages with a higher priority from time to time. Because you are sending as many messages as you can whenever the third note sends messages you should get conflicts and transmit errors but no receive errors.
Mephirius:
Sure I think this is what I'm searching for, I have been trying out to implement these functions to my code but as I am an Arduino beginner I can not make them work... any help may be useful!
These are the instructions I am interested to run in my code:
Okay, Klaus, I am going to try to add the functions to the .cpp and .h files and test them... but in any case, I read the error part on the MCP2515 datasheet and it seems like TEC and REC counters increases and decreases?? even tho I achieve to read this counters how will I be able to know how many errors ocurred?
I think I just don't understand you in this part: "When the number of messages go down you should see more errors in your TEC/REC counter."
Also, I am not expecting to have more than 127 errors so I shouldn't expect changes on Error Mode (I will always be on Error-passive).
Mikb55 What do you mean by "these were written for"? Are all of these functions already declared on the .cpp and .h files? Because comparing both mcp_can.cpp of each library it is the same... Why would it be easier to switch to this library?
Your CAN bus will have a maximum number of messages it can send per second. This depends on the bitrate, ID length and data length. Because you are sending fixed messages you can calculate how many messages per second you can send. If you send messages as fast as possible, every time a message is repeated because of an error you will see a lower message count, when this happens you should see the error count go up.
to read the register TEC And REC, how do I change them from being a private function to public of both archives of the library (mcp_can.h and mcp_can.cpp).