Shop OBEX P1 Docs P2 Docs Learn Events
Please help me fix this code — Parallax Forums

Please help me fix this code

kicknitinkckicknitinkc Posts: 28
edited 2010-03-04 03:20 in Learn with BlocklyProp
Hello all, I am new to this forum so sorry if this has been covered somewhere. I have a homework assignment which entails that I can do whatever I want with what I have in this custom basic stamp 2 kit. It's pretty much the "whats a microcontroller?" kit with a few extra goodies. What I decided to do is do the lightmeter project with the 2x16 serial lcd as the display, a button to start and stop the lightmeter, and a speaker to play sounds for on/off events and for different time settings from RCTIME. I had it working perfect but when I came back to mess with it, the program tells me I have data that occupies the same location as the program. I've narrowed it down to the intro message (which has an animation) but cannot figure out what the heck I changed with it that has caused this problem. If any one of you stamp 2 pros could give me some insight, I would greatly appreciate it. This assignment is due Thursday, March 4, so if that date has passed, don't worry bout it. Anyways, here's my super long code:




' {$STAMP BS2}
' {$PBASIC 2.5}

'----------CONSTANTS-----------
button1         PIN     3               ' button pin
TX              PIN     15              ' serial output to LCD
LcdBaud         CON     32              ' LCD baudrate = 19,200
LcdCls          CON     $0C             ' clear LCD (use PAUSE 5 after)
LcdBLon         CON     $11             ' backlight on
LcdBLoff        CON     $12             ' backlight off
LcdOff          CON     $15             ' LCD off
LcdOn1          CON     $16             ' LCD on; cursor off, blink off
LcdCC0          CON     $F8             ' define custom char 0
LcdCC1          CON     $F9             ' define custom char 1
LcdCC2          CON     $FA             ' define custom char 2
LcdLine1        CON     $80             ' move to line 1, column 0
LcdLine2        CON     $94             ' move to line 2, column 0
midtime         CON     10000

'------------VARIABLES-----------
idx1            VAR     Byte
idx2            VAR     Byte
idx3            VAR     Byte
idx4            VAR     Byte
s               VAR     Byte
time            VAR     Word
newchar         VAR     Byte

'-----------EEPROM DATA----------
CC0             DATA    LcdCC0, 14,21,31,10,14,14,0,0
CC1             DATA    LcdCC1, 14,21,31,10,14,0,14,0
CC2             DATA    LcdCC2, 14,21,31,10,14,0,0,14

msg2            DATA  "  Mechatronics  "
msg3            DATA  "  is AWESOME!!  "



'--------------power on song-----------

PAUSE 250

  FREQOUT 14, 75, 2093
  FREQOUT 14, 75, 2637
  FREQOUT 14, 75, 3136
  FREQOUT 14, 75, 2349
  FREQOUT 14, 75, 2793
  FREQOUT 14, 75, 3520
  FREQOUT 14, 75, 2637
  FREQOUT 14, 75, 3136
  FREQOUT 14, 75, 3951
  FREQOUT 14, 75, 2793
  FREQOUT 14, 25, 4186
  FREQOUT 14, 25, 4086
  FREQOUT 14, 25, 4186
  FREQOUT 14, 25, 4286
  FREQOUT 14, 25, 4186
  FREQOUT 14, 25, 4086
  FREQOUT 14, 25, 4186
  FREQOUT 14, 25, 4286
  FREQOUT 14, 1000, 4186, 4191



    HIGH TX                               ' setup serial output pin
    PAUSE 100                             ' allow LCD to initialize



    FOR idx1 = 0 TO 26                ' download 3 characters
     READ CC0 + idx1, s                ' get data from table
      SEROUT TX, LcdBaud, [noparse][[/noparse][b]s[/b]]          ' send to LCD
    NEXT


  SEROUT TX, LcdBaud, [noparse][[/noparse]LcdBLoff, LcdOn1, LcdCls]
  PAUSE 250

'------------intro message-----------------------
'*************fault is in here somewhere***************
FOR idx3 = 0 TO 15                   ' scroll across line
    READ (Msg2 + idx1), newChar         ' read new character
    FOR idx2 = 0 TO 4                   ' animate a current position
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1,  newchar], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](LcdLine1 + idx1), s]
      PAUSE 50
    NEXT
  NEXT

FOR idx4 = 0 TO 15                   ' scroll across line
    READ (Msg3 + idx1), newChar         ' read new character
    FOR idx2 = 0 TO 4                   ' animate a current position
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1,  newchar], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](LcdLine2 + idx1), s]
      PAUSE 50
    NEXT
  NEXT
'********************************************************

FOR idx1 = 1 TO 10
    SEROUT TX, LcdBaud, [noparse][[/noparse]LcdBLon]
    PAUSE 75
    SEROUT TX, LcdBaud, [noparse][[/noparse]LcdBLoff]
    PAUSE 75
  IF idx1 = 10 THEN
    SEROUT TX, LcdBaud, [noparse][[/noparse]LcdBLon]
    PAUSE 250
    ENDIF
  NEXT

DO

  IF button1 = 1 THEN
    HIGH TX                               ' setup serial output pin
    PAUSE 100
      DO
      SEROUT TX, LcdBaud, [noparse][[/noparse]lcdblon, LcdOn1, LcdCls]

'-------------lightmeter---------------------

  HIGH 2
  PAUSE 2
  RCTIME 2, 1, time

  IF time > 20000 THEN
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),(lcdline2),"B =0%"," t =", DEC time]
      FREQOUT 14, 105, 1661

  ELSEIF time < 20000 AND time >= 18750 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,(lcdline2),"B =6%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 100, 1760
    NEXT

  ELSEIF time < 18750 AND time >= 17500 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,(lcdline2),"B =13%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 95, 1865
    NEXT

  ELSEIF time < 17500 AND time >= 16250 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,(lcdline2),"B =19%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 90, 1976
    NEXT

  ELSEIF time < 16250 AND time >= 15000 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,(lcdline2),"B =25%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 85, 2093
    NEXT

  ELSEIF time < 15000 AND time >= 13750 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,(lcdline2),"B =31%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 80, 1217
    NEXT

  ELSEIF time < 13750 AND time >= 12500 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,(lcdline2),"B =38%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 75, 2349
    NEXT

  ELSEIF time < 12500 AND time >= 11250 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,(lcdline2),"B =44%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 70, 2489
    NEXT

  ELSEIF time < 11250 AND time >= 10000 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,(lcdline2),"B =50%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 65, 2637
    NEXT

  ELSEIF time < 10000 AND time >= 8750 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,(lcdline2),"B =56%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 60, 2793
    NEXT

  ELSEIF time < 8750 AND time >= 7500 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =63%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 55, 2960
    NEXT

  ELSEIF time < 7500 AND time >= 6250 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =68%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 50, 3136
    NEXT

  ELSEIF time < 6250 AND time >= 5000 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =75%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 45, 3322
    NEXT

  ELSEIF time < 5000 AND time >= 3750 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =81%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 40, 3520
    NEXT

  ELSEIF time < 3750 AND time >= 2500 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =88%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 35, 3729
    NEXT

  ELSEIF time < 2500 AND time >= 1250 THEN
    FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =94%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 30, 3951
    NEXT

  ELSEIF time < 1250 AND time >= 0 THEN
  FOR idx2 = 0 TO 4
      LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
      SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =100%"," t =", DEC time]
      PAUSE 75
      FREQOUT 14, 25, 4186
    NEXT
  ENDIF

PAUSE 100

  IF button1 = 1 THEN
    FOR idx3 = 0 TO 2 STEP 1
  NEXT
  SEROUT TX, LcdBaud, [noparse][[/noparse]LCDCLS, (lcdline1),2,1,0,1,2,"SEE YA",2,1,0,1,2 ]
  ENDIF
  IF button1 = 1 AND idx3 = 3  THEN

'----------------outro-------------------

    FREQOUT 14, 75, 2093
    FREQOUT 14, 75, 4186
    FREQOUT 14, 75, 2793
    FREQOUT 14, 75, 3951
    FREQOUT 14, 75, 3136
    FREQOUT 14, 75, 2637
    FREQOUT 14, 75, 3520
    FREQOUT 14, 75, 2793
    FREQOUT 14, 75, 2349
    FREQOUT 14, 75, 3136
    FREQOUT 14, 25, 2637
    FREQOUT 14, 25, 2093
    FREQOUT 14, 25, 1993
    FREQOUT 14, 25, 2093
    FREQOUT 14, 25, 2193
    FREQOUT 14, 25, 2093
    FREQOUT 14, 25, 1993
    FREQOUT 14, 25, 2093
    FREQOUT 14, 1000, 2093, 2098
  EXIT
  ENDIF
  LOOP

  ENDIF
PAUSE 500
SEROUT TX, LcdBaud, [noparse][[/noparse]Lcdoff, lcdbloff ]
LOOP

Post Edited (kicknitinkc) : 3/2/2010 6:54:20 AM GMT

Comments

  • kicknitinkckicknitinkc Posts: 28
    edited 2010-03-02 06:46
    Just to add to my post, I think the problem has something to do with calling out the custom character animations. I used the same format as the Serial_LCD_Demo.bs2 file I found on the parallax website. When I use my custom characters in place of the "chomper" for the demo file it works just fine. I dunno, I just can't figure out where the data is overlapping the program, especially since it worked flawlessly for awhile until I cleaned up the code. If you couldn't already tell, I had to teach myself how to use the serial LCD because we haven't gone over it in class yet, lol, so sorry if the code looks like junk. I'll mess with it some more tomorrow......

    PS: On a side note, with this part of the code:

    IF button1 = 1 THEN
    FOR idx3 = 0 TO 2 STEP 1
    NEXT
    SEROUT TX, LcdBaud, [noparse][[/noparse]LCDCLS, (lcdline1),2,1,0,1,2,"SEE YA",2,1,0,1,2 ]
    ENDIF
    IF button1 = 1 AND idx3 = 3 THEN

    anyone know why idx3 somehow goes to 3 and why "IF button1 = 1 AND idx3 = 3 THEN" is the only way I can get the button to turn off the lightmeter? Seems like I'm missing something here.
  • Tony B.Tony B. Posts: 356
    edited 2010-03-02 14:24
    You are recieving the error because you are using up all the available memory of the stamp. Each SEROUT command takes alot of space, and your code use many of them. I commented out two of the SEROUT commands and was then able to get the program to compile and show the memory map. With two SEROUT commands commented out the memory map show 96% of the memory full. Note that when you are looking at the memory map your DATA is shown at the top and fills downward and your program code starts at the bottom and fills upwards. In other words you are running out of memory space because of the many SEROUT commands.

    Since many of the SEROUTs do practically the same thing look for ways to store similar things in DATA and CONs then you could have maybe one or two SEROUT that you call and pass in the data.

    Tony

    Post Edited (Tony B.) : 3/2/2010 2:42:18 PM GMT
  • bill190bill190 Posts: 769
    edited 2010-03-02 14:39
    Do this and you can run memory map and see...

    'msg2··········· DATA· "· Mechatronics· "
    'msg3··········· DATA· "· is AWESOME!!· "

    msg2··········· DATA· "· M"
    msg3··········· DATA· "· i"

    Above uses less EEPROM space. Try adding a bit more to a message and see what happens...
  • kicknitinkckicknitinkc Posts: 28
    edited 2010-03-02 17:46
    Thanks for your help guys. I thought the bs2 had much more space than that. I'll try messing with using less SEROUT commands but not quite sure how I would do that yet. I'll also try getting rid of idx3 and 4 and decreasing the amount of space set for variables where applicable. In the future I will be using the serial LCD for my big project and may need more space. How would I go about adding more space to the bs2? I have a boatload of questions concerning this final project and will post another thread for it. Thanks.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-03-02 18:36
    You can't add more space to the BS2. You have to trim down your program. In your case, you will have to make your program more "table-driven" with the table information stored in EEPROM along with your program using DATA statements and READ statements to access it. For example,
    ELSEIF time < 2500 AND time >= 1250 THEN
        FOR idx2 = 0 TO 4
          LOOKUP idx2, [noparse][[/noparse]0, 1, 2, 1, 0], s
          SEROUT TX, LcdBaud, [noparse][[/noparse](lcdline1),s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,(lcdline2),"B =94%"," t =", DEC time]
          PAUSE 75
          FREQOUT 14, 30, 3951
        NEXT
    


    This is repeated many times with only small changes. In particular, the lower and upper time range, percent shown, and FREQOUT value are the only things changed. These could be stored in a table using only 5 bytes per entry since you need only one time bound (lower or upper) if you search the table from the beginning each time. Similarly, you could store the power-on song and the "outro" song as a sequence of two byte FREQOUT values using a zero or -1 as a "stop" entry and have a little loop to play them like this:
    playIt:
       READ  position, word temp
       position = position + 2
       IF temp = 0 THEN RETURN
       FREQOUT 14, 25, temp
       GOTO playIt
    


    To play the power on song, you'd do:
    powerOn DATA
       DATA word 2093, word 2637   ' and so on
       DATA word 0   ' marks end of table
    


    Then you'd do:
       position = powerOn
       GOSUB playIt
    
  • kicknitinkckicknitinkc Posts: 28
    edited 2010-03-02 20:48
    Hmm, I see I see. So I will have to give it another shot and use tables when i get off work. Are you saying that I need to assign a word to each frequency value? I'm also confused about what your temp variable is. Thanks Mike!
  • Mike GreenMike Green Posts: 23,101
    edited 2010-03-02 21:02
    Yes, you need a word to hold each frequency value since the values are all greater than 8 bits. You could probably compress them to 8 bits by using a base value (like 2000) and a scale factor (like 2 or 3) so the actual frequency value = theByte * scale + base.

    temp is just a word variable as is position. They can be used for other temporary purposes elsewhere in the program.

    Encoding your data in tables in EEPROM is often a great way to save space in a program with a lot of repetitive stuff.
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2010-03-02 23:59
    Excellent suggestions, Mike!

    kicknitinkc, looks like you are doing some great work and really getting the hang of things.

    For examples of tables, and to compact your FREQOUT songs, see Chapter 8 of What's a Microcontroller.· For examples of reusing a Temp variable, and for squeezing a lot of sensor data into a small space, take a look at·Advanced Robotics with the SumoBot.

    -Steph
  • kicknitinkckicknitinkc Posts: 28
    edited 2010-03-03 04:36
    I have been trying to make tables for the freqout commands and I was wondering if there is there a way to get this method to work? I'm thinking I might have to make separate loops for the "READ frequencies + (intro), Word freq" and "READ durations + (durationsequence), Word duration" lines to make it work. I was trying to avoid using lookup and lookdown commands because this makes better sense to me ( I used MATLAB alot last semester and grew accustomed to the coding). Anyways, here's what I came up with for the intro code so far:

    
                              '0           1         2          3         4         5
    frequencies     DATA   Word 1993, Word 2093, Word 2193,  Word 2349, Word 2637, Word 2793,
                              '6           7         8          9         10        11
                           Word 3136, Word 3520, Word 3951, Word 4086 ,Word 4186, Word 4286
    
    IntroSequence   DATA    1,  4,  6,  3,  5,  7,  4,  6,  8,  5,
                            10,  9,  10,  11,  10,  9,  10,  11
    
    OutroSequence   DATA    1,  10,  5,  8,  6,  4,  7,  5,  3,  6,
                            4,  1,  0,  1,  1,  2,  1,  0,  1
    
    
    
                              '0  '1
    durations         DATA    25,  75
    
    DurationSequence  DATA  1,  1,  1,  1,  1,  1,  1,  1,  1,
                            1,  0,  0,  0,  0,  0,  0,  0,  0
    
    
    
    
    freq             VAR    Word
    duration         VAR    Word
    index            VAR    Byte
    INtro            VAR    Byte
    outro    VAR    Byte
    durationseq VAR    Byte
    '--------------power on song-----------
    
    
    
    PAUSE 250
    
    FOR index = 0 TO 18
    
      READ IntroSequence + (index * 2), intro
        READ frequencies + (intro), Word freq
      READ durationsequence + (index * 2), durationseq
        READ durations + (durationseq), Word duration
    
    'play last note with mixed frequency
    
      IF index = 18 THEN
      FREQOUT 14, 1000, 4186, 4191
      ELSEIF index => 0 AND index <= 17 THEN
      FREQOUT 14, duration, freq
      ENDIF
    
    NEXT
    
    



    Thanks for the references and encouragement Steph, I've read most of "What's a Microcontroller?" and I had a rough time with that chapter haha. I'm now checking out the "AppliedSumo" book for that temporary variable thing.

    Thanks for your help.

    Post Edited (kicknitinkc) : 3/3/2010 7:01:30 AM GMT
  • kicknitinkckicknitinkc Posts: 28
    edited 2010-03-03 06:57
    Ok, I gave up on using tables and just changed the intro message to a non-animated one because my lazy method was promising but had some kinks and I didn't want to go back and organize the songs again. It pays to save different filenames occasionally..... lesson learned. I think I can handle tables now, thanks for pointing me in that direction. I'm sure I'll have to use that later.


    I added my final code if anyone is curious
    The setup is:
    photoresistor w/ 0.1mF cap. pin 2
    pushbutton pin 3
    speaker pin 14
    serial lcd pin 15

    Post Edited (kicknitinkc) : 3/3/2010 7:12:48 AM GMT
  • kicknitinkckicknitinkc Posts: 28
    edited 2010-03-03 16:53
    I was looking at ch. 8 on "What's a Microcontroller?" and I didn't like the way they used the lookup and lookdown commands because they use repeated frequencies and durations which takes up more space. Is there a way to just call out the frequencies and durations that are needed without repeating then in the table? This would be pretty much like my method I tried earlier but with lookup and lookdown commands, which I think would work out the kinks I had. Thanks for your feedback.
  • Mike GreenMike Green Posts: 23,101
    edited 2010-03-03 17:51
    One option for special cases (like repeated entries) is to use "invalid" values to mean something special. For example, if your frequency information is always greater than 1000, you can use values less than 1000 for a repeat count and make table entries either two or three words so you'd have:

    DATA word 1993, word 100 ' freq 1993 for duration 100 (default repeat count = 1)
    DATA word 20, word 1993, word 100 ' freq 1993 for duration 100 repeated 20 times
  • kicknitinkckicknitinkc Posts: 28
    edited 2010-03-04 03:20
    Thanks for your suggestion Mike. Sorry to be an annoyance but I'm trying to understand what you mean but I don't quite get it. Here's where I got stumped:

    
    '{$STAMP BS2}
    ' {$PBASIC 2.5}
     index VAR Byte
     frequency     DATA Word 20, Word 1993, Word 100
     freq VAR byte
    FOR index 0 TO 20
     READ frequency, Word freq
     FREQOUT 14, ???, ???
    next
    
    
    



    I guess I'm confused about how I would call out that data using FREQOUT.
Sign In or Register to comment.