Перейти к содержанию
    

ESP32 + FREERTOS + TCA9548A + LIS2MDDL

Добрый вечер!

Пытаюсь получить данные с датчиков LIS2MDL через мультиплексор TCA9548A  под FREERTOS применительно к  esp32 

По одному датчику сканирую в отдельной программе - все читается, осциллографом сигнал отличный.

Как только завожу через task и пытаюсь получить данные с датчиков - то есть данные, то нет, причем абсолютно на ровном месте.

Подскажите пожалуйста, что я делаю не так? Пример кода ниже.

 


#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif

#define I2C_Freq 3400000
#define SDA_1 32
#define SCL_1 33

#define SDA_0 21
#define SCL_0 22

#define TCA9548_ADDRESS 0x71
//#define TCA9548_ADDRESS 0x72
//#define TCA9548_ADDRESS 0x73

// Номер канала мультиплексора (0-7)
#define TCA9548_CHANNEL 0



//------------------ INCLUDE -----------------

#include <Adafruit_LIS2MDL.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include "esp_timer.h"

//#include <stdio.h>
 
//-----------------------------------

const uint8_t tca_addresses[] = { 0x71, 0x72, 0x73 };

static uint32_t step;// = STEP_BTON; параметры включения WiFi  и BLE

// Определение структуры SensorInfo и массива sensorInfoArray (как в предыдущем ответе)
struct SensorInfo {
    uint8_t multiplexerAddress; //
    uint8_t channel_num; // 
    float x;
    float y;
    float z;
};

SensorInfo sensorInfoArray[20] = {
    // First column
  {0x71, 0, 0, 0, 0}, {0x71, 1, 0, 0, 0}, {0x71, 2, 0, 0, 0}, {0x71, 3, 0, 0, 0}, {0x71, 4, 0, 0, 0},
  // Second column
  {0x71, 7, 0, 0, 0}, {0x71, 6, 0, 0, 0}, {0x71, 5, 0, 0, 0}, {0x72, 8, 0, 0, 0}, {0x72, 1, 0, 0, 0},
  // Third column
  {0x72, 6, 0, 0, 0}, {0x72, 5, 0, 0, 0}, {0x72, 4, 0, 0, 0}, {0x72, 3, 0, 0, 0}, {0x72, 2, 0, 0, 0},
  // Fourth column
  {0x73, 4, 0, 0, 0}, {0x73, 3, 0, 0, 0}, {0x73, 2, 0, 0, 0}, {0x72, 1, 0, 0, 0}, {0x73, 0, 0, 0, 0}

};


Adafruit_LIS2MDL lis2mdl = Adafruit_LIS2MDL();

SemaphoreHandle_t i2cMutex; // Мьютекс для I2C
SemaphoreHandle_t arrayMutex; // Мьютекс для массива с данными с датчика

/* our Array for data 20 sensor X,Y,Z float

1 column | 2 column  |3 column | 4 column
         |           |         |
71-0     |  71-7     |  72-6   |  73-4
71-1     |  71-6     |  72-5   |  73-3
71-2     |  71-5     |  72-4   |  73-2
71-3     |  72-0     |  72-3   |  73-1
71-4     |  72-1     |  72-2   |  73-8

*/

//-----------TASKS------------------------------ 
// define tasks
// polling 3 multiplexers and 20 lis2mdl sensors

void Task_1_READ_71(void* pvParameters);

//------------------------------------------------

//-------------Functions ---------------------- 

void tcaSelect_71(uint8_t channel);
bool tca9548Available();

//------------------------------------------------


// the setup function runs once when you press reset or power the board
void setup() {

    // initialize serial communication at 115200 bits per second:
    Serial.begin(115200);

    Wire.begin(SDA_0, SCL_0, I2C_Freq);
    Wire.setClock(3400000);

    tcaSelect_71(TCA9548_CHANNEL);
   

    if (!tca9548Available()) { Serial.println("TCA9548 not found!"); while (1); }

    // Initialise the sensor 
    if (!lis2mdl.begin()) {  // I2C mode
        Serial.println("Ooops, no LIS2MDL detected ... Check your wiring!");
        while (1) delay(10);
    }

     for (uint8_t channels = 0; channels < 8; channels++) {
          tcaSelect_71(channels);
          lis2mdl.enableAutoRange(true);
      }

 
  i2cMutex = xSemaphoreCreateMutex(); // Создаём мьютекс для I2C
  if (i2cMutex == NULL) {
      Serial.println("Не удалось создать мьютекс для I2C");
      while (1);
  }

  arrayMutex = xSemaphoreCreateMutex(); // Создаём мьютекс для массива с данными с датчика
  if (arrayMutex == NULL) {
      Serial.println("Не удалось создать мьютекс для массива");
      while (1);
  }

  

  // Now set up two tasks to run independently.
  xTaskCreatePinnedToCore(
      Task_1_READ_71
      , "Task_1_READ_71"   // A name just for humans
      , 2048  // This stack size can be checked & adjusted by reading the Stack Highwater
      , NULL
      , 2  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
      , NULL
      , ARDUINO_RUNNING_CORE);
  
}

void loop()
{
    // Empty. Things are done in Tasks.
}


/*--------------------------------------------------*/
/*------------------- FUNCTIONS --------------------*/
/*--------------------------------------------------*/


// Функция для выбора канала на мультиплексоре TCA9548  uint8_t
void tcaSelect_71(uint8_t channel) {
    Wire.beginTransmission(TCA9548_ADDRESS);
    Wire.write(1 << channel);
    Wire.endTransmission();
}


bool tca9548Available() {
     Wire.beginTransmission(TCA9548_ADDRESS);
   // Wire.beginTransmission(uint8_t(0x71));
    byte status = Wire.endTransmission();
    return status == 0;
}


/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/

void Task_1_READ_71(void* pvParameters) {
    (void)pvParameters;

    sensors_event_t event71;

   //      READ sensors 71-0 ->71-7      Write to array

    while (1) {
        
        int64_t start_time = esp_timer_get_time();

        for (uint8_t i = 0; i < 8; i++) {
                xSemaphoreTake(i2cMutex, portMAX_DELAY); // Захватываем мьютекс I2C
                tcaSelect_71(sensorInfoArray[i].channel_num); // Выбираем канал на мультиплексоре TCA9548A
                                  
                xSemaphoreTake(arrayMutex, portMAX_DELAY);// Теперь захватываем мьютекс массива
                               
                lis2mdl.getEvent(&event71);
               
                // Преобразование полученных данных в микротесла и запись в массив
                
                sensorInfoArray[i].x = event71.magnetic.x;
                sensorInfoArray[i].y = event71.magnetic.y;
                sensorInfoArray[i].z = event71.magnetic.z;

                xSemaphoreGive(arrayMutex); // Освобождаем мьютекс массива
                
                xSemaphoreGive(i2cMutex); // Освобождаем мьютекс I2C

                Serial.println("========== AFTER =================");
                Serial.print(sensorInfoArray[i].multiplexerAddress, HEX);
                Serial.print(" ");
                Serial.print(sensorInfoArray[i].channel_num);
                Serial.print("  ");
                Serial.print(sensorInfoArray[i].x);
                Serial.print("  ");
                Serial.print(sensorInfoArray[i].y);
                Serial.print("  ");
                Serial.println(sensorInfoArray[i].z);
                Serial.println("  ");
                               
                vTaskDelay(500 / portTICK_PERIOD_MS); // Задержка между опросами датчиков

 
        }

        int64_t end_time = esp_timer_get_time();

        int64_t elapsed_time = end_time - start_time;
        Serial.print("  ");
        Serial.print("Elapsed time: ");
        Serial.print(elapsed_time);
        Serial.println(" ns");

        vTaskDelay(10 / portTICK_PERIOD_MS); // 
    }
}


    
}
 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Смотрите анализатором что творится на выводах

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 минут назад, uriy сказал:

Смотрите анализатором что творится на выводах

Опрос по выводам проходит, качество i2c сигнала - отличное. Такое впечатление, что во freertos  я что-то не сделал. Вопрос что?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 minutes ago, AlanSbor said:

Такое впечатление, что во freertos  я что-то не сделал. Вопрос что?

Например, стека не доложили.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, aaarrr сказал:

Например, стека не доложили.

Можно ткнуть в код, где именно?

У меня же таск работает от включения до выключения устройства, значит не статическая задача на один раз и стек принудительно выделять не нужно. Или я что то не понял?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я к тому, что значения 2048 может быть недостаточно. Это стоит проверить.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, aaarrr сказал:

Например, стека не доложили.

вангую, что в таком случае, ТС наткнулся бы на HF, а не на "то есть данные, то нет".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, aaarrr сказал:

Я к тому, что значения 2048 может быть недостаточно. Это стоит проверить.

Я проверял от большего к меньшему, начинал с 4096 и шел на снижение пока не полезли алерты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

44 минуты назад, AlanSbor сказал:

Я проверял от большего к меньшему, начинал с 4096 и шел на снижение пока не полезли алерты.

Странная какая-то у вас методика определения размера стека. :shok: Так половину данных затрёте и не заметите....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

41 минуту назад, jcxz сказал:

Странная какая-то у вас методика определения размера стека. :shok: Так половину данных затрёте и не заметите....

Я работаю не под esp-idf. Подскажите пожалуйста методику - проверю вечером.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, jcxz сказал:

Странная какая-то у вас методика определения размера стека. :shok: Так половину данных затрёте и не заметите....

image.thumb.png.5575d41db44d7a9e9aa5a55a854d06b2.png

Не помогло.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Wire.setClock(3400000);

Эта штука что делает? Задает частоту для I2C? Вам не кажется 3 МГц многовато для I2C? 

Сомневаюсь что без Freertos это у вас работало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, uriy сказал:
Wire.setClock(3400000);

Эта штука что делает? Задает частоту для I2C? Вам не кажется 3 МГц многовато для I2C? 

Сомневаюсь что без Freertos это у вас работало.

Работает. Могу код для одного датчика выложить. Ограничение на скорость накладывается самим контроллером, по осциллографу до 950кГц. Пробовал понижать до 400 и 100кГц, с одним датчиком работает всегда. Под freertos  видит только 0канал с датчиком. Сейчас ковыряю подтягивающий резисторы, пробую разные номиналы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Странный у вас подход. В первом посте написали что смотрели осцилом - сигнал отличный. Зачем тогда резисторы разные пробовать? 

У TCA9548A  в даташите указана максимальная частот 400 кГц. У LIS2MDL да указано 3.4 МГц

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как вы Arduino с FreeRTOS скрещивали? Родная FreeRTOS не понимает ни start() ни loop() функций.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...