One Timer for more tasks?

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

I'm trying to use a one-timer to generate a PWM signal for two servos at OC1A and OC1B pins and to

use the same timer to calculate a distance with the HC-SR04 sensor. I can't do both things at the same time so I tried to turn of

registers witch sets up PWM for my servos and when I want to calculate a distance I'm setting up registers for distance(HC-SR04) after I'm finished

with the calculation of distance I just came back with servo configuration. I need to use a Timer1 because I need OC1A and OC1B for PWM and I also need a

ICP1(Input capture interrupt)pin for Ultra-sonic sensor. This is not the best solution but I don't have another idea.

The main question is how I'm supposed to share a Timer1 time between these two tasks?

 

Eather PWM and HC-SR04 work perfectly independently.

 

I'm using an Atmega32A MCU with 16MGHz Cristal

 

This is my code (function for calculated distance):

int soundSensor()
{
    long count;
    double distance; 
    
    servoConfig_stop(); //disable PWM registers
    
    TIMSK |= (1<<TOIE1);
    
    PORTA |= (1<<PINA0);
    _delay_ms(10);
    PORTA &= ~(1<<PINA0);
    
    TCNT1 = 0;
    TCCR1B |= (1<<ICES1) | (1<<CS10);
    TIFR |= (1<<ICF1);
    TIFR |= (TOV1);
    TimerOverFlow = 0;
    
    while((TIFR & (1 << ICF1)) == 0); //Rising edge..
    TCNT1 = 0;
    TCCR1B &= ~(1<<ICES1) | (1<<CS10);
    TIFR |= (1<<ICF1);
    TIFR |= (1<<TOV1);
    TimerOverFlow = 0;
    
    while((TIFR & (1<<ICF1)) == 0);//Falling edge...
    count = ICR1 + (65535 * TimerOverFlow);
    
    distance = (double)count / 932.6;
    
    TCNT1 = 0; // disable HC-SR04 registers
    TIMSK = 0;
    TCCR1B = 0;
    TIFR = 0;
    
    if (distance < 15)
    {
        servoInit();//enable servo PWM
        _deley_ms(200);
        return 1;
    }else{
        PORTA &= ~(1<<PINA1);
        servoInit();
        _deley_ms(200);
        return 0;
    }
    
}

 

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

danroxi wrote:
I can't do both things at the same time
Tell us more about that.

 

Of course a timer can do more than one thing. Inside the middle of your Windows or Linux there is a timer that is probably doing 500 to 1,000 different things - so getting an AVR timer to just do 2 or 3 is trivial.
 

The key to all this is to look at thigs that need "timing". Say you have something that has to happen every 3ms and something that has to happen every 8ms then you simply run a timer at 1ms and cout to 3 and do the 3ms work also count to 8 and do the 8ms work.

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

danroxi wrote:

servoInit();//enable servo PWM

The key to using one timer for multiple uses, is finding common ground between all the uses, this takes a bit of pre-planning after listing out all of the requirements.

Please post the code to the servo init function so we know how the timer is setup for pwm.

Generally servos want a 1ms to 2ms pulse to set position and a rep rate around 20ms.

What is the required resolution of your servos? 1deg, 10deg's, 0.1deg's / step?

What is the range of measurements for your echo ranger and what is the required resolution required over this range.

With this info, common ground may be found so the timer can do both without reconfiguration. 

In other words, what are your specifications for the servo's and ranging?

 

Jim

 

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!

 

Last Edited: Thu. Mar 11, 2021 - 04:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is my servo PWM configuration:

 

void servoTimer()
{
	ICR1 = 4999; //Set TOP count for timer1 in ICR1 register 
	
	
	// Set Fast PWM, TOP in ICR1, Clear OC1A/OC1B on compare match, clk/64
	TCCR1A |= (1<<COM1A1) | (1<<WGM11) | (1<<COM1B1);
	TCCR1B |= (1<<CS11) | (1<<CS10) | (1<<WGM12) | (1<<WGM13);
	
	
	OCR1A = 130; //Servos at -90 degree..
	OCR1B = 130;
}

 

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

 I also need a ICP1(Input capture interrupt)pin for Ultra-sonic sensor.

There are many ways to interface with and read an SR-04 module!

 

The ICP is clearly a great approach, and very straight foreward, when you have access to that I/O pin.

 

I recall using a slightly different approach when I re-used a small PCB that didn't make using the ICP pin practical.

The following approach worked fine, at least for that project.

 

Recall that one of the nice features about using a Timer/Counter for PWM is that once configured, you just update a PWM value  now and then, when you want to change the servo's position, and the hardware module does all of the real work.

That means that it takes incredibly little processing power to run the servos.

 

That's good as the following, non-ICP, approach uses a lot of processing power, (but hey, life is full of trade offs).

 

Recall that under typical conditions, (temperature, humidity, altidude, etc.), a sound wave travels one centimeter in about 29.2 uSec, (mircoseconds).

 

Therefore, another approach would be two use one or two of the M32's T/C's for driving the servos, and use one for the SR-04.

Configure the T/C to fire an interrupt once every 29.2 uSec.

Send a trigger pulse to the SR-04.

When the Echo signal goes high turn on the 29 uS ISR.

In the ISR just increment a counter and exit.

 

When the Exho signal goes low turn off the ISR (and hence turn off the counting).

 

The counter now tells you how many centimeters the Ping traveled, (out and back).

Divide it by two for the Range, (distance from the sensor to the target that reflected the signal).

 

If the counter reaches X counts then the Ping never came back, so there was no reflected signal, or it was out of range.

 

This approach will give you a Range reading with an accuracy of +/- 1 cm.

 

Recall that the SR-04 is an indredible little module, works well, and is very inexpensive.

But it isn't really designed for sub-centimeter accuracy anyways, so the above approach is usually reasonable for many simple applications.

 

If you go this route, then get it working without the PWM.

Once you understand your code,and have reliable, reproducible results, then add it into your project's code.

 

Averaging several Range readings is usually helpful.

 

Setting up a T/C's prescaler for an approximatley 29.2 uSec interrupt, and programming the T/C in CTC mode for this periodic interrupt, then become the key elements of this approach.

 

The "downside" of this approach is that there is a lot of processing overhead with using an ISR, to enter the ISR, run your code, and then exit the ISR.

The code has to save and restore a bunch of registers.

Firing the ISR at that rate, (pretty fast), therefore ties up a lot of processing power during the time that you are taking measurments.

(One could write the ISR in assembly to increment a counter and minimize the ISR overhead, but that is a lot of work and likely isn't needed for your project!)

 

That is why it is nice that the other T/C module, handing the servo ( s ), doesn't need much processing time.

 

Good luck with your project!

 

JC   

 

 

Last Edited: Thu. Mar 11, 2021 - 04:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

danroxi wrote:

servoInit();//enable servo PWM

 

What is the required resolution of your servos? 1deg, 10deg's, 0.1deg's / step?

What is the range of measurements for your echo ranger and what is the required resolution required over this range.

 

 

My servo needs to have ranged from -90deg +90deg with a 1deg/step.

But I'm using an HC-SR04 more for detecting a movement close to sensor.

 

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


Take a look at app note AVR136, to create two software PWM channels for your servo's, while freeing up ICR1 for your pulse length capture. 

You can find these on the documents page for your micro: https://www.microchip.com/wwwpro...

 

by using software for your PWM outputs, you can now use the timer as configured to also capture your echo timing too.

 

Jim

 

 

Keys to wealth:

Invest for cash flow, not capital gains!

Wealth is attracted, not chased! 

Income is proportional to how many you serve!