Attiny13 и серво. Помогите найти ошибку в коде.
- Войдите на сайт для отправки комментариев
Всем добрый день! Пытаюсь тодключить к Attiny13 и сервопривод, но что-то какие-то глюки... Суть работы проста: Установить серву в 90, ести на 4 пине гогическая "1" то учтановить серву в 60, если на 3 пине "1" то установить серву в 120. Если на пинах 3 и 4 "0", то установить серву в начальное положение - 90. К пинам 3 и 4 подпаяны резисторы по 20кОм к земле что бы избежать ложных срабатываний. Питается все это от аккумулятора 18650. Заранее оговорюсь: серва нормально работает от 3.3 вольта, проверял на Ардуино ДУЕ! Почему-то серва не хочет нормально позиционироваться. Поварачивается не туда, или вообще не поварачивается... или ровно в 90 не хочет становиться, а стает +- 5-10...
вот код:
#include <avr/io.h>
#include <util/delay.h>
byte s=0;
byte pos=90;
boolean lastPos = false;
void setup() {
//pinMode(s, OUTPUT);
DDRB |= (1<<0);
DDRB &= ~(1<<3);
DDRB &= ~(1<<4);
pulseOut(s,pos);
}
void loop() {
if (lastPos == false) {
if (PINB & (1<<PINB3)){
_delay_ms(5);
if (PINB & (1<<PINB3))
{
pulseOut(s, pos - 30);
lastPos = true;
_delay_ms(200);
}
}
if (PINB & (1<<PINB4)){
_delay_ms(5);
if (PINB & (1<<PINB4))
{
pulseOut(s,pos + 30);
lastPos = true;
_delay_ms(200);
}
}
}
if (lastPos == true) {
if (!(PINB & (1<<PINB4)) && !(PINB & (1<<PINB4))){
for (byte i=0;i<10;i++){
pulseOut(s,pos);
_delay_ms(2);
}
lastPos = false;
_delay_ms(200);
}
}
_delay_ms(20);
}
void pulseOut( byte pin, byte p){
PORTB |= (1<<0);
delayMicroseconds(300+p*(2500/180));
PORTB &= ~(1<<0);
}
Заготовку кода брал здесь: https://arduinodiy.wordpress.com/2015/05/20/servo-on-attiny13/
В первой ветке при lastPos==false Вы изменяете lastpos=true послк чего у Вас выполняется и вторая ветка с lastPos==true;
Вряд ли Вы хотели такого результата?
В общем именно этого я и хотел. В первой ветке идет поворот вправо-влево, а во второй восстановление в 90. Условие lastPos я использовал для того что бы "не мучить серву": появился сигнал - повернуть серву - перейти к другой ветке и ждать пока сигнал не пропадет. Сигнал пропал - поставить серву в 90 - Перейти к 1-й ветке и ожидать сигнала на поворот.
Я только учусь программированию. Если есть более оптимальный вариант, то я буду рад если мне покажут как правильно.
Вот рабочий код:
#define TopTimer 200 #define angle60 188 #define angle90 186 #define angle120 184 #include <avr/io.h> #include <avr/interrupt.h> int main(void) { CLKPR=0x80; CLKPR=1<<CLKPS2;// на 16 //настройка порта DDRB=(1<<PB1); PORTB=(1<<PB3)|(1<<PB4); //настройка ШИМ TCCR0A=(1<<WGM01)|(1<<WGM00)|(1<<COM0B0)|(1<<COM0B1); TCCR0B=(1<<WGM02)|(1<<CS01)|(1<<CS00);//предделитель счетчика на 64 OCR0A=TopTimer; //счетчик будет считать до OCR0B=angle90; //устравноить серву в 90 while(1) { uint8_t buf=(PINB>>3)&0x03; //проверяем сигналы на пинах switch (buf){ case 0:OCR0B=angle90;break; case 1:OCR0B=angle60;break; case 2:OCR0B=angle120;break; default:break; } } }Для тех кому сложно, вот код по-проще:
#include <avr/io.h> #include <util/delay.h> const byte servo = 0; // Servo pin on ATtiny int tPulse = 4000; // Total pulse length on 1 Mhz clock int hPulse = 60; // High pulse time (60=0deg -> 280=180deg) boolean lastPosL = false; boolean lastPosR = false; boolean lastPosU = false; int main(void) { DDRB |= (1<<0); hPulse = 110; DDRB &= ~(1<<3); hPulse = 170; _delay_ms(100); pulseOut(); pulseOut(); pulseOut(); while (1) { if (PINB & (1<<PINB3) && lastPosL == false){ //Поворачиваем влево lastPosL = true; lastPosR = false; lastPosU = false; hPulse = 133; pulseOut(); pulseOut(); pulseOut(); } else if (PINB & (1<<PINB4) && lastPosR == false){ //Поворачиваем вправо lastPosL = false; lastPosR = true; lastPosU = false; hPulse = 240; pulseOut(); pulseOut(); pulseOut(); } else if (!(PINB & (1<<PINB3)) && !(PINB & (1<<PINB4)) && lastPosU == false) //Исходное положение { lastPosL = false; lastPosR = false; lastPosU = true; hPulse = 170; pulseOut(); pulseOut(); pulseOut(); } delayMicroseconds(500); // Give servo some time to move before giving it a new position } } void pulseOut(){ PORTB |= (1<<0); delayMicroseconds(hPulse); // High pulse angle data PORTB &= ~(1<<0); delayMicroseconds(tPulse-hPulse); }Похоже, у Вас ощибка в строке 37, Вы дважды смотрите состояние пина 4, а должны смотреть пин 4 и пин3
Да, там ошибка, вы правы.
Последние два кода рабочие, можно их использовать