Как записать программу на ардуино

Люблю я на досуге поиграться с 8-битными AVR-микроконтроллерами. Почему? Потому что они просты в использовании и программировании, у них весьма очевидное внутреннее устройство, но при всем этом они позволяют быстро, дешево и без sms запиливать достаточно нетривиальные проекты. Arduino (и всевозможные дешевые китайские клоны, разумеется) — вообще достаточно популярная железка (и среда разработки) среди погромистов и инженеров. Имея на руках пару breadboard’ов и клубок проводов для них, с Arduino вы сможете без пайки собрать макет какого-нибудь проекта и закодить его, практически не напрягаясь.

Но я сюда пишу не для того, чтобы поднять продажи китайцам, а чтобы заняться настоящей хардкорной разработкой под AVR. Сегодня мы с вами начнем писать настоящую операционную систему с вытесняющей многозадачностью, которую потом запустим на обычных железяках Arduino! Но это еще не все, ведь мы будем писать эту ОСь на C C++14, сдабривая все это щедрым количеством ассемблерных вставок и макросов. Вот это будет пламенная смесь! А назовем мы нашу операционную систему пафосно — Atmos!

Как загрузить прошивку в Arduino nano подробная инструкция

Перед тем, как начать, я должен сказать, что подобные ОС достаточно профессионального уровня и с длительной поддержкой уже существуют. Это, например, кросс-платформенная богатая на фичи и толстая FreeRTOS, или компактная (но не очень удобная) Femto OS. Вы, конечно, можете открыть их исходные коды и постараться разобраться, в чем я вам желаю удачи. Но я в этом цикле статей поясню базовые принципы, которые стоят за созданием такой операционки для AVR и буду писать ее по шагам, разжевывая подробно каждый этап. Если вы готовы вместе со мной окунуться в раскаленные пучины кода, то вперед!

Сперва я отвечу на вопрос, который мог у вас возникнуть: «В AVR и так памяти для кода и оперативки раз-два и обчелся, какая нах*й еще многозадачность?!». Ну тогда сначала определим, зачем нам вообще может понадобиться операционная система с вытесняющей многозадачностью для AVR8.

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

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

В 3-4 килобайта можно уместить массу функционала со стороны ОС. Даже если брать Atmega8 — у этого контроллера 8 кб доступно, итого у вас останется еще ~4 килобайта для ваших задач. А с оперативкой вот что: на каждую задачу будет необходимо выделить блок оперативной памяти определенного размера, порядка 40 байтов (для архитектуры reduced tiny — почти в два раза меньше).

Arduino для начинающих. Начало работы

Сама ОС тоже потребует около 20 байтов оперативной памяти. А дальше все уже зависит от того, сколько памяти требует ваш код. Если брать ту же Atmega8, то для трех выполняемых задач и ОС потребуется порядка 140 байтов оперативки из 1 килобайта доступной. Почему именно такие цифры, увидим дальше, по ходу разработки.

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

Ну, а теперь поехали! Для начала определим, а можно ли вообще такую ОСь запилить под 8-битные AVR. Что нам для этого потребуется? Как мы выяснили, памяти для кода и для данных нам хватит, даже если брать совсем простецкий контроллер. ОС наша будет предлагать вытесняющую многозадачность, то есть сама решать, когда какой задаче выполняться.

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

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

Читайте также:
Как установить программу ncalayer на ноутбук

Передать управление тоже несложно — достаточно выполнить команду перехода на нужную инструкцию, на которой мы остановились в прошлый раз. Доступ у нас к этой информации в AVR имеется. Остается один момент — у каждой задачи будет свой независимый стек (прямо как у процесса или потока в Windows/*nix!), и нам надо будет его как-то сохранять и восстанавливать. В контроллерах AVR и это не проблема — нам доступен регистр указателя стека SP (иногда состоящий из двух 8-битных частей SPL и SPH ). Мы можем читать и записывать его значение. Итого, у нас есть все необходимое для реализации нашего хитрого плана.

Сначала мы займемся тем, что запилим код, позволяющий универсально, практически под любые контроллеры AVR, настраивать таймер, который будет использоваться операционкой для переключения задач. Так как у большинства AVR’ок таймеров несколько, мы дадим возможность выбирать, какой из таймеров должен использоваться ОС.

Кстати, этот код можно будет использовать и для того, чтобы просто настроить некий таймер на срабатывания с определенным интервалом времени. Код я буду писать в бесплатной и весьма неплохой среде Atmel Studio 7 и компилировать его, соответственно, компилятором GCC, входящим в комплект поставки этой среды. Делать я буду стараться все, как у серьезных мужиков: писать комменты на английском, задумываться над универсальностью кода и компактностью его после компиляции, а потом еще и залью все это дело на GitHub. Проверять все это дело будем на Arduino, потому что Arduino нет только у ленивого, да и программировать просто, через ту же Atmel Studio.

Начнем с того, что запустим Atmel Studio и создадим проект «atmos».

создание проекта в atmel studio

Код я буду проверять на Arduino Mega 2560, которая основана на контроллере Atmega2560, поэтому такой контроллер и выберем, как целевой. Впрочем, код я буду тестировать и на Arduino Uno r3, в котором стоит Atmega328P, но девайс мы сможем поменять легко уже потом, когда это потребуется. А пока что ставим Atmega2560.

выбор контроллера в atmel studio

Ну и все, получаем готовый проект, который ничего, кроме бесконечного пустого цикла, не делает, зато компилируется.

пустой проект в atmel studio

Начнем с того, что создадим каталог kernel («Solution explorer» — «atmos» — правой кнопкой мыши — «Add» — «New folder» — kernel). Далее в эту папку добавим файл config.h (правой кнопкой мыши на папке kernel — «Add» — «New item. «). Как у любой уважающей себя операционной системы, у нашей тоже будет файл конфигурации со всякими настройками, которые позволят собрать систему так, как того пожелает пользователь.

добавление файла к проекту atmel studio

Содержимое этого файла у нас пока будет следующим:

Источник: kaimi.io

Блог

Скетч программы Arduino

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

Структура программы Arduino

Базовый скетч Arduino состоит из двух функций, называемых setup () и loop () .

Откройте IDE Arduino и выберите Файл → Примеры → 01.Basics → BareMinimum, чтобы увидеть две функции. Эти две функции теперь появляются в новом окне IDE Arduino по умолчанию, поэтому нет необходимости открывать пример программы BareMinimum после скачивания в новой версии IDE.

Базовая структура программы

Что такое функция?

Подробнее о функциях мы поговорим позже, а пока вам просто нужно знать следующее о функциях:

  • Все функции должны иметь уникальное имя, setup — это один из примеров уникального имени функции ( setup (настройка) и loop (цикл) являются специальными функциями в программировании Arduino и являются частью структуры базового скетча).
  • За именем функции следуют открывающая и закрывающая круглые скобки (), которые могут что-то содержать, а могут и не содержать.
  • Все функции должны иметь возвращаемый тип. И setup, и loop имеют тип возвращаемого значения void.
  • Тело функции состоит из открывающей и закрывающей скобок ( и > ).

«Привет мир!» Пример скетча

Это традиция программирования — писать программу «Привет, мир» всякий раз, когда начинаешь изучать новый язык программирования.

Программа «Hello, world» просто пишет текст «Hello, world!» на экране. Цель этой программы — убедиться, что ваша среда программирования правильно установлена ​​и также правильно работает. Если ваша программа «Hello, world» работает, то вы точно готовы приступить к изучению нового языка программирования.

Читать также: Следующий за рукой робот на Ардуино

У Arduino нет экрана для вывода записи текста «hello world», но мы можем использовать порт USB и окно в меню Монитор порта.

Написание скетча

Измените ранее открытый скетч BareMinimum следующим образом:

void setup ( ) <
Последовательный . begin ( 9600 ) ;
Серийный . println ( «Hello, world!» ) ;

Сохраните измененную программу как hello_world в папке со скетчами, выбрав Файл → Сохранить как… в меню Arduino IDE, а затем переименовав файл в hello_world.

Запуск скетча

Подключите Arduino к компьютеру с помощью USB-кабеля. Нажмите кнопку «Загрузить», чтобы загрузить программу в Arduino.

Читайте также:
Прекращена работа программы genome gaming system

Теперь откройте окно Монитор порта IDE Arduino, чтобы увидеть выполнение скетча и текстовое сообщение.

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

Запуск скетча hello_world

Текстовое сообщение, которое выводит программа, должно быть видно в окне Монитор порта.

Поиск ошибок программирования

Все, что в приведенных выше строках кода неправильно введено в окно IDE, скорее всего, вызовет ошибку компиляции, поэтому обязательно введите все в точности так, как показано в приведенном выше коде. Программа компилируется при нажатии кнопки «Проверить» (значок в виде галочки) или кнопки « Загрузить» (значок в виде горизонтальной стрелки).

Ошибка компиляции появится в нижней части Arduino IDE, как показано на изображении ниже.

Ошибка компиляции

В этом примере точка с запятой ( ; ) была оставлена ​​в конце этой строки: Serial.println(«Hello, world!»), из-за чего IDE Arduino отображала сообщение об ошибке.

Если у вас возникли проблемы с загрузкой скетча в Arduino, убедитесь, что в меню Инструменты → Плата, выбрана правильная плата Arduino, а в Инструменты → Монитор порта выбран именно он.

Читать также: Операторы отношения

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

Последовательность выполнения программы Arduino

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

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

Части скетча Arduino

Как работает скетч Hello World

В скетче hello world сначала выполняются операторы функции setup () сверху вниз. Объявление Serial.begin (9600); является первым оператором в функции setup (), поэтому он запускается первым. Этот оператор устанавливает скорость Монитор порта на 9600 бод. Настройка скорости в окне монитора порта должна соответствовать этому значению, чтобы Arduino и окно монитора порта могли обмениваться данными с одинаковой скоростью.

Второй оператор, выполняемый в функции setup (), — это Serial.println («Hello, world!»); который отправляет текст Hello, world! из последовательного / USB-порта для отображения в окне Монитор порта. В этом операторе любой текст может быть помещен между открывающимися и закрывающимися кавычками ( «» ), и он будет отображаться в окне Монитор порта.

Функция setup ()

Операторы в функции setup () запускаются только один раз при каждом запуске скетча. Затем программа начинает выполнять операторы функции loop ().

Скетч будет запущен после того, как он будет отправлен в Arduino. Открытие окна Монитор порта перезагрузит Arduino и заставит его снова запустить скетч.

Читать также: Большая бионическая птица своими руками

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

Функция loop ()

Операторы в функции loop () будут выполняться непрерывно сверху вниз, а затем обратно вверх.

Если функция loop () содержит два оператора, то будет выполняться первый оператор, затем второй оператор, затем снова первый оператор и так далее в цикле.

Поскольку в нашем примере hello world в функции loop () нет операторов, выполнение программы завершится в цикле и останется там, ничего не делая.

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

В следующей нашей статье мы поместим некоторые программные операторы в функцию loop (), чтобы увидеть, как она работает.

С Уважением, МониторБанк

Источник: monitorbank.ru

Создаем мобильное приложение для управления «Умной теплицей» на Arduino

На 5 уроке про Умную теплицу на Ардуино, мы создадим свое собственное мобильное приложение для устройств на Андроиде. Для этого мы используем редактор визуального программирования Android App Invertor 2

В следующей статье про перенос « функции мониторинга и управления теплицей на телефон или планшет с ОС Androi d» мы установили связь нашей системы с телефоном (или планшетом) с операционной системой Android по Bluetooth, что позволило нам отправлять данные мониторига данных нашей теплицы на телефон и получать команды управления с телефона. Но для связи теплицы с телефоном мы использовали на телефоне приложение Bluetooth Terminal, что совсем неудобно. Нам нужно полноценное приложение. В этом уроке мы и займемся его созданием.
Глубоко внимать в вопросы программирования для операционной системы Android не входит в наши планы, поэтому нам нужна простая и понятная система создания кода для Android, наподобие системы Sctratch для Arduino, которую мы рассматривали на этом уроке – Программируем с Arduino… К счастью подобный визуальный редактор есть. Это онлайн визуальный редактор для визуального программирования для Android App Invertor 2. Страница проекта – http://ai2.appinventor.mit.edu.

Читайте также:
Программа past инструкция на русском

Страница онлайн-редактора App Invertor 2 01

Рисунок 1. Страница онлайн-редактора App Invertor 2.

Рисунок 2 Ваш профиль программы App Invertor 2 Создание проекта для ардуино 02

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

Рисунок 2. Ваш профиль программы. Создание проекта.

создаем моб приложение Создание интерфейса в Design 03

Сначала в панети Design создаем интерфейс нашего приложения, перетаскивая на экран необходимые компоненнты. Кроме визуальных компонентов необходимо добавить 3 невизуальных:
Bluetooth client из раздела Connectivity;
Clock из раздела Sensors (для получения данных из Bluetooth c периодичностью, установленной в Clock);
Notifer из UserInterface.

Рисунок 3. Создание интерфейса в Design.

Код для инициализации Bluetooth соединения и создания Bluetooth клиента 04

Теперь создаем код. Переходим в раздел Block. Сначала создаем код для инициализации Bluetooth соединения и создания Bluetooth клиента (рисунок 4).

Рисунок 4. Код для инициализации Bluetooth соединения и создания Bluetooth клиента.

Затем код для отправки сообщений при изменениии состояний chexckbox-ов для насоса, вентилятора и лампы (рисунок 5).

Код для отправки сообщений при изменениии состояний chexckbox-ов 05

Рисунок 5. Код для отправки сообщений при изменениии состояний chexckbox-ов.

И код получения по таймеру сообщений, поступающих по Bluetooth из Arduino (рисунок 6).

Код получения по таймеру сообщений поступающих из Arduino 06

Рисунок 6. Код получения по таймеру сообщений, поступающих из Arduino

Создаем app приложение (рисунок 7) и загружаем его на телефон.

Генерация app приложения 07

Рисунок 7. Генерация app приложения

Нам надо внести самые маленькие изменения в наш предыдущий скетч, заменив разделитель с пробела на символ ‘*’ при отправке данных с Arduino на Android.
Создадим в Arduino IDE новый скетч, занесем в него код из листинга 1 и загрузим скетч на на плату Arduino. Напоминаем, что в настройках Arduino IDE необходимо выбрать тип платы (Arduino UNO) и порт подключения платы.

// подключение библиотеки SoftwareSerial #include // подключение библиотеки DHT #include «DHT.h» // тип датчика DHT #define DHTTYPE DHT11 // контакты подключения bluetooth-модуля HC-05 int pinBlRx=17; int pinBlTx=18; // контакт подключения входа данных модуля DHT11 int pinDHT11=9; // контакт подключения аналогового выхода модуля влажности почвы int pinSoilMoisture=A0; // контакт подключения аналогового выхода датчика температуры TMP36 int pinTMP36=A1; // контакт подключения аналогового выхода фоторезистора int pinPhotoresistor=A2; // пины светодиодов индикации #define LED_TEMP 5 #define LED_MOISTURE 6 #define LED_LIGHT 7 // значения для условий #define TEMP_DETECT 30 #define MOISTURE_DETECT 500 #define LIGHT_DETECT 250 // реле int pinRelays[]=; // статусы полива, освещения, вентилятора boolean statusRelays[]=; // создание экземпляра объекта SoftwareSerial SoftwareSerial HC05Serial(pinBlRx,pinBlTx); // создание экземпляра объекта DHT DHT dht(pinDHT11, DHTTYPE); unsigned long millisupdate=0; // для получения данных из SoftwareSerial String inputString0 = «»; // признак конца полученной строки boolean stringComplete0 = false; void setup() < // запуск последовательного порта Serial.begin(9600); // pinMode(LED_TEMP,OUTPUT);digitalWrite(LED_TEMP,LOW); pinMode(LED_MOISTURE,OUTPUT);digitalWrite(LED_MOISTURE,LOW); pinMode(LED_LIGHT,OUTPUT);digitalWrite(LED_LIGHT,LOW); // инициализация dht dht.begin(); // запуск SoftwareSerial HC05Serial.begin(9600); // резервирование 50 bytes для the inputString: inputString0.reserve(50); >void loop() < // ожидание конца строки для анализа поступившего запроса: serialEvent0(); if (stringComplete0) < Serial.println(inputString0); parse_string0(inputString0); // очистить : inputString0 = «»; stringComplete0 = false; >// каждые 5 сек — получение показаний датчиков // и вывод на дисплей if(millis()-millisupdate>5000) < millisupdate=millis(); // получение данных с DHT11 float h = dht.readHumidity(); if (isnan(h)) < Serial.println(«Failed to read from DHT»); HC05Serial.println(«H1=101»); delay(10); >else < Serial.print(«HumidityDHT11= «); Serial.print(h);Serial.println(» %»); HC05Serial.print(«aH=»);HC05Serial.print(h);HC05Serial.print(«*»); delay(10); >// получение значения с аналогового вывода модуля влажности почвы int val0=analogRead(pinSoilMoisture); Serial.print(«SoilMoisture= «); Serial.println(val0); HC05Serial.print(«SM=»);HC05Serial.print(h);HC05Serial.print(«*»); delay(10); // получение значения с аналогового вывода датчика температуры TMP36 int val1=analogRead(pinTMP36); // перевод в мВ int mV= val1*1000/1024; // перевод в градусы цельсия int t=(mV-500)/10+75;//t=23; Serial.print(«TempTMP36= «); Serial.print(t);Serial.println(» C»); HC05Serial.print(«aT=»);HC05Serial.print(t);HC05Serial.print(«*»); delay(10); // получение значения с аналогового вывода фоторезистора int val2=analogRead(pinPhotoresistor); Serial.print(«Light= «); Serial.println(val2); HC05Serial.print(«Ph=»);HC05Serial.print(val2);HC05Serial.print(«*»); delay(10); // обновить // вывод состояние полива, лампы, вентилятора Serial.print(«pump — «); Serial.println(statusRelays[2]); Serial.print(«fun — «); Serial.println(statusRelays[1]); Serial.print(«lamp — «); Serial.println(statusRelays[0]); HC05Serial.print(«PM=»);HC05Serial.print(statusRelays[2]);HC05Serial.print(«*»); delay(10); HC05Serial.print(«FN=»);HC05Serial.print(statusRelays[1]);HC05Serial.print(«*»); delay(10); HC05Serial.print(«LM=»);HC05Serial.print(statusRelays[0]); delay(10); //// проверка условий // увлажненность почвы if(val0 > MOISTURE_DETECT) digitalWrite(LED_MOISTURE,HIGH); else digitalWrite(LED_MOISTURE,LOW); // температура воздуха if(t > TEMP_DETECT) digitalWrite(LED_TEMP,HIGH); else digitalWrite(LED_TEMP,LOW); // освещенность if(val2 < LIGHT_DETECT) digitalWrite(LED_LIGHT,HIGH); else digitalWrite(LED_LIGHT,LOW); // пауза 5 секунд Serial.println(); >> // SerialEvent для HC05 void serialEvent0() < while (HC05Serial.available()) < // получить очередной байт: char inChar = (char)HC05Serial.read(); // добавить в строку inputString0 += inChar; // /n — конец передачи if (inChar == ‘#’) < stringComplete0 = true; >> > // парсинг строки из android void parse_string0(String inputString) < // длина строки int length1=inputString.length(); if(length1!=5) if(inputString.charAt(2)!=’=’) if(inputString.charAt(4)!=’#’) String param1=inputString.substring(0,2); int param2=inputString.substring(3,4).toInt(); Serial.print(«param1=»);Serial.println(param1); Serial.print(«param2=»);Serial.println(param2); if(param1==»PM») doCommand(2,min(param2,1)); else if(param1==»FN») doCommand(1,min(param2,1)); else if(param1==»LM») doCommand(0,min(param2,1)); > // исполнение команды от смартфона void doCommand(int relay, int status1) < // изменить статус statusRelays[relay]=status1; // изменить состояние реле digitalWrite(pinRelays[relay],statusRelays[relay]); >

Загружаем скетч на Arduino, на телефоне запускаем приложение.

08 Рисунок Приложение в работе 09 Рисунок Приложение в работе10 Рисунок Приложение в работе

Рисунок 8, 9, 10. Приложение в работе.
На следующем уроке рассмотрим вопрос превращения нашей теплицы в объект IoT (Интернет вещей).

Источник: playarduino.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru