私はarduino UNOのプロジェクトに取り組んでいます。私はマルチタスクのためにfreertosを使用しています。私は2つのタスクを持っています: 1-TaskLedBlink。 および2-TaskSerialP6008。 最初のタスクは指定された時間間隔ごとに2回LEDを点滅させるために使用され、 はシリアルポートからフレームを受信して戻すために使用されます。フレームは0x02で始まり、0x0Dで終わる必要があります。 0x02が受信されたら、受信フレームをという配列に追加し始めます。0x0Dを受け取った後、私はホールフレームを送ります。 その瞬間までは、プログラムはうまく動いていた。次に、asciiFrameのデコードを担当するコードブロックを追加することにしました。結果はbinaryFrameという配列に保存されます。ここでは、プログラムが奇妙に動作するようになりました。 LEDが点滅を停止し、時には時にはオフになり、シリアルデータが失われます(受信されません)。最悪の場合、プログラムは私がarduinoを再起動するまで応答しなくなります。 私はこの問題を解決するために周りを見始めたとき、私はこの行を削除したときにそれが見つかりましたbinaryFrame [m] =(asciiFrame [k] & 15)+((asciiFrame [k + 1] & 15)< < 4);プログラムは正常に動作します。この問題を解決する助けてください...ここで私は、問題は、グローバルなどの変数を宣言していたと思いコードArduino uno freertosタスクが実行を停止しました
#include <Arduino_FreeRTOS.h>
#include <semphr.h> // add the FreeRTOS functions for Semaphores (or Flags).
byte inByte = 0; // incoming serial byte
bool startByte = false;
byte asciiFrame[18]; //array to save ascci frame p6008 02 xx xx....0d max 18 bytes including 0x02 and 0x0D
byte binaryFrame[8]; //array to save binary frame p6008 (max 7 bytes + CHECKSUM)
byte i=0; //index used to select case in array
byte j=0; //index used to select byte in array to send it over serial
byte k=0; //index used to convert from ascii to binary
byte m=0; //to save data in binary frame
bool asciiFrameComplete = false; //to indicate that a complete frame(ascii mode) hs been recieved
bool binaryFrameComplete = false;
bool asciiP6008Enabled = true; //true(ascii mode) false(binary mode)
// Declare a mutex Semaphore Handle which we will use to manage the Serial Port.
// It will be used to ensure only only one Task is accessing this resource at any time.
SemaphoreHandle_t xSerialSemaphore;
// define two Tasks for DigitalRead & AnalogRead
void TaskLedBlink(void *pvParameters);
void TaskSerialP6008(void *pvParameters);
// the setup function runs once when you press reset or power the board
void setup() {
// initialize serial communication at 9600 bits per second:
pinMode(13, OUTPUT);
Serial.begin(9600);
// Semaphores are useful to stop a Task proceeding, where it should be paused to wait,
// because it is sharing a resource, such as the Serial port.
// Semaphores should only be used whilst the scheduler is running, but we can set it up here.
if (xSerialSemaphore == NULL) // Check to confirm that the Serial Semaphore has not already been created.
{
xSerialSemaphore = xSemaphoreCreateMutex(); // Create a mutex semaphore we will use to manage the Serial Port
if ((xSerialSemaphore) != NULL)
xSemaphoreGive((xSerialSemaphore)); // Make the Serial Port available for use, by "Giving" the Semaphore.
}
// Now set up two Tasks to run independently.
xTaskCreate(
TaskLedBlink
, (const portCHAR *)"LedBlink" // A name just for humans
, 128 // This stack size can be checked & adjusted by reading the Stack Highwater
, NULL
, 2 // Priority, with 1 being the highest, and 4 being the lowest.
, NULL);
xTaskCreate(
TaskSerialP6008
, (const portCHAR *) "AnalogRead"
, 256 // Stack size
, NULL
, 1 // Priority
, NULL);
// Now the Task scheduler, which takes over control of scheduling individual Tasks, is automatically started.
//vTaskStartScheduler();
}
void loop(){
// Empty. Things are done in Tasks.
}
/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/
void TaskLedBlink(void *pvParameters __attribute__((unused))) // This is a Task.
{
for (;;) // A Task shall never return or exit.
{
digitalWrite(13, HIGH);
vTaskDelay(1);
digitalWrite(13, LOW);
vTaskDelay(6);
digitalWrite(13, HIGH);
vTaskDelay(1);
digitalWrite(13, LOW);
vTaskDelay(17);
}
}
void TaskSerialP6008(void *pvParameters __attribute__((unused))) // This is a Task.
{
for (;;)
{
// read the input on analog pin 0:
//int sensorValue = analogRead(A0);
if (Serial.available()>0)
{
inByte = Serial.read();
if ((inByte == 2 || startByte)&&asciiP6008Enabled) //if 2 was received or already has been(startByte), and ascii mode is enabled
{
startByte = true; //start byte came
asciiFrame[i] = inByte; //save bytes in frame array
i++; //increment to the next case in frame array
if (inByte == 13) //end byte came
{
asciiFrameComplete = true;
startByte = false;
i=0;
if (xSemaphoreTake(xSerialSemaphore, (TickType_t) 5) == pdTRUE)
{
for (j=0;j<18&&asciiFrame[j]!=0;j++) //send frame back
Serial.write(asciiFrame[j]);
memset(asciiFrame, 0, sizeof(asciiFrame)); //then clear it
}
xSemaphoreGive(xSerialSemaphore); // Now free or "Give" the Serial Port for others.
for(k=1 ; k<sizeof(asciiFrame) ; k++)
{
if(asciiFrame[k]==13)
{
binaryFrameComplete=true;
m=0;
break;
}
if(k%2!=0)
{
binaryFrame[m]=(asciiFrame[k]&15)+((asciiFrame[k+1]&15)<<4);
m++;
}
}
// if (xSemaphoreTake(xSerialSemaphore, (TickType_t) 5) == pdTRUE)
// {
// for (j=0;j<8;j++) //send frame back
// Serial.write(binaryFrame[j]);
// memset(asciiFrame, 0, sizeof(asciiFrame)); //then clear it
// memset(binaryFrame, 0, sizeof(asciiFrame)); //then clear it
// }
// xSemaphoreGive(xSerialSemaphore); // Now free or "Give" the Serial Port for others.
}
if (i==sizeof(asciiFrame)) //if array is full ecrase received data, frame length should not exceed 18 bytes
{
memset(asciiFrame, 0, sizeof(asciiFrame)); //clear array
i=0; //init i
startByte = false;
}
}
else if(!asciiP6008Enabled) //binary enabled
{
Serial.println("binary enabled");
}
}
//vTaskDelay(1); // one tick delay (15ms) in between reads for stability
}
}
あなたが一見見ると、私は** m ** ** ** 0x0D **が受信されるまでは動作しませんので、** m **は常にリセットされます。それは問題ではありません – Madon
私はリセットしないと思っていません** m **は、タスクの切り替えや停止を防ぎます。 RAMについて言えば、Arduino IDEを使ってスケッチをコンパイルすると、スケッチは10,080バイト(31%)のプログラム記憶領域を使用すると言います。最大値は32,256バイトです。 グローバル変数は422バイト(20%)のダイナミックメモリを使用し、ローカル変数には1,626バイトを使用します。最大は2,048バイトです。 – Madon
もう少し詳しく見ると、私は同意します...;)
Arduino_FreeRTOSが外部メモリを使用しているとは思わないようにしましょう。 あなたは確かにいくつかの独立した点滅を持っているだけで、そのような洗練されたマルチタスクのものは必要ありません。単純にBlinkWithoutDelayです。 – datafiddler