Считаем импульсы, вращаем моторчик)

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 9
Зарегистрирован: Ср ноя 16, 2016 07:04:33
Откуда: Одесса

Сообщение Vadim1984 »

Здраствуйте, уважаемые форумчане!
Написал программку, все работает, но немного не так как надо :(
Суть: считаем импульсы на входе, в зависимости от их кол-ва приводим в действие исполнительный механизм (моторчик и концевик, сигнализирующий о необходимости выключения моторчика). Новые импульсы могут прийти во время работы мотора, потому создал переменную для хранения кол-ва циклов включения мех-ма "ball". На случай поломки концевика(INT1), каждый цикл включения мотора ограничен по времени (TIMER2_OVF_vect). Входящие импульсы принимаем на INT0, в случае окончания пакета импульсов не будет в течении пол секунды, считаем (TIMER1_OVF_vect). Все работает, НО при опыте, вместо 10 необходимых срабатываний концевичка, хватает 8..9 иногда 10 для завершения работы, т.е. Должны выдать 10 мячиков, выдаем 8. Я только учусь, поэтому буду благодарен каждому тычку носом в проблемные места :)

Код: Выделить всё

#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


volatile uint8_t timer0_counter = 0;	//счетчик таймера макс длинны импульса
volatile uint8_t imp = 0;	//подсчет импульсов
volatile uint8_t ball = 0;	//подсчет, необходимого к выдачи, количества мячиков


ISR(INT0_vect){//принимаем импульсы с купброприемника
	GICR &= ~(1 << INT0);	//выключаем прерывания от купюроприемника
	_delay_ms(20);
	if(!(PIND & (1 << 2))){
		GICR |= (1 << INT0);
		return;
	}
	TCNT0 = 0;				//
	timer0_counter = 0;		//настраиваем таймер длинны импульса
	TIMSK |= (1 << TOIE0);	//и включаем прерываниуе по переполнению таймера0
	imp++;			//считаем импульс
	GICR |= (1 << INT0);	//включаем прерывания от купюроприемника
	
}
ISR(TIMER0_OVF_vect){				//таймер длинны импульса
	timer0_counter++;					//по истечению мы понимаем, что пакет импульсов от купюроприемника
	if(timer0_counter > 3){			//принят, и назначаем количество выдаваемых мячиков, увеличивая значение
		TIMSK &= ~(1 << TOIE0);			// буферной переменной ball
		if(imp > 4 && imp < 6){
			ball++;
			imp = 0;
			return;
		}
		else if(imp > 9 && imp < 11){
			ball += 2;
			imp = 0;
			return;
		}
		else if (imp >19 && imp < 21){
			ball += 4;
			imp = 0;
			return;
		}
		else if (imp > 49 && imp < 51){
			ball += 10;
			imp = 0;
			return;
		}
	}
}

volatile uint8_t flag = 0;	//флаг отключения мотора, по признаку срабатывания концевика INT1 либо исхода макс времени работы мотора
volatile int timer2_counter = 0;//счетчик длительности работы мотора

ISR(INT1_vect){			//концевик выключения мотора
	GICR &= ~(1 << INT1);
	flag = 1;
	_delay_ms(300);
}

ISR(TIMER2_OVF_vect){	//таймер выключения мотора ~5 секунд
	timer2_counter++;
	if(timer2_counter > 15){
		flag = 2;
		TIMSK &= ~(1 << TOIE2);
	}
	
}




int main(void)
{
	MCUCR = (1 << ISC01)|(1 << ISC00)|(1 << ISC11);
	GICR = (1 << INT0);
	TCCR0 = (1 << CS02)|(1 << CS00);
	TCCR2 = (1 << CS22)|(1 << CS21)|(1 << CS20);
	TIMSK = 0;
	DDRD = 1;
	PORTD = 0;
	sei();
	while(1)
	{
		if(ball > 0 && !(PIND &(1<<0))){		//включаем мотор
			PORTD |= (1 << 0);
			GICR |= (1 << INT1);//включаем прерывание от концевика
			timer2_counter = 0;
			TCNT2 = 0;
			TIMSK |= (1 << TOIE2);// настраиваем и включаем таймер длительности работы мотора
			flag = 0;
		}
		if(flag != 0 && (PIND &(1<<0))){		//выключаем мотор
			PORTD &= ~(1 << 0);
			GICR &= ~(1 << INT1);//выкл прерывание от концевика
			TIMSK &= ~(1 << TOIE2);//выкл таймер длительности работы мотора
			ball--;
			//flag = 0;
		}
		
	}
}
И схемка [img][url=http://img.radiokot.ru/files/119676/medium/17bk7b5cc1.jpg][/img]
Реклама
Zat
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Пн ноя 02, 2009 05:27:41
Откуда: С-Пб

Сообщение Zat »

Я бы для начала избавился от задержек в прерываниях, как-то это не по-кошачьи.
Затем, нарисовал бы алгоритм работы сего аппарата и уже после разделил на блоки и написал код.
А тут как-то видать все решалось по ходу пьесы. И уже к тому, что написано приклеивался новый код.
Видать сначала был написан код учитывающий работу концевых датчиков, а потом приклеился таймаут, если
концевик сломался.. и поехали ошибки.
Реклама
Ответить

Вернуться в «AVR»