Потоковая передача ИК-видео MLX90640 в формате MJPEG через веб-сервер HTTP с использованием ESP32
Я совершенно неопытен, когда дело касается HTTP или любого кода веб-сервера. Я пытаюсь передать свое видео MLX90640 на веб-сервер с помощью ESP32. В настоящее время у меня есть MLX90640, подключенный к ESP32, и я могу повторно печатать пиксели на последовательном мониторе, чтобы показать ASCII-видео. Сейчас я изо всех сил пытаюсь перейти от этого к просмотру видео на своем веб-сервере.
Мой MLX90640 выводится в массив 32x24 чисел с плавающей запятой. Затем я сопоставляю это значение с 0–255 и использую его в качестве входных данных для массива 16-битных цветов камеры. Я предполагаю, что у меня возникают проблемы при попытке преобразовать uint16_t в любой тип данных, необходимый для описания кадра jpeg.
В настоящее время я вижу полностью черный экран с маленьким белым квадратом в центре экрана, когда открываю свой сервер на Chrome. Ниже я прикрепил все соответствующие функции к этой части проекта, но я буду следить за ним и при необходимости могу опубликовать остальную часть моего кода!
Я читал много похожих проектов, но в большинстве из них используются камеры другого типа, и мне не удалось воспроизвести функции, которые потребуются для MLX90640. Будем очень признательны за любые предложения о том, что попробовать или прочитать дальше!
Заранее спасибо.
float frame[32*24]; // buffer for full frame of temperatures
float MinTemp;
float MaxTemp;
const char HEADER[] = "HTTP/1.1 200 OK\r\n" \
"Access-Control-Allow-Origin: *\r\n" \
"Content-Type: multipart/x-mixed-replace; boundary=123456789000000000000987654321\r\n";
const char BOUNDARY[] = "\r\n--123456789000000000000987654321\r\n";
const char CTNTTYPE[] = "Content-Type: image/jpeg\r\nContent-Length: ";
const int hdrLen = strlen(HEADER);
const int bdrLen = strlen(BOUNDARY);
const int cntLen = strlen(CTNTTYPE);
const uint16_t camColors[] = {0x480F,
0x400F, 0x400F, 0x400F, 0x4010, 0x3810, 0x3810, 0x3810, 0x3810, 0x3010, 0x3010,
0x3010, 0x2810, 0x2810, 0x2810, 0x2810, 0x2010, 0x2010, 0x2010, 0x1810, 0x1810,
0x1811, 0x1811, 0x1011, 0x1011, 0x1011, 0x0811, 0x0811, 0x0811, 0x0011, 0x0011,
0x0011, 0x0011, 0x0011, 0x0031, 0x0031, 0x0051, 0x0072, 0x0072, 0x0092, 0x00B2,
0x00B2, 0x00D2, 0x00F2, 0x00F2, 0x0112, 0x0132, 0x0152, 0x0152, 0x0172, 0x0192,
0x0192, 0x01B2, 0x01D2, 0x01F3, 0x01F3, 0x0213, 0x0233, 0x0253, 0x0253, 0x0273,
0x0293, 0x02B3, 0x02D3, 0x02D3, 0x02F3, 0x0313, 0x0333, 0x0333, 0x0353, 0x0373,
0x0394, 0x03B4, 0x03D4, 0x03D4, 0x03F4, 0x0414, 0x0434, 0x0454, 0x0474, 0x0474,
0x0494, 0x04B4, 0x04D4, 0x04F4, 0x0514, 0x0534, 0x0534, 0x0554, 0x0554, 0x0574,
0x0574, 0x0573, 0x0573, 0x0573, 0x0572, 0x0572, 0x0572, 0x0571, 0x0591, 0x0591,
0x0590, 0x0590, 0x058F, 0x058F, 0x058F, 0x058E, 0x05AE, 0x05AE, 0x05AD, 0x05AD,
0x05AD, 0x05AC, 0x05AC, 0x05AB, 0x05CB, 0x05CB, 0x05CA, 0x05CA, 0x05CA, 0x05C9,
0x05C9, 0x05C8, 0x05E8, 0x05E8, 0x05E7, 0x05E7, 0x05E6, 0x05E6, 0x05E6, 0x05E5,
0x05E5, 0x0604, 0x0604, 0x0604, 0x0603, 0x0603, 0x0602, 0x0602, 0x0601, 0x0621,
0x0621, 0x0620, 0x0620, 0x0620, 0x0620, 0x0E20, 0x0E20, 0x0E40, 0x1640, 0x1640,
0x1E40, 0x1E40, 0x2640, 0x2640, 0x2E40, 0x2E60, 0x3660, 0x3660, 0x3E60, 0x3E60,
0x3E60, 0x4660, 0x4660, 0x4E60, 0x4E80, 0x5680, 0x5680, 0x5E80, 0x5E80, 0x6680,
0x6680, 0x6E80, 0x6EA0, 0x76A0, 0x76A0, 0x7EA0, 0x7EA0, 0x86A0, 0x86A0, 0x8EA0,
0x8EC0, 0x96C0, 0x96C0, 0x9EC0, 0x9EC0, 0xA6C0, 0xAEC0, 0xAEC0, 0xB6E0, 0xB6E0,
0xBEE0, 0xBEE0, 0xC6E0, 0xC6E0, 0xCEE0, 0xCEE0, 0xD6E0, 0xD700, 0xDF00, 0xDEE0,
0xDEC0, 0xDEA0, 0xDE80, 0xDE80, 0xE660, 0xE640, 0xE620, 0xE600, 0xE5E0, 0xE5C0,
0xE5A0, 0xE580, 0xE560, 0xE540, 0xE520, 0xE500, 0xE4E0, 0xE4C0, 0xE4A0, 0xE480,
0xE460, 0xEC40, 0xEC20, 0xEC00, 0xEBE0, 0xEBC0, 0xEBA0, 0xEB80, 0xEB60, 0xEB40,
0xEB20, 0xEB00, 0xEAE0, 0xEAC0, 0xEAA0, 0xEA80, 0xEA60, 0xEA40, 0xF220, 0xF200,
0xF1E0, 0xF1C0, 0xF1A0, 0xF180, 0xF160, 0xF140, 0xF100, 0xF0E0, 0xF0C0, 0xF0A0,
0xF080, 0xF060, 0xF040, 0xF020, 0xF800,
};
uint16_t colorFrame(float color){
uint8_t colorIndex = map(color, MinTemp-5.0, MaxTemp+5.0, 0, 255);
colorIndex = constrain(colorIndex, 0, 255);
return camColors[colorIndex];
}
void setMinMaxTemps(){
MaxTemp = frame[0]; // Get first data to find Max and Min Temperature
MinTemp = frame[0];
for (int x = 0 ; x < 768 ; x++) // Find Maximum and Minimum Temperature
{
MaxTemp = max(MaxTemp, frame[x]);
MinTemp = min(MinTemp, frame[x]);
}
}
void handle_videostream(){
WiFiClient client = server.client();
client.write(HEADER, hdrLen);
client.write(BOUNDARY, bdrLen);
uint16_t frameColor[768];
char buf[32];
while (1)
{
if (!client.connected())
break;
Serial.println("Get the MLX frame!");
if (mlx.getFrame(frame) != 0) {
Serial.println("Failed to get the frame..");
}
setMinMaxTemps();
for(int i=0; i<768; i++){
frameColor[i] = colorFrame(frame[i]);
}
client.write(CTNTTYPE, cntLen);
sprintf( buf, "%d\r\n\r\n", 768*4 );
client.write(buf, strlen(buf));
Serial.println(buf);
client.write((char *)frameColor, 768*4);
client.write(BOUNDARY, bdrLen);
if (!client.connected())
break;
}
}