Servo control using potentiometer for ATMega32

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

Please help me with the following code. It seems that when I start conversion using 1 << ADSC instruction, motor dosent respond. Otherwise when conversion is not started using same statement, instructions inside while{} are executed correctly. I further want to modify the program. Some statements are // framed during troubleshooting.

Hepl appreciated!!


#include
#include
#include

static volatile uint8_t low_value = 0;
static volatile uint16_t ten_bit_value = 0;
int servo_value;

int delay( void );

int main( void )
{	
	ADCSRA |= 1 << ADEN;
	ADCSRA |= 1 << ADIE;
	sei();
	ADCSRA |= 1 << ADPS2;
	ADMUX |= 1 << REFS0;
	
	TCCR1A |= 1 << COM1A1 | 1 << COM1A0 | 1 << WGM11;
	TCCR1B |= 1 << WGM13 | 1 << WGM12 | 1 << CS10;
	
	ICR1 = 19999;
	
	DDRD |= 1 << PIND5;
	ADCSRA |= 1 << ADSC;
	
	
	servo_value = 18059;
	
	while(1)
	{	
		OCR1A = 18059;
		delay();
		OCR1A = 19519;
		delay();
		OCR1A = 18500;
		delay();
		OCR1A = 19000;
		delay();
		
	}
}

int delay( void )
{	_delay_ms( 100 );		
	return 1;
}

ISR( ADC_vect )
{
	low_value = ADCL;
	ten_bit_value = ADCH << 8 | low_value;
	servo_value = (-1.427175 * ten_bit_value + 19519);
	ADCSRA |= 1 << ADSC;	
}

$ Fixed code tags - JS $

Attachment(s): 

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

Do you need to link in the floating point library, or does the compiler figure that out on its own?

Imagecraft compiler user

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

compiler will figure that out

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

Hi,
Declare

volatile int servo_value;

But usualy it is used

TCCR1A = (1<<COM1A1) | (1<<WGM11);
OCR1A = 1000 //left
OCR1A = 1500 //center
OCR1A = 2000 //right

and in isr you can count without float

ten_bit_value = ADC;
OCR1A = ten_bit_value + 1000;

Range 1000 - 2023 ms should be ok.

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

Quote:
compiler will figure that out
It will link to a floating point library, but it may not link to the one you really want. To do that, you might have to specifically tell it.

Regards,
Steve A.

The Board helps those that help themselves.

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

This code:

ISR( ADC_vect )
{
   low_value = ADCL;
   ten_bit_value = ADCH << 8 | low_value;
   servo_value = (-1.427175 * ten_bit_value + 19519);
   ADCSRA |= 1 << ADSC;   
} 

would be more efficient as:

ISR( ADC_vect )
{
   servo_value = (-1.427175 * ADC + 19519);
   ADCSRA |= 1 << ADSC;   
} 

even more so as:

ISR( ADC_vect )
{
   servo_value = (((10 * ADC) / 7) + 19519);
   ADCSRA |= 1 << ADSC;   
} 

(OK 10/7 is actually 1.428571 but it's close and with a bit of work you could find integers to replace the 7 and 10 that were a closer approximation to 1.427175)

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

#include
#include
#include

volatile int servo_value;

int delay( void );

int main( void )
{
ADCSRA |= 1 << ADEN;
ADCSRA |= 1 << ADIE;
sei();
ADCSRA |= 1 << ADPS2;
ADMUX |= 1 << REFS0;

TCCR1A |= 1 << COM1A1 | 1 << COM1A0 | 1 << WGM11;
TCCR1B |= 1 << WGM13 | 1 << WGM12 | 1 << CS10;

ICR1 = 19999;

DDRD |= 1 << PIND5;

servo_value = 18059;

ADCSRA |= 1 << ADSC;

while(1)
{
OCR1A = servo_value;
//delay();
//OCR1A = 19519;
//delay();
}
}

int delay( void )
{ _delay_ms( 100 );
return 1;
}

ISR( ADC_vect )
{
servo_value = (-1.427175 * ADC + 19519);

ADCSRA |= 1 << ADSC;
}

Thank you all of you!!
This is the revised code and working perfectly.
Can you please tell me where I was going wrong in first sample code?

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

Did you notice the additional bits added to the bottom of your first post?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I changed two things as compared to first program.
1. Instead of int servo_value, I declared it as volatile int servo_value.
2. ADC is directly used in ISR instead of ten_bit_value = ADCH << 8 | low_value;
Does any of these statements create difference??

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

Quote:
Can you please tell me where I was going wrong in first sample code?
Among others you calculated hard the value of "servo_value"
servo_value = (-1.427175 * ten_bit_value + 19519);

but then you used it nowhere.

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

Quote:
Does any of these statements create difference??
The use of volatile ensures that a variable used both inside and outside an ISR gets updated properly. Since in your current code servo_value is only used inside the ISR, volatile is not necessary. In your previous code it didn't matter at all since you were never using the value gotten from the ISR anyways.

The other difference is irrelevant except for possibly a slight difference in the speed that things are done (but the floating point math far overwhelms any other action in the ISR).

Regards,
Steve A.

The Board helps those that help themselves.

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

In first sample code, even when I tried to equate OCR1A and servo_value, it was not getting reflected on servo motor rotation; that is why for troubleshooting purpose I excluded OCR1A = servo_value statement.
Thank you all for help.

Can you also provide me with information for modifying servo motor for continuous rotation?

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

If you have Google, write there "servo continuous rotation" and click "Search".
I got 1 910 000 links.

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

You are right.
But I also want to know what makes it move continuously as I am not that much in electronics rather than their applications.

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

Replacing the pot inside the servo with resistor network make the servo run "forever" chasing the right value of the pot now replaced with resistors to fake a mid point setting of the pot.

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

Thank You!!