Hello everyone!
Is it possible to use reading on I2С bus with core 1 and at that time transmitting other data to uart, by the processor 0 core?
I2C and UART parallel
-
- Posts: 9709
- Joined: Thu Nov 26, 2015 4:08 am
Re: I2C and UART parallel
Yes. You should even be able to do both on the same core.
-
- Posts: 9709
- Joined: Thu Nov 26, 2015 4:08 am
Re: I2C and UART parallel
No clue what's happening there. Can you post your code? No analog interference between the IO pins?
Re: I2C and UART parallel
There is no interference. Here is the code:
- #include <Wire.h>
- #include "MLX90640_API.h"
- #include "MLX90640_I2C_Driver.h"
- TaskHandle_t Task1; // Присваиваем индификаторы задач.
- TaskHandle_t Task2;
- const byte MLX90640_address = 0x33; //Slave адрес I2C MLX90640 по умолчанию.
- #define TA_SHIFT 8 //Default shift for MLX90640 in open air
- //#define LED_UART 23 // Нога индикации передачи буфера по UART (D23-MODULE, 36-CHIP).
- //const byte LED_UART = 23;
- //#define LED_CALC 19 // Нога индикации передачи буфера по UART (D19-MODULE, 38-CHIP).
- float mlx90640To[768]; // Массив для расчетов кадра.
- float mlx90640Se[768]; // Массив для выдачи кадра.
- byte newframe = 0; // Флаг нового кадра.
- paramsMLX90640 mlx90640;
- void setup()
- {
- // pinMode(LED_UART, OUTPUT);
- // pinMode(LED_CALC, OUTPUT);
- Wire.begin();
- Wire.setClock(400000); // Установить скорость шины I2C 400kHz.
- Serial.begin(921600); // Установить скорость шины UART 921600.
- //Serial.begin(256000); // Установить скорость шины UART 256000.
- //Serial.begin(115200); // Установить скорость шины UART 115200.
- if (isConnected() == false)
- {
- Serial.println("MLX90640 not detected at default I2C address. Please check wiring. Freezing.");
- while (1);
- }
- // Далее получаем данные EEPROM датчика.
- int status;
- uint16_t eeMLX90640[832];
- status = MLX90640_DumpEE(MLX90640_address, eeMLX90640);
- if (status != 0) Serial.println("Failed to load system parameters");
- status = MLX90640_ExtractParameters(eeMLX90640, &mlx90640);
- if (status != 0) Serial.println("Parameter extraction failed");
- //Once params are extracted, we can release eeMLX90640 array
- // Установка частоты обновления датчика (указана в полных кадрах).
- //MLX90640_SetRefreshRate(MLX90640_address, 0x00); //Set rate to 0.25Hz effective - OK
- //MLX90640_SetRefreshRate(MLX90640_address, 0x01); //Set rate to 0.5Hz effective - OK
- //MLX90640_SetRefreshRate(MLX90640_address, 0x02); //Set rate to 1Hz effective - OK
- //MLX90640_SetRefreshRate(MLX90640_address, 0x03); //Set rate to 2Hz effective - OK
- //MLX90640_SetRefreshRate(MLX90640_address, 0x04); //Set rate to 4Hz effective - OK
- MLX90640_SetRefreshRate(MLX90640_address, 0x05); //Set rate to 8Hz effective - OK_D
- //MLX90640_SetRefreshRate(MLX90640_address, 0x06); //Set rate to 16Hz effective - Works at 800kHz !!! -???
- //MLX90640_SetRefreshRate(MLX90640_address, 0x07); //Set rate to 32Hz effective - fails !!! -???
- // После получения EPPROM данных с датчика, увеличиваем скорость шины I2C до 1Mhz.
- Wire.setClock(1000000); // Скорость шины I2C 800kHz (из за внутреннего делителя частоты такта).
- delay(500); // small delay
- // Ref: http://esp32.info/docs/esp_idf/html/db/da4/task_8h.html#a25b035ac6b7809ff16c828be270e1431
- // Создаем задачу с кодом из функции Task1code(),
- // с приоритетом 1 и выполняемую на ядре 0:
- xTaskCreatePinnedToCore(
- Task1code, /* Функция задачи */
- "Task1", /* Название задачи */
- 10000, /* Размер стека задачи */
- NULL, /* Параметр задачи */
- 1, /* Приоритет задачи */
- &Task1, /* Идентификатор задачи,
- чтобы ее можно было отслеживать */
- 0); /* Ядро для выполнения задачи (0) */
- delay(500);
- // Создаем задачу с кодом из функции Task2code(),
- // с приоритетом 1 и выполняемую на ядре 1:
- xTaskCreatePinnedToCore(
- Task2code, /* Функция задачи */
- "Task2", /* Название задачи */
- 10000, /* Размер стека задачи */
- NULL, /* Параметр задачи */
- 1, /* Приоритет задачи */
- &Task2, /* Идентификатор задачи,
- чтобы ее можно было отслеживать */
- 1); /* Ядро для выполнения задачи (1) */
- delay(500);
- }
- // =============================================== Ядро 1 =========================================================
- void Task2code( void * pvParameters )
- {
- for(;;) // Бесконечный цикл.
- {
- for (byte x = 0 ; x < 2 ; x++)
- {
- uint16_t mlx90640Frame[834];
- int status = MLX90640_GetFrameData(MLX90640_address, mlx90640Frame);
- // digitalWrite(LED_CALC, HIGH);
- float vdd = MLX90640_GetVdd(mlx90640Frame, &mlx90640);
- float Ta = MLX90640_GetTa(mlx90640Frame, &mlx90640);
- float tr = Ta - TA_SHIFT; //Reflected temperature based on the sensor ambient temperature
- float emissivity = 0.95;
- MLX90640_CalculateTo(mlx90640Frame, &mlx90640, emissivity, tr, mlx90640To);
- // digitalWrite(LED_CALC, LOW);
- //Calculation time on a Teensy 3.5 is 71ms.
- //Calculation time on a ESP32 is 27,79ms - 27,83ms.
- }
- for (int a = 0 ; a < 768 ; a++) // Скопировать массив кадра для дальнейшего вывода.
- {
- mlx90640Se[a] = mlx90640To[a];
- }
- newframe = 1; // Поднять флаг нового кадра.
- }
- }
- // =============================================== Ядро 1 (по умолчанию) =========================================
- void loop()
- {
- delay(100);
- }
- // =============================================== Ядро 0 =========================================================
- void Task1code( void * pvParameters )
- {
- for(;;) // Бесконечный цикл.
- {
- if ( newframe == 1)
- {
- newframe = 0; // Сбросить флаг нового кадра.
- Serial.write(158); // Передать температуру -250,00 (число -25000).
- Serial.write(88);
- Serial.write(158); // Передать температуру -250,00 (число -25000).
- Serial.write(88);
- // Вывод кадра через UART (1536 байт при скорости 921600 - 15,27 ms).
- // digitalWrite(LED_UART, HIGH);
- for (int z = 0 ; z < 768 ; z++)
- {
- short tempx = mlx90640Se[z] * 100; // Выделяем только два занака после запятой в целое число и передаем в порт.
- byte raw[2]; // Выделить два байта из short переменной и передать.
- (short&)raw = tempx;
- Serial.write(raw[1]);
- Serial.write(raw[0]);
- }
- Serial.write(154); // Передать температуру -260,00 (число -26000).
- Serial.write(112);
- Serial.write(154); // Передать температуру -260,00 (число -26000).
- Serial.write(112);
- // digitalWrite(LED_UART, LOW);
- }
- delay(1);
- }
- }
- // ========================================== пока не понятно =====================================================
- // Возвращает TRUE, если датчик ответил на шине I2C.
- boolean isConnected()
- {
- Wire.beginTransmission((uint8_t)MLX90640_address);
- if (Wire.endTransmission() != 0) return (false); //Датчик не ответил ACK.
- return (true);
- }
-
- Posts: 9709
- Joined: Thu Nov 26, 2015 4:08 am
Re: I2C and UART parallel
Just guessing as I don't know the Arduino drivers that well, but can you try initializing the serial port and the Wire interface inside the tasks you spawn instead of in the main function? Thing is that the drivers likely register the interrupts on the CPU they're initialized on, which in your case is CPU0 for both drivers. That could lead to what you're seeing.
(Additionally, instead of using a variable (NewFrame) it's better to use something like a FreeRTOS semaphore or a queue for inter-task communication.)
(Additionally, instead of using a variable (NewFrame) it's better to use something like a FreeRTOS semaphore or a queue for inter-task communication.)
Re: I2C and UART parallel
A good idea. I will try. By default, the "void setup" and the "void loop" on the arduino ide are executed on 1 core.Just guessing as I don't know the Arduino drivers that well, but can you try initializing the serial port and the Wire interface inside the tasks you spawn instead of in the main function? Thing is that the drivers likely register the interrupts on the CPU they're initialized on, which in your case is CPU0 for both drivers. That could lead to what you're seeing.
Can an example how to implement this?(Additionally, instead of using a variable (NewFrame) it's better to use something like a FreeRTOS semaphore or a queue for inter-task communication.)
Another question, the priority of tasks, the same on both cores, can this be a problem? What is she responsible for and how to ask her correctly?
Who is online
Users browsing this forum: DonEvans and 92 guests