const int analogInPin = A0; // Analog input pin that the potentiometer is attached toint sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)void setup() {
Serial.begin(9600);
pinMode(2,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
pinMode(10, OUTPUT);
}void loop() {
// read the analog in value:
sensorValue = analogRead(analogInPin);
// map it to the range of the analog out:
outputValue = map(sensorValue, 0, 1023, 0, 5);
switch(int(outputValue)){
case 0:
{
digitalWrite(2, HIGH);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
break;
}
case 1:
{
digitalWrite(2, LOW);
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
break;
}
case 2:
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
break;
}
case 3:
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7, HIGH);
digitalWrite(8, LOW);
break;
}
case 4:
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, HIGH);
break;
}
}digitalWrite(10, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(10, LOW); // turn the LED off by making the voltage LOW
delay(1000);// print the results to the Serial Monitor:
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);delay(2);
}
Как мы видим, все действия проходят один за другим, и даже при изменении входного напряжения на аналоговом входе, светодиоды переключаться только тогда, когда до них дойдет очередь, что бы исправить данную ситуацию и при этом у нас все работало как рас и применяется очереди в FreeRTOS.
Очередь позволяет накапливать данные которые необходимо обработать, до тех пор пока часть программы которой нужны эти данные не заберет их для обработки.
Программный код который реализует работу нашего алгоритма с помощью очереди в среде FreeRTOS:
#include <Arduino_FreeRTOS.h>
#include <queue.h>
QueueHandle_t queue_1;
void TaskADC( void *pvParameters );
void TaskLenta( void *pvParameters );
void TaskBlink( void *pvParameters );
void setup() {
queue_1 = xQueueCreate(4, sizeof(int));
if (queue_1 == NULL) {
Serial.println("Queue can not be created");
}
xTaskCreate(TaskADC, "TaskADC", 128, NULL, 2,NULL);
xTaskCreate(TaskLenta, "Blink2", 128, NULL, 2, NULL);
xTaskCreate(TaskBlink, "Blink3", 128, NULL, 2, NULL);
}
void loop()
{
// Empty. Things are done in Tasks.
}
void TaskADC (void *pvParameters){
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
int sensorValue = 0;
int outputValue = 0;
Serial.begin(9600);
for (;;) // задача должна никогда не прекращаться или прерываться
{
// read the analog in value:
sensorValue = analogRead(analogInPin);
// map it to the range of the analog out:
outputValue = map(sensorValue, 0, 1023, 0, 5);
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
xQueueSend(queue_1, &outputValue, portMAX_DELAY);
vTaskDelay( 10 / portTICK_PERIOD_MS );
}
}
void TaskLenta(void *pvParameters){
int outputValue = 0; // value output to the PWM (analog out)
pinMode(2,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
for (;;) // задача должна никогда не прекращаться или прерываться
{
if (xQueueReceive(queue_1, &outputValue, portMAX_DELAY) == pdPASS) {
switch(int(outputValue)){
case 0:
{
digitalWrite(2, HIGH);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
break;
}
case 1:
{
digitalWrite(2, LOW);
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
break;
}
case 2:
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
break;
}
case 3:
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7 HIGH);
digitalWrite(8, LOW);
break;
}
case 4:
{
digitalWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, HIGH);
break;
}
}
}
vTaskDelay( 1 / portTICK_PERIOD_MS ); // ждать одну секунду
}
}
void TaskBlink(void *pvParameters) // Это задача.
{
(void) pvParameters;
// настроить цифровой вывод 10 на выход.
pinMode(10,OUTPUT);
for (;;) // задача должна никогда не прекращаться или прерываться
{
digitalWrite(10, HIGH); // включить светодиод (HIGH – это уровень напряжения)
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // ждать одну секунду
digitalWrite(10, LOW); // выключить светодиод, установив напряжение LOW
vTaskDelay( 1000 / portTICK_PERIOD_MS ); // ждать одну секунду
}
}
В данном программном коде мы использовали очередь, то есть наш АЦП выполнил преобразование и поместил данные в очередь, программа которая использует данные с АЦП, по мере возможности забирает их с очереди и обрабатывает. Таким образом у нас нет данных которые могли не обработаться и потеряться. Конечно, необходимо следить, что бы очередь не переполнялась, иначе мы все таки потеряем часть данных.
Функция которая отвечает за создание очереди xQueueHandle xQueueCreate( unsigned portBASE_TYPE uxQueueLength, unsigned portBASE_TYPE uxItemSize);
где:
uxQueueLength | Максимальное количество элементов, которое можно сохранить в очереди в любой момент времени. |
uxItemSize | Размер в байтах каждого элемента данных, который можно сохранить в очереди. |
возвращаемое значение | Если функция вернула не NULL, то значит очередь создана успешно. Возвращенная величина в этом случае должна быть сохранена как хендл к созданной очереди. |