Datalogger Nightmare
CumQuaT
Posts: 156
Alright, so for a week now I've been trying to get this damned Parallax USB Datalogger working with my Propeller chip, and I'm having very little joy. I'm using the 'USBdrive' object from the OBEX (I've attached it so people know which one I'm talking about). The object uses the DataLogger in UART mode in case people are wondering.
All I'm trying to get it to do is accomplish three very simple steps:
Step 1 - Access flashcard [noparse]/noparse][noparse][[/noparse]Completed
Okay, this part I managed to get working fine using the following code:
Verrrry simple. I like it that way. This works 100% of the time so I am happy with that. Which brings me to...
Step 2 - Writing data to the flashcard [noparse]/noparse][noparse][[/noparse]Completed
This part I also managed to get working after SIGNIFICANT messing around using the following code:
(the USB object is my USBdatalogger file I have attached to this post)
This ALSO works a treat, and is fairly straightforward, but then comes the final stage, which is driving me to the point of insanity.
Step 3 - Reading data back OFF of the flashcard [noparse]/noparse][noparse][[/noparse]Frustratingly incomplete
No matter what I try, this simply will not work for me. I have tried everything I can think of, and every time I have asked on here for specific help I get turned away with either very off-track answers or people saying they need the code for everything, so I figured I'd document the entire thing and post all the code rather than make people as frustrated as I am.
I've trawled through the forums with a fine toothed comb to find a good tutorial on how to use the datalogger without any success, so I figure one needs to get made.
As the USBdrive object uses the WriteLine() function to write data, it has a Read() function to get data back off the drive. It looks like this:
Now, while I know my way around in spin fairly well, I'm no expert, so please forgive me if I'm missing something obvious here, but this function isn't returning anything... It just seems to use the byte[noparse]/noparse command to store the read-back data to main memory. But if this code is in a separate object, how do I access that read-back memory in my other program? Plus, it seems to be text data it brings back, so if it's text data such as the "42" that I added to the file when I wrote to it, how does that translate back to my program? My latest attempt looks a little something like this:
Now, to explain properly, the inVAL variable is a byte array, declared thusly 'byte inVAL'. I made it because I'm pulling in 2 bytes of data ("42"), but I don't fully understand the Read function's parameters anyway... ReadLength... Read Length in what? Bytes? Bits? Kilobytes? And what is the stringptr? No documentation or examples come with this object, but it's the only one that seems to work for me when it comes to connecting and writing to a USB flashcard... If I use the SPI module, it keeps saying no card detected (and yes, It's hooked up properly)
So what I'm asking is this: Do any of you Spin Masters out there know how I can achieve the following (and please read these questions carefully. I don't mean offense, but I get soooo many people on here not actually read the question before they answer)
1 - How can I retrieve my "42" out of my text file and display it in the console?
2 - How can I retrieve my "42" and use it as a functional number (as in be able to use it mathematically)
If I've left anything out here I will be glad to add more info, though I apologize if it takes a long time as I live in Australia and am in a very different time zone.
I hope to hear from some people soon! Thank you very much in advance!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Who are you, and why are you reading my signature?
All I'm trying to get it to do is accomplish three very simple steps:
Step 1 - Access flashcard [noparse]/noparse][noparse][[/noparse]Completed
Okay, this part I managed to get working fine using the following code:
USB.Start(22, 20, 21, 23) waitcnt(clkfreq/2 + cnt)
Verrrry simple. I like it that way. This works 100% of the time so I am happy with that. Which brings me to...
Step 2 - Writing data to the flashcard [noparse]/noparse][noparse][[/noparse]Completed
This part I also managed to get working after SIGNIFICANT messing around using the following code:
(the USB object is my USBdatalogger file I have attached to this post)
if usb.OpenForWrite(string("TESTFILE.TXT")) debug.str(string("Opened file...", 13)) usb.WriteLine(String("42")) usb.Close(string("TEST.TXT")) else debug.str(string("File Open Fail", 13)) debug.str(string("Complete!", 13))
This ALSO works a treat, and is fairly straightforward, but then comes the final stage, which is driving me to the point of insanity.
Step 3 - Reading data back OFF of the flashcard [noparse]/noparse][noparse][[/noparse]Frustratingly incomplete
No matter what I try, this simply will not work for me. I have tried everything I can think of, and every time I have asked on here for specific help I get turned away with either very off-track answers or people saying they need the code for everything, so I figured I'd document the entire thing and post all the code rather than make people as frustrated as I am.
I've trawled through the forums with a fine toothed comb to find a good tutorial on how to use the datalogger without any success, so I figure one needs to get made.
As the USBdrive object uses the WriteLine() function to write data, it has a Read() function to get data back off the drive. It looks like this:
PUB Read(readLength,stringptr) | i USB.rxflush USB.str(string("RDF ")) USB.tx((readLength>>24) & $FF) USB.tx((readLength>>16) & $FF) USB.tx((readLength>> 8) & $FF) USB.tx( readLength & $FF) USB.tx(CR) repeat i from 0 to readLength-1 byte[noparse][[/noparse]stringptr++] := USB.rx
Now, while I know my way around in spin fairly well, I'm no expert, so please forgive me if I'm missing something obvious here, but this function isn't returning anything... It just seems to use the byte[noparse]/noparse command to store the read-back data to main memory. But if this code is in a separate object, how do I access that read-back memory in my other program? Plus, it seems to be text data it brings back, so if it's text data such as the "42" that I added to the file when I wrote to it, how does that translate back to my program? My latest attempt looks a little something like this:
if usb.OpenForRead(string("RECORDS.TXT")) debug.str(string("Opened file...", 13)) inVAL := usb.Read(2,0) usb.Close(string("RECORDS.TXT")) else debug.str(string("File Open Fail", 13)) debug.str(string("File Closed", 13)) waitcnt(clkfreq + cnt) debug.cls debug.str(inVAL)
Now, to explain properly, the inVAL variable is a byte array, declared thusly 'byte inVAL'. I made it because I'm pulling in 2 bytes of data ("42"), but I don't fully understand the Read function's parameters anyway... ReadLength... Read Length in what? Bytes? Bits? Kilobytes? And what is the stringptr? No documentation or examples come with this object, but it's the only one that seems to work for me when it comes to connecting and writing to a USB flashcard... If I use the SPI module, it keeps saying no card detected (and yes, It's hooked up properly)
So what I'm asking is this: Do any of you Spin Masters out there know how I can achieve the following (and please read these questions carefully. I don't mean offense, but I get soooo many people on here not actually read the question before they answer)
1 - How can I retrieve my "42" out of my text file and display it in the console?
2 - How can I retrieve my "42" and use it as a functional number (as in be able to use it mathematically)
If I've left anything out here I will be glad to add more info, though I apologize if it takes a long time as I live in Australia and am in a very different time zone.
I hope to hear from some people soon! Thank you very much in advance!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Who are you, and why are you reading my signature?
Comments
var
byte read_buffer[noparse][[/noparse] 128 ]
....
Read( 2, @read_buffer )
after this read you will find the 42 in read_buffer[noparse][[/noparse]0] and read_buffer.
If you want to treat this input as a string, you should make sure that the next byte is a 0 ( read_buffer := 0 ) in this case.
My expectation is that Read will also return the number of bytes really read. So you can use this information to set the byte after the last read byte to 0.
2. There is a number-object which has functions to convert a numerical string into a number. Maybe you want to make this an exercise and write such a function by yourself. It's not that hard and improves your understanding of programming and datatypes.
read_buffer was declared like this: byte read_buffer[noparse][[/noparse]16] (I made it 16 just as overkill to be sure it'd work)
My debug window just comes up empty...
Any ideas?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Who are you, and why are you reading my signature?
read_buffer[noparse][[/noparse] 3 ] := 0
and the output of the string has to be done with
debug.str( @read_buffer )
Though it does raise another question for me... What if my text file had more than one line in it? I gave it a try like this:
But that just returned the first number...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Who are you, and why are you reading my signature?
John Abshier
Many functions ( like debug.str and conversion functions to convert a string to a numer ) work with a simple data-structure that represents a string. This is an array of bytes containing characters encoded in ASCII. If you click on Help->View Character chart in the propeller tool you can see which byte means which character - at least in the propeller character set which is only partial equal to ASCII.
For example a byte containing a 65 is an uppercase A.
In a string array the 0 is not allowed as character, because it defines the end of a string.
In the code reading "42" or bytes 52, 50 or $34, $32 I only added a 0 or $00 at the end to make sure the buffer can really be used as a string. That's why I mentioned that Read propably returns the number of bytes read. You should use this return value to set the character after the read text to 0 to convert it to a string.
Reading bigger files is another thing. Do you want to read the file with a PC afterwards?
You need to think about a file-format for your purpose. If you do data-logging this could be:
timestamp measured-value
or
timestamp measured-value1 measured-value2 .....
or without timestamp
If you want to be able to read the file manually on a PC you have to store it as text using linefeed at the end of a line.
If you don't want to read it manually you could simply store longs without conversion.
.....
Depending on that both, the reader and the writer, will look different.
You could use fixed length output (each long written as text has 10 digits with leading zeros) which then also leads to fixed lenght lines. Then you only have to read this amount of bytes for each line and you exactly know where a number starts.
If the lines are variable length it's more difficult. You read a bunch of bytes (at least the max. linelength) and try to find the separators, replace these with zeros and can then treat em like a string.
You could have a look at the ConfigReader I put into the object exchange under Tools to find out more about reading variable line length files.
PS: noticed the post above ... ReadLine and WriteLine makes this part easier of course ;o) So you only have to find the separators if you have more numbers per line.
Post Edited (MagIO2) : 6/19/2010 4:35:47 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Who are you, and why are you reading my signature?
Parallax USB datalogger is simply great. Works smoothly with the UART Datalogger object. That object drives the original Vinculum·module, too.
http://obex.parallax.com/objects/542/
Would you please take the trouble and try it. I hope your opinion about·the 'damned' USB datalogger module will change.
If you can get·the module·work, it will make all those SD card FAT file system botherations obsolete.
Cheers,
Istvan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Intentionally Left Blank
And yes, I'd very much love to have my opinion changed of this little device!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Who are you, and why are you reading my signature?
that you are using, both on the FTDI website.