Shop OBEX P1 Docs P2 Docs Learn Events
Datalogger Nightmare — Parallax Forums

Datalogger Nightmare

CumQuaTCumQuaT Posts: 156
edited 2010-06-20 16:08 in Propeller 1
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:

  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

  • MagIO2MagIO2 Posts: 2,243
    edited 2010-06-19 15:26
    1. You need a buffer where you want the Read instruction to store the data. For example a byte array. You only read 2 bytes in this case, cut the byte array should be as long as the maximum numbers of bytes you want to read in future.

    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.
  • CumQuaTCumQuaT Posts: 156
    edited 2010-06-19 15:43
    Hi, thanks for the quick reply. I gave it a go and still have no joy. Here's the code I used:

    PUB ReadVal
      if usb.OpenForRead(string("TEST.TXT"))
        debug.str(string("Opened file...", 13))
        usb.Read(2,@read_buffer)
        read_buffer := 0
        usb.Close(string("TEST.TXT"))
      else
        debug.str(string("File Open Fail", 13))
      debug.str(string("File Closed", 13))
      
      waitcnt(clkfreq + cnt)
    
      debug.cls
      debug.str(read_buffer)
    
    



    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?
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-06-19 15:45
    Sorry .. I should know better ... the forum system removed some [noparse][[/noparse] ] ....

    read_buffer[noparse][[/noparse] 3 ] := 0

    and the output of the string has to be done with

    debug.str( @read_buffer )
  • CumQuaTCumQuaT Posts: 156
    edited 2010-06-19 15:54
    You're a genius! It worked!

    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:

    usb.Read(4, @read_buffer)     'An extra two characters for the second line
    
    



    But that just returned the first number...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Who are you, and why are you reading my signature?
  • John AbshierJohn Abshier Posts: 1,116
    edited 2010-06-19 16:22
    I noticed you are using version 1.0 of the data logger object. There is a version 1.1. The ReadLine methods are different. Something to consider. The WriteLine method adds CR/LF or LF/CR. You will have to account for them when you read the second line.

    John Abshier
  • MagIO2MagIO2 Posts: 2,243
    edited 2010-06-19 16:29
    So you did not really understand what I wrote.

    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
  • T ChapT Chap Posts: 4,223
    edited 2010-06-19 20:50
    This is precisely the reason that several people stated to post the entire code. Also, the answer was posted in your original post, not sure why it didn't make sense then but just in case you missed it, I stated that you must be reading the bytes back from the reads using an array to store that values so that you can then do what you want to do with the individual or collective strings afterwards. I used the byte name stringptr as an example only, but assumed the following showed exactly how the read would place your numbers in the array. Below I showed you a VAR named stringptr with 64 bytes allocated to it.

    You can read in a string into the Prop using an array created in VAR like stringptr[noparse][[/noparse] 64], where the read starts placing the values at stringptr[noparse][[/noparse] 0] and fills up the buffer, then it starts overwriting at the top again. You access the values in the array the same way... the following shows what the array will look like after reading the first few lines of your text file. 
    
    stringptr[noparse][[/noparse] 0] == 49
    stringptr[noparse][[/noparse] 1] == 55
    stringptr[noparse][[/noparse] 2] == 48
    
    
    
  • CumQuaTCumQuaT Posts: 156
    edited 2010-06-20 05:27
    Hi all, thanks for the thorough descriptions. I've sort of gotten it working based around that. I went and tried out the v1.1 of the datalogger object, but can't actually find a ReadLine method in there at all. After reading what you said, it sounds like the ReadLine function is the way to go for my needs, but it's simply not there... To clarify, I'm using the object here (http://obex.parallax.com/objects/368/)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Who are you, and why are you reading my signature?
  • cessnapilotcessnapilot Posts: 182
    edited 2010-06-20 06:40
    Hi,

    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
  • CumQuaTCumQuaT Posts: 156
    edited 2010-06-20 09:58
    I'll give that a go, too, to see if it makes my day a little better. Thanks for the tip!

    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?
  • T ChapT Chap Posts: 4,223
    edited 2010-06-20 16:08
    That obj is massive and incredibly thorough. I recommend for anyone starting out on the Vinculum to first read the Vinculum manual and also the Firmware manual
    that you are using, both on the FTDI website.
Sign In or Register to comment.