B4R Question Microseconds Timer needed AVR

ThorstenStueker

Member
Licensed User
Hi there, I need a way to have a precise microseconds timer in B4r, how can I do that. Simply I have to produce a precise frequency with a precise Dutycycle. Normaly I would say I can handle that with PWM but I didn't found a way. Thank you for answering!
 

emexes

Well-Known Member
Licensed User
I have to produce a precise frequency with a precise Dutycycle.
For what purpose? Sounds like driving servos, for which the frequency doesn't have to be precise.

Also, which AVR microcontroller? Different models have different timer hardware.
 

ThorstenStueker

Member
Licensed User
Okay, if I write precise I need precise, you may belave me that I know what I am writing about. The frequencies are variable starting at 0,1 Hz and ending at 10000 Hz. So in this Range I have to generate the frequencies. Interesting would be if it would be possible to use the System timers of the MCU for this (i.e. ATMEGA328PB wich is supportet by Arduino ISE). I this would be possible I would be able to setup this with Inline C to generate my Output. But I need to know if this would be possible.
 

ThorstenStueker

Member
Licensed User
🐻 Sorry I am really in stress, I could write more friendly.....I need the frequencies and it is not for a motor. Let me change this cause nobody deserves an answer like this. Sorry for that!
 

emexes

Well-Known Member
Licensed User
The frequencies are variable starting at 0,1 Hz and ending at 10000 Hz.
That is a pretty wide range ie 100000:1 which won't be directly possible with 16-bit (65535:1) timers. But you could split it into two ranges, say 0.1 to 32 Hz and 32 Hz to 10,000 Hz, and so if we deal with the lower range first:

It looks like there are three identical 16-bit timer/capture/compare modules, called TC1, TC3 and TC4. Let's use TC3.

I don't know what the timer clock frequency is exactly - it depends on the system clock crystal frequency - but usually it's around 1 MHz. For the lower range, we'd prescale that by 256, which would be a timer clock of 3906.25 Hz, and the timer would count from 0 to 65535 in a bit over 16 seconds, which is comfortably longer than your 0.1 Hz minimum frequency period of 10 seconds.

Each module has two compare values, which can be used to alter a compare output (your frequency output) when the timer equals a set value. One of the compare values can also reset the timer back to zero.

So what you'd do if you wanted say 7 Hz with a 37% duty cycle is:

first calculate the total period count = 3906.25 Hz timer clock / 7 Hz = 558.035714 = 558 timer ticks (so our actual output frequency would be 7.000448 Hz)

then calculate the high period count = 558 ticks x 37% = 206.46 = 206 timer ticks (thus our actual duty cycle would be 36.917563%, ie maximum relative error of 0.5 / 558)

and then you'd set OCR3A to 558, to set the output high *and* reset TC3 to 0 when it reaches 558,

and set OCR3B to 206, to set the output low after it has been high for 206 ticks (timer counts 0 to 205)

I might have the highs and lows the wrong way around, but I'll leave the fine polishing for you ✌ the general plan is good 🍻

For output frequencies in the higher range (32 Hz to 10000 Hz) you'd change the prescaler from 1/256 to 1/1 so that the timer clock is now 1000000 Hz instead of 3906.25 Hz, and calculate the total and high period counts accordingly.

You should only need to do those calculations when you want to change the frequency or duty cycle. And if you are only changing the duty cycle, you don't need to recalculate total period count... bonus! Once you've got the timer set up, it'll generate your signal continuously all by itself, while your program can go off and do its own thing. I'm pretty sure it'll work without needing an interrupt handler to update anything.

You could probably split your output range into three bands, and use three prescalers 1/256, 1/16 and 1/1, to give you better frequency and duty cycle resolution. Higher period counts = better resolution.
 
Last edited:

ThorstenStueker

Member
Licensed User
That means all timers except timer 0 are working? I thought that this will not run. If so there is a way cause I can calculate the timer prescaler and the ocra value. There is a problem with the 16 bit timers I have to split 16bit ocr value in 2 Bytes (high and low) ich I understood correct. Then I would be able to write the Software. But can I use the timer Interrupts within using B4R? If this would run I would be really, really happy with this cause I can write the timers in inline C (#if c) and set my variables as objects so thet I can send them to the cpu. But what is when CPU is doing a timer interrupt with my B4R Code
 

emexes

Well-Known Member
Licensed User
That means all timers except timer 0 are working?
There are three 16-bit timers, and I would be surprised if the operating environment used all three of them, and did not leave any free for application use.

I thought that this will not run.
This is a pessimism-free forum. 🍻

If so there is a way cause I can calculate the timer prescaler and the ocra value.
I agree. The calculations are straightforward, although you might want to consider doing them with integer arithmetic rather than floating-point.

There is a problem with the 16 bit timers
No. No problem. Refer pessimism note above. 🍻

I have to split 16bit ocr value in 2 Bytes (high and low) ich I understood correct.
Section 19.3 "Accessing 16-bit Timer/Counter Registers" on page 159 of the datasheet is one step ahead of you.

edit: also this document AN_1493 - AVR072: Accessing 16-bit I/O Registers 👍
edit: although this seems to be about what to do if the I/O Register might *also* be changed from within an interrupt handler 🤔 which is not us

But can I use the timer Interrupts within using B4R?
The whole beauty of using the timer compare output and reset features is that timer interrupts are not required. Interrupts = heartache. Avoid if possible.

If this would run
I agree it is still an "if" until we see it working. I have done this on another microcontroller with similar timer capabilities; here I am working off the datasheet, and trusting that the designers are designing hardware to help their customers (eg you and me) solve common problems (eg generating PWM signal).

I would be really, really happy with this
👍 you and me both

cause I can write the timers in inline C (#if c)
or, because we're just setting registers, no interrupts required, I would expect B4X code to be similarly basic

and set my variables as objects so thet I can send them to the cpu.
No idea what this means. Setting up the timer should just be a case of setting registers to values. Adding objects sounds like over-complication to me.

But what is when CPU is doing a timer interrupt with my B4R Code
No idea what this means. No interrupts required to generate this frequency signal - the resetting of the timer count by OCRxA compare does the job for us. Section 19.9.2 "Clear Timer on Compare Match (CTC) Mode" on page 168 of the datasheet describes this heartache-reducing feature.
 
Last edited:

emexes

Well-Known Member
Licensed User
Step one would be to just get a timer emitting a repetitive signal, in the Arduino environment if you are comfortable with C. This code is probably less than ten lines of timer configuration register assignments, and I expect there are Application Notes with sample code.

Then get the high and total periods correct, for three randomly-chosen frequency+duty-cycle test target signals, ie know the timer input clock frequency (1 MHz? 4.096 MHz? 0.921600 MHz?) and output polarity, Note that it doesn't matter whether our 0..n tick wave cycle is high-then-low or low-then-high, as long as we know which way around it is so that we know whether to set OCRxB to be number-of-ticks-high or number-of-ticks-low.

Then move that code to B4X. Then add the calculations to convert frequency and duty cycle to high and total period. Then introduce the prescalar to handle lower frequencies.

What could possibly go wrong? 🍻
 
Last edited:

emexes

Well-Known Member
Licensed User
Last edited:
Top