CAN bus transport implementation
-
Gateway Logs on MyController
(CAN Bus and RS485 Bus)two separate files
CAN log
RS485 logfiles split in parts :
A : gateways startup
B : reboot of the gateways
C : launch of MyClock Nodes (id23 and id55)
D ; periodic refresh requestTime(receiveTime)
E ; send value (1700 and 2100)(I have prepared the work for you to read)
a 1st analysis
- (at the bottom of the listing, the sending of values "1700 or 2100" with MyC)
The RS485 bus dialogues much more, the CAN bus is more timid :)
Adam Slowik bravo
I test what now???
the ACK ??Oh yes, I have to check the disconnection of the nodes.
The Gateway gives me the impression that the information does not go back to MyC if a Node is off ??? - (at the bottom of the listing, the sending of values "1700 or 2100" with MyC)
-
@JeeLet said in CAN bus transport implementation:
I test what now???
I was at similar position some time ago:
@Adam-Slowik said in CAN bus transport implementation:
Any suggestion what to test next?
I have no idea what to test next. I do not use MySensors. I hope this will change in the future, but as of now I'm a newbie.
If You won't get any advice from more experienced users I would suggest to do some long running test to see if it's stable. If it's stable try to use it in some real use cases.
If You find any bugs in transmission layer post logs here. I will do My best to support CAN, because I will need it in a future.
-
" I would suggest doing a long term test to see if it is stable." yes I will stress it to see the weakness
".. If it is stable, try to use it in real use cases." yes that's the point
One last question
I'm going from 8Mhz to 16Mhz (in development/MyConfig.h on line 306)
question: can you explain how I can bring up in the sketch the parameters that are related to the MCP_CAN_lib library
it should not be complicated for me :) it is only text to insert ???
an example with the #define CAN_CLOCK MCP_8MHZ
Thanks Adam Slowik
-
@JeeLet said in CAN bus transport implementation:
I'm going from 8Mhz to 16Mhz (in development/MyConfig.h on line 306)
In My opinion You should not override MyConfig.h. If You want to go for 16MHz You should put:
#define CAN_CLOCK MCP_16MHZin Your sketch. Preferably somewhere around line:
#define MY_CAN@JeeLet said in CAN bus transport implementation:
can you explain how I can bring up in the sketch the parameters that are related to the MCP_CAN_lib library
If it's a parameter that is listed in MyConfig.h simply define it like 'CAN_CLOCK'. If parameter is not listed in MyConfig please let me know exactly what parameter You would like to modify, then I will try to figure it out.
-
-
I'm not sure if We understood each other. This line
#define CAN_CLOCK MCP_16MHZshould be in Your sketch. You should not modify MyConfig.h.
Libraries (in general not only MySensors) should not be modified. MyConfig.h is part of library.Let's take a look at this code from MyConfig.h
#ifndef CAN_CLOCK #define CAN_CLOCK MCP_8MHZ #endif.This is if statement. If user didn't defined
CAN_CLOCKdefine it asCAN_CLOCK MCP_8MHZ
If user defined (in sketch)CAN_CLOCKthen do nothing.So You can treat MyConfig.h as a set of defaults which can be overridden from sketch.
I have put all relevant (in My opinion) properties from
MCP_CAN_libinto MyConfig.h, so You can override them. If I have missed some relevant property please let Me know. -
Thank you for this clarification.
(yes translator and my neuron it gives crooked dialog)"If I have missed a relevant property, please let me know."
The list of #define go up for the MySensors sketch .
( if I'm not mistaken ?)***for MCP_CAN_lib **************** MyConfig.h line 280 to 315 CAN_INT // Pin for interrupting an incoming message. CAN_CS // Chip selection pin. CAN_SPEED // Transmission speed. The allowed values can be found in mcp_can_dfs.h CAN_CLOCK // Can clock. Allowed values can be found in mcp_can_dfs.h. CAN_BUF_SIZE // Assembly buffer size. As long messages can be split and arrive mixed with other messages, an assembly buffer is needed. **** for MyS **************** MyConfig.h line 2492 to 2494 MY_CAN // Set this to use the CAN wire transport for sensor network communication. MY_DEBUG_VERBOSE_CAN // Set this for verbose debugging printouts related to the %CAN driver.can be added, for testing and controlling the CAN bus
#define CAN_MSGAVAIL #define CAN_OK #define CAN_CTRLERRORThanks
return of the last 24 hours .
CAN bus no error, good dialogue, no hole in the measurements and commands.the hardware base on the bus is :
gateway + node 55 + node 56 .I will add another node 57.
I think to go until 6 nodes -
@JeeLet said in CAN bus transport implementation:
The list of #define go up for the MySensors sketch .
( if I'm not mistaken ?)You are right.
@JeeLet said in CAN bus transport implementation:
can be added, for testing and controlling the CAN bus
#define CAN_MSGAVAIL
#define CAN_OK
#define CAN_CTRLERRORI'm afraid i do not understand what You want to achieve.
To clarify things lets look atCAN_CLOCKCAN_CLOCKcan take values: 0 or 1 or 2 those values are defined in mcp_can_dfs.h:#define MCP_20MHZ 0 #define MCP_16MHZ 1 #define MCP_8MHZ 2If You want to use 8MHz You can
#define CAN_CLOCK 2
or
#define CAN_CLOCK MCP_8MHZ
Both lines will do the same. However#define CAN_CLOCK MCP_8MHZis recommended approach.
SoCAN_CLOCKcan take one of values values (0,1,2), and user (based on used hardware) should pick one of them.Next example could be
CAN_INT. User should be able to pick which interrupt pin should be used.Now when it comes to:
#define CAN_MSGAVAIL #define CAN_OK #define CAN_CTRLERRORin
mcp_can_dfs.hWe can find a section:#define CAN_OK (0) #define CAN_FAILINIT (1) #define CAN_FAILTX (2) #define CAN_MSGAVAIL (3) #define CAN_NOMSG (4) #define CAN_CTRLERROR (5) #define CAN_GETTXBFTIMEOUT (6) #define CAN_SENDMSGTIMEOUT (7) #define CAN_FAIL (0xff)This We can treat as return code dictionary.
For example when I initialize CAN in MyTransportCAN.cpp:if (CAN0.begin(MCP_STDEXT, CAN_SPEED, CAN_CLOCK) != CAN_OK) { canInitialized = false; return false; } canInitialized = true;I could write
if (CAN0.begin(MCP_STDEXT, CAN_SPEED, CAN_CLOCK) != 0but recommended approach is to use dictionary key (CAN_OK) instead of dictionary value (0)Now overriding
CAN_OKto777instead of0is possible, but it won't cause nothing but chaos. If We do that the functionCAN0.begin(MCP_STDEXT, CAN_SPEED, CAN_CLOCK)would return777instead of0. I don't think user should do that.Code from
mcp_can.cpp:INT8U MCP_CAN::checkReceive(void) { INT8U res; res = mcp2515_readStatus(); /* RXnIF in Bit 1 and 0 */ if (res & MCP_STAT_RXIF_MASK) { return CAN_MSGAVAIL; } else { return CAN_NOMSG; } }This function returns dictionary key
CAN_MSGAVAILorCAN_NOMSGbut if We could stop in debug We would see3or4
Again overridingCAN_MSGAVAILto let's say42won't give user nothing.@JeeLet said in CAN bus transport implementation:
return of the last 24 hours .
CAN bus no error, good dialogue, no hole in the measurements and commands.
the hardware base on the bus is :
gateway + node 55 + node 56 .
I will add another node 57.
I think to go until 6 nodesI keep My fingers crossed. Great job.
-
The original idea was: how to check the status of the CAN bus.
. is there any dialogue ?
. are there any messages?of course this can be done with MySensors.
But to get as close as possible to the communication channel (the CAN bus) I thought it was easy to do.
this is by reading the post of bricoleau here
text french
that the idea came to me.- on the arduino have a blinking led to say that the CAN bus is out of order (but we forget, it loads the program unnecessarily)
and also because you suggested it to me
yes we have to beat the iron when it is hot, and my time available for the computer will soon be reduced (purchase and work of a house)I appreciate very much your explanatory note, thank you
I activated the 16Mhz in the sketch, and put it back in the library
#define MY_NODE_ID 57 /*Node en ID static*/ #define MY_CAN #define CAN_CLOCK MCP_16MHZ -
The original idea was: how to check the status of the CAN bus.
. is there any dialogue ?
. are there any messages?of course this can be done with MySensors.
But to get as close as possible to the communication channel (the CAN bus) I thought it was easy to do.
this is by reading the post of bricoleau here
text french
that the idea came to me.- on the arduino have a blinking led to say that the CAN bus is out of order (but we forget, it loads the program unnecessarily)
and also because you suggested it to me
yes we have to beat the iron when it is hot, and my time available for the computer will soon be reduced (purchase and work of a house)I appreciate very much your explanatory note, thank you
I activated the 16Mhz in the sketch, and put it back in the library
#define MY_NODE_ID 57 /*Node en ID static*/ #define MY_CAN #define CAN_CLOCK MCP_16MHZ@JeeLet said in CAN bus transport implementation:
The original idea was: how to check the status of the CAN bus.
. is there any dialogue ?
. are there any messages?
of course this can be done with MySensors.
But to get as close as possible to the communication channel (the CAN bus) I thought it was easy to do.That is something I can work with. I will check if used library provides some function to check bus status.
@JeeLet said in CAN bus transport implementation:
my time available for the computer will soon be reduced (purchase and work of a house)
I totally understand.
-
So library gives us 3 interesting functions:
INT8U checkError(void); INT8U errorCountRX(void); INT8U errorCountTX(void);Full description can be found in library source code and in documentation chapter 6:
https://ww1.microchip.com/downloads/en/DeviceDoc/MCP2515-Stand-Alone-CAN-Controller-with-SPI-20001801J.pdflong story short:
INT8U checkError(void);returns:
-CAN_CTRLERRORwhen things are bad or very bad
-CAN_OKwhen things are ok or not so bad (error counters below 96)
I would like to chage implementation of sanity check to something like this:
bool transportSanityCheck(void) { return (CAN0.getError()==CAN_OK) }It won't blink diodes in case of communication problems, but will provide some feedback about communication to MySensors library.
2)
INT8U errorCountRX(void);return error counter for received messages. AFAIK this counter is incremented when error occurs and decremented when message is received. I'm not a 'radio guy' but i think this could be returned asint16_t transportGetReceivingSNR(void)orint16_t transportGetReceivingRSSI(void). I know SNR and RSSI are radio related parameters, but perhaps We could bend the border here. Maybe some 'radio guy' could say something about this idea?3)
INT8U errorCountTX(void);same situation as with #2. 'Radio guy' opinion would by great.Again ideas #2 and #3 are not solving problems, but providing feedback to MySensors.
Are My ideas ok, or do they do not pass
sanityCheck():) -
"Are my ideas good" .. yes yes c'est tout bon
"It will not flash the diodes in case of communication problems" ... it's not a problem, Christmas is still far :)
But yes a counter that increments is a good thing.
what do you want me to test ????
bool transportSanityCheck(void) { return (CAN0.getError()==CAN_OK) }The "radio guy" opinion would be great.
((I'll look for possible help ). )Re-Edit
hal/transport/CAN/MyTransportCAN.cpp
bool transportSanityCheck(void) { // not implemented yet return true; }:stuck_out_tongue_winking_eye:
Edit
I searched the web, and using SNR RSSI with the CAN bus is a dead end.
https://www.thethingsnetwork.org/docs/lorawan/rssi-and-snr/ -
Are You still have an issue when
MY_DEBUGis deactivated? Have You tried to add delay as is was suggested in one of the threads You found? -
@Adam-Slowik, @JeeLet
Ok, I will give CAN-Bus a try. This is my test setup:
I will use the demo sketches from Adam's fork. Let you know how it works for me.
-
"Are my ideas good" .. yes yes c'est tout bon
"It will not flash the diodes in case of communication problems" ... it's not a problem, Christmas is still far :)
But yes a counter that increments is a good thing.
what do you want me to test ????
bool transportSanityCheck(void) { return (CAN0.getError()==CAN_OK) }The "radio guy" opinion would be great.
((I'll look for possible help ). )Re-Edit
hal/transport/CAN/MyTransportCAN.cpp
bool transportSanityCheck(void) { // not implemented yet return true; }:stuck_out_tongue_winking_eye:
Edit
I searched the web, and using SNR RSSI with the CAN bus is a dead end.
https://www.thethingsnetwork.org/docs/lorawan/rssi-and-snr/what do you want me to test ????
bool transportSanityCheck(void) { return (CAN0.getError()==CAN_OK) }The "radio guy" opinion would be great.
((I'll look for possible help ). )I'm not a "radio guy", but I think this code change looks fine. When sanity check fails then MySensors core calls transportInit() which would try to re-initialise the MCP2515 module.
In my setup with only 2 CAN modules I'm afraid this will always return CAN_OK. So no idea how to check this. May be unplug the both CAN wires?
-
@Adam-Slowik, @JeeLet Ok, with the both sketches it works with some limitations.
Nice work so far - thank you for contributing!I have done some modifications in the CAN transport files.
@Adam-Slowik I would like to create a PR in your forked repo. Then we can discuss the code changes in GitHub. Would that be Ok for you - do you have time for this?One limitation I found so far are long MyMessages. They can be up to 32 byte - which results in up to 4 CAN-Bus sub telegrams. When I send 32 byte message I observed the sub telegrams do not always arrive in send order in MyTransportCAN.cpp like this:
19916 CAN:RCV:CANH=2202010368,ID=3,TOTAL=4,CURR=0,TO=3,FROM=0 19921 CAN:RCV:LN=8,DTA0=0,DTA1=0,DTA2=3,DTA3=202,DTA4=9,DTA5=2,DTA6=0,DTA7=49 19929 CAN:RCV:SLOT=0,PART=1 19932 CAN:RCV:CANH=2202075904,ID=3,TOTAL=4,CURR=1,TO=3,FROM=0 19937 CAN:RCV:LN=8,DTA0=50,DTA1=51,DTA2=52,DTA3=53,DTA4=54,DTA5=55,DTA6=56,DTA7=57 19945 CAN:RCV:SLOT=0,PART=2 19947 CAN:RCV:CANH=2202206976,ID=3,TOTAL=4,CURR=3,TO=3,FROM=0 19953 CAN:RCV:LN=8,DTA0=56,DTA1=57,DTA2=48,DTA3=49,DTA4=50,DTA5=51,DTA6=52,DTA7=53 19960 !CAN:RCV:proper slot not found 19964 CAN:RCV:CANH=2202141440,ID=3,TOTAL=4,CURR=2,TO=3,FROM=0 19970 CAN:RCV:LN=8,DTA0=48,DTA1=49,DTA2=50,DTA3=51,DTA4=52,DTA5=53,DTA6=54,DTA7=55 19978 CAN:RCV:SLOT=0,PART=3Sub telegram 3 arrives before 2.
I'm afraid the function _findCanPacketSlot() needs an update to handle this.
@Adam-Slowik Do you see a chance for you to update the logic next time?Other limitation I see is the limited CAN telegram buffer of 3 packets in the MCP2515 module. I'm afraid for reliable operation with MySensors a change from polling to interrupt mode is required.
But this can be done later, after the fix for the PacketSlot logic. -
In logic analyser it looks like this:

Upper 4 channels are from node, lower ones are from gateway.Close up from gateway send (4 packets):
