سؤال

I had no experience with Controller Area Networks(CAN) or ValueCAN3 prior to this project, and I used an example from Intrepid for my reading of messages. However I am having issues with efficiency and frequency of the updates for my GUI which displays the analog and digital signals I am reading.

My GUI consists of 16 numeric up/down boxes for analog channels and 36 buttons that change to green depending if a digital signal is turned on (1) or off(0). While reading in my CAN messages I then update the GUI controls to display the appropriate feedback. However the digital channels respond almost instantly when I press a button on a CAN joystick that is plugged in, whereas the analog signals don't update that fast with the string pots I am using to vary the signal. Sometimes it takes an analog signal 1 - 2 seconds to respond.

Currently I set the GUI controls, and then I read the values from the GUI controls and send the values out over a socket connection to another application via UDP. I should probably change this to sending the data from the signals I receive directly rather then reading from the GUI controls I am setting, but I don't think that is the issue.

I am using System::Timers::Timer objects to update, read messages, and send out data packets. I need a rate of 50hz - 100hz, preferably closer to 100hz. Using the socket on the other end I can see that my packets are sent frequently enough, but the data doesn't change smoothly or frequently for the analog channels. If anyone has any thoughts on what I might be doing wrong, or how to process the data in a more efficient way please state it.

Here is the segment of code from Intrepid that reads the CAN messages:

// Read the messages every timer event (1000 ms)
        if (m_bPortOpen) // only if the port is open
        {
            // call icsneoGetMessages to read out the messages
            lResult = icsneoGetMessages(hObject,stMessages,&lNumberOfMessages,&lNumberOfErrors);
            if (lResult != 0)
            {
                // a successful read
                mNumberOfErrorsRead = lNumberOfErrors;
                mNumberOfMessagesRead = lNumberOfMessages;  // store the number of messages in the current buffer
            }
        }

My form requests a msg from my CanReader Object using:

msg = can->GetLatestMsg();

and that method grabs the last message received.

public: icsSpyMessage* GetLatestMsg()
{
return &stMessages[mNumberOfMessagesRead - 1];
};

I think this GetLatestMsg() seems like a bad way to implement the retrival of the latest message, but I'm not entirely sure how much this is affecting my program or how else I could do this because the CanReader is seperate from the Form so I'd have to pass an array of messages I think otherwise. I do suspect this might be skipping messages because it only reads the last one grabbed and not the ones leading up to it, which if those were read should make the GUI output appear smoother for transitions.

Another thing to note is that I am reading from 6 different PGNs, the analog signals correspond to 4 of the PGNs and 2 correspond to the digital signals.

UPDATE

After playing with my application and using the string pots on different analog channels I am noticing that some channels are updating more then others. And by checking the PGNs being accessed I find that I am accessing some more frequently then others.

Doesn't a CAN device broadcast the data at relatively the same rates for the different PGNs? and if yes then my GetLatestMsg() method must not be reading the different PGNs effectively. It reads a new msg every 5 milliseconds.

Additionally, does anyone know if I should make seperate reading timers to detect the different PGNs seperately?

If there is additional code I can provide for clarity please let me know.

هل كانت مفيدة؟

المحلول

After lots of testing and debugging I have found a stable solution. I am posting this answer in hopes that someone else may benefit from this explanation.

When reading message on a CANbus the messages are broadcasting across the bus and you have to pick out the messages you want based on the parameter group names (PGNs). Each PGN should be defined for different pieces of data.

For instance engine rpm would correspond to a particular PGN, and when you check the messages in your buffer, you will be looking for the messages with the PGN corresponding to the engine rpm.

In my case, I am reading/wanting 6 different PGNs from the valueCAN3 device I am using. Each of these messages contains different data that corresponds to analog and digital signals. The error with efficiency was related to how I was retreiving the latest message from the buffer.

When you are just streaming all the same data in each packet it makes sense to just grab the latest or most recent message from your buffer. However, in my case since I require 6 different PGNs that means I when I grab the last message off of the buffer it corresponds to just 1 of out the 6 PGNs, and since the messages on my CANbus are sent out at a constant rate and in the same order, I was reading about half of the packets all the time, and missing the other half. By grabbing the 2 most recent packets I found that all my channels are now updating at the speed needed for my application. All my signals change without noticable lag, and are easily meeting my 50hz - 100hz range that I required.

However, I think the optimal solution would be to read the latest message for each PGN when I pull from the buffer, rather then just the latest two messages, which could correspond to any of my 6 PGNs because I read more often then I receive the packets.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top