Shop OBEX P1 Docs P2 Docs Learn Events
programming in spin — Parallax Forums

programming in spin

The new nuts volts mag, April issue 2017.. There is an article on a garage or parking sentinel using the Propeller Project Board USB. Now, I'm totally new the propeller world but I did get the program to compile but when I tried to run it nothing happened. I looked at the the signal pin on the 3 terminal ultrasonic unit and there are no pulses. Looking at the compiled program I noticed that the I2C portion of the code is red and pink. The I2C title is red and everything below it is pink. I don't know if that is normal or not. the rest of the code is blue. Is that where the problem is? If so how do I fix the problem? if not, what could it be?

Comments

  • I write about Spin programming in the odd-numbered months so I rarely download things. Where can I find the code you're having trouble with?
  • Google. "garage sentinel, nuts & volts"

    Thanks for the quick response
  • www.nutsvolts.com/magazine/article/August2015_Coyle
  • How is the Ping sensor connected?

    I notice in the article the author said he powered the Ping with 3.3V. I don't think the Ping is reliable at 3.3V.

    I suggest powering the Ping with 5V and use a 4.7k ohm resistor in series on the signal line.

    There are other things you can do test each component but I suggest trying the above with the Ping sensor.

    The colors of the sections of code you described are normal.
  • I thought about that, and I tried it but there are no pulses going to the signal pin. I also puled the Ping unit out of the circuit and there still no pulses where they should be. Thought the ping unit might be bad and pulling the signal down. The ping is now connected to 5v instead of 3.3v. I have also added a 2k resistor to the signal line. It is good to know that the colors are OK, thanks!
  • capnruss wrote: »
    I have also added a 2k resistor to the signal line.

    A 2k resistor is out of specs for the Propeller. The current on an input pin needs to be limited to 500uA. This requires about are resistor value of at least 3k. You don't want to use too high of a value or the Ping might now see the 3.3V signal. I've used 4.7k myself many times.

    You 2k resistor will probably be okay but you're putting the I/O pin at risk.

    My standard procedure of debugging a program is to add debug statements.

    I haven't tested the code below but hopefully it will give you a clue of what the program is doing.

    I left out the "Calmode" method for now.

    Give the code below a try and let us know what you see in the terminal window. The program requires input from the terminal to start so it won't work without being connected to a computer.
    CON
      _xinfreq = 5_000_000          ' specify 5 MHz xtal 
      _clkmode = xtal1 + PLL16X     ' and set clock to 80 MHz
    
      clkpermsec    = 80_000  ' define one millisec
        
    ' I/O pin assignments
      pinger        = 7
      medshortdist  = 0   ' Red LED lamp
      longdist      = 1   ' Amber LED lamp
      calbutton     = 6   ' calibration push button, active low
      
    ' EEPROM constants
      eepAdrLd      = $8000         ' non-volatile, long distance thhreshold
      eepAdrMed     = $8008         ' non-volatile, medium/short threshold
      eepromSel     = $A0           ' EEPROM select code
      promSCL       = 28            ' EEPROM SCL (clock) pin
      promSDA       = 29            ' EEPROM SDA (data) pin
    
      BAUD = 115200
      
    OBJ
      i2c   : "Basic_I2C_Driver"
      Pst   : "Parallax Serial Terminal" 
    
    VAR
      long millisec, microsec ' timing constants in system clock counts
      long duration
      long echostart, loopstart
      long flashflag
      long distance  ' distance to object, centimeters
      long pinouts   ' pattern written to output pins
      long farmark, nearmark ' zone demarcations (cm)
      long caltime ' length of cal button press, milliseconds
      long calstart, calontime
       
    PUB Main
    
      millisec := clkfreq/1_000    ' define timing constants
      microsec := clkfreq/1_000_000
    
      Pst.Start(BAUD)
    
      repeat
        Pst.Str(string(11, 13, "Press any key to begin."))
        waitcnt(clkfreq / 2 + cnt)
      until Pst.RxCount
    
      Pst.RxFlush
      
      dira[medshortdist..longdist]~~ ' set up indicator pins as output
      dira[calbutton]~
    
        ' read zone demarcation distances from EEPROM  
      farmark := i2c.ReadLong(promSCL,eepromSel,eepAdrLd)
      nearmark := i2c.ReadLong(promSCL,eepromSel,eepAdrMed)
                                                                                  
      repeat
        'IF ina[calbutton] == %0
        '  Calmode
    
        Pst.Str(string(11, 13, "About to trigger Ping."))    
        loopstart := cnt  ' begin timed loop
        !flashflag        ' toggle flash status flag
        dira[pinger]~~    ' ping a short pulse
        outa[pinger]~~
        waitcnt(50*microsec + cnt)
        dira[pinger]~   ' wait for return
         
        repeat until ina[pinger]==%1
        echostart := cnt    ' begin duration measurement
        repeat until ina[pinger]==%0
        duration := cnt - echostart ' echo delay in sys counts
        distance := duration/4936  ' distance in cm ( 6.17 msec/meter )
    
        Pst.Str(string(11, 13, "distance = "))   
        Pst.Dec(distance)
        
        IF distance => 260   ' both LEDs off
          pinouts := %00
          Pst.Str(string(11, 13, "both LEDs off")) 
        IF distance<260      ' amber on
          pinouts := %10
          Pst.Str(string(11, 13, "amber on"))
        IF distance<farmark      ' red steady on
          pinouts := %01
          Pst.Str(string(11, 13, "red steady on"))
        IF distance<nearmark       ' red flashes
           IF flashflag AND %1 == %1
             pinouts := %01
           ELSE
             pinouts := %00
           Pst.Str(string(11, 13, "red flashes"))  
        outa[longdist..medshortdist] := pinouts       
        waitcnt(250*millisec + loopstart)
    

  • JonnyMacJonnyMac Posts: 8,918
    edited 2017-04-02 22:00
    capnruss wrote: »
    www.nutsvolts.com/magazine/article/August2015_Coyle
    Well, that's in a different spot than the April 2017 issue mentioned in the OP. :)

  • Hey, thanks this worked!! It turns on the amber light at about 8 ft. Of coarse I can't change it. I also put a 4.3k resistor in the signal line. Can you put this together with the rest of the code, I'm no programmer, especially in spin. Much appreciated!!!!
  • Yes, JohnnyMac, that was my mistake sorry.
  • JonnyMacJonnyMac Posts: 8,918
    edited 2017-04-02 23:45
    capnruss wrote: »
    Yes, JohnnyMac, that was my mistake sorry.
    So is adding an errant "h" to my name! :)

    I couldn't find a Ping handy, else I would have created a new version of this project using my objects.

  • I'm changing the program so you can set the thresholds as constants.

    I'll post it in a few minutes.
  • Your the man, thanks
  • This version has the distances hard coded in to the program. You no longer need the calibration button.

    The I/O pins controlling the lights can now be on any I/O pins. They don't need to be next to each other as they were in the original program.
    CON
      _xinfreq = 5_000_000          ' specify 5 MHz xtal 
      _clkmode = xtal1 + PLL16X     ' and set clock to 80 MHz
             
      MILLISECOND = 80_000  ' define one millisecond
      MICROSECOND = 80  ' define one microsecond
      PING_TRIGGER_TIME = 50 * MICROSECOND
      LOOP_INTERVAL = 250 * MILLISECOND 
    ' I/O pin assignments
      PING_PIN = 7
      RED_PIN = 0   ' Red LED lamp
      AMBER_PIN = 1   ' Amber LED lamp
    
      BAUD = 115200
    
      CONVERT_TO_CM = 4936
      CONVERT_TO_INCH = 12537
      ACTIVE_CONVERSION = CONVERT_TO_INCH
       
    CON '' Distance Constants
    
      '' Change these constants to set ranges.
      TOO_CLOSE_THRESHOLD = 24       ' inches
      CLOSE_ENOUGH_THRESHOLD = 36    ' inches
      APROACHING_THRESHOLD = 48     ' inches
         
    OBJ
     
      Pst   : "Parallax Serial Terminal" 
    
    VAR
    
      long duration
      long loopstart
      long flashflag
      long distance  ' distance to object, centimeters
      long pinouts   ' pattern written to output pins
      
    PUB Main
    
      Pst.Start(BAUD)
      
      dira[RED_PIN] := 1
      dira[AMBER_PIN] := 1
                                                                                  
      repeat
        Pst.Str(string(11, 13, "About to trigger Ping."))    
        loopstart := cnt  ' begin timed loop
        !flashflag        ' toggle flash status flag
        dira[PING_PIN] := 1  ' ping a short pulse
        outa[PING_PIN] := 1
        waitcnt(PING_TRIGGER_TIME + cnt)
        dira[PING_PIN] := 0         ' switch to input to sense echo
    
        duration := -cnt    ' begin duration measurement
        
        waitpne(0, |< PING_PIN, 0) ' Wait for pin to go high; this more accurate than the ina loop.
    
        duration += cnt ' echo delay in sys counts
        
        distance := duration / ACTIVE_CONVERSION  ' distance in inches ( 6.17 msec/meter )
    
        Pst.Str(string(11, 13, "distance = "))   
        Pst.Dec(distance)
          
        if distance < TOO_CLOSE_THRESHOLD ' red flashes
          !outa[RED_PIN]
          outa[AMBER_PIN] := 0
          Pst.Str(string(11, 13, "Too close!"))
          Pst.Str(string(11, 13, "Less than "))
          Pst.Dec(TOO_CLOSE_THRESHOLD)
          Pst.Str(@unitsName)
        elseif distance < CLOSE_ENOUGH_THRESHOLD
          outa[RED_PIN] := 1
          outa[AMBER_PIN] := 0
          Pst.Str(string(11, 13, "Good distance!"))
          Pst.Str(string(11, 13, "Less than "))
          Pst.Dec(CLOSE_ENOUGH_THRESHOLD)
          Pst.Str(@unitsName)
        elseif distance < APROACHING_THRESHOLD
          outa[RED_PIN] := 0
          outa[AMBER_PIN] := 1
          Pst.Str(string(11, 13, "Getting close but not there yet."))
          Pst.Str(string(11, 13, "Less than "))
          Pst.Dec(APROACHING_THRESHOLD)
          Pst.Str(@unitsName)
        else
          outa[RED_PIN] := 0
          outa[AMBER_PIN] := 0
          Pst.Str(string(11, 13, "Too far away."))
          Pst.Str(string(11, 13, "You are at least "))
          Pst.Dec(APROACHING_THRESHOLD)
          Pst.Str(@unitsName)
          Pst.Str(string(" away."))
           
        waitcnt(LOOP_INTERVAL + loopstart)
    
    
    DAT
    
    unitsName     byte " in", 0
    'unitsName     byte " cm", 0
         
    

    I used inches as the unit of distance since you mentioned feet in an earlier post.

    To change the thresholds of when the various lights will turn on and off you just need to edit these constants.
    CON '' Distance Constants
    
      '' Change these constants to set ranges.
      TOO_CLOSE_THRESHOLD = 24       ' inches
      CLOSE_ENOUGH_THRESHOLD = 36    ' inches
      APROACHING_THRESHOLD = 48     ' inches
    

    As the code is now, it has four distance zones. It wouldn't be hard to add a fifth zone had have the amber light blink as one of the zones.

    I haven't tested this code. If it doesn't work as expected, let me know and I'll dig out a PING sensor and test it myself.
  • That's great. May be tomorrow before I get chance to try it. My wife has made plans for me.
  • I tried it and the pinger is working but the red led flashes at all time no matter the distance
  • capnruss wrote: »
    I tried it and the pinger is working but the red led flashes at all time no matter the distance

    Does the distance display correctly?

    Does it repeatedly output "Too close!"?

    I figured there was a good chance I did something wrong but once in a while I get lucky with an untested program.

    I'll wire up a sensor and try the program myself.

  • I was missing a "waitpeq" command.

    The code below works for me.

    Make sure and change the distance values to fit your need.
    CON
      _xinfreq = 5_000_000          ' specify 5 MHz xtal 
      _clkmode = xtal1 + PLL16X     ' and set clock to 80 MHz
             
      MILLISECOND = 80_000  ' define one millisecond
      MICROSECOND = 80  ' define one microsecond
      PING_TRIGGER_TIME = 50 * MICROSECOND
      LOOP_INTERVAL = 250 * MILLISECOND 
    ' I/O pin assignments
      PING_PIN = 7
      RED_PIN = 0   ' Red LED lamp
      AMBER_PIN = 1   ' Amber LED lamp
    
      BAUD = 115200
    
      CONVERT_TO_CM = 4936
      CONVERT_TO_INCH = 12537
      ACTIVE_CONVERSION = CONVERT_TO_INCH
       
    CON '' Distance Constants
    
      '' Change these constants to set ranges.
      TOO_CLOSE_THRESHOLD = 24       ' inches
      CLOSE_ENOUGH_THRESHOLD = 36    ' inches
      APROACHING_THRESHOLD = 48     ' inches
         
    OBJ
     
      Pst   : "Parallax Serial Terminal" 
    
    VAR
    
      long duration
      long loopstart
      long distance  ' distance to object, centimeters
      
    PUB Main
    
      Pst.Start(BAUD)
      
      dira[RED_PIN] := 1
      dira[AMBER_PIN] := 1
                                                                                  
      repeat
        Pst.Str(string(11, 13, "About to trigger Ping."))    
        loopstart := cnt  ' begin timed loop
        dira[PING_PIN] := 1  ' ping a short pulse
        outa[PING_PIN] := 1
        waitcnt(PING_TRIGGER_TIME + cnt)
        dira[PING_PIN] := 0         ' switch to input to sense echo
    
        
        waitpne(0, |< PING_PIN, 0) ' Wait for pin to go high.
        duration := -cnt    ' begin duration measurement
        waitpeq(0, |< PING_PIN, 0) ' Wait for pin to go low; this more accurate than the ina loop.
    
        duration += cnt ' echo delay in sys counts
        
        distance := duration / ACTIVE_CONVERSION  ' distance in inches ( 6.17 msec/meter )
    
        Pst.Str(string(11, 13, "distance = "))   
        Pst.Dec(distance)
          
        if distance < TOO_CLOSE_THRESHOLD ' red flashes
          !outa[RED_PIN]
          outa[AMBER_PIN] := 0
          Pst.Str(string(11, 13, "Too close!"))
          Pst.Str(string(11, 13, "Less than "))
          Pst.Dec(TOO_CLOSE_THRESHOLD)
          Pst.Str(@unitsName)
        elseif distance < CLOSE_ENOUGH_THRESHOLD
          outa[RED_PIN] := 1
          outa[AMBER_PIN] := 0
          Pst.Str(string(11, 13, "Good distance!"))
          Pst.Str(string(11, 13, "Less than "))
          Pst.Dec(CLOSE_ENOUGH_THRESHOLD)
          Pst.Str(@unitsName)
        elseif distance < APROACHING_THRESHOLD
          outa[RED_PIN] := 0
          outa[AMBER_PIN] := 1
          Pst.Str(string(11, 13, "Getting close but not there yet."))
          Pst.Str(string(11, 13, "Less than "))
          Pst.Dec(APROACHING_THRESHOLD)
          Pst.Str(@unitsName)
        else
          outa[RED_PIN] := 0
          outa[AMBER_PIN] := 0
          Pst.Str(string(11, 13, "Too far away."))
          Pst.Str(string(11, 13, "You are at least "))
          Pst.Dec(APROACHING_THRESHOLD)
          Pst.Str(@unitsName)
          Pst.Str(string(" away."))
           
        waitcnt(LOOP_INTERVAL + loopstart)
    
    
    DAT
    
    unitsName     byte " in", 0
    'unitsName     byte " cm", 0
    
  • I just tried it and it works perfectly. Thank you so much!! I can't tell you how grateful I am. You took the time to help me and you don't even know me. There aren't many like you anymore, it seems. My heart felt gratitude goes out to you. These forums are wonderful things to help people learn and grow and folks like you make it happen!!!
  • Duane is one of the really nice guys on the forum, (there are a lot).
  • He certainly is. Look forward to getting to know more like him.
  • JonnyMacJonnyMac Posts: 8,918
    edited 2017-04-05 16:42
    I don't have a Ping to test this with -- but I do have a high degree of confidence it will work. To be clear, this demo just reads the Ping sensor and displays the distance.

    Many of my programs run a generic background cog; I use this to keep a running timer and process specialty IO so that the foreground doesn't have to be bothered. In some of my Escape Room apps, I even have a monotonic music player that can play notes and simple musical runs while the foreground code happily does its thing.

    If I were building this project I would monitor the Ping in a background cog so the foreground simple had a value to deal with. In this case, the value is distance to target in microseconds which is easily converted to cm or inches.

    This also shows how to measure a pulse with a counter module so that you don't get trapped by waitpeq/waitpne if there is a sensor problem. The counter is put into POS Detect mode which counts the number of ticks the input line is high. Note that the Ping measurement is broken into discrete states so that it can be folded into the background process. At the moment, there is just the timer and the Ping, but you can do other things.

    Here's the background code -- very typical of many of my projects.
    var
    
      long  bgcog
      long  bgstack[32]
    
      long  millis
    
    
    pri background | t
    
      millis := 0
      pingstate := 0
    
      ctra := %01000 << 26 | PING                                   ' set ctra for pos detect
      frqa := 1 
    
      ' background loop
      
      t := cnt
      repeat
        waitcnt(t += MS_001)
        ++millis
        scan_ping
    
    
    var
    
      long  pingstate
      long  pingus
    
    
    pri scan_ping                                                   ' scan/measure every 100ms                                                 '
    
      case pingstate
        0 :
          outa[PING] := 1                                           ' ping output high
          dira[PING] := 1
          waitcnt(cnt + constant(US_001 << 3))                      ' wait 8+ us
          dira[PING] := 0                                           ' set to input
          phsa := 0                                                 ' clear accumulator
    
        19 :
          pingus := phsa / constant(US_001 << 1)                    ' distance to target in us
    
        99 :
          pingstate := -1                                           ' reset                                         
    
      ++pingstate
    
  • Thanks Jonny!!
  • Sorry, I just saw that you don't like to be called Jonny What should I call you?
  • TorTor Posts: 2,010
    edited 2017-04-05 14:17
    He would be OK with Jonny (or Jon) I guess.. it was Johnny (with an 'h') he objected to :)
  • Jon it is then
  • We're off topic, but... my name is Jon (says so in my signature). If you want to call me by my hacker/maker handle, "JonnyMac," that is okay, too.

    www.jonmcphalen.com
Sign In or Register to comment.