#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);
}