Shop OBEX P1 Docs P2 Docs Learn Events
Spurius characters occationally — Parallax Forums

Spurius characters occationally

The weather program that I've been working on for a while is nearing completion, thanks to a lot of help from this forum!

Sometimes weird characters show up after running it. If left for hours it also sometimes locks up. I don't know how to figure this out. There must be some anomaly somewhere.

How do I check for this?

There are also a few other things that need completing.

It's a long program, but if anyone has time on their hands and could point me to some bad code, that would be appreciated?
OBJ    
    vga:    "VGACOLOR_320x240_CURSOR"  ' VGA Driver             need 2 Cog's
    i2c  :   "I2C pasm driver v1.8od"       

PUB main  
 
    cognew(windSpeed,@stack)
    cognew(RTCcog,@Rtcstack)

    init
    initScreen
    ms := 0   

    repeat
        dira[16]~~
        Winput:=I2C.readByte(MCP,GPIOA)      ' wind direction
        dir:=winput 
        updateDir
     
        waitcnt((clkfreq / 1000) * 1 + cnt)   ' wait 1 ms        

            'get_measurements                 '' reads temperature and pressure into UT and UP
     
        I2C.writeByte(BMP,CONTROL,TEMP)      ' start a temperature measurement
        waitcnt(cnt + clkfreq / 10000 * 45)  ' wait 4.5ms
        UT := I2C.readWordB(BMP,ADC)         ' read temperature
         
        I2C.writeByte(BMP,CONTROL,PRESSURE)  ' start a pressure measurement - 0 oversampling
        waitcnt(cnt + clkfreq / 10000 * 45)  ' wait 4.5ms
        UP := I2C.readWordB(BMP,ADC)         ' read pressure

        convert_measurements
        PSI:=(p-1280)/(32)
        updateSpeed
         
        waitcnt(clkfreq/2+cnt)
        ms++
        str(15,27, $0F, $00,string("reset at 0")) 
        decxy(27, 27, $08, $00, (120 - ms))
        if   ms=>120    'works out to be every 71 seconds
                                         
          ms := 0        'clear and restart counter  
          gust := 0      'clear gusts
        updatetime

        if (ms==40) OR (ms==80) OR (ms==2)           
             
          updateTemp
           
          updateBarom

          updateHDC
          
          outa[16]~~
          waitcnt(clkfreq + cnt)  'adds a second to the ms countdown
          outa[16]~          

PRI updateSpeed    '
  
    'decxy(11, 3, $08, $00, speed)
    updategusts
    updateMax
    
PRI  updateGusts
  
  if  speed > gust
    gust:= speed
    
  if  ms==120
      gust:=0  
  decxy(29,3,$0B,$00,gust)    
PRI  updateMax

    if  speed > maxWind
      maxWind := speed
      decxy(11,5,$0B,$00,maxWind)
       hex(timbuf[2],2)
       str(19, 5, $0B, $00,@nstr)  
       str(21, 5, $0B, $00, string(":"))
       hex(timbuf[1],2)
       str(22, 5, $0B, $00,@nstr)

PRI updateTime   'this is time in lower right corner

    hex(timbuf[2],2)                   'convert hours to string stored at nstr
    str(31, 25, $0B, $00,@nstr)  
    str(33, 25, $0B, $00, string(":"))
    hex(timbuf[1],2)
    str(34, 25, $0B, $00,@nstr)    
    str(36, 25, $0B, $00, string(":"))
    hex(timbuf[0],2)
    str(37, 25, $0B, $00,@nstr)

PRI updateTemp   'this is inside temp from baro sensor

    decxy(10, 9, $0A, $00, (T * 9 / 5 + 320)/(10))   ' Print farenheit
    str(13,9,$0A,$00,string("F"))                       
                

PRI updateBarom
    
    decxy(23, 9, $0B, $00,PSI)
    str(28,9,$0E,$00,string("2 decimals"))                                 

PRI updateHDC  |  local_long

    local_long := HDC << 1 | 1
    I2C.command(HDC,$00)       'start a temp, hum measurement
    waitcnt(clkfreq/10+cnt)

    I2C.arbitrary(@local_long,1,@local_long,4)
    waitcnt(clkfreq/10+cnt)

    temp_C := local_long.byte[0] << 8 | local_long.byte[1]
    temp_C := temp_C * 165 / 65536 - 40

    Far := temp_C * 9/5+32
    decxy(10,11,$0A,$00,Far)  'this is outside temp
    str(13,11,$0A,$00,string("F"))

    RH := local_long.byte[2] << 8 | local_long.byte[3]
    RH := RH * 100 / 65536
    str(10,14,$0F,$00,string("RH"))
    decxy(13,14,$0A,$00,RH)
    str(15,14,$0A,$00,string("%"))

    DP := Far - ((100-RH)/5)
    str(17,14,$0F,$00,string("DP"))
    decxy(20,14,$0A,$00,DP)
    str(23,14,$0A,$00,string("F"))    
     
PRI updateDir     
    
    binxy(8, 16, $0E, $00, Winput, 8)              ' Print binary Winput               cyan on black           

    case Winput
        %0000_0110:                 '128
            updateNeedle(@wind_N)
            str(12, 7, $0D, $00,string("N   "))
        %0000_0100:                 '129
            updateNeedle(@wind_NNE)
            str(12, 7, $0D, $00,string( "N NE"))
        %0000_1100:                 '1
            updateNeedle(@wind_NE)
            str(12, 7, $0D, $00,string("NE  "))
       
PRI updateNeedle(ptr) | x, y

    repeat y from 19 to 25
        repeat x from 2 to 8
            printxy(x, y, $0D, $00, byte[ptr++])            ' Print Needle             white on black

PRI init | i, j, k, p1, offs
''************************************************
''* Start  VGA Cog's, Clear Screen and  *
''* set Cursor's                                 *
''************************************************
    I2C.start(scl,sda,bitrate)   

    offs := 62                                              ' 62 Bytes BMP-Header not used, 128x128 2 Color Bitmap
    repeat i from 15 to 0
        repeat j from 7 to 0
            p1 := (i * 16) + (j * 256)
            repeat k from 0 to 15
                fontbuff[p1+k] := reverse(font[offs++]) 

    wordfill(@vgabuff, $0F20, 1200)                         ' Clear Screen with $20 (Space) FG-Color $F (white), BG-Color $0 (black)

    vga.start(video, @vgabuff, @fontbuff, @cursor, @sync)   ' Start Video Driver
    waitcnt(clkfreq * 1 + cnt)                              ' wait 1 second for cogs to start

    I2C.writeWordB(HDC,Config_reg,Config_params)            'configure HDC
    waitcnt(clkfreq/10+cnt) 


    str(0, 16, $0F, $00, @strWinput)          ' Print "Winput"                            white on black   

PRI reverse(val) : new | i
''************************************************
''* Reverse a Byte                               *
''* eg. %01000000 = $40 to %00000010 = $02       * 
''************************************************

    i := 1
    val <<= 32 - 8
    repeat 8
        if ((val <-= 1) & 1) == 1
            new += i 
        i *= 2 


PRI getPos(x, y)

    return (x + y * 40) * 2


PRI print(fgc, bgc, char) 
''************************************************
''* Print Character char at current pos          *
''* with Foreground-Color fgc and                *
''*      Background-Color bgc                    *
''************************************************

    vgabuff[pos++] := char
    vgabuff[pos++] := bgc * 16 + fgc


PRI printxy(x, y, fgc, bgc, char) 
''************************************************
''* Print Character char at current pos          *
''* with Foreground-Color fgc and                *
''*      Background-Color bgc                    *
''************************************************

    pos := getPos(x, y)
    print(fgc, bgc, char)


PRI str(x, y, fgc, bgc, string_ptr)
''************************************************
''* Print String at x, y                         *
''* with Foreground-Color fgc and                *
''*      Background-Color bgc                    *
''************************************************

    pos := (x + y * 40) * 2
    repeat strsize(string_ptr)
        print(fgc, bgc, byte[string_ptr++])

PRI drawBox(x, y, w, h, fgc, bgc) | t1, m, b, i
''************************************************
''* Draw Box at x, y with w = width, h = height  *
''* Foreground.Color fgc                         *
''* Background-Color bgc                         *
''************************************************

    t1 := (y * 40 + x) * 2
    m := t1 + 80
    b := m + ((h-2) * 80)
    pos := t1  
    print(fgc, bgc, $80)               
    fill(fgc, bgc, $81, w-2)           
    print(fgc, bgc, $82)               
    repeat i from 0 to h-3
        pos := m + i * 80
        print(fgc, bgc, $86)
        fill(fgc, bgc, $20, w-2)
        print(fgc, bgc, $86)   
    pos := b   
    print(fgc, bgc, $83)                
    fill(fgc, bgc, $81, w-2)           
    print(fgc, bgc, $84)

PRI fill(fgc, bgc, char, len) | x
''************************************************
''* Fill len of Char's with char                 *
''* Foreground.Color fgc                         *
''* Background-Color bgc                         *
''* at current pos                               * 
''************************************************

    if len <> 0
        repeat x from 1 to len
            print(fgc, bgc, char)

PRI decxy(x, y, fg, bg, val) 

    pos := getPos(x, y)
    prn(fg, bg, val)
    print(fg, bg, $20)


PRI prn(fg, bg, val) | dig

    dig := 48 + (val // 10)
    val := val/10
    if val > 0
        prn(fg, bg, val)
    print(fg, bg, dig)

PRI binxy(x, y, fgc, bgc, value, digits)
''************************************************
''* Print binary value at x, y                   *
''* with Foreground-Color fgc and                *
''*      Background-Color bgc                    *
''************************************************

    pos := (x + y * 40) * 2
    value <<= 32 - digits
    repeat digits
        print(fgc, bgc, (value <-= 1) & 1 + "0")

PUB convert_measurements | X1, X2, X3, B3, B4, B5, B6, B7, oss 
        ' converts uncalibrated UT and UP into calibrated temperature T and pressure P
        
    X1 := ((UT - AC6) * AC5) ~> 15           ' X1 := (UT - AC6) * AC5 / 2^15
    X2 := ~~MC << 11 / (X1 + ~~MD)           ' X2 := MC * 2^11 / (X1 + MD)
    B5 := X1 + X2                            ' B5 := X1 + X2
    T := (B5 + 8) ~> 4                      ' T  := (B5 + 8) / 2^4

    oss := 0                                

    B6 := B5 - 4000                          ' B6 := B5 - 4000
    X1 := (B2 * ((B6 * B6) ~> 12)) ~> 11   ' X1 := (B2 * (B6 * B6 / 2^12)) / 2^11
    X2 := (~~AC2 * B6) ~> 11               ' X2 := AC2 * B6 / 2^11                                    
    X3 := X1 + X2                          ' X3 := X1 + X2                                            
    B3 := (AC1 * 4 + X3) ~> 2            '* ' B3 := ((AC1 * 4 + X3) << oss + 2) / 4
    X1 := (~~AC3 * B6) ~> 13                    ' X1 := AC3 * B6 / 2^13
    X2 := (B1 * ((B6 * B6) ~> 12)) ~> 16        ' X2 := (B1 * (B6 * B6 / 2^12)) / 2^16                     
    X3 := ((X1 + X2) + 2) ~> 2                  ' X3 := ((X1 + X2) + 2) / 2^2                              
    B4 := (AC4 * (X3 + 32768)) ~> 15            ' B4 := AC4 * {(unsigned long)}(X3 + 32768) / 2^15
    B7 := (UP - B3) * (50000 >> oss)     '*     ' B7 := {((unsigned long))}(UP - B3) * (50000 >> oss)      
    if (B7 < $8000_0000)                        ' if (B7 < $8000_0000)                                     
      P := (B7 << 1) / B4                       '    p := (B7 * 2) / B4                                    
    else                                        ' else                                                     
      P := (B7 / B4) << 1                       '    p := (B7 / B4) * 2
    X1 := (P ~> 8) * (P ~> 8)                   ' X1 := (p / 2^8) * (p/2^8)                                
    X1 := (X1 * 3038) ~> 16                     ' X1 := (X1 * 3038) / 2^16                                 
    X2 := (-7357 * P) / 65536                   ' X2 := (-7357 * p) / 2^16                                 
    P := P + (X1 + X2 + 3791) ~> 4              ' p := p + (X1 + X2 + 3791) / 2^4


PUB WindSpeed | PlsCnt'cog
         'Set up the counters
  ctra := %01110 << 26 + pin1     'counter A in NEG edge detect mode
  
  frqa  := 1               'increment 1 per pulse      
       'pulse count loop
  repeat    
    phsa := 0                         'reset count registers       
    waitcnt(clkfreq *2 + cnt)  'wait gate time of 2 second  
    PlsCnt := phsa                     'read the puls counts             
             'convert pulse count to RPM and display
    speed := PlsCnt    'pulse average divided by 2 segments times 60 seconds

    decxy(11, 3, $08, $00, speed)
      

PUB hex(value, digits)

'' Returns pointer to a digits-wide hexadecimal string

  clrstr(@nstr, MAX_LEN) 
  return hexstr(value, digits)


PRI clrstr(strAddr, size)

' Clears string at strAddr
' -- also resets global character pointer (idx)

  bytefill(strAddr, 0, size)                            ' clear string to zeros
  idx~                                                  ' reset index


PRI hexstr(value, digits)

' Converts value to digits-wide hexadecimal string equivalent
' -- characters written to current position of idx
' -- returns pointer to nstr

  digits := 1 #> digits <# 8                            ' qualify digits
  value <<= (8 - digits) << 2                           ' prep most significant digit
  repeat digits
    nstr[idx++] := lookupz((value <-= 4) & $F : "0".."9", "A".."F")
  return @nstr
  
 
PUB  RTCcog
   repeat
     I2C.readbytes(RTC,0,@timbuf,7)
     waitcnt(clkfreq /2 + cnt)     
                   
     

Comments

  • I forgot to include the screen shot
    3072 x 2304 - 861K
  • Tracy AllenTracy Allen Posts: 6,656
    edited 2018-05-31 01:19
    One possible cause of weirdness is i2c methods running async in two cogs. The RTCcog is hitting the i2c port every 1/2 second, and sooner or later it will clash with the i2c methods that are called in your main cog. This is a danger unless the i2c is protected with locks. In your program, it may be easier just to roll the call to the RTC back into the main loop in one cog.
  • I put the RTC in the main program (eliminated the RTC cog) but still after a while get some weird characters in various places.
    I've attached a screenshot with some garbage in the wind direction box.

    Could it have anything to do with initing the screen (writing the text words) at the beginning of the program and never refreshing it?


    As I write this, there has now appeared some garbage just after the wind direction data.

    Aaron

    3072 x 2304 - 2M
  • I just tried reiniting the screen every 2 minutes and so far so good
  • It looks like maybe the stack is inside the video buffer.
  • Hello,

    @AGCB

    you use my "VGACOLOR_320x240_CURSOR.spin" - Driver.

    Can you post the whole Code?
    Maybe i can help you.

    Greetings from Nuremberg, Germany
    Werner

  • Werner
    13,489 characters too long to post. Is there a way around this?
    Aaron
  • AGCB wrote: »
    Werner
    13,489 characters too long to post. Is there a way around this?
    Aaron

    Zip it up in the Propeller tool, and attach the zip.
  • I don't see hoe to 'zip it up'
  • I'll be away from computer till Monday AM so will not be able to reply to new posts.
    Thanks Aaron
  • WhitWhit Posts: 4,191
    @AGCB - sounds like others are helping solve your problem. Just wanted to say that this is a cool project. Best of luck.
  • Hello Aaron,
    i think i found the Error:

    The "decxy" Method in the Mainloop and the "decxy" in the "Windspeed"-Cog
    fight against each other. :lol:

    Make this Changes:
    DAT
    
    ' Add the new "pos2" var, add "print2", "decxy2" and "prn2"
    ' Change in "WindSpeed" "decxy" to "decxy2"
    ' Hope this will help... 
    
    
    VAR
    
        long pos2                          ' Global Screen-Pointer #2
    
    
    PRI print2(fgc, bgc, char) 
    ''************************************************
    ''* Print Character char at current pos2         *
    ''* with Foreground-Color fgc and                *
    ''*      Background-Color bgc                    *
    ''************************************************
    
        vgabuff[pos2++] := char
        vgabuff[pos2++] := bgc * 16 + fgc
    
    
    PRI decxy2(x, y, fg, bg, val) 
    
        pos2 := getPos(x, y)
        prn2(fg, bg, val)
        print2(fg, bg, $20)
    
    
    PRI prn2(fg, bg, val) | dig
    
        dig := 48 + (val // 10)
        val := val/10
        if val > 0
            prn2(fg, bg, val)
        print2(fg, bg, dig)
    
    
    PUB WindSpeed | PlsCnt'cog
             'Set up the counters
      ctra := %01110 << 26 + pin1     'counter A in NEG edge detect mode
      
      frqa  := 1               'increment 1 per pulse      
           'pulse count loop
      repeat    
        phsa := 0                         'reset count registers       
        waitcnt(clkfreq *2 + cnt)  'wait gate time of 2 second  
        PlsCnt := phsa                     'read the puls counts             
                 'convert pulse count to RPM and display
        speed := PlsCnt    'pulse average divided by 2 segments times 60 seconds
    
    '    decxy(11, 3, $08, $00, speed)
        decxy2(11, 3, $08, $00, speed)                      ' use it's own "decxy" Method
    
    

    Greetings from Nuremberg, Germany
    Werner
  • That was the problem? Thanks. Even overnight, no garbage.

    Werner, how do I get a 'degree symbol' to print in VGA? When I put one in from the Propeller font is just gives a squiggly line.

    Aaron
  • Werner
    Would you please give me some basic info on how to use that Cp437_8_new.bmp font. I've tried to figure it out on my own but haven't.

    Thanks
    Aaron
  • Hello Aaron,

    the "CP437_8_NEW.BMP" (256 Colors) is the Template for the "CP437_8.BMP" (2 Colors).

    In the "CP437_8_NEW.BMP" (256 Colors) i see the unused Characters. (green/darkgreen)

    The "CP437_8.BMP" must have only 2 Colors.

    The 'degree symbol' is always available in the "CP437_8.BMP" File, as Char $BF,

    The green Char:

    cp437_8_degree.bmp
    PRI updateTemp   'this is inside temp from baro sensor
    
        decxy(10, 9, $0A, $00, (T * 9 / 5 + 320)/(10))   ' Print farenheit
        str(13, 9, $0A, $00, @strF)                      ' Print "°F"                     
    
    
    
    DAT
    
    strF              byte $BF, "F", 0
    
    
    

    I hope all is clear...

    Greetings from Nuremberg, Germany
    Werner


  • Thanks Werner! I think I got it.
    Aaron
  • It's been working great for months! I still get a few spurious characters in or around the needle graphic but not so as to be much of a bother.
    However, I'd like to do a few changes in the program code but can't seem to get in. When I try it says "can't find file CP437_8.bmp in work folder or library". I tried to add it to library but it won't allow. It is already in the same folder as the main code.(I think)
    I've tried multiple things to correct this to no avail. I remember having the same problem when I was 1st working on this but somehow got it to work.

    I wanted to see if there were any cogs left to put in a 'onewire' temperature display and also wanted to add a automatic daylight savings time correction.

    Please advise me.

    Thanks
    Aaron
  • Is there a way to tell easily how many COGs a program is using?
Sign In or Register to comment.