Visualizzazione post con etichetta ESP32. Mostra tutti i post
Visualizzazione post con etichetta ESP32. Mostra tutti i post

venerdì 14 novembre 2025

SmartConfig Esp32

SmartConfig e' un metodo per configurare il WiFi di una Esp32 utilizzando una app su smartphone scaricabile dagli store o personalizzabile tramite sorgenti  (EspTouch, Github

https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/network/esp_smartconfig.html 

Esistono due versioni. In V1 vengono configurati inviando le credenziali di rete a tutti i dispositivi in ascolto 

V1
In V2 si puo' usare il Custom Data per inviare un codice riconosciuto da un solo dispositivo
 
V2

Dopo la configurazione i dati vengono salvati nella memoria NVS cosi' che al prossimo riavvio l'Esp32 riesca a connettersi in automatico al WiFi. Per cancellare la NVS si usa

idf.py erase-flash
 

 // Change from:
ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );

// To:
ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_V2) );

menu "SmartConfig Example Configuration"

config LED_GPIO
int "LED GPIO Pin"
default 2
help
GPIO pin for LED status indicator.
Default is GPIO 2 for most ESP32 boards.
ESP32-C3: Try GPIO 8
ESP32-S2/S3: Try GPIO 18 or 48

endmenu


 

 

/*
* ESP32 SmartConfig Example - ESP-IDF
*
* File: main/smartconfig_main.c
*/

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
#include "driver/gpio.h"

/* LED GPIO */
#define LED_GPIO CONFIG_LED_GPIO
#define LED_GPIO_DEFAULT 2

/* FreeRTOS event group to signal when we are connected/disconnected */
static EventGroupHandle_t s_wifi_event_group;

/* Event bits */
#define CONNECTED_BIT BIT0
#define ESPTOUCH_DONE_BIT BIT1

static const char *TAG = "smartconfig";

static void smartconfig_task(void * parm);

/* Event handler for WiFi and SmartConfig events */
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
ESP_LOGI(TAG, "WiFi station started");
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
ESP_LOGI(TAG, "Disconnected from AP");
esp_wifi_connect();
xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "Got IP:" IPSTR, IP2STR(&event->ip_info.ip));
xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
} else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
ESP_LOGI(TAG, "Scan done");
} else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
ESP_LOGI(TAG, "Found channel");
} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
ESP_LOGI(TAG, "Got SSID and password");

smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
wifi_config_t wifi_config;
uint8_t ssid[33] = { 0 };
uint8_t password[65] = { 0 };
uint8_t rvd_data[33] = { 0 };

bzero(&wifi_config, sizeof(wifi_config_t));
memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
wifi_config.sta.bssid_set = evt->bssid_set;
if (wifi_config.sta.bssid_set == true) {
memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
}

memcpy(ssid, evt->ssid, sizeof(evt->ssid));
memcpy(password, evt->password, sizeof(evt->password));
ESP_LOGI(TAG, "SSID:%s", ssid);
ESP_LOGI(TAG, "PASSWORD:%s", password);
if (evt->type == SC_TYPE_ESPTOUCH_V2) {
ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );
ESP_LOGI(TAG, "RVD_DATA:");
for (int i=0; i<33; i++) {
printf("%02x ", rvd_data[i]);
}
printf("\n");
}

ESP_ERROR_CHECK( esp_wifi_disconnect() );
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
esp_wifi_connect();
} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
}
}

/* Initialize WiFi in station mode */
static void initialise_wifi(void)
{
ESP_ERROR_CHECK(esp_netif_init());
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
assert(sta_netif);

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );

ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
ESP_ERROR_CHECK( esp_wifi_start() );
}

/* SmartConfig task */
static void smartconfig_task(void * parm)
{
EventBits_t uxBits;
ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) );
ESP_LOGI(TAG, "SmartConfig started");
ESP_LOGI(TAG, "Use ESPTouch app to configure WiFi");
while (1) {
uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
if(uxBits & CONNECTED_BIT) {
ESP_LOGI(TAG, "WiFi Connected to AP");
}
if(uxBits & ESPTOUCH_DONE_BIT) {
ESP_LOGI(TAG, "SmartConfig over");
esp_smartconfig_stop();
vTaskDelete(NULL);
}
}
}

/* LED blink task */
static void led_task(void *pvParameters)
{
gpio_reset_pin(LED_GPIO);
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
while(1) {
EventBits_t bits = xEventGroupGetBits(s_wifi_event_group);
if (bits & CONNECTED_BIT) {
/* Slow blink when connected */
gpio_set_level(LED_GPIO, 1);
vTaskDelay(100 / portTICK_PERIOD_MS);
gpio_set_level(LED_GPIO, 0);
vTaskDelay(900 / portTICK_PERIOD_MS);
} else {
/* Fast blink during configuration */
gpio_set_level(LED_GPIO, 1);
vTaskDelay(200 / portTICK_PERIOD_MS);
gpio_set_level(LED_GPIO, 0);
vTaskDelay(200 / portTICK_PERIOD_MS);
}
}
}

void app_main(void)
{
ESP_LOGI(TAG, "=== ESP32 SmartConfig Example ===");
/* Initialize NVS */
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);

/* Initialize WiFi */
initialise_wifi();
/* Try to connect with saved credentials */
ESP_LOGI(TAG, "Attempting connection with saved credentials...");
esp_wifi_connect();
/* Wait 10 seconds for connection */
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
CONNECTED_BIT,
pdFALSE,
pdFALSE,
10000 / portTICK_PERIOD_MS);
if (bits & CONNECTED_BIT) {
ESP_LOGI(TAG, "Connected with saved credentials!");
} else {
ESP_LOGI(TAG, "No saved credentials or connection failed");
ESP_LOGI(TAG, "Starting SmartConfig...");
xTaskCreate(smartconfig_task, "smartconfig_task", 4096, NULL, 3, NULL);
}
/* Start LED task */
xTaskCreate(led_task, "led_task", 2048, NULL, 2, NULL);
}


 

 

 

 

 

giovedì 13 novembre 2025

test ESPNow con IDF

Ho provato Espnow, un protocollo per inviare brevi messaggi tra Esp32 e simili senza l'appoggio di un accesspoint 

 ho usato Idf 5.3.1 ed il programma di esempio

idf.py create-project-from-example "espressif/esp-now:get-started"

idf.py menuconfig

Example configuration 

CONFIG_ESPNOW_CHANNEL → e.g. 1

 CONFIG_ESPNOW_SEND_LEN → e.g. 200

 CONFIG_ESPNOW_SEND_COUNT → e.g. 100

 CONFIG_ESPNOW_SEND_DELAY → e.g. 1000 (ms)

se non si vuole un progetto di esempio si aggiunge il componente
idf.py add-dependency "espressif/esp-now" 

 l'esempio si puo' usare in assenza di wifi e si carica lo stesso firmware di esempio su entrambi i dispositivi. A seconda di send_param->magic=esp_random() viene scelto quale tra i due dispositivi e' il sender e quale e' il receiver 

se si vuole forzare il ruolo si 

#define FORCE_SENDER 1 // 1 = always sender, 0 = always receiver 

sender.c (a seconda delle impostazione di peer mac la comunicazione puo' essere broadcast, specificando come Mac Address FF:FF:FF:FF:FF:FF od indirizzata specificatamente ad un dispositivo)

==================================== 

#include "esp_wifi.h"
#include "esp_now.h"
#include "esp_log.h"
#include "nvs_flash.h"

#include "string.h"

static const char *TAG = "ESPNOW_SENDER";

// 👉 Replace this with your receiver’s MAC address (check via `esp_read_mac`)
uint8_t peer_mac[] = {0x24, 0x6F, 0x28, 0xAA, 0xBB, 0xCC};

static void send_cb(const uint8_t *mac_addr, esp_now_send_status_t status) {
    ESP_LOGI(TAG, "Send to %02X:%02X:%02X:%02X:%02X:%02X  status: %s",
             mac_addr[0], mac_addr[1], mac_addr[2],
             mac_addr[3], mac_addr[4], mac_addr[5],
             status == ESP_NOW_SEND_SUCCESS ? "OK" : "FAIL");
}

void app_main(void) {
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_wifi_init(&(wifi_init_config_t)WIFI_INIT_CONFIG_DEFAULT()));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE));

    ESP_ERROR_CHECK(esp_now_init());
    ESP_ERROR_CHECK(esp_now_register_send_cb(send_cb));

    esp_now_peer_info_t peer = {0};
    memcpy(peer.peer_addr, peer_mac, 6);
    peer.channel = 1;
    peer.encrypt = false;
    ESP_ERROR_CHECK(esp_now_add_peer(&peer));

    const char *msg = "Hello ESPNOW";
    while (1) {
        esp_err_t res = esp_now_send(peer_mac, (uint8_t *)msg, strlen(msg));
        if (res == ESP_OK) ESP_LOGI(TAG, "Message sent: %s", msg);
        else ESP_LOGE(TAG, "Send error: %s", esp_err_to_name(res));
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

================================ 

receiver.c

============================= 

#include "esp_wifi.h"
#include "esp_now.h"
#include "esp_log.h"
#include "nvs_flash.h"

static const char *TAG = "ESPNOW_RECEIVER";

static void recv_cb(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
    ESP_LOGI(TAG, "From %02X:%02X:%02X:%02X:%02X:%02X | Len: %d | Data: %.*s",
             info->src_addr[0], info->src_addr[1], info->src_addr[2],
             info->src_addr[3], info->src_addr[4], info->src_addr[5],
             len, len, data);
}

void app_main(void) {
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_wifi_init(&(wifi_init_config_t)WIFI_INIT_CONFIG_DEFAULT()));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE));

    ESP_ERROR_CHECK(esp_now_init());
    ESP_ERROR_CHECK(esp_now_register_recv_cb(recv_cb));

    ESP_LOGI(TAG, "Receiver ready");
}

================================= 

se si vuole mandare variabili di tipo differente nel pacchetto queste devono essere incluse in una struttura. La lunghezza dei pacchetti e' 250 bytes

================================= 

#include "esp_wifi.h"
#include "esp_now.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <string.h>

static const char *TAG = "ESPNOW_SENDER";

uint8_t peer_mac[] = {0x24, 0x6F, 0x28, 0xAA, 0xBB, 0xCC};

// Define your custom data structure
typedef struct {
    uint32_t id;
    float temperature;
    float humidity;
    int status;
    char label[16];
} sensor_packet_t;

static void send_cb(const uint8_t *mac_addr, esp_now_send_status_t status) {
    ESP_LOGI(TAG, "Send to %02X:%02X:%02X:%02X:%02X:%02X  status: %s",
             mac_addr[0], mac_addr[1], mac_addr[2],
             mac_addr[3], mac_addr[4], mac_addr[5],
             status == ESP_NOW_SEND_SUCCESS ? "OK" : "FAIL");
}

void app_main(void) {
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_wifi_init(&(wifi_init_config_t)WIFI_INIT_CONFIG_DEFAULT()));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE));

    ESP_ERROR_CHECK(esp_now_init());
    ESP_ERROR_CHECK(esp_now_register_send_cb(send_cb));

    esp_now_peer_info_t peer = {0};
    memcpy(peer.peer_addr, peer_mac, 6);
    peer.channel = 1;
    peer.encrypt = false;
    ESP_ERROR_CHECK(esp_now_add_peer(&peer));

    sensor_packet_t pkt = {0};
    pkt.id = 1;

    while (1) {
        pkt.temperature = 22.5 + (esp_random() % 100) / 10.0;
        pkt.humidity = 60.0 + (esp_random() % 100) / 10.0;
        pkt.status = esp_random() % 2;
        strcpy(pkt.label, "Node_A");

        esp_err_t res = esp_now_send(peer_mac, (uint8_t *)&pkt, sizeof(pkt));
        if (res == ESP_OK)
            ESP_LOGI(TAG, "Sent packet: id=%lu T=%.1f H=%.1f status=%d",
                     pkt.id, pkt.temperature, pkt.humidity, pkt.status);
        else
            ESP_LOGE(TAG, "Send error: %s", esp_err_to_name(res));

        pkt.id++;
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

==================== 

#include "esp_wifi.h"
#include "esp_now.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include <string.h>

static const char *TAG = "ESPNOW_RECEIVER";

typedef struct {
    uint32_t id;
    float temperature;
    float humidity;
    int status;
    char label[16];
} sensor_packet_t;

static void recv_cb(const esp_now_recv_info_t *info, const uint8_t *data, int len) {
    if (len != sizeof(sensor_packet_t)) {
        ESP_LOGW(TAG, "Invalid packet size: %d", len);
        return;
    }

    sensor_packet_t pkt;
    memcpy(&pkt, data, sizeof(pkt));

    ESP_LOGI(TAG, "From %02X:%02X:%02X:%02X:%02X:%02X | id=%lu | T=%.1f | H=%.1f | status=%d | label=%s",
             info->src_addr[0], info->src_addr[1], info->src_addr[2],
             info->src_addr[3], info->src_addr[4], info->src_addr[5],
             pkt.id, pkt.temperature, pkt.humidity, pkt.status, pkt.label);
}

void app_main(void) {
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(esp_wifi_init(&(wifi_init_config_t)WIFI_INIT_CONFIG_DEFAULT()));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_set_channel(1, WIFI_SECOND_CHAN_NONE));

    ESP_ERROR_CHECK(esp_now_init());
    ESP_ERROR_CHECK(esp_now_register_recv_cb(recv_cb));

    ESP_LOGI(TAG, "Receiver ready");
}
 

 

 

venerdì 20 giugno 2025

NanoProtoBuf Esp32 IDF

Su Esp32 (e piu' in generale sui microcontrollori) la libreria Protobuf non puo' funzionare e quindi si deve usare nanopb (nano proto buffer)  https://github.com/nanopb/nanopb

Il seguente progetto e' stato creato usando il plugin Esp-Idf di VSCode

Per utilizzarla si deve prima installare il compilare protoc e poi scaricare e compilare il pacchetto nanopb da GitHub ...questo servira' come plugin per protoc

Si procede  quindi con il seguente comando che genera i file sensor.pb.c e sensor.pb.h dove sono inserite le classi per la lettura scrittura del file sensor.proto. questi due file sono da inserire nella main del progetto mentre i file pb_common.c pb_common.h pb_decode.c pb_decode.h pc_encode.c e pb_encode.h si inseriscono nel folder nanopb all'interno del folder main  

protoc --plugin=protoc-gen-nanopb=/home/luca/nanopb/generator/protoc-gen-nanopb --nanopb_out=./ --proto_path=/home/luca/nanopb/generator/proto sensor.proto

sensor.proto

syntax = "proto3";

message SensorData {
int32 id = 1;
float temperature = 2;
float humidity = 3;
}

Si modifica quindi il file CMakeLists.txt per puntare i nuovi file

idf_component_register(
SRCS
"main.c"
"sensor.pb.c"
"nanopb/pb_encode.c"
"nanopb/pb_decode.c"
"nanopb/pb_common.c"
INCLUDE_DIRS
"."
"nanopb"
)

e si puo' compilare questo semplice programma di esempio sull'utilizzo di nanopb 

#include <stdio.h>

#include "sensor.pb.h"
#include "pb_encode.h"
#include "pb_decode.h"

#include "driver/uart.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void app_main(void)
{
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};



uart_driver_install(UART_NUM_0, 1024, 0, 0, NULL, 0);
uart_param_config(UART_NUM_0, &uart_config);

const char *msg = "Hello from UART0 via USB!\n";
uart_write_bytes(UART_NUM_0, msg, strlen(msg));


vTaskDelay(pdMS_TO_TICKS(3000));
printf("USB CDC active\n");

vTaskDelay(pdMS_TO_TICKS(500)); // Delay to let USB CDC connect


uint8_t buffer[128];
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));

SensorData da = SensorData_init_zero;
da.id = 42;
da.temperature = 23.5;
da.humidity = 55.2;

if (pb_encode(&stream, SensorData_fields, &da)) {
size_t message_length = stream.bytes_written;
// Send buffer over serial, BLE, etc.
} else {
//Serial.println("Encoding failed!");
}

size_t message_length = stream.bytes_written;

SensorData da_r = SensorData_init_zero;
//int received_length = 0;
pb_istream_t str = pb_istream_from_buffer(buffer, message_length);

while(1){
if (pb_decode(&str, SensorData_fields, &da_r)) {
char str_out[32];
snprintf(str_out, sizeof(str_out), "%.2f\n", da_r.humidity);
uart_write_bytes(UART_NUM_0, str_out, strlen(str_out));
printf("Temp: %.2f, Humidity: %.2f\n",da_r.temperature, da_r.humidity);
} else {
uart_write_bytes(UART_NUM_0, "Decoding error\n", strlen("Decoding error\n"));
printf("Error decoding\n");
}

vTaskDelay(pdMS_TO_TICKS(1000));}

}

 

 

 

lunedì 9 giugno 2025

M5 Dial LVGL e Platformio

Per compilare i progetti M5Dial con Platformio si scaricano gli esempi da https://github.com/mzyy94/M5Dial-LVGL

 


 

Da dentro Platformio si apre il folder del progetto in examples/dial_number e si effettua la build

Un dettaglio .. il pulsante di reset e' nascosto dietro l'adesivo

 



 

T-Dongle S3 ed IDF 5

Ho ripreso in mano il T-Dongle S3 di Lilygo ed i progetti IDF che sono presenti sul github ufficiale non funzionano piu' perche' la libreria LovyanGFX non risulta compatibile con IDF 5.x (il codice e' stato scritto per una versione precedente di IDF)


 

Ho provato a correggere ma alla fine ho preso un docker IDF 4.4 ed ho usato questo per compilare il progetto 

Importante: per mettere in modalita' programmazione la scheda si deve premere il pulsante e poi inserire la scheda nella porta USB.  Per avviare lo sketch la scheda deve essere rimossa e poi inserita

sudo apt update
sudo apt install docker.io
sudo systemctl enable docker --now
sudo usermod -aG docker $USER
newgrp docker

 

docker pull espressif/idf:release-v4.4

docker run --rm -it   --device=/dev/ttyACM0   -v ~/T-Dongle-S3:/project   -w /project   espressif/idf:release-v4.4 

 

 idf.py set-target esp32s3

 idf.py build

 

 

 

mercoledì 18 dicembre 2024

Debugger integrato ESP32S3

Aggiornamento

In realta' il Jtag USB funziona anche sui moduli cinesi

Il problema risiede  nell'ID USB della porta Jtag. Nel modulo Espressif originale si trova in 303a:1001 mentre nel modulo cinese si trova in 303a:4001

Si deve quindi modificare la configurazione di OpenOCD nel file

/.espressif/tools/openocd-esp32/v0.12.0-esp32-20240821/openocd-esp32/share/openocd/scripts/interface/esp_usb_jtag.cfg 

espusbjtag vid_pid 0x303a 0x4001
espusbjtag caps_descriptor 0x2000


modificando Pid da 1001 a 4001 ed aggiungendo la regola in udev 

ATTRS{idVendor}=="303a", ATTRS{idProduct}=="4001", MODE="664", GROUP="plugdev", TAG+="uaccess

--------------------------------------------------------------------------------------------------------

La Esp32S3 espone sui pin 19 e 20 una porta USB che puo' essere usata per fare debug....ma attenzione...questo e' valido per il DevKit ufficiale di Espressif ma non funziona con i moduli cinesi (ci sono impazzito dietro a questa cosa)

 

Si deve creare un cavo usb tagliandone uno, giuntando dei cavi Dupount femmina e connettendo

D+ (verde) a GPIO19

D- (bianco) a GPIO20

GND (nero) a GND (forse non necessario)




a questo punto connettendo la scheda con lsusb si legge Espressif USB Jtag Serial (che si e' andato su /dev/ttyACM0) come debugger e CP210x UART Bridge come /dev/ttyUSB0 per la normale connessione con Esp32

a questo punto si ha il seguente errore nell'avviare il server OpenOCD

libusb_open() failed with LIBUSB_ERROR_ACCESS

prima di tutto si deve inserire l'utente nel gruppo plugdev

sudo usermod -a -G plugdev luca

poi si crea un file 99-jtag.rules con contenuto 

ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="664", GROUP="plugdev", TAG+="uaccess"

e lo si copia in /etc/udev/rules.d. (i valori sono ripresi da comando lsusb). Si aggiorna plugdev

sudo udevadm control --reload-rules & sudo udevadm trigger

si avvia il server OpenOcd

openocd -f board/esp32s3-builtin.cfg

e poi da dentro Visual Code plugin ESP-IDF si clicca su Flash (se il progetto e' configurato bene inizia anche il debug) Select Flash Mode JTAG port /dev/ttyUSB0

ed ecco alla fine avviata la sessione di debug usando l'esempio Fibonacci




venerdì 29 novembre 2024

ESP32 logger low power

A seguito del precedente post in questo caso il logger e' stato fatto con una ESP32S3 






Al contrario di Arduino dove i dati erano salvati su SD card qui vengono salvati sulla memoria interna tramite Littefs. Al primo avvio viene cancellato il file dati poi vengono salvati i dati in append dell'ADC, inoltre 

 

E' stato usato il deep sleep tramite RTC. In questo modo la ESP32 effettua un riavvio completo ogni tot secondi..la variabile conta serve come contatore progressivo dei riavvii in modo che al primo ciclo vengano eseguiti specifici. la variabile conta e' dichiarata come RTC_DATA_ATTR in modo da non essere volatile ed essere preservata nella fase di deep sleep

Anche se non precisssimo quando in deep l'RTC continua a funzionare...si setta quindi la data ed ora al primo riavvio e poi si legge il tempo aggiornato ai successivi riavvii. 

 Usando lo sketch della sola lettura analogica di un pin ESP32 consuma circa 19 mA



in deep sleep il consumo crolla al livello delle decine di  microA tanto che la mia schedina non riesce a rilevarlo

 


per usare LittleFs si deve aggiungere il componente in idf_component.yml

dependencies:
joltwallet/littlefs: "==1.14.8"
## Required IDF v

modificare sdkconfig per indicare il file dove sono settate le impostazioni della partizione (in questo caso il file csv)

# Partition Table
#
# CONFIG_PARTITION_TABLE_SINGLE_APP is not set
# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_demo_esp_littlefs.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions_demo_esp_littlefs.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
CONFIG_PARTITION_TABLE_MD5=y
# end of Partition Table


e creare il corrispondente file 

nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 1M,
littlefs,  data, spiffs,      ,  0xF0000,

questo il codice finale

include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "sdkconfig.h"
#include "soc/soc_caps.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "driver/rtc_io.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "deep_sleep_example.h"

#include <time.h>
#include <sys/time.h>

#include "driver/gpio.h"
#define PIN GPIO_NUM_35

#include "esp_system.h"
#include "spi_flash_mmap.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_littlefs.h"
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>


#include "driver/adc.h"
#include "esp_adc_cal.h"



/*
#if SOC_RTC_FAST_MEM_SUPPORTED
static RTC_DATA_ATTR struct timeval sleep_enter_time;
#else
static struct timeval sleep_enter_time;
#endif
*/
RTC_DATA_ATTR int conta =0;

struct tm tm;

static void deep_sleep_task(void *args)
{
esp_deep_sleep_start();
}

static void deep_sleep_register_rtc_timer_wakeup(void)
{
const int wakeup_time_sec = 15;
conta = conta + 1;
gpio_set_direction(PIN, GPIO_MODE_OUTPUT);
gpio_set_level(PIN, 0);
vTaskDelay(100);
gpio_set_level(PIN, 1);

struct timeval tv;
char buffer[30];
time_t curtime;
gettimeofday(&tv, NULL);
curtime=tv.tv_sec;
strftime(buffer,30,"%m-%d-%Y %T.",localtime(&curtime));
printf("Orario %s%ld\n",buffer,tv.tv_usec);

esp_adc_cal_characteristics_t adc1_chars;
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars);
adc1_config_width(ADC_WIDTH_BIT_DEFAULT);
adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_11);
int adc_value = adc1_get_raw(ADC1_CHANNEL_4);
static const char *TAG = "demo_esp_littlefs";

ESP_LOGI(TAG, "Initializing LittelFS");

esp_vfs_littlefs_conf_t conf = {
.base_path = "/littlefs",
.partition_label = "littlefs",
.format_if_mount_failed = true,
.dont_mount = false,
};

// Use settings defined above to initialize and mount LittleFS filesystem.
// Note: esp_vfs_littlefs_register is an all-in-one convenience function.
esp_err_t ret = esp_vfs_littlefs_register(&conf);

if (ret != ESP_OK)
{
if (ret == ESP_FAIL)
{
ESP_LOGE(TAG, "Failed to mount or format filesystem");
}
else if (ret == ESP_ERR_NOT_FOUND)
{
ESP_LOGE(TAG, "Failed to find LittleFS partition");
}
else
{
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
}
return;
}

size_t total = 0, used = 0;
ret = esp_littlefs_info(conf.partition_label, &total, &used);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Failed to get LittleFS partition information (%s)", esp_err_to_name(ret));
}
else
{
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}

// Use POSIX and C standard library functions to work with files.
// First create a file.
ESP_LOGI(TAG, "Opening file");
FILE *f = fopen("/littlefs/dati.txt", "a");
if (f == NULL)
{
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f,"%s%ld, %i\n",buffer,tv.tv_usec,adc_value);
fclose(f);
ESP_LOGI(TAG, "File written");
ESP_LOGI(TAG, "Reading file");
f = fopen("/littlefs/dati.txt", "r");
if (f == NULL)

{
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}

int c;
while ((c = getc(f)) != EOF)
putchar(c);

//char line[64];
//fgets(line, sizeof(line), f);
fclose(f);

// All done, unmount partition and disable LittleFS
esp_vfs_littlefs_unregister(conf.partition_label);
ESP_LOGI(TAG, "LittleFS unmounted");



printf("conteggio %d\n",conta);
//printf("Minuti: %llu\n",tv.tv_sec);
printf("Stato: %d\n",adc_value);
printf("Enabling timer wakeup, %ds\n", wakeup_time_sec);
ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000));
}

void app_main(void)
{

gpio_set_direction(PIN, GPIO_MODE_OUTPUT);
gpio_set_level(PIN, 1);

tm.tm_year = 2024 - 1900;
tm.tm_mon = 11;
tm.tm_mday = 27;
tm.tm_hour = 13;
tm.tm_min = 23;
tm.tm_sec =10;

if (conta < 2) {
time_t t = mktime(&tm);
struct timeval now = { .tv_sec = t };
settimeofday(&now, NULL);

static const char *TAG = "esp_littlefs";

esp_vfs_littlefs_conf_t conf = {
.base_path = "/littlefs",
.partition_label = "littlefs",
.format_if_mount_failed = true,
.dont_mount = false,
};

esp_err_t ret = esp_vfs_littlefs_register(&conf);

if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find LittleFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
}
return;
}

if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount or format filesystem");
} else if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "Failed to find LittleFS partition");
} else {
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
}
return;
}

struct stat st;

if (stat("/littlefs/dati.txt", &st) == 0) {
// Delete it if it exists
unlink("/littlefs/dati.txt");
}
else{
ESP_LOGE(TAG, "File non cancellato");

}
esp_vfs_littlefs_unregister(conf.partition_label);
ESP_LOGI(TAG, "LittleFS unmounted");
}

deep_sleep_register_rtc_timer_wakeup();
xTaskCreate(deep_sleep_task, "deep_sleep_task", 4096, NULL, 6, NULL);
}


 

Analisi MNF su spettri di riflettanza di plastica

Devo cerca di lavorare su spettri di riflettanza di plastica e la prima domanda e': quale sono le bande significative? Sono partito dal ...