Можно ли использовать Arduino Uno для измерения частоты прямоугольной волны до 600 кГц?
Я делаю проект с датчиком цвета, где выходной сигнал датчика цвета представляет собой прямоугольную волну ШИМ.
Чтобы измерить его частоту с помощью Arduino Uno, я использую функцию pulseIn()
, но не могу получить правильный результат.
Может ли Arduino Uno измерять частоту до 600 кГц с помощью функции pulseIn()
?
@MADHAN KUMAR. S, 👍0
Обсуждение1 ответ
В документации для pulseIn указано, что его можно использовать для интервалов от 10 микросекунд до 3 минут.
600 кГц частота будет иметь интервал 1,6 микросекунды и поэтому не подходит для этого приложения. (1/600000 = 0,000001666).
У меня есть код на моей веб-странице о таймерах для скетча, который может измерять до 8 МГц только с 0,5% ошибка.
Этот код воспроизводится ниже:
// Пример таймера и счетчика
// Автор: Ник Гэммон
// Дата: 17 января 2012 г.
// Вход: контакт D5
// они проверяются в основной программе
volatile unsigned long timerCounts;
volatile boolean counterReady;
// внутри подпрограммы подсчета
unsigned long overflowCount;
unsigned int timerTicks;
unsigned int timerPeriod;
void startCounting (unsigned int ms)
{
counterReady = false; // время еще не истекло
timerPeriod = ms; // сколько 1 мс отсчитывает сделать
timerTicks = 0; // сброс счетчика прерываний
overflowCount = 0; // пока нет переполнения
// сбросить Таймер 1 и Таймер 2
TCCR1A = 0;
TCCR1B = 0;
TCCR2A = 0;
TCCR2B = 0;
// Таймер 1 - считает события на выводе D5
TIMSK1 = bit (TOIE1); // прерывание при переполнении Таймера 1
// Таймер 2 - дает нам интервал счета в 1 мс
// Тактовая частота 16 МГц (62,5 нс на тик) — предварительно масштабирована на 128
// счетчик увеличивается каждые 8 мкс.
// Итак, мы насчитали 125 из них, что дает ровно 1000 мкс (1 мс)
TCCR2A = bit (WGM21) ; // режим СТС
OCR2A = 124; // считать до 125 (относительно нуля!!!!)
// Таймер 2 - прерывание при совпадении (т.е. каждые 1 мс)
TIMSK2 = bit (OCIE2A); // включить прерывание от Таймера 2
TCNT1 = 0; // Оба счетчика обнулены
TCNT2 = 0;
// Сброс предделителей
GTCCR = bit (PSRASY); // сбросить предварительный делитель сейчас
// запускаем Таймер 2
TCCR2B = bit (CS20) | bit (CS22) ; // прескалер 128
// запускаем Таймер 1
// Внешний источник синхронизации на выводе T1 (D5). Часы на переднем фронте.
TCCR1B = bit (CS10) | bit (CS11) | bit (CS12);
} // конец startCounting
ISR (TIMER1_OVF_vect)
{
++overflowCount; // подсчитываем количество переполнений Counter1
} // конец TIMER1_OVF_vect
//*************************************************** ******************
// Служба прерывания Таймера 2 вызывается аппаратным Таймером 2 каждые 1 мс = 1000 Гц
// 16 МГц / 128 / 125 = 1000 Гц
ISR (TIMER2_COMPA_vect)
{
// получить значение счетчика до того, как оно изменится
unsigned int timer1CounterValue;
timer1CounterValue = TCNT1; // см. техническое описание, стр. 117 (доступ к 16-битным регистрам)
unsigned long overflowCopy = overflowCount;
// смотрим, достигли ли мы периода времени
if (++timerTicks < timerPeriod)
return; // еще нет
// если только что пропустили переполнение
if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 256)
overflowCopy++;
// конец времени стробирования, измерение готово
TCCR1A = 0; // остановить таймер 1
TCCR1B = 0;
TCCR2A = 0; // остановить таймер 2
TCCR2B = 0;
TIMSK1 = 0; // отключить прерывание от Таймера 1
TIMSK2 = 0; // отключить прерывание от Таймера 2
// подсчитываем общее количество
timerCounts = (overflowCopy << 16) + timer1CounterValue; // каждое переполнение на 65536 больше
counterReady = true; // устанавливаем глобальный флаг для окончания периода счета
} // конец TIMER2_COMPA_vect
void setup ()
{
Serial.begin(115200);
Serial.println("Frequency Counter");
} // конец настройки
void loop ()
{
// останавливаем прерывания Таймера 0 от сброса отсчета
byte oldTCCR0A = TCCR0A;
byte oldTCCR0B = TCCR0B;
TCCR0A = 0; // остановить таймер 0
TCCR0B = 0;
startCounting (500); // сколько мс считать
while (!counterReady)
{ } // цикл до окончания счета
// настроить счетчики по интервалу счета, чтобы получить частоту в Гц
float frq = (timerCounts * 1000.0) / timerPeriod;
Serial.print ("Frequency: ");
Serial.print ((unsigned long) frq);
Serial.println (" Hz.");
// перезапустить таймер 0
TCCR0A = oldTCCR0A;
TCCR0B = oldTCCR0B;
// давайте закончим работу с последовательным интерфейсом
delay(200);
} // конец цикла
Может ли Arduino UNO измерять частоту до 600 кГц, если мы используем функцию pulseIn()?
Нет. Без использования pulseIn. Однако см. приведенный выше код для измерения такой частоты.
- Какова работа pulseIn?
- Как использовать две функции pulseIn() одновременно в Arduino?
- Как измерить ультразвуковой датчик без импульсного метода?
- Импульсный тахометр
- Непрерывное чтение двух последовательных периодов импульса
- Функция Pulsein() блокирует одновременное выполнение других задач
- Считывание ШИМ-сигнала с радиоуправляемого приемника
- Работа с PulseIn() и Millis().
Я не могу получить правильный результат
... что это значит? ... какой результат вы получите?, @jsotolaВы хотите измерить частоту или рабочий цикл?, @Nick Gammon