我有几项与 arduino 相关的任务,但其中一项需要很长时间,所以我正在考虑使用线程同时运行它们。我有一个 Arduino Mega
[更新] 四年后,我终于可以在我的 arduino mega 中安装 FreeRTOS。这是一个链接
我有几项与 arduino 相关的任务,但其中一项需要很长时间,所以我正在考虑使用线程同时运行它们。我有一个 Arduino Mega
[更新] 四年后,我终于可以在我的 arduino mega 中安装 FreeRTOS。这是一个链接
简而言之:没有。但你可以试一试: http ://www.kwartzlab.ca/2010/09/arduino-multi-threading-librar/
还没有,但我总是在大型项目中使用这个库: https ://github.com/ivanseidel/ArduinoThread
我将回调放在定时器中断中,瞧!你有在 Arduino 上运行的伪线程......
只是为了使这个线程更完整:还有一些原型线程的内存占用非常小(如果我没记错的话,可以使用几个字节)并保留线程本地的变量;非常方便且节省时间(更少的有限状态机 -> 更具可读性的代码)。
示例和代码: arduino-class / ProtoThreads wiki
只是为了让您知道您可能期望什么结果:串行通信@ 153K6 波特率,线程用于:状态二极管闪烁、时间保持、请求的功能评估、IO 处理和逻辑以及所有在 atmega328 上。
不是真正的线程,但 TimedActions 是许多用途的不错选择
http://playground.arduino.cc/Code/TimedAction#Example
当然,如果一个任务阻塞,其他任务也会阻塞,而线程可以让一个任务冻结而其他任务将继续......
不,你不能,但你可以使用定时器中断。参考:https ://www.teachmemicro.com/arduino-timer-interrupt-tutorial/
前面的答案是正确的,但是,arduino 通常运行得很快,所以如果你正确地计时你的代码,它可以或多或少地同时完成任务。
最好的做法是制作自己的函数,避免在默认的 void 循环中放入过多的真实代码
你可以使用arduinos
它专为 Arduino 环境而设计。特征:
当我需要从蓝牙/网络/串行接收新命令同时执行旧命令并且旧命令有延迟时,我会使用它。一个线程是执行以下循环的服务器线程:
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
}
Arduino 不支持多线程编程。
但是有一些解决方法,例如这个项目中的一个(您也可以从 Arduino IDE 安装它)。
似乎您必须自己定义调度时间,而在真正的多线程环境中,决定何时执行任务的是操作系统。
或者,您可以使用protothreads
直接的答案是不不不!有一些替代方案,但您不能指望 arduino mega 提供完美的多线程功能。您可以使用 arduino due 或 lenado 进行多线程,如下所示 -
void loop1(){
}
void loop2(){
}
void loop3(){
}
通常,我在后端处理这些类型的案例。您可以在服务器中运行主要代码,同时使用 Arduino 来收集输入和显示输出。在这种情况下,我更喜欢内置 wifi 的 nodemcu。
线程不!同时是的!
您可以使用 FreeRTOS 库同时运行不同的任务。 https://www.arduino.cc/reference/en/libraries/freertos/
void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );
// Now set up two tasks to run independently.
xTaskCreate(
TaskBlink
, (const portCHAR *)"Blink" // A name just for humans
, 128 // Stack size
, NULL
, 2 // priority
, NULL );
xTaskCreate(
TaskAnalogRead
, (const portCHAR *) "AnalogRead"
, 128 // This stack size can be checked & adjusted by reading Highwater
, NULL
, 1 // priority
, NULL );
void TaskBlink(void *pvParameters) // This is a task.
{
(void) pvParameters;
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
for (;;) // A Task shall never return or exit.
{
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
}
}
void TaskAnalogRead(void *pvParameters) // This is a task.
{
(void) pvParameters;
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
for (;;)
{
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
vTaskDelay(1); // one tick delay (15ms) in between reads for stability
}
}
小心点!当不同的任务试图同时到达变量时,比如 i2c 通信线或 sd 卡模块。使用信号量和互斥量 https://www.geeksforgeeks.org/mutex-vs-semaphore/。
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)();
}