Приветствую всех! Я новичок по части Arduino, но у меня есть опыт разработки приложений (по большей части на языках высокого уровня). Вероятно, именно поэтому я написал слово "приложение" в заголовке. Возможно, я ошибся веткой/форумом. В таком случае, просьба не кидаться тапками, а просто направить куда нужно. Спасибо. Я понимаю, что программы пишутся по-разному, в зависимости от платформы и языка. Но, тем не менее, меня смутил первый же скетч: Код (C++): void loop() { digitalWrite(13, HIGH); delay(1000); digitalWrite(13, LOW); delay(1000); } Конкретно, мне не нравится вызов delay(). Такой подход вынуждает все системы ждать, пока мы моргаем светодиодом. Возможно, иногда это вполне приемлемо и оправдано, но иногда требуется, чтобы несколько систем работали сообща. В этом случае, такой подход не будет работать. Да, есть TimedAction. Это позволит нам запускать несколько задач одновременно. В основном, это решает проблемы. Но мне больше нравится несколько другой подход (в целом, думаю, TimedAction реализован примерно также). Мое решение основано на функции millis(). Идея в том, чтобы в цикле обновлять состояния всех систем, на основе времени, прошедшего с предыдущего обновления. Не блокировать поток исполнения вызовами delay(), постоянно наращивать время исполнения операций (короче говоря, интегрирование). Скорее всего, я изобретаю велосипед. Пардон, просто не нашел ответов на вопросы в гугле, да и хочется с кем-нибудь обсудить свои мысли. Весь код далее написан "на коленке" и не претендует на то, чтобы быть конечным вариантом. Прошу не относиться к нему слишком строго, это исключительно для демонстрации концепции (честно говоря, я даже не компилировал его xD ). Файл Parallel.h Код (C++): class Parallel { private: unsigned long prevTime; unsigned long stepTime; public: Parallel(); public: void loop(); unsigned long getDeltaTime(); }; Файл Parallel.сpp Код (C++): #include "Parallel.h" Parallel::Parallel() : prevTime(0) { } void Parallel::loop() { unsigned long tmp = millis(); stepTime = tmp - prevTime; prevTime = tmp; } unsigned long Parallel::getDeltaTime() { return stepTime; } Создаем один единственный экземпляр этого класса (а лучше вообще сделаем его синглтоном, если это возможно). Метод Parallel::loop() вызываем в каждом цикле Arduino. Таким образом мы всегда будем знать, сколько времени длился предыдущий цикл обновления. Далее, предположим у нас есть помпа, отвечающая за полив растения. В простом случае помпа включается на определенное время, рассчитанное на основе его пропускной способности. В таком случае, можно написать примерно следующее: Файл Watering.h Код (C++): class Parallel; class Watering { private: Parallel *parallel; boolean started; boolean inProcess; unsigned long currentProcessTime; unsigned long fullProcessTime; public: Watering(Parallel *p, unsigned long time); public: void loop(); void start(); }; Файл Watering.cpp Код (C++): #include "Watering.h" #include "Parallel.h" Watering::Watering(Parallel *p, unsigned long time) : parallel(p), started(false), inProcess(false), currentProcessTime(0), fullProcessTime(time) { } void Watering::loop() { if(inProcess) { if(!started) { // enable pump } else { processTime += parallel->getDeltaTime(); if(processTime > fullProcessTime) { inProcess = false; // sisable pump } } } } void Watering::start() { inProcess = true; } Основной файл: Код (C++): #include "Parallel.h" #include "Watering.h" Parallel parallel(); Watering watering(¶llel, 10000); boolean button_clicked() { // return true, if button clicked } void setup() { } void loop() { if(button_clicked()) { watering.start(); } parallel.loop(); watering.loop(); } (Мне кажется, код достаточно простой, но если нужно, я напишу комментарии). Я пока не в курсе, чем точно отличается язык программирования arduino от C++, но если это возможно, я бы сделал абстрактный класс, пронаследовал от него мой мой класс Watering и прочие подобные классы. Еще я бы создал диспетчер задач, которые бы инкапсулировал в себе обновления всех классов, типа Watering (вызов loop()). Да, я привык экономить время разработки за счет использования памяти. Да, я понимаю, что такое решение, скорее всего, использует больше памяти. Да, я понимаю, что у меня теперь мало памяти) Но тем не менее, те, кто дочитал до этого места, что вы думаете об этом? А как вы организуете свой код? Вероятно, не стоит создавать диспетчер (наследование нужно как раз для него, так что без диспетчера не нужно и наследование), так мы сэкономим память. Но в целом мне такой подход нравится. Всем спасибо за внимание )
TL;DR Отформатируйте в Wiki, просигнальте @acos Ничем, абсолютно, кроме базовой библиотеки, которая не есть часть языка.
Лисапед. А вот мой, почитай https://github.com/DetSimen/Arduino- и https://github.com/DetSimen/Arduino-MessageList
Вот еще один вариант http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov ПС: Попробуйте написать несколько рабочих программ в вашем стиле. А потом скажете ваши ощущения. ППС: Ваш метод он очень сырой, но если отшлифовать, то будет понятен не всем.
Простите, не понял что значит отформатировать в вики. Спасибо за ответ! Обязательно попробую! Я только все время боюсь, что не хватит памяти именно из-за этого оверхеда. Пока программы маленькие все, конечно, хорошо. С другой стороны, надо и о структуре кода заботиться. Если я правильно понял, то первое это как раз что то типа TimedAction. Про второе - я пока не думал, как организовать межклассовое взаимодействие, и очередь сообщений проверенный способ, но вот пихать в очередь сообщения про время исполнения мне не кажется очень хорошей идеей (может быть не совсем правильно понял вашу идею). Очень похоже на то что предлагаю я, только у меня еще есть один единый класс отвечающий за время. На счет понятен не всем - ну, в целом, тут нет ничего сложного. Да и я бы не стал писать что-то очень сложное с точки зрения структуры, потому что боюсь оверхеда. Думаю, буду пытаться искать компромисные решения по удобству/затратам памяти. А вот ваш совет по поводу написать пару программ приму. Тем более, насколько я понял, подобный подход все же используют и это не самая плохая идея.
Хотел сказать, что в принципе сойдет за статью в Wiki, если немного отшлифовать и соответственно оформить.
Эм.. просто вы написали TL;DR. И мне казалось что в вики стоит оформлять только то, что представляется нормальным подходом. А я как раз спрашивал о праве такого подхода на существование.
Код писался на коленке не особо задумываясь как именно это должно выглядеть, а только как это может выглядеть. Для статьи надо доработать. Ну и если делать что-то вроде фреймворка, то нужно предусмотреть способы взаимодействия таких классов (как у меня описано). Мне нравится очереди сообщений, как у @DetSimen, но, вероятно, я бы сделал по-другому.