Shop OBEX P1 Docs P2 Docs Learn Events
Counters, POS detector and long period measurment — Parallax Forums

Counters, POS detector and long period measurment

It a long time since I've played around with the counters.

I had an idea for an instrumentation experiment with a wood moisture sensor based on a relaxation circuit. The only caveat, the frequency can be as low as one full cycle every 100seconds.

I cant remember from the top of my head how high the frequency could go, should be in the range 5-10kHz as an absolute maximum. (above 1khz should be of little to no interest if I've done and calulated this correctly)

I worry about the counter rolling over. Am I correct in understanding, setting the counter to pos mode, and loading the FRQ register with a number larger than one, f.ex 1000, will increment PHS register every thousand ticks? Should I rather use spin and wait for pinstate instructions instead?


  • JonnyMacJonnyMac Posts: 8,974
    edited 2024-05-15 14:25

    ...loading the FRQ register with a number larger than one, f.ex 1000, will increment PHS register every thousand ticks?

    No, the counter will add the value of FRQx into the accumulator every cycle. With FRQx set to 1 the counter will roll-over at about 56 seconds when running at 80MHz. You could slow the P1 by changing the PLL setting, but this may affect other code.

    I've written dozens of P1 programs that invoke a background process, typically running a loop every 1ms (which is convenient to create a timing element). I did a simple pulse measurement using that strategy. What I love about the P1 is I can create a pulse on a pin in one cog and measure it in another without any wires using that same pin.

    This could be modified to measure the high and low side if you wanted -- it's very simple code. Here's the background code. A demo is attached.

    pri background | sample, pwidth, t
      repeat                                                        ' wait for input to be low
        if (ina[PLS_IN] == 0)
        waitcnt(cnt + MS_001)
      sample := %00                                                 ' clear locals
      pwidth := 0
      t := cnt                                                      ' sync loop timer
        waitcnt(t += MS_001)
        millis += 1
        sample := ((sample << 1) | ina[PLS_IN]) & %11               ' sample, save last & current
        case sample
          %01 : pwidth  := 1                                        ' leading edge, reset
          %11 : pwidth  += 1                                        ' input high, accumulate
          %10 : pulsems := pwidth                                   ' falling edge, report
          %00 : pwidth  := 0                                        ' input low
  • JonnyMacJonnyMac Posts: 8,974
    edited 2024-05-15 14:35

    Just because I like to be sure, I ran this little test:

      ctra := %01000 << 26 | PLS_IN 
      frqa := 1                   
      phsa := 0
        term.fstr1(string("Measured pulse: %dms\r"), phsa/MS_001)
        phsa := 0

    The measurement reads 1000ms as expected. Increasing the value of frqa to 10 multiplies the result by 10; this confirms that frqa does not act like a divider when using it in pos-detect mode.

  • HH Posts: 21

    Thanks for the clarification Jon, I should have tested. But I had a feeling that rollover would give me some trouble, so I knew I needed some help

    Yeah, I use "slow" loops like this pretty much the same way. Everything that need speed runs in its own cog, and the main loop runs a looptimer, and does the coordination and "taskmanagment"

    btw: thats a really neat way to save and compare the previous value. It pleases my OCD, and probably solves the problem without much modification. I'll borrow that one :smile:

Sign In or Register to comment.