Is there an example for sending/receiving high multiple of CAN messages?

cancel
Showing results for 
Search instead for 
Did you mean: 

Is there an example for sending/receiving high multiple of CAN messages?

749 Views
Poley
Contributor IV

Hi,

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.

0 Kudos
11 Replies

742 Views
mariuslucianand
NXP Employee
NXP Employee

@paulvlase , can you comment on this?

Thank you,

Marius

0 Kudos

718 Views
Poley
Contributor IV

Hi @paulvlase 

Have you been able to look at my model by any chance? Or able to send an example with a high number of receives?

Really running out of time to get this issue fixed.

Thank you very much!

0 Kudos

712 Views
paulvlase
NXP Employee
NXP Employee

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)?

Regards,

Paul

0 Kudos

706 Views
Poley
Contributor IV

Hi @paulvlase 

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!

 

0 Kudos

698 Views
Poley
Contributor IV

Also @paulvlase 

Would it be possible for you to send me an example of using the Tx complete block to send over 10 messages using the same buffer?

Thanks!

0 Kudos

691 Views
paulvlase
NXP Employee
NXP Employee

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:

pcan.png

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.

 

trace.png

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.

Regards,

Paul

0 Kudos

688 Views
Poley
Contributor IV

Hi @paulvlase 

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?:

Poley_0-1625659858805.png

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?

Thanks! 

 

 

0 Kudos

678 Views
paulvlase
NXP Employee
NXP Employee

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.

 

Regards,

Paul

0 Kudos

652 Views
Poley
Contributor IV

Hi @paulvlase 

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:

Poley_0-1626107769407.png

 

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) 

Thanks

0 Kudos

675 Views
Poley
Contributor IV

Hi @paulvlase 

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.

0 Kudos

669 Views
Poley
Contributor IV

Also @paulvlase 

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?)

Thanks!

0 Kudos