test
This commit is contained in:
267
main/main.c
267
main/main.c
@@ -21,21 +21,62 @@
|
||||
#define HREF_GPIO_NUM 7
|
||||
#define PCLK_GPIO_NUM 13
|
||||
|
||||
#define WIFI_IF WIFI_IF_AP
|
||||
|
||||
#define MAX_PAYLOAD_SIZE 1400
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_mac.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "lipton/cci.h"
|
||||
#include "lipton/vospi.h"
|
||||
#include "lipton/lepton_system.h"
|
||||
#include "lipton/lepton_utilities.h"
|
||||
|
||||
// Number of consecutive VoSPI resynchronization attempts before attempting to reset
|
||||
#define LEP_SYNC_FAIL_FAULT_LIMIT 10
|
||||
|
||||
// Reset fail delay before attempting a re-init (seconds)
|
||||
#define LEP_RESET_FAIL_RETRY_SECS 5
|
||||
|
||||
//
|
||||
// Code start
|
||||
//
|
||||
int vsync_count = 0;
|
||||
int sync_fail_count = 0;
|
||||
int reset_fail_count = 0;
|
||||
int64_t vsyncDetectedUsec;
|
||||
|
||||
esp_err_t tx_with_retry(wifi_interface_t iface, const void *buffer, int len, bool en_sys_seq)
|
||||
{
|
||||
for (int i = 0; i < 160; i++)
|
||||
{
|
||||
esp_err_t err = esp_wifi_80211_tx(iface, buffer, len, en_sys_seq);
|
||||
if (err == ESP_OK)
|
||||
return ESP_OK;
|
||||
if (err != ESP_ERR_NO_MEM)
|
||||
return err;
|
||||
// No delay, retry immediately
|
||||
}
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
static camera_config_t camera_config = {
|
||||
.pin_pwdn = PWDN_GPIO_NUM,
|
||||
.pin_reset = RESET_GPIO_NUM,
|
||||
.pin_xclk = XCLK_GPIO_NUM,
|
||||
.pin_sccb_sda = SIOD_GPIO_NUM,
|
||||
.pin_sccb_scl = SIOC_GPIO_NUM,
|
||||
// .pin_sccb_sda = SIOD_GPIO_NUM,
|
||||
// .pin_sccb_scl = SIOC_GPIO_NUM,
|
||||
.pin_sccb_sda = -1,
|
||||
.pin_sccb_scl = -1,
|
||||
.sccb_i2c_port = I2C_MASTER_NUM,
|
||||
|
||||
.pin_d7 = Y9_GPIO_NUM,
|
||||
.pin_d6 = Y8_GPIO_NUM,
|
||||
@@ -54,8 +95,8 @@ static camera_config_t camera_config = {
|
||||
.ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
.pixel_format = PIXFORMAT_JPEG, // YUV422,GRAYSCALE,RGB565,JPEG
|
||||
//.frame_size = FRAMESIZE_UXGA, // QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.+
|
||||
.frame_size = FRAMESIZE_128X128, // QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.
|
||||
.frame_size = FRAMESIZE_UXGA, // QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.+
|
||||
//.frame_size = FRAMESIZE_128X128, // QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates.
|
||||
|
||||
.jpeg_quality = 12, // 0-63, for OV series camera sensors, lower number means higher quality
|
||||
.fb_count = 1, // When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
|
||||
@@ -66,6 +107,89 @@ static camera_config_t camera_config = {
|
||||
|
||||
esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq);
|
||||
|
||||
uint16_t calculate_checksum(uint8_t *data, size_t len)
|
||||
{
|
||||
uint16_t checksum = 0;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
checksum ^= data[i]; // Simple XOR-based checksum
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
|
||||
void send_data_frame(uint8_t type, uint8_t *data, size_t len)
|
||||
{
|
||||
uint8_t mac_addr[6];
|
||||
if (esp_wifi_get_mac(WIFI_IF_AP, mac_addr) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to get MAC address");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t header[] = {
|
||||
0x08, 0x02, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x10, 0x00};
|
||||
memcpy(&header[10], mac_addr, 6);
|
||||
memcpy(&header[16], mac_addr, 6);
|
||||
|
||||
size_t max_chunk_size = MAX_PAYLOAD_SIZE - (11 + 2);
|
||||
size_t total_chunks = (len + max_chunk_size - 1) / max_chunk_size;
|
||||
|
||||
for (uint16_t seq = 0; seq < total_chunks; seq++)
|
||||
{
|
||||
size_t offset = seq * max_chunk_size;
|
||||
size_t chunk_size = (len - offset > max_chunk_size) ? max_chunk_size : (len - offset);
|
||||
|
||||
uint8_t *raw_frame = malloc(11 + chunk_size + 2);
|
||||
uint8_t *full_packet = malloc(sizeof(header) + 11 + chunk_size + 2);
|
||||
if (!raw_frame || !full_packet)
|
||||
{
|
||||
ESP_LOGE(TAG, "Memory allocation failed!");
|
||||
free(raw_frame);
|
||||
free(full_packet);
|
||||
return;
|
||||
}
|
||||
|
||||
raw_frame[0] = type;
|
||||
raw_frame[1] = seq >> 8;
|
||||
raw_frame[2] = seq & 0xFF;
|
||||
raw_frame[3] = total_chunks >> 8;
|
||||
raw_frame[4] = total_chunks & 0xFF;
|
||||
raw_frame[5] = 'P';
|
||||
raw_frame[6] = 'l';
|
||||
raw_frame[7] = 'e';
|
||||
raw_frame[8] = 'c';
|
||||
raw_frame[9] = 'y';
|
||||
raw_frame[10] = 'C';
|
||||
|
||||
memcpy(raw_frame + 11, data + offset, chunk_size);
|
||||
uint16_t checksum = calculate_checksum(raw_frame, 11 + chunk_size);
|
||||
raw_frame[11 + chunk_size] = checksum >> 8;
|
||||
raw_frame[12 + chunk_size] = checksum & 0xFF;
|
||||
|
||||
memcpy(full_packet, header, sizeof(header));
|
||||
memcpy(full_packet + sizeof(header), raw_frame, 11 + chunk_size + 2);
|
||||
|
||||
esp_err_t ret = tx_with_retry(WIFI_IF, full_packet, sizeof(header) + 11 + chunk_size + 2, true);
|
||||
|
||||
if (ret == ESP_OK)
|
||||
{
|
||||
ESP_LOGI(TAG, "Sent chunk %d/%d, size: %d bytes", seq + 1, total_chunks, chunk_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to send chunk %d, %s", seq, esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
free(raw_frame);
|
||||
free(full_packet);
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t camera_init()
|
||||
{
|
||||
// initialize the camera
|
||||
@@ -100,13 +224,6 @@ esp_err_t camera_capture()
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (fb->len < 2 || fb->buf[0] != 0xFF || fb->buf[1] != 0xD8) {
|
||||
ESP_LOGE(TAG, "Invalid JPEG data (no SOI marker)");
|
||||
esp_camera_fb_return(fb);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
const size_t headerSize = sizeof(PreData);
|
||||
const size_t totalSize = fb->len + headerSize;
|
||||
uint8_t *dataOut = malloc(totalSize);
|
||||
@@ -130,31 +247,7 @@ esp_err_t camera_capture()
|
||||
memcpy(dataOut + headerSize, fb->buf, fb->len);
|
||||
|
||||
// Now chunk and send
|
||||
const size_t chunkSize = 1400;
|
||||
size_t bytesSent = 0;
|
||||
while (bytesSent < totalSize)
|
||||
{
|
||||
size_t bytesToSend = (totalSize - bytesSent) > chunkSize ? chunkSize : (totalSize - bytesSent);
|
||||
|
||||
int retries = 3;
|
||||
esp_err_t err;
|
||||
do
|
||||
{
|
||||
err = esp_wifi_80211_tx(WIFI_IF_AP, dataOut + bytesSent, bytesToSend, true);
|
||||
if (err != ESP_OK)
|
||||
ESP_LOGW(TAG, "Retrying chunk send...");
|
||||
} while (err != ESP_OK && --retries > 0);
|
||||
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to send chunk after retries");
|
||||
free(dataOut);
|
||||
esp_camera_fb_return(fb);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
bytesSent += bytesToSend;
|
||||
}
|
||||
send_data_frame(0x10, dataOut, totalSize);
|
||||
|
||||
free(dataOut);
|
||||
esp_camera_fb_return(fb);
|
||||
@@ -164,13 +257,111 @@ esp_err_t camera_capture()
|
||||
void app_main(void)
|
||||
{
|
||||
|
||||
nvs_flash_init();
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_sta();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
|
||||
wifi_config_t ap_config = {
|
||||
.ap = {
|
||||
.ssid = "ESP32-Test",
|
||||
.channel = 10,
|
||||
.authmode = WIFI_AUTH_OPEN,
|
||||
.max_connection = 1,
|
||||
.ssid_hidden = 1,
|
||||
.beacon_interval = 60000}};
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
|
||||
|
||||
esp_log_level_set("wifi", ESP_LOG_DEBUG);
|
||||
|
||||
uint8_t mac_addr[6];
|
||||
esp_read_mac(mac_addr, ESP_MAC_WIFI_SOFTAP);
|
||||
ESP_LOGI(TAG, "ESP32 MAC: %02X:%02X:%02X:%02X:%02X:%02X",
|
||||
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
|
||||
camera_init();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(300)); // Let the camera wake up fully
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
gpio_config_t usb_phy_conf = {
|
||||
.pin_bit_mask = (1ULL << 19) | (1ULL << 20),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
gpio_config(&usb_phy_conf);
|
||||
|
||||
printf("[MAIN] Start task\n");
|
||||
|
||||
LEP_CONFIG.agc_set_enabled = true;
|
||||
LEP_CONFIG.emissivity = 100;
|
||||
LEP_CONFIG.gain_mode = LEP_GAIN_AUTO;
|
||||
|
||||
// initialize spi, i2c and gpio for lepton
|
||||
if (!lepton_io_init())
|
||||
{
|
||||
printf("[MAIN] Error: I/O init failed");
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
// allocate lepton buffers
|
||||
if (!lepton_buffer_init())
|
||||
{
|
||||
printf("[MAIN] Error: Memory init failed");
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
// wait for lepton to initialize
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));;
|
||||
|
||||
// Attempt to initialize the VoSPI interface
|
||||
if (vospi_init() != ESP_OK)
|
||||
{
|
||||
printf("[MAIN] Error: Lepton VoSPI initialization failed\n");
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
// initialize lepton
|
||||
if (!lepton_init())
|
||||
{
|
||||
printf("[MAIN] Error: Lepton CCI initialization failed\n");
|
||||
while (1)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
|
||||
// disable data from lepton
|
||||
gpio_set_level(LEP_CSN_PIN, 1);
|
||||
|
||||
printf("LEPTON INIT DONE");
|
||||
|
||||
int64_t start = esp_timer_get_time();
|
||||
camera_capture();
|
||||
vTaskDelay(pdMS_TO_TICKS(50)); // 20 FPS = 1000/50ms
|
||||
int64_t end = esp_timer_get_time();
|
||||
|
||||
int64_t duration = end - start;
|
||||
|
||||
printf("%lf FPS, %lf SPF\n", 1 / (duration / 1000000.0), duration / 1000000.0);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user