How can I have Variable Frequency PWM with STM32? - variables

I am working on an LLC converter project. So I need PWM signals with variable frequency. I mean I need too change frequency real time. For example frequency modulation 40kHZ-80kHZ. Can anyone give me an idea? Which timer mode I have to use ? Thanks..

Its a little tricky to answer your question when you dont state the exact hardware you're working with. Seeing your tags i will assume its a member of the the STM32 family.
STM standard timers have registers you usually dont need to interface directly. Hal does that for you. However as far as i am aware Hal does not support such functionalities. The standard STM32 Timer has a TIMx_ARR and a TIMx_CCRn register. These hold some of the configuration necessary for PWM generation. You should be able to change your frequency by adjusting the ARR register and the Duty-Cycle by adjusting the CCRn register.
Be carful with that approach tho as it usually has no inbuilt protection. You will not damage your device but it is very easy to produce unintended behavior.
You also need to consider the prescaler values and the general configuration of your timer.
For detailed information refer to the Chapter: GPTIM in the reference Manual of your device as i can not give you a more detailed description with the little information you have provided.

As far as I understood from your question and follow-up comments, you want a constant duty cycle (~50%), but you want variable fequency, as well as phase shift. That is totally doable, and you can change the values on the fly, but for the phase shift, I would suggest using two timers. One master, one slave.
Idea:
Master slave controls the phase shift. The period of master slave is equal to the period of the final waveform. It goes from 0 to its ARR, and at some point there is the phase shift value in Compare register, which flips the output of master from LOW to HIGH on its way from 0 to ARR.
The slave is activated by master output change from LOW to HIGH, runs for one period, which is equal to the period of the master (ARR). It outputs PWM to some pin. Once it reaches ARR, it stops (only for master to start it again). Obviously, you need to adjust Compare register for PWM output to keep the duty cycle constant.
I made some crude illustration of what I mean, because discussing timers with text only can be a little (very) tricky. Paint skills 10/10:
How to adjust stuff:
Adjust frequency (period length) by changing ARR of both timers (it's always the same), if you want to keep duty cycle, you will need to immediately adjust compare value to ARR/2 (for ~50% duty cycle) of the slave timer. Make sure the compare value of the phase shifter master is below the ARR if you reduce ARR, otherwise the slave will never get triggered.
Adjust phase shift by changing compare value of the master timer between 0 and ARR.
Additional notes:
The master timer is configured to have TRGO (trigger output, master feature) on switch from LOW to HIGH of "compare".
The slave timer is in one pulse mode (OPM), meaning it disables itself after a single period. It will be reactivated by the next master's phase shift pulse (compare HIGH).
The master's signal is supposed to do reset and activation of the timer (resets CNT) (there is a list of modes - what TRGI trigger input does to the slave timer). Resetting the timer will load new values into ARR (see next point).
Both master and slave have ARR buffer enabled. This will allow you to change ARR values, but the changes take effect only when the current cycle ends. This will prevent jitter while changing period length and/or phase shift.
The slave timer is in PWM1 or PWM2 mode, depending on whether you want the first part of the output aveform to be LOW or HIGH, that's all the difference.
Helpful example from me:
I have written an implementation of master/slave timers with them activating each other differently purely on registers and with every line of code commented. I was a little new to it all (which shows in the structure of the project), it was literally my first experiment with timers after studying the timers in the reference manual for days, but I tried my best. I have a description of what I do in main.c. You may find it helpful. Note that the timers with the same numbers are similar or even identical across various STM32 devices, so my code is likely portable down to copy-paste into your code (which I'm totally OK with if you or anyone does it). Here is a link to main.c on my GitHub. I also have oscilloscope screenshots there.

Related

ATMEGA88PA Timet 1 Fast PWM Issue

I'm working on a project for a customer in which we're using the chip mentioned in the title. The chip works as a fan motor driver, setting a duty cycle in accordance to a required tach count. One channel is utilizing timer 0 while another is utilizing timer 1. The fan driver on timer 0, which is set up on fast PWM mode, works perfectly every time in accordance to the required duty cycle. On channel 1 the fan driver looks like it works almost all the time, but sometimes it fails in strange occurrences, this is set up in fast PWM mode as well. When it does fail, the PWM output pin can only be set to zero percent duty cycle or 100 percent (or rather just on and off) and will not take in values between that (utilizing the ICR register to set the frequency, so
ICR=MAIN_CLOCK_CPU/required_frequency
and OCR1A to set the duty cycle
OCR1A=(required_duty*ICR)/100)
). I have yet to have this fail on my bench top setup, but if I take the PCB out of the product back to my desk, reprogram it and then place it back in the product, it fails consistently (but the PCB will still work fine at my desk?).
The main clock frequency is set to 8MHz and the MCU is being powered by 3.3V. According to the data sheet, this is fine, and we shouldn't expect any strange behavior. I feel like I have exhausted all of my options as besides sometimes when the controller boots up it gets in this state, but it is not consistent. I'm just curious if others have experienced this issue before.
I feel like this can't be a firmware issue, due to the inconsistency I am seeing, but I'm not sure how the hardware could just simply not output a proper signal?

TinyAVR 0-Series: Can I use pin-change sensing without entering interrupt handler?

I am evaluating the ATtiny806 running at 20MHz to build a cycle-accurate Intel 4004 microprocessor emulator. (I know it will be a bit too slow, but AVRs have a huge community.)
I need to synchronize to the external, two-phase non-overlapping clocks. These are not fast clocks (the original 4004 ran at 750kHz)
but if I spin-wait for every clock edge, I risk wasting most of my time budget.
The TinyAVR 0-series has a very nice pin-change interrupt facility that can be configured to trigger only on rising edges.
But, an interrupt routine round-trip is 8 cycles (3 in, 5 out).
My question is:
Can I leverage the pin-change sensing mechanism while never visiting an ISR?
(Other processor families let you poll for interruptible conditions without enabling interrupts from that peripheral). Can polling be done with a tight skip-on-bit/jump-back loop, followed by a set-bit instruction?
Straightforward way
You can always just poll on the level of the GPIO pin using the single cycle skip if bit set/clear instruction on the appropriate PORT register and bit.
But as you mention, polling does burn cycles so I'm not sure exactly what you want here - either a poll (that burns cycles but has low latency) or an interrupt (that has higher latency but allows processing to continue until the condition is true).
Note that if things get really tight and you are looking for, say, power savings by sleeping between clock signal transitions then you can do tricks like having an ISR that nevers returns (saving the IRET cycles) but that requires some careful coding probably with something like a state machine.
INTFLAG way
Alternately, if you want to use the internal pin state machine logic and you can live without interrupts, then you can use the INTFLAGS flags to check for the pin change configured in the ISC bits of the PINxCTRL register. As long as global interrupts are not enabled in SREG then you can spin poll on the appropriate INTFLAG bit to check/wait for the desired condition, and then write a 1 to that bit to clear the flag.
Note that if you want to make this fast, you will probably want to map the appropriate PORT to a VPORT since the VPORT registers are in I/O Memory. This lets you use SBIS to test the INTFLAG bit a single cycle and SBI to clear the bit in a single cycle (these instructions only work on IO memory and the normal PORT registers are not in IO Memory).
Finally one more complication, if you need to leave the interrupts on when doing this, it is probably possible by hacking the interrupt priority registers. You'd set the pin change to be on level 0, and then make sure the interrupts you care about are level 1 or higher, and then trick the interrupt controller into thinking that there is already a level 0 running so these interrupts do not actually fire. There are also other restrictions to this strategy so avoid it if at all possible.
Programmable logic way
If you want to get really esoteric, it is likely possible that you could route the input value of a pin to a configurable custom logic LUT in the chip and then route the output of that module to a bit that you test using a 1-cycle bit test (maybe an unused IO Pin). To do this, you'd feedback the output of the LUT back into one of its inputs and then use the LUT to create a strobe on the edge you are looking for. This is very complex, and also since the strobe has no acknowledgement that if the signal changes when you are not looking for it (in a spin check) then it will be lost and you will have to wait for the next edge (probably fatal in your application).

How to deep sleep an Attiny until an analog value of a photoresistor changes?

for a battery powered project I would like to put an Attiny85 into deep sleep mode immediately after program start and let it wake up only when a sensor value (in this case a photo resistor) changes. Unfortunately I could only find examples for interrupts by a button and not for photo resistors in the internet. Does anyone have an idea how I could implement it, or if it is impossible?
Turn out that this is probably a software question.
Probably to lowest power and simplest way to implement this would be to...
Connect the analog sensor value to any one of the analog input pins on the ATTINY.
Make sure you disable the digital buffer on that pin.
Set up the ADC to point to the pin and set other relevant values like precaller.
Set up a watchdog timer to fire a periodic interrupt.
Go into deep sleep and wait for the watchdog timer to fire.
Each time the watchdog fires...
Enable the the ADC.
Take a sample.
Jump to main code if the value has changed more than your threshold.
Disable ADC.
Go back to deep sleep.
How power efficient this will be really depends on how often the timer interrupt fires - the less often the better. If your application can live with only checking the sensor, say, once per second then I bet power usage will be single digits of microamps or less.
If you really need very low latency when that sensor values changes, then you could instead use the build in analog comparitor...
.. to generate an interrupt when the input voltage goes above or below a threshold value, but this will likely use much more power since just the analog comparitor itself uses ~30ua while on, and you will also need to generate the voltage that you are comparing to either with the internal 1.1 voltage reference or an external resistor bridge or buffer capacitor.

What does post-layout simulation take a long time?

I am wondering why post-layout simulations for digital designs take a long time?
Why can't software just figure out a chip's timing and model the behavior with a program that creates delays with sleep() or something? My guess is that sleep() isn't accurate enough to model hardware, but I'm not sure.
So, what is it actually doing that takes so long?
Thanks!
Post layout simulations (in fact - anything post synthesis) will be simulating gates rather than RTL, and there's a lot of gates.
I think you've got your understanding of how a simulator works a little confused. I say that because a call like sleep() is related to waiting for time as measured by the clock on the wall, not the simulator time counter. Simulator time advances however quickly the simulator runs.
A simulator is a loop that evaluates the system state. Each iteration of the loop is a 'time slice' e.g. what the state of the system is at time 100ns. It only advances from one time slice to the next when all the signals in it have reached a steady state.
In an RTL or untimed gate simulation, most evaluation of signals happens in 'zero time', which is to say that the effect of evaluating an assignment happens in the same time slice. The one exception tends to be the clock, which is defined to change at a certain time and it causes registers to fire, which causes them to change their output, which causes processes, modules, assignments which have inputs from registers to re-evaluate, which causes other signals to change, which causes other processes to re-evaluate, etc, etc, etc.... until everything has settled down, and we can move to the next clock edge.
In a post layout simulation, with back-annotated timing, every gate in the system has a time from input to output associated with it. This means nothing happens in 'zero time' any more. The simulator now has put the effect of every assignment on a list saying 'signal b will change to 1 at time 102.35ns'. Every gate has different timing. Every input on every gate will have different timing to the output. This means that a back-annotated simulation has to evaluate lots and lots of time slices as signals are changing state at lot's of different times. Not just when the clock changes. There probably isn't much happening in each slice, but there's lots of them.
...and I've only talked about adding gate timing. Add wire timing and things get even more complex.
Basically there's a whole lot more to worry about, and so the sims get slower.

Measure Duty Cycle of PWM input with PIC?

I am trying to write a program for a PIC24F mcu that can measure the duty cycle of a pulse width modulated input signal. Has anyone done this? What would be the best approach?
It may depend on exactly which PIC24 part you are using, but some and possibly all PIC24 parts include timer hardware with input capture capability (check your part's data sheet). When configured for input capture, this will copy the timer counter value to a register in an input transition, and then generate an interrupt. Typically, in the interrupt handler, you would copy the input capture register and set the input capture up for the next transition, once you have the first three transitions, you can calculate the duty-cycle, and thereafter update it on every transition, or with perhaps a little less complexity every other transition.
There is a simpler possibility for this problem if you have:
a spare ADC which suits your meassurement precision requirements
room/money for this circuit (there might be simpler ones)
Then just meassure the output voltage which is linearly dependent on your duty cycle.