简体   繁体   English

对标准I / O端口(ATmega32 AVR)上的伺服的多个控制?

[英]Multiple controls to servo on standard i/o port (ATmega32 AVR)?

I'm basically trying to perform a chain of actions on multiple servo motors when a particular button is pressed.The following code works fine but can only perform a single movement on multiple servos ie when the button is pressed Servo1 moves to 900 and servo2 to 1500 else they go back to standard positions. 我基本上是想在按下一个特定按钮时对多个伺服电机执行一系列动作。以下代码可以正常工作,但只能对多个伺服器执行一次移动,即当按下按钮时,Servo1移至900,Servo2移至900。 1500,否则他们回到标准位置。

What I want to achieve is a set of movements, for instance when the button is pressed I want both the servos to swing(0 to 180 to 0(3 different movements)). 我要实现的是一组运动,例如,当按下按钮时,我希望两个舵机都摆动(0到180到0(3个不同的动作))。 I tried to use a delay function and change the values of the servo but then it wouldn't work, which im assuming is because the delay becomes greater than my Fast PWM time period. 我尝试使用延迟功能并更改伺服器的值,但此后它不起作用,我认为这是因为延迟变得大于我的Fast 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;  
}

How do I go about the same? 我该怎么做? Any help appreciated. 任何帮助表示赞赏。

It seems you are implementing your PWM manually using the Timer1, that means that you can't add delays as those from <util/delay.h> so, your only option is implement something similar to a state machine. 似乎您正在使用Timer1手动实现PWM,这意味着您不能像<util / delay.h>那样添加延迟,因此,您唯一的选择就是实现类似于状态机的延迟。

define a variable for the state where STATE0 will be the waiting state, STATE1 will be the first movement STATE2 the second movement and so on... 为状态定义一个变量,其中状态0将是等待状态,状态1将是第一个动作,状态2是第二个动作,依此类推...

then define a 'time table' to define how much time it'll wait on each state, (ideally it should be a condition table but anyway...) 然后定义一个“时间表”来定义每个状态要等待的时间(理想情况下应该是条件表,但无论如何...)

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...
}

I haven't check your timer configuration, hence I actually don't know if the waiting time of 500 cycles should be enough or too much, but you should change the time[] table according your tests... 我没有检查您的计时器配置,因此实际上我不知道500个周期的等待时间是否足够,但是您应该根据测试更改time []表...

it's also recommended to use 2 switches, one to check the condition and change the states accordingly, and the other one to actually do the task for the actual state... I just got lazy and did both in a single switch... 还建议使用2个开关,一个检查条件并相应地更改状态,另一个使用实际执行实际状态的任务...我只是很懒,并且都在一个开关中完成了这两个操作...

also as you are using an enum{}, it's better that you rename the states to soemthing meaningful, like STATE_WAIT or STATE_POS_180 or STATE_LOCATION_A... 同样,在使用枚举{}时,最好将状态重命名为有意义的东西,例如STATE_WAIT或STATE_POS_180或STATE_LOCATION_A ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM