Сайт не активен
Хостинг провайдер «Хостер kg» представляет качественные услуги хостинга, аренды серверов и размещения Вашего сетевого оборудования на наших площадках( колокейшн).
Тарифы созданы с учетом пожелания клиентов и 12 летнего опыта работы. Подробнее вы можете ознакомиться с условиями на нашем сайте по адресу www.hoster.kg
Так-же к Вашим услугам платная регистрация имен в любых доменных зонах, бесплатные домены в целевых зонах
-.biz.kg, -.on.kg, -.shop.kg, -.el.kg, -.go.kg.
Для удобства работы наших клиентов, мы предоставляем программное обеспечение ведущих производителей в сфере хостинг-услуг таких как ISPsystem, Parallels Inc. Размещение на оборудование ведущих брэндов — Dell¸ HP, Cisco, MikroTic и других.
Служба технической поддержки — готова круглосуточно придти Вам на помощь в решении технических проблем, консультации Вы получите бесплатно.
Офис № 1
г.Бишкек, ул. Ахунбаева, 123
Здание БГТС (правое крыло, вход со стороны Ахунбаева)
Офис № 2
ул. Горького, д. 19, второй этаж, офис № 2 (вход со двора)

Чем мы можем Вам помочь
Для владельцев сайта
Ваш домен настроен корректно, сервер также обрабатывает запросы правильно – но вместо своего сайта
Вы видите нашу информационную страницу.
Возможно несколько причин по которым Вы видите данную страницу вместо Вашего сайта
Отсутствует правильно настроенная стартовая (индексная) страница для Вашего сайта.
Подробнее про решение данной проблемы можно узнать тут: База знаний
Необходима внести оплату за услуги хостинга.
Оплатить вы можете любым удобным для Вас способом. Подробнее о методах оплаты Вы можете узнать на странице www.hoster.kg/payment/ После поступления оплаты Ваш сайт заработает в течении пяти минут.
Возможно Ваш сайт превысил лимиты ресурсов и отключен Администратором.
В данном случае с отчетом о причине отключения Вы можете ознакомиться на Вашей почте. Просмотрите почтовый ящик который указан при заключении договора на услуги хостинга. При возникновении вопросов Вы всегда сможете получить консультации в Службе Технической Поддержки
Возможно мы не предусмотрели какой-либо вариант развития событий
и все вышеперечисленные причины Вы исключили, тогда мы рекомендуем незамедлительно связаться со Службой Технической Поддержки.
Круглосуточно, в любой день недели наши специалисты рады будут помочь Вам.
Так-же рекомендуем:
Если Ваш сайт отключен за неуплату и Вам срочно нужно восстановить работу ресурса Вы можете воспользоваться услугой «Обещанный платеж», с помощью которой у вас появляется возможность самостоятельно продлить услугу хостинга в кредит. Для этого Вам необходимо:
1. Зайти в Личный кабинет абонента биллинга по адресу https://bill.hoster.kg/manager/billmgr
2. Слева в Меню «Финансы» выбрать пункт «Платежи», далее на странице в меню сверху кликнуть на иконку «Новый», в всплывшем окошке нажать кнопку «Далее», после чего в строке «Метод оплаты» выбрать пункт «Обещанный платеж» в следующей строчке указать сумму в пределах 570 сом и нажать «Далее». На следующих страницах обязательно заполните недостающие данные Вашей анкеты и подтвердите нажатием кнопки «Ок»
Указанная сумма мгновенна будет зачислена на Ваш счет и Вы сможете активировать продление услуги хостинга.
Внимание!
В течении следующих 7 (семи) дней Вам необходимо внести на баланс сумму не меньше чем сумма заказанная в «Обещанном платеже». Услугой «Обещанный платеж» могут пользоваться абоненты у которых нет непогашенных задолжностей по данной услуге.
Обратитесь к нашим операторам ни один Ваш вопрос не останется без ответа.
При обращении в Службу Технической Поддержки, обязательно укажите Ваш домен, также любую другую контактную информацию которая поможет нам идентифицировать Вас как клиента. И самое важное — как можно детальнее опишите суть проблемы и тогда решение будет более оперативным!
Функции Arduino: void loop() и void setup() — 4 особенности

Программирование
Arduino IDE — это интегрированная среда разработки для контроллеров Arduino, которая позволяет написать, загрузить и отладить код. Её можно скачать с официального сайта: www.arduino.cc.
Среда программирования Arduino включает в себя две важные функции setup()и loop(), которые необходимы во всех скетчах (программах). Эти функции используются для инициализации переменных и выполнения повторяющихся задач соответственно.
Setup() и loop()

Функция setup()вызывается один раз при включении или сбросе платы Arduino. Эта функция используется для инициализации переменных, настройки режимов выводов и запуска библиотек. Обычно он используется для настройки начальных условий скетча и вызывается только один раз в течение жизни скетча.
С loop()другой стороны, функция вызывается многократно в бесконечном цикле. Он используется для выполнения повторяющихся задач, таких как считывание показаний датчиков и управление исполнительными механизмами. Функция цикла является сердцем скетча и реализует большую часть логики программирования.
Пример скетча
Вот пример простого скетча Arduino, в котором используются функции setup()и loop():
В этом примере setup()функция инициализирует последовательную связь со скоростью 9600 бит/с и loop()отправляет сообщение «Привет, Arduino!» по серийному номеру и ждет 1 секунду перед повторением процесса.
Таким образом, функции setup()и loop()имеют решающее значение для среды программирования Arduino. Функция setup()используется для инициализации переменных и установки начальных условий скетча, а loop()функция используется для выполнения повторяющихся задач. Обе функции необходимы во всех скетчах Arduino.
Void setup()
void setup() <
// тут располагаются команды подпрограммы
Void loop()
Особенность кода
Еще одним важным аспектом, который следует учитывать при работе с функциями setup()и loop(), является порядок выполнения кода. Функция setup()вызывается только один раз, в начале скетча, при этом loop()функция вызывается многократно. В результате любой код, помещенный в setup()функцию, будет выполнен только один раз, а код внутри loop()функции будет выполняться несколько раз.

Например, если у вас есть переменная, которую нужно инициализировать только один раз, вы должны поместить этот код в setup()функцию. С другой стороны, если у вас есть код, который нужно выполнять многократно, например, для считывания показаний датчика или управления исполнительным механизмом, вы должны поместить этот код в loop()функцию.
Также стоит отметить, что loop()функция должна быть максимально эффективной, поскольку она будет вызываться многократно. В общем, вам следует избегать использования долго работающих функций или задержек внутри loop()функции, так как они могут привести к тому, что скетч перестанет отвечать на запросы или вызовет задержки в других задачах.
Кроме того, вы можете использовать эту setup()функцию для некоторых других важных вещей, таких как установка режимов контактов для ввода и вывода, запуск последовательной связи, настройка скорости передачи данных, подключение к Wi-Fi или другим сетевым подключениям и т. д.
Глобальные переменные
Другим важным аспектом, который следует учитывать при работе с функциями setup()и loop(), является использование глобальных переменных. Глобальные переменные — это переменные, объявленные вне какой-либо функции и доступные из любого места скетча. Эти переменные могут быть полезны для хранения значений, к которым должен обращаться несколько функций, но они также могут привести к непредвиденному поведению, если они не используются должным образом.

При работе с глобальными переменными важно инициализировать их внутри setup()функции, а не вне какой-либо функции. Это гарантирует правильную инициализацию переменных перед их использованием в loop()функции или любой другой функции. Неспособность инициализировать глобальные переменные может привести к непредсказуемому поведению и ошибкам в вашем скетче.
Также важно учитывать область действия ваших переменных. Переменная, объявленная внутри setup()функции или loop()функции, будет доступна только внутри этой функции и не будет доступна другим функциям. С другой стороны, переменная, объявленная вне какой-либо функции, доступна любой функции внутри скетча.
Еще одна вещь, которую следует учитывать, это то, что при работе с несколькими глобальными переменными важно отслеживать их значения и то, как они изменяются, поскольку это может привести к ошибкам и неожиданному поведению. Хорошей практикой было бы использование комментариев для объяснения их назначения, а также ожидаемых значений и диапазонов.
Библиотеки
Другим важным аспектом функций setup()и loop()является использование библиотек. Библиотеки — это наборы предварительно написанного кода, которые можно легко импортировать в ваш эскиз для добавления функциональности. Например, библиотека Arduino Servo позволяет управлять серводвигателями всего несколькими строками кода.

При использовании библиотек в скетче важно включить необходимые файлы заголовков библиотек в верхнюю часть скетча и вызвать соответствующие библиотечные функции внутри функций setup()и loop().
Эта setup()функция является идеальным местом для инициализации библиотечных функций, которые необходимо настроить только один раз, таких как открытие последовательного порта или инициализация сетевого подключения. Эта loop()функция является идеальным местом для вызова библиотечных функций, которые необходимо многократно выполнять, таких как считывание значений датчиков или управление исполнительными механизмами.
Также важно помнить, что некоторые библиотеки могут вызывать конфликты с другими библиотеками или с функциональностью функций setup()и loop(). Важно тщательно протестировать свой эскиз и ознакомиться с используемыми библиотеками, чтобы убедиться, что они работают должным образом и не вызывают конфликтов.
Прерывания
Еще одна важная вещь, которую следует учитывать при работе с функциями setup()и loop(), — это использование прерываний. Прерывания — это способ временной остановки нормального выполнения loop()функции для выполнения определенной задачи, такой как реакция на нажатие кнопки или показания датчика. Прерывания могут быть полезны для создания отзывчивых и эффективных скетчей, поскольку они позволяют реагировать на события без постоянного опроса датчиков или ожидания задержек в работе loop()функции.
При работе с прерываниями важно иметь в виду, что setup()функция — это место, где вы должны настроить прерывания, и loop()функция не должна быть заблокирована какой-либо задержкой или длительными функциями. Таким образом, прерывание может быть выполнено в любое время, и ваш скетч останется отзывчивым.

Также важно помнить, что код, выполняемый в подпрограмме обслуживания прерывания (ISR), должен быть как можно короче и эффективнее, поскольку он временно остановит выполнение loop()функции.
Вы также должны знать, что глобальные переменные, доступ к которым осуществляется внутри ISR, могут вызвать неожиданное поведение, если к ним также обращаются внутри loop()функции, поскольку loop()функция может быть прервана в любое время. Чтобы избежать этого, рекомендуется использовать в ISR только локальные переменные.
В заключение, прерывания — это мощный инструмент для создания отзывчивых и эффективных эскизов при работе с функциями setup()и . loop()Они позволяют реагировать на события, не опрашивая постоянно датчики и не дожидаясь задержек в работе loop()функции. Чтобы эффективно использовать прерывания, важно сконфигурировать их в setup()функции, сделать код ISR максимально коротким и эффективным, а также помнить о потенциальных конфликтах с глобальными переменными.
Конечные автоматы
Другим аспектом, который следует учитывать при работе с функциями setup()и loop(), является использование конечных автоматов. Конечные автоматы — это способ управления потоком эскиза путем разделения его на ряд состояний. Каждое состояние представляет определенный этап скетча, например инициализацию, выполнение или завершение работы. Конечные автоматы могут быть полезны для создания сложных и надежных эскизов, поскольку они позволяют организовать код и обрабатывать различные сценарии.
При работе с конечными автоматами важно помнить, что setup()функция — это место, где вы должны инициализировать начальное состояние и любые другие необходимые переменные. Затем loop()функция должна использовать оператор switch или оператор if-else для проверки текущего состояния и выполнения соответствующего кода.
Также важно помнить, что код в каждом состоянии должен быть специфичным для этого состояния и не иметь никакого влияния на другие состояния. Таким образом, скетч останется предсказуемым и легко устраняемым.
Вы также должны знать, что конечные автоматы могут использоваться в сочетании с прерываниями и библиотеками для создания сложных и чувствительных скетчей. Например, вы можете использовать прерывания для перехода между состояниями в ответ на показания датчиков или нажатия кнопок, а также использовать библиотеки для выполнения определенных задач в каждом состоянии.
В заключение можно сказать, что конечные автоматы — это мощный инструмент для создания сложных и надежных эскизов при работе с функциями setup()и . loop()Они позволяют организовать код и эффективно обрабатывать различные сценарии. Чтобы эффективно использовать конечные автоматы, важно инициализировать начальное состояние в setup()функции, использовать оператор switch или оператор if-else для проверки текущего состояния в loop()функции и сохранять код в каждом состоянии, специфичном для этого состояния. Конечные автоматы также можно использовать в сочетании с прерываниями и библиотеками для создания сложных и чувствительных скетчей.
void loop и void setup в Ардуино что это
Процедуры void loop и void setup в Aduino IDE — это первое с чем сталкивается любой человек, кто начинает знакомство с языком программирования микроконтроллеров Ардуино. Разберем для чего нужны в скетче данные функции, что следует размещать внутри циклов. Данные правила относятся ко всем платам семейства Arduino в начале изучения языка Aduino IDE, следует подробно изучить void loop в Ардуино что это.
Необходимые компоненты:
- Arduino Uno / Arduino Nano / Arduino Mega
- светодиоды и резисторы
- макетная плата
- коннекторы
Функции void loop и void setup как работают? Данные функции должны быть включены в каждую программу и вызываться только один раз, даже если один из циклов не используется. Дело в том, что когда вы запускаете микроконтроллер Ардуино, то начинает работать встроенная микропрограмма. Первое, что делает микропрограмма, это проверяет, не начала ли загружаться в микроконтроллер новая программа с компьютера.
Функции void loop, void setup в Arduino IDE

Оба цикла при запуске скетча вызываются встроенной функцией main() в файле main.cpp. Функция void setup() вызывается один раз, а функция void loop() вызывается бесконечное число раз в цикле for. Если в программе Aduino IDE имеется более одной функции void setup Arduino или void loop Arduino, то при компиляции кода в Arduino IDE появится переопределение ‘void setup()’ или переопределение ‘void loop()’ соответственно.
Скобки указывают на начало и конец функции void. Поэтому все команды должны располагаться между ними. Если вы случайно удалите или поставите лишнюю скобку, вы получите ошибку во время компиляции скетча. Процедура void setup в Ардуино вызывается только один раз и используется для назначения режима работы выходам микроконтроллера или командам, которые должны выполняться при загрузке программы.
Функция void setup Arduino IDE описание

В первом примере рассмотрим мигание светодиодом, когда команды расположены только в процедуре войд сетап. После загрузки программы в микроконтроллер и при каждой последующей перезагрузке платы, светодиод будет включаться только один раз. Если эти же команды переместить в процедуру воид луп (смотри второй пример программы далее), то светодиод будет мигать постоянно, пока на плату будет поступать питание.
Процедура void setup Ардуино синтаксис
Функция void loop Arduino IDE описание
После выполнения конфигурации в цикле void setup, программа входит в цикл void loop Ардуино, который повторяется до тех пор, пока плата включена. Если цикл содержит одну инструкцию, он будет выполняться тысячи раз в секунду. Если вы решили написать скетч для мигания светодиода от Ардуино, то необходимо добавить в скетч задержку (delay или millis) на выполнение программы, иначе мигание светодиодов будет незаметным.
Процедура void loop Ардуино синтаксис
Заключение. Таким образом, если вам нужно один раз включить светодиод или пьезодинамик для индикации начала работы устройства на микроконтроллере Arduino во время выполнения программы, лучше записать команду в функции void setup(). Если вам необходимо постоянно выполнять какое-либо действие в программе, например, выводить информацию на дисплей 1602, команду следует поместить в функцию void loop().
Arduino the Object Oriented way
In the early to mid 1990’s, programmers began coding in a new way — the Object Oriented way.
Ok, that’s a total lie. OO programming and languages had been around for years. But it was around this time that it became big commercially, spurred by the introduction of OO features to existing languages, such as C++, and by new languages and platforms such as Java
Ok, that was a total lie, too. The truth is: I learned Java back in the late 90’s and got myself a java job in 2000 or so. And that was when I personally started doing this stuff.
Object oriented programming is part of a progression in language design over the last 50 years:
People don’t usually count object oriented languages as being the fourth generation, but it fits the progression here.
What are usually called «4th-generation languages» are languages in which you specify what you want rather than how to do it. It isn’t that relevant to Arduino programming.
- Machine code
- Assembler, Macro assembler
- Compiled languages
- Block-structured languages
- Object-oriented languages
At each stage in this progression, the new programming languages provide constructs that «wrap» blocks of code that you had to write in the old one. Assembler macros wrap chunks of assembler. Compiled languages such as Fortran did the grunt work of converting expressions into assembler. «Fortran» is a shortening of «formula translation»: the new thing was that a compiler would turn «a * (b + c)» into machine code. Block-structured languages replaced the usual idioms for flow of control with «if» and «while» statements, which Wirth proved mathematically was sufficient to do anything that you could do with GOTO. Functions and subroutines and the idea of a «stack» … well, that had been around for a long time — there’s support for it on the chip. But «functions» are a formalisation of it.
At each stage of the progression it becomes easier to make more complex things. The features of the language mean that there’s fewer balls in the air as you code. Once you write a function and get it right, you no longer need to think about what is in that function — you just use it for what it does. Another very important feature is that this isolation of chunks of code makes it much easier for teams of programmers to build something.
Arduino programming — at least, what you see on the Arduino message boards — seems to be stuck at step 3. But OO coding has a great deal to offer in terms of making Arduino code simpler and more robust. it’s well worthwhile getting your head around it.
This page is about how I personally address a typical project posted on the Aruino boards, using C++ objects. It works for me. The discussion on the discussion boards is about this page is here. You may want to consider some criticisms there of this page here, although it might be worthwhile skipping some of the quibbling about using byte instead of int .
The OO Way
The OO way of programming is like building electronics, or building something mechanical, or building anything, really. You use something simple to make something moderately complicated, and those moderately complicated things to make something very complicated. The trick is: when it comes time build the very complicated thing, you work with what your moderately complicated things do and you temporarily forget about how they do it.
In our headlamp example, we have two things. We have a button that emits a short-click and a long-click. And we have a headlamp that turns on and off and that cycles brightness. If we can make those two things work, and hook them together — job done.
Adding the tail light is straightforward. Our tail light has two independent on/off variables: day/night, and braking/not braking. We program a thing that can do that, and then we program up the interactions between the things.
What is an object?
An object is a bundle of variables (holding state) and functions that operate on those variables.
Whenever you code things for an arduino this is what you wind up doing anyway. You will always have sets of variables that work togther (in OO language: that have strong cohesion), and blocks of code that mainly deal with those variables. A function is just a block of code that you have separated out and given a name. If you have a thing that needs to blink, your will inevitably have a set of variables like blinkTimeMs and blinkState to keep track of the blink, and functions named handle_blink and such.
Yes, there is also inheritance and polymorphism. This is meant to be a simple introduction to OO programming. Simply using encapsulation to manage your code is a win, compared to many things on the discussion boards.
C++, however, allows you to bundle these things together.
Sure, you can do this without classes and objects. If you code Arduino, you already are doing these things without classes and objects. All you have to do is be careful to keep track of things and it helps to give everything sensible names.
But the same applies to all of the progression of languages over the years. Assembler doesn’t allow you to do anything you can’t do with raw opcodes. Compilers don’t allow you to do anything that you can’t do in assembler. Block-structured languages don’t allow you to do anything that you can’t do with gotos. All these things do is make it easier for you — the programmer — to get it right.
Bundling your variables and code for those variables together has a few advantages.
Your code becomes easier to understand and modify, because the variables that the code needs are right there, next to the code.
It becomes much easier to create multiple objects that all do the same thing. A set of blinkers, each one with its own output pin. A pair of servos that both behave in the same way. You no longer need to declare multiple variables all with slightly different names, or have them in arrays.
It becomes easier to build compound objects, such as a pair of relays which must never be both on at the same time, requiring a delay between turning one off and the other on.
Objects can conceal parts of themselves from other objects (in fact, that’s the default). You can build an object and be confident that it will work correctly because other parts of your sketch cannot interfere with its internals. Conversely, if another part of your sketch needs to interfere with its internals, then this signals to you — the programmer — that there’s something you haven’t thought of and might need to take into account.
But the most important thing is difficult to quantify: it changes the way that you think about what you are doing, it changes the way you code.
«But,» you cry, «most sketches don’t have user interfaces!» Of course they do. A pushbutton is a user interface. It might not be a graphical interface, but it still counts. Even outputs to servos are interfaces — there isn’t any difference between a servo out and a gauge showing what the servo position would be if one was connected.
And finally, doing objects the way I suggest here makes managing asynchonous, event-driven interfaces to sketches much easier and more natural to do. Blink-without-delay for everything.
The Example Problem
In the code that is sometimes posted to the Arduino message boards, things start to get messy when coders are having to deal with several independent devices, which is to say clusters of pins — input and output.
The other symptom of a need for an OO approach is when a post appears on the board with the title «Need help combining two codes into one code! Urgent!»
The OP has a bike headlamp. this headlamp has a button that you can press 5 times to cycle through 5 output settings, and a power switch. the OP would like to have one button to control it. A long click should turn the lamp on and off, and a short click should cycle the brightness. Furthermore, when the lamp is turned on, the OP would like the arduino to cycle the light up to its previous level of brightness. The outputs to cycle the lamp should be pulses with a duration of 100ms, separated by 100ms. The output to turn the lamp on and off should simply be HIGH/LOW on a digital out.
Simple stuff — you would think. But the output clicks to cycle the lamp up to a level of brightness take time. What happens if there’s a short click while this is happening? A long click? How do the timing of the input clicks on the controller button interact with the timing of the output to the lamp? Oh, and there should be a 50ms debounce delay on the button, too.
What happens is that people try to code this up by having long chains of nested if statements, trying to account for all the possibilities. This never works out, because the number of possibilities explodes combinatorially. These sketches also tend to have a rat’s nest of variables declared at the top.
Let’s add something to the OP’s sketch — a tail light and a brake sensor. If the headlamp is on, then the tail light should flash intermittently (100ms every second). The tail light should also shine continuously if the brakes are on.
Adding this to a sketch structured in the usual way people attempt to write these things — you’d just give up. But if you code things the Object Oriented way, it becomes easy. Easier, anyway. Do-able.
Part I — the headlamp and control button
Enough! Show me the code!
Ok, let’s start with the control button. I will drop it onto pin 7.
This defines a class for the button, and a single instance of the button class named button .
Obviously, it does nothing yet. However, in the programming pattern I am describing here, we give every object a setup and a loop method (functions inside classes are called methods). The setup method of every object is invoked in the main setup , and the loop method of every object is invoked in the main loop .
And this is the key to this pattern for building Arduino projects. Every object gets a turn, even if it does nothing. And every object guarantees that it returns quickly from it’s loop method. And each object does not rely on the other objects getting their slices of time in any particular order. We rely on the fact that there is a single thread in an Ardiono sketch. Each object guarantees that at the end of each iteration of its loop , it is in a suitable state for other objects to interrogate it and call its public methods.
Notice that I have had to introduce a public declaration. As I mentioned, the default behaviour for objects is that their internals are not visible to other things or to the main sketch. Anything that needs to be visible must be in a public section.
At this stage, we can introduce the usual code for button behaviour which you have all seen a million times before.
We can see here a bit of weirdness — the button state is inside the button class, but the pin that it uses is a constant defined outside. This is a problem if you want — for instance — more than one button with similar behaviour.
To fix this, we move the pin number into the button class using a constructor. Constructors get invoked before any setup , so its important that they don’t attempt to talk to the outside world at all. They are purely for initializing the object into a sensible pre-setup state.
The colon syntax allows you to initialise things inside your class that themselves have constructors, which we will be doing later.
You can do other things inside your constructor, but in this case all we are doing is assigning a simple variable.
At this point our button is complete, except for the code for what actually gets done when a long and short click is performed. So just for testing purposes, let’s have our button change the state of a pair of LEDs on pin 8 and 9. The LED on pin 8 will change for a short click, and the LED on pin 9 will change in response to a long click.
Sans issues with the damn PCB-mount buttons jumping out of the breadboard (grr!), it works exactly as it should.
Step 2 — the light.
Next step is the light controller. It has two outputs — a power on/of and a brightness cycle. The brightness cycler switch needs pauses between clicks. For purposes of my demo, I will make the pauses long: a 250ms on and a 750ms off.
The controller needs two inputs — power on/off and brightness cycle. Our problem is: what happens if things happen while the brightness is cycling?
I’ll over-engineer this a little and make the brightness cycle a sub-object. It has two input events: a «cycle by one» and a «cancel». What state does it need? Well, it needs to know if it is currently doing a click, it needs to know when it started doing the click that it is currently doing, and it needs to know how many clicks are pending on the queue.
Without further ado, the code looks like this:
There are a few things to note about this, which I believe are good practise.
Alternatively, use typedefs.
First, any variable that holds a physical quantity should be suffixed with the unit of measurement of that quantity. This is a coding standard born of bitter experience. Variables, parameters, and functions dealing with time should be suffixed Day Min Sec or Ms accordingly. This also applies to currency, although we don’t often encounter that in Arduino programming.
Notice that the variable pin is not the same variable in the two classes. We say that they are in different «scopes». An advantage of scoping is that you don’t have to keep coming up with new and creative ways of naming your variables.
Use an enum for states. Enums are better than const int or #define when a variable might hold one of a small set of related values, because the compiler will check the types for you and make sure you are using the right one. It also means that you can use namespaces, for instance if you have several things each with an INIT state.
If tight timing is very important, then this state-driven programming style may not be appropriate.
The loop method reads any state that it needs to (millis(), pin reads, getValue() calls to other objects), and this is followed by a switch statement that operates as a state machine. We have a branch for each state that the object might be in, and each branch of the switch statement follows the form:
You can skip the final else . If the «do stuff» or the conditions are complex, move them into a function. However, the assignment of the state should be done in the switch statement in the loop. That way, by inspection of the loop alone you can map put the flow of state changes in the object.
You might notice that I don’t handle the case where a button finished being pressed but there are more presses on the queue. It doesn’t matter — the next time slice will take care of it. The key is that loop() gets called frequently, because none of the other objects hang up with delay()s .
But alternatively, then yes you can make the ‘end of click’ processing do it. The problem is that there would then be two places where whatever needs to be done to start a click gets done. A block of duplicate code. This is usually a Bad Thing.
So what you would normally do is pull out the code (the digital write and the setting of the start time) into a private function and call that from both places. If you name that function clearly (eg: beginClickDown ), then it might be reasonable to set the value of state in that function. As is often the case, it doesn’t matter what you do, so long as you are consistent and name things appropriately.
So let’s test it! I’ll modify the button click code like so:
And — it doesn’t work. Of course it doesnt: I have to gibe this new object some time slices.
And now it works like a charm. When I short-click the button four times, the LED on pin 8 switches on/off (the testing code) and the LED on pin 11 flashes 4 times slowly.
Cancel
Ok, what about cancel? Specifically, what do we do if a cancel occurs while we are in the middle of a click? What if we turn off the click, and then have another click immediately after? This requires a decision. I am going to go the simple way and have cancel simply turn off the click unconditionally. This is because I know that in this case, the sketch will be hitting cancel only when the power to the light is going to be going off, so having hanging state is not really a concern.
If we need things like cool-down periods before turning off the power — well, we would have to code for that. In this simple case, no.
So let’s test it:
And again, it works perfectly. A series of short clicks will queue up a series of flashes, and a long click will cancel them all.
The rest of the light: composition
Ok, now that we have a thing that can click the clicky thing to advance the light through its brightness levels, its time to think about power on/off.
The main thing we want is that if power goes of and then on again, we want the arduino to advance the brightness to its prior knows state.
So, lets get the basics going. We write our basic headlamp class:
Alter the button code to sent messages to that instead of the click queue
And alter the main setup and loop to include this new object,
Now, at this point I want to think about pins. I want to think of the headlamp as a single object, with a power output pin and a brightness click output pin. But the brightness pin needs to be operated by a ClickQueue. What I have will kinda work, because both the click queue and the headlamp are listening to pin 11, but that’s the wrong way to go about things: a pin should be «owned» by only one object.
So what I am going to do is to build a compound object by composition. The click queue will be part of the headlamp.
This does not mean that the Headlamp class needs to have the the ClickQueue class inside it. Instead, it means that the Headlamp class has an instance of the ClickQueue class in it.
The result looks line this:
Because the brightness clicker is part of the headlamp, the headlamp becomes responsible for setting it up with its constructor, and for calling its setup and loop methods.
Consequently, we get rid of the clickQueue instance altogether — it’s all headlamp now.
From here, we put the code into the headlamp that keeps track of what the brightness is and turns things on and off. The result looks like this:
You may notice that I have had to add a «addClicks» method to the clicker. This is not a big deal.
You may also notice that I have added a 50ms delay to the power toggle. This is a potential source of trouble. But the only thing that is going to happen is that a short click might be ignored after a long click to turn the lamp on. This is something we can live with.
And you know what? It works exactly as it should. Short clicks increment the brightness when the lamp is on; Long clicks turn it off and on; and when the lamp is turned on there’s a series of clicks to bring it up to the previous level of brightness.
Job done. Well — there’s some refinements to make.
An aside
Re-reading this after having not visited for a few months, there’s something worth noting in this section. The comment «now that we have a thing that can click the clicky thing». I don’t say «I have a function» to do it or «come code» to do it. I have a thingy to do it.
When you code the OO way, once you have built an object you proceed to think of it as a black box. It’s like plugging an IC into a circuit. Notice that none of the code in Headlamp deals with the pin at all — Headlamp doesn’t even save the value of brightnessOutAttach. It’ relies entirely on brightnessClicker to deal with it.
Headlamp doesn’t «think» about brightnessClicker in terms of pins, timings, internal state. All it knows is that brightnessClicker is a ClickQueue.That means you can add as many clicks to it as you want, and you can at any time cancel all the clicks. That’s all. Which is good. The whole point of encapsulating code and state in a class is that once you have written (and tested!) ClickQueue you can unload from your current train-of-thought all the design you did about how it works. All you need to care about from here on in is what it does.
Separating out the button behaviour: polymorphism
It really irks me that our very abstract short-click/long-click button has a bunch of code in it that’s specific to headlamps in particular. I want to separate out the bit that worries about timing from the bit that thinks about headlamps.
The way I am going to do this is with inheritane. My base button class will only think about timings, and will call a longClick and shortClick method. But here’s the thing: these methods will not be implemented. It looks like this:
We then have what we call a subclass of button whose job it is to know how to work a headlight. Crucially, that subclass has everything that a button has — it uses the button’s setup and loop . So the only thing it needs is that it needs to supply the definition of what to do if there’s a short and a long click.
With this change, the sketch — well — does exactly what it did before :). But now, if we want to make other long/short clicky buttons on difefrent pins doing different things, it’s easy.
Wiring up the buttons with constructors: composition by reference
The next thing that irritates me is how the HeadlampControlButton object is tied to the headlamp object defined in the main part of the sketch. What if we want two headlamps and buttons? What if we want to call it something different?
So what I will do is have a HeadlampControlButton hold a reference to its headlight. It is given this reference in the constructor, which means that the thing that builds it is responsible for working out which headlight it is supposed to be tied to.
Because the object does not «own» the headlight, it will not call the setup and loop methds.
It looks a little like this:
At this point, the main part of the sketch looks like this
See how it is now the declarations in the main part of the sketch that defines who uses what pins and how they interact. Each component only «knows» about its own little world and can be swapped in and out on one place without needing other coding.
The full, working sketch
As you have been so patient looking at these code fragments and snippets, here is the full thing.
Part II — adding the tail light
Now, one of the the motivations for going to all this trouble is to demonstrate that it’s reasonably easy to modify and extend tour sketch. I will add a tail and brake light that flashes intermittently when the headlamp is on and comes on when the brake is hit.
Before I do, stop and think what sort of a challenge this would be with the usual way of coding — one big loop method doing the lamp on of, keeping track of the brightness, bringning the brightness up when the lamp is turned in, the whole thing. Coding this way — the OO way — means that adding another thingumajig is mostly more of the same.
Flashing Tail Light
Ok, our tail light has two independent state things — on/off, and braking/not braking — and it’s attached to a pin. Lets just code up one of those.
And we declare one, attach it to pin 12, and give it a setup and a time slice.
Great! Now, for logic — the loop. If the brake is on, then the taillight should be on. If the brake is not on and it’s day (not flashing), the LED should be off. otherwise, it should flash.
Now, for flashing, I am totally going to cheat. I want it to flash every second. You know what’s really close to a second? 1024 milliseconds. Bit 10 of millis() . And I want it to be on 1/10th of the time. You know what’s really close to 1/10? 1/8. Three bits. So I will look at three bits at position 10 to 8 of millis. If they are all off, then the light is on. That should make it flash like a boss.
I won’t bother with «if it was off before and it’s on now, then we need to turn on the pin». I’ll just unconditionally write the state to the pin. Meh.
Flashes just like a bought one! Fantastic. Now to do the rest of the state.
Hooking the taillight to the headlamp
Next thing I need to do is to have the taillight flashing only if the headlamp is on. Now, I don’t want to do a lot of surgery to the headlamp. So instead of having the headlamp push its state to the taillight, I will have the taillight pull the data from the headlamp. This means the headlamp needs to expose its isOn state. You can do this by having a method that returns the value (an accessor method), but I will just make the variable public.
This breaks some of the rules, because it means that another object can directly write to that state without the headlamp class knowing about it. This could put the object into an invalid state. YOu would not do this if you were writing a library class, meant to be used by other people.
But in this case, it’s just me personally writing this thing. So — meh. I need the taillight to hold a reference to a headlamp, and I actually don’t need the ‘flashing’ variable at all.
So, the variables at the top of the headlamp class now look like this:
The declarations in the main sketch that create our components look like this:
And the taillight looks like this:
And once again, it works. A long click turns the headlamp on and starts the flashing taillight. Short clicks advance the brightness. A long click turns everything off. Another long click starts the falshing and sends a series of clicks to the brightness to bring it back up to where it was.
Adding the brake switch
You know what? I am not going to bother with making up a brake switch object. I’ll just have the tail light read the pin itself. It’s justifiable because, well, its a brake light so its ok to have it listen to a brake pin.
Easy as. I’ll put the switch on pin 6. I’ll reorder the constructor arguments so that inputs come first, then outputs. And since the taillight now is dealing with two pins, I’ll rename pin to ledOutPin
The full, working sketch, with tail light
And here’s the final result. It seems to work exactly right.
Final thoughts
Well, that seems like a lot of code. But review what this sketch does — two inputs, one of them timer based, and three outputs. Flashing, internal state, a little routine that must be done when the light comes on. It’s all there, and it all works seamlessly.
Using the «objects where each gets a time slice» pattern, no individual step was particularly difficult to do. At each step, I could check that the object I had written so far worked. And once it worked, I mostly didn’t have to go back to revisit things.
Yes, it does require programming skills beyond the cut-and-paste cookbook approach. You actually have to know how to program in C++. I appreciate that many Arduino hobbyists are more interested in hardware and electronics than in programming. What can I say? If you want your program to do something complex, grinding away at a wall of nested if/else-if statements is a recipe for long frustrating hours and at the end of it all, you can’t be 100% confident that you really have thought of everything, caught every possible condition.
Writing this stuff is much quicker and easier than writing about it. With this approach, your new project works basically the same as your previous one. Which is good. Your code matches the physical components you have. If you decide that your bike doesn’t need a taillight, removing it from the sketch above is just a matter of a couple of lines, not of hunting through the code to find every place where it is mentioned.
The sketch has some issues, and I wouldn’t sell it like that. The way the taillight depends on the lamp is not good. What I probably need is a ‘pushbutton to toggle’ class. A software t-flipflop. Both the headlamp and the brake light would read that. I’d have a ‘runnable’ abstract class for things that have a setup and loop, and manage them with an array rather than hard-coding individual things into the main setup and loop.
But, there you have it. This is one way that a dude who has been making a living programming for 30 years addresses Arduino projects.
Appendix — automatically managing runnables
One of the irritations of this pattern is making sure that you give a time-slice to every component. Your main setup and loop have to include everything explicitly by name.
As every one of these objects has a setup and loop method, there’s a pattern there. Perhaps there should be an abstract superclass named — let’s say Runnable — and all these classes should inherit that class:
That way, you just keep an array of runnables and iterate through them in your loop and setup .
Pretty snazzy. But maintianing that array of pointers is a bit of a wart. What we can do, however, is to have the Runnable constructors automagically build a linked list of runnables.
The main section of the sketch now looks like this:
A little spooky, because all the runnable objects get put on the queue invisibly. But it works. And you can remove the bit inside Headlamp where it calls the setup and loop of its embedded ClickQueue . The embedded ClickQueue also automagically adds itself to the list of Runnables
Why do this? Well — I like it that way. Sometimes, it just comes down to personal preference. I like the way that, using this pattern, you simply create a runnable object and suddenly it comes alive. You can make an array of them if you want and they all come alive.
Now you may be wondering, «Wait! What? What order will things get run in?»
It doesn’t matter. Everything gets a time-slice. We could write this thing so that each loop , one random runnable was selected and run. It would still work. Everything would (most probably) get a time-slice in a reasonable amount of time.
The key to that is that if an object exposes methods that defer things to be done later, during their loop, it must be done in such a way that it can handle any number of calls on those methods before loop gets done.
That is, any object that works this way must either maintain some sort of queue of things-to-do, or expose a «ready» method that the things that use it interrogate. In our case, the clickqueue holds a queue of pending events simply by keeping the number of pending clicks. More complex things that use this model may need to maintain some sort of buffer or use the heap.
Can this result in deadlocks? Sure! If your buffers aren’t big enough, if you are asking your arduino to do something that it just plain doesn’t have enough memory for, if your serial cable falls out, or (here’s the salient bit) if you program it up wrong.
But even then, using objects makes it much easier do draw up dependency and data-flow diagrams to try to work out what’s jamming, because you already know what rectangles you need to draw and where the arrows go.
