Управление мотором постоянного тока с помощью одного транзистора

Тестирование работы схемы

Сделайте все необходимые соединения в схеме, загрузите программу в плату Arduino и подайте питание на контроллер ESC. Убедитесь в том, что ваш BLDC двигатель надежно закреплен, иначе он будет прыгать во время вращения. Когда вы подадите питание на контроллер ESC вы услышите приветственный тон и он будет издавать этот звук до тех пор пока не поступит управляющий сигнал заданного уровня (в заданных границах). Начните постепенно вращать ручку потенциометра чтобы на его выходе напряжение стало отличным от 0, и этот звук прекратится. Это будет означать, что вы подали на контроллер ШИМ сигнал минимально допустимого уровня. При дальнейшем вращении ручки потенциометра двигатель начнет медленно вращаться. При дальнейшем повороте ручки потенциометра и увеличении напряжения на его выходе скорость вращения двигателя будет увеличиваться. Когда напряжение достигнет верхней допустимой границы двигатель остановится. В дальнейшем вы можете повторить весь этот процесс заново.

Некоторые термины, используемые в тематике BLDC и ESC

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

Braking (торможение) – определяет насколько быстро BLDC двигатель может остановить свое вращение. Это особенно актуально для летающих средств (дронов, геликоптеров и т.д.) поскольку они вынуждены часто изменять количество оборотов двигателя в минуту чтобы маневрировать в воздухе.

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

Motor Direction (направление вращения двигателя) – обычно направление вращения BLDC двигателей не изменяется в процессе эксплуатации, однако во время сборки и тестирования работы изделия может потребоваться изменение направления вращения двигателя, обычно это можно сделать просто поменяв местами любые два провода двигателя.

Low Voltage Stop (остановка при низком напряжении питания). Обычно BLDC двигатели калибруют так, чтобы при одинаковом уровне управляющего воздействия скорость его вращения была постоянной. Однако этого трудно достигнуть потому что со временем напряжение питающей батареи уменьшается. Чтобы предотвратить это обычно контроллеры ESC программируют таким образом чтобы они останавливали работу BLDC двигателя когда напряжение питающей батареи опускается ниже определенной границы. Особенно эта функция полезна при использовании BLDC двигателей в дронах.

Response time (время отклика, время реакции, время ответа). Означает способность двигателя быстро изменять скорость вращения при изменении управляющего воздействия. Чем меньше время реакции, тем лучше контроль над двигателем.

Advance (движение вперед). Эта проблема является своеобразной «ахиллесовой пятой» для BLDC двигателей. Все BLDC двигатели имеют хотя бы небольшой подобный баг. Эта проблема вызвана тем, что когда катушка статора запитана ротор движется вперед поскольку на нем есть постоянный магнит. И когда управляющее напряжение с этой катушки снимают (чтобы подать его на следующую катушку) ротор продвигается вперед немного дальше чем предусмотрено логикой функционирования двигателя. Это нежелательное продвижение двигателя вперед в англоязычной литературе называют “Advance” и оно может приводить к нежелательным вибрациям, нагреву и шуму при работе двигателя. Поэтому хорошие контроллеры ESC стараются по возможности устранить этот эффект в работе BLDC двигателей.

Улучшение связи

Предложено Саней Чёрным. Есть предложение по улучшению помехоустойчивости работы на дальние дистанции. К примеру имеем 30 устройств на линии. У каждого подтяжка к + внешняя по 100К. В сумме считаем это как параллельное соединение резисторов и при передаче LOW(0-ка) нужно пересилить 3.45кОм это 1.45мА на вывод. Все вроде как хорошо, но если в этом же кабеле( к примеру ПВС4*1 – четырехжильный кабель с сечением 1мм^2) рядом идет 220VAC, то на линию GND Arduin-ы будет идти нехилая наводка, которая на длине в 100м(а это всего 50м от передатчика, т.к. 50м провод данных и 50м провод земли) приведет к целому ряду ложных приемов пакетов. Поэтому предлагаю схему, которая позволит каждому устройству на линии при получении LOW дублировать его. Это влечет за собой уменьшение скорости передачи данных. Т.к. каждая оптопара имеет задержку в 4мкс. А на 30 последовательно соединенных устройствах это 0.12мс.

Использование интерфейса SPI в Arduino

Перед тем как начать обмен данными между двумя платами Arduino по протоколу SPI давайте рассмотрим основные принципы работы с библиотекой SPI (SPI library) в Arduino IDE.

Для того чтобы подключить использование этой библиотеки в программе применяется простая команда #include<SPI.h>. Далее для задействования протокола SPI в плате Arduino необходимо выполнить следующую последовательность шагов:

1. SPI.begin()

Инициализирует шину SPI при помощи установки режимов работы контактов SCK, MOSI и SS на вывод данных, подачи на контакты SCK и MOSI напряжения низкого уровня (low), а на контакт SS – напряжения высокого уровня (high).

2. SPI.setClockDivider(divider)

Используется для установки делителя (коэффициента деления) для сигнала синхронизации SPI по отношению к тактовой частоте микроконтроллера в плате Arduino. Можно использовать делители 2, 4, 8, 16, 32, 64 или 128.

Обозначение делителей:

• SPI_CLOCK_DIV2
• SPI_CLOCK_DIV4
• SPI_CLOCK_DIV8
• SPI_CLOCK_DIV16
• SPI_CLOCK_DIV32
• SPI_CLOCK_DIV64
• SPI_CLOCK_DIV128

3. SPI.attachInterrupt(handler)

Включает режим прерываний в ведомом (slave) устройстве. Прерывание будет возникать каждый раз, когда ведомое устройство будет принимать данные от ведущего (master) устройства.

4. SPI.transfer(val)

Эта функция используется для одновременного приема и передачи данных между ведущим и ведомым.

Защита от помех AC

Момент выключения

Напряжение в сети является синусоидой, которая 100 раз в секунду пересекает значение 0. Если выключить нагрузку в тот момент, когда напряжение в сети равно нулю – это сильно уменьшит выброс. Для этих целей проще всего использовать твердотельные реле (SSR) с детектором нуля (Zero-Crossing Detector): такие реле сами отключают и включают нагрузку в нужный момент. Детектор нуля есть почти во всех моделях SSR, но лучше уточнить в документации.

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

Искрогасящие цепи AC

Выбросы ЭДС после отключения нагрузки присутствуют также и в цепях переменного тока, особенно если нагрузка может быть выключена в случайный момент времени. Выброс напряжения может проявляться искрой между контактами в момент отключения нагрузки, что плохо для контактов и опасно в целом. Для гашения этих выбросов используются снабберные цепи из резистора и конденсатора.

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

Вольты, амперы, ёмкость

Начнем с базовых понятий мира электричества: Вольты и Амперы (более подробно про это читай в этом уроке). Вольты – напряжение, оно же разность потенциалов. Напряжение задаёт источник питания, например батарейка или блок питания. Амперы – сила тока в цепи, показывает с какой силой “расходуется” электрическая энергия. Ток в цепи задаёт потребитель. (Примечание: описанное выше справедливо для источника напряжения, коим является любая батарейка/аккумулятор или обычный блок питания. Источником тока может быть специальное зарядное устройство или светодиодный драйвер, от них питать предназначенную для источника напряжения схему нельзя – сразу сгорит).

Потребляемую и запасаемую энергию принято считать в Ампер*часах, работает это следующим образом: допустим, ёмкость аккумулятора составляет 1 А*ч (Ампер*час). Это означает, что такой аккумулятор сможет отдавать ток с силой 1 Ампер в течение одного часа, полностью при этом разрядившись. Если ток в цепи будет 0.5 А – аккумулятора хватит на 1 А*ч / 0.5 А == 2 часа. Плата Ардуино потребляет в районе 24 мА, то есть тот же условный аккумулятор сможет питать её в течение 1000 мА*ч /24 мА ~ 42 часов. При параллельном подключении потребителей, как это обычно бывает в схеме, ток потребления суммируется. Если добавить в “схему” из предыдущего расчёта дисплей с подсветкой, который будет потреблять условно ещё 30 мА, то такая схема проработает от того же аккумулятора 1000 мА*ч / (24+30 мА) ~ 18.5 часов. 

Объяснение программы для Arduino

Полный текст программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.

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

Arduino

#include <Arduino.h>

1 #include <Arduino.h>

Далее в программе мы должны инициализировать все используемые контакты: сенсорный датчик подключен к контакту A5, реле – к контакту A4. Для работы программы также используется встроенный в плату светодиод, подключенный к контакту 13.

Arduino

/*
* Pin Description
*/
int Touch_Sensor = A5;
int LED = 13;
int Relay = A4;

1
2
3
4
5
6

/*
* Pin Description
*/

intTouch_Sensor=A5;

intLED=13;

intRelay=A4;

Далее в функции void setup() нам необходимо задать режимы работы используемых контактов.

Arduino

/*
* Pin mode setup
*/
void setup() {
pinMode(Touch_Sensor, INPUT);
pinMode(LED, OUTPUT);
pinMode(Relay, OUTPUT);
}

1
2
3
4
5
6
7
8

/*
* Pin mode setup
*/

voidsetup(){

pinMode(Touch_Sensor,INPUT);

pinMode(LED,OUTPUT);

pinMode(Relay,OUTPUT);

}

Далее объявим две переменные целого типа: переменная ‘condition’ используется для хранения состояния сенсорного датчика (нажат он или нет). Переменная ‘state’ используется для хранения состояния светодиода и реле – включены они или выключены.

Arduino

/*
* Programme flow Description
*/
int condition = 0;
int state = 0; //To hold the switch state.

1
2
3
4
5

/*
* Programme flow Description
*/

intcondition=;

intstate=;//To hold the switch state.

Сенсорный датчик во время нажатия (прикосновения) изменяет свое состояние с логического 0 на логическую 1. Мы состояние датчика считываем с помощью функции digitalRead() и сохраняем его в соответствующей переменной. Когда состояние датчика равно 1 состояния светодиода и реле изменяются. Тем не менее, для устранения эффекта дребезга контактов в программе используется соответствующая задержка (debounce delay). Эта задержка delay(250) используется для распознавания одиночного нажатия на датчик.

Arduino

void loop() {
condition = digitalRead(A5); // Reading digital data from the A5 Pin of the Arduino.
if(condition == 1){
delay(250); // debounce delay.
if(condition == 1){
state = ~state; // Changing the state of the switch.
digitalWrite(LED, state);
digitalWrite(Relay, state);
}
}
}

1
2
3
4
5
6
7
8
9
10
11

voidloop(){

condition=digitalRead(A5);// Reading digital data from the A5 Pin of the Arduino.

if(condition==1){

delay(250);// debounce delay.

if(condition==1){

state=~state;// Changing the state of the switch.

digitalWrite(LED,state);

digitalWrite(Relay,state);

}

}

}

При тестировании проекта соблюдайте меры предосторожности при работе с напряжением сети переменного тока (220 В)

Потребление компонентов схемы

Если в устройстве помимо МК есть какие-то другие модули/датчики/дисплеи/микросхемы, то больший вклад в потребление энергии будут вносить именно они, потому что МК можно погрузить в сон, а их – не всегда. Логично, что для максимальной экономии энергии нужно держать все компоненты в полностью отключенном состоянии и включать только на период активной работы: датчики – на время опроса, дисплеи и подсветки – на время взаимодействия с человеком, и тому подобное.

  • Некоторые железки имеют очень удобный пин EN – enable, позволяющий логическим уровнем с МК полностью включать и выключать компонент, что позволяет очень просто управлять его состоянием.
  • Некоторые микросхемы имеют встроенный режим энергосбережения, который можно активировать из программы (например, передав нужную команду по интерфейсу связи). Информацию нужно искать в даташите или библиотеке на конкретную железку.
  • Если таких возможностей у железки нет – всегда можно просто разорвать ей питание при помощи транзистора или оптопары. Электромеханическое реле использовать не рекомендуется, т.к. оно само потребляет приличный ток.
  • Маломощные (до 20 мА) компоненты можно питать напрямую от пинов МК, что ещё больше упрощает задачу по управлению питанием. Примечание: у “Ардуиновских” AVR весьма приличный запас по току – в районе 40 мА на пин, но на таком токе напряжение просаживается и работа “железки” может стать нестабильной, поэтому не рекомендуется подключать на пин нагрузку выше 20 мА. К слову, у других процессоров (STM32, esp8266) максимальный ток с пинов на порядок ниже (2-5 мА) и что-то от них питать в принципе невозможно.
  • Большинство “интерфейсных” микросхем при сбросе питания будут требовать повторной инициализации. У того же например lcd дисплея после отключения и включения питания нужно вызвать метод , чтобы дисплей начал реагировать на остальные команды.

Если система измеряет напряжение питания выше 5V (напряжение батареи аккумуляторов), то делитель напряжения должен быть рассчитан оптимально, чтобы не тратить ток в холостую. Об этом мы говорили в уроке про аналоговые входы.

Общие принципы ШИМ

Метод осуществления ШИМ показан на следующем рисунке.

Если на представленном рисунке кнопка нажата, то двигатель начнет вращение и он будет вращаться до тех пор пока кнопка не будет отжата. Эта ситуация происходит если кнопка будет нажата постоянно – верхний график на представленном рисунке. Если же мы будем нажимать кнопку только в течение 8 мс из всего цикла в 10 мс, то в этом случае двигатель уже не будет в полной мере получать все напряжение батареи 9 В – в этом случае среднеквадратичная величина напряжения, получаемого двигателем, будет около 7 В. Соответственно, двигатель по сравнению с первым случаем (когда кнопка нажата постоянно) будет вращаться с меньшей скоростью. Поэтому цикл занятости (который еще называют коэффициентом заполнения ШИМ) в этом случае составит время включенного состояния/(время включенного состояния + время выключенного состояния) = 8/(8+2)=80%.

В следующих рассмотренных на рисунке случаях кнопка будет находиться в нажатом состоянии еще меньше чем в рассмотренном случае (80%). Соответственно, среднеквадратичная величина напряжения, получаемого двигателем, будет составлять еще меньшую величину, поэтому и скорость вращения двигателя также уменьшится. Это уменьшение скорости вращения двигателя вследствие уменьшения среднеквадратичной величины напряжения будет происходить до тех пор, пока получаемое двигателем напряжение не станет не достаточным для его вращения. То есть, изменяя величину цикла занятости (коэффициент заполнения ШИМ), можно управлять скоростью вращения двигателя постоянного тока.

Питание “мощных” схем

Резюмируя и повторяя всё сказанное выше, рассмотрим варианты питания проектов с большим потреблением тока.

Питать мощный проект (светодиоды, двигатели, нагреватели) от 5V можно так: Arduino и потребитель питаются вместе от 5V источника питания:

Питать мощный потребитель от USB через плату нельзя, там стоит диод, да и дорожки питания тонкие:

Что делать, если всё-таки хочется питать проект от USB, например от powerbank’а? Это ведь удобно! Всё очень просто:

Если есть только блок питания на 12V, то у меня плохие новости: встроенный стабилизатор на плате не вытянет больше 500 мА:

Но если мы хотим питать именно 12V нагрузку, то проблем никаких нет: сама плата Arduino потребляет около 20 мА, и спокойно будет работать от бортового стабилизатора:

Ожидание ответа (v1.1)

Метод работает по такой же логике, как предыдущий, но не блокирует выполнение кода. Логика такая: вручную отправляем реквест и при помощи можем дождаться ответа и попытаться достучаться до приёмника, автоматически отправляя новые запросы через таймаут миллисекунд. Количество попыток ограничено заданным. Метод возвращает статусы:

Код Название Описание
Ничего не делаем
1 Ждём ответа
2 Ответ не получен
3 Получено подтверждение
4 Получены данные

Примеры находятся в examples/GBUS/wait_ack. В примере wait_ack_rx можно закомментировать отправку ответа и в мониторе порта увидеть, как передатчик отправляет несколько запросов перед тем, как выдать ошибку.

Работа схемы и программы

Схема устройства представлена на следующем рисунке.

В отличие от управления серводвигателем с помощью микроконтроллеров AVR в случае использования платы Arduino нам уже нет необходимости вручную устанавливать значения регистров чтобы получить нужную частоту и коэффициент заполнения управляющих сигналов для серводвигателя. Для платформы Arduino для этих целей разработаны специальные библиотеки, с помощью которых эти функции реализуются достаточно просто – необходимо в программе просто подключить заголовочные файлы этих библиотек. В этом случае мы достаточно просто сможем устанавливать позицию сервомотора с помощью сигналов ШИМ.

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

Вначале мы должны установить частоту ШИМ сигнала для управления сервомотором – в данном случае это делается простым подключением заголовочного файла “#include <Servo.h>”. С подключением этого заголовочного файла необходимая частота ШИМ сигнала для управления серводвигателем устанавливается автоматически, кроме этого открываются возможности использования различных функций для простого управления серводвигателем.

После этого мы должны определиться с именем сервомотора, которым будем управлять в программе. Делается это с помощью функции “Servo sg90sevo”, где ‘sg90servo’ – это выбранное имя для нашего сервомотора. Особенно актуально указание имен сервомоторов когда под нашим управлением будет находиться несколько сервомоторов (до 8 для Arduino) – в этом случае удобно их будет различать по данным им именам.

Далее мы должны сообщить Arduino к какому контакту подключен сервомотор, то есть на каком контакте необходимо будет формировать сигнал ШИМ. Мы это будем делать с помощью функции “Sg90.attach(3);”, которая указывает Arduino что сервомотор подключен к контакту PIN3.

Теперь все, что осталось сделать, это указать на какой угол необходимо повернуть ось серводвигателя, это можно сделать с помощью функции “Sg90.write(30);”, которая повернет ось серводвигателя на 30 градусов. В дальнейшем, если нам понадобится повернуть ось серводвигателя на какой-нибудь другой угол, то необходимо воспользоваться командой ”Sg90.write(needed_position_ angle);”. На представленной схеме у нас есть две кнопки, одна из них будет увеличивать угол поворота оси серводвигателя (вращать его против часовой стрелки), а другая – уменьшать (вращать его по часовой стрелке).

Ковка ножа

“Универсальное” электромагнитное реле

Электромагнитное реле является по сути управляемым механическим выключателем: подали на него ток – оно замкнуло контакты, сняли ток – разомкнуло. Контакты являются именно контактами: металлическими “пятаками”, которые прижимаются друг к другу. Именно поэтому такое реле может управлять как нагрузкой постоянного, так и переменного тока. 

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

После изучения данного урока вы сами сможете её составить (транзистор и диод), а сейчас мы поговорим о модулях реле: готовая плата, на которой стоит само реле, а также цепи коммутации, защиты и даже оптическая развязка. Такие модули бывают “семейными” – с несколькими реле на борту. Спасибо китайцам за это! Купить можно на Aliexpress, также смотрите варианты у меня в каталоге ссылок на Али.

Такое реле сделано специально для удобного управления с микроконтроллера: пины питания VCC (Vin, 5V) и GND подключаются к питанию, а далее реле управляется логическим сигналом, поданным на пин IN. С другой стороны стоит клеммник для подключения проводов, обычно контакты подписаны как NO, NC и COM. Это общепринятые названия пинов кнопок, переключателей и реле:

  • COM – Common, общий. Реле является переключающим, и пин COM является общим.
  • NO – Normal Open, нормально открытый. При неактивном реле данный контакт не соединён с COM. При активации реле он замыкается с COM.
  • NC – Normal Closed, нормально закрытый. При неактивном реле данный контакт соединён с COM. При активации реле он размыкается с COM.

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

Важный момент: катушка реле в активном режиме потребляет около 60 мА, то есть подключать больше одного модуля реле при питании платы от USB не рекомендуется – уже появятся просадки по напряжению и помехи:

Такие модули реле бывают двух типов: низкого и высокого уровня. Реле низкого уровня переключается при наличии низкого сигнала (GND) на управляющем пине . Реле высокого уровня соответственно срабатывает от высокого уровня . Какого типа вам досталось реле можно определить экспериментально, а можно прочитать на странице товара или на самой плате. Также существуют модули с выбором уровня:

На плате, справа от надписи High/Low trigger есть перемычка, при помощи которой происходит переключение уровня.

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

  • Ограниченное количество переключений: механический контакт изнашивается, особенно при большой и/или индуктивной нагрузке.
  • Противно щёлкает!
  • При большой нагрузке реле может “залипнуть”, поэтому для больших токов нужно использовать более мощные реле, которые придётся включать при помощи… маленьких реле. Или транзисторов.
  • Необходимы дополнительные цепи для управления реле, так как катушка является индуктивной нагрузкой, и нагрузкой самой по себе слишком большой для пина МК (решается использованием китайского модуля реле).
  • Очень большие наводки на всю линию питания при коммутации индуктивной нагрузки.
  • Относительно долгое переключение (невозможно поставить детектор нуля, читай ниже), при управлении индуктивными цепями переменного тока можно попасть на большой индуктивный выброс, необходимо ставить искрогасящие цепи.

Важный момент связан с коммутацией светодиодных светильников и ламп, особенно дешёвых: у них прямо на входе стоит конденсатор, который при резком подключении в цепь становится очень мощным потребителем и приводит к скачку тока. Скачок может быть настолько большим, что 15-20 Ваттная светодиодная лампа буквально сваривает контакты реле и оно “залипает”! Данный эффект сильнее выражен на дешёвых лампах, будьте с ними аккуратнее (за инфу спасибо DAK).

При помощи реле можно плавно управлять сильно инерционной нагрузкой, такой как большой обогреватель. Для этого нужно использовать сверхнизкочастотный ШИМ сигнал, у меня есть готовая библиотека. Не забываем, что реле противно щёлкает и изнашивается, поэтому для таких целей лучше подходит твердотельное реле, о котором мы поговорим ниже.

Уроки Arduino #8 - управление релеУроки Arduino #8 — управление реле

Устройство и принцип работы транзистора

Транзистором называется полупроводниковый прибор, предназначенный для усиления и генерирования электрических колебаний. Транзисторы являются ключами (кнопками) в сетях с постоянным током. Биполярные транзисторы могут управлять электрической цепью до 50 В, полевые транзисторы могут управлять приборами до 100 В (при напряжении на затворе 5 В). В сетях с переменным током использую реле.

Фото. Устройство полевого и биполярного транзистора

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

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

Объяснение программы для ведомой (Slave) платы Arduino

1. Как и в ведущей плате, первым делом в программе мы должны подключить библиотеку Wire для задействования возможностей протокола I2C и библиотеку для работы с ЖК дисплеем. Также нам необходимо сообщить плате Arduino к каким ее контактам подключен ЖК дисплей.

Arduino

#include<Wire.h>
#include<LiquidCrystal.h>
LiquidCrystal lcd(2, 7, 8, 9, 10, 11);

1
2
3

#include<Wire.h>    
#include<LiquidCrystal.h>      

LiquidCrystallcd(2,7,8,9,10,11);

  1. В функции void setup():

—  мы инициализируем последовательную связь со скоростью 9600 бод/с;

Arduino

Serial.begin(9600);

1 Serial.begin(9600);

— далее мы инициализируем связь по протоколу I2C на контактах A4 и A5

В качестве адреса ведомого мы будем использовать значение 8 – очень важно здесь указать адрес ведомого;. Arduino

Wire.begin(8);

Arduino

Wire.begin(8);

1 Wire.begin(8);

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

Arduino

Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);

1
2

Wire.onReceive(receiveEvent);

Wire.onRequest(requestEvent);

— затем мы инициализируем ЖК дисплей для работы в режиме 16х2, отображаем на нем приветственное сообщение и очищаем его экран через 5 секунд.

Arduino

lcd.begin(16,2); //Initilize LCD display
lcd.setCursor(0,0); //Sets Cursor at first line of Display
lcd.print(«Circuit Digest»); //Prints CIRCUIT DIGEST in LCD
lcd.setCursor(0,1); //Sets Cursor at second line of Display
lcd.print(«I2C 2 ARDUINO»); //Prints I2C ARDUINO in LCD
delay(5000); //Delay for 5 seconds
lcd.clear(); //Clears LCD display

1
2
3
4
5
6
7

lcd.begin(16,2);//Initilize LCD display

lcd.setCursor(,);//Sets Cursor at first line of Display

lcd.print(«Circuit Digest»);//Prints CIRCUIT DIGEST in LCD

lcd.setCursor(,1);//Sets Cursor at second line of Display

lcd.print(«I2C 2 ARDUINO»);//Prints I2C ARDUINO in LCD

delay(5000);//Delay for 5 seconds

lcd.clear();//Clears LCD display

3. Затем нам будут необходимы две функции: одна для события запроса (request event) и одна для события приема (receive event).

Для события запроса:

Эта функция будет выполняться когда ведущий будет запрашивать значение от ведомого. Эта функция будет считывать значение с потенциометра, подключенного к ведомой плате Arduino, преобразовывать его в диапазон 0-127 и затем передавать его ведущей плате.

Arduino

void requestEvent()
{
int potvalue = analogRead(A0);
byte SlaveSend = map(potvalue,0,1023,0,127);
Wire.write(SlaveSend);
}

1
2
3
4
5
6

voidrequestEvent()

{

intpotvalue=analogRead(A0);

byteSlaveSend=map(potvalue,,1023,,127);

Wire.write(SlaveSend);

}

Для события приема:

Эта функция будет выполняться когда ведущий будет передавать данные ведомому с адресом 8. Эта функция считывает принятые значения от ведущего и сохраняет ее в переменной типа byte.

Arduino

void receiveEvent (int howMany)
{
SlaveReceived = Wire.read();
}

1
2
3
4

voidreceiveEvent(inthowMany)

{

SlaveReceived=Wire.read();

}

4. В функции Void loop():

Мы будем непрерывно отображать принятые от ведущей платы значения на экране ЖК дисплея.

Arduino

void loop(void)
{
lcd.setCursor(0,0); //Sets Currsor at line one of LCD
lcd.print(«>> Slave <<«); //Prints >> Slave << at LCD
lcd.setCursor(0,1); //Sets Cursor at line two of LCD
lcd.print(«MasterVal:»); //Prints MasterVal: in LCD
lcd.print(SlaveReceived); //Prints SlaveReceived value in LCD received from Master
Serial.println(«Slave Received From Master:»); //Prints in Serial Monitor
Serial.println(SlaveReceived);
delay(500);
lcd.clear();
}

1
2
3
4
5
6
7
8
9
10
11
12

voidloop(void)

{

lcd.setCursor(,);//Sets Currsor at line one of LCD

lcd.print(«>>  Slave  <<«);//Prints >> Slave << at LCD

lcd.setCursor(,1);//Sets Cursor at line two of LCD

lcd.print(«MasterVal:»);//Prints MasterVal: in LCD

lcd.print(SlaveReceived);//Prints SlaveReceived value in LCD received from Master

Serial.println(«Slave Received From Master:»);//Prints in Serial Monitor

Serial.println(SlaveReceived);

delay(500);

lcd.clear();

}

После того как вы соберете всю схему проекта и загрузите обе программы в платы Arduino вы можете приступать к тестированию работы проекта. Вращая потенциометр на одной стороне вы должны увидеть изменяющиеся значения на экране ЖК дисплея на другой стороне.

Теперь, когда вы разобрались, как работать с интерфейсом I2C в плате Arduino, вы можете использовать описанные в данной статье приемы для подключения к плате Arduino любых датчиков, работающих по данному протоколу.

Управление мощной нагрузкой переменного тока / Хабр

Фазовая модуляция

  1. Подавать импульсы равно в тот момент времени, когда нужно. Для этого придётся завести на микроконтроллер сигнал с детектора перехода напряжения через ноль
  2. К затвору симистора подключить компаратор, на который завести сигнал с делителя напряжения и с аналогового выхода микроконтроллера
Устойчивость к помехам/возможность коммутации индуктивной нагрузки
  1. Нагрузка, управляемая симистором (обмотка мотора)
  2. Фильтр (snubber), расположенный рядом с симистором и призванный его защищать
  3. Внешняя помеха (грозовой разряд)

VIdV/dtdI/dtсгорит(dV/dt)c(dI/dt)c

Защита от короткого замыкания
  1. Превышение dI/dt. Симистор не успевает открыться полностью, ток идет не через весь кристалл, образуются локальные горячие области, выжигающие кристалл.
  2. Превышение интеграла Джоуля I^2t. Задает количество теплоты, накопление которой в кристалле приведет к разрушению кристалла.
  1. Быстродействующий плавкий предохранитель. Обычный предохранитель не подойдет так как симистор сгорит до того, как он сработает. Но стоят такие предохранители дороже новых симисторов.
  2. Геркон/реле. Если удастся найти такое, чтобы выдерживало кратковременные большие токи.

Важные страницы

  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макро, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  • Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту (alex@alexgyver.ru)

Проверка работоспособности Watchdog

В примерах к библиотеке идёт скетч тестирования поддержки watchdog на вашей плате. Загрузите его в плату и откройте монитор порта. Спустя 10 секунд паузы, установленной для упрощения перепрошивки при boot loop, в монитор порта начнет выводиться время работы программы в секундах. Если при достижении таймаута программа сбросилась и отсчет начался заново – ваша плата (загрузчик) поддерживает watchdog на все 100%. Если после перезагрузки корректный вывод времени в монитор порта прекратился, а светодиод на плате начал быстро и безостановочно мигать – загрузчик на вашей плате не поддерживает перезагрузку watchdog. Загрузите в плату любой другой скетч, чтобы продолжить использование.

#include <GyverWDT.h>

/*
  Пример тестирующий поддержку всех функций watchdog на вашем устройстве
  > После 10 секунд отсчета программа стартует заного -> поддерживаются все функции
  > После таймаута устройство зависает, светодиод на D13 начинает мигать -> поддерживается только INTERRUPT_MODE
  В случае bootloop у вас будет 10 секунд на перепрошивку устройства после подачи питания
  Для добавления поддержки всего функционала watchdog загрузите optiboot или откажитесь от загрузчика
*/


void setup() {
  Serial.begin(9600);

  Serial.println("Program started , wait 10 seconds");
  delay(10000);                                             // 10 секунд на перепрошивку в случае bootloop

  Watchdog.enable(RESET_MODE, WDT_PRESCALER_1024);          // Режим сторожевого сброса , таймаут ~8с
  Serial.println("watchdog enabled");

  while (1) {                                               // Бесконечный цикл , эмуляция "зависания"
    if (!(millis() % 1000)) {                               // Каждую секунду
      Serial.println((uint16_t)((millis() / 1000) - 10));   // Вывести время после включения watchdog в секундах
      delay(10);
    }
  }

}

void loop() {}

Что делать, если загрузчик на моей плате не поддерживает watchdog?

Если вам действительно нужен полный функционал сторожевого таймера – необходимо перепрошить загрузчик, для этого необходим программатор, который поддерживает МК AVR, или другая плата Arduino + скетч Arduino ISP. Подробнее читайте в уроке про работу с программатором. Без перепрошивки загрузчика вам доступны обычные прерывания, не использующие таймеров и имеющие высокий приоритет, и соответственно возможность использования watchdog в режиме будильника МК.

Тестирование работы проекта

В нашем проекте мы подключили датчик расхода воды к водопроводной трубе. Если по трубе не течет воды, то на выход датчика расхода воды не поступает никаких импульсов, следовательно, не регистрируется прерываний на контакте 2 платы Arduino и значение переменной flow_frequency будет равно нулю. В этом случае выполняется код основной программы, идущий после оператора else.

Если по трубе протекает вода, то турбина (колесо, крыльчатка) внутри датчика расхода воды начинает вращаться, поэтому на выходе датчика расхода воды появляются электрические импульсы, генерируемые датчиком Холла. Каждый из этих импульсов вызывает срабатывание прерывания на контакте 2 платы Arduino. С каждым поступившим сигналом прерывания (rising edge – передний фронт импульса) значение переменной flow_frequency увеличивается на 1. Затем переменные current time и cloopTIme гарантируют, что значение переменной flow_frequency будет учитываться в расчетах каждую секунду. После проведения вычислений значение переменной flow_frequency устанавливается равным 0 и процесс начинается сначала.

Более подробно работу проекта вы можете посмотреть в видео, приведенном в конце статьи.

Коды статусов и ошибок

Помимо тика, текущий статус можно узнать из функции , она возвращает то же самое, что тик:

Код Название Описание
Ожидание
1 Передача
2 Буфер переполнен
3 Передача завершена
4 Приём
5 Ошибка приёма
6 Ошибка. Приём прерван
7 Ошибка. Буфер или пакет переполнен
8 Ошибка. Не наш адрес
9 Ошибка. Не совпадает CRC
10 Успешное получение запроса
11 Успешный приём данных
12 Успешное получение подтверждения

Статус можно опрашивать как по коду, так и по имени (константа подсветится синим).

В версии 2.5 появилась функция , возвращающая при изменении статуса. Использовать можно так:

bus.tick();   // тикаем
if (bus.statusChanged()) {  // если статус изменился
  Serial.println(bus.getStatus());  // выводим код
}

Оцените статью
Рейтинг автора
5
Материал подготовил
Илья Коршунов
Наш эксперт
Написано статей
134
Добавить комментарий