Во многих датчиках в качестве аварийного сигнала используется звуковое оповещение. Давайте тоже научим МК издавать такой сигнал. Исходные данные: МК MSP430FR2433 Излучатель звука - пьезоэлемент. Напряжение питания - 3-3.3в Минимизация токов потребления. 1. Схемотехника. Как подключить пьезоэлемент, чтобы получить максимальное акустическое давление при минимальном токе и минимальном напряжении? Во-первых, необходимо раскачивать пьезоизлучатель н частоте механического резонанса (всего резонансов у пьезоизлучателей - три). Во-вторых, необходимо акустическое оформление. В нашем случае я обойдусь просто диффузором, приклеенным к излучателю. Ну и третье - электрическое подключение. Самый верный способ при малом напряжении питания - автотрансформация. Способ хорош, но требует расчета и изготовления трансформатора. Поэтому пойдем другим путем. Применим мостовое включение пьезоизлучателя к МК. Да,теряем две ноги, но зато получаем удвоенный размах сигнала. 2. Форма сигнала. Сигнал будет напоминать прерывистое щебетание. Вот его осциллограмма: 3. Алгоритм программы. По осциллограмме четко прослеживаются следующие состояния: генерация меандра частотой 4кГц, пауза в генерации меандра, пауза между генерациями. Так и напрашивается конечный автомат. А так как периоды чередования состояний автомата заранее известны, то сделаем автоматический секвенсор состояний. 4. Реализация. В нашем МК есть все для того, чтобы реализовать задуманное аппаратно. Генерацию меандра будем осуществлять на таймере TA0. Для этого воспользуемся двумя его компараторами. А вот для отсчета периодов состояний конечного автомата будем использовать таймер RTC. Таким бразом, большую часть времени мы будем спать просыпаясь лишь только для того, чтобы сменить состояние автомата.
Лучше бы начали с инструкции как к нему провода присоединять. Или вы верите, что на форуме найдётся больше трёх человек, которые хотя бы слышали что это.
Он знает места в штатах, где за 4.30 можно взять. А продолжение где? А то пока только мы тут щебечем.
Тут вся загвоздка в трансформаторе, хрен найдешь такой, у кого есть радиоприемник Юность? А ТС нам пост образовательный пишет, так что ждём лектора.
Мне влом под такую хрень 1200 платить.У меня Мурка на звонке играла на Тини13.Я лучше TTGO Esp32 с дисплеем за эту цену куплю
Все вы о материальном... А человек рассказывает как он новые вершины покоряет. Вот смотри, в альпинизме, считай, никакой практической пользы, а люди этим увлекаются. Так и здесь - создам звоночек на никому неизвестной плате. Это уважаемо.
5. Выбор источника тактирования. Серия МК MSP430 обладает весьма развитой системой тактирования. Для серии MSP430FR2xx структурная схема этой системы представлена на рисунке ниже. MCLK - это главный тактовый сигнал. От него тактируется ядро. SMCLK - это дополнительный тактовый сигнал. VLOCLK - это тактовый сигнал от микромощного внутреннего осциллятора VLO, который работает на частоте около 10 кГц. XT1CLK - это тактовый сигнал от внешнего осциллятора. Он может быть как низкочастотным (например, при работе от часового кварца), так и высокочастотным. Резонаторы для этого осциллятора могут быть как керамическими, так и кварцевыми. ACLK - дополнительный источник тактирования. MODLOCK - тактовый сигнал от осциллятора MODO. В MSP430FR2433 не представлен. Теперь об осцилляторах. DCO - это внутренний цифровой осциллятор с фазовой стабилизацией частоты. К нему можно подключить источники тактовых сигналов MCLK и SMCLK (по умолчанию они к нему и подключены). По умолчанию он работает на частоте 2 МГц. REFO - внутренний осциллятор с фазовой стабилизацией частоты. Типовая частота 32768 Гц. К этому осциллятору можно подключить все источники, кроме VLOCLK и MODCLK. Чтобы определиться, какой таймер к какому источнику подключить, необходимо вспомнить про наше требование о минимизации токопотребления. Начнем с режима сна. Всего их 6. Но самые интересные это LPM3, LPM4 и LPM3.5. LPM4.5 нам не интересен - там не работает вообще ничего.Смотрим таблицу из даташита. Сразу договоримся - система SVS у нас выключена. Смотрим: режим сна LPM3 с включенным внешним осциллятором и запущенным таймером RTC - 1.13 мкА. Это много. Тоже самое, но с VLO - 0.98 мкА. Уже лучше. LPM4: данных о токе с запущенными осцилляторами даташит не приводит, но можно ожидать, что VLO с запущенным RTC в этом режиме будет потреблять меньше, чем в LPM3. На этом и остановимся. Таймер TA0 мы можем подключить либо к ACLK, либо к SMCLK. Я пока выберу SMCLK. Позже сравним его с ACLK.
Покодим? Определяем состояния нашего конечного автомата Код (C++): enum state_enum { pwm, pause, sleep } volatile state = pwm; Состояния pwm и pause - это состояние генерации меандра и небольшая пауза между этими генерациями. Для входа в состояние sleep мы будем считать количество переходов pwm->pause. Для этого определим константу: Код (C++): #define CNT_TWEET 10 и счетчик: Код (C++): volatile uint8_t cnt_tweet; Отсчет периодов, в течение которых мы будем проводить в состояниях, будет осуществлять таймер RTC. Тактируем его от VLOCLK с частотой 10 кГц. У таймера всего одно прерывание по переполнению счетчика - по нему и будем определять конец периода текущего состояния. Чтобы было удобно отсчитывать интервалы, таймер RTC включим через делитель на 100. Таким образом, таймер RTC будет тикать каждые 0.1 сек. Соответственно, определяем ещё константы: Код (C++): #define FRQ_TWEET 2 #define PAUSE_TWEET 40 Максимальное значение счетчика определяется регистром RTCMOD. Этот регистр буферизированный. Значение из буфера в рабочий (так называемый теневой) регистр попадает тогда, когда счетчик таймера сбрасывается (либо принудительно из программы, либо по переполнению). Теперь запишем наш секвенсор состояний. Целиком функция выглядит так: Код (C++): inline void Set_State(void) { switch (state) { case pwm: TA0CTL = TASSEL__SMCLK | MC__UP | TACLR; state = pause; break; case pause: TA0CTL = MC__STOP; if (--cnt_tweet) { state = pwm; } else { state = sleep; RTCMOD = PAUSE_TWEET; } break; case sleep: cnt_tweet = CNT_TWEET; RTCMOD = FRQ_TWEET; state = pwm; break; } } Что же здесь происходит? При первом вызове данной функции мы находимся в состоянии pwm, т.е. генерации меандра. Поэтому при входе в обработчик этого состояния мы запускаем таймер TA0 в режим Up_Mode (см. рисунок ниже) и переключаемся в режим короткой паузы pause. В этом режиме мы выключаем таймер, при этом генерация меандра прекращается. Затем инкрементируем счетчик переходов pwm -> pause чтобы выяснить, наступил ли момент для "большой перемены" (sleep). Если наступил, то записываем в регистр RTCMOD значение константы, соответствующей желаемому периоду "большой перемены". На самом деле здесь программа выполняется так: в теневом регистре RTCMOD ещё лежит значение короткого периода для состояний pwm и pause. Значение периода "большой переменной" запишется в теневой регистр только после сброса счетчика RTCMOD. А произойдет это тогда, когда программа окажется в обработчике sleep. Нам такой сдвиг во времени никак не мешает и экономит выполнение одной инструкции - сброс счетчика таймера RTC. В обработчике состояния "большой перемены" мы взводим счетчик переходов pwm -> pause и записываем в RTC значение короткого периода. Вызывается эта функция-секвенсор в обработчике прерывания RTC.
Главный цикл выглядит так: Код (C++): int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT // Configure GPIO P1DIR = BIT1 | BIT2; P1SEL1 = BIT1 | BIT2; PM5CTL0 &= ~LOCKLPM5; // Configure Timer_A TA0CCR0 = 256; TA0CCTL1 = OUTMOD_2; // Output mode Capture/Compare1 toggle/reset TA0CCR1 = MEANDR; TA0CCTL2 = OUTMOD_6; // Output mode Capture/Compare2 toggle/set TA0CCR2 = MEANDR; TA0CTL = TASSEL__SMCLK | MC__UP | TACLR;// | TAIE; // Configure RTC RTCMOD = FRQ_TWEET; RTCCTL = RTCSS__VLOCLK | RTCPS__100 | RTCIE | RTCSR; // RTC period ~0.1s, enable interrupt __bis_SR_register(LPM4_bits | GIE); // Enter LPM4, enable interrupts // __no_operation(); // For debugger } Первые две строчки переводят пины МК на выход и подключают их к выходам компараторов таймера TA0. Далее следует настройкка таймера TA0. Код (C++): TA0CCR0 = 256; Здесь мы указываем максимальное значение счетчика таймера, после которого идет его сброс. Посмотрим на картинку из даташита: Откуда видим, что чтобы получить разнополярные импульсы на выходе двух наших компараторов, необходимо первый заинициализировать как Output Mode 2, второй как Output Mode 6. Что мы и делаем: Код (C++): TA0CCTL1 = OUTMOD_2; // Output mode Capture/Compare1 toggle/reset TA0CCR1 = MEANDR; TA0CCTL2 = OUTMOD_6; // Output mode Capture/Compare2 toggle/set TA0CCR2 = MEANDR; Максимальная звуковая отдача пьезоэлемента будет при подаче на него меандра. Поэтому в регистры сравнения записываем половину от максимального счета счетчика таймера. Далее конфигурируем таймер TA0 на тактирование от SMCLK, задаем режим счета - считать вверх до значения регистра TA0CCR0 и далее сброс. Чтобы сменить режим счета, необходимо таймер сбросить. Для этого необходимо взвести бит TACLR: Код (C++): TA0CTL = TASSEL__SMCLK | MC__UP | TACLR;// | TAIE; Далее инициализируем таймер RTC. Задаем значение регистра RTCMOD, по достижении значения которого таймер сбрасывается и формирует прерывание. Также задаем источник тактирования, включаем делитель со значением 100, разрешаем формирование прерывания и сбрасываем таймер. Код (C++): // Configure RTC RTCMOD = FRQ_TWEET; RTCCTL = RTCSS__VLOCLK | RTCPS__100 | RTCIE | RTCSR; // RTC period ~0.1s, enable interrupt Значение делителя 100 выбрано для облегчения рассчета периодов сброса. При таком значении делителя счетчик таймера будет тикать примерно каждые 0.1 сек. Здесь нет цикла while(). Почему? Всё просто. Последняя инструкция - это режим сна. Когда MCU выходит из него (по прерыванию), значение регистра SR целиком помещается в стек, а сам MCU переходит в активный режим работы (если нет других указаний по смене текущего режима). После завершения обработки процедуры прерывания, значение регистра SR копируется из стека и MCU возвращается в тот режим, который был до прерывания. Таким образом, чтобы сменить текущий режим работы, необходимо явно это указать в программе. Ну и в обработчике прерывания мы просто вызываем рассмотренную раннее функцию: Код (C++): #pragma vector=RTC_VECTOR __interrupt void RTC_ISR(void) { switch (RTCIV) { case RTCIV_NONE: break; case RTCIV_RTCIF: Set_State(); break; } } Код полностью лежит здесь https://github.com/dashkova/MSP430FR/tree/master/MSP430FR2433/tweeter
Программируется он по двум проводам. Не считая Vss и Vcc. Я уже писал, какие цели преследуются мной. хотел было взять у китайцев. Но у китайцев дороже, чем на маузере. А на маузере дороже, чем на сайте TI. А у них там ещё и скидка это очень громоздко, не энергоэффективно, не управляемо, не современно, дорого. без меня справились https://store.arduino.cc/usa/nano-every ATMega4809 - это полноценная версия аттиньки817, которую я здесь представлял.