Generating output with 20% duty cycle using only one counter - microcontroller

If i have micro with no PWM module , how to generate output of duty cycle (20%) on pin 1 , and output with duty cycle(80) on pin2
using one counter and interrupt not polling.

Configure a timer to interrupt periodically. The timer period should be 1/100th (or 1/10th or 1/5th) of the desired signal period. Increment a counter in the timer interrupt handler. Reset the counter value to zero when the counter reaches the maximum value of 100 (or 10 or 5). Toggle the appropriate pins when the counter value reaches 20% or 80% of the max counter value. And toggle the pins when the counter value resets to 0.

If you've got an AVR, and you can pick the pins, you can get this behavior with no interrupts. You just need to configure one of the timers to use the count-up and clear timer on compare mode. You get to set which register is the clear timer on compare, and what the Waveform generation mode is for the COMPA and COMPB registers. I recommend using the ICR as the timebase (clear on compare register) and then using the two COMP registers to generate the waveforms, by setting the WGM bits to clear the output on reset and set the output on compare match. You can then set the COMPn registers to whatever fraction of the ICR register to achieve whatever duty cycle you want, on the OCxn pins.

Related

Analog digital conversion with AD7091 on SPI

I am trying to use AD7091R-8 ADC chip with SPI.
Procedure for getting converted value is described inside Datasheet and says:
Reset chip
Bring CONVST line low for 600ns and then get it high.
For enabled channels inside Channels register (I have enabled last 3 chans) start clocking out data which is contained in 2 bytes.
So I bring CONVST line for 1ms then up and wait for 1 ms and start clocking out data by enabling CS then clocking 16bytes and then bring CS up.
In those 16bits that clocks out I should get inside first 3 bit channel id and I got it but only the first one. Other 2 frames are without channel id which gives assumption that something got bad.
Does chip after starting CONVST and clocking out data autoincrements ADC results or somehow ADC channel result should be addresed?
Could someone please give hint on how should data be retrived from this ADC after doing CONVST?
If you look at the diagram on page 36 of the datasheet (Channel sequencer), you will find your answer.
You need to do the following sequence:
Toggle CONVST
Tie CS low, write the channel register on SDI, ignore SDO, Tie CS high
Then for each channel that you want to read:
Toggle CONVST
Tie CS low, read operation of NOP regiter on SDI, next channel on SDO, Tie CS high

Interrupt arduino when a particular value is read by a ultrasonic range finder

I'm new to arduino and currently using Arduino Uno. I need to interrupt arduino when a specific value is read by ultrasonic range finder. Since i'm entirely new to this i dont know anything on interrupts in arduino, I'm expecting a clear answer.
I assume that you are using SC-RS04 module, because that is what Arduino hobbyst usually use.
Acccording to the datasheet, the distance is encoded in the duration of an echo pulse Arduino will recive from the module.
To calculate the width of the pulse you will need to set up two interrupts.
One is RISING interrupt for catching the start of the pulse. The interrupt handler will use the millis function to record the time of the start of the pulse.
The other is FALLING interrupt for recording the end of the pulse. This interrupt handler will use millis function and previously recorded time to calculate the durantion and from that duration it will calculate the distance. If the distance is below a specific threshold, it will call your logic.
Read here about setting up interrupts.

Does Arduino's clock (millis) continue counting in the background during interrupts?

I have a quick question which apparently isn't said online from what I've read: I know millis() on an Arduino doesn't change during a custom interrupt, but does the associated timer still counts in the background?
My program is time-sensitive and I would like to know if I should increase its value (how?) each time one of my interrupts is handled so that the main program's clock doesn't drift.
Thanks in advance,
Regards,
Mister Mystère
The CPU-internal timer will count even when interrupts are disabled. BUT when the timer overflows an interrupt is generated which will increment some counter in the library. If that interrupt is blocked for a long time ... then you will have a drift.
The CPU timer is hardware and not affected by any interrupt flags. Once it overflows the overflow bit is set / an interrupt is triggered. If interrupts are blocked at that time this interrupt will be queued. The queue size is 1, that is your must allow interrupts before the next interrupt is triggered. Since the timer overflows roughly once per millisecond you will need to ensure that you never block interrupts for longer than ~1ms.
Anyway you will have a drift since the Arduino's clock is not that precise at all. See my experiment on crystal deviations.

Interrupt works too fast on the Arduino

I know this sounds a bit funny :). But I am trying to eliminate possibilities:
On the Arduino Uno I have attached an interrupt triggered on HIGH to a routine which only increments a volatile defined long counter. This counter is displayed on an LCD screen.
If I connect a pulse generator with a frequency of 1 Hz at TTL levels, I would expect the counter to increase with about 1 per second. However this is not the case.
As the frequency is 1 Hz (duty cycle 50%) could it be possible that once the counter is incremented the IRS is exited (and clears the interrupt flag) BUT: the INT0 level is still HIGH so the ISR would be called again? At 1 Hz 50% duty, the HIGH would stay for 500 ms and at 16 mHz...
The processor at the heart of any Arduino has two different kinds of interrupts: “external”, and “pin change”. There are only two external interrupt pins on the ATmega168/328 (ie, in the Arduino Uno/Nano/Duemilanove), INT0 and INT1, and they are mapped to Arduino pins 2 and 3. These interrupts can be set to trigger on RISING or FALLING signal edges, or on low level. The triggers are interpreted by hardware, and the interrupt is very fast. The Arduino Mega has a few more external interrupt pins available.
So as commented: It triggers on an edge!
See more details on the Arduino Playground web page.
Two electrical reasons can explain why interrupt does not function as you need.
1- The pulse generator output and MCU input can have an impedance mismatch, which can cause ringing on the waveform edges. For example, if your function generator has a 50 ohm output capable of generating high frequencies you might see a problem driving a high impedance input like the Arduino at low frequency.
The name "pulse generator" makes me think this is a 50 ohm out device intended to make very short pulses with sharp edges. In such a case, you add a terminating resistor at the destination (load) to match the impedance of the source (pulse generator). For a 50 ohm output, 47 ohm would be close enough. If the output is 100 kohm, then place a matching resistor at the Arduino.
2- Just the opposite, the generator waveform edges may be so slow that the voltage passes through TTL 0 to 1 transition multiple times. If you have noise on your signal input, a slow edge could be causing multiple triggers. For example, if you are picking up some 60 Hz ripple from a power supply and grounding issues, your square wave edges won't be as square as you think.
In such cases hysteresis is a solution. There are many ways to de-glitch (debounce) in code. There is no answer that is right for all problems. A simple example would be that the ISR you require that the input reads high twice in a row for the edge to be accepted.

capture the incoming signal

i'm using msp430f2013 micro controller in my project.. in that i need to calculate the incoming train of pulse signal frequency.... i don't know how to do it.... can anyone help me in this.. example code is more usefull to me.... advance thanks for
You need to read the manual for the micro-controller, then work out how to set up a timer which can measure the interval between two pulse edges (e.g. from one leading edge to the next). The frequency, f, will be the reciprocal of this time interval, t, i.e.
f = 1 / t
There are various ways to do this, perhaps the simplest to understand is to setup a timer as a simple counter. Poll the input pin, when it changes state save the count on the timer, when it changes state again save the count on the timer, subtract one time from the other and that is how many clock ticks of some frequency X ticks per second. your difference is y ticks per input pulse. y / x the ticks cancel out and you get seconds per pulse. If you are measuring a full period rising edge to rising edge or falling edge to falling edge then it is the same solution the difference is which timer samples to subtract (last rising edge and current rising edge for example).
Some microcontrollers have the ability to interrupt when there is a state change on the input pin (or at least the same edge, rising or falling), and you may prefer to use that method to sample the timer, subtract and get ticks per period, etc to get cycles per second (frequency).
Using a timer can be tricky, I always start by using the timer to blink an led, first once per second to get in the ball park, then once every 5 or 10 or 30 seconds, and compare that to a second hand on a watch or some other reference to verify that you are accurate and not a dozen percent off this way or that. That establishes understanding of the timer and its divisor, from there you can start to work on using it to measure the input. to make sure I have the gpio programmed right (the led exercise covers some of that already) I sample the input pin and change the led state with the input pin state and can often then look at the led to see blinks or a dull glow to see that I am able to sample the gpio pin. then put it all together and sample the timer when the input changes state, first polling then if need be interrupts or other.

Resources