«Цифровая лаборатория» - генерируем и измеряем частоту
«Цифровая лаборатория» - генерируем и измеряем частоту
На основе набора «Цифровая лаборатория» из серии «Азбука электронщика» можно создать как генератор, так и частотомер. Достаточно просто сменить программу в микроконтроллере!
Статьи

«Цифровая лаборатория» - генерируем и измеряем частоту

Мастер Кит «Цифровая лаборатория» - генерируем и измеряем частоту NR05, азбука электронщика, цифровая лаборатория, мастер китКаждый радиолюбитель, в том числе и начинающий, должен иметь в своей домашней лаборатории генератор и частотомер. Не всегда это должны быть приборы с отменными характеристиками, во многих случаях достаточно оценить частоту или сгенерировать периодический  сигнал с постоянной амплитудой.

На основе набора NR05 из серии «Азбука электронщика» можно создать  как генератор, так и частотомер. Для этого даже не придется что-либо докупать. Достаточно просто сменить программу в микроконтроллере!

На плате расширения набора имеется двухстрочный  индикатор, который вполне подойдет для отображения частоты при работе частотомера, и пять кнопок, которые можно задействовать для управления генератором.

Для создания программы управления генератором используем стандартную дополнительную функцию вывода tone. Эта функция позволяет получить меандр (прямоугольный сигнал с равными длительностями импульса и паузы в периоде) с частотой от 31 Гц до 65535 Гц на любом выводе Ардуино.

При этом воспроизводиться одновременно может только один сигнал. Если сигнал уже воспроизводится на одном выводе, то вызов tone() с номером другого вывода в качестве параметра ни к чему не приведет, если же tone() будет вызвана с тем же номером вывода, то будет установлена новая частота сигнала.

Следует иметь в виду, что использование функции tone() помешает использовать ШИМ на портах входа/выхода 3 и 11.

Принцип действия функции рассмотрен, например,  в материале http://ucheba33.ru/?p=389 и основан на использовании прерывания по таймеру.

Используем размещенную на плате «аналоговую» клавиатуру из пяти кнопок для установки частоты нашего генератора. Все кнопки для экономии портов микроконтроллера подключены только к одному порту через резисторный делитель, а номер нажатой кнопки определяется микропроцессором по величине напряжения на этом порту. Текущая частота генератора отображается на индикаторе.

Пусть при включении будет генерироваться частота 1000 Гц, при нажатии:

- на первую (слева) кнопку частоты уменьшается на 1 Гц;

- на вторую – увеличивается на 1 Гц;

- на четвертую – уменьшается на 100 Гц;

- на пятую – увеличивается на 100 Гц;

- на третью (среднюю) увеличивается на 1000 Гц до 20000 Гц.

 

Текст программы генератора:

 

// подключаем библиотеку и определяем, к каким выводам подключен индикатор

#include <LiquidCrystal.h>

LiquidCrystal lcd(A1, A2, A3, 2, 4, 7);

// порт вывода частоты

#define output 3

 

// определяем порт, к которому подключены кнопки

#define NUM_KEYS 5

// задаем экспериментально определенные значения, соответствующие номерам кнопок

int adcKeyVal[NUM_KEYS] = {30, 150, 360, 535, 760};

// частота при включении питания

int frequency = 1000;

 

void setup() {

// инициализирум индикатор, 16 символов, 2 строки

lcd.begin(16, 2);

// включаем генерацию 1000 Гц

tone(output, frequency);

// выводим значение частоты на индикатор

lcd.print(frequency);

lcd.print(" Hz");

}

 

void loop() {

 

// получаем номер нажатой кнопки 

int key = get_key();

 

// в зависимости от номера кнопки выполняем изменения генерируемой частоты

switch (key){

  case 1:

  frequency--;

  if(frequency < 50) frequency = 50;

  setFrequency();

  break;

  case 2:

  frequency++;

  if(frequency > 20000) frequency = 20000;

  setFrequency();

  break;

  case 3:

  frequency +=1000;

  if(frequency > 20000) frequency = 1000;

  setFrequency();

  break;

  case 4:

  frequency -=100;

  if(frequency < 50) frequency = 50;

  setFrequency();

  break;

  case 5:

  frequency +=100;

  if(frequency > 20000) frequency = 20000;

  setFrequency();

  break;

}

 

}

 

 

// функция установки и индикации частоты

void setFrequency(){

tone(output, frequency);

lcd.clear();

lcd.print(frequency);

lcd.print(" Hz");

delay(200); 

}

 

// функция определения номера нажатой кнопки

int get_key()

  {

    int input = analogRead(A6);

    int k;

    for(k = 0; k < NUM_KEYS; k++)

      if(input < adcKeyVal[k])

        return k + 1;    

    return 0;

  }

Принцип действия электронно-счетных (цифровых) частотомеров основан на подсчете количества импульсов, сформированных входными цепями из периодического сигнала произвольной формы, за определенный интервал времени. Интервал времени измерения также задается методом подсчета импульсов, взятых с внутреннего кварцевого генератора частотомера или из внешнего источника (например, стандарта частоты). Таким образом, цифровой частотомер является прибором сравнения, точность измерения которого зависит от точности эталонной частоты.

Микроконтроллер, установленный на плате Ардуино, работает на частоте 16 мГц, обеспечиваемой кварцевым генератором. Таким образом, мы имеем эталон частоты для сравнения.

Программа считает число импульсов на цифровом порту 5 за заданный период времени и выводит значение частоты на индикатор. При этом программа обращается напрямую к регистрам микроконтроллера для настройки таймеров.

Текст программы частотомера:

//Пин 5 вход измерителя частоты.

//06_02_2016

//------------------------------

#include <LiquidCrystal.h>

LiquidCrystal lcd(A1, A2, A3, 2, 4, 7);

//----

unsigned long interval_izm= 1000;//Время счета входной частоты в миллисекундах

unsigned long interval_LCD= 1000;//Интервал смены показаний на LCD в миллисекундах

unsigned long F_min       =   99;//Минимальная измеряемая частота Гц

unsigned long korr_timer  =   67;//Время запроса после вызова таймера в тактах

//----

unsigned long currentTime;  //Текущее время в милисекундах

unsigned long lastTime_LCD; //Время последнего изменения LCD

unsigned long DeltaTime_LCD;//Время с момента вывода на LCD

unsigned long ovf_tic_timer_1,out_ovf_tic_timer_1;

unsigned long ovf_tic_timer_2,out_ovf_tic_timer_2;

unsigned long tik_timer_1,tik_timer_2;

unsigned long interval_timer_2;

unsigned int  out_TCNT2,out_TCNT1;

boolean       stop_for_timer_1,start_for_timer_1,flag_LED;

float f,t1;

//----

void setup() {

pinMode(5, INPUT);              //Назначим вывод 5 на ввод сигналов

digitalWrite(5, HIGH);          //Включаем подтягивающий резистор

lcd.begin(16, 2);               //Задаем размерность LCD дисплея

lcd.clear(); //Очистка экрана   

lcd.print("Ready");

delay(1000);

lcd.clear(); //Очистка экрана   

//---Настройка таймера 1

TCCR1A=0;

TIMSK1 = 1 << OCIE1A; //прерывание по совпадению с OCR1A

OCR1A = (F_min-1);    //Минимальная измеряемая частота Гц

TCCR1B = (1 << CS10) | (1 << CS11) | (1 << CS12) | (1 << WGM12);

TCNT1=0;

//---Настройка таймера 2

TCCR2A=0;

TIMSK2 = 1<<TOIE2;//прерывание по переполнению таймера2

TCCR2B = 1 << CS20; // делитель 1

//----

interval_timer_2=(unsigned long)interval_izm*62.5;

//----

}

//---Прерывание по таймеру 1

ISR (TIMER1_COMPA_vect){

if (start_for_timer_1==1  && flag_LED==0)

{

TCNT2=0;TCCR2B = 1 << CS20;TCNT1=0;TCNT1=0;

start_for_timer_1=0;ovf_tic_timer_2=0;ovf_tic_timer_1=0;

}

if (stop_for_timer_1==1  && flag_LED==0){

TCCR2B=0;TCCR1B=0;

out_TCNT2=TCNT2;

out_TCNT1=TCNT1;

TCNT1=0;TCNT2=0;  //сброс счётных регистров

out_ovf_tic_timer_1=ovf_tic_timer_1;ovf_tic_timer_1=0;

out_ovf_tic_timer_2=ovf_tic_timer_2;ovf_tic_timer_2=0;

flag_LED=1;stop_for_timer_1=0;

}

if (start_for_timer_1==0 && stop_for_timer_1==0 && flag_LED==0)

{ovf_tic_timer_1=ovf_tic_timer_1+1;}

}

//---Прерывание по таймеру 2

ISR (TIMER2_OVF_vect){

ovf_tic_timer_2=ovf_tic_timer_2+1; //количество переполнений таймера 2

if (ovf_tic_timer_2>=interval_timer_2 && flag_LED==0)stop_for_timer_1=1;

}

//----

void loop()

{

//---Условия для вывода показаний на LCD

currentTime=millis();

DeltaTime_LCD  =abs(currentTime - lastTime_LCD);

if (DeltaTime_LCD >= interval_LCD && flag_LED==1)//вывод на LCD

{

//----

tik_timer_2=(unsigned long)out_ovf_tic_timer_2*256+out_TCNT2;

tik_timer_1=(unsigned long)out_ovf_tic_timer_1*F_min+out_TCNT1;

t1=(float)(tik_timer_2-korr_timer)/tik_timer_1;

f=1000000.0/(t1*0.0625);

//----

lcd.clear();                            //Очистка экрана

lcd.setCursor(0,0);lcd.print(f,0);lcd.print(" Hz");

//----

lastTime_LCD = currentTime;

flag_LED=0;             //Сигнал об окончании вывода на индикатор

TCCR1B = (1 << CS10) | (1 << CS11) | (1 << CS12) | (1 << WGM12);

start_for_timer_1=1;

}

}

Для проверки функционирования устройств возьмем две платы расширения из наборов NR05. Одну из них запрограммируем как генератор, вторую – как частотомер и подключим выход генератора к входу частотомера.

Ссылка на маленькое видео: 

Будем менять частоту генератора (он на видео слева) и наблюдать за показаниями частотомера (справа).

Как видно, показания не совсем точны, что обусловлено и нестабильностью частот задающих генераторов микроконтроллеров, и самими методами формирования и подсчета импульсов, но для оценки в домашних условиях вполне могут устроить. Разумеется, для измерения частот различных сигналов потребуется входной усилитель-формирователь, который преобразует периодический входной сигнал произвольной формы в цифровой сигнал прямоугольной формы с крутыми фронтами, уверенно воспринимаемый частотомером. Такие формирователи различной сложности достаточно широко описаны в радиотехнической литературе и легко находятся в Интернете.

Таким образом, мы добавили еще два устройства на основе набора «Цифровая лаборатория » к уже описанным на нашем сайте masterkit.ru и в других материалах.

Рейтинг@Mail.ru

Почему выбирают Мастер Китнас


Мы в Сети


© 1999-2022 Мастер Кит