Shop OBEX P1 Docs P2 Docs Learn Events
Data Logging? — Parallax Forums

Data Logging?

GeorgeLGeorgeL Posts: 131
edited 2008-12-03 03:25 in BASIC Stamp
Is it possible to log data on the BS2, then come back to the computer and retrieve the data? The data I would be recording is simple, a Boe-bot is roaming and when it changes direction, records a specific value( like 2 when going left and 3 when right so on). And the recording would be only a minute or two of mostly straight path.

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2008-11-29 05:23
    If your program doesn't use all of the 2K of EEPROM, you can use the WRITE (and READ) statements to store (and retrieve) data from EEPROM. You'll need to either add a routine to your program to retrieve the data (to send to the PC) or download a new program (over top of the normal one) to do this. If the new program is not larger than the roaming program, all the data will be intact in the lower part of the EEPROM. Read the chapters in the manual on the READ and WRITE statements.
  • GeorgeLGeorgeL Posts: 131
    edited 2008-11-29 06:12
    Ah, I see. I was thinking that when you upload a new program to the BS2, it clears the EEPROM. Ill try that tommorow then.
  • GeorgeLGeorgeL Posts: 131
    edited 2008-11-29 06:43
    cry.gif·Didnt work as planned.· I decided to use a quick solution for testing:
    '{$STAMP BS2}
    '{$PBASIC 2.5}
    time VAR Word ' SONY TV remote variables
    remoteCode VAR Byte
    pulseCount VAR Byte
    value VAR Word
    value2 VAR Word
    DEBUG "Binary Value Decimal Value", CR, ' Display heading
    "Bit 76543210 ", CR,
    "

    "
    DO ' Beginning of main loop
    Get_Pulses: ' Label to restart message check
    remoteCode = 0 ' Clear all bits in remoteCode
    ' Wait for resting state between messages to end.
    DO
    RCTIME 9, 1, time
    LOOP UNTIL time > 1000
    ' Measure start pulse. If out of range, then retry at Get_Pulses label.
    RCTIME 9, 0, time
    IF time > 1125 OR time < 675 THEN GOTO Get_Pulses
    ' Get data bit pulses.
    RCTIME 9, 0, time ' Measure pulse
    IF time > 300 THEN remoteCode.BIT0 = 1 ' Set (or leave clear) bit-0
    RCTIME 9, 0, time ' Measure next pulse
    IF time > 300 THEN remoteCode.BIT1 = 1 ' Set (or leave clear) bit-1
    RCTIME 9, 0, time ' etc
    IF time > 300 THEN remoteCode.BIT2 = 1
    RCTIME 9, 0, time
    IF time > 300 THEN remoteCode.BIT3 = 1
    RCTIME 9, 0, time
    IF time > 300 THEN remoteCode.BIT4 = 1
    RCTIME 9, 0, time
    IF time > 300 THEN remoteCode.BIT5 = 1
    RCTIME 9, 0, time
    IF time > 300 THEN remoteCode.BIT6 = 1
    DEBUG CRSRXY, 4, 3, BIN8 remoteCode, ' Display keypad code
    CRSRXY, 14, 3, DEC2 remoteCode
    IF (remotecode=1) THEN
    value = 1
    WRITE 0, Word value
    FOR pulseCount = 0 TO 30
    PULSOUT 13,650
    PULSOUT 12,850
    NEXT
    ENDIF
    IF (remotecode=4) THEN
    value2 = 2
    WRITE 1, Word value2
    FOR pulseCount = 0 TO 30
    PULSOUT 13,850
    PULSOUT 12,650
    NEXT
    ENDIF
    IF (remotecode=3) THEN
    FOR pulseCount = 0 TO 30
    PULSOUT 13,650
    PULSOUT 12,650
    NEXT
    ENDIF
    IF (remotecode=5) THEN
    FOR pulseCount = 0 TO 30
    PULSOUT 13,850
    PULSOUT 12,850
    NEXT
    ENDIF
    IF (remotecode=0) THEN
    PULSOUT 13,750
    PULSOUT 12,750
    ENDIF
    LOOP ' Repeat main

    and i tried presssing a few times each button, and then tried this to read the values i "got"

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    result· VAR···· Word
    Main:
    · READ 0, result.LOWBYTE
    · READ 1, result.HIGHBYTE
    · DEBUG DEC ? result
    · END


    and i didnt get what i wanted, a 1 or 2 in the same sequence. I just got the number from the example i used. any help on this? it would help a lot of other people in the future too.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2008-11-29 07:39
    George -

    Not to rain on your present efforts, if this were my project, I'd use a BS-2E. It's designed for data logging, as you can see here:
    http://www.parallax.com/Store/Microcontrollers/BASICStampModules/tabid/134/CategoryID/9/List/0/SortField/0/Level/a/ProductID/2/Default.aspx

    Note carefully the following which I have extracted from the web link above:

    "The BS2E-IC, powered by the Ubicom SX microcontroller, is ideal for those that have previous experience with the BS2 and would like more variable or program space. For a complete technical comparison between the BS2e and all other modules, check out the BASIC Stamp Comparisons (.pdf) in the downloads section."

    What you are looking for in a chip which does data logging is more variable space. With this particular Stamp module you have banked memory (2 x 8K) to use as you see fit, and a lower current profile. The BS2E is essentially a lower power version of the BS-2SX. The BS-2SX is faster, but it also draws more current, both when active and also while sleeping (SLEEP command).

    Regards,

    Bruce Bates

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When all else fails, try inserting a new battery.
  • Tracy AllenTracy Allen Posts: 6,662
    edited 2008-11-29 17:47
    No need for Word in the following...
    WRITE 0, Word value
    WRITE 1, Word value2
    Just
    WRITE 0, value
    WRITE 1, value2

    Then in readout, I think they should be separate values?:
    Read 0,value
    Read 1,value2
    DEBUG DEC value, TAB, DEC value2

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com
  • GeorgeLGeorgeL Posts: 131
    edited 2008-11-29 18:23
    Ok, so I tried Tracy's solution, but when i take the reading, i just get an output of a 1 followed by a tab and then a 2. The plan is to record the order in which the movements are, so if I go forward twice, it records 1 1 and then if it goes forward forward forward back back forward it would record 11121. I hope this is clear.

    @Bruce
    I looked at the price tag of the already assembled BS2e and that is way out of budget (Im in high school) and no this is not for school. They dont even have woodshop here, really disapointing. And I took a look at the parts to build my own BS2e, theyre more moderate, and if I were to build this could I use my Boe Bot Board (its the one with removable BS2)? Also is this BS2e similar in programming and how difficult is it to solder it? Is it the same small contacts as on the BS2?
  • sylvie369sylvie369 Posts: 1,622
    edited 2008-11-29 18:54
    GeorgeL said...
    Ok, so I tried Tracy's solution, but when i take the reading, i just get an output of a 1 followed by a tab and then a 2. The plan is to record the order in which the movements are, so if I go forward twice, it records 1 1 and then if it goes forward forward forward back back forward it would record 11121. I hope this is clear.

    If you mean "111221" then it is. If you really mean "11121" for "forward forward forward back back forward" then I have no idea what you're trying to do. Can you clarify that first?
    GeorgeL said...
    @Bruce
    I looked at the price tag of the already assembled BS2e and that is way out of budget (Im in high school) and no this is not for school. They dont even have woodshop here, really disapointing. And I took a look at the parts to build my own BS2e, theyre more moderate, and if I were to build this could I use my Boe Bot Board (its the one with removable BS2)? Also is this BS2e similar in programming and how difficult is it to solder it? Is it the same small contacts as on the BS2?

    You can remove the BS2 (CAREFULLY!) from the Boe Bot board and put a BS2e chip in there, if you mean this kind of thing:

    www.parallax.com/Store/Microcontrollers/BASICStampModules/tabid/134/CategoryID/9/List/0/SortField/0/Level/a/ProductID/2/Default.aspx

    Is that what you meant by "already assembled"? It's $54. If you're asking about whether or not you can put one of these

    www.parallax.com/Store/Microcontrollers/BASICStampOEM/tabid/135/CategoryID/10/List/0/SortField/0/Level/a/ProductID/13/Default.aspx

    into your Boe Bot board, the answer is "no". If that's what you mean by "build my own BS2e", you might be able to wire together a version that you could wire up to a socket that then plugs into the Boe on your Bot, but it seems like a lot of trouble, and by the time you're done with the $13 interpreter chip, another $2 for the EEPROM, another $1 for the resonator, a buck or so for the circuit board and another buck for whatever you're using to connect it to the Boe, a few bucks for the power supply parts, and a few more bucks for the programming interface parts (DB9, capacitors, etc. - more if you're using USB), you're going to be close to $30, I think. And yes, you'll have to solder standard through-the-hole components together to build it.

    However, it sounds to me like you're not planning to collect so much data that it's going to be necessary to have that extra space anyway. Once you get WRITE/READ going properly with the BS2, see if you have enough space for the data you need to collect.

    BTW, here's how to write and read those word-sized variables:

    ' {$STAMP BS2sx}
    ' {$PBASIC 2.5}
    
    value   VAR     Word
    
    Main:
      value = 1125
      WRITE 0, value.LOWBYTE         ' Remember to leave two memory locations for each word-sized variable.
      WRITE 1, value.HIGHBYTE
    PAUSE 5000                              ' This is not really necessary, of course. Just here as a separator. 
      READ 0, value.LOWBYTE
      READ 1, value.HIGHBYTE
    
      DEBUG ? value
    
    



    (copied from the WRITE help page, with a little modification. Of course you'll need to use $STAMP BS2 instead)

    Finally, if you're really cramped for space, you might be able to squeeze quite a bit of data into a single byte with a little clever programming. Imagine that your bot is going to do nothing but move forward and backwards. In that case, everything would be either a 0 (say, for backwards) or a 1 (for forwards). If you went forward, forward, forward, back, back, forward, forward, back, you'd have

    Location 1 - 1
    Location 2 - 1
    Location 3 - 1
    Location 4 - 0
    Location 5 - 0
    Location 6 - 1
    Location 7 - 1
    Location 8 - 0

    So it takes 8 locations to hold all of those data. But you could instead store them in a single location,

    Location 1 - 230 (= binary 11100110 = 1*128 + 1*64 + 1*32 + 0*16 + 0*8 + 1*4 + 1*2 + 0*1)

    Using that kind of coding, each location could store 8 data points, and you now have 8 times as much storage space. Now that's sort of "best case": you've suggested that you have more than just forward and backwards, which means that kind of simple binary coding isn't going to work. But it might still be possible to figure out something that uses one location for forward-backwards and the next for right-left, and still preserve the order in which those things happened, and also still save some memory space. The simplest thing I can think of would require three bytes of memory to store 8 data points (and I may be oversimplifying it in my head - it might require 4 or even 5), but if you're butting up against memory limits, it might be worth putting some thought into that kind of thing.

    Post Edited (sylvie369) : 11/29/2008 7:10:09 PM GMT
  • GeorgeLGeorgeL Posts: 131
    edited 2008-11-29 19:01
    Thanks for all the info. What I am trying to do is record the travel path of the Boe-Bot, then export the changes in direction (1 if it goes forward, 2 backward, 3 left, 4 right) into a program I wrote in VB, that draws that data that models the path of the robot. And hopefully, I dont need the BS2e, for now at least. Thanks.
  • sylvie369sylvie369 Posts: 1,622
    edited 2008-11-29 19:11
    There's also the option of just adding an external EEPROM:

    www.parallax.com/Portals/0/Downloads/docs/prod/oem/24LC128-v2.0.pdf

    $2 plus a couple of resistors and some wire, and you can fairly easily add up to 8 of them, for WAY more memory than you're ever going to need for this project.
  • GeorgeLGeorgeL Posts: 131
    edited 2008-11-29 23:56
    Well, for my purpose, I only need to record maybe 5 values. So extra EEPROM is overkill. I really need help on recording additional values, more then just one 1 but like 3 or 4 of them. Thanks
  • GeorgeLGeorgeL Posts: 131
    edited 2008-11-30 18:24
    Still trying to get a solution for this, any small help code for me? PLEASE thanks.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-11-30 19:39
    You need a counter to keep track of the current location where you're storing values and a subroutine to record a value like this:
    ' Counter to keep track of memory location being used
    counter   var   byte   ' initialize to zero at the beginning of your program
    
    ' Subroutine to write the variable "value" to the next available location in EEPROM
    logTheData:
       write counter,value   ' write the value to EEPROM
       counter = counter + 1   ' increment the counter
       return
    


    Notice a couple of things:
    1) 'counter' is deliberately only a byte value. This keeps its value to between 0 and 255 and prevents a bug from causing your program to use more than 256 bytes of EEPROM for data and possibly overwriting your program. You said that you only needed to record a few values.
    2) The last thing logged should be some kind of marker like 255, which, by design, would never occur in your log data. This marks the end of the data for when you go back and read it later
    3) There's a limit of maybe 100,000 times any given location in EEPROM can be written before it begins to "wear out". This isn't normally a problem, but be careful about programs that write data a lot in the same location or buggy programs that are allowed to run for hours. If a program writes to the same location in EEPROM 10 times a second, that location in EEPROM will start to wear out in only 10,000 seconds. That's only about 2.5 hours.
    4) To write a value to the log, set "value" to the value (0-254) that you want to log and call "gosub logTheData".

    A program that might read this log and transmit the values to the Stamp Editor's Debug Window (assumes end of data marker is 255):
    counter   var   byte
    value      var   byte
    
       counter = 0
    
    getNextValue:
       read counter,value
       counter = counter + 1
       if value = 255 then goto theEnd
       debug value,cr
       goto getNextValue
    
    theEnd:
       debug "End of Data",cr
       stop
    

    Post Edited (Mike Green) : 11/30/2008 7:46:12 PM GMT
  • stamptrolstamptrol Posts: 1,731
    edited 2008-11-30 19:41
    George,

    Assuming you have some room left after loading the program, use the memory map in the development environment to see what's available. Say you've got 100 or so bytes left; based on what you've said that would be 100 direction codes ( 1, 2,3,4, as you've described). Would that be enough?

    If so, write a bit of code to store the direction codes using the WRITE command. Don't forget to increment the storage location after each WRITE. Also BYTE size will be fine, as several responders have pointed out.

    Also write a small subroutine that systematically READs all those locations and sends them out serially, either through a spare pin or the programming port. The serial out would be triggered by a spare pin input or a code from the keypad. When sending serially you'll have the chance to send them as DECimal chars, Hex, or as String characters which will depend on your VB program.

    Cheers,

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tom Sisk

    http://www.siskconsult.com
    ·
  • Carl HayesCarl Hayes Posts: 841
    edited 2008-11-30 19:58
    Since you have four values to record (forward, aft, port, starboard), you could record each one in a dibit (two bits), 00=forward, 01=aft, 10=port, 11=starboard, and you'd get four of them in each byte. As Mike suggests, keep a counter to know where to store the next one. This counter can be a single byte or larger, depending upon how many data you must store. Or perhaps you might want to use a two-place counter (low order goes from 0 to 3 to say which dibit in a byte, and high order goes from 0 to [noparse][[/noparse]whatever] to say which byte).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · -- Carl, nn5i@arrl.net
  • GeorgeLGeorgeL Posts: 131
    edited 2008-12-01 05:35
    Thanks for all the great ideas, ill try Mikes as soon as possible, sorry for being so unclear. I think the counter idea is what I have been looking for the whole time.
  • GeorgeLGeorgeL Posts: 131
    edited 2008-12-02 04:52
    ERRRR....
    So I was more successfull then usual, but I still have an issue, for some reason the terminal just reads
    a
    a
    a
    a
    a
    a
    a
    a
    a

    then theres a break and it repeats the long list of a's


    heres the code i ran to write the values:
    'Copyright George Lejnine
    'Only for use with Sony(r) remotes
    '{$STAMP BS2}
    '{$PBASIC 2.5}
    time VAR Word ' SONY TV remote variables
    remoteCode VAR Byte
    pulseCount VAR Byte
    counter VAR Byte
    value VAR Byte
    DEBUG "Binary Value Decimal Value", CR, ' Display heading
    "Bit 76543210 ", CR,
    "

    "
    DO ' Beginning of main loop
    Get_Pulses: ' Label to restart message check
    remoteCode = 0 ' Clear all bits in remoteCode
    ' Wait for resting state between messages to end.
    DO
    RCTIME 0, 1, time
    LOOP UNTIL time > 1000
    ' Measure start pulse. If out of range, then retry at Get_Pulses label.
    RCTIME 0, 0, time
    IF time > 1125 OR time < 675 THEN GOTO Get_Pulses
    ' Get data bit pulses.
    RCTIME 0, 0, time ' Measure pulse
    IF time > 300 THEN remoteCode.BIT0 = 1 ' Set (or leave clear) bit-0
    RCTIME 0, 0, time ' Measure next pulse
    IF time > 300 THEN remoteCode.BIT1 = 1 ' Set (or leave clear) bit-1
    RCTIME 0, 0, time ' etc
    IF time > 300 THEN remoteCode.BIT2 = 1
    RCTIME 0, 0, time
    IF time > 300 THEN remoteCode.BIT3 = 1
    RCTIME 0, 0, time
    IF time > 300 THEN remoteCode.BIT4 = 1
    RCTIME 0, 0, time
    IF time > 300 THEN remoteCode.BIT5 = 1
    RCTIME 0, 0, time
    IF time > 300 THEN remoteCode.BIT6 = 1
    DEBUG CRSRXY, 4, 3, BIN8 remoteCode, ' Display keypad code
    CRSRXY, 14, 3, DEC2 remoteCode


    '
    Routines

    IF (remotecode=1) THEN ' go forward
    value = 1
    GOSUB logthedata
    FOR pulseCount = 0 TO 30
    PULSOUT 13,650
    PULSOUT 12,850
    NEXT
    ENDIF

    IF (remotecode=4) THEN ' go backward
    value = 2
    GOSUB logthedata
    FOR pulseCount = 0 TO 30
    PULSOUT 13,850
    PULSOUT 12,650
    NEXT
    ENDIF

    IF (remotecode=3) THEN ' go left
    value = 3
    GOSUB logthedata
    FOR pulseCount = 0 TO 30
    PULSOUT 13,650
    PULSOUT 12,650
    NEXT
    ENDIF

    IF (remotecode=5) THEN 'go right
    value = 4
    GOSUB logthedata
    FOR pulseCount = 0 TO 30
    PULSOUT 13,850
    PULSOUT 12,850
    NEXT
    ENDIF

    IF (remotecode=0) THEN 'stop
    PULSOUT 13,750
    PULSOUT 12,750
    ENDIF

    IF (remotecode=9) THEN 'stop
    counter = 0
    ENDIF
    logthedata:
    WRITE counter,value ' write the value to EEPROM
    counter = counter + 1 ' increment the counter
    RETURN
    LOOP ' Repeat main





    then the code to read them:

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    counter VAR Byte
    value VAR Byte

    counter = 0

    getNextValue:
    READ counter,value
    counter = counter + 1

    DEBUG value,CR
    GOTO getNextValue




    I really want to get this right, so I dont have to bother you guys with this. Maybe a defect somewhere but I doubt.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-12-02 05:00
    You can't do this
    IF (remotecode=9) THEN 'stop
    counter = 0
    ENDIF
    logthedata:
    WRITE counter,value ' write the value to EEPROM
    counter = counter + 1 ' increment the counter
    RETURN
    LOOP ' Repeat main
    


    You have to put a GOSUB logTheData there and move the LOOP to before the logTheData: label. What you end up with the way you did it is a RETURN without a GOTO and anything can happen that way. You're also resetting "counter" rather than "value". You'll end up overwriting the first entry of the log.

    Your code to read the logged data will keep going past the end of the log, then display whatever junk is in the EEPROM.

    Post Edited (Mike Green) : 12/2/2008 5:06:51 AM GMT
  • GeorgeLGeorgeL Posts: 131
    edited 2008-12-02 05:05
    Umm?
    What do you mean?
    "IF (remotecode=9) THEN 'stop
    counter = 0
    ENDIF"
    is seperate of
    "
    WRITE counter,value ' write the value to EEPROM
    counter = counter + 1 ' increment the counter
    RETURN
    LOOP ' Repeat main"

    Or are you reffering to something I did wrong in the other If THEN statement. The (remotecode=9) is just a button on the remote I press to reset the Location of the EEPROM writting. I press this when I first begin writting new data.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-12-02 05:15
    logTheData:
    WRITE counter,value ' write the value to EEPROM
    counter = counter + 1 ' increment the counter
    RETURN
    


    is a subroutine. It must be called with a "GOSUB logTheData" after setting "value". The subroutine has to be placed in your program somewhere where execution will not "fall through" into it. If this happens, the RETURN will be executed and the Stamp will attempt to return to a place in your program that doesn't exist. Often the Stamp will reset. Sometimes it will return to after a previous GOSUB.
  • GeorgeLGeorgeL Posts: 131
    edited 2008-12-02 05:19
    But thats what I have:
    IF (remotecode=1) THEN ' go forward
    value = 1
    GOSUB logthedata
    FOR pulseCount = 0 TO 30
    PULSOUT 13,650
    PULSOUT 12,850
    NEXT
    ENDIF

    Isn't that exactly what you are saying?
  • Mike GreenMike Green Posts: 23,101
    edited 2008-12-02 05:30
    Look at what you posted. The subroutine is just before the LOOP and will be executed (including the RETURN) on every pass through the DO / LOOP.
  • GeorgeLGeorgeL Posts: 131
    edited 2008-12-02 05:48
    Oh, so I should put the logtheData after the Do LOOP, hope thatas what you mean
    Im going to try that right now then.
  • GeorgeLGeorgeL Posts: 131
    edited 2008-12-02 05:52
    Nope, didnt work , still doing the:
    a
    a
    a
    a
    a
    a
    a
    a

    in the debug terminal. Whats interesting is why does it keep writting a not somethin else?
  • Mike GreenMike Green Posts: 23,101
    edited 2008-12-02 06:05
    I didn't understand that the "a" were displayed by the routine to read the log.

    1) Make sure that the program logs a value of 255 as the last valid value like I said originally.

    2) Here's the display routine:
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    counter VAR Byte
    value VAR Byte
    
    counter = 0
    
    getNextValue:
    READ counter,value
    counter = counter + 1
    if value = 255 then stop
    DEBUG "Entry #",dec counter," is ",dec value,CR
    GOTO getNextValue
    
  • GeorgeLGeorgeL Posts: 131
    edited 2008-12-02 06:08
    WOW, Thanks it works now!!! I really apreciate everyones help. THANKS SO VERY MUCH!!!!!
    Here is a log of a very long topic:
    Entry #0 is 1
    Entry #1 is 1
    Entry #2 is 2
    Entry #3 is 3
    Entry #4 is 3
    Entry #5 is 4
    Entry #6 is 1
    Entry #7 is 1
    Entry #8 is 2
    Entry #9 is 2
    Entry #10 is 4
    Entry #11 is 1
    Entry #12 is 1
  • sylvie369sylvie369 Posts: 1,622
    edited 2008-12-03 03:25
    Congratulations. Good work.
Sign In or Register to comment.