2016-08-07 26 views
0

私は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 
    } 
} 

答えて

1

ですが、私はタスク内でそれらを宣言したのだが、かなり良い取り組んでいます。すぐに見ることによって

1


たり、mはbinaryFrame制限を超えています...あなたはRAMの限界近くにいるようだ...

、私はmはkの約半分であることを推定し、あなたは

を定義しメモリを偽装するときに異なる動作を取得し、ローカル変数で
byte asciiFrame[18]; 
byte binaryFrame[8]; 

と全く0x0Dのはありません場合は、Mはリセットされません...

+0

あなたが一見見ると、私は** m ** ** ** 0x0D **が受信されるまでは動作しませんので、** m **は常にリセットされます。それは問題ではありません – Madon

+0

私はリセットしないと思っていません** m **は、タスクの切り替えや停止を防ぎます。 RAMについて言えば、Arduino IDEを使ってスケッチをコンパイルすると、スケッチは10,080バイト(31%)のプログラム記憶領域を使用すると言います。最大値は32,256バイトです。 グローバル変数は422バイト(20%)のダイナミックメモリを使用し、ローカル変数には1,626バイトを使用します。最大は2,048バイトです。 – Madon

+0

もう少し詳しく見ると、私は同意します...;)
Arduino_FreeRTOSが外部メモリを使用しているとは思わないようにしましょう。 あなたは確かにいくつかの独立した点滅を持っているだけで、そのような洗練されたマルチタスクのものは必要ありません。単純にBlinkWithoutDelayです。 – datafiddler

関連する問題