I am designing an application that uses a NI CAN board to communicate with an Engine Controller Unit CAN device.
I use a CAN Network Inteface object (CNI) to get all preiodical data and monitor the bus, and I use 2 CAN Objects (CO) to communicate with the device for configuration and communication.
The problem is that as soon as I use both, the driver hangs and I get DRIVER ERROR messages.
This device, that I will call ECU, sends data every 10 and 100 ms using 5 different IDs.
In order to get these data I do the following:
1) I configure the port (ncConfigure("CAN0", ...))
2) Open the port with ncOpenObject("CAN0", &objh)
3) Start the communication with ncAction(objh, NC_OP_START, 1)
4) start a notification callback with ncCreateNotification, reacting to all possible states. My callback reads all incoming frames, check the ID and monitor frames:
- detect and list IDs
- count incoming frame globaly and for each ID
- copy data to a buffer
It works pretty fine, except that it is hard to garantie that no NC_ERR_OVERFLOW will occure for the read queue, specially if the system is temporarily heavily loaded.
(In correlation to this problem, it would be fine if you could give me some tips to garantie no overflow, or at least to be able to continue communication and frame monitoring even if this error occures, since it is not so critical to miss some frames.)
Now, let's come to the real problem.
The ECU uses ID 1264 for special request, and ID 1265 for the answer.
E.g. I want to get the value of the parameter 2 of the ECU, I will send a frame with data 022102XXFFFFFFFF (XX=02) with ID 1264 and I will receive the answer on ID 1265 on the form 026102XXVVFF with VV = value.
In order to communicate with the ECU in this way I do the following:
A.
1) I configure each CO, the first for sending data with ncWrite, the second to receive unsolicited frames. both start on open.
2) I open both CO with ncOpenObject("CAN0::STD1264", &objh1) and ncOpenObject("CAN0::STD1265", &objh2)
3) I create a notification callback for object of ID 1265 called when data is in the read-queue.
This callback read available frame, put in it the time at which it has been received, and store it in an internal small queue.
B.
Now when I want to communicate with the ECU, I do the following:
1) Get the system time TIME
2) status = ncWrite(objh1, sizeof(send), &send)
3) ncWaitForState(objh1, NC_ST_WRITE_SUCCESS, 200, &state);
4) find in the internal queue of ID 1265 if a frame newer than TIME has been received.
5) if yes, get it and return the data.
This seems very simple. But the fact is that when I do this, and that the other process of bus monitoring with CNI is working in the same time, I get problems:
* It works a bit (sometimes 10 times, sometimes more) and then my application get stuck randomly, for a very long time, at the call of ncWaitForState, just after ncWrite.
* I get a NC_ERR_DRIVER error and the CNI callback doesn't receive anything any more.
* Driver errors have following qualifiers:
Driver error (qual = 3FFF0000)
Driver error (qual = 20000000)
Is there a problem calling ncWaitForState on an object too often while a notification is active on a CNI?
What could be the problem?
I really need help, the application must be relyable and I don't want to look for another CAN system at the moment.
By the way I hope that the answer to these questions will help other people developing with NI CAN products and facing same kind of problems.