PIC12F683 + Turnigy TG9

Мне необходимо было управлять сервомашинкой Turnigy TG9.
В качестве языка программирования был выбран Hi-Tech PICC v9.81, программатор PicKit2, микроконтроллер PIC12F683.

Вот так выглядит сервомашинка, которой нужно было управлять.
Turnigy TG9

Схема данного устройства проста:

Микроконтроллер работает от внутреннего тактового генератора и включена внутренняя подтяжка ресета.

Когда поворачивается ручка потенциометра на определенный угол, то и сервомашинка поворачивается так же. Также абсолютно не важно положение рукоятки сервомашинки в момент подачи питания, она станет в положение указанное потенциометром.
Код программы максимально прост и понятен, все значения инициализации взяты из даташита на контроллер. Импульсы для сервомашинки Turnigy TG9 подобраны опытным путем.

Для получения временных задержек были написаны функции аппаратной(с использованием таймера) и программной задержки.

void SoftDelayUs(unsigned int time){
	do {
		asm("nop");
	} while(--time);
}

void SoftDelayMs(unsigned int time){
	do {
		SoftDelayUs(996);
	} while(--time);
}

void Timer1Init(void){
	T1CON = 0b10000100;
}

void DelayUs(unsigned int time){
	unsigned int TMR1;
	TMR1=0x0000FFFF - time;	

	TMR1IF=0;

	TMR1L=TMR1;
	TMR1H=TMR1>>8;
	
	TMR1ON=1;
	while(TMR1IF!=1){}
	TMR1ON=0;
}

void DelayMs(unsigned int time){
	do {
		DelayUs(1000);
	} while(--time);
}


Функция DelayUs(unsigned int time) получает значение на которое должен задержаться таймер, так как таймер инкрементирующий то это значение нужно отнимать от максимального значения таймера (0xFFFF). Выполнение программы останавливается до получения флага переполнения: while(TMR1IF!=1).

Функция выдающая импульсы (програмный ШИМ):

void ServoPulse(byte zeroWidth){
byte i;
for(i=0;i<25;i++){
		out=1;
		SoftDelayUs(zeroWidth);
		out=0;
		DelayMs(3);
}	
}

Данная функция получает длительность еденичного импульса, которые выдаются «пачкой» по 25шт. иначе работоспособность нарушалась. Длительность нулевого импулься выбрана минимальная работоспособная.

Функция получения результатов с АЦП:

unsigned char getADC(void)
{
	GO_DONE=1;
	while(GO_DONE==1)
	{
		asm("nop");
	}
	return ADRESH;
}


Главная функция с бесконечным циклом выполнения:

void main(void){
	byte i;

	TRISIO = 0b00000010;
	CCP1CON=0; //выключили модуль сср
	CMCON0=7;
	VREN=0;   //отключили опорное напряжение 

	ANSEL =0b00000010;
	ADCON0=0b00000100;
	ADON=1;

	while(1){
		i=getADC();

		if (i<25) i=25;
		if (i>250) i=250;

		ServoPulse(i);
	}
}

Здесь происходит инициализация АЦП, порта ввода/вывода, и основной цикл программы в котором полученное знацение с АЦП корректируется и подается на сервоманинку.
  • 0
  • 04 июля 2011, 22:02
  • zaman
  • 1
Файлы в топике: servo.zip

Комментарии (4)

RSS свернуть / развернуть
Код конешн жуткий, но ничего :) Главное что работает
0
а какой макс. ток на пин у этой пикушки?
… а если серву нагрузить?
0
А причем тут ток пикушки и нагрузка сервы?
Серва управляется 50Гц ШИМ, питание сервы идет отдельно. В этом и прелесть.
0
Если код немножко изменить то реакция сервомашинки увеличивается:
void ServoPulse(byte zeroWidth){
		out=1;
		SoftDelayUs(zeroWidth);
		out=0;
		DelayMs(3);
}
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.