Как сделать шим сигнал на ардуино

Добавил пользователь Алексей Ф.
Обновлено: 18.09.2024

Я работаю одним из ведущих конструкторов на одном крупном военном Зеленоградском заводе, и в данный момент веду проект по разработке метрологического средства измерения. В данной задаче существует бесконечное множество проблем, которые требуют индивидуального решения. Одной из таких задач является управление шаговым двигателем без шумов и с шагом не 1.8 градуса, как сказано в документации шагового двигателя, а до 0.0001 градуса. Казалось бы, задача сложна и нерешабельна, но, повозившись немного со схемами управления, пришёл к выводу, что всё реально и возможно. Требуется только генерация двух сигналов специфичной формы и со сдвигом фаз и частотой изменения напряжения до 1 МГц. (Подробное исследование шагового мотора и раскрытие всех тайн управления напишу в следующей статье) Сразу же в голове стали появляться проблески надежды, что я не зря потратил 1500 рублей на свою красненькую Seeeduino, и я, набравшись энтузиазма, начал разбираться.

Первоначальный ужас:

Подключив микропроцессорную плату к осцилографу, и написав цикл digitalWrite(HIGH), и ниже digitalWrite(LOW), на осцилографе обнаружил довольно унылый меандр с частотой 50Гц. Это кошмар. Это крах, подумал я, на фоне требуемых 1Мгц.
Далее, через осцилограф, я изучил еще несколько скоростей выполнения:
AnalogRead() — скорость выполнения 110 мкс.
AnalogWrite() — 2000 мкс
SerialPrintLn() — при скорости 9600 около 250мкс, а при максимальной скорости около 3мкс.
DigitalWrite() — 1800мкс
DigitalRead() — 1900мкс

На этом я, всплакнув, чуть не выкинул свою Seeeduino. Но не тут-то было!

Глаза боятся, руки делают!

Не буду рассказывать свои душевные муки и описывать три долгих дня изучения, лучше сразу скажу всё как есть!
Подняв всю возможную документацию на Arduino и на процессор Atmega1280, исследовав опыт зарубежных коллег, хочу предложить несколько советов, как заменять чтение/запись:

Улучшаем AnalogRead()

void setup() int start ;
int i ;

Serial.begin(9600) ;
Serial.print("ADCTEST: ") ;
start = millis() ;
for (i = 0 ; i

Результат: скорость 18,2 мкс против бывших 110 мкс.
Кстати, максимальная скорость АЦП Атмеги как раз 16мкс. Как вариант — использовать другую микросхему, заточенную именно под АЦП, которая позволит уменьшить скорость до 0,2мкс (читать ниже, почему)

Улучшаем digitalWrite()

Каждая Arduino/Seeeduino/Feduino/Orduino/прочаяduino имеет порты. Каждый порт — 8 бит, которые сначала надо настроить на запись. Например, на моей Seeeduino PORTA — c 22 по 30 ножку. Теперь всё просто. Управляем с 22 по 30 ножки с помощью функций
PORTA=B00001010 (битовая, ножки 23 и 25 — HIGH)
или
PORTA=10 (десятичная, всё так же)
Результат = 0,2мкс против 1800мкс, которые достигаются обычным digitalWrite()

Улучшаем digitalRead()

Практически то же самое, что и в улучшении с digitalWrite(), но теперь настраиваем ножки на INPUT, и используем, например:
if (PINA==B00000010) <. >(если на ножке 23 присутствует HIGH, а на 22 и 24-30 присутствует LOW)
Результат выполнения этого if() — 0.2мкс против 1900мкс, которые достигаются обычным digitalRead()

Улучшаем ШИМ модулятор, или analogWrite()


Итак, есть данные, что digitalRead() исполняется 0,2мкс, и ШИМ модулятор имеет дискретность 8 разрядов, минимальное время переключения ШИМ 51,2мкс против 2000 мкс.
Используем следующий код:
int PWM_time=32; //Число, которое мы как бы хотим записать в analogWrite(PIN, 32)
for (int k=0;k

for (int k=0;k
Вот и получили ШИМ с частотой 19кГц против 50Гц.

Подведём итоги


digitalWrite() было 1800мкс, стало 0,2мкс
digitalRead() было 1900мкс, стало 0,2мкс
analogWrite() было 2000мкс, стало 51,2мкс
analogRead() было 110мкс, стало 18,2мкс, а можно до 0,2мкс

Arduino проекты. Уроки, программирование, управление и подключение ардуино.

Arduino и PWM. Широтно-импульсная модуляция (ШИМ).

Давайте вспомним предыдущую статью о том, как сделать гирлянду на Arduino и попробуем выполнить новую задачу. Думаю, что все видели новогодние витринные гирлянды, в которых плавно мигают светодиоды. Допустим, что мы хотим сделать нечто подобное.
Мы уже рассматривали функцию digitalWrite() и знаем, что значение, которое она записывает, может быть двух вариантов - высокий или низкий уровень. В данном случае нам поможет функция analogWrite(). "Формулировки" функций различаются только начальными приставками, поэтому их легко запомнить.

Функция analogWrite(), так же как и digitalWrite(), содержит в скобках два аргумента и работает по тому же словесному принципу: "куда, что". Главным различием является возможность записи широкого диапазона значений вместо привычного LOW или HIGH. Это и позволит нам регулировать яркость светодиода. Главное замечание, которое необходимо учитывать, это то, что данная функция работает только на определенных контактах. Эти контакты обозначены символом "~". Этот символ означает, что это PWM-контакт. PWM (pulse-width modulation) звучит по-русски как ШИМ (широтно-импульсная модуляция). Принцип работы основан на изменении длительности импульса. Графически это можно изобразить так:


Давайте попробуем разобраться как это работает, рассмотрев простой пример. Для этого необходимо подключить светодиод к PWM-контакту через резистор номиналом 150 Ом и "зашить" в Arduino простенькую программу. Схема подключения и код скетча представлены ниже:


Давайте вернемся к схеме из предыдущего урока и попробуем сделать аналогичную гирлянду с использованием функции analogWrite().

boolean lastButton = LOW;
boolean currentButton = LOW;
boolean enable = false;

void setup()
pinMode(buttonPin, INPUT);
for(int mode = 0; mode = 0; brightness--)
analogWrite(pins[i], brightness);
delay(1);
>
delay(40);
>
>

if(enable == false)
for(int i = 0; i

Визуально скетч стал несколько сложнее. На самом деле здесь все просто и давайте в этом разберемся. Нам необходимо идентифицировать все подключенные светодиоды, но вместо привычного int led мы используем массив, каждый элемент которого является PWM-контактом на Arduino. В теле функции void setup() мы тоже поступили хитрым образом. "Перечислять" все контакты мы доверили циклу for(), с каждой итерацией которого производится конфигурация соответствующего контакта на OUTPUT. Переходим к функции void loop(). Функция debounce() и начальное условие if() остается без изменений. У нас по-прежнему идет проверка уровней двух переменных: предыдущее значение (изначально LOW) и текущее состояние кнопки. При выполнении этих условий значение переменной enable инвертируется. Учитывая это, мы добавили еще два простых условия if(). Если enable = true, то гирлянда включается, плавностью "перетекания" которой управляет цикл for(). Если же enable = false, то все светодиоды выключены. По окончанию условий переменная lastButton принимает текущее состояние кнопки.
Тестируя нашу программу, мы заметили, что все работает не должным образом. Помните, в прошлом уроке мы сделали поправку, что при большом значении временной задержки кнопка срабатывает по её истечению? В прошлом примере, при включенной гирлянде, суммарная задержка в теле функции void loop() составляла 85мс. Это давало нам возможность успеть "попасть" в определенной отрезок времени. В данном скетче, при том же условии, задержка отличается в несколько раз. Возможно, при желании выключить гирлянду напрашивается слово "прервать". Это и будет являться решением данной задачи!

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

3 коммент.:

Замечательная, среди остальных, статья о ШИМ в Arduino! Спасибо, все работает.

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

Wow! this is Amazing! Do you know your hidden name meaning ? Click here to find your hidden name meaning


Для наших целей понадобится один аналоговый вход - А0, который используем для подключения переменного резистора, а также один выход ШИМ - возьмём 11. Соберём простую схему :


И напишем простую программу для управления яркостью светодиода , подключённого к 11 выходу ШИМ. Регулировать будем переменным резистором, который подключен к аналоговому входу А0.



Получаем первый результат - яркость светодиода изменяется с помощью переменного резистора. Для управления какой-нибудь силовой нагрузкой включённой в сеть 220 вольт такой ШИМ тоже сгодится, только желательно сделать гальваническую развязку между силовой частью и Arduino. Можно взять готовый кусочек схемы из предыдущей страницы " ШИМ-регулятор 220 В( IGBT)"


Провёл небольшие испытания этого ШИМ-регулятора - сначала как обычно подключил активную нагрузку ( лампочку накаливания) а затем и коллекторный двигатель. Всё работает. Снял видео -

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


и подал это сигнал на аналоговый вход А1. Для защиты входа Ардуино от перенапряжения поставил ещё стабилитрон на 5.1 вольт. Получилась такая схема


Для написания программы управления оборотами коллекторного двигателя использовал библиотеку PID - регулятора для Arduino.


// подключаем библиотеку PID-регулирования

В результате получилось очень даже неплохо - регулируются обороты двигателя с поддержанием мощности. Снял по этому поводу видео -



169 комментариев:

Здравствуйте вы случайно неделание регулятора и управления бесколекторный двигателем от стиральной машины лж рабочее напряжение от 0 до 100 вольт постоянного тока ампераж сказать не могу

Я такими пока не занимался, возможно там какое-то подобие частотного привода

Александр, прокомментируй, пожалуйста что происходит в void loop

Александр, я написал кое-какие пояснения в скетче, хотя я не большой специалист в программировании. Делал программу больше по аналогии и по интуиции. А что конкретно непонятно в этом скетче?
Вообще на первый взгляд ПИД-регулятор - это просто, но вся проблема заключена в этих коэффициентах Kp, Ki, Kd а также в их подборе для каждого конкретного случая.

Спасибо. Да, вот смотрю на вашу программу и вижу что просто. До этого читал, не понял толком ничего. Размазывают, растягивают, а что куда подставлять не понятно. Позже посмотрю ваши пояснения - спрошу ещё.

Доброго всем времени.
Вопрос к автору и повторившим, есть ли разница между регулятором на Ардуино и ТДА1085. в работе на динамическую нагрузку например болгарка.

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

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

можете выложить саму библиотеку PID_v1.h

Почему нет защиты, ведь не сложно реализовать.

Подключайтесь, предлагайте свои решения, а я стараюсь всё очень постепенно добавлять.
Всё в принципе просто сделать, только почему-то все ждут готовых решений.

Великолепное по простоте решение! Особенно в программной части :). Есть два маленьких недостатка. Во-первых при такой обратной связи реальные обороты двигателя не определить, т.к. все импульсы таходатчика сглаживаются. Но это излечимо, если снимать с датчика не выпрямленное напряжение, а считать частоту импульсов. И во вторых, силовая часть будет малость по-дороже, чем в случае управления переменным током через симистор. Но зато как всё просто!

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

Я очень извиняюсь, но с нетерпением жду регулятор с тахометром. Когда можно, примегно ждать. Еще раз извините, но сам я не могу ничего написать.Очень жду.

Буду работать над этим вопросом, но точно не могу сказать - это зависит очень от многих причин.

У меня вопрос, что это за транзистор VT2 S8580?

Вы правы - опечатка - это S8550

Здравствуйте. Хочу повторить эту схему. С ардуино уже знаком (часы,барометр собирал, светодиодиком моргал :)) , надеюсь получится. Вопрос по диоду RHRP3060. Его функции? Он скоростной,мощный (30А) , нужен именно такой или чем то можно заменить ?
И спасибо за проделанную работу.

Это защитный диод для работы с индуктивной нагрузкой, он должен быть быстродействующий - зависит от частоты ШИМ. Должен перекрывать рабочие напряжение и ток. Насчёт быстродействия - я подбирал по нагреву - сначала поставил по-моему FR1007 на 10 ампер 1000 вольт - на малой частоте ШИМ не нагревался - как только я увеличил частоту до 10-20 кГц - стал сильно греться. Тогда поставил RHPR3060 - стала нормальная температура . То есть главный параметр - это быстродействие.

Увы, по быстрому повторить не получится. Как я понимаю, логичное продолжение проекта это драйвер hcpl 3120 и транзистор Fga25n120 ? Так в наших радиоларьках запросили 3$ за драйвер и 11$ (!) за транзистор, про диод уже и спрашивать не стал. Всё заказал на eBay, (к примеру: 10 драйверов всего 2.45 и 5 транзистров за 4$ ). Придётся ждать.

Знакомая история, я почти всё так заказываю.

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

Дисплей будет LCD1602, а для обработки сигнала таходатчика компаратор LM393

Спасибо, буду готовиться.

Доброго дня, хочеться повторить Вашу схему. Подскажите программа для ардуино в свободном доступе, ткните где/как скачать. И еще вопрос, она программа, совместима с ардуино мини?
Извините за ламерские вопросы)) учусь.
Спасибо.

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

Этот комментарий был удален автором.

александр подскажите наименование стабилитронов vd2, vd4, vd8 и диодный мост на входе тахо?

1N4742A и 1N4733A подойдут?
а вот диодный мост какой?

Подойдут любые 0.5 или 1 Вт, 1N4742A и 1N4733A тоже подойдут.
Диодный мост абсолютно любой, напряжение до 50 вольт, ток небольшой.

и мощность резисторов хотелось бы узнать )
а еще скажите почему с5 на 400 вольт?

Амплитуда у синусоиды питающей - 310 вольт ( 220 вольт это действующее значение)
R12 у меня 2 Вт, R11 - два 5-ватных сопротивления по 20 Ком. Остальные 0.25 Вт.

А разве R10 не на 3 ватта?

Да, R10 стоит на 3 ватта

а где на схеме с5? я не нахожу

Транзистор FGA25N120ANTD с диодом внутри между эмиттером и коллектором .нужен ли тогда диод VD5 ?

Диод нужен, он ставится параллельно индуктивной нагрузке и в обратной полярности.

А параметры схемы которая идет с таходатчика у вас подобраны таким образом, что когда вы потенциометром устанавливаете, допустим, 2.5 В, у вас двигатель раскручивается до таких оборотов, что с таходатчика приходит 2.5 Вольта, или это необязательно, главное чтобы просто было меньше 5?

Просто непонятно, как работает регулятор, он должен сравнивать входной сигнал с потенциометра и с датчика или нет?

Подстроечник R3 устанавливается так, чтобы на максимальных оборотах на вход Ардуино поступало 5 вольт. Тогда получается диапазон 0 - 5 вольт.

Совершенно верно, сравнивает два сигнала - с потенциометра и с таходатчика

А на последнем рисунке с кодом, это весь программный код, или ещё что-то есть?
просто попробовал сейчас его загрузить, у меня на выходе стабильно 0 почему-то.
Как при разных сигнлах на А1 и А0 так и при одинаковых

Наверно у вас нет этой библиотеки PID_v1.h - загрузить надо.

А помните, в первоначальном коде вы задавали уменьшение выходной переменной в 4 раза, в это случае нужно ли так делать? просто на выходе то изначально предел сигнала 1024

Разобрался, это почему-то некорректно отображался именно сам светодиод, когда подключил к двигателю всё заработало)

А ещё, последний вопрос. Почему у вас в строке
PID myPID(&pwmSpeed, &pwmOut, &pwmSet, 0.2, 0.5, 0, DIRECT);
задан параметр DIRECT? Директ это ведь прямое рягулирование, и уменьшение сигнала входного сигнала приводит к уменьшению сигнала на выходе? Там разве не нужно было написать Reverse?

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

Здраствуйте помогите в написании скетча для ардуино уно управление двигателем постоянного тока с реверсом поддержанием момента и торможением?

Я больше по аппаратной части, программы у меня очень упрощённые получаются - не программист я. Мне бы самому помощь в программировании не помешала бы.

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

Все собрал, движок 750 Вт (Ручной фрезер), сгорает выходной транзистор, видать пусковой ток очень большой (сопротивление обмоток на холостую 10-12 Ом). Есть мысли как ограничить пусковой ток (аппаратно или программно)? Частоту увеличил до 4 кГц, датчик тахометра поставил цифровой. Кому интересно скетч выложу.

Да, интересно. Делаю для 1.2 квт фрезера.

Здравствуйте, Александр. Собрал я электропривод к инвалидной коляске на двигателе с "индезита" 370 Вт. Питание 75-80 В (6 аккумуляторов ИБП 12В). Управлял китайским ШИМ регулятором 0-90 В, За месяц два сгорело. Хочу сделать ШИМ на ардуинке, силовую часть на FGA25N120ANTD. Пробовали ли Вы для управления использовать драйвер hcpl 3120?

Пока сделал пробный регулятор на NE555 с гальвнической развязкой от 220 вольт и с драйвером TLP250. Он похож на HCPL3120. Также аппаратную защиту по току сделал. На компараторе.

Подскажи пожалуйста какая площадь радиаторов и как сильно греется ? у меня нагрузка примерно 500 вт.

Да, планирую и делаю сейчас, но всё очень медленно получается.

Здравствуйте! Я так понимаю для тэна эта схема тоже подойдет? Можно ли использовать сторонний источник +12В? Нужно ли как-то программно ограничивать шим(ведь после моста у нас будет 310В)? Для чего резистор R10 0,1 Ом между истоком и землей? Обязательно ли использовать диод D8, если нагрузка чисто активная?
Заранее благодарю за ответы.

Защита по току будет сделана на следующем этапе, будет аппаратная защита и ещё датчик тока.

Спасибо. Буду пробовать. А как подобрать R10? У меня нагрузка тэн на 130 Вт. Присмотрел мосфет STP4NK60ZFP(N-ch Vds=600V Id25=4A Rds=2Ohm), думаю должно хватить, как и моста на 2А 1000В.

Спасибо. Теперь понятно по R10. Тут чем меньше, тем лучше. Тем более, что сигнал усиливается операционником. Мост и мосфет подберу чуть мощнее.

Здравствуйте, у вас на схеме две земли или одна? Не могу просто понять все собрал по схеме и не работает??

Т.е одна общая или две отдельные?

Ксть кто онлайн люди помогите! Очень нужна эта схема но вот не могу понять что за две земли!

Этот комментарий был удален автором.

Да,землю ардуино и землю силовой части следует связать.

Схему исправил , должно быть понятно - две земли и они развязаны.

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

Нет, земли разные. Оптрон PC817 именно для такой развязки стоит.

А как быть если ц меня ардуина и драйвер мосфета питаются от компьютерного БП АТХ? В нем же земля общая

Спасибо 12в на транзистоах появились:) Но вопрос еще а как igbt транзистор подключать? На хеме стоит полевой мосфет

Смотрел, но как подключать так и не понял

У igbt транзистора коллектор и эмиттер. А на схеме полевой у него сток исток? У меня тоже fga25n120!

Люди, выручайте! Все равно не работает монтаж правильный соплей между дорожками нет

Автор! Помогите с подключением транзистора

Схема не работает почему то

Светодиод меняет яркость? Когда крутите переменный резистор.

но на выходе 0.2 вольта

Какую нагрузку подключаете - мотор? Вместо нагрузки можно подключить лампочку на время запуска.

Также можно все испытания проводить на небольшом напряжении вмечто 220 вольт.

отлично! заработало всем спасибо ОГРОМНОЕ за помощь!! Автор на самом деле модчина схема проста до безобразия если в ней разобраться а так вполне рабочая

Вопрос еще а можно ли как то ограничить выходное напряжение до 110вольт?

Мне управлять не с ардуино а с match3 чпу шпиндель 500ватт 110вольт постоянка

Тогда только трансформатор 220/110 и подавать на силовой мост, а для 12В(драйвера) брать мост послабее и запитывать от 220В.

В поставляемом бп к шпинделю 100 вольт постоянного формируется из переменного 220 также ШИМом(Мой сгорел хотел востановить но не получилось).Собрал вашу схему на FGA25N120ANTD + конденсатор из бп(в оригинале он был после моста) шпинбель работает но при хорошой нагрузке напряжение проседает обароты падают.Прикрутить бы отслеживание по напряжению.

И при этом оставить регулировку шим сигналом 0-110вольт

И при этом оставить регулировку шим сигналом 0-110вольт

Приветствую! Собрал ШИМ-регулятор по Вашей схеме. Работает отменно! Двигатель подобный Вашему, либо такой-же, но вот импульсный таходатчик из двигателя я извлек, поскольку долго воевал с корректным отображением оборотов на LCD 1602, а Вашу схему обработки сигнала таходатчика, я тогда не видел. Сейчас установлен оптический, инфракрасный датчик, и одна метка на валу, то есть один оборот - один импульс, так отображение максимально корректно, в виду высокой оборотистости двигателя. Еще вывод ШИМ у меня на пятом контакте, на нем удвоенная частота ШИМ.
Поскольку мои навыки написания скетчей, скажем так, не велики, столкнулся с проблемой - Ваш скетч ПИД алгоритма, у меня работает не корректно, а точнее я могу только увеличивать обороты, а вот с уменьшением - помогает лишь полная остановка двигателя через ресет ардуино. Подозреваю дело в количестве импульсов на оборот? Что нужно изменить/дописать в Вашем скетче?
Спасибо!

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

Потенциометр новый, десятиоборотный. В моем скетче ШИМ-регулятора, на LCD выводятся показания потенциометра в процентах, от значения 0.00, до 100.00, и есть подтягивающий резистор на 10k, подключенный на gnd и A0. Показания потенциометра отличные, дребезга нет и все работает, а вот ПИД-алгоритм ни в какую.

А зачем вам подтягивающий резистор? В схеме я его не вижу.

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

Скорее всего, эта подтяжка и не даёт снизить скорость до минимума, задавая минимальное начальное смещение.

Потенциометр тоже 10k, так что никакого влияния, кроме защиты от обрыва и дребезга, подтяжка не имеет. В моем скетче ШИМ, с отображением на LCD оборотов и значения с потенциометра в процентах, обороты регулируются идеально, от от нуля, двигатель остановлен, до ста процентов где двигатель выходит на максимальные обороты. Еще у меня внешнее питание на ардуино и вольтаж на ардуино 4.97 в., так что проблем из за недостаточного питания тоже нет.

Здравствуйте, прочитал ваши комментарии. Я сам не очень силён в программировании, поэтому и обратился к ПИД-библиотеке. Но вы тоже должны были изменить скетч - у меня информацию об оборотах даёт аналоговый сигнал. Если вы используете оптический датчик - должен быть другой скетч. Покажите ваш вариант - совместными усилиями что-нибудь сделаем.
Или надо написать что-нибудь без ПИД, от простого к сложному

//ШИМ.
int pwmPin = 11; // Выход ШИМ (Пятый пин ардуино - удвоеная частота ШИМ).
int analogPin = 0; // Потенциометр.

//Проценты ШИМ.
int Value=0; // Переменная для хранения значения.
float Value_percent=0;

//Обороты.
int valrpm = 0; // Переменная для хранения значения.
void rpm() valrpm++;
>
LiquidCrystal_I2C lcd(0x3f, 16, 2);

//ШИМ.
pinMode(pwmPin, OUTPUT); // Установка порта на выход ШИМ.

//Обороты.
attachInterrupt(0, rpm, CHANGE);

Serial.begin(9600);
lcd.init();
lcd.backlight();
>

void loop()
//ШИМ.
Value = analogRead(analogPin); // Считывается напряжение с потенциометра - значения от 0 до 1023.
analogWrite(pwmPin, Value / 4); // analogRead-значение от 0 до 1023, analogWrite в диапазоне от 0 да 255.

//Обороты.
valrpm = 0; // сбрасываем счетчик и ждем.
lcd.setCursor(0, 0);
lcd.print("RPM: ");

delay(250); // так как прерывание CHANGE, срабатывает два раза (delay 500), то и считываем каждые пол секунды.

Как ранее уже писалось на странице Arduino Nano выходы на плате есть 14 цифровых выходов. Из них 6 могут работать в качестве ШИМ.

Обозначения на разных версиях Arduino.
У Arduino Mega обозначаются PWM
У Arduino UNO - стоит знак ~
У Arduino NANO никаких обозначений нет, наверное не хватило места. Надо просто запомнить D3, D5, D6, D9, D10, D11 или открывать Arduino Nano datasheet.

Arduino Nano

ШИМ – это Широтно-Импульсная Модуляция?
Но правильнее называть её PWM – Pulse-Width Modulation — процесс управления мощности методом пульсирующего включения и выключения прибора.

Как работает ШИМ.
Если вы подключите светодиод к батарейке(через резистор конечно, но вы это и так знаете), светодиод будет светиться постоянно. Если бы вы смогли очень часто включать/выключать светодиод, ну раз так 500 в секунду, то он бы не успевал загореться в полную силу, но и погаснуть до конца он бы тоже не успел. Светодиод светился бы в пол накала.
Цифровые выходы Arduino Nano могут выдавать только 0(LOW) или 1(HIGH).

Arduino Nano

Пример работы можно посмотреть в ARDUINO IDE.

Arduino Nano

Здесь светодиод подключенный к выходу 9(ШИМ) будет постепенно загораться и гаснуть.
Внимание.
Есть проблема при работе функции tone().
функция tone() накладывается на ШИМ сигнал на "3" и "11" выводах Arduino.
Т.е., вызванная, например, для пина "5", функция tone() может мешать работе выводов "3" и "11".

Продолжим изучение цифровых выводов. Напомню, что есть два типа выводов: цифровые и аналоговые. Цифровые выводы в свою очередь могут быть двух видов: c PWM и без них. PWM-выводы помечены символом тильды (~): ~3, ~5, ~6, ~9, ~10, ~11 и используют широтно-импульсную модуляцию (ШИМ) или по английски PWM. Сигнал ШИМ используется для управления устройствами (электродвигатели), которым требуется аналоговый сигнал.

Для плавного изменения сигнала используют вызов функции analogWrite(), указав в параметре значение от 0 до 255.

01.Basics: Fade

Рассмотрим пример Fade, который поставляется с Arduino IDE (File | Examples| 01.Basics | Fade). Скетч позволяет делать плавное затухание светодиода с использованием цифрового PWM-вывода.

Сама конструкция на плате совпадает с примером мигания внешнего светодиода через резистор и провода.

Когда я только начинал изучать Arduino, то допустил ошибку - запустив скетч на плате, я не увидел плавного затухания. В моём случае светодиод продолжал мигать странным образом. Расстроившись, я стал читать ответы на форумах и случайно перечитал ответ на свой вопрос. Там я заметил ремарку, на которую не обратил внимание в первый раз. Оказывается, нужно было соединяться с выводом, который помечен символом тильды (~). На Arduino UNO вывод 12 тильдой не был отмечен. Я быстро перекинул перемычку на вывод с меткой 10 и все заработало. Кстати, в комментариях к примеру уже даны необходимые пояснения, но раньше их не было или я не обратил на них внимания.

Разбор кода

Теперь рассмотрим код для затухания. Он совсем несложный. Комментарии даны с переводом.

03.Analog: Fading

Есть ещё один похожий пример в File | 03.Analog | Fading. Только на этот раз вместо автоматического увеличения значения яркости в главной цикле-функции loop() используются два цикла for. Результат такой же.

Мигалка

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

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

У меня получился следующий код.

Запустив проект, мы получим два светодиода, мигающих поочерёдно. Напомнило мне мигалку. Осталось подключить сирену. Надо запомнить этот урок и реализовать недостающую функциональность.

Fade

PWM на любом выводе

При желании можно реализовать широтно-импульсную модуляцию на любом выводе, написав чуть больше кода. Создадим глобальную переменную pwm​, в которой будем сохранять текущее значение уровня заполнения в процентах. Дальше мы включаем "высокое" и "низкое" состояние вывода, в соответствии с этим значением - когда одно значение велико, второе, наоборот, мало. В цикле for повторим участок кода 1000 раз - без него светодиод менял бы яркость слишком быстро.

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

Читайте также: