Справка - Atmega328p, преобразование ШИМ-сервокода из pin9 в pin6
Я нашел рабочий код, который использует pin9 (PB1) на ардуино для управления сервоприводом, но в моем проекте ультразвуковой датчик уже использует этот pin / таймер. Я хочу преобразовать код для использования pin6 (PD6), изменил регистры в соответствии с таблицей данных atmega, но это не работает. Нужна помощь:/
Код должен позволить мне поворачивать сервопривод с помощью потенциометра.
#define F_CPU 16000000 //16MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define PWM_PRESCALLER 64
#define ICR_MAX (long double)F_CPU/PWM_PRESCALLER/50
#define OCR_MIN (float)ICR_MAX/37.5 // /8.75
#define OCR_MAX (float)ICR_MAX/8.7 // 37.5
volatile unsigned long adc_val=0;
volatile unsigned long counter=0;
unsigned long curr_adc=0;
ISR (ADC_vect)
{
adc_val += ADC;
counter++;
}
int main(void)
{
DDRD |= (1<<DDD6);
ICR1 = ICR_MAX;
OCR0A = OCR_MIN;
TCCR0A = (1 << COM1A1) | (1<<WGM00) | (1<<WGM01);
TCCR0B = (1<<WGM02) | (1<<CS01) | (1<<CS00);
ADMUX = (1 << REFS0);
ADCSRA = (1 << ADEN)|(1 << ADATE)|(1 << ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
sei();
ADCSRA |= (1<<ADSC);
while(1)
{
if(counter >= 1000)
{
cli();
unsigned long round_val = round(adc_val / counter);
adc_val=0;
counter=0;
if(abs(round_val - curr_adc) > 1)
{
curr_adc = round_val;
}
long double ocr = OCR_MIN + ((long double)curr_adc * (OCR_MAX - OCR_MIN)/1024);
OCR0A = (int)round(ocr);
sei();
}
}
}
@Peti, 👍1
Обсуждение2 ответа
Бит PORTB 6 управляется с помощью TIMER0, а бит PORTB 1 - с помощью TIMER1. Поэтому вам необходимо соответствующим образом изменить переменные таймера. Одна из ошибок в вашем коде заключается в том, что вы покидаете ICR1. Это должно быть OCRA, если вы хотите использовать TIMER0.
Я думал о ICR0, но, согласно таблице данных, ICR0 нет., @Peti
Проверил это, вы правы. Я думаю, что вы можете использовать только OCRA. Не OCR0A?, @MichaelT
Отсутствие OCRA по данным Atmel studio, @Peti
Timer0 уже используется для delay и millis . Используйте контакт 3 или 11, так как они используют timer2, который не используется., @Gerben
Моя проблема теперь в том, что я должен использовать ICR0 для моего сервопривода и ультразвукового датчика, а затем они путаются. Есть ли альтернатива для этого ICR0?, @Peti
Я думаю, что вы решите эту проблему, прочитав технический паспорт. Значения для TCR0A и TCR0B определяются режимом генерации формы сигнала, значением TOP и тактовым прескалером. Согласно вашему коду, WGM = 0x7, т.е. Быстрый ШИМ, OCR0A = TOP. Читать раздел 19.7.3 Atmel-42735B-ATmega328/P_Datasheet_Complete-11/2016, @MichaelT
Я согласен с комментарием Ника Гэммонао том, что намного проще использовать платформу Arduino и использовать функцию analogRead()
в сочетании с библиотекой servo.
Сказав это, вы решили написать программу с нуля, как это предпочитают делать многие другие по той или иной причине. Я хотел передать 2 веб-страницы, на которые я всегда захожу, когда играю с частотами ШИМ и настройками.
- http://playground.arduino.cc/Main/TimerPWMCheatsheet
- https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
- Как правильно настроить ШИМ для управления углом сервопривода в AVR?
- Проблемы с пониманием минимальных и максимальных параметров серводвигателя
- Как Arduino Uno может поддерживать до 12 сервоприводов, если у него всего 6 цифровых выводов ШИМ?
- Управление сервоприводом без библиотеки сервоприводов
- Как изменить скорость нескольких сервоприводов, работающих одновременно с модулем PCA9685?
- Контакты ШИМ серводвигателей, Arduino Uno
- Управление сервоприводом с помощью ATtiny13A
- О UART один передатчик несколько приемников
Пожалуйста, отредактируйте свой вопрос и попробуйте вставить код еще раз. Каким-то образом появились дополнительные новые строки, и все отступы были удалены, что сделало код довольно трудным для чтения., @Gerben
Разве не было бы намного проще просто делать
analogRead
каждый раз через ваш цикл? И используйте [Servo library] (https://www.arduino.cc/en/Reference/servo ) для управления сервоприводом?, @Nick Gammon