【问题标题】:Move servo with pushbuttons | C | Atmel Studio用按钮移动伺服| C |爱特梅尔工作室
【发布时间】:2014-12-14 01:54:32
【问题描述】:

我现在正在使用 ATMEGA1284P 进行太阳能跟踪器项目,在配置 PWM 之后,是时候发现跟踪器的机械限制,以便我可以定义伺服系统的边界。

为此,我准备了一个简单的代码。我知道 PWM 工作正常(也检查了范围),但我无法让这段代码工作。这个想法是用两个按钮(连接到接地)移动伺服,然后配置 UART,以便我可以将当​​前伺服位置发送到我的计算机。 我也试过在 if 循环之外调用 pwm_set1 函数,但它根本没有响应。

开关的接线也正确,我还用电压表检查了 uC 引脚上的电压,它们都工作正常,即按下时为 GND,上拉电阻配置如下面的代码所示。

非常感谢任何建议。 谢谢! 干杯, 瑞莫雷诺。

#ifndef F_CPU
#define F_CPU 1000000L   // 1 Mhz
#endif
#include <avr/io.h>
#include <avr/portpins.h>
#include <util/delay.h>

void pwm_init(){
    // Configurar o Waveform Generation Mode.
        // Para modo de fast PWM, WGM11, 12 e 13 têm que estar a 1
    TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 0<<COM1A0;     // COM1A1 para configurar PWM em modo non-    inverted (devido ao BJT) | anterior:COM1A1 e COM1A0 para configurar PWM em inverted mode
    TCCR1B |= 1<<WGM13 | 1<<WGM12 | 1<<CS10;      // CS10 serve para selecionar o prescaler     (nenhum, neste caso)

    //Definir o período para PWM
    ICR1 = 19999;
    OCR1A = ICR1 - 550;  // posição inicial do servo
};

void pwm_set1(uint16_t x){
    OCR1A = ICR1-x;
}

int main(void)
{
    DDRD |= 0xFF; //Configurar Porta D como saída em todos os pinos

    pwm_init();
    uint16_t posx = 550;

    //configurar pinos C1 e C2 como entrada para os switches left e right (just in case)
    DDRC &= ~(1 << PC2);
    DDRC &= ~(1 << PC3);
    //pull-up resistors nos pinos C1 e C2
    PORTC |= (1 << PC2);
    PORTC |= (1 << PC3);


    while(1)
    {
            if ((PINC & (1<<2)) == 0){
                posx+=1;
                pwm_set1(posx);
            }

            if ((PINC & (1<<3)) == 0){
                posx-=1;
                pwm_set1(posx);
            }
    }    
}

【问题讨论】:

    标签: avr avr-gcc atmega atmelstudio


    【解决方案1】:

    我已经设法通过使用中断使开关工作:

    ISR(INT0_vect) {        
        if (bit_is_set(PIND, PIND2)) {   //PD2
            OCR1A+=20;
        }
        else{}
    }
    
    ISR(INT1_vect) {        
        if (bit_is_set(PIND, PIND3)) {   //PD2
            OCR1A-=20;
        }
        else{}
        }
    
    void initInterrupts(void) {
        EIMSK |= ((1 << INT0)|(1 << INT1));     //enable INT0 and INT1
         //EICRA |= (1 << ISC01);      //trigger on falling edge
        sei();                          // set (global) interrupt enable bit
       }
    

    仍然有点原始,因为我想要的是中断更新一个变量,然后在 main 下使用该更新后的变量执行 pwm_set1 函数。 我还必须实现某种去抖动机制。

    干杯, 瑞·莫雷诺。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-01
      • 2018-08-02
      • 1970-01-01
      相关资源
      最近更新 更多