0 and 100 percent duty cycle detection........

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

Hello there......

I have a little project here that takes in a pulse train, whose duty cycle varies from 0 to 100% and I am converting it to 0-10vdc using an UNO and a DAC.  Its all working great except for the problem of detecting when teh input is at a logic low (0%), or logic high(100%) pont.  Everything between those two works like a charm.

 

But I need to be able to know if the line is at one extreme, or teh other.

 

So, I read up on PulseIn() here:

https://www.arduino.cc/reference...

 

And from what I gather, this function needs to see a transition...fair enough.

 

I was looking at this example:

https://create.arduino.cc/projec...

 

But it makes no mention of what happens when you hit the endpoints.

 

I suppose I could have some code that checks the state of the pin when the PulseIn() function returns '0'

 

Anyone have a better idea?

 

Jim

This topic has a solution.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Wed. Aug 3, 2022 - 07:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need some form of monostable, but if the code has a timeout param already, that might be good enough.

I presume you can tolerate the blocking ?

You would just set the timeout comfortably longer than the known? PWM period. 

Easy to try :)

 

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

jgmdesign wrote:
whose duty cycle varies from 0 to 100%

 

I can imagine both cases, common is 'no-pulse' situation.

Detect no pulse, measure H or L, that is it.

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

So how does a simple servo do it ?

 

[edit]

Scratch that: They only allow a very limited range of duty cycle.

 

How about if you impose limits on duty cycle. (0.1% to 99.9% for example) ?

 

Last Edited: Wed. Aug 3, 2022 - 09:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:

So how does a simple servo do it ?

 

 

If you mean teh little hobby servos that are in RC cars and planes there is a continuous pulse train with a varying duty cycle that matches the fully CCW and fully CW points.  There is never a 0% or 100% duty cycle

 

grohote wrote:

I can imagine both cases, common is 'no-pulse' situation.

Detect no pulse, measure H or L, that is it.

 

Exactly. 

 

Who-me wrote:
You would just set the timeout comfortably longer than the known? PWM period. 

That does me no good because the 0% or 100% could sit at that state for very long periods of time, and in both cases PulseIn() returns a '0' which tells me nothing other than the pin is not pulsing.

 

I guess the easiest solution is to do a digital read of the pin when PulseIn() returns a '0'.  And move on with life

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:

 

Who-me wrote:
You would just set the timeout comfortably longer than the known? PWM period. 

That does me no good because the 0% or 100% could sit at that state for very long periods of time, and in both cases PulseIn() returns a '0' which tells me nothing other than the pin is not pulsing.

 

I guess the easiest solution is to do a digital read of the pin when PulseIn() returns a '0'.  And move on with life

Yes, exactly.

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

How fast is the pulse train? I'm assuming it's some form of PWM or PPM. It might be possible to just calculate a moving average (simple or exponential) of the input.

 

For a simple moving average, keep a ring buffer to hold old samples. Continuously read the input every millisecond or so (depends on how fast the pulse train runs), and if it's high, add 1 to a running sum; subtract the oldest sample in the ring buffer from the running sum. Drop the oldest sample from the ring buffer and add the new sample to the ring buffer (depending on how you implement the ring buffer, adding a new sample could automatically and simultaneously drop the oldest sample). Then divide the running sum by the size of the array. That's your average duty cycle.

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

christop wrote:

How fast is the pulse train?

 

30Hz

 

christop wrote:
I'm assuming it's some form of PWM

Cant fool you!

 

christop wrote:
For a simple moving average, keep a ring buffer to hold old samples. Continuously read the input every millisecond or so (depends on how fast the pulse train runs), and if it's high, add 1 to a running sum; subtract the oldest sample in the ring buffer from the running sum. Drop the oldest sample from the ring buffer and add the new sample to the ring buffer (depending on how you implement the ring buffer, adding a new sample could automatically and simultaneously drop the oldest sample). Then divide the running sum by the size of the array. That's your average duty cycle.

Too much work.  But fancy for sure ;)

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Seems like you can just take a high speed timer irq (ex 50us, 20KHz) and count how many times the signal reads "hi" .  After every 8888 (or any number) measures, the ratio is then known for setting your DAC (just scale with an int mult and shift and send to dac).  Reset the count for the next round of measures.  Actually you'd prob use 20000 and not 8888, that's just to show it is independent of the sampling speed.   8888 would give an update every 8888/20000=0.444 seconds.  You'd play with the values to get both the update rate and resolution you want.   This would handle anything from zero% to full on 100%.

 

Of course you also know if the total is zero or 8888, then you are at 0% or 100%.  Also, you won't need any division to get the DAC value, other than a possible shift.

 

 

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

jgmdesign wrote:

Too much work.  But fancy for sure ;)

 

 

Exponential moving average is even easier (no ring buffer or anything). Read the input continuously (as with the simple moving average), and calculate the sum of the input multiplied by some small factor and the running average value multiplied by one minus that same factor, then set the running average to the result. The average is also the output. E.g., out = avg = in * x + avg * (1-x). (Use scaled integers or floats as appropriate.)

 

The downside with EMA is the output won't go to full 0% or 100% but will only asymptotically approach those two extremes--that's just the nature of exponential decay.

 

Edit to add: I like avrcandies solution too. It's like the simple moving average method but is just an average without the "moving". It's also not as continuous as a moving average though.

Last Edited: Wed. Aug 3, 2022 - 12:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

grohote wrote:
Detect no pulse, measure H or L, that is it.

 

THis seems to me the simplest idea.  Since PulseIn() returns a '0' when there is no 'trigger' then I can just put in a couple of IF>THEN's to sample teh pin on a digital read.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

 

Edit to add: I like avrcandies solution too. It's like the simple moving average method but is just an average without the "moving". It's also not as continuous as a moving average though.

It's essentially "batch  averaging", like most simple "gated" freq counters.  So that lets you pick the time span...if you want a smoother response, just pick a longer interval to totalize.  Downside is that the result update rate slows down. 

----------

The exp avg is really hard to beat when you need a quick simple avg.  You do have to watch with the finite bit arithmetic, since the fractional part gets tossed (or rounded) each cycle.  A trick is to keep the latest result at 4x or 8x and maintain (remember) these few extra fraction bits scooted into the whole portion.  So the true output result is this value shifted a few places to get rid of the xx scaling.

 

Here is one I threw together  with Ynew=  (7*Yold+Sample)/8 ...you can see it stalls out and never reaches 1000, only 997, due to finite numerics.  (15Yold+sample)/16  would be worse yet.  With an 8x result scaling you see a perfect 1000 is reached (perfect due to rounding).  some rows not shown

n

the yellow 8 is the 8x scaling factor---causes all values from column A (inputs) to be 8x larger

Detect no pulse, measure H or L, that is it.

Could that lead to a race condition?  EX: All low coming in for a long time...eventually returns as "no pulse". Thus decision made to check the level, of the "no pulse" but just around then a hi arrives and gets read...so now instead of looking like 0% , it falsely looks like 100%.

 

I had the thought you could take the original wave, RC filter & ADC it...then convert that value into the DAC value...sort of an odd roundabout way & ADC tolerance issues to boot!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. Aug 3, 2022 - 08:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
PulseIn() returns a '0' when there is no 'trigger'

 

Yes, but you should tell the function how long it will measure.

 

Reminds me of my first F-meter. Everything was OK, but how to measure few or no Hertz? I limited lower boundary to not have a nightmares or measure misery.

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

pulseIn() is implemented in arduino\hardware\arduino\avr\cores\arduino\wiring_pulse.c

unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
	// cache the port and bit of the pin in order to speed up the
	// pulse width measuring loop and achieve finer resolution.  calling
	// digitalRead() instead yields much coarser resolution.
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	uint8_t stateMask = (state ? bit : 0);

	// convert the timeout from microseconds to a number of times through
	// the initial loop; it takes approximately 16 clock cycles per iteration
	unsigned long maxloops = microsecondsToClockCycles(timeout)/16;

	unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops);

	// prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out
	if (width)
		return clockCyclesToMicroseconds(width * 16 + 16);
	else
		return 0;
}

which in turn seems mostly reliant on arduino\hardware\arduino\avr\cores\arduino\wiring_pulse.S:

/*
 * The following routine was generated by avr-gcc 4.8.3 with the following parameters
 * -gstabs -Wa,-ahlmsd=output.lst -dp -fverbose-asm -O2
 * on the original C function
 *
 * unsigned long pulseInSimpl(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops)
 * {
 *     unsigned long width = 0;
 *     // wait for any previous pulse to end
 *     while ((*port & bit) == stateMask)
 *         if (--maxloops == 0)
 *             return 0;
 *
 *     // wait for the pulse to start
 *     while ((*port & bit) != stateMask)
 *         if (--maxloops == 0)
 *             return 0;
 *
 *     // wait for the pulse to stop
 *     while ((*port & bit) == stateMask) {
 *         if (++width == maxloops)
 *             return 0;
 *     }
 *     return width;
 * }
 *
 * some compiler outputs were removed but the rest of the code is untouched
 */

#include <avr/io.h>

.section .text

.global countPulseASM

countPulseASM:
etc

(I didn't show the Asm as the C comment is perhaps more explanatory)

 

So the point is that "timeout" you pass is converted to "maxloops" and passed to the Asm and because no transition is detected it simply follows one of the "return 0" paths to indicate timeout rather than a width.

 

Presumably you can just digitalRead() the pin on receiving 0 to know whether it is fully high or fully low ?

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

it simply follows one of the "return 0" paths to indicate timeout rather than a width.

 

Presumably you can just digitalRead() the pin on receiving 0 [from pulse in] to know whether it is fully high or fully low ?

from #12, duplicated here:

Could that lead to a race condition?  EX: All low coming in for a long time...eventually returns as "no pulse". Thus decision made to check the level, of the "no pulse" but just around then a hi arrives and gets read...so now instead of looking like 0% , it falsely looks like 100%.

 

It seems like when it has finally declared & reported, no pulse, looking at the level right then can lead to a wrong conclusion.

If 0% & 100% cases are to be treated as equivalent, a wrong conclusion wouldn't matter---but then, the hi/lo follow on read would be redundant

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

Depend on how serious or important the result is.

 

When No-pulse is detected, it can start a supervision, assigning Interrupt to monitored pin, to catch the exact moment of 'back-to-pulse' state.

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

When you say 30Hz does that mean (when not only low or high) that one of the edges come every about 333 ms and then the other edge will move, and it's actually that placement you want measure, or is it the duty cycle? 

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

It’s a 30Hz square wave whose duty cycle varies between 0 and 100%.  End of description.

 

as I mentioned earlier I think some of you are making this more difficult than it needs to be.  Grohote and Cliff have the same idea I do, by using the timeout to check the pin.  If it transitions during that pin read that error is acceptable as the whole routine runs every two seconds, so it will ‘fix itself’ should the error occur.

 

I don’t have time today to try this out, but I will at some point.

 

thanks,

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:
a pulse train 30Hz

 

What you know about: is it a precise one, is it a Fast PWM or perhaps Phase Correct?

 

I am asking, because not only one Interrupt catching pulse restoration- it may be possible to improve all with all-time interrupt.

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

grohote wrote:
What you know about: is it a precise one, is it a Fast PWM or perhaps Phase Correct?

 

It doesnt matter. Again, y'all are making this into a ballistic missile project.

 

I'll try the pin read after timeout and report back

 

Thanks again

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

If it transitions during that pin read that error is acceptable as the whole routine runs every two seconds, so it will ‘fix itself’ should the error occur.

If the app can tolerate it being the far opposite voltage for 2 sec, then it is prob not critical.  It is not guaranteed to fix itself, though it's likely (the error could repeat). 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

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

avrcandies wrote:
If the app can tolerate it being the far opposite voltage for 2 sec, then it is prob not critical.

 

Ya think?

 

avrcandies wrote:
It is not guaranteed to fix itself, though it's likely (the error could repeat). 

 

The projects 'codename' is "the Sloth" as any transitions are not happening very quickly.  Should teh PWM go from 99% to 100%, its gonna stay that way for a while before any changes.  Same thing from 1% to 0% too.  There is also no chance that I would go from one extreme to the other instantly either.

 

Ok, I keep typing that I am done and will report back.  THis time I mean it.  It must be a really slow day for everyone to keep pounding this - LOL.  I asked for it I guess.....

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

It does matter, for a perfect solution.

 

This project is similar to Synchronize external 1Hz with own 1Hz osc (from Timer2). It is possible if the scanning is 32Hz.

With Fast PWM it can be easy, with Phase correct not at all. With unstable 30Hz definitely not.

 

You should be worried about Phase Correct, because in this case you may have 30Hz, 30Hz-Delta and 30Hz+Delta.

Thus, unsafe frequency. If the duty factor jumps too high, or low, you may be lost.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

OK, time to put this to bed and move on:

 

I ran this little test:

 ONCycle = pulseIn(PWM_IN, HIGH);
    if(ONCycle == 0)
    {
       temp = digitalRead(PWM_IN);
       if(temp == 1)
       {
        Serial.print("HIGH");
       }
    }
    OFFCycle = pulseIn(PWM_IN, LOW);
    if(OFFCycle == 0)
    {
       temp = digitalRead(PWM_IN);
       if(temp == 0)
       {
        Serial.print("LOW");
       }
    }

If there is a pulse train coming in between 1 and 99% the IF statements never go true and nothing on teh serial monitor is printed.  When I tie teh input high(100%), the serial monitor displays "HIGH", and when I tie the input to ground(0%), teh serial monitor displays "LOW"

 

This is what I was looking for.  Simple indication of 0% or 100%.  I can change my code to do what is needed during these conditions.

 

So, as far as the 'solution' goes:

 

grohote wrote:
Detect no pulse, measure H or L, that is it.

 

and

 

clawson wrote:
Presumably you can just digitalRead() the pin on receiving 0 to know whether it is fully high or fully low ?

 

So both grohote, and Cliff were on the spot so they both get kudos points.

 

Thanks all for the suggestions.

 

Topic closed

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:

 

It’s a 30Hz square wave whose duty cycle varies between 0 and 100%.  End of description.

...

 

If there is a pulse train coming in between 1 and 99% the IF statements never go true and nothing on teh serial monitor is printed.  When I tie teh input high(100%), the serial monitor displays "HIGH", and when I tie the input to ground(0%), teh serial monitor displays "LOW"

 

This is what I was looking for.  Simple indication of 0% or 100%.  I can change my code to do what is needed during these conditions.

 

The link in your #1 says this 

pulseIn(pin, value, timeout) 

Parameters
pin: the number of the Arduino pin on which you want to read the pulse. Allowed data types: int.
value: type of pulse to read: either HIGH or LOW. Allowed data types: int.
timeout (optional): the number of microseconds to wait for the pulse to start; default is one second. Allowed data types: unsigned long.

 

If you add the timeout parameter, your design can become a lot more responsive than that default 1 second, and it is a more general solution. 

 

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

jgmdesign wrote:
Topic closed

 

This is 'freaks.  The topic isn't closed until all of the skin is off the dead horse! laugh

Letting the smoke out since 1978

 

 

 

 

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

digitalDan wrote:

jgmdesign wrote:
Topic closed

 

This is 'freaks.  The topic isn't closed until all of the skin is off the dead horse! laugh


 

cannot argue that comment at all……..

 

jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

From your answer in #18

 

I will just say that what we know so far I would just have made a timer interrupt that run 2**n times faster that 30 Hz and then inc a counter each time the IO is low. and when reaching 2**n rool over there is a result, everything else would be to over complicate things.

 

And if n could be the same as n on the DAC there will be no calculations at all.

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

sparrow2 wrote:
a timer interrupt that run 2**n times faster that 30 Hz

 

ASSR, Timer2, 32kHz can do it.