当按下特定按钮时,我基本上尝试对多个伺服电机执行链操作。以下代码工作正常但只能在多个伺服电机上执行单个移动,即当按下按钮Servo1移动到900,伺服2移动到1500,否则它们会回到标准位置。
我想要实现的是一组动作,例如当按下按钮时我想要两个舵机摆动(0到180到0(3个不同的动作))。我尝试使用延迟功能并更改伺服的值但是它不起作用,我假设这是因为延迟变得大于我的快速PWM时间段。
void main()
{
DDRB = 0xFF;
DDRC = 0x00;
PORTC = 0XFF;
TCCR1A |= 1<<WGM11;
TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10;
TIMSK |= 1<<OCIE1A;
ICR1=19999;
sei();
uint16_t Servo1 = 2000, Servo2 = 900;
while(1)
{
if(bit_is_clear(PINC,0))
{
Servo1 = 900, Servo2 = 1500;
}
else{
Servo1 = 1500, Servo2=2200;
}
if(TCNT1>=800 && TCNT1<=2400)
{
if (TCNT1 >= Servo1 && bit_is_set(PORTB,PINB0)) PORTB &= ~(1<<PINB0);
if (TCNT1 >= Servo2 && bit_is_set(PORTB,PINB1)) PORTB &= ~(1<<PINB1);
}
}
}
ISR(TIMER1_COMPA_vect)
{
PORTB = 0xFF;
}
我该怎么做? 任何帮助表示赞赏。
答案 0 :(得分:0)
您似乎正在使用Timer1手动实现PWM,这意味着您无法添加来自&lt; util / delay.h&gt;的延迟。所以,你唯一的选择是实现类似于状态机的东西。
为状态定义一个变量,其中STATE0将是等待状态,STATE1将是第一个移动STATE2,第二个移动等等......
然后定义一个'时间表'来定义它在每个状态上等待的时间,(理想情况下它应该是一个条件表,但无论如何......)
enum{ STATE0,STATE1,STATE2};// from 0 to 2
int time[3]={0,500,500}; //for state 0 it'll wait the button
volatile int time_counter=0; //needs to be volatile 'cos it's used inside the interrupt
int state = STATE0;
void main()
{
DDRB = 0xFF;
DDRC = 0x00;
PORTC = 0XFF;
TCCR1A |= 1<<WGM11;
TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10;
TIMSK |= 1<<OCIE1A;
ICR1=19999;
sei();
uint16_t Servo1 = 2000, Servo2 = 900; // are these initial values ok for STATE0?
while(1)
{
//eval state
switch(state){
case STATE0:
if(bit_is_clear(PINC,0)) // if button
{
//change state
state=STATE1;
time_counter=0;
//do task
Servo1 = 900, Servo2 = 1500;
}
break;
case STATE1:
if(time_counter>time[state])
{
//change state
state=STATE2;
time_counter=0;
//do task
Servo1 = 1500, Servo2 = 2200;
}
break;
case STATE2:
if(time_counter>time[state])
{
//change state
state=STATE0; // go to wait the buton again
time_counter=0; // not necesary but anyway...
//do task
Servo1 = 2000, Servo2 = 900;
}
break;
}
//do the pwm stuff
if(TCNT1>=800 && TCNT1<=2400)
{
if (TCNT1 >= Servo1 && bit_is_set(PORTB,PINB0)) PORTB &= ~(1<<PINB0);
if (TCNT1 >= Servo2 && bit_is_set(PORTB,PINB1)) PORTB &= ~(1<<PINB1);
}
}
}
ISR(TIMER1_COMPA_vect)
{
PORTB = 0xFF;
time_counter++; //here we count the pwm cycles...
}
我没有检查你的计时器配置,因此我实际上不知道500个循环的等待时间是否应该足够或太多,但你应该根据你的测试改变时间[]表...
还建议使用2个开关,一个用于检查条件并相应地更改状态,另一个用于实际执行实际状态的任务...我只是懒得并且在一个开关中都做了。 ..
同样在使用枚举{}时,最好将状态重命名为soemthing,如STATE_WAIT或STATE_POS_180或STATE_LOCATION_A ......