espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.62k stars 7.41k forks source link

Sharing variables on between tasks #5358

Closed eswarkeshav2001 closed 2 years ago

eswarkeshav2001 commented 3 years ago

Make your question, not a Statement, inclusive. Include all pertinent information: Why I am not able to write a typical Global variable from multiple tasks and Why the if loops continuously iterate in a Task when there is no other task to run.

What you are trying to do? I am trying to Sample an ADC and Send the values to the Mobile Using BLE. Here I have Used a Hardware timer to Sample ADC once the sampling is done I want to stop the timer to optimize efficiency and when there is input from the User Via Bluetooth connection the timer should start again and the ADC sample has to be sent again. Here I haven't Implemented my BLE receiving part So well, but Used a global variable to simulate it.

Describe your system( Hardware, computer, O/S, core version, environment). Processor :Intel i5 Windows :10 Ide: arduino

Describe what is failing. When the Global variable is set by the BLE task(Task2) the Timer_turn on task (Task3 has to run). But it didn't work when I used GLOBAL variable t3 to act as a flag it didn't start the Timer_turn on task(task 3) didn't run. So I Used the actual Flag this time Timer_Turnon task in only running rest of the tasks is not running. It feels like the if condition at timer turn on task is running continuously without giving proper timer for other tasks. And then I Used Semaphore to signal the Timerturon once BLE task has completed ts work it works perfectly. But I still want to know why Flag method is going crazy and Global variable method is not working. I used freertos here. Please help me out, guys. Without knowing the answer I am not even able to sleep.

Show the shortest possible code that will duplicate the error.

void Timer_Turnon(void *parameters)
{
  while(1)
  {
    if(t3==1)
  //xSemaphoreTake(bin_sem2,portMAX_DELAY);
  { 
  { 
     timerStart(timer);
     Serial.println("Timer started again"); 
     t3=0;
  }
 }
}
} 

void BLE_Task(void *parameters)
{
   while(1)
  {
    //Serial.println("Task3 on work");
    //if(BLE_flag==1)
    {
    //BLE_flag=0;
    xSemaphoreTake(bin_sem,portMAX_DELAY);
    Serial.println("BLE");
    for (i=0;i<BUF_SIZE;i++)
  {
   if(i==0)
  {
    sprintf(Reading,"[%d",buf[i]);
  }
  else if(i==BUF_SIZE-1)
  {
    sprintf(Reading,",%d]",buf[i]);
  }
  else{
  sprintf(Reading,",%d",buf[i]); 
  }
   Serial.print(Reading);
    if (deviceConnected) {
        pTxCharacteristic->setValue(Reading);
        pTxCharacteristic->notify();
        delay(10); // bluetooth stack will go into congestion, if too many packets are sent
  }   
 }
 Serial.println();

  }
  t3=1;
  //xSemaphoreGive(bin_sem2);
 }
}

Show the EXACT error message(it doesn't work is not enough). Global Variable

There is Error Message. It just works one time it doesn't work the other time. That means I'm unable to share the global variable

12:05:14.914 -> Waiting a client connection to notify...
12:05:15.937 -> Buffer is full
12:05:15.937 -> BLE
12:05:15.937 -> [4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,4095,2638,144,25,0,901,2480,3558,..........1000]

When using flag it works promisingly and printing a single statement timer started and it doesn't give enough time for other tasks even though all the tasks are same priority level

All of this work on your part shows us that you have worked to solve YOUR problem. The more complete your issue posting is, the more likely someone will volunteer their time to help you.

If you have a Guru Meditation Error or Backtrace, **please decode it:** I don't have Backtrace or Guru Meditation Error

Hardware:

Board: ESP32 Dev Module IDE name: Arduino IDE Flash Frequency: 80Mhz Upload Speed: 115200 Computer OS: Windows 10

Description:

Describe your problem here I am trying to Sample an ADC and Send the values to the Mobile Using BLE. Here I have Used a Hardware timer to Sample ADC once the sampling is done I want to stop the timer to optimize efficiency and when there is input from the User Via Bluetooth connection the timer should start again and the ADC sample has to be sent again. Here I haven't Implemented my BLE receiving part So well, but Used a global variable to simulate it. When the Global variable is set by the BLE task(Task2) the Timer_turn on task (Task3 has to run). But it didn't work when I used GLOBAL variable t3 to act as a flag it didn't start the Timer_turn on task(task 3) didn't run. So I Used the actual Flag this time Timer_Turnon task in only running rest of the tasks is not running. It feels like the if condition at timer turn on task is running continuously without giving proper timer for other tasks. And then I Used Semaphore to signal the Timerturon once BLE task has completed ts work it works perfectly. But I still want to know why Flag method is going crazy and Global variable method is not working. I used freertos here. Please help me out, guys. Without knowing the answer I am not even able to sleep.

Sketch: (leave the backquotes for code formatting)

#include <ArduinoJson.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

/*#if CONFIG_FREERTOS_UNICORE
  static const BaseType_t app_cpu = 0;
#else
  static const BaseType_t app_cpu = 1;
#endif*/

static const BaseType_t pro_cpu = 0;
static const BaseType_t app_cpu = 1;

//ADC Related Global Variables
static const uint16_t timer_divider =80;
static const uint64_t timer_max_count=1000;

static const int adc_pin=A0;

static const int BUF_SIZE=1000;

static int buf[BUF_SIZE];
int Buff_Len=0;
static int Read=0;
static int Write=0;
static int count=0;
static float avg=0;
int i=0;
int BLE_flag=0;
String cmd;
static volatile uint8_t msg_flag = 0;
int t3=0;

static hw_timer_t *timer=NULL;
static uint16_t val;
static int count1=0;

static SemaphoreHandle_t bin_sem=NULL;
static SemaphoreHandle_t bin_sem2=NULL;
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
//ADC Related Global Variables

//BLE Global Variable
char Reading[1000];
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;

TaskHandle_t task1;
TaskHandle_t task2;
TaskHandle_t task3;
//Declaration BLE necessary Classes
#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};
//BLE Global Variables

//Task Section 
void IRAM_ATTR onTimer()
{
  BaseType_t xHigherPriorityTaskWoken=pdFALSE;

  val=analogRead(adc_pin);
  count1++;

  vTaskNotifyGiveFromISR(task1, 
                         &xHigherPriorityTaskWoken);

  if (xHigherPriorityTaskWoken) {
    portYIELD_FROM_ISR();
  }
}
void Timer_Turnon(void *parameters)
{
  while(1)
  {
    if(msg_flag == 1)
    //if(t3==1)
  //xSemaphoreTake(bin_sem2,portMAX_DELAY);
  { 
  { 
     timerStart(timer);
     Serial.println("Timer started again"); 
     msg_flag = 0;
  }
 }
}
}

void move_to_Queue (void *parameters)
{
  while(1)
  {
    static uint32_t thread_notification;
    thread_notification = ulTaskNotifyTake(pdTRUE, 
                        portMAX_DELAY);

   if(thread_notification)
   {
   //xSemaphoreTake(bin_sem2,portMAX_DELAY);
    if(Buff_Len==BUF_SIZE||count1>2000)
    {
      Serial.println("Buffer is full");
      xSemaphoreGive(bin_sem);
      //BLE_flag=1;
      Buff_Len=0;
      count1=0;
      timerStop(timer);    
    }
    else
    {
      buf[Write]=val;
      Write = (Write + 1) % BUF_SIZE;
      Buff_Len++;
    } 
  }
}
}

void BLE_Task(void *parameters)
{
   while(1)
  {
    //Serial.println("Task3 on work");
    //if(BLE_flag==1)
    {
    //BLE_flag=0;
    xSemaphoreTake(bin_sem,portMAX_DELAY);
    Serial.println("BLE");
    for (i=0;i<BUF_SIZE;i++)
  {
   if(i==0)
  {
    sprintf(Reading,"[%d",buf[i]);
  }
  else if(i==BUF_SIZE-1)
  {
    sprintf(Reading,",%d]",buf[i]);
  }
  else{
  sprintf(Reading,",%d",buf[i]); 
  }
   Serial.print(Reading);
    if (deviceConnected) {
        pTxCharacteristic->setValue(Reading);
        pTxCharacteristic->notify();
        delay(10); // bluetooth stack will go into congestion, if too many packets are sent
  }   
 }
 Serial.println();

  }
  msg_flag = 1;
  //t3=1;
  //xSemaphoreGive(bin_sem2);
 }
}

void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  bin_sem = xSemaphoreCreateBinary();
  bin_sem2 = xSemaphoreCreateBinary();
  vTaskDelay(1000/portTICK_PERIOD_MS);

  //BLE Declarations
  BLEDevice::init("UART Service");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  pTxCharacteristic = pService->createCharacteristic(
                    CHARACTERISTIC_UUID_TX,
                    BLECharacteristic::PROPERTY_NOTIFY
                  );

  pTxCharacteristic->addDescriptor(new BLE2902());
  pService->start();
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
  //BLE Declaration

  //ADC Semaphore and Timer Declarations
  bin_sem = xSemaphoreCreateBinary();
  bin_sem2 = xSemaphoreCreateBinary();

  if(bin_sem==NULL||bin_sem2==NULL)
  {
    Serial.println("Could not create semaphore");
    ESP.restart();
  }
    xTaskCreatePinnedToCore(move_to_Queue,
                          "move_to_Queue",
                          1024,
                          NULL,
                          2,
                          &task1,
                          app_cpu);
     xTaskCreatePinnedToCore(BLE_Task,
                          "BLE_Task",
                          2048,
                          NULL,
                          2,
                          &task2,
                          app_cpu);

     timer = timerBegin(0, timer_divider, true);

  // Provide ISR to timer (timer, function, edge)
     timerAttachInterrupt(timer, &onTimer, true);

  // At what count should ISR trigger (timer, count, autoreload)
     timerAlarmWrite(timer, timer_max_count, true);

  // Allow ISR to trigger
     timerAlarmEnable(timer);
     xTaskCreatePinnedToCore(Timer_Turnon,
                    "Timer_Turnon",
                    1024,
                    NULL,
                    2,
                    &task3,
                    app_cpu);
      vTaskDelete(NULL);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Debug Messages:

Enable Core debug level: Debug on tools menu of Arduino IDE, then put the serial output here

12:19:36.490 -> [D][FreeRTOS.cpp:189] take(): Semaphore taking: name: RegisterAppEvt (0x3ffde614), owner: <N/A> for registerApp
12:19:36.490 -> [D][FreeRTOS.cpp:189] take(): Semaphore taking: name: RegisterAppEvt (0x3ffde614), owner: <N/A> for registerApp
12:19:36.537 -> [D][FreeRTOS.cpp:198] take(): Semaphore taken:  name: RegisterAppEvt (0x3ffde614), owner: registerApp
12:19:36.537 -> [D][BLEDevice.cpp:102] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
12:19:36.537 -> [D][FreeRTOS.cpp:189] take(): Semaphore taking: name: CreateEvt (0x3ffde86c), owner: <N/A> for createService
12:19:36.537 -> [D][FreeRTOS.cpp:198] take(): Semaphore taken:  name: CreateEvt (0x3ffde86c), owner: createService
12:19:36.537 -> [D][FreeRTOS.cpp:189] take(): Semaphore taking: name: CreateEvt (0x3ffdead0), owner: <N/A> for executeCreate
12:19:36.585 -> [D][FreeRTOS.cpp:198] take(): Semaphore taken:  name: CreateEvt (0x3ffdead0), owner: executeCreate
12:19:36.585 -> [D][BLEDevice.cpp:102] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
12:19:36.585 -> [D][BLEService.cpp:225] addCharacteristic(): Adding characteristic: uuid=6e400003-b5a3-f393-e0a9-e50e24dcca9e to service: UUID: 6e400001-b5a3-f393-e0a9-e50e24dcca9e, handle: 0x0028
12:19:36.585 -> [D][BLECharacteristic.cpp:90] executeCreate(): Registering characteristic (esp_ble_gatts_add_char): uuid: 6e400003-b5a3-f393-e0a9-e50e24dcca9e, service: UUID: 6e400001-b5a3-f393-e0a9-e50e24dcca9e, handle: 0x0028
12:19:36.632 -> [D][FreeRTOS.cpp:189] take(): Semaphore taking: name: CreateEvt (0x3ffdf4ec), owner: <N/A> for executeCreate
12:19:36.632 -> [D][FreeRTOS.cpp:198] take(): Semaphore taken:  name: CreateEvt (0x3ffdf4ec), owner: executeCreate
12:19:36.632 -> [D][BLEDevice.cpp:102] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
12:19:36.632 -> [D][FreeRTOS.cpp:189] take(): Semaphore taking: name: CreateEvt (0x3ffdf700), owner: <N/A> for executeCreate
12:19:36.632 -> [D][FreeRTOS.cpp:198] take(): Semaphore taken:  name: CreateEvt (0x3ffdf700), owner: executeCreate
12:19:36.679 -> [D][BLEDevice.cpp:102] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
12:19:36.679 -> [D][FreeRTOS.cpp:189] take(): Semaphore taking: name: StartEvt (0x3ffdeb90), owner: <N/A> for start
12:19:36.679 -> [D][FreeRTOS.cpp:198] take(): Semaphore taken:  name: StartEvt (0x3ffdeb90), owner: start
12:19:36.679 -> [D][BLEDevice.cpp:102] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
12:19:36.679 -> [I][BLEDevice.cpp:554] getAdvertising(): create advertising
12:19:36.725 -> [D][BLEDevice.cpp:556] getAdvertising(): get advertising
12:19:36.725 -> [D][BLEAdvertising.cpp:196] start(): - no services advertised
12:19:36.725 -> Waiting a client connection to notify...
12:19:36.725 -> [D][BLEDevice.cpp:556] getAdvertising(): get advertising
12:19:36.725 -> [D][BLEAdvertising.cpp:491] handleGAPEvent(): handleGAPEvent [event no: 0]
12:19:36.725 -> [D][BLEDevice.cpp:556] getAdvertising(): get advertising
12:19:36.725 -> [D][BLEAdvertising.cpp:491] handleGAPEvent(): handleGAPEvent [event no: 1]
12:19:36.725 -> [D][BLEDevice.cpp:556] getAdvertising(): get advertising
12:19:36.725 -> [D][BLEAdvertising.cpp:491] handleGAPEvent(): handleGAPEvent [event no: 6]
12:19:37.711 -> Buffer is full
12:19:37.711 -> [4095,312,288,292,292,284,276,286,234,184,74,.........1000]

image

stale[bot] commented 3 years ago

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

PilnyTomas commented 2 years ago

Hi, your post was very difficult to read and the code is confusing too. I tried to edit the post (not the code) to make it more readable - please check that I didn't change the meaning. I would suggest you edit the code:

  1. Remove unused (commented) code.

  2. Remove unnecessary curly brackets: '{' and '}'.

  3. Instead of global variable use FreeRTOS queue to pass data between tasks

  4. NEVER use an infinite loop in a task without any yielding or blocking calls - no other task will get to be executed!

    • Yield in tasks i.e. use blocking functions to wait on something - for example xQueueReceive or use vTaskDelay for periodic execution.
  5. bin_sem and bin_sem2 are created twice in the setup() function - remove one of the creation.

  6. Let the FreeRTOS decide on which core the task will run - instead of xTaskCreatePinnedToCore use xTaskCreate - this does the same as the previous function, only without core specification.

Please try these tips and if it doesn't fix your issue let me know and post the updated code.

VojtechBartoska commented 2 years ago

Closing due no response.