Is there something simpler than a PLL?

Go To Last Post
26 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working on a low latency IR light curtain.

 

On the receiver side, I need to extract a 4 Khz synchronization pulse from a 10% duty waveform that has lots of phase jitter on both edges.

 

The frequency of the waveform will be highly stable and accurate, since it's derived from IR send by a crystal controlled transmitter.  However, the duty cycle and phase will "jitter" significantly. 

 

I think I could do a software PLL to create a stable waveform at the frequency of the transmitter at a desired duty cycle and phase locked to something like an average, or perhaps maximum delay of the incoming waveform.  But, the math may  be a bit much for the Attiny44/84 running at 8 Mhz.

 

I'm looking for suggestions on potentially better (simpler) implementations or an implementation of something like a PLL running on an Attiny at something like 4 khz.

 

 

 

 

Last Edited: Sun. Jan 1, 2017 - 03:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I need to do some homework.

 

I just discovered the "Input Capture Unit" on the Attiny 44/84.   That may be all I need.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe you just need to generate a 25uS pulse every time you see the 4KHz pulse?

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, now I know about the capture unit and found AVR135.

 

That might get me close, but AVR135 is about capturing a duty cycle while I need to create phase locked waveform with a fixed duty cycle using the input.

 

The pulse width of the incoming waveform isn't significant.
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Torby wrote:

see the 4KHz pulse?

 

So, how to "see" the pulse?   If  use either edge of the incoming waveform, then the output waveform will have the same jitter.  That's not what I want.

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But, the math may  be a bit much for the Attiny44/84 running at 8 Mhz.

What is the hardest thing for a PLL? Probably the sine / cosine calculation.

For example you can simplify this by using a triangular waveform or a some interpolation algorithm.

 

In the beginning was the Word, and the Word was with God, and the Word was God.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

but I guess that you can do it simpler.

If you look at one edges then the same edge should come about 2000 clk later

If you make a simple delta tracker then count one down if it came early add 1 if late, it will then slowly track into the correct value, and jitter around that.

 

 

  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skotti wrote:

But, the math may  be a bit much for the Attiny44/84 running at 8 Mhz.

What is the hardest thing for a PLL? Probably the sine / cosine calculation.

For example you can simplify this by using a triangular waveform or a some interpolation algorithm.

 

 

Gosh, I was thinking just having floating point might be too much.  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

but I guess that you can do it simpler.

If you look at one edges then the same edge should come about 2000 clk later

If you make a simple delta tracker then count one down if it came early add 1 if late, it will then slowly track into the correct value, and jitter around that.

  

 

Yes, something along these lines is what I was thinking.  But, maybe change even slower than 1 clk per cycle using something like a running average for the cycle count. 

 

Maybe also look for the "same edge" during a relatively narrow time window.  This should make it less susceptible to spurious pulses.

 

Ideally, neither the rising or falling edge of the received would be used to generate an output edge since both have jitter when viewed relative to the transmit waveform.  If I just create one edge that's maintains constant phase relative to the transmit waverform, "I'm good".

 

Currently, one of the edges has much less jitter than the other.  It might be good enough to use it "as is".  I can't know until I get some more code developed and some system testing done. 

 

I'll try something along the lines you suggested.   Thanks!

 

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

That sounds similar to phase locking one clock against another.  In my case to give long term lock of the internal RC clock to a 32KHz crystal driving RTIMER3, by varying OSCCA, with typical result

 

The code is shown in https://github.com/contiki-os/co... and only needs a small addition to the TCNT3 interrupt:

 

    uint8_t error = (TCNT3 - last_phase) & 0x3f;
    if (error == 0) {
    } else if (error<32) {
      OSCCAL=osccallow-1;
    } else {
      OSCCAL=osccalhigh+1;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Assuming the OP will be using an ATtiny44/84, how will the above code and the MCU respond if the OSCCAL value is on the wrong side of 128?

 

I remember this:

 

 

- John

Last Edited: Mon. Jan 2, 2017 - 12:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You'd need to catch such conditions, also it's possible to slip a cycle. But in my case OSCCAL was biased to run at 8192 kHz so well into the high region. It works well enough to sync two radios over an hour or so.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would not change the speed of the chip, just find the speed.

 

It should be ok to know that 4KHz are 1940clk or 2100, and not the perfect 2000.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for the delay--the notification on new posts entries rarely work for me.

 

But, this seems exactly like what I need (OSCAL)!  I'll give it a try.

Last Edited: Mon. Jan 2, 2017 - 07:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

it's possible to slip a cycle

 

Can you elaborate?  By slipping a cycle, do you mean the phase of the clocks could differ by 1 8 Mhz cycle?  (Not a problem).

 

But, if the "slipped" cycles continue to accumulate for increasing phase error, this won't work for me.

 

Thanks!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My description from memory was wrong, this is a (clocked by 32 kHz crystal) async Timer2 interrupt at 1 kHz that looks at the phase of (clocked by RC oscillator) Timer3. The adjustment is done every second and only works when the phase error is in the region -31...31.  A thumb on the chip can drive it outside that range, then it will lock onto the new multiple after a possible overshoot. Increasing the mask size would lower the chances of that happening but would introduce 16 bit arithmetic.  Checking the phase more often should also give a tighter lock.

 

I was concerned about changing OSCCAL too often, but that does not seem to be a consideration. Also in my case there were other interrupts that could block the clock interrupt by up to a msec which would make the error appear too large over short time period. And I was outputting the data for the graph through the UART.  You can probably do the adjustment more frequently if you have a better way to monitor the error while setting it up.

 

 

 

Last Edited: Mon. Jan 2, 2017 - 11:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dak664 wrote:

My description from memory was wrong...,

 

Ok, thanks for the heads up.

 

I thought about it some more, and what I need is a bit different.

 

Some jittter in the received IR waveform is expected due to the varying amount of integration time the sensor needs before it's output indicates "IR sensed".   It can be from 5 to 10 IR (40 Khz) cycles, according to the  sensor spec.

 

But, the type of jitter I'm seeing on the oscope doesn't seem consistent with what I'd expect due to slightly varying sensor delays.  It's bimodal with a set of edges coming too early to be  the result of the sensor recognizing a burst of IR.

 

So, I'm going to understand what's causing that behavior.  Maybe it can be resolved so I can just use the edge as is.

 

In my light curtain application, each sensor has a timeslot.  The edge is only needed to maintain synchronization with the IR transmitter so that an IR sensor only gets a chance to indicate "sensor blocked" during the timeslot(s) it is expected to "see" the IR signal.  Even the jitter as is may be ok, but I'm going to try to fix it.

 

Thanks!

 

I

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reflections might be a cause for your jitter.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Reflections are definitely something to worry about, but the jitter I was observing isn't anywhere near a full timeslot period.   

 

The pulse the IR sensors are generating  is when all emitters are off. 

 

Turns out if I use two timeslots of dead time instead of one, the jitter on the "first IR on" edge is virtually eliminated.

 

So, I'm thinking that while the digital output of the sensor indicated "no IR", internally the sensor still had some residual memory (maybe a partially charged integration capacitor) that caused the turn on delay to be much shorter (sometimes).

 

That's just a theory, but I do observe that blocking the IR emitter that precedes the "dead timeslot" eliminated the jitter of the "IR back on" edge.   So, I can probably eliminate the jitter by extending the dead time to something longer than one timeslot. ( Two timeslots worth of dead time pretty much eliminates the jitter).

 

Thanks!

 

 

 

 

 

 

Last Edited: Wed. Jan 4, 2017 - 01:05 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jfiresto wrote:
Assuming the OP will be using an ATtiny44/84, how will the above code and the MCU respond if the OSCCAL value is on the wrong side of 128? I remember this: ...

 

I struggled a bit with this in an app some time ago, where a watch crystal was used to tune the internal oscillator as close to 7.37MHz as practical for USART work.  [Tuning towards the magic frequency makes the small error more forgiving...]

 

Anyway, I thought I would be clever, and if way off I'd take a leap in OSCCAL values to try to get close.  But in practice, in units where the leap jumped over the discontinuity I ended up in no-man's-land and never got there as the next reading would cause a leap in the opposite direction.

 

My solution was crude and simple -- and perhaps obvious in hindsight:  Only take one step of OSCCAL in the right direction each pass.  So, using your chart say I determined that the clock was running too fast for my taste, and OSCCAL is 192.  Step down, step, step, step, and at 128 or so it got worse.  Just keep step, step, step, down to a good value.

 

In a side note, with e.g. the chart you posted, tuning to 7.37MHz instead of 8MHz will give a final result away from the discontinuity.

 

An exercise left for the student:  Once you are "there" and satisfactorily tuned you have some choices.  In all probability you won't be exact, but a little high or a little low.  During the calibration process, you could keep track of how much change the last step made, and use that as a deadband.  Or arbitrarily establish a deadband.  In the end I chose to just let it keep tuning +/-1 OSCCAL count each pass.

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OSCCAL is not guaranteed to be monotonic on the LSB.  It is guaranteed to be monotonic on LSB+1, though.  That is, increasing OSCCAL by one is not guaranteed to increase the oscillator frequency, but increasing is by two is.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
OSCCAL is not guaranteed to be monotonic on the LSB. It is guaranteed to be monotonic on LSB+1, though. That is, increasing OSCCAL by one is not guaranteed to increase the oscillator frequency, but increasing is by two is.

1)  Does that also apply to the models with the discontinuity in the curve?

2)  Then my brute-force "keep stepping in the right direction" still works.

2a) ... lol unless the right spot happens to be on one of those pseudo values?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1)  Does that also apply to the models with the discontinuity in the curve?

I believe so.  AVR053 doesn't mention it specifically, but that document was prepared after the introduction of version 5.x oscillators, which employs the two overlapping ranges selected by OSCCAL's MSB, and that aspect at least is covered in the appnote.

 

2a) ... lol unless the right spot happens to be on one of those pseudo values?

That's my take on it, yes.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It should be possible to identify algorithmically any non-monotonic steps in OSCCAL in advance and store a map in EEPROM or FLASH.  A test program can characterise the actual speed for every value of OSCCAL, then those values are sorted by speed.  Runtime calibration then becomes an matter of incrementing/decrementing the index to the lookup table, rather than OSCCAL itself.  OSCCAL is then loaded with the appropriate table entry.  The lookup table is of course going to take 256 bytes (or 128 for devices with only one range), but an advantage is that values from both ranges are homogenised into a single range.

 

I've done something similar in the past.  Using the WDT as a reference, one-time characterisation of all values of OSCCAL takes about four seconds. 

 

If a full LUT isn't desired or feasible, it should be possible to determine the weight of each bit in OSCCAL, then create a polynomial which predicts the real-world effects of any given OSCCAL value.  Eight 16-bit coefficients would take 32 bytes to store v.s. 256 bytes for the LUT, but I'd guess the code footprint could be higher.  Sounds like an interesting project... when things die down for me around here (in a couple of months) I may take a crack at it :)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

this is reply to #20 sometimes the system show a wrong number

 

[Tuning towards the magic frequency makes the small error more forgiving...]

What!

Unless you run different baud rates it don't make any sense, the best clk is to run close to 8MHz with 0% error like 9600 baud from 8MHz should be 7987200Hz

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

davethomaspilot wrote:

Is there something simpler than a PLL?

I'm working on a low latency IR light curtain....

...

Some jittter in the received IR waveform is expected due to the varying amount of integration time the sensor needs before it's output indicates "IR sensed".   It can be from 5 to 10 IR (40 Khz) cycles, according to the  sensor spec.

 

But, the type of jitter I'm seeing on the oscope doesn't seem consistent with what I'd expect due to slightly varying sensor delays.  It's bimodal with a set of edges coming too early to be  the result of the sensor recognizing a burst of IR.

 

 

I'm not quite following this approach/perceived problem.

Usually in a Light-Curtain app, you also generate the IR drive, and so know already the frequency. ergo you do not need a PLL.

What is commonly needed is a synchronous detector, so that you sense the modulated IR and reject mains lighting, and sunlight.

That can be an analog switch, integration cap, and ADC. This can work 'into the noise', and recover IR carrier info not visible on an ordinary scope trigger.