[sape_tizer]
Ср. Май 31st, 2023

Что и как строить на земельном участке или обо всем понемногу

Все о инструментах, строительстве, работах, АРДУИНО, электрика, электроника и многое другое

Урок 1: Мигаем светодиодом (blink)

Итак, приступаем к освоению. Первый урок не потребует от вас никаких материалов и просто призван ознакомить с простотой ARDUINO. Как в большинстве программ ознакомление  начинается с «Hello World!» так и мы начнем с самого простого- мигания светодиодом. Что вам для этого потребуется: собственно сама плата ARDUINO, USB кабель для подключения ARDUINO к компьютеру, оболочка программирования ARDUINO. Оболочки выпускаются новые, но самой стабильной признана версия 1.0.6. Скачать вы ее можете на официальном сайте. Это версия для Windows, для Linux качаете здесь. Сразу стоит понять что для продолжения изучения вам понадобится макетная плата (заказать в Китае или купить в интернет- магазине), провода (можно купить там же или найти старые системные блоки и вытащить провода идущие на переднюю панель, раньше даже USB на лицевой панели соединялись одинарными проводами а не целым разъемом, именно они вам и подойдут- вытаскиваете провод, на другой конец напаять штырьки от разъемов на плате, затем надеваете на место пайки небольшой кусочек термоусадочной трубки, чтобы провод не переломился на месте пайки, нагреваете и у вас готовый провод мама(штеккер с отверстием)- папа (штырек от платы).

Как сделать провода для ARDUINO
Самодельные провода для ARDUINO

Таким же образом сделайте провода- папа-папа, они пригодятся для коммутации на макетной плате и присоединения ARDUINO к макетной плате. Кстати можно, даже нужно, сделать такие провода в виде шлейфа- так гораздо удобнее соединять ARDUINO с блоками), ну и блоки с которыми вы будете работать (покупаются тоже в Китае или в интернет- магазинах). Выбор датчиков и исполнительных механизмов огромен и не ограничивает вашу фантазию. Но на первых порах будет достаточно термодатчика Dallas, индикатора 1602 (можно конечно и 7- сегментные светодиодные но они кушают ток в несколько раз больший чем 1602 а это отрицательно скажется при питании от аккумуляторов и батарей, да и выводят они только цифровую информацию), реле, все что вам будет нужно вы всегда сможете докупить. Для тех кто не стеснен в средствах лучше сразу купить набор. Хоть это и дороговато но он сразу отбрасывает все проблемы с приобретением датчиков и вы сможете изготавливать устройства сразу. Выбор все равно будет только за вами. Ладно, заговорился, ближе к теме.

Подключаем ARDUINO к компьютеру, запускаем программу, в программе заходим Сервис- Плата-выбираете вашу плату,  все- можете работать!

Кстати, китайский клон может быть собран микросхеме ch340 и у вас компьютер будет требовать драйвер на USB порт.  Для установки скачайте драйвер CH341SER, распакуйте и при запросе драйвера укажите на папку с распакованными файлами.

Не теряя времени делаем следующее: Файл-Примеры-Basics-Blink. Откроется новое окно

Стандартная программа Blink на ARDUINO
Blink на ARDUINO

в котором вы увидите программу, можете сразу нажать на вторую кнопку в панели программы с изображением стрелки, программа скомпилируется и передастся в ARDUINO, светодиод на плате начнет мигать! 1 секунду горит,  1 секунду не горит. Рассмотрим саму программу. Вы увидите прежде всего комментарии отмеченные знаками /*  текст */ и // текст. Первый значит что текст от знака /* до знака */ является комментарием и компилятор просто не обрабатывает и не учитывает эту информацию, очень удобно писать в таких комбинациях описание программы, ее алгоритм, авторство и многое другое. Знак // комментирует только строку. Причем вы можете писать этот знак как в начале строки, так и после каких либо строк программы, но ни в коем случае не перед строками  программы- программа посчитает всю строку за комментарий.

Например:

digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)— правильно

// turn the LED on (HIGH is the voltage level) digitalWrite(13, HIGH);— неправильно

Если вы хотите сделать комментарий перед оператором в одной строке то воспользуйтесь комбинацией /*  текст */, т.е. строка будет выглядеть так: /* turn the LED on (HIGH is the voltage level) */ digitalWrite(13, HIGH);

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

Следующее что вы увидите-  следующий текст:

// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
}

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

Затем идет оператор void setup() {….}— начинающий собственно секцию установок для данного скетча (так называется программа для ARDUINO).

В следующем комментарии написано что определяем 13 пин ARDUINO как выход. Хочу напомнить что на странице Коротко об ARDUINO описаны пины платы, так вот 13 вывод является цифровым (о чем написано в подписях к выходам) и может принимать только 2 состояния- включено (при этом на него подается напряжения порядка 5В), т.е. логическая 1(единица), или выключено (напряжения нет) т.е. логический 0 (ноль). При ноле все равно есть небольшое напряжение на пине но они низкое по отношению к логической единице. Кроме того к 13 пину подключен через резистор светодиод на самой плате, именно он и мигает при выполнении программы.

pinMode(13, OUTPUT);— pinMode- переводится как режим пина, 13- номер пина, OUTPUT- выход, т.е. строка означает что 13 вывод будет работать как выход, OUTPUT , если написать INPUT то это уже будет ЦИФРОВОЙ ВХОД, т.е. вы можете обрабатывать поступающие на этот пин ЦИФРОВЫЕ данные.

Если вы подключите к 13 пину светодиод с последовательно подсоединенным резистором на 1кОм , а другую ножку к пину GND то светодиод будет мигать вместе со светодиодом на плате. Если он у вас не замигал- поменяйте полярность светодиода.

Следующие строки являются программой описывающей действия с портом:

// the loop function runs over and over again forever
void loop() {
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second


void loop() {…}
— секция программы где описываются действия для работы, данные в этом цикле могут меняться и обрабатываться в соответствии с условиями.Комментарий сообщает что следующий цикл будет выполняться снова и снова всегда

digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)-  digitalWrite- записать ЦИФРОВОЙ сигнал, 13- номер пина, HIGH- высокий уровень, т.е. логическая единица (напряжение около 5В), дальше комментарий что включаем светодиод высоким логическим уровнем.

delay(1000); // wait for a second- delay (задержка), ждем 1000 миллисекунд или 1 секунду. Нужный оператор, особенно при обработке нажатий кнопки, в данном случае он используется как указание ждать 1 секунду после включения 13 пина.

digitalWrite(13, LOW); // turn the LED off by making the voltage LOW- как и первая строка цикла указывает что 13 пин надо переключить, только теперь на уровень LOW- низкий уровень, логический ноль (напряжение около 0В).

delay(1000); // wait for a second- опять задержка 1 сек  прежде чем цикл начнется выполняться заново.

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

Программа простейшая, понятная с первого раза но в ней есть недостатки: оператор delay заставляет ARDUINO ждать пока он не закончит свою работу, т.е. в этот момент МК не обрабатывает никакие данные, попросту говоря он ждет исполнения оператора, ладно если значения невысокие, а если нужно оперативно обработать данные? За 1 секунду данные могут поменяться не одну сотню раз, а МК не учитывает их, он ждет выполнения программы. Для того чтобы не пропускать поступающие данные можно воспользоваться следующим скетчем. Открываем скетч: Файл- Примеры- Digital- BlinkWithoutDelay. Откроется окно следующего содержания:

/* Blink without Delay

Turns on and off a light emitting diode(LED) connected to a digital
pin, without using the delay() function. This means that other code
can run at the same time without being interrupted by the LED code.

The circuit:
* LED attached from pin 13 to ground.
* Note: on most Arduinos, there is already an LED on the board
that’s attached to pin 13, so no hardware is needed for this example.

created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
modified 11 Nov 2013
by Scott Fitzgerald

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/

// constants won’t change. Used here to set a pin number :
const int ledPin = 13; // the number of the LED pin

// Variables will change :
int ledState = LOW; // ledState used to set the LED

// Generally, you shuould use «unsigned long» for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated

// constants won’t change :
const long interval = 1000; // interval at which to blink (milliseconds)

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}

void loop()
{
// here is where you’d put code that needs to be running all the time.

// check to see if it’s time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.
unsigned long currentMillis = millis();

if(currentMillis — previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;

// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);
}
}

Пропускаем все комментарии и переходим к строке:

// constants won’t change. Used here to set a pin number :
const int ledPin = 13; // the number of the LED pin

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

const int ledPin = 13; // the number of the LED pin- const означает константу, т.е постоянную величину которую нельзя изменить в программе, int- сокращенно от слова integer, означает тип данных который может принимать значения от -32768 до 32768. Кроме integer есть еще 5 типов данных. Чем они отличаются? Они отличаются размерами, т.е. например в переменную типа byte можно записать всего 256 значений, разница в размерах- int-2 байта (кроме ARDUINO DUE, в нем INT занимает уже 4 байта но значения принимает от -2147483648 до 2147483647 ), byte как и написано- 1 байт. В больших программах экономия памяти является очень важным моментом и поэтому старайтесь избегать где только можно применения более «тяжелых» типов если можно обойтись «легкими» типами. Например здесь хватило бы типа  byte т.к. 13 вписывается в предел между 0 и 255, да и остальные цифровые пины тоже бы вписались в этот тип данных. ledPin — название самой константы. 13- значение константы, из комментария выше понятно что эта константа будет использована для выбора пина.

// Variables will change :
int ledState = LOW; // ledState used to set the LED

Комментарий говорит что переменная будет меняться в программе

int ledState = LOW; // ledState used to set the LED- объявляет переменную ledState имеющую начальное значение LOW (логический ноль) и комментарий что переменная ledState будет использоваться для светодиода (LED по не нашему).

// Generally, you shuould use «unsigned long» for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated

Комментарий говорит что вы должны использовать переменную типа unsigned long для времени, следующая строка предупреждает что значение будет слишком большим для переменной типа int для хранения. Unsigned long применяется для хранения ЧИСЕЛ и может хранить значения от 0 до 4294967295 занимая 4 байта.

unsigned long previousMillis = 0; // will store last time LED was updated- создает переменную previousMillis  типа unsigned long  и присваивает значение 0, в ней будет хранится время когда было обновлено состояние светодиода.

// constants won’t change :
const long interval = 1000; // interval at which to blink (milliseconds)

Тоже константа, типа long, предназначена для хранения ЧИСЕЛ, занимает 4 байта и может принимать значения от -2147483648 до 2147483647, interval- название переменной, 1000- значение переменной. В комментарии подписано что это будет интервал мигания в миллисекундах.

void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}

Функция знакомая по предыдущему примеру, только здесь указывается пин не явно а через переменную ledPin, которая описана у нас как константа  и имеет значение 13. Т.е это равносильно тому что если было бы написано pinMode(13, OUTPUT);

Ну и собственно тело программы:

void loop()
{
// here is where you’d put code that needs to be running all the time.

// check to see if it’s time to blink the LED; that is, if the
// difference between the current time and last time you blinked
// the LED is bigger than the interval at which you want to
// blink the LED.

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

unsigned long currentMillis = millis();

Объявляется переменная currentMillis типа unsigned long которая хранит данные оператора millis()millis()— внутренний оператор МК указывает сколько миллисекунд проработал ARDUINO.

if(currentMillis — previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;

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

if(условие==значение){

Действие если условие выполняется

}

else{

Действие если условие не выполняется

}

Знак == может меняться на любые другие знаки >,<,>=, <=, != (не равно). Условие как и значение может высчитываться. Если условие не выполнено то программа переходит в секцию else. Довольно часто секцию else не используют а просто пишут программу дальше. Это уже зависит от алгоритма работы программы и должно быть продумано заранее. Условий может быть сколько угодно и они могу быть вложены друг в друга, т.е. пока не выполнится одно условие- другое даже выполняться не начнет.

Итак оператор if вычитает из текущих миллисекунд  предыдущее значение и сравнивает с переменной interval. Если значение меньше то программа выходит из условия и начинается сначала, если больше или равно то переменной previousMillis присваивается значение currentMillis и программа переходит на следующий шаг:

// if the LED is off turn it on and vice-versa:
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;

В этой секции выясняется какое состояние у светодиода, если на светодиод подавался низкий уровень LOW то переменной ledState присваивается значение HIGH, и наоборот (секция else) если был высокий уровень HIGH то переменной ledState присваивается значение LOW. Заметьте что здесь if используется уже без {}. Это допускается если нужно обработать в секции выполнения не более 1 строки.

// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState);

Ну и наконец  записываем на значение переменной ledPin (оно было равно 13), значение переменной ledState. Т.е. данная строка может быть записана как digitalWrite(13, LOW); или digitalWrite(13, HIGH); в зависимости от времени работы МК. Обратите внимание что использован оператор digitalWrite- именно он указывает что надо передать значение в логическом формате, т.е. ноль или единицу. Больше он никаких значений принять не может. Любые другие значения ledState будут автоматически приведены к логической 1.

}
}

Вот и разобрана работа второй программы. Какая разница между первой и второй программой если они выполняют одно и тоже действие но во второй написано раз в 5 больше строк? Как я и говорил что первая программа просто ждет когда закончит свою работу оператор delay и только потом продолжит работу. Во время delay вы не сможете обрабатывать никаких данных. Вторая программа позволяет получать, обрабатывать и отдавать данные во время мигания светодиода. Просто дописываете нужный код в секцию loop и наслаждаетесь работой!  Мы с моим другом подсчитали что код пробегается во втором случае около 4 млн. раз в секунду, поэтому задержек практически нет.

Ну а теперь самое главное. Спустя некоторые время, наигравшись, вы скажете- «Че толку то мигать лампочкой… Где это можно использовать? Только индикатор того что устройство работает…» Вы будете не совсем правы. У вас есть инструмент, что вы с его помощью можете сделать- это только ваша вина если вы ничего не можете придумать. Это как любому человеку дать полный набор инструментов и попросить что нибудь сделать, например комплект столярного инструмента вручить мужчине, кто то будет всю жизнь строгать одну и ту же доску, поражаясь чистоте с которой рубанок строгает и пытаясь наточить железку как можно острее,  а кто-то будет делать в это самое время высококачественную мебель. Кем будете вы- решать только Вам. Еще мой совет, где то я вычитал, даже не помню-«НЕ ИЩИТЕ ПРОБЛЕМЫ, ИЩИТЕ ИХ РЕШЕНИЕ!» Если вы будете пользоваться таким подходом у вас возникнет гораздо меньше всяких КАК и ПОЧЕМУ. Ну а теперь про мигание светодиодом. В интернете куча советов по пользованию различными индикаторами, конечно это красиво, придает какую то значимость автору и т.д… но это задевает самое главное- экономия пинов и памяти. Для того чтобы подключить индикатор 1602 надо занять 6 цифровых пинов + 2 провода питания! Это если не пользоваться протоколом I2C. К тому же  библиотека на LCD занимает 4кБ. И никто не думает о дальнейшей функциональности, ну поигрались индикатором и все- тоже бросили. Неужто никто не задавался вопросом что можно одним светодиодом получать всю необходимую информацию? Например ошибки. Написали функцию и передаете в нее код ошибки. Это же удобно- не надо опять разбирать код а просто посмотреть что не так работает. Или, к примеру, мой друг собрал на ARDUINO mini контроллер газового котла, т.е. по температуре в дому (снимаемой датчиком Dallas), включался/отключался циркуляционный насос. Когда насос был отключен, котел нагревался до 40°С и стоял на запальнике, температура в комнате падала- включался насос и при остывании теплоносителя котел сам включался. Очень удобно и появилась существенная экономия газа! Всего за каких то 200-300 рублей он экономил каждый день по несколько кубов газа! Он тогда все думал- как же отследить температуру в комнате без подключения всяких WiFi и компьютеров, я предложил- пускай светодиод мигает столько раз, сколько градусов в комнате… Посмеялись конечно- 20-25 раз считать по любому ошибешься, тогда я предложил- пусть мигает сначала десятки градусов а через паузу- единицы, например 24 градуса, сначала 2 раза мигнул, через паузу еще 4. Все! Никаких больше индикаторов! И это можно применить в любой области! Ищите нестандартные подходы и старайтесь экономить энергию и входы. Даже если используете I2C. Всем удачи в освоении МК и, в частности, ARDUINO.

Следующий урок>>

Добавить комментарий