Страницы курса:

Уроки

Задания


index.htm
01.htm
02.htm
03.htm
04.htm
05.htm
06.htm
07.htm
08.htm
09.htm


z1.htm
z2.htm
z3.htm
z4.htm
z5.htm
z6.htm
z7.htm
z8.htm
z9.htm
z10.htm
z11.htm

New! - ФОРУМ!

Совет - умейте правильно находить информацию!


         
         
   

Задача 10. 

Устройство изменяющее состояние нагрузки при громком звуке длительностью от 5 до 20 мС. 

Цель задачи: разработать устройство и программу для МК ATmega16 которое будет анализировать длительность сигнала от микрофона и если она будет лежать в пределах 5-20 мС то будет менять состояние подключенной нагрузки: если была выключена - то включит и наоборот.

Что нужно для выполнения этой задачи:   

- Компилятор Си для AVR CodeVisionAVR 

- Программный эмулятор для AVR VMLAB = Visual Micro Lab

- DataSheet (ДШ) на МК AVR ATmega16

- знание других материалов курса

- твердое знание первой страницы курса на 5 с плюсом  

- свободное время и желание.

Можно использовать МК ATmega8 
только понадобится ДШ и на него!

 

Что делать 
с сигналом от микрофона?

Я предлагаю использовать встроенный в МК компаратор - стр. 199 ДШ.

Компаратор сравнивает напряжения на входах "+" и "-" 

Если напряжение на "+" выше чем на "-" то на выходе компаратора ACO  устанавливается высокий уровень - лог.1  а если наоборот то низкий уровень лог.0  

Изменение на выходе компаратора ACO может вызывать прерывание - мы будем использовать это.

 

Как же подать сигнал от микрофона на входы компаратора? 

Я набросал схему для электретного микрофона.

R1 - питает микрофон, его номинал зависит от напряжения питания и типа микрофона - примерно 3 - 5 КОм.

R2 - 4,7 КОм - образует с С1  ФНЧ - ослабляет частоты выше 
чем 1/(6.28 * R * C)   - отсюда находим С1

R3 - 47 КОм - образует с С2  ФВЧ - ослабляет частоты ниже 
чем 1/(6.28 * R * C)   - отсюда находим С2

 
Внимание ! В симуляторе VMLAB  есть возможность как бы подключится к внутренним точкам в МК ! Например напряжение на выходе компаратора ACO вы можете вывести в окно SCOPE !

 

Вы можете нарисовать эту схему в симуляторе Micro Cap (всего 6 МБ - куча примеров схем и масса возможностей! ) и определить номиналы элементов чтобы получить  нужную вам полосу пропускания входной схемы.

 

Мы применили пассивный фильтр - значит он будет довольно слабо обрезать не нужные нам частоты - спад около 6 Дб на октаву (на двукратное изменение частоты) 

 

А вот в симуляторе электронных схем Micro Cap есть примеры активных  фильтров более высоких порядков на ОУ и вы сможете применить их заранее подобрав устраивающую вас характеристику.

 

Еще более заманчиво - подать сигнал от микрофона на АЦП МК и применить цифровую фильтрацию! - скорости МК хватит, пример цифрового фильтра есть в AN AVR и на Си с целочисленной математикой C:\VMLAB\ST6_demo\DSPDEMO.C

 

 

 

Запускаем компилятор CV 
(CodeVisionAVR) 

и затем генератор начального кода программы:

Лучший друг начинающего микроконтроллерщика!

 

1) выбираем ATmega16 и частоту 1 МГц  - высокая точность такта не нужна и можно использовать внутренний RC генератор МК в установке фьюзов с завода. 

Внешний кварц не нужен!

 

2) откроем ярлык - компаратор:

- включили компаратор
- включили прерывание по изменению логического уровня на выходе компаратора - ACO 

 

3) теперь включим передатчик USART для отправки информации из МК через адаптер rs232 на COM-порт ПК или в терминал VMLAB

- максимально 4800 бод получается при тактовой частоте МК 1 МГц

 

4) Сделаем ножки PB0 и PB1 выходами

Аналогично сделайте выходом ножку PC0

 

Все установки сделаны. 

5) можно генерировать начальный текст программы и 
сохранять файлы


Сохраните файлы вот так:

 

 

 

Теперь у вас должен быть открыт текст программы в окне компилятора CodeVisionAVR.

 

Надо наполнить программу смыслом!

 

Используя мастер начального кода компилятора вы поняли, что при любом изменении логического уровня на выходе компаратора ACO будет возникать прерывание и мы будем попадать в функцию обработчик прерывания:

     
  // Analog Comparator interrupt service routine
interrupt [ANA_COMP] void ana_comp_isr(void)
{
// Place your code here

при изменении ACO 
мы попадаем сюда ...


}

 
     

А изменение уровня на выходе компаратора вызывается сигналом микрофона преодолевшим фильтрацию.

 

Попали в прерывание и что с ним делать? 

Ну можно наверно запомнить что это случилось! т.е. посчитать его - обычно для этого используют некоторую переменную например:

     
  #include <stdio.h>

uunsigned char int_ctr = 0;
/* мы объявили переменную которая 
называется int_ctr и может хранить 
число от 0 до 255
сейчас в ней число 0

Эта переменная глобальная - значит 
доступна в любом месте программы


это еще и пример обрамления 
многострочного комментария 
к программе*/

 

 
     

 

Добавляемый в программу код я буду писать синим!

Комментарии к программе - зеленым.

Теперь нужно добавить в функцию обработчик прерывания

- строчку кода увеличивающую на 1 переменную int_ctr - значит посчитать возникшее прерывание. 

- запретить пока прерывание от компаратора! Иначе, как только мы выйдем из функции обработки прерывания оно будет мгновенно возникать снова пока есть звук и логический уровень ACO "трепыхается"! 

     
 

При возникновении любого разрешенного индивидуально прерывания происходит запрещение глобально всех прерываний в МК "очисткой" (значит обнулением) бита_i в регистре SREG 

эквивалентно выполнению строки: #asm("cli")


Выполнение кода функции обработчика прерывания до конца и автоматический выход из нее разрешает глобально все разрешенные индивидуально прерывания! "установкой" (set - значит сделать "1") бита_i в регистре SREG 


эквивалентно выполнению строки: #asm("sei")

 

Важно! 

Если вы покинете функцию обработчик прерывания не выполнив ее код до конца (например через старый добрый оператор goto) бита_i в регистре SREG останется "0" и ни каие прерывания не произойдут пока вы не разрешите их програмно! 

например такой строчкой: #asm("sei")

 
     

 

-но прежде я бы хотел добавить диагностическую (методы отладки программы МК здесь) строчку кода изменяющую состояние ножки 
PC0
на противоположное существующему.

делаем:

     
  // Analog Comparator interrupt service routine
interrupt [ANA_COMP] void ana_comp_isr(void)
{
// при изменении уровня на выходе компаратора
// мы попадаем сюда!

// Place your code here

PORTC.0^=1; /*инвертировать бит0 регистра 
если был "0" станет "1" и наоборот

при возникновении прерывания мы сможем увидеть момент  попадания сюда в виртуальном осциллографе SCOPE симулятора VMLAB или на реальном подключенном к ножке PC0 */

int_ctr = int_ctr + 1; /* мы посчитали 
прерывание, увеличив на 1 счетчик прерываний переменную int_ctr 

конечно программисты написали бы 

int_ctr++;

красивей, элегантней, но смысл тот же!  */

ACSR &=~(1<<3); /* Сделали "0" бит_3 в регистре ACSR - стр 200 в ДШ мега16.

Это запрещает прерывание от изменения выхода компаратора!

Register – ACSR 

• Bit 3 – ACIE: Analog Comparator Interrupt Enable

When the ACIE bit is written logic one and the I-bit in the Status Register is set, the Analog
Comparator Interrupt is activated. 

When written logic zero, the interrupt is disabled.

 */
}

 
     

 

дословно на Си PORTC.0^=1; означает: 
взять значение бит_0 регистра PORTC сделать XOR (исключающее или) этого значения с числом 1 (а проще = инвертировать бит) и результат записать опять в бит_0 регистра PORTC

Логическое "исключающее или" - XOR - значит, что напротив 1  значение меняется!

байт А 1 1 0 0 0 0 0 1
байт В 0 1 1 0 1 1 0 1
A^B 1 0 1 0 1 1 0 0

 

Старайтесь думать над значением каждой строки программы и четко проговаривать выполняемые операции !

 

Давайте разберем как мы обнулили  бит_3 
написав:   ACSR &=~(1<<3);

&=  означает сделать логическое "и" того переменной слева с результатом вычисления того, что справа и результат поместить в переменную слева. 

Логическое "и" значит что только 1 и 1 дают 1

Логическое И
A B A & B
1 1 1
0 1 0
1 0 0
0 0 0

Пожалуйста изучите логические операции
их не много. 

Это нужно вам !


Вычислим что у нас справа:

1<<3 означает сдвинуть число 1 на 3 разряда влево - это равносильно умножению на 2 в 3-й степени, или на 8. Делается так:

0000 0001  - это число 1

0000 0010 - это число 2 что равно числу 1 сдвинутому на 1 разряд в лево или умноженному на 2 в первой степени.

0000 0100 - это число 4 что равно числу 1 сдвинутому на 2 разряда в лево или умноженному на 2 в квадрате.

0000 1000 - это число 8 или результат  (1<<3)

 

~  означает инверсию - т.е. 1 сделать 0 и наоборот. 

~(1<<3)  эквивалентно  ~0000 1000 и дает число: 1111 0111

 

Итак мы нашли что:  ACSR &=~(1<<3);

эквивалентно:

ACSR = (ACSR & 1111 0111);

Вы наверно поняли операцию "и" и видите, что напротив 0 в регистре ACSR получится 0 не зависимо что там было раньше, а другие биты регистра не изменятся!

Обязательно и подробно комментируйте свою программу! не откладывайте на потом...  

Потом не сделаете !  

... знаю, знаю. Сам такой !

 

Дальнейший алгоритм простой - в начале программы нужно подождать тишину более 0.2 сек. Затем ждем звука. Обнаружив прерывание мы сделаем паузу 5 мС и вновь разрешим прерывания от компаратора. Если прерывание случится - значит сигнал длится не менее 5 мС и мы будем жадать еще 15 мС и вновь разрешим прерывание - если оно не случится в течении 0.2 С то можно считать что звук длился от 5 до 20 мС - переключаем состояние ножек PB0 PB1 напротивоположное - а к ним подключено исполнительное устройство.

Если что-то не так как описано выше то мы возвращаемся в начало программы.

 

Продолжение следует.

Хотите - посмотрите задачу 9

 


   
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Rating All.BY Rambler's Top100 МЕТА - Украина. Рейтинг сайтов


2009-2015 123avr.com