Захотелось поуправлять сервой кнопкой, задача такая, нажимаю кнопку серва поварачивается на ~10гр., и в этоже время на семисегментный индикатор выводится цифра, и так серва поворачивается под управлением кнопки сначала в одну сторону, а достигнув минимума в другую. Но симулирую в протеусе и возникает проблема, нехочет серва двигаться, хотя символы меняются Сигнал сервы - portd.0 portc - аноды светодиода portd - катод
#include <mega16.h> unsigned char n=0; //переменная для вывода цифр и вычитания\суммирования угла сервы int mass[9]={0,237,171,15,227,143,141,47,233}; //цифры unsigned char push=0; // проверка нажатия unsigned char i=0; //для разделения паузы и сигнала на серву unsigned char m=0; //задает направление движения сервы unsigned int preangle=2250; // середина для сервы unsigned int angle; //значения для угла поворота
// Timer 1 output compare A interrupt service routine interrupt [TIM1_COMPA] void timer1_compa_isr(void) { TCCR1B=0x00; if (PINB.2==0){ push++; if (push==4){ n++; //обработка для устранения дребезга } if (push==100) { push=5; } }
if (i==0) { //20мс сервы между сигналами PORTD |= 0x01; OCR1AH=0x75; OCR1AL=0x30; i=1; } else {
if (angle<=1503) { //если минимум то m=1; } if (angle>=2997) {//если максимум то m=2; }
if (n>=1 && n<9) {
if (m==1) { angle=preangle + (n*83); //угол увеличиваем в зависимости от кол-ва нажатий } else { angle=preangle - (n*83);//угол уменьшаем в зависимости от кол-ва нажатий }
Я планировал что таймер на меге считает до 20мс с опущеной ногой сервы, прерывается, дальше считает нужное кол-во для импульса сервы с поднятой ногой сервы, и так зацикливается, но в протеусе творится жесть
Вы привыкайте проблемы локализовывать. Напишите простую программу, которая просто управляет сервой. Без всяких 10-ти градусов и кнопок. Заработало? Копайте дальше? Не заработало? Значит пред-делители таймера криво настроены или МК работает не на той частоте, поставьте светодиод и мигайте им раз в секунду. Мигает раз в четыре секунды? Делайте выводы.
Добавлено спустя 4 минуты 26 секунд: 20ms между импульсами он ждет ОК, а вот сам импульс длительностью 42мс
Добавлено спустя 4 минуты 49 секунд: Я с атмегой не работаю, но ошибка с большой долей вероятности вот тут:
Обычно, когда есть int (я так понимаю angle сложными математическими действиями приводится к количеству тиков таймера), и его надо раскидать на чары, то это делается так:
Добавлено спустя 11 минут 57 секунд: Но это вроде не должно так сильно повлиять, ошибка только в LSB появляется, т.е. порядок длительности должен быть тем же.
А зачем вам Compare? Взводите таймер на -angle, когда он перекатится через ноль, отработает прерывание. Кроме того, я не вижу - вы таймер где-нибудь обнуляете?
Вот 42мс меня и смутили, я планировал что 20мс, а дальше таймер сам сбросится в ноль, а дальше я уже задам ему импульс для сервы... 1) вообще я думал что таймер в режиме Fast PWM доходит до TOP значения в OCR1A и дальше сбрасывается в нуль - как написано в даташите "The counter counts from BOTTOM to TOP then restarts from BOTTOM" ? 2) Можно\Нужно ли при остановленном таймере просто обнулять значение TCNT1, дабы сбросить его в нуль ? 3) TCCR1B=0x00; просто останавливает таймер на последнем тике или останавливает и сбрасывает в ноль ?
Насчет unsigned char - спасибо, исправил Насчет последнего недопонял, я и задаю в OCR1A значение angle, чтобы достигнув его таймер прерывался...
Спасибо за советы , надеюсь на дальнейшую помощь
P.S. Да видимо я спутал назначение TIM1_COMPA и TIM1_OVF...как я понял как раз по этому весь сигнал был 42мс?
Сделал без кнопок пока, в протеусе шим дает нужный от 1 до 2 мс с 20мс паузами, серва протеусовская движется, попробовал на живой - двигается в одну сторону до предела а дальше жужжит и испытывает явный дискомфорт
Подаю просто 1,5мс стабильные, в протеусе серва держится центра, реальная снова клонится до конца в угол, эххх осцила нет жаль ((
В чем может быть проблема ?
Я не понимаю вот мк включился для управления сервой, он же не знает в каком она положении, нужно наверно делать в первую секунду установку на центр ?
Это скорее всего значит, что процессор работает не на той частоте, которую вы планировали. Если нет осцилла - мигайте светодиодом раз в секунду. Если светик будет мигать слишком часто или слишком медленно - вы нашли проблему.
У меня еще была проблема, сервы начинали самопроизвольно дергаться туда сюда, причем сильно, а по программе должны были удерживать угол. Оказалось проблема в питании. При питании от 1 источника 16 серв очень нехило просаживали питание в момент перемещения и видимо у МК от скачков напряжения менялось что-то (может быстродействие как то зависит от напряжения, может таймеры, хз) и система входила в колебательный режим. Сервы дергаются на нужный угол, напряжение падает, импульсы сбиваются, сервы уходят на новую точку, и опять.
Вылечилось разделением питания. Теперь у меня электроника питается от маленького акка, а все сервы от силового с большими конденсаторами.
Но на 1-4 сервах эффект был незаметен, так что скорее всего согласен с предыдущим ответчиком.
while(1) { PORTD = 0xFF; // Старт импульса delay_us(1500); // Длительность импульса. 1500 = центр. Тут можно менять число от 1000 до 2000. PORTD = 0x00; // Стоп импульса
while(1) { PORTD = 0xFF; // Старт импульса delay_us(1500); // Длительность импульса. 1500 = центр. Тут можно менять число от 1000 до 2000. PORTD = 0x00; // Стоп импульса
delay_ms(19); // Задержка между импульсами }
Попробуйте такой вариант для начала.
Попробовал в старом проекте закоментировать все что в обработке прерывания стоит, и ставил ваш код в основное тело цикла программы- серва начала вести себя странно... затем сделал новый проект без таймера - все работает вроде...
Последний раз редактировалось AVRus 13 фев 2011, 17:16, всего редактировалось 1 раз.
протеус вам в помощь... а если управление несколькими сервами - то думайте как организовать работу таймера, так чтобы, только перегружать таймер новым значением..