01-01-2011 01:57 AM
Hi Nobizz,
I have a group of vi's which i think will do pretty much what you want. I will attach them below. I have assumed that the CRC for your data just consists of an accumulation of the 4 data bytes before the 5th CRC byte. If this is the case then the attached CRC routine should work, if it is different then obviously it will fail. If the CRC routine is different then you can either re-write it according to what you need. If you struggle let me know what CRC algorithm your expecting and it wont take me long to adjust it.
I have attache 2 MAIN vi's. One of the vi's is a tester, it allows you to test the software by just inputting string values. The second MAIN vi should actually communicate to your attached hardware.
In the examples i have sent you the data that will be displayed is just the last good data read in. If you need to read all data that has been read in-between reads then all you have to do is insert the last case structure into the for loop that holds the CRC vi, remove the conditional stop button from the for loop and wire the output of the crc to the case structure. This then send all good data read into the TRUE case, you may want to do this if you need to log all data. If all you are doing is displaying the data to be seen then all you need to do is display the most current read data, which is how its set up at the moment.
Hope it helps,
Rgs,
Lucither
01-03-2011 12:27 AM
Thanks Lucither, very good work and very helpful post, Major Kudos. It’s a little over my head right now but something I will study. Did I mention I used labview quite a bit several years ago but am otherwise a very limited labview programmer ? The Xbee Comms MAIN vi works great as is since I will be ultimately receiving data at less frequent intervals. However, it is certainly helpful to have the flexibility to read all data for future applications I am envisioning.
My original thinking is that I would read in the larger serial strings coming into the read buffer and parse each API packet (thanks for your help). Then I would filter out and keep only good packets by verifying the checksum Hex value at the end of each packet. Finally, parse out the “payload” bits I want to convert to decimal for graphing purposes. I’m almost there! I just need to have a clearer understanding of the problem and learn more of labview’s capabilities.
Just an FYI, I have 4 nodes with 3 identical sensors sending data to a receiver at the pc serial port. The goal is to plot this data on the same 3 graphs, time stamp it and save it to file. Additionally, I am planning to send packet data to an additional node to basically flip a switch. Any advice you can offer is greatly appreciated.
Thanks again.
Nobizz
01-05-2011 09:48 AM
Nobizz,
For the larger project look up examples of the Producer/Consumer design pattern. I would have 3 producer loops, each getting data from your sensors and passing to a single consumer loop. In your consumer loop you can process the incoming data. You can save it, plot it, do whatever you want with it in there.
There are plenty of tutorials on the website and also examples that come with LabVIEW.
Good luck,
Rgs,
Lucither.
01-05-2011 05:49 PM
Lucither,
The checksum algorithm I am working to achieve will do the following:
7E 00 0A 01 01 50 01 00 48 65 6C 6C 6F B8
[ omit ] 01+01+50+01+00+48+65+6C+6C+6F+B8 = 2FF
For API mode checksum test,
Skip the first three bytes, add remaining bytes including the CRC. The resulting right 2 most Hex values must be F to pass.
This method will be useful because it will allow me to check a string of any given length, since I havent decided yet how many samples I will be looking to process. But I'm guessing this wont matter for this step of the program development cycle.
I appreciate your advice, I will look at understanding and using the producer/consumer method for the next step.
However, please excuse this question if it seems obvious; if I settle on a specific data string size, is there a way I can parse out the bits I need at the beginning, right from the port?
Thanks for all your help.
Nobizz
01-05-2011 09:33 PM
Nobiz,
I personally cant see how you can implement the checksum test you show above. A checksum is used to check that the data you receive is the same as the data sent, ie has the data been corrupted. To do this in your case the transmitter applies a checksum before transmitting and attaches this value to the end, if you then calculate the checksum and it corrosponds to the sent checksum you know you have a good packet of data.
In your version you are ignoring the sent checksum, adding all the values and then comparing this to a fixed value 'FF'. Why would the data consistently add up to FF if good? It wont. In some circumstances it will but only by chance. You cant implement a checksum routine where the receiver calculates the actual checksum to add, this must be done by the transmitter as its only the transmitter that knows the true value of the data that's sent. If the receiver already knew this then we would have machines communicating like ants
In the example i wrote for you i used a buffer to parse your data. I did this by parsing all data inbetween to start idents (~), for what you originally showed me this was a viable solution as you gave no indication of message length. A problem with this solution though is that your last message read can only be parsed once an incoming message is coming in. This is because it parses between idents. This didnt seem a problem for you as at the beginning you showed that you was getting about 5 input messages at a time from your read.vi. As an example, if you are receiving a new message every 200ms, then in the example i sent you each valid message output from the parser will be at least 200ms old. If this is a problem and you know the message length of the incoming message you can adjust the code i sent you to scan for the start ident, then count the required amount of bytes and send this out as a complete message. Some message protocols have a start ident and then a message length byte which tells the parser how many bytes the incoming message has, does yours have this?
Just out of interest, in your above message you say to omit the first 3 bytes, what do the 2nd and 3rd byte signify.
Rgs,
Lucither
01-06-2011 01:49 AM
Lucither,
My apologies for any confusion on my part, I am trying to absorb a lot of information in a short time. So I am sure I am missing some information or am not fully aware of my problem.
This link explains the make up of the packets being transmitted and the calculations for verifying data integrity.
The "data packet" portion of the transmitted hex string is what can change the length of the of the overall API string being transmitted. This is preset in the firmware of the device and is a function of up to 6 A/D channels where each channel can collect a maximum of I believe 49 samples. So you can imagine how long the strings can get.
This link shows an example of an API data packet with 2 A/D channels open, collecting 5 samples on each.
http://www.digi.com/support/kbase/kbaseresultdetl.jsp?kb=180
The number of packets I was receiving was 5 as function of the “delay before read” (1000-1200ms) variable on the VISA controller and the transmit interval I had preset to be (5/sec) . This was strictly arbitrary just as a place to start. Your code does handle the parsing quite well and I Am sure it will handle faster transmit intervals. So perhaps this is where I can pull the data?
Hopefully I am not wearing you out or confusing myself further. You have been quite helpful.
Thanks again,
Nobizz
01-06-2011 01:59 AM
Also, there are 2 modes the transmitters can be set to. I have mine set to API mode therefore I am using the second checksum calculation method. I have verified that the results are correct, the hard way by calculating by hand in a spread sheet using the hex code read from the serial read window.
01-06-2011 03:23 AM - edited 01-06-2011 03:28 AM
Nobizz,
Ok, i understand now what you are trying to implement. Was not difficult. I spent a couple of mins modifying the original CRC checker i wrote. Should now do what you are after.
I have attached the modified files. In the Main folder there is a small CRC tester vi, if you run this you will see how it works.
The 2nd and 3rd bytes are message length bytes. To improve of the code i sent you you should use these to capture the data when it comes into the buffer. Look for the start byte, read the next 2 bytes (Which hold the amount of DATA bytes to read), read these in plus one more (The checksum byte), send this out of the buffer as a complete message. As it stands at the moment what i have sent you will work just could be improved upon to make more efficient. For example, as it is written at the moment you will see a start byte but if another byte within the message is also (7E) then this will be parsed out as a complete message (It will fail the crc though so you wont notice). You will miss some data though in this event.
Rgs,
Lucither.
01-07-2011 12:07 AM
Awesome, this is so cool, thanks a bunch.
Although I don’t think I will need it for this project, for sport I am working the modification you suggested earlier to read all strings. I have the last case structure wired in the CRC for loop with the conditional stop removed but it’s not obvious to me how I need to rewire the CRC Pass? bool. In any event I’m not sure I know what to expect. I adjusted the delay read to 1000 ms to fill more of the message array, but the data string display does not seem to be toggling through the list as I am thinking.
Anyhow, the code works perfectly for what I am planning. I just need to step through the final complete message, find the exact byte in the array I need to pull, convert it to Dec and graph, sounds easy anyway.
I can’t thank you enough.
CHEERS!
01-07-2011 12:54 AM
See attached,
There is an extra file in the MAIN folder that reads all good messages, not just the last one.
Rgs,
Lucither