I have the task of building a small J1939 to Modbus RTU gateway. I have to read about 20 PGNs from the J1939 data link with a Pic Micro, store them, then allow them to be retrieved via MB RTU.
I only need to update the registers approx. once per second, and the modbus request will be around 1 to 10 seconds depending on the data.
My concerns are... There is a lot of data coming across this link. Even the hardware filtered PGNs are coming at 100 ms. each so that is about 200 messages per second.
Is the best way to do this is to set a hardware filter for the range of PGNs I want, then use a software on the pic to rotate PGNs and accept them only as needed. Then process Modbus request in between.
Example, say I had 5 PGNs, and to keep it simple, I will use small numbers.....
Array of PGNs [1, 7, 12, 13, 26]
index = 0
Get PGN number from array I want to wait on
Wait on PGN xx data to arrive
Got data from PGN xx so decode and store the data
If Index > 5 then Index = 0 else increment index
'Check for modbus request
My Modbus will be on the USART and interrupt driven so it should jump to the modbus routines upon a request, process it, then go back to processing J1939 data. Would something like this work?
It really depends on the nature of the application and the data involved. In either case you still need to be aware of the problems of accessing two comm asyncronous channels and possible data corruption. Also, if any of the J1939 data is of an event type that cannot be lost due to the difference in sampling intervals (such as a momentary alarm event that needs to be logged) you may need to resolve how to retain a record of such events.
I assume that the PIC CAN hardware filtering is interrupt based, and therefore triggered when one of the group of PGNs you select gets transmitted over the bus. One of the issues I've had to deal with is the reception of concurrent PGNs from the same group being received back-to-back. I don't know offhand if the PIC CAN hardware is double buffered for each frame object, but you may need to push frames of interest into a queue or secondary buffer for later processing outside the interrupt. If you have enough RAM perhaps you can store the entire frame, otherwise a high priority task or flag should be looked at to handle parsing the data from received frames. It would be good to double buffer this data so if a new frame is received at the interrupt level it has a place to go if the mainline code is still parsing the previous frame.
If you're not concerned about anything but the last values received when a request for data is being processed on the Modbus side, then it may be possible to set a flag (Mutex) from the Modbus side that a PGN is being processed which can be tested on the CAN side, and if the flag is true bypass the new frame update for that PGN and dump the incoming frame while the previous data frame is being parsed and output to the Modbus side. The flag is cleared once the CAN frame data is processed and sent to the Modbus. Then you only need to process and decode the CAN frame buffers as needed by the Modbus requests, and save some processing overhead.
Does this help?
> In either case you still need to be aware of >the problems of accessing two comm asyncronous >channels and possible data corruption.
Yes, one of my concerns....
>Also, if any of the J1939 data is of an event >type that cannot be lost due
> I assume that the PIC CAN hardware filtering is >interrupt based, and therefore triggered when >one of the group of PGNs you select gets >transmitted over the bus.
Yes, but those particular PGN's come across at 10 per scecond. That is why I thought about including a rotating software filter. Wait for the PGN I need, process it, go wait on the next one, repeat. I could set my own pace.
> One of the issues I've had to deal with is the >reception of concurrent PGNs from the same group >being received back-to-back.
This would be a problem, but not currently a problem for my current project.
> If you're not concerned about anything but the >last values received
That is all we need, no control involved, just reading values for informational purposes.
>when a request for data is being processed on >the Modbus side, then it may be possible to set >a flag (Mutex) from the Modbus side that a PGN
Well, if they all came across at 10hz, then this would work, but some only come across every 7-10 seconds so that would cause some timeout issues, unless I sent RTR.
I think it would e better just to store the last value in the regs and then it would be immediately available. So what if the data is a second old. If this were a PID loop or something it would be pretty critical, but since it's informational only, I see no big deal.
I have to determine if I'm going to use a SJA1000 or MCP2515 or a 18F with built in CAN.
Thanks for the suggestions.