Переместить сервопривод с помощью кнопок | C | Атмел Студио
Сейчас я работаю над проектом солнечного трекера с ATMEGA1284P, и после настройки ШИМ пришло время обнаружить механические ограничения трекера, чтобы я мог определить границы для сервоприводов.
Для этого я подготовил простой код. Я знаю, что ШИМ работает правильно (проверено также с областью действия), но я просто не могу заставить этот код работать. Идея состоит в том, чтобы переместить сервопривод двумя кнопками (подключенными к gnd), а затем настроить UART, чтобы я мог отправлять текущее положение сервопривода на мой компьютер. Я также попытался вызвать функцию pwm_set1 вне цикла if, но она не отвечает вообще.
Переключатели также подключены правильно, и я также проверил с помощью вольтметра на выводах uC, и они оба работают нормально, то есть заземление при нажатии, подтягивающие резисторы настроены, как вы можете видеть в коде ниже.
Любые предложения высоко ценятся. Спасибо! Ура, Руи Морено.
#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);
}
}
}
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
}
Все еще немного сырой, поскольку я хочу, чтобы прерывания обновляли переменную, а затем функцию pwm_set1 под main с этой обновленной переменной. Также мне придется реализовать какой-то механизм устранения неполадок.
Ура, Руи Морено.