Русский
Русский
English
Статистика
Реклама

Инфракрасный

ИК датчик движения на STM32

19.09.2020 00:21:00 | Автор: admin

Приветствую, в этой статье вы узнаете: как сделать датчик движения с использованием ИК диода и ИК приемника на STM32 с минимальным использованием ядра (т.е. с максимальной загрузкой периферии) на регистрах, используя таймеры.

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

Оглавление:

Общая картина

Схемы устройств

Работа ИК диода и ИК приемника

Код для передатчика ИК сигнала

Код для приемника ИК сигнала

Полный код

Дополнительно

Заключение

Общая картина

Используются два устройства: передатчик ИК сигнала и приемник ИК сигнала.

Общий принцип работы следующий: передатчик ИК сигнала излучает сигнал инфракрасного диапазона длин волн, а приемник ИК сигнала их принимает. Между этими устройствами образуется луч, пересечение которого каким-либо объектом фиксируется приемным устройством.

В качестве ИК диода используется TSAL6200, в качестве ИК приемника TSOP4856.

TSAL6200TSAL6200 TSOP4856TSOP4856

Схемы устройств

Опустим цепи питания и другие элементы реальных устройств и рассмотрим только необходимые.

Передатчик ИК сигнала состоит из микроконтроллера STM32L151C8T6, полевого транзистора 2N7002, резистора 1 Ом и ИК диода TSAL6200. Ниже представлена электрическая схема передатчика.

Транзистор необходим для усиления тока, протекающего через ИК диод, так как выходной ток с пина МК ограничен (выходной ток с пина МК STM32L151C8T6 не более 25 мА, максимальный постоянный ток через ИК диод TSAL6200 100 мА).

Выбор транзистора на ваше усмотрение. Здесь выбран транзистор 2N7002, потому что он дешевый и его характеристик достаточно для моего использования. Стоит выбирать транзистор с меньшим пороговым напряжением затвора (Gate Threshold Voltage), так как на затвор вы сможете подать напряжение не более напряжения питания без дополнительных цепей, в нашем случае 3.3 В.

Точный расчет величины сопротивления резистора является трудным, конечно, существуют специальные формулы, но я предлагаю подобрать резистор опытным путем. Так в моем случае используется резистор 1 Ом, амплитуда тока цепи составляет 20 мА, дальность связи при таком токе достигает 14 м в зависимости от конфигурации передаваемого сообщения (количество импульсов в пачке, скважность, об этом ниже). Если вам требуется большая дальность, следует или подобрать резистор поменьше, или увеличить напряжение питания для диода, или выбрать транзистор с меньшим пороговым напряжением и меньшим падением напряжения на сток-истоке.

Приемник ИК сигнала состоит из микроконтроллера STM32L151C8T6, ИК приемника TSOP4856, резистора 100 Ом и конденсатора 0.1 мкФ. Ниже представлена электрическая схема приемника.

Работа ИК диода и ИК приемника

При протекании тока через диод TSAL6200 излучается ИК сигнал с длиной волны 940 нм. Это излучение необходимо промодулировать меандром с частотой 56 кГц (приемник настроен на данную частоту, см. даташит). Передавать следует пачки таких импульсов с определенной скважностью.

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

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

Код передатчика ИК сигнала

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

Выбор пина должен быть обоснован. Необходимо выбирать такой пин, к которому может быть подключен какой-либо канал (кроме четвертого) любого General-purpose таймера. В нашем случае выбран пин PB6, к нему подключается первый канал TIM4. Приемник же будет подключен к пину PB7, второй канал TIM4.

Будем использовать два таймера: TIM4 будет генерировать меандр с частотой 56 кГц, TIM2 будет управлять таймером TIM4, т.е. создавать пачки из меандра. TIM2 будет работать в режиме Master, TIM4 Slave. Почему именно таймер TIM2? Он выбран исходя из таблицы даташита подключений таймеров друг к другу.

Приступим к написанию функции инициализации таймеров Tim_Init_Transmitter(). Код написан для пустого проекта. Сначала объявляем функцию, в теле main её инициализируем, а после мэйна прописываем уже саму функцию.

#include "main.h"void Timer_Init_Transmitter(void);int main(void){   RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6;   // MSI 4.194 MHz enable   Timer_Init_Transmitter();   while(1)   {   }}void Timer_Init_Transmitter(void){}

RCC->ICSCR |= RCCICSCRMSIRANGE_6 - эта строчка просто устанавливает частоту 4.194 МГц МК. У вас может быть любая другая частота.

Настраиваем пин. Включаем тактирование, включаем альтернативную функцию, выбираем скорость пина повыше (это не является необходимым), выбираем какую именно альтернативную функцию хотим подключить к пину. Под спойлерами описано все подробно.

Подробнее про включение тактирования

В даташите находим регистр RCC_AHBENR. Нужно прописать 1 в поле GPIOBEN.

Для этого выбираем в библиотеке CMSIS строчку RCC_AHBENR_GPIOBEN, которая ставит данный бит в единицу.

И изменяем регистр AHBENR следующим образом:

RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable

Подробнее про включение альтернативной функции

В даташите находим регистр GPIOx_MODER. Нужно прописать 10 в поле MODER6 (для пина PB6).

Для этого выбираем в библиотеке CMSIS строчку GPIO_MODER_MODER6_1, которая ставит второй бит в единицу.

В дальнейшем все такие обозначения будут браться аналогично.

И изменяем регистр MODER следующим образом:

GPIOB->MODER |= GPIO_MODER_MODER6_1;//Alternative function mode enable

Включение высокой скорости для пина делается аналогично включению альтернативной функции.

Подробнее про выбор альтернативной функции

Обозначение альтернативных функций представлено на картинке ниже.

Нам нужна альтернативная функция для TIM4 это AF2.

Стоит отметить, что существует два регистра для выбора альтернативных функций: нижний GPIOx_AFRL для пинов с номерами от 0 до 7 и верхний GPIOx_AFRH для пинов с номерами от 8 до 15. Однако, в библиотеке CMSIS определен сдвоенный регистр AFR[2], прописав в скобки 0, мы выбираем нижний регистр, прописав 1, выбираем верхний регистр.

В даташите находим регистр GPIOx_AFRL.

Нам нужно прописать 0010 в поле AFRL6, для этого нам нужно число в шестнадцатеричной форме 0x2000000, 2 седьмая справа для пина PB6, потому что первые шесть цифр для пинов с номерами от 0 до 5.

И изменяем регистр AFRL следующим образом:

GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable

Получили следующий код для настройки пина внутри нашей функции:

void Timer_Init_Transmitter (void){   //Settings for GPIO PB6   RCC->AHBENR |= RCC_AHBENR_GPIOBEN;             //GPIO port B clock enable   GPIOB->MODER |= GPIO_MODER_MODER6_1;           //Alternative function mode enable   GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1;  //High speed   GPIOB->AFR[0] |= 0x2000000;                    //Pin PB6 TIM4 alternative function AF2 enable}

Теперь перейдем к настройке TIM4.

Нам нужно выбрать прескейлер PSC (делитель частоты), рассчитать значения для регистров CCR1 (длительность импульса) и ARR (период импульсов), выбрать режим работы таймера ШИМ, выбрать входной управляющий сигнал от таймера TIM2, выбрать режим для Slave и подать выходной сигнал таймера на пин PB6.

Включение тактирования осуществляется аналогично включению тактирования GPIO.

Подробнее про выбор прескейлера PSC и расчет CCR1 и ARR

Выберем значение преселлектора входной частоты равное 0, в этом случае частота тактирования таймера будет равна частоте МК.

И изменяем регистр PSC следующим образом:

TIM4->PSC = 0; //Prescaler value

Перейдем к расчету ARR.

Для расчета ARR нам нужно поделить тактовую частоту таймера 4.194 МГц (у вас своя) на 56 кГц. Получаем 74,89, округляем до целого. Я округлил до 75. И вписываем в регистр ARR:

TIM4->ARR = 75 //Auto-reload value

Осталось рассчитать CCR1.

Так как у нас простой меандр, то в регистр CCR1 при режиме ШИМ нужно указать половину от значения ARR:

TIM4->CCR1 = 37;//Capture/Compare 1 value

Подробнее про выбор режима работы ШИМ таймера

Так как у нас первый канал, то используем регистр CCMR1. Нас интересует в этом регистре поле OC1M. Режим ШИМ позволяет настраивать длительность импульса при фиксированном периоде.

Выберем PMW mode 1, вписав две единицы во второй и третий биты, т.е. 110:

TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1

Подробнее про настройку подачи выходного сигнала на пин PB6

В регистр CCER в поле CC1E нужно вписать 1, включив подачу выходного сигнала на пин.

Вписываем следующую строчку:

TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding pin

Подробнее про выбор управляющего сигнала и режима Slave

Для управления TIM4 таймером TIM2 нужно выбрать входной сигнал ITR1. Для этого нужно вписать в поле TS регистра TIMx_SMCR 001. Также выберем режим для Slave, вписав 101 в поле SMS. В этом режиме пока входной сигнал ITR1 будет высоким, то TIM4 будет работать и выдавать меандр на пин, как только ITR1 станет низким, TIM4 выключается.

Для этого вписываем:

TIM4->SMCR |= TIM_SMCR_TS_0;//choosing ITR1

TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode

Добавим к уже существующему коду, и получим:

void Timer_Init_Transmitter (void){   //Settings for GPIO PB6   RCC->AHBENR |= RCC_AHBENR_GPIOBEN;             //GPIO port B clock enable   GPIOB->MODER |= GPIO_MODER_MODER6_1;           //Alternative function mode enable   GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1;  //High speed   GPIOB->AFR[0] |= 0x2000000;                    //Pin PB6 TIM4 alternative function AF2 enable   //Settings for TIM4 - Slave   RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;            //TIM4 clock enable   TIM4->PSC = 0;                                 //Prescaler value   TIM4->ARR = 75;                                //Auto-reload value   TIM4->CCR1 = 37;                               //Capture/Compare 1 value   TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1    enable   TIM4->CCER |= TIM_CCER_CC1E;                   //OC3 signal is output on the corresponding output pin   TIM4->SMCR |= TIM_SMCR_TS_0;                   //choosing ITR1   TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode   TIM4->CR1 |= TIM_CR1_CEN;                      //TIM4 enable}

Включение TIM4 можно производить, а можно и нет, так как управляющий сигнал с TIM2, всё равно включит его.

Теперь перейдем к настройке TIM2.

Необходимо подать тактирование на таймер, рассчитать PSC, CCR1 и ARR, выбрать режим работы таймера ШИМ, выбрать какой сигнал будет выходным (входным управляющим для TIM4) и включить таймер.

Включение тактирования аналогично, как и для таймера TIM4.

RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;//TIM2 clock enable

Подробнее про расчет PSC, CCR1 и ARR для TIM2

Так как по даташиту на диод в пачке следует использовать не менее 10 импульсов (на самом деле можно и меньше, но качество работы может быть не очень хорошим), то выберем тактирование таймера TIM2 в десять раз меньше, чем TIM4.

Как видим в формуле для расчета частоты тактирования таймера в знаменателе уже есть +1, т.е. нам нужно записать в регистр PSC 9, чтобы получить частоту в 10 раз меньшую, чем частоту МК.

TIM2->PSC = 9;//Prescaler value

Теперь рассчитаем значение для CCR1: отправлять будем 10 импульсов, следовательно, нам нужно взять значение ARR для TIM4 (период одного импульса, это 75) и умножить на 10, т.е. получаем 750, однако, у нас есть прескейлер, который делит частоту на 10, т.е. нам нужно поделить 750 на 10, в итоге получаем снова 75 (как и в TIM4, но уже с другим прескейлером). Запишем это значение в регистр CCR1 таймера TIM2.

TIM2->CCR1 = 75;//Capture/Compare 1 value

Перейдём к расчету ARR: тут всё просто, допустим, хотим стрелять пачками со скважностью 11.2, при этом период излучения пачек будет около 2 мс (из расчета, что 1 мс это 4194000/1000 = 4194 тика, и умножаем на 2, получаем округлённо 8400, а с прескейлером 10, получаем 840 тиков), умножаем длительность пачки 75 на 11.2 и получаем 840, как видите, значения совпадают. Запишем это в регистр ARR.

TIM2->ARR = 840;//Auto-reload value

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

Режим работы таймера TIM2 точно такой же, как и у TIM4 - ШИМ.

TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable

Подробнее про выбор выходного сигнала TIM2 (управляющего для TIM4)

Найдем регистр TIMx_CR2.

Нам нужно подать сигнал с первого канала (мы же используем CCR1), на выход с таймера TIM2. Этим сигналом является OC1REF. Ниже на картинке можно найти комбинацию битов для этого сигнала 100.

В поле MMS необходимо вписать 1 в третий бит.

TIM2->CR2 |= TIM_CR2_MMS_2;//OC1REF signal is used as trigger output (TRGO)

Теперь осталось включить TIM2, записав следующую строчку:

TIM2->CR1 |= TIM_CR1_CEN;//TIM2 enable

В таком случае при включении МК, диод начнет излучать. Если вы хотите включать диод в определенное время, тогда вам в нашей функции необходимо убрать две строчки с включением таймеров, и просто в нужный момент включить TIM2.

Добавим эти строчки к предыдущим и получим:

void Timer_Init_Transmitter (void){   //Settings for GPIO PB6   RCC->AHBENR |= RCC_AHBENR_GPIOBEN;             //GPIO port B clock enable   GPIOB->MODER |= GPIO_MODER_MODER6_1;           //Alternative function mode enable   GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1;  //High speed   GPIOB->AFR[0] |= 0x2000000;                    //Pin PB6 TIM4 alternative function AF2 enable   //Settings for TIM4 - Slave   RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;            //TIM4 clock enable   TIM4->PSC = 0;                                 //Prescaler value   TIM4->ARR = 75;                                //Auto-reload value   TIM4->CCR1 = 37;                               //Capture/Compare 1 value   TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable   TIM4->CCER |= TIM_CCER_CC1E;                   //OC3 signal is output on the corresponding output pin   TIM4->SMCR &= ~TIM_SMCR_TS;                    //clear bits   TIM4->SMCR |= TIM_SMCR_TS_0;                   //choosing ITR1   TIM4->SMCR &= ~TIM_SMCR_SMS;                   //clear bits   TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode   TIM4->CR1 |= TIM_CR1_CEN;                      //TIM4 enable   //Settings for TIM2 - Master   RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;            //TIM2 clock enable   TIM2->PSC = 9;                                 //Prescaler value   TIM2->ARR = 840;                               //Auto-reload value   TIM2->CCR1 = 75;                               //Capture/Compare 1 value   TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable   TIM2->CR2 |= TIM_CR2_MMS_2;                    //OC1REF signal is used as trigger output (TRGO)   TIM2->CR1 |= TIM_CR1_CEN;                      //TIM2 enable}

Теперь у нас ИК диод будет излучать пачки по 10 импульсов, у которых частота 56 кГц, со скважностью 11.2, т.е. с периодом следования пачек в 2 мс. Заметим, что момент пересечения каким-либо объектом внутри периода пачек не определен, т.е. мы можем судить о пересечении ИК луча только по отсутствию следующей пачки. Таким образом, погрешность измерения момента времени пересечения луча составляем 2 мс.

Код приемника ИК сигнала

Для приема ИК сигнала снова будем использовать таймеры, а точнее всего один. В микроконтроллерах STM32 таймеры могут быть не только Master или Slave, а могут быть Master/Slave, т.е. они могут управлять сами собой.

В разделе статьи Код передатчика ИК сигнала мы уже выбрали пин PB7 для приемника ИК сигнала. Схему подключения см. выше. К этому пину подключается второй канал TIM4.

Ниже на картинке представлена схема устройства таймера.

Из схемы видно, что у каждого канала есть вход и выход, у таймера есть входной управляющий сигнал TRGI, также показаны тактирование и устройство Trigger controller.

Принцип работы для нашего проекта заключается в следующем: пусть наш таймер будет просто считать время, допустим, равное 5 периодам излучаемых пачек ИК сигнала, следовательно, в ARR будет число, равное 5 периодам пачек, т.е. 840 * 5 = 4200. Настроим таймер так, чтобы при приеме каждой пачки таймер перезагружался и начинал считать заново. При достижении таймером числа в регистре ARR таймер выдает прерывание, которое означает, что на вход уже как 5 периодов не приходит пачка, следовательно, луч пересекается каким-то объектом. Вот и вся работа таймера. Осталось настроить TIM4.

Создадим новый проект и функцию инициализации таймера:

#iclude "main.h"void Timer_Init_Receiver(void);int main(void){   RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6;    // MSI 4.194 MHz enable   Timer_Init_Receiver();   while(1)   {   }}void Timer_Init_Receiver(void){}

Необходимо настроить пин PB7: включить тактирование порта B, настроить альтернативную функцию пина, настроить скорость и выбрать какую конкретную альтернативную функцию подключить к пину. Всё, как и в предыдущем случае.

void Timer_Init_Receiver(void){//Settings for GPIO PB7RCC->AHBENR |= RCC_AHBENR_GPIOBEN;          // GPIO port B clock enableGPIOB->MODER |= GPIO_MODER_MODER7_1;        // Alternative function mode enableGPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1;// High speedGPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;        // pull-up PB7GPIOB->AFR[0] |= 0x20000000;                // Pin PB7 TIM4 alternative function AF2 enable}

Все настройки аналогичны, как и для передатчика, только альтернативная функция немного отличается, 2 нужно вписать уже на восьмое место справа. Еще необходимо подтянуть пин к плюсу прописав строчку:

GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;

Теперь настроим TIM4.

Включим тактирование таймера. Так как у нас второй канал, то будем использовать CCR2. Прескейлер приравняем к 9, чтобы частота тактирования таймера была как у TIM2 передатчика. Для приемника можно приравнять CCR2 и ARR. Как уже рассчитали ранее, вписываем в эти регистры 4200.

RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;// TIM4 clock enable

TIM4->PSC = 9;// Prescaler value

TIM4->ARR = 4200;// Auto-reload value

TIM4->CCR2 = 4200;// Capture/Compare 2 value

Далее настроим режим работы таймера.

Нам нужно, чтобы он просто считал, и всё. Для этого в даташите находим TIMx_CCMR1 и в поле OC2M вписываем 000, что соответствует Frozen mode. Изменим регистр, обнулив все биты:

TIM4->CCMR1 &= ~TIM_CCMR1_OC2M;// Frozen mode enable

Настроим канал на выход, обнулив биты поля CC2S (более подробно написано в даташите), впишем нули в эти биты:

TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode

Теперь обратимся к картинке со схемой устройства таймера (см. выше). Нам необходимо, чтобы входной сигнал с пина PB7 был управляющим для таймера TIM4, таким сигналом является TI2FP2. Проследите путь этого сигнала от TIMx_CH2 до TRGI. Чтобы выбрать данный сигнал в качестве управляющего, необходимо в регистр TIMx_SMCR в поле TS вписать 110. Сразу же выберем режим для Slave: Reset mode, вписав 100 в поле SMS. Для этого пропишем строчки:

TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2

TIM4->SMCR |= TIM_SMCR_SMS_2;// Reset mode

Теперь нам нужно определиться, что будет являться триггером обновления таймера: передний или задний фронт входных импульсов (на самом деле не особо важно, но лучше выбрать по переднему фронту, в нашем случае, это фронт спада напряжения). Для этого нужно использовать пару битовых полей регистра CCER: CC2P и CC2NP, они работают в паре, более подробно написано о них в даташите.

Для нашего случая вписываем 1 в CC2P и 0 в CC2NP. Делаем это так:

TIM4->CCER &= ~TIM_CCER_CC2NP;// This bit is used in conjunction with CC2P.

TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge

Разрешим прерывание по переполнению. Для этого в регистре TIMx_DIER в поле CC2IE впишем 1.

Для этого впишем строчку:

TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable

Включаем таймер строчкой:

TIM4->CR1 |= TIM_CR1_CEN;// TIM4 enable

Не забываем разрешить глобальное прерывание:

NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable

Наша функция инициализации таймера выглядит следующим образом:

void Timer_Init_Receiver(void){//Settings for GPIO PB7RCC->AHBENR |= RCC_AHBENR_GPIOBEN;           // GPIO port B clock enableGPIOB->MODER |= GPIO_MODER_MODER7_1;         // Alternative function mode enableGPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speedGPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;         // pull-up PB7GPIOB->AFR[0] |= 0x20000000;                 // Pin PB7 TIM4 alternative function AF2 enable//Settings for TIM4RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;          // TIM4 clock enableTIM4->PSC = 9;                                 // Prescaler valueTIM4->ARR = 4200;                              // Auto-reload valueTIM4->CCR2 = 4200;                             // Capture/Compare 2 valueTIM4->CCMR1 &= ~TIM_CCMR1_OC2M;              // Frozen mode enableTIM4->CCMR1 &= ~TIM_CCMR1_CC2S;              // Output modeTIM4->CCER &= ~TIM_CCER_CC2NP;               // This bit is used in conjunction with CC2P.TIM4->CCER |= TIM_CCER_CC2P;                 // Inverted/falling edgeTIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2TIM4->SMCR |= TIM_SMCR_SMS_2;                // Reset modeTIM4->DIER |= TIM_DIER_CC2IE;                // Capture/Compare 2 interrupt enableTIM4->CR1 |= TIM_CR1_CEN;                    // TIM4 enableNVIC_EnableIRQ(TIM4_IRQn);                   // TIM4 global Interrupt enable}

Теперь напишем обработчик прерываний:

Первое что нужно сделать, это снять флаг в регистре статуса TIMx_SR:

TIM4->SR &= ~TIM_SR_CC2IF;

Далее можем делать, что хотим. Хоть ставить какой-нибудь флаг, хоть зажигать диод. Допустим будем зажигать светодиод. Настроим пин PB15 на выход, прописав в мэйне:

GPIOB->MODER |= GPIO_MODER_MODER15_0;// PB15 output mode

Наш обработчик прерываний будет выглядеть следующим образом:

void TIM4_IRQHandler(void){TIM4->SR &= ~TIM_SR_CC2IF;GPIOB->ODR |= GPIO_ODR_ODR_15;  // Led red on}

Готово! Теперь при пересечении ИК луча каким-либо объектом, на приемнике будет зажигаться светодиод.

Полный код

Код передатчика ИК сигнала
void Timer_Init_Transmitter(void);int main(void){   RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6;             // MSI 4.194 MHz enable   Timer_Init_Transmitter();   while(1)   {   }}void Timer_Init_Transmitter(void){  //Settings for GPIO PB6   RCC->AHBENR |= RCC_AHBENR_GPIOBEN;             //GPIO port B clock enable   GPIOB->MODER |= GPIO_MODER_MODER6_1;           //Alternative function mode enable   GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1;  //High speed   GPIOB->AFR[0] |= 0x2000000;                    //Pin PB6 TIM4 alternative function AF2 enable   //Settings for TIM4 - Slave   RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;            //TIM4 clock enable   TIM4->PSC = 0;                                 //Prescaler value   TIM4->ARR = 75;                                //Auto-reload value   TIM4->CCR1 = 37;                               //Capture/Compare 1 value   TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable   TIM4->CCER |= TIM_CCER_CC1E;                   //OC3 signal is output on the corresponding output pin   TIM4->SMCR &= ~TIM_SMCR_TS;                    //clear bits   TIM4->SMCR |= TIM_SMCR_TS_0;                   //choosing ITR1   TIM4->SMCR &= ~TIM_SMCR_SMS;                   //clear bits   TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode   TIM4->CR1 |= TIM_CR1_CEN;                      //TIM4 enable   //Settings for TIM2 - Master   RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;            //TIM2 clock enable   TIM2->PSC = 9;                                 //Prescaler value   TIM2->ARR = 840;                               //Auto-reload value   TIM2->CCR1 = 75;                               //Capture/Compare 1 value   TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable   TIM2->CR2 |= TIM_CR2_MMS_2;                    //OC1REF signal is used as trigger output (TRGO)   TIM2->CR1 |= TIM_CR1_CEN;                      //TIM2 enable}
Код приемника ИК сигнала
#include main.hvoid Timer_Init_Receiver(void);int main(void){   RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6;         // MSI 4.194 MHz enable  GPIOB->MODER |= GPIO_MODER_MODER15_0;        // PB15 output mode   Timer_Init_Receiver();   while(1)   {   }}void Timer_Init_Receiver(void){//Settings for GPIO PB7RCC->AHBENR |= RCC_AHBENR_GPIOBEN;           // GPIO port B clock enableGPIOB->MODER |= GPIO_MODER_MODER7_1;         // Alternative function mode enableGPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speedGPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;         // pull-up PB7GPIOB->AFR[0] |= 0x20000000;                 // Pin PB7 TIM4 alternative function AF2 enable//Settings for TIM4RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;          // TIM4 clock enableTIM4->PSC = 9;                                 // Prescaler valueTIM4->ARR = 4200;                              // Auto-reload valueTIM4->CCR2 = 4200;                             // Capture/Compare 2 valueTIM4->CCMR1 &= ~TIM_CCMR1_OC2M;              // Frozen mode enableTIM4->CCMR1 &= ~TIM_CCMR1_CC2S;              // Output modeTIM4->CCER &= ~TIM_CCER_CC2NP;               // This bit is used in conjunction with CC2P.TIM4->CCER |= TIM_CCER_CC2P;                 // Inverted/falling edgeTIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2TIM4->SMCR |= TIM_SMCR_SMS_2;                // Reset modeTIM4->DIER |= TIM_DIER_CC2IE;                // Capture/Compare 2 interrupt enableTIM4->CR1 |= TIM_CR1_CEN;                    // TIM4 enableNVIC_EnableIRQ(TIM4_IRQn);                   // TIM4 global Interrupt enable}void TIM4_IRQHandler(void){TIM4->SR &= ~TIM_SR_CC2IF;GPIOB->ODR |= GPIO_ODR_ODR_15;               // Led red on}

Дополнительно

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

Нужно добавить глобальную переменную, например, написав между "инклюдами" и мэйном такую строчку:

int StatusDiode = 0;// 0 - diode is off, 1 - diode is on

Эта переменная необходима для запоминания статуса светодиода: выключен или включен.

Далее в функции инициализации таймера нужно изменить строчку с разрешением прерывания по переполнению на разрешение прерывания по триггеру, такой строчкой:

TIM4->DIER |= TIM_DIER_TIE;// Trigger interrupt enable

И последнее: изменим обработчик прерываний.

Соответственно, если диод был выключен и у нас сработало прерывание по триггеру, то снимаем соответствующий флаг, включаем диод, выключаем разрешение прерывания по триггеру, включаем разрешение прерывания по переполнению, обнуляем счетчик (можно не делать этот пункт) и изменяем статус диода.

Если диод был включен, делаем все наоборот: снимаем соответствующий флаг, выключаем диод, выключаем разрешение прерывания по переполнению, включаем разрешение прерывания по триггеру и изменяем статус диода.

Стоит помнить, что счетчик не останавливается, если не выключить таймер, однако, при прерывании по переполнению он перезагружается (обновляется регистр CNT), а при прерывании по триггеру обновления не происходит, поэтому мы его и обнуляем.

Получим такой обработчик прерываний:

void TIM4_IRQHandler(void){if (StatusDiode == 0){    TIM4->SR &= ~TIM_SR_TIF;    GPIOB->ODR |= GPIO_ODR_ODR_15;         // Led red on    TIM4->DIER &= ~TIM_DIER_TIE;           // Trigger interrupt disable    TIM4->DIER |= TIM_DIER_CC2IE;          // Capture/Compare 2 interrupt enable    TIM4->CNT = 0;    StatusDiode = 1;}else{    TIM4->SR &= ~TIM_SR_CC2IF;    GPIOB->ODR &= ~GPIO_ODR_ODR_15;        // Led red off    TIM4->DIER &= ~TIM_DIER_CC2IE;         // Capture/Compare 2 interrupt disable    TIM4->DIER |= TIM_DIER_TIE;            // Trigger interrupt enable    StatusDiode = 0;}}
Полный код для приемника ИК сигнала
#include main.hvoid Timer_Init_Receiver(void);int main(void){   RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6;      // MSI 4.194 MHz enable  GPIOB->MODER |= GPIO_MODER_MODER15_0;     // PB15 output mode   Timer_Init_Receiver();   while(1)   {   }}void Timer_Init_Receiver(void){//Settings for GPIO PB7RCC->AHBENR |= RCC_AHBENR_GPIOBEN;           // GPIO port B clock enableGPIOB->MODER |= GPIO_MODER_MODER7_1;         // Alternative function mode enableGPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speedGPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;         // pull-up PB7GPIOB->AFR[0] |= 0x20000000;                 // Pin PB7 TIM4 alternative function AF2 enable//Settings for TIM4RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;          // TIM4 clock enableTIM4->PSC = 9;                                 // Prescaler valueTIM4->ARR = 4200;                              // Auto-reload valueTIM4->CCR2 = 4200;                             // Capture/Compare 2 valueTIM4->CCMR1 &= ~TIM_CCMR1_OC2M;              // Frozen mode enableTIM4->CCMR1 &= ~TIM_CCMR1_CC2S;              // Output modeTIM4->CCER &= ~TIM_CCER_CC2NP;               // This bit is used in conjunction with CC2P.TIM4->CCER |= TIM_CCER_CC2P;                 // Inverted/falling edgeTIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2TIM4->SMCR |= TIM_SMCR_SMS_2;                // Reset modeTIM4->DIER |= TIM_DIER_TIE;                  // Trigger interrupt enableTIM4->CR1 |= TIM_CR1_CEN;                    // TIM4 enableNVIC_EnableIRQ(TIM4_IRQn);                   // TIM4 global Interrupt enable}void TIM4_IRQHandler(void){if (StatusDiode == 0){    TIM4->SR &= ~TIM_SR_TIF;    GPIOB->ODR |= GPIO_ODR_ODR_15;           // Led red on    TIM4->DIER &= ~TIM_DIER_TIE;             // Trigger interrupt disable    TIM4->DIER |= TIM_DIER_CC2IE;            // Capture/Compare 2 interrupt enable    TIM4->CNT = 0;    StatusDiode = 1;}else{    TIM4->SR &= ~TIM_SR_CC2IF;    GPIOB->ODR &= ~GPIO_ODR_ODR_15;          // Led red off    TIM4->DIER &= ~TIM_DIER_CC2IE;           // Capture/Compare 2 interrupt disable    TIM4->DIER |= TIM_DIER_TIE;              // Trigger interrupt enable    StatusDiode = 0;}}

Заключение

Таким образом, разработали датчик движения, основанный на работе пересечения каким-либо объектом ИК луча. Система состоит из двух устройств, имеет минимум элементов, проста в реализации, имеет низкую стоимость и высокое быстродействие. При этом ядро МК свободно и может использоваться для других нужд.

Подробнее..

Как влияют помехи на ИК приемник

18.12.2020 08:10:10 | Автор: admin

Приветствую всех, эта короткая статья о влиянии помех на работу ИК приемника. В данном исследовании в качестве такого устройства используется TSOP4856. В этой статье вы узнаете: какие помехи бывают для данного типа устройств, и какое влияние они оказывают.

Следует сразу отметить, что дання статья не претендует на истину в последней инстанции, а только предоставляет читателю оценку возможного влияния помех на ИК приемник. Приятного чтения. Начинаем!

Оглавление:

Описание ИК диода TSAL6200 и ИК приемника TSOP4856

Работа ИК диода и ИК приемника

Помехи для ИК приемника

Исследование влияния солнечного света и люминесцентного излучения на работу ИК приемника

Заключение

Описание ИК диода TSAL6200 и ИК приемника TSOP4856

ИК диод TSAL6200 полупроводниковый диод, излучающий волны инфракрасного спектра.

Внешний вид ИК диода представлен ниже на картинке.

TSAL6200TSAL6200

Некоторые его характеристики: длина волны, излучаемой ИК диодом, равна 940 нм. Максимальный прямой постоянный ток не более 100 мА. Импульсный ток не более 1.5 А. Мощность излучения до 40 мВ. Ширина ДН равна 34 градусам.

ИК приемник TSOP4865 миниатюрный ИК приемный модуль, у которого PIN диод и усилитель собраны в свинцовом каркасе, эпоксидный корпус содержит ИК фильтр. Внешний вид ИК приемника представлен ниже на картинке.

TSOP4856TSOP4856

Некоторые его характеристики: длина волны принимаемого ИК сигнала 940 нм. Необходимая частота модуляции 56 кГц. Минимальная освещенность 0.12 мВт/м2. Максимальная 50 Вт/м2. Ширина ДН 90 градусов. Эти устройства работают в паре.

Работа ИК диода и ИК приемника

При протекании тока через диод TSAL6200 излучается ИК сигнал с длиной волны 940 нм. Это излучение модулируется меандром с частотой 56 кГц. Передаются пачки таких импульсов со скважностью равное не менее 4.

Эти пачки принимается устройством TSOP4856. Его функциональная схема представлена на слайде.

Функциональная схема ИК приемника TSOP4856Функциональная схема ИК приемника TSOP4856

где 1 - OUT; 2 - GND; 3 - +Vпит; ВФ входной фильтр; АРУ автоматическая регулировка усиления; ПФ полосовой фильтр.

Через PIN диод начинает протекать ток, соответствующий интенсивности принимаемого ИК сигнала. Схема автоматической регулировки усиления (АРУ) усиливает этот ток. Далее принимаемый сигнал фильтруется полосовым фильтром (ПФ) и демодулируется. Пока принимается одна пачка, на выходном выводе OUT приемника низкое значение напряжения, как только на входе нет импульсов, приемник поднимает выходной вывод к напряжению питания.

Далее представлены временные диаграммы данного процесса.

Временные диаграммы примо-передачи ИК сигналаВременные диаграммы примо-передачи ИК сигнала

Сверху показан процесс происходящий на ИК диоде, снизу - на ИК приемнике. Слева рассматривается процесс приемо-передачи в масштабе одной пачки, а справа - в масштабе нескольких пачек.

Стоит заметить, что просто передавать ИК сигнал без модуляции 56 кГц не получится, т.к. полосовой фильтр ИК приемника настроен как раз на эту частоту. Также не получится передавать непрерывный меандр с этой частотой в 56 кГц, так как система АРУ будет занижать в таком случае коэффициент усиления (это сделано для устранения постоянных помех). Т.е. обязательно нужно передавать пачки импульсов, а с какой частотой будут передаваться эти пачки не важно, главное, чтоб скважность между ними была не менее 4.

Помехи для ИК приемника

Помехами для TSOP4856 являются:

- солнечный свет;

- свет от вольфрамовых ламп;

- излучение от люминесцентных ламп с электронными балластами;

- Wi-Fi 2,4 ГГц и 5 ГГц.

В данной работе рассматривается влияние солнечного света и излучение люминесцентных ламп.

Рассмотрим график чувствительности в зависимости от окружающей освещенности, взятый из документации на TSOP4856.

График зависимости чувствительности ИК приемника TSOP4856График зависимости чувствительности ИК приемника TSOP4856

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

Следует добавить, что чувствительность ИК приемника также зависит от амплитуды пульсаций источника питания, от величины напряжения питания, от температуры и от длины волны ИК сигнала. Более подробно с этими параметрами можно ознакомиться в технической документации.

В нашем случае все эти параметры имеют рабочие значения: пульсация источника питания минимальна, напряжение питания 3.3 В, температура 25 градусов по Цельсию, длина волны 940 нм.

Исследование влияния солнечного света и люминесцентного излучения на работу ИК приемника

Экспериментальная установка состоит из следующих элементов:

- передатчик ИК сигнала;

- приемник ИК сигнала;

- измерительная рулетка;

- фотодиод ФД-24К;

- квадрантный фотодиод QPD150;

- мультиметр;

- переходник USB-UART;

- ноутбук.

У квадрантного фотодиода QPD150 все фазовые выводы соединены. Измеряется суммарное напряжение, вырабатываемое фотодиодом при его освещении.

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

Передатчик ИК сигнала формирует пачку из 20 импульсов, частота импульсов 56 кГц. Амплитуда импульсов тока, проходящих через ИК диод TSAL6200, составляет 20 мА, что соответствует, примерно, 8 мВт мощности излучения.

Излучение пачки происходит раз в секунду. Если пачка принята, то приемник ИК сигнала выдает сообщение на ноутбук о регистрации этой пачки импульсов.

Порядок проведения эксперимента: измеряется дальность приемо-передачи ИК сигнала для двух случаев: принятие 10 из 10 импульсов подряд и 0 из 10 импульсов, а также измеряются напряжения на ФД-24К и QPD150.

Варианты экспериментов:

- в полной темноте;

- при освещении люминесцентной лампой сверху на потолке в помещении;

- при освещении люминесцентной лампой прямо перед приемником в помещении;

- при освещении солнечным светом ИК приемник сзади сверху;

- при освещении солнечным светом ИК приемник спереди сверху.

В таблице ниже приведены результаты исследования влияния помех на работу ИК приемника TSOP4856.

Ниже представлен график зависимости дальности приемо-передачи от мощности помехи для различных типов помех. По вертикали средняя мощность помех в относительных единицах, так как измерить или вычислить реальную принимаемую мощность ИК приемником TSOP4856 проблематично. По горизонтали дальность приемо-передачи в метрах. Левая крайняя точка отрезков значение дальности при приеме 10 из 10 импульсов, а правая крайняя точка значение дальности при приеме 0 из 19 импульсов, т.е. данные отрезки дистанции ухудшения качества приема сигнала от 100 до 0 %. В таблице представлены относительные ухудшения характеристик относительно эксперимента "в полной темноте" в процентах,

Из графика видно, то с увеличением мощности помехи не только уменьшается дальность приемо-передачи, но и дистанция ухудшения качества приема сигнала от 100% до 0% становится короче.

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

Заключение

Из полученных данных можно сделать следующий выводы:

1) чем сильнее помеха по мощности, тем меньше дальность приемо-передачи ИК сигнала;

2) влияние помехи на качество приема пропорционально мощности помехи (чем меньше помеха по мощности, тем длиннее отрезки, т.е. качество приема ИК сигнала медленнее ухудшается с увеличением расстояния);

3) разные типы помехи имеют разное влияние на работу TSOP4856.

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

Надеюсь статья оказалась полезной. Спасибо за внимание!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru