Shop OBEX P1 Docs P2 Docs Learn Events
Gate Timer — Parallax Forums

Gate Timer

Brian_BBrian_B Posts: 842
edited 2015-09-28 22:15 in Propeller 1
Hi All,
I'm working on a dual gate timer and have it somewhat working. This code works except that I can't figure out how to get hundredths of seconds to display properly. Any thoughts would be much appreciated.

Thanks Brian

Comments

  • I have no idea what you're doing, but I think what I've attached is a cleaner way to do it.

    Unless you know your gate time is going to be very short, avoid using calls to the cnt register. In this version the ADC reader cog also increments a millis register that is used to provide timing references -- same way you're doing.

    No need for floating point, either.

  • Jon,
    It looks good ,but adc seems like it's not working.

    Thanks'
    Brian
  • Jon,
    If I comment out "waitcnt (t +=MS_001)" it runs.


    Thanks'
    Brian
  • JonnyMacJonnyMac Posts: 9,105
    edited 2015-09-29 17:35
    You can't simply remove the waitcnt as that is controlling your milliseconds timing. I did a quick test and it turns out in Spin, that ADC is stupid slow (yes, I know I wrote the code, but I never measured until today). It takes about 1.5ms to read an ADC channel so you can change your milliseconds resolution to 2 like this:
    pri gates | t, ch
    
    '' Scan analog channels every 2 milliseconds
    '' -- update global millis value
    
      adc.start(ADC_CS, ADC_CLK, ADC_DI, ADC_DO)                     ' start adc
    
      t := cnt                                                       ' sync time point
      repeat
        repeat ch from 0 to 3                                        ' loop through channels
          long[@chan0][ch] := adc.read(ch)                           ' read adc
          waitcnt(t += (MS_001 << 1))                                ' allow 2ms window to expire
          millis += 2                                                ' update millis register
    

    This is still 5x the desired resolution you want to display, so I think you'll be fine.

    Sorry for the confusion.

    If you know for a fact that your timing is always going to be under 26 seconds, you can get to clock ticks pretty easy -- this is what I did to determine the time to read an ADC channel.
    elapsed := -cnt
    { code under timing test }
    elapsed += cnt - 544
    

    The "- 544" removes the Spin overhead (if there is no test code between the timing lines the result will be 0). In my program I have constants for microseconds and milliseconds that I use for converting clock ticks to human-friendly time units.

    Finally, you now have an object called jm_time.spin that can do timing for you. You can do something like this
    time.start
    { code under timing }
    elapsed := time.millis
    

    Because I do so many timing-oriented things, I developed the object. The only caveat with it is you must call it periodically (no less than every 53 seconds at 80MHz). If you had a very long timing event you could do it like this
    repeat until (start_condition)
    time.start
    repeat
      elapsed := time.mark
    until (stop_condition)
    
  • Jon,
    Works SUPER ! It has a little glitch if you try it really fast , but that should never be a proplem.

    Here are some photo's of my 3d printed gates and homemade air track.

    Thanks' a million,
    Brian
    864 x 648 - 168K
    864 x 648 - 209K
    648 x 864 - 197K
    864 x 648 - 181K
  • Cool!

    I'm curious as to why you're using the ADC for inputs. What is the output of the device you're reading? Based on your threshold, the sensor seems to be pulled up and then goes low. If this is the case and it drops below 1.6v, you can use a simple digital input.
  • Jon,
    That's a good question. When I started messing with this IR sensor (BPW41N) I couldn't get it to drop below 4.8 volts. Now that I have it wired right it goes from 5 volts to .5 volts , so yes I could just use a simple digital input.

    It's funny that once you start heading one way with a problem you overlook the simple solution :)

    Thanks'
    Brian

  • JonnyMacJonnyMac Posts: 9,105
    edited 2015-09-30 16:55
    If you use a couple pins as inputs, you no longer need the background cog (remove it). And as I know you're doing very short-term events, I would modify the main code like this to display gate-to-gate time with 1ms resolution.
    pub main | elapsed 
    
      setup
    
      repeat
        repeat while ina[START_PIN]
        elapsed := -cnt                                              ' start timing
        outa[LED_26] := IS_ON
         
        repeat while ina[STOP_PIN]
        elapsed += cnt - 544                                         ' stop timing
        outa[LED_26] := IS_OFF
    
        elapsed /= MS_001                                            ' convert ticks to ms
    
        term.str(string("Elapsed time: "))                           ' report 
        term.dec(elapsed / 1000)
        term.tx(".")
        term.rjdec(elapsed // 1000, 3, "0")
        term.tx(term#CR)
    

    Now that I have it wired right it goes from 5 volts to .5 volts , so yes I could just use a simple digital input.

    To be on the safe side, put a 3.9K (or higher) resistor between the sensor output and the pin.

  • Jon,
    Now I remember why I went with a ADC. During daylight hours the beam break only drops the voltage to 4.5 volts. If wrap my hand totally around the sensor it will drop to .5 volts.


    Thanks'
    Brian
  • Brian_BBrian_B Posts: 842
    edited 2015-10-14 23:24
    Jon,
    I finally got the logic code to work in sunlight. I printed some "sun glasses" for my gates , just some pinhole covers on the infrared sensors.

    Thanks' for the help !

    Brian
    490 x 653 - 120K
    490 x 653 - 116K
Sign In or Register to comment.