I have 17 different CAN messages with different ID's that I need to send at 100ms periodically. If I have them all in an Atomic subsystem (Set to 0.1s) then they don't get transmitted at all, I assume the CAN controller is getting overrun.
I then set up a stateflow chart to cycle through each message at 2ms apart, stopping at the last message I want to send. This then restarts after 100ms. The problem is either this or my CAN receive logic is causing my application code to run slowly (CAN transmit is anywhere between 100ms-150ms depending on exact logic I use). I also have 18 MB's set up to receive on this CAN BUS as I need to receive 96 messages which is split into these 18 depending on CAN ID.
I have attached a test model showing what I have. Would really appreciate if there was an example or someone to show me where I am going wrong with using this blockset as this logic works on other family uC's.
Hi @Poley ,
Can you send a model for the first method to see what you tried to do?
The fastest way to send a set of CAN messages is to using non-blocking CAN send, with different message buffers for each send block. So for 17 CAN messages you will have 17 FCAN_Send blocks, each block with its own MB (message buffer).
Another method, a little slower but one that is using only one MB, is to use the blocking FCAN_Send. The blocking FCAN Send will wait for the CAN send operation to finish before executing the next blocks. This wait makes sure that the next FCAN Send block doesn't override the previous CAN Send operation on the same MB.
Does the first method work on other family uC's or the second method (with stateflow)?
I have attached a model with all 17 transmits on different MB's. Not sure what I was doing before but this does send them properly when in an atomic subsystem, the transmit messages don't seem super stable at 100ms still though. The other issue is I can't have it like this as I need to receive 96 messages which take up a lot of MB's to be able to accept them all.
Is the way I have set up receive at the bottom of the model correct? Splitting it by MB's and calling it like I have?
The stateflow method that I have made is what works on other uC's. I guess it works similar to what you are saying with waiting till Tx is complete. I give each message a 4ms delay between them to let the message finish sending. I guess I could link Tx complete to the stateflow and it moves on to next message when that is complete rather than just using my 4ms value?
Also, you will see that 1 of the 17 transmit messages is on it's own, that's because in my main model I need to know when that is sent to the trigger something else.
Thanks for the help!
Hi @Poley ,
I updated your model to use blocking FCAN Send blocks to send the CAN messages, and only one MB, 31.
And I got these results in PCAN-View, the CAN analyzer that I am using:
The cycle time tells us that the messages are sent each 103 milliseconds, not 100 ms. I will try to explain why it is so.
Simulink is using the configured solver step as the base rate for all timings in your models. In your model the solver step is set to 0.001 seconds or 1 ms, which means that your model will be executed each 0.001 seconds and that the duration of each executed step doesn't exceed this value. So to trigger your subsystems each 100 ms, Simulink is using a counter that is incremented on each executed step and when it reaches100 it is reset to 0. Each time your counter is 0 your subsystems that send CAN messages are executed.
From the CAN message trace we can approximate how much it takes to send the CAN messages, and it is seems to be around 3.6 ms.
last message timestamp - first message timestamp = 2.6661 sec - 2.6625 = 0.0036 sec or 3.6 ms
So your execution of the model when the CAN messages are send takes at least 3.6 ms instead of 1 ms, the expected duration. Now if you do 3.6 ms + 99 steps each taking 1 ms you get 102.6 ms. Which is almost the cycle time measured by PCAN-View.
If you want to sent the CAN messages every 100 ms, you will have to use the PIT interrupt to trigger your subsytems each 100 ms exactly.
Thanks for the response!
When I run the model you linked I get a 104ms cycle time, which being only 1ms out from what you was getting I didn't see it as an issue, is that right?:
Also, will using CAN send blocks in blocking mode cause an issue for the rest of my model?
Does this not mean everything in the model is running 4% slower?
Hi @Poley ,
The cycle time is between 103-104 ms on my side, so it is not an issue.
The only issue is that your model will run slower than expected. And indeed, it will run 4% slower. But you can change the solver step from 0.001 to 0.005 seconds if your logic allows it, and you will get the expected result.
Another method is to try to use CAN Tx complete event, which is triggered when a non-blocking CAN send completes. You will have to initiate the first non-blocking CAN send from outside the event subsystem, and then use a non-blocking CAN send in the event subsystem to initiate the next CAN send operation, until you send all the CAN messages. It will allow the model to be executed while a CAN send operation is handle by the CAN hardware.
I did a mistake in the previous post, the first message is 0x210 with timestamp 2.6625. I will update my post.
I have changed the model to have a 5ms step time which works fine with just that one bus. But I have now added the other 2 busses and it now send out at > 160ms on all signals now.
What am I doing wrong here?
Seems to work OK if I use non block on the new CAN0 and CAN1 transmit messages each with their own MB, like this:
However it often goes to 105ms randomly during runtime, is that a problem? Just need to make sure I also don't miss CAN receive messages between the 5ms steps (posted on my other reply)
My stateflow works perfectly fine if I run it at 200ms, maybe that's my easiest solution! I guess that because it takes 3.4ms, it is missing time steps occasionally (The stateflow at 100ms cycle makes it transmit at 120ms).
Do you mean If the solver is 0.005 the blocking method from before will work at 100ms?
Lastly do you have a quick example of what you mean in terms of using Tx complete to cycle through messages at 100ms?
Thanks again for the help!
Also the separate single transmit can be on a different MB so that's why it's out of the stateflow.
If the solver was set to 0.005, will I have issued receiving CAN messages in between the time steps? (If it received one at 2, 4 and 5ms in that time stamp on different MB's, will I get all of them still?)