Shop OBEX P1 Docs P2 Docs Learn Events
Help with Stargate project running out of memory — Parallax Forums

Help with Stargate project running out of memory

Kenny DKenny D Posts: 8
edited 2006-07-03 06:44 in BASIC Stamp
I am working on a project building a stargate as in Stargate SG1. I am using a servo to turn the inner wheel and a cherry picker switch to count grooves that correspond to the symbols on the wheel. The switch will later be changed out for an opto coupler for greater accuracy.
I have a BS2e and I am using an infrared remote control to select a symbol
from 1 to 39.· I enter the number then press enter on the remote.
··
After entering the number the stargate moves left until it counts to the first chevron then it moves right to the second chevron, then it moves the selected symbol to the home position.
·
I have gotten it to work. However, I can only program about 15 or so symbols before I run out of memory on the BS2.· I would also like the wheel to pause for about 2 seconds after it reaches each destination and light an led.· i have had limited luck ith this.···
·
I had a BS2 stamp and when I ran out of memory I bought the BS2E thinking it would handle it.
·
Can anyone look at this program and tell me if there is a better way to do these functions without using up all my memory?
·
· Right now I only have one case to make things easier to follow.

Thanks,
·
' {$STAMP BS2e}
' {$PBASIC 2.5}

' -----[noparse][[/noparse] I/O Definitions ]-------------------------------------------------

' SONY TV IR remote declaration - input receives from IR detector
 IrDet PIN 9
 Speaker PIN 4
 
' -----[noparse][[/noparse] Constants ]-------------------------------------------------------

' SONY TV IR remote constants for non-keypad buttons.
Enter CON 11
 
' -----[noparse][[/noparse] Variables ]-------------------------------------------------------

' SONY TV IR remote variables'
irPulse VAR Word           ' Single-digit remote variables
remoteCode VAR Byte
index VAR Nib
value VAR Word             ' Stores multi-digit value
pulsecount VAR Word
counter VAR Word
newin7 VAR Bit
oldin7 VAR Bit
oldin7 = IN7
led VAR Bit
'------------------------------------------------------------------------------
 

start:
DO
DEBUG "Enter a value: ", CR
GOSUB Get_Multi_Digit_Value
DEBUG "The value is: ", DEC value, CR, CR
 ' DEBUG ? counter

  SCAN:
   newin7 = IN7
   counter = counter + (newin7 ^ oldin7 & newin7)        ' increment on 0-->1 transition
     oldin7=newin7

'******************************************************************
SELECT value          ' Value is the remote code entered
 
CASE 1
 
DO
 'DEBUG ? counter
IF (counter <= 8) THEN           'fisrt stop
  GOSUB forward
    ELSEIF counter = 9 THEN       ' feeble attempt at turning on an led at the 9th count
     GOSUB led1
      ELSEIF (counter >= 9) AND (counter<=14) THEN      ' 2nd stop
       GOSUB back
       ELSEIF counter = 15 THEN                            '3rd stop
    
      ELSEIF (counter >= 15) AND (counter<=20) THEN      '4th stop,I deleted the other 2 stops for memory
     GOSUB forward
    ELSEIF counter = 21 THEN
  GOSUB reset                                              'reset
ENDIF                                                   ' more cases later 
 GOTO scan
  LOOP
       ENDSELECT
  LOOP
   '-----------------------------routines
        forward:
          PULSOUT 13, 800
          PAUSE 20
           RETURN
        Back:
          PULSOUT 13, 700
          PAUSE 20
          RETURN
        led1:
          HIGH 1
          PAUSE 100
          LOW 1
          GOSUB forward
          RETURN
        reset:
         HIGH 1
         PAUSE 200
         LOW 1
         PAUSE 200
         HIGH 1
         PAUSE 200
         LOW 1
         counter = 0

   GOTO start
 

' -----[noparse][[/noparse] Subroutine - Get_Ir_Remote_Code ]---------------------------------
' SONY TV IR remote subroutine loads the remote code into the
' remoteCode variable.
Get_Ir_Remote_Code:
remoteCode = 0 ' Clear all bits in remoteCode.
DO ' Wait for rest between messages.
RCTIME IrDet, 1, irPulse
LOOP UNTIL irPulse > 1000
PULSIN IrDet, 0, irPulse ' Measure pulse.
IF irPulse > 500 THEN remoteCode.BIT0 = 1 ' Set (or leave clear) bit-0.
RCTIME IrDet, 0, irPulse ' Measure next pulse.
IF irPulse > 300 THEN remoteCode.BIT1 = 1 ' Set (or leave clear) bit-1.
RCTIME IrDet, 0, irPulse ' etc.
IF irPulse > 300 THEN remoteCode.BIT2 = 1
RCTIME IrDet, 0, irPulse
IF irPulse > 300 THEN remoteCode.BIT3 = 1
RCTIME IrDet, 0, irPulse
IF irPulse > 300 THEN remoteCode.BIT4 = 1
RCTIME IrDet, 0, irPulse
IF irPulse > 300 THEN remoteCode.BIT5 = 1
RCTIME IrDet, 0, irPulse
IF irPulse > 300 THEN remoteCode.BIT6 = 1
' Adjust remoteCode so that keypad keys correspond to the value
' it stores.
IF (remoteCode < 10) THEN remoteCode = remoteCode + 1
IF (remoteCode = 10) THEN remoteCode = 0
RETURN
' -----[noparse][[/noparse] Subroutine - Get_Multi_Digit_Value ]------------------------------
' Acquire multi-digit value (up to 65535) and store it in
' the value variable. Speaker beeps each time a key is
                                             ' pressed.
Get_Multi_Digit_Value:
value = 0
remoteCode = 0
DO
value = value * 10 + remoteCode
DO
GOSUB Get_Ir_Remote_Code
IF (remoteCode < 10) THEN
DEBUG "You pressed: ", DEC1 remoteCode, CR
GOSUB Beep_Valid
EXIT
ELSEIF (remoteCode = Enter) THEN
DEBUG "You pressed: ENTER", CR
GOSUB Beep_Valid
EXIT
ELSE
DEBUG "Press 0-9 or ENTER", CR
GOSUB Beep_Error
ENDIF
LOOP
LOOP UNTIL (remoteCode = Enter)
RETURN
' -----[noparse][[/noparse] Subroutine - Beep_Valid ]------------------------------------
' Call this subroutine to acknowledge a key press.
Beep_Valid:
FREQOUT Speaker, 100, 3500
PAUSE 200
RETURN
' -----[noparse][[/noparse] Subroutine - Beep_Error ]------------------------------------
' Call this subroutine to reject a key press.
Beep_Error:
FREQOUT Speaker, 100, 3000
PAUSE 200
RETURN

Comments

  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2006-06-24 22:33
    Kenny,

    ·· I think the problem might be that you thought you could put a larger program into the BS2e. While it has more EEPROM memory it is split up into 8 program slots.· Please see the following Nuts & Volts article which should help you out.

    http://www.parallax.com/dl/docs/cols/nv/vol3/col/nv87.pdf

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Kenny DKenny D Posts: 8
    edited 2006-06-27 00:06
    That's great info.

    Not sure how to apply it to my application though.

    If anyone has any ideas or something to put me on the right track,
    It'd be greatly appreciated.

    confused.gif·
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2006-06-27 00:12
    Kenny,

    ·· Read that article, and plan your program around a slot-oriented architecture and you'll be able to make it work.· Move sections of the program that can run by themselves into other slots, or, if data is taking up a lot of your program space, for example a lot of DEBUG or SEROUT routines, consider making one subroutine and placing the data in another slot.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Kenny DKenny D Posts: 8
    edited 2006-06-27 01:47
    Thanks,

    I'll see what I can come up with.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2006-06-27 03:21
    Kenny,

    ·· Don't forget to declare your variables exactly the same in each slot/program to preserve them between banks.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • crgwbrcrgwbr Posts: 614
    edited 2006-06-29 19:25
    Have you gotten this running yet? I'm a huge fan of SG-1 (only 15 more days till season 10!); anyway, I'd love to see a picture of this.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    NerdMaster
    For
    Life
  • Kenny DKenny D Posts: 8
    edited 2006-06-30 02:34
    m still working on it...so far I'm using 4 banks.

    It's a bit tricky to jump around but I think Im on th right track now.

    I'll post a pic when it's done.

    kenny
  • HarborHarbor Posts: 73
    edited 2006-06-30 03:45
    Kenny:

    Learning how to use the slot architecture is the most important change, but some of it is just the need to put things more compactly. Express them in the easiest way for the tokenizer. For example, the subroutine: Get_Ir_RemoteCode.
    Original was...
    Get_Ir_Remote_Code:
    remoteCode = 0 ' Clear all bits in remoteCode.
    DO ' Wait for rest between messages.
    RCTIME IrDet, 1, irPulse
    LOOP UNTIL irPulse > 1000
    PULSIN IrDet, 0, irPulse ' Measure pulse.
    IF irPulse > 500 THEN remoteCode.BIT0 = 1 ' Set (or leave clear) bit-0.
    RCTIME IrDet, 0, irPulse ' Measure next pulse.
    IF irPulse > 300 THEN remoteCode.BIT1 = 1 ' Set (or leave clear) bit-1.
    RCTIME IrDet, 0, irPulse ' etc.
    IF irPulse > 300 THEN remoteCode.BIT2 = 1
    RCTIME IrDet, 0, irPulse
    IF irPulse > 300 THEN remoteCode.BIT3 = 1
    RCTIME IrDet, 0, irPulse
    IF irPulse > 300 THEN remoteCode.BIT4 = 1
    RCTIME IrDet, 0, irPulse
    IF irPulse > 300 THEN remoteCode.BIT5 = 1
    RCTIME IrDet, 0, irPulse
    IF irPulse > 300 THEN remoteCode.BIT6 = 1
    ' Adjust remoteCode so that keypad keys correspond to the value
    ' it stores.
    IF (remoteCode < 10) THEN remoteCode = remoteCode + 1
    IF (remoteCode = 10) THEN remoteCode = 0
    RETURN
    This form takes 200 bytes in code space. I'm not familiar with the physical events you're detecting here, so I'll assume you need to change from pulsin to rctime. But after that original pulsin we can make the coding more efficient:
    Get_Ir_Remote_Code:
    · ndx VAR Nib
    · SetBit VAR Byte
    · remoteCode = 0 ' Clear all bits in remoteCode.
    · SetBit=1
    · DO ' Wait for rest between messages.
    ··· RCTIME IrDet, 1, irPulse
    · LOOP UNTIL irPulse > 1000
    · PULSIN IrDet, 0, irPulse ' Measure pulse.
    · IF irPulse > 500 THEN remoteCode=remotecode|SetBit
    · FOR ndx=0 TO 6
    ··· SetBit=SetBit<<1
    ··· RCTIME IrDet, 0, irPulse ' Measure next pulse.
    ··· IF irPulse > 300 THEN remoteCode = remotecode|SetBit
    · NEXT
    · IF remotecode<10 THEN remotecode=remotecode+1
    · IF remotecode=10 THEN remotecode=0
    RETURN
    This version takes only 110 bytes. Formatted this way, it's not obvious, but I'm also indenting things like the body of a loop. Good habit to develop. Now, I actually would not code those last two lines of the subroutine·that way. It may be intentional, but it seems odd that you return the same value (zero) for a detected remotecode of 9 or 10. The interaction between if-then statements can be tricky. I prefer the select-case statement. It will cost another three bytes, but will save errors in the long run. My version may not be what you intend since remotecode 9 will return ten and 10 will return zero. But it still only takes 113 bytes. This is a 43% reduction in code space, which adds up quickly. In-line code is generally not as efficient as looping except in special cases.

    The select-case form looks like this:
    · SELECT remotecode
    ···· CASE <10
    ·· ···· remotecode=remotecode+1
    ··· ·CASE =10
    ····· · remotecode=0
    · ENDSELECT
  • SSteveSSteve Posts: 808
    edited 2006-06-30 17:06
    If I'm not mistaken, his Get_Ir_Remote_Code is taken from a Nuts & Volts article by Jon Williams. In the article Jon specifically says that the code can't be put in a loop because it would slow execution down enough to where the Stamp wouldn't be able to keep up with the IR stream.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    OS-X: because making Unix user-friendly was easier than debugging Windows

    links:
    My band's website
    Our album on the iTunes Music Store
  • HarborHarbor Posts: 73
    edited 2006-07-01 03:07
    That's quite possible. I'm not familiar with the physical characteristics of remote codes. I wouldn't have expected them to be spaced so closely a BS2 couldn't manage a for-next loop, but expectations mean nothing. I'm sure Jon measured things with an oscilloscope and knew how many milliseconds were available between pulses.
  • Kenny DKenny D Posts: 8
    edited 2006-07-03 06:44
    That is correct I used pieces of code from the article
    I have figured out how to do multi bank programming now, so my memory problem is
    solved. Now, I just have to get the machine finished and make it all come together.

    Thanks for the replies...It's encouraging to know there are so many knowledgeable people here to help.
Sign In or Register to comment.