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

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.

Related

How can I have Variable Frequency PWM with STM32?

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.

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).

What is an analog Watchdog?

I Quote from Wikipedia:
A watchdog timer (WDT; sometimes called a computer operating properly or COP timer, or simply a watchdog) is an electronic timer that is used to detect and recover from computer malfunctions.
While using STM32F429I-Discovery, I came across a term [in "stm32f4xx.h"] which uses a register to disable Watchdog:
#define ADC_CR1_AWDIE ((uint32_t)0x00000040) //Analog Watchdog interrupt enable
Here, I am unable to understand Analog Watchdog
And if possible,
#define ADC_CR1_JAWDEN ((uint32_t)0x00400000) //Analog watchdog enable on injected channels
What is injected channel here?
A watchdog timer can be thought of as two separate circuits, a timer circuit and a watchdog circuit. The timer circuit merely counts the time that passes. The watchdog circuit actively monitors the timer to see if a certain amount of time has passed without being reset by software. If so, the software is no longer running and the watchdog typically performs an automated function such as resetting the processor. The watchdog needs only to be told at initialization how much time to monitor for and it handles the rest of its operation without additional software interaction.
An analog watchdog operates in a similar manner. Only instead of monitoring a timer, it monitors an analog input channel. At initialization, you tell the watchdog what analog thresholds to monitor for. If a converted value on an analog input passes one of these thresholds, it will fire an interrupt for you to process the signal sample. This means you don't have to write code to continuously poll the analog inputs and check their levels. It is all handled autonomously in the background by the analog watchdog circuitry.
An injected channel can just be thought of as a high priority conversion channel. If a regular analog input is in the middle of performing a conversion and a conversion is triggered (either by a timer or because it is programmed in continuous conversion mode) on an injected channel, the conversion on the regular channel will halt and wait while the injected channel is converted before completing its own conversion. This is useful if you have an analog input that must be responded to in a realtime manner.
Here is an application note (which, for some strange reason, doesn't seem to be available in ST's website) that give a few examples of the use of the various ADC features. And here is another explanation of the two features your question was about.
The term "watchdog" in this context refers to the fact that the ADC channel is continuously monitored.
In this context the term is not related to a processor operation watchdog - which monitors processor operation. Although you could use it for brown-out detection or power-supply failure detection if your power supply as a reservoir capacitor or battery back-up capable of keeping the processor up long enough after the supply side drops-out.
The analogue watchdog on STM32 is simply a means of generating an interrupt when some external voltage drops below or exceeds a programmable threshold level. This is done without software intervention when the ADC conversion s configured to free-run, so if the application only needs to respond to thresholds, this can be implemented with zero software overhead for ADC polling.
You might use the feature for example for carrier sense detection in an RF application by using it to monitor the RSSI signal from an FM demodulator. Or it might be used in a in a bang-bang controller, such as a boiler thermostat. The AWD has upper and lower thresholds so can be used to implement hysteresis, and you can modify the thresholds dynamically to generate multiple events on a curve for example.

Plot a graph of Time vs RSSI for a 433Mhz RF ASK Receiver

Hi Im using the following RF module
http://www.apogeekits.com/rf_receiver_module_rx433.htm
on an embedded board with the PIC16F628A. Sadly, I realized that the signal strength was in analog form and couldn't get any ideas to get the RSSI reading off the pin because well my PIC is digital DUH!.
My basic idea was
To get the RSSI value from my Receiver
Send it to the PIC
Link the PIC to a PC via RS232
Plot a graph of time vs RSSI of the receiver (so I can make out how close my TX is to my RX)
I thought it was bloody brilliant at first but ive hit a dead end here. Any ideas on getting the RSSI data to my PC from this receiver would be nice.
Thanks in Advance
You can get a PIC that has an integrated ADC for sampling the analog signal. Or, you can use an external ADC chip to do the conversion. You would connect that to your PIC using SPI or I2C.
The simplest thing to do is obviously to use a more appropriate microcontroller - one with an ADC! There are many (most), including PICs (though that wouldn't be my first choice).
Attaching an external SPI or I2C ADC might be a bit tedious since having no SPI or I2C on your part, you'd have to bit-bash it. If you do that, use an SPI part - its simpler. Your sample rate will suffer and may end-up being a bit jittery if you are not careful.
Another solution is to use a voltage controlled PWM, then use the timer input capture to time the pulse width. That will give you good regularity and potentially good resolution. You can get a chip (example) to do that, or grow your own. That last option requires a triangle wave input as well as the measured (control) voltage, but on the same site...
In a similar vein, you could use a low frequency VCO (example) and use the output to clock one of the timers, then using a second timer periodically sampling the first and reset it. The count will relate to the voltage, though not necessarily a linear relationship, linearisation could be none on the PIC or at the receiving PC - I'd go for the latter - your micro will suck at arithmetic (performance wise) - even integer arithmetic, especially if it involves division.

polling hardware button's state

I need to implement the following feature for my device running embedde linux on a 200mhz MIPS cpu:
1) if a reset button is pressed and held for less then a second - proceed with reboot
2) if a reset button is pressed and held for at least 3 sec. - restore the system's configuration with default values from NVRAM and then reboot.
I'm thinking of two ways:
1) a daemon that constantly polls the button's state with proper timings via GPIO ioctls
(likely too big overhead, lots of context switching ?)
2) simple char driver polling the button, measuring timings and reporting the state, for example, via /proc to user space where daemon or a shell script can check and do what's required.
And for both cases I have no idea how to measure the time :(
What would you suggest/recommend?
You have to implement those in hardware. The purpose of the "restore defaults from NVRAM" is to restore a so-called "bricked" device.
For example, what if an NVRAM seting is modified (cosmic ray?) such that the device cannot boot? In that case, your proposed button-polling daemon will never execute.
For the one-second held reboot, use an RC (resistor + capacitor) circuit to "debounce" the button press. Select an RC time constant which is appropriate for the one second delay. Use a comparator watching the RC voltage to signal the RESET pin on the MIPS cpu.
For the three-second press functionality (restore NVRAM defaults), you have to do something more complicated, probably.
One possibility is to put a tiny PIC microcontroller into the reset circuit, but only use a microcontroller with fuse (non-erasable) ROM, not NVRAM.
An easier possibility is to have a ROM containing defaults on the same circuit and bus as the NVRAM. A J/K flip-flop latch can become part of your reset circuitry. You'll also need a three-second-tuned RC circuit and comparator. On sub-three-second presses, the flip-flop should latch a 0 output and on three-second-plus presses, the 2nd RC circuit should trigger the comparator after 3 seconds and present a 1 to the J/K latch, which will toggle its output.
The flip-flop output Q will store the single bit telling your circuit whether this reset cycle was subsequent to a three-second push. If so, that output Q is driving the chip select to the NVRAM and Q* is driving the chip select to ROM. (I assume chip select is negative logic on both NVRAM and ROM chips.)
Then when your CPU boots, it will fetch the settings from either the NVRAM or the ROM, depending on the chip select line.
Your boot code can detect that it booted with ROM chip select, and can later reset the J/K flip-flop with a GPIO line. Then the CPU will be able to write good values back into the NVRAM. That unbricks the device, hopefully.
You want to use ROM that is not erasable or reusable. That kind of ROM is the most resistant to static electricity, power supply trouble, and radiation. Radiation is much more present than we generally realize, and the amount of cosmic ray flux is multiplied by taking a device onboard an airliner, for example.
I am not familiar with the MIPS processor and the GPIO/interrupt capabilities of the pin that you could be using but a possible methodology could be as follows.
Configure the input pin as an interrupt input.
When the interrupt fires disable the interrupt and start a short 100ms-ish timer
When the timer triggers check that the button is still pressed (for debounce). If it is not then re-enable the GPIO interrupt and restart, otherwise set the timer to re-trigger after the 3 second timeout.
When the timer triggers this time then if the button is not pressed then do your reboot otherwise reset the system configuration and reboot.
If the pin cannot provide an interrupt then step 1 will be a polling task to look at the input.
The time between the reset button being pressed and the full reset process being run will always be 3 seconds from a debounced button press. In a reset situation this may not be important particularly if as part of step 3 you make it apparent to the user that a reset sequence has started - blank the display for example.
If you want to do this in software, you need to put this in kernel (interrupt) code, rather than in a shell script or daemon. The better approach would be to put this in hardware.
In my experience, the likely reason for resetting the device will be bad user code which has locked or bricked the processor. If the issue is a corruption of memory due to RF energy or something of that nature, you may require hardware or an external (hardened) processor to reflash the device and fix the problem.
In the bad-user-code case, processor interrupts and kernel code should continue to run, while user code may be completely stalled. If you can poll the pin from an interrupt, you stand a much better chance of actually getting the reset you expect. Also, this enables you to do event-driven programming, rather than constantly polling the pin.
One other approach (not to the specs you listed, but a popular method for achieving the same goal) would be to have the startup routines check a GPIO line, and hold a button down when you want to re-initialize the device. On most embedded Linux devices which I've seen, the "Reset" button is wired to a dedicated reset pin on the microcontroller, and not to a GPIO pin. You may have to go with this route, unless you want to start cutting traces.