回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【花雕学编程】Arduino FreeRTOS 之控制多个执行器 简单

头像 驴友花雕 2024.10.18 40 0

000-=.jpg

Arduino FreeRTOS是一个结合了Arduino平台和FreeRTOS实时操作系统(RTOS)的概念。为了全面详细地解释这个概念,我们可以从以下几个方面进行阐述:

一、Arduino平台
Arduino是一个开源的硬件和软件平台,旨在简化电子设备的原型设计和开发。它包含了一系列基于易用硬件和软件的微控制器,以及一个用于编写和上传代码的集成开发环境(IDE)。Arduino平台以其简洁的编程接口和丰富的扩展功能,成为了电子爱好者、设计师、工程师和艺术家们的首选工具。

二、FreeRTOS实时操作系统(RTOS)
FreeRTOS是一个开源的、轻量级的实时操作系统内核,专为嵌入式设备设计。它提供了任务管理、时间管理、信号量、消息队列、内存管理、软件定时器等一系列功能,以满足较小系统的需求。FreeRTOS以其源码公开、可移植、可裁减和调度策略灵活的特点,受到了广大嵌入式开发者的青睐。

三、Arduino FreeRTOS
1、定义:Arduino FreeRTOS是指在Arduino平台上运行FreeRTOS实时操作系统的解决方案。它允许开发者在Arduino设备上实现多任务并行处理,从而提高程序的灵活性和响应性。

2、功能:
多任务处理:使用FreeRTOS,开发者可以在Arduino上同时运行多个任务,每个任务独立执行不同的操作。这有助于将复杂的项目分解为多个并发执行的部分,从而提高开发效率。
实时性要求高的应用:FreeRTOS能够确保任务按照预定的时间约束执行,满足实时性要求。通过设置任务的优先级和时间片轮转调度策略,开发者可以控制任务的执行顺序和频率。
通信与同步:FreeRTOS提供了多种通信和同步机制,如队列、信号量、互斥锁等。这些机制有助于在不同的任务之间进行数据交换和同步操作,实现任务之间的协作。
低功耗应用:FreeRTOS提供了休眠和唤醒机制,有助于优化功耗。开发者可以将某些任务设置为休眠状态,在需要时唤醒它们来执行操作,从而减少功耗。

3、优势:
提高程序的复杂性和功能:通过多任务并行处理,Arduino FreeRTOS允许开发者实现更复杂的软件架构和更高效的代码执行。
增强实时性:FreeRTOS确保了任务的实时响应,这对于需要精确时间控制的应用至关重要。
简化编程:将复杂的逻辑分解为多个任务,使得代码更易于理解和维护。
移植性:FreeRTOS支持多种微控制器平台,使得基于FreeRTOS的项目在不同硬件间的移植变得更加容易。

4、注意事项:
虽然FreeRTOS带来了多任务的优势,但也会增加编程难度和调试工作。因此,在选择是否使用FreeRTOS时,开发者需要权衡利弊。
在使用FreeRTOS时,开发者需要注意任务堆栈大小、优先级设置等参数,以确保系统的稳定性和可靠性。
综上所述,Arduino FreeRTOS是一个结合了Arduino平台和FreeRTOS实时操作系统的强大解决方案。它允许开发者在Arduino设备上实现多任务并行处理,提高程序的复杂性和功能,同时保持代码的可读性和可靠性。
 

00-.jpg

Arduino FreeRTOS 之控制多个执行器

一、概述
在嵌入式系统中,控制多个执行器是常见的需求,尤其是在复杂的自动化和实时控制应用中。使用 Arduino FreeRTOS,可以方便地管理和调度多个执行器的控制任务,确保系统的高效性和稳定性。执行器可以包括电机、舵机、阀门、传感器等,通常需要同时或交替操作,以实现特定功能。

二、主要特点
多任务管理:
FreeRTOS 支持多个任务的并发执行,用户可以为每个执行器创建独立的任务,从而实现多线程控制。这使得系统能够同时处理多个执行器的状态和控制指令。
优先级调度:
FreeRTOS 提供优先级调度机制,可以根据任务的紧急程度和重要性设置不同的优先级,确保关键任务能够及时执行。例如,紧急的安全控制任务可以被设置为高优先级,而不那么重要的监测任务可以设置为低优先级。
任务间通信:
FreeRTOS 提供多种机制(如消息队列、信号量和事件组)用于任务之间的通信和同步。这对于协调多个执行器的操作至关重要,确保数据的一致性和任务的协调执行。
资源管理:
在控制多个执行器时,需合理管理系统资源(如内存和CPU时间),FreeRTOS 的任务管理和调度机制可以有效防止资源争用和冲突。
时间管理:
FreeRTOS 支持定时器和延时功能,用户可以设定任务在特定时间后执行或周期性执行。这有助于定期控制执行器的状态,进行周期性监测和调整。

三、应用场景
自动化生产线:
在工业自动化中,多个执行器(如电机、传送带、机器人手臂等)需要协调工作,FreeRTOS 可以管理这些任务,确保生产线的高效运转。
智能家居系统:
在智能家居中,多个执行器(如灯光、窗帘、温控设备等)需要根据用户指令或传感器数据进行调节,FreeRTOS 可以实现灵活的控制和管理。
机器人控制:
在移动机器人中,多个执行器(如舵机、驱动电机、传感器等)需要实时协调,以实现平稳的移动和任务执行,FreeRTOS 能够提供必要的任务调度和管理。
环境监测系统:
在环境监测应用中,多种传感器和执行器(如风扇、水泵等)需要根据传感器数据进行实时控制,FreeRTOS 可以有效管理这些任务。
无人机控制:
在无人机系统中,多个执行器(如电机、舵机和传感器)需要协调工作,FreeRTOS 提供的多任务管理可以确保无人机在飞行中的稳定性和响应性。

四、注意事项
任务优先级设计:
在设计任务优先级时,需考虑每个执行器的控制需求,合理分配优先级,以避免优先级反转和任务饥饿现象。
实时性要求:
控制多个执行器时,需确保系统的实时性能,避免延迟影响任务执行。可以通过优化任务调度和减少任务切换来提升实时性。
资源管理:
需对系统资源进行合理管理,避免过多任务同时运行导致的资源争用,确保系统稳定性。
调试与监控:
在实际应用中,需进行充分的调试和监控,以确保系统的稳定性和可靠性。可以通过串口输出任务状态和执行情况进行监控。
任务间通信:
在设计任务间通信机制时,需选择合适的同步方式,避免死锁和竞态条件,确保数据的一致性和任务的协调执行。

总结
Arduino FreeRTOS 之控制多个执行器为复杂的自动化和实时控制应用提供了高效的解决方案。通过多任务管理、优先级调度和任务间通信,能够实现对多个执行器的灵活控制和协调。广泛应用于自动化生产、智能家居和机器人等领域。在实施过程中,需要关注任务优先级设计、实时性要求和资源管理等问题,以确保系统的高效性和可靠性。合理的设计与优化将推动该技术在嵌入式系统中的应用。
 

00-3.jpg

1、控制两个LED灯的闪烁

代码
#include <Arduino_FreeRTOS.h>

void TaskBlink1(void *pvParameters);
void TaskBlink2(void *pvParameters);

void setup() {
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);

  xTaskCreate(TaskBlink1, "Blink1", 128, NULL, 1, NULL);
  xTaskCreate(TaskBlink2, "Blink2", 128, NULL, 1, NULL);

  vTaskStartScheduler();
}

void loop() {}

void TaskBlink1(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    digitalWrite(13, HIGH);
    vTaskDelay(500 / portTICK_PERIOD_MS);
    digitalWrite(13, LOW);
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

void TaskBlink2(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    digitalWrite(12, HIGH);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    digitalWrite(12, LOW);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

2、控制一个舵机和一个LED灯
 

代码
#include <Arduino_FreeRTOS.h>
#include <Servo.h>

Servo myServo;

void TaskServo(void *pvParameters);
void TaskLED(void *pvParameters);

void setup() {
  myServo.attach(9);
  pinMode(13, OUTPUT);

  xTaskCreate(TaskServo, "Servo", 128, NULL, 1, NULL);
  xTaskCreate(TaskLED, "LED", 128, NULL, 1, NULL);

  vTaskStartScheduler();
}

void loop() {}

void TaskServo(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    myServo.write(0);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    myServo.write(180);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void TaskLED(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    digitalWrite(13, HIGH);
    vTaskDelay(500 / portTICK_PERIOD_MS);
    digitalWrite(13, LOW);
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

3、控制两个步进电机

代码
#include <Arduino_FreeRTOS.h>
#include <Stepper.h>

#define STEPS 100

Stepper stepper1(STEPS, 8, 9, 10, 11);
Stepper stepper2(STEPS, 4, 5, 6, 7);

void TaskStepper1(void *pvParameters);
void TaskStepper2(void *pvParameters);

void setup() {
  stepper1.setSpeed(60);
  stepper2.setSpeed(30);

  xTaskCreate(TaskStepper1, "Stepper1", 128, NULL, 1, NULL);
  xTaskCreate(TaskStepper2, "Stepper2", 128, NULL, 1, NULL);

  vTaskStartScheduler();
}

void loop() {}

void TaskStepper1(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    stepper1.step(50);
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

void TaskStepper2(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    stepper2.step(100);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

要点解读
任务创建与调度:每个示例程序都创建了多个任务,并通过xTaskCreate函数将其添加到调度器。调度器会确保每个任务按设定的时间片轮流运行。
延迟机制:使用vTaskDelay函数进行任务延迟,以在任务之间创建时间间隔,从而避免任务之间的冲突。
硬件资源初始化:每个示例程序在setup函数中初始化硬件资源,如设置引脚模式、舵机或步进电机参数。
任务无限循环:所有任务函数都使用无限循环(for(;;))来持续运行任务,保证了任务在FreeRTOS环境下不会退出。
任务优先级和堆栈大小:通过xTaskCreate函数可以设置任务的优先级和堆栈大小,从而优化任务的运行效率和资源分配。

 

00-9.jpg

4、控制多个舵机

代码
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>
#include <Servo.h>

// 定义三个舵机对象
Servo servo1;
Servo servo2;
Servo servo3;

// 定义任务句柄
TaskHandle_t servoTask1Handle = NULL;
TaskHandle_t servoTask2Handle = NULL;
TaskHandle_t servoTask3Handle = NULL;

// 舵机控制任务函数
void servoTask1(void* pvParameters) {
    while (1) {
        servo1.write(90);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        servo1.write(0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void servoTask2(void* pvParameters) {
    while (1) {
        servo2.write(180);
        vTaskDelay(1500 / portTICK_PERIOD_MS);
        servo2.write(90);
        vTaskDelay(1500 / portTICK_PERIOD_MS);
    }
}

void servoTask3(void* pvParameters) {
    while (1) {
        servo3.write(45);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        servo3.write(135);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

void setup() {
    Serial.begin(9600);
    servo1.attach(9);
    servo2.attach(10);
    servo3.attach(11);
    // 创建舵机控制任务
    xTaskCreate(servoTask1, "ServoTask1", 128, NULL, 1, &servoTask1Handle);
    xTaskCreate(servoTask2, "ServoTask2", 128, NULL, 2, &servoTask2Handle);
    xTaskCreate(servoTask3, "ServoTask3", 128, NULL, 3, &servoTask3Handle);
}

void loop() {
    // 无需在 loop 中执行任何操作,因为任务由 FreeRTOS 管理
}

要点解读:
硬件定义:定义了三个Servo对象代表三个舵机。在setup函数中,将舵机连接到特定的引脚。
任务定义:为每个舵机创建一个任务函数,分别控制不同舵机的运动。每个任务函数中包含了舵机的具体控制逻辑,如设置角度和延迟时间。
任务句柄:使用任务句柄来管理任务的创建和删除。在这个例子中,为每个舵机任务分配了一个任务句柄。
任务创建:在setup函数中,使用xTaskCreate函数创建三个舵机控制任务,并指定任务的名称、栈大小、参数、优先级和任务句柄。
主循环空闲:在loop函数中不执行任何操作,因为所有的任务都由 FreeRTOS 进行管理和调度。

5、控制多个直流电机

代码
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>
#include <AFMotor.h>

// 定义三个电机对象
AF_DCMotor motor1(1);
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);

// 定义任务句柄
TaskHandle_t motorTask1Handle = NULL;
TaskHandle_t motorTask2Handle = NULL;
TaskHandle_t motorTask3Handle = NULL;

// 电机控制任务函数
void motorTask1(void* pvParameters) {
    while (1) {
        motor1.setSpeed(150);
        motor1.run(FORWARD);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        motor1.setSpeed(0);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void motorTask2(void* pvParameters) {
    while (1) {
        motor2.setSpeed(200);
        motor2.run(BACKWARD);
        vTaskDelay(2500 / portTICK_PERIOD_MS);
        motor2.setSpeed(0);
        vTaskDelay(1500 / portTICK_PERIOD_MS);
    }
}

void motorTask3(void* pvParameters) {
    while (1) {
        motor3.setSpeed(100);
        motor3.run(FORWARD);
        vTaskDelay(3000 / portTICK_PERIOD_MS);
        motor3.setSpeed(0);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

void setup() {
    Serial.begin(9600);
    // 创建电机控制任务
    xTaskCreate(motorTask1, "MotorTask1", 128, NULL, 1, &motorTask1Handle);
    xTaskCreate(motorTask2, "MotorTask2", 128, NULL, 2, &motorTask2Handle);
    xTaskCreate(motorTask3, "MotorTask3", 128, NULL, 3, &motorTask3Handle);
}

void loop() {
    // 无需在 loop 中执行任何操作,因为任务由 FreeRTOS 管理
}

要点解读:
硬件定义:使用AFMotor库定义了三个直流电机对象。在setup函数中初始化电机。
任务定义:为每个电机创建一个任务函数,控制电机的速度和方向。任务函数中包含了电机的具体控制逻辑和延迟时间。
任务句柄:与案例一类似,使用任务句柄管理任务。
任务创建:使用xTaskCreate函数创建三个电机控制任务,并设置不同的优先级。
主循环空闲:主循环不执行任何操作,由 FreeRTOS 管理任务的执行。

6、控制多个 LED 和蜂鸣器

 

代码
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>

// 定义 LED 和蜂鸣器引脚
const int led1Pin = 2;
const int led2Pin = 3;
const int led3Pin = 4;
const int buzzerPin = 5;

// 定义任务句柄
TaskHandle_t ledTask1Handle = NULL;
TaskHandle_t ledTask2Handle = NULL;
TaskHandle_t ledTask3Handle = NULL;
TaskHandle_t buzzerTaskHandle = NULL;

// LED 控制任务函数
void ledTask1(void* pvParameters) {
    while (1) {
        digitalWrite(led1Pin, HIGH);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        digitalWrite(led1Pin, LOW);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void ledTask2(void* pvParameters) {
    while (1) {
        digitalWrite(led2Pin, HIGH);
        vTaskDelay(1500 / portTICK_PERIOD_MS);
        digitalWrite(led2Pin, LOW);
        vTaskDelay(1500 / portTICK_PERIOD_MS);
    }
}

void ledTask3(void* pvParameters) {
    while (1) {
        digitalWrite(led3Pin, HIGH);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        digitalWrite(led3Pin, LOW);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
}

// 蜂鸣器控制任务函数
void buzzerTask(void* pvParameters) {
    while (1) {
        digitalWrite(buzzerPin, HIGH);
        vTaskDelay(500 / portTICK_PERIOD_MS);
        digitalWrite(buzzerPin, LOW);
        vTaskDelay(500 / portTICK_PERIOD_MS);
    }
}

void setup() {
    Serial.begin(9600);
    pinMode(led1Pin, OUTPUT);
    pinMode(led2Pin, OUTPUT);
    pinMode(led3Pin, OUTPUT);
    pinMode(buzzerPin, OUTPUT);
    // 创建 LED 和蜂鸣器控制任务
    xTaskCreate(ledTask1, "LedTask1", 128, NULL, 1, &ledTask1Handle);
    xTaskCreate(ledTask2, "LedTask2", 128, NULL, 2, &ledTask2Handle);
    xTaskCreate(ledTask3, "LedTask3", 128, NULL, 3, &ledTask3Handle);
    xTaskCreate(buzzerTask, "BuzzerTask", 128, NULL, 4, &buzzerTaskHandle);
}

void loop() {
    // 无需在 loop 中执行任何操作,因为任务由 FreeRTOS 管理
}

要点解读:
硬件定义:定义了 LED 和蜂鸣器的引脚。在setup函数中,将引脚设置为输出模式。
任务定义:为每个 LED 和蜂鸣器创建一个任务函数。LED 任务控制 LED 的闪烁,蜂鸣器任务控制蜂鸣器的鸣叫。
任务句柄:使用任务句柄管理任务。
任务创建:使用xTaskCreate函数创建四个任务,分别控制三个 LED 和一个蜂鸣器。
主循环空闲:主循环不执行任何操作,由 FreeRTOS 管理任务的执行。

 

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

 

00-11.jpg
 

评论

user-avatar
icon 他的勋章
    展开更多