Ответ 1
Короче: NO. Но вы можете дать ему шанс: http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar/
У меня есть пара задач, связанных с arduino, но одна из них занимает очень много времени, поэтому я подумал об использовании потоков для их одновременного запуска. У меня есть Arduino Mega
[Обновить] Наконец, через четыре года я могу установить FreeRTOS в свой Arduino Mega. Вот ссылка link
Короче: NO. Но вы можете дать ему шанс: http://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar/
Пока нет, но я всегда использую эту библиотеку с большими проектами: https://github.com/ivanseidel/ArduinoThread
Я помещаю обратный вызов в прерывание таймера, и вуаля! У вас есть псевдопотоки, работающие на Arduino...
Просто, чтобы сделать эту цепочку более полной: есть также protothreads, у которых очень малый объем памяти (пару байтов, если я правильно помню) и сохраняю переменные локальные для потока; очень удобно и экономить время (гораздо меньше конечных автоматов → более читаемый код).
Примеры и код: arduino-class/ProtoThreads wiki
Просто, чтобы вы знали, какие результаты вы можете ожидать: последовательная связь @153K6 обеспечивает скорость передачи данных для потоков: мигание статусных диодов, сохранение времени, оценка запрошенных функций, обработка ввода-вывода и логика и все на atmega328.
Не настоящая резьба, но TimedActions - хорошая альтернатива для многих применений
http://playground.arduino.cc/Code/TimedAction#Example
Конечно, если одна задача блокируется, другие тоже будут, в то время как потоки могут позволить одной задаче заморозить, а остальные будут продолжаться...
Предыдущий ответ верен, однако, arduino обычно работает довольно быстро, поэтому, если вы правильно используете свой код, он может выполнять задачи более или менее одновременно.
Лучшая практика - сделать свои собственные функции и не помещать слишком много реального кода в цикл void по умолчанию
Вы можете использовать arduinos
Он предназначен для среды Arduino. Особенности:
Я использую его, когда мне нужно получать новые команды из bluetooth/network/serial при выполнении старых, а старые имеют задержку в них. Один поток - это поток потока, который выполняет следующий цикл:
while (1) {
while ((n = Serial.read()) != -1) {
// do something with n, like filling a buffer
if (command_was_received) {
arduinos_create(command_func, arg);
}
}
arduinos_yield(); // context switch to other threads
}
Другой - это командный поток, который выполняет команду:
int command_func(void* arg) {
// move some servos
arduinos_delay(1000); // wait for them to move
// move some more servos
}
Нет, вы не можете, но вы можете использовать прерывание от таймера. Ref: https://www.teachmemicro.com/arduino-timer-interrupt-tutorial/
Arduino не поддерживает многопоточное программирование.
Однако были некоторые обходные пути, например, в этом проекте (вы можете установить его также из Arduino IDE).
Кажется, вам нужно самим определять время расписания, тогда как в реальной многопоточной среде именно ОС решает, когда выполнять задачи.
В качестве альтернативы вы можете использовать protothreads
Arduino не поддерживает многопоточность. Однако вы можете сделать следующую лучшую вещь и структурировать свой код вокруг конечных автоматов, работающих в режиме чередования.
Хотя существует множество способов реализовать ваши задачи в качестве конечных автоматов, я рекомендую эту библиотеку (https://github.com/Elidio/StateMachine). Эта библиотека абстрагирует большую часть процесса.
Вы можете создать конечный автомат как класс:
#include "StateMachine.h"
class STATEMACHINE(Blink) {
private:
int port;
int waitTime;
CREATE_STATE(low);
CREATE_STATE(high);
void low() {
digitalWrite(port, LOW);
*this << &STATE(high)<< waitTime;
}
void high() {
digitalWrite(port, HIGH);
*this << &STATE(low)<< waitTime;
}
public:
Blink(int port = 0, int waitTime = 0) :
port(port),
waitTime(waitTime),
INIT_STATE(low),
INIT_STATE(high)
{
pinMode(port, OUTPUT);
*this << &STATE(low);
}
};
Макрос STATEMACHINE()
абстрагирует наследование классов, макрос CREATE_STATE()
абстрагирует создание оболочки состояния, макрос INIT_STATE()
абстрагирует перенос метода, а макрос STATE()
абстрагирует ссылку на оболочку состояния в классе конечного автомата.
Переход между состояниями абстрагируется оператором <<
между классом конечного автомата и состоянием, и если вам нужен переход с отложенным состоянием, все, что вам нужно сделать, это использовать этот оператор с целым числом, где целое число - это задержка в миллисекундах.
Чтобы использовать конечный автомат, сначала вы должны создать его экземпляр. Объявление ссылки на класс в глобальном пространстве при создании экземпляра его с помощью new
в функции настройки может помочь.
Blink *led1, *led2, *led3;
void setup() {
led1 = new Blink(12, 300);
led2 = new Blink(11, 500);
led3 = new Blink(10, 700);
}
Затем вы запускаете состояния в цикле.
void loop() {
(*led2)();
(*led1)();
(*led3)();
}