Tanner Posted January 4, 2010 Report Share Posted January 4, 2010 (edited) Hi all, I'm having some trouble getting our cRIO to read back a binary file I wrote to the file system. I don't know why it is doing it, as I created a simple example vi that just does the exact same thing, writes a couple of clusters to a binary file and reads them back and it works fine (though that was on the computer versus the cRIO). What is happening is that when I read the file back, I'm not getting back the same values as I wrote to the file. For example, as seen in the vi's pictured below, I'll write some joystick axis data and button data, but the joystick data will be all over the place (out of the ordinary 1 to -1) and the button data will show that x number of buttons were triggered, but they will be the wrong buttons. The entire read data seems that it is shifted by something because the joystick values are out of whack and the button pressed/released are actually shifted. I'm not sure if there is something happening in the background or what. I made LabVIEW do a md5 hash check on the file on writing and reading the file, and the file is not changing. There is either a problem in reading or writing the file. Any ideas? Write File VI: Read File VI: Thanks -Tanner Edited January 4, 2010 by Tanner Quote Link to comment
ned Posted January 5, 2010 Report Share Posted January 5, 2010 Are you getting back the same number of points that you wrote? Do you get any error from Read from Binary File? That information would help determine if there's an offset when reading the file, or if you're writing the correct number of bytes but misinterpreting them. You do have an unnecessary "Set File Position" in the read, but I don't think that's causing your problem. There are some style points you should correct in your code. Do you really need to check every 1 ms if the time is elapsed, or can you use a longer, more reasonable wait? You should eliminate most of your global variables and replace them with shift registers (I know, the FIRST framework uses global variables all over the place). Both Current Line and the Previous Data Time should be integers, not floating point values (find the global definition, right-click, and change the representation to I32). Sequence structures, especially stacked ones, are almost never necessary and can be removed. Quote Link to comment
Ton Plomp Posted January 5, 2010 Report Share Posted January 5, 2010 Could you upload the global control and a saved (malformed) VI? Ton Quote Link to comment
Tanner Posted January 5, 2010 Author Report Share Posted January 5, 2010 Are you getting back the same number of points that you wrote? Do you get any error from Read from Binary File? That information would help determine if there's an offset when reading the file, or if you're writing the correct number of bytes but misinterpreting them. You do have an unnecessary "Set File Position" in the read, but I don't think that's causing your problem. Same number of points? The array as far as I know contains the same number of elements, but I'd have to check to be for sure. I do not believe I'm getting a error from Read from Binary File. I added the Set File Position just to make sure that the Read Vi was reading the right place. There are some style points you should correct in your code. Do you really need to check every 1 ms if the time is elapsed, or can you use a longer, more reasonable wait? You should eliminate most of your global variables and replace them with shift registers (I know, the FIRST framework uses global variables all over the place). Both Current Line and the Previous Data Time should be integers, not floating point values (find the global definition, right-click, and change the representation to I32). Sequence structures, especially stacked ones, are almost never necessary and can be removed. The vi isn't being executed by itself (or at least it shouldn't be), I only had that because it appeared to be the only way to get a time stamp in ms. Is there a pro to using shift registers? Some of them I use in other places or have to be initialized. I don't see how I could get rid of the sequence structures, as I have to increment the line I'm reading and something else and putting it all in one structure would appear to make it run in whichever order LabVIEW wants (unless I misunderstood how smart it would be at that). Could you upload the global control and a saved (malformed) VI? I'll have to see if the code does not contain any Beta code (which I cannot release under a NDA). How would I save the state of the Vi unless you mean just the Vi? Thanks -Tanner Quote Link to comment
Daklu Posted January 6, 2010 Report Share Posted January 6, 2010 Is there a pro to using shift registers? Shift registers (or any design that maintains data flow) execute more efficiently than globals. More importantly, when using globals all over your code it gets very complicated and difficult to debug. The data is too accessable. For example, your Read File vi depends on a 'Current Line' global. There's nothing preventing a different VI in your application from changing that value, which would cause incorrect results from this vi. I don't see how I could get rid of the sequence structures, as I have to increment the line I'm reading and something else and putting it all in one structure would appear to make it run in whichever order LabVIEW wants (unless I misunderstood how smart it would be at that). You are correct that removing the sequence structure from your existing code would allow Labview to parallelize most of the execution however it wants. That's another side effect of using globals; it's harder to make operations sequential. Stacked sequence structures really become problems when trying to pass data from one frame to the next. Since you're not doing that I personally think it's fine. However, if you decide to ditch the globals you will be passing data between frames (Recorded Data Array) and it would be better to replace it with something else. Here's one way to go about making the Read File vi data dependent. (I'm guessing as to the use of some of the global variables, so use this as an example not as actual code that is functionally equivalent to yours.) Personally I would break it down even more. I'd eliminate the Recorded Data Array Updated and Recorded Data Array inputs as well as the Joystick Data outputs, and make the Read File.vi do nothing other than read the data from the file and return it as an array. Extract the correct Joystick Data from the array in another sub vi or in a higher level vi. Trying to do too much in a sub vi often leads to confusing code. (Like having to include a Recorded Data Array Updated boolean flag to decide whether or not to actually read the data from the file.) ---------------- Regarding your original question, I noticed you've wired a cluster control in each of the VIs to define the type information for the read/write data primitives. Do those derive from a common typedef or are they independent controls on each vi? If they are independent, make sure any numbers inside those clusters have the same representation and all the elements of the cluster are in the same order. (Better yet, define a typedef for your ARDS Data cluster and use that instead.) For instance, if one of the numbers in your Read File.vi ARDS Data cluster was an I32 instead of a DBL, that would throw things out of whack. Quote Link to comment
Tanner Posted January 6, 2010 Author Report Share Posted January 6, 2010 Shift registers (or any design that maintains data flow) execute more efficiently than globals. More importantly, when using globals all over your code it gets very complicated and difficult to debug. The data is too accessable. For example, your Read File vi depends on a 'Current Line' global. There's nothing preventing a different VI in your application from changing that value, which would cause incorrect results from this vi. That actually makes a heck of a lot of sense if I think about this as a textual language. Private data for stuff that doesn't need to be public. You are correct that removing the sequence structure from your existing code would allow Labview to parallelize most of the execution however it wants. That's another side effect of using globals; it's harder to make operations sequential. Stacked sequence structures really become problems when trying to pass data from one frame to the next. Since you're not doing that I personally think it's fine. However, if you decide to ditch the globals you will be passing data between frames (Recorded Data Array) and it would be better to replace it with something else. Again that makes sense. I'll see how much I can get rid of the global variables, just to make the execution flow a bit better. Regarding your original question, I noticed you've wired a cluster control in each of the VIs to define the type information for the read/write data primitives. Do those derive from a common typedef or are they independent controls on each vi? If they are independent, make sure any numbers inside those clusters have the same representation and all the elements of the cluster are in the same order. (Better yet, define a typedef for your ARDS Data cluster and use that instead.) For instance, if one of the numbers in your Read File.vi ARDS Data cluster was an I32 instead of a DBL, that would throw things out of whack. The clusters used to be independent controls on a each vi, but they should now derive from a common typedef (after I figured out how to connect the two). I'll check the data type when I get a chance as well to make sure everything's the same. Thanks -Tanner Quote Link to comment
Grampa_of_Oliva_n_Eden Posted January 6, 2010 Report Share Posted January 6, 2010 ... The clusters used to be independent controls on a each vi, but they should now derive from a common typedef (after I figured out how to connect the two). I'll check the data type when I get a chance as well to make sure everything's the same. Thanks -Tanner Including cluster order. Better off with the Type-def. Ben Quote Link to comment
Ton Plomp Posted January 7, 2010 Report Share Posted January 7, 2010 Could you upload the global control and a saved (malformed) VI? Ton I'll have to see if the code does not contain any Beta code (which I cannot release under a NDA). How would I save the state of the Vi unless you mean just the Vi? Sorry I should have written: and a saved (malformed) VI datafile Ton Quote Link to comment
Tanner Posted January 8, 2010 Author Report Share Posted January 8, 2010 This includes the Vi's plus the typedefs and a data file. I haven't changed anything just to not break anything that is already broken. So, the hints I don't really want to implement cause I'm not too experienced otherwise and just want to get it working first. Should all run (has no other dependencies) and the data within the file should have the joystick Y increasing, buttons 4/5 being pushed, and then joystick Y decreasing. Shout if I forgot something. -Tanner ARDS.zip Quote Link to comment
asbo Posted January 8, 2010 Report Share Posted January 8, 2010 Shout if I forgot something. LV8.6 is asking for a control typdef, Joystick.lvlib:ButtonState.ctl. I don't know if a license prohibits you from posting that here, though. Quote Link to comment
Tanner Posted January 8, 2010 Author Report Share Posted January 8, 2010 LV8.6 is asking for a control typdef, Joystick.lvlib:ButtonState.ctl. I don't know if a license prohibits you from posting that here, though. Don't think I could, but if you need it I can post it tomorrow (cause then everyone gets the code). I don't think you need it for Reading it, just Writing it. -Tanner Quote Link to comment
Mark Yedinak Posted January 8, 2010 Report Share Posted January 8, 2010 I would look into using a state machine to replace your stacked sequence frame structure. There are several advantages to state machines versus sequence structures. They are easier to modify and add functionality. They are easier to pass data between states using shift registers. They allow you to abort or modify the order of operations whereas a sequence structure must run all frames in order and cannot terminate prematurely. These are just a few benefits of using states machines. Also, it has been mentioned that you should make sure that all your cluster references are tied to the same typedef. I noticed in your original post that there were coercion dots (the small red dots on the wire connecting to a terminal) on the bundle by name. This means that there is a possible mismatch in the data types. This can lead to the types of problems you are seeing. Quote Link to comment
Tanner Posted January 8, 2010 Author Report Share Posted January 8, 2010 Also, it has been mentioned that you should make sure that all your cluster references are tied to the same typedef. I noticed in your original post that there were coercion dots (the small red dots on the wire connecting to a terminal) on the bundle by name. This means that there is a possible mismatch in the data types. This can lead to the types of problems you are seeing. I did some looking and noticed that my ARDS Data.ctl was not linked to ARDS Joystick Data.ctl as the ARDS Data contained two joystick's worth of data. I linked those and found a few others that needed to be linked or changed. Thought that would fix it, but nope. Still returning odd/adbnormal data. New files attached. -Tanner And it won't let me edit that post. Grr.. Here's the files. ARDS.zip Quote Link to comment
Mark Yedinak Posted January 9, 2010 Report Share Posted January 9, 2010 I did some looking and noticed that my ARDS Data.ctl was not linked to ARDS Joystick Data.ctl as the ARDS Data contained two joystick's worth of data. I linked those and found a few others that needed to be linked or changed. Thought that would fix it, but nope. Still returning odd/adbnormal data. New files attached. -Tanner And it won't let me edit that post. Grr.. Here's the files. It may not have fixed it in this instance but it can definitely lead to issues. Quote Link to comment
Tanner Posted January 9, 2010 Author Report Share Posted January 9, 2010 It may not have fixed it in this instance but it can definitely lead to issues. Oh definitely. Plus I learned something new - always good. Thanks -Tanner Quote Link to comment
ned Posted January 10, 2010 Report Share Posted January 10, 2010 Just to confirm, are you also seeing that you can read back the file you posted just fine on a PC, and you're only having problems on the cRIO? I don't have access to a cRIO against which I can test your code, but it looks fine on my PC. Quote Link to comment
Tanner Posted January 10, 2010 Author Report Share Posted January 10, 2010 Just to confirm, are you also seeing that you can read back the file you posted just fine on a PC, and you're only having problems on the cRIO? I don't have access to a cRIO against which I can test your code, but it looks fine on my PC. I haven't tested the exact same file, just the whole idea, and that has worked. I'll see if I have tomorrow to test if I can read the file that was written by the cRIO back on the computer, though tomorrow's busy. I'll see though. -Tanner Quote Link to comment
Tanner Posted January 21, 2010 Author Report Share Posted January 21, 2010 Ugh. Got busy and haven't had a chance to figure out whats wrong yet. When I have a chance (hopefully before Saturday), I'll upload the full code. I'm not really sure when I'll have the chance to test it fully with the cRIO again, so any help would be appreciated. Thanks -Tanner Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.