Влияет ли изменение предварительного масштаба для Таймера 0 или Таймера 2 на функцию micros()?
Я использую ATTiny88 для управления ШИМ-устройством. Прежде всего, изучая литературу, сложно сказать, в чём разница между ATTiny85 и ATTiny88, и подавляющее большинство ссылок относится к ATTiny85.
В данном случае я использую D10 на ATTiny88 для выхода ШИМ. Частота ШИМ должна быть выше 5 кГц, поэтому я выполню команду:
TCCR1B = TCCR1B & 0b11111000 | 0x01;
Как я понял, это установит частоту ШИМ 31 кГц на D10. Пожалуйста, сообщите мне, если это не так. Кроме того, мне нужно использовать функцию micros():
const int pulseDelay = 183;
unsigned long MicroSeconds = micros();
while(micros() - MicroSeconds < pulseDelay){} // 1/2 периода звонка
if (Enable) {digitalWrite(14, 1);} // Если Enable = True, послать высокий импульс на Bell, иначе Bell молчит
while(micros() - MicroSeconds < pulseDelay){} // 1/2 периода звонка
digitalWrite(14,0);
В этом случае, вероятно, лучше не использовать вызов блокировки прерывания.
EDIT: Я написал короткий драйвер, чтобы протестировать:
#include <Arduino.h>
#define True 1
#define False 0
#define Bell 14 // Порт Bell
#define LED 10 // Порт интенсивности
int Intensity = 25;
void Beep(bool Enable, float Delay)
{
const int pulseDelay = 183; // 1/2 периода импульса Белла в микросекундах
int Span = Delay * 2732;
for (int x = 0; x < Span; x++)
{
unsigned long MicroSeconds = micros();
while(micros() - MicroSeconds < pulseDelay){} // 1/2 периода звонка
digitalWrite(Bell, 1); // Послать высокий импульс на Bell
while(micros() - MicroSeconds < pulseDelay){} // 1/2 периода звонка
digitalWrite(Bell,0); // Послать низкий импульс на звонок
}
}
void setup()
{
pinMode(LED, OUTPUT);
analogWrite(LED, Intensity); // Установить начальную интенсивность
pinMode(Bell, OUTPUT); // Установить Bell как выход
// TCCR1B = TCCR1B & 0b11111000 | 0x01; <=========== удалите комментарий, чтобы проверить вызов
}
void loop()
{
Intensity += 25;
if (Intensity > 255) {Intensity = 25;}
analogWrite(LED, Intensity);
Beep(True, 2);
}
Когда я удаляю комментарий, Arduino сильно нагревается. Напряжение на D10 достигает 1 вольта с большим количеством высокочастотного шума и остаётся на этом уровне. D10 выдаёт сигнал частотой 5 кГц с очень узким, но довольно постоянным импульсом.
@LesRhorer, 👍1
Обсуждение1 ответ
ATTiny85 и ATTiny88 — довольно разные устройства. ATTiny85 — это 8-контактный микроконтроллер, тогда как ATTiny88 имеет 28 контактов, и довольно похож на ATmega328P, который можно найти в Uno (но медленнее).
Что касается влияния предварительного делителя на micros(), все зависит от
Ядро, которое вы используете. Я не знаю о стандартном ядре Arduino для
ATTiny88, но большинство ядер AVR используют таймер 0 для millis(),
micros() и delay(). Если вы измените его предделитель, все эти
Функции будут затронуты. Другие таймеры не создают такой проблемы.
Правка 1: Если я правильно понимаю, вы используете это ядро от MH-ET
LIVE. Это очень похоже на стандартное ядро AVR Arduino. Оно
также настраивает предделитель таймера 0 на 64. Если вы
измените этот предделитель, micros() и друзья будут считать неправильно с
Коэффициент ошибки равен 64/предделитель. Например, если вы установите
предделитель на 1 (т.е. без предделителя), micros() будет считать
В 64 раза быстрее.
Вы спросили:
Как именно использование
TCCR1B = TCCR1B & 0b11111000 | 0x01;повлияет на функция micros()?
Это никак не повлияет. Регистр TCCR1B принадлежит
Таймер 1, тогда как, как объяснялось выше, функция синхронизации Arduino
полагаться на Таймер 0.
Правка 2: Ответы на новые вопросы, появившиеся в комментарии.
какой таймер управляет ШИМ на порту 10 на ATTiny88
На ATtiny88 нет контакта, который бы однозначно назывался «контакт 10». Тогда ответ на этот вопрос зависит от того, что вы подразумеваете под «контактом 10», Что, в свою очередь, зависит от используемого вами ядра. Вы написали, что используете Ядро «MH-ET LIVE Tiny88 (16.0 МГц)». Я не нашёл ядра с таким же точно кодом. Имя (ссылка на ваш сердечник была бы полезна!). Шкафы соответствуют Я нашел тех, кого я уже упоминал из MH-ET LIVE, и Спенса ATTinyCore от Konde. В последнем определяется плата с именем «ATtiny88 (Micronucleus, MH-ET t88 с тактовой частотой 16 МГц)».
Если вы действительно используете один из них, они оба определяют «контакт 10» как PB2, который то же самое, что и OC1B (выходное сравнение Таймер 1, канал B). Таким образом, его ШИМ-возможности контролируются по Таймеру 1.
Какую команду мне следует использовать, чтобы получить ШИМ 5 кГц на этом порту?
Существуют различные варианты, в зависимости от выбора режима ШИМ и Предделитель. Вот один из вариантов:
/* Configure Timer 1 for phase correct PWM at 5 kHz. */
void setup() {
DDRB |= _BV(PB2); // установить контакт 10 = PB2 = OC1B как выход
TCCR1A = _BV(COM1B1) // неинвертирующий ШИМ на выводе OC1B
| _BV(WGM11); // выбираем режим 10: фазовая коррекция ШИМ...
TCCR1B = _BV(WGM13) // ...с TOP = ICR1.
| _BV(CS10); // тактовая частота F_CPU
ICR1 = 1600; // период = 2 * 1600 тактов = 0,2 мс
}
Для управления рабочим циклом необходимо ввести число от 0 (для сигнала постоянно НИЗКИЙ) и 1600 (постоянно ВЫСОКИЙ) к регистр OCR1B. Например:
/* Ramp the duty cycle from 0% to 100%. */
void loop() {
for (int duty = 0; duty <= 1600; duty++) {
OCR1B = duty;
delayMicroseconds(1000);
}
}
Я проверил это на Uno, у которого распиновка очень похожа на ATtiny88. и, насколько я могу судить, идентичные реализации Таймера 1.
Почему медленнее? Предположительно, ATTiny88 использует ATmega328, по крайней мере, если я правильно читаю рекламу. Также я понимаю, что только D9 и D10 — это аппаратный ШИМ (плюс моя плата уже использует D10). Я использую ядро MH-ET LIVE Tiny88 (16,0 МГц). Это единственное, которое мне удалось заставить работать с этими платами. Если есть другое ядро, которое будет работать лучше, я готов его попробовать. Как именно использование TCCR1B = TCCR1B & 0b11111000 | 0x01; повлияет на функцию micros()? Я могу справиться, если функция считает за 8, 16, 32... мкс, а не за 1, если я знаю множитель., @LesRhorer
Согласно спецификации, ATtiny88 может работать на частоте до 12 МГц. Похоже, упомянутая вами плата её разгоняет. Возможно, она всё равно будет работать нормально., @Edgar Bonet
Главный вопрос, по сути, остаётся без ответа. Если Timer0 управляет регистрами millis() и micros() для ATTiny88, то какой предделитель должен быть настроен для управления частотой ШИМ на ATTiny88: timer0 или timer1? Сейчас я получаю 490 Гц на порту ШИМ (D10). Мне нужно в 16 раз больше., @LesRhorer
@LesRhorer: Думаю, я ясно ответил на вопрос в заголовке: изменение предварительного делителя для Таймера 0 влияет на micros(); изменение предварительного делителя для Таймера 2 не влияет., @Edgar Bonet
Ну ладно, полагаю, всё верно. Формулировка, возможно, не совсем соответствует сути. Основные вопросы: какой таймер управляет ШИМ на порту 10 микроконтроллера ATTiny88 и какую команду нужно использовать, чтобы получить ШИМ с частотой 5 кГц на этом порту. Возможно, главный вопрос заключается в том, стоит ли мне перейти на Arduino Nano вместо ATTiny88?, @LesRhorer
@LesRhorer: См. развернутый ответ., @Edgar Bonet
Ядро, которое я использую, взято из https://raw.githubusercontent.com/MHEtLive/arduino-boards-index/master/package_mhetlive_index.json, @LesRhorer
Работает отлично! Спасибо, сэр. Устройство требует минимум 5 кГц, поэтому я, вероятно, установлю ICR1 на 1000 вместо 1600, что даст мне период 125 мкс, или частоту 8 кГц, и шаг скважности 0,1% вместо 0,0625%., @Leslie Rhorer
- Генерация сигнала частотой 38 кГц без таймеров
- Arduino IDE с ошибкой ATtiny85 «множественное определение `__vector_5»
- Возникли проблемы с определением CTC на таймере 1 с помощью ATTiny85.
- Создание регулируемого низкочастотного ШИМ-контроллера на Arduino
- Можно ли сгенерировать точный тактовый импульс 15 кГц с помощью ардуино?
- Программирование сервопривода на ATtiny85
- Digispark ATtiny 85 - не распознается как HID устройство
- Клавиатура Digispark ATtiny85
Функция micros() использует прерывание по переполнению Timer0 для увеличения счётчика микросекунд. Если отключить прерывания, функция micros() не будет обновляться корректно., @liaifat85
Если микроконтроллер нагревается, а выходной сигнал остаётся в пределах между НИЗКИМ и ВЫСОКИМ уровнями, то проблема в электрике. Обычно это чрезмерная нагрузка (слишком низкое сопротивление) на выводе. Отключите всё, что подключено к D10, и посмотрите, что выходит с этого вывода., @Edgar Bonet
Вы делаете ряд необоснованных предположений. Главное из них — D10 к чему-то подключен. Arduino не подключена ни к чему, кроме питания по USB во время этого тестирования. Оказывается, Arduino неисправна — у неё внутреннее короткое замыкание. Я почти уверен, что до тестирования устройство было исправно. Либо это совпадение, либо команда TCCR1B = TCCR1B & 0b11111000 | 0x01; привела к сбою чего-то внутри Arduino. Я не хочу менять предделители, пока проблема не будет решена., @LesRhorer