#include <Arduino.h>
#include <WiFi.h>
#include <SPI.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebSrv.h>
#include <ArduinoJson.h>
// Configurazione hardware
#define CS_PIN 5
#define DRDY_PIN 4
// Configurazione acquisizione
#define DEFAULT_SAMPLE_RATE 30000 // Hz
// Configurazione Wi-Fi
const char* WIFI_SSID = "WebPocket-E280";
const char* WIFI_PASSWORD = "dorabino.7468!";
// Gestione configurazione
struct Config {
uint32_t sampleRate;
uint8_t gain;
bool filterEnabled;
float threshold;
bool streaming;
};
// Variabili globali
QueueHandle_t dataQueue;
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
Config globalConfig = {DEFAULT_SAMPLE_RATE, 1, false, 1000000, true};
float emaAlpha = 0.1;
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi] Event: %d\n", event);
switch(event) {
case ARDUINO_EVENT_WIFI_READY:
Serial.println("WiFi interface ready");
break;
case ARDUINO_EVENT_WIFI_SCAN_DONE:
Serial.println("Completed scan for access points");
break;
case ARDUINO_EVENT_WIFI_STA_START:
Serial.println("WiFi client started");
break;
case ARDUINO_EVENT_WIFI_STA_STOP:
Serial.println("WiFi clients stopped");
break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
Serial.println("Connected to access point");
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
Serial.println("Disconnected from WiFi access point");
break;
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
Serial.println("Authentication mode of access point changed");
break;
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
Serial.print("Obtained IP address: ");
Serial.println(WiFi.localIP());
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
Serial.println("Lost IP address and IP address is reset to 0");
break;
}
}
void printWiFiDetails() {
if(WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi Connection Details:");
Serial.printf("SSID: %s\n", WiFi.SSID().c_str());
Serial.printf("BSSID: %s\n", WiFi.BSSIDstr().c_str());
Serial.printf("Channel: %d\n", WiFi.channel());
Serial.printf("RSSI: %d dBm\n", WiFi.RSSI());
Serial.printf("IP: %s\n", WiFi.localIP().toString().c_str());
Serial.printf("Subnet: %s\n", WiFi.subnetMask().toString().c_str());
Serial.printf("Gateway: %s\n", WiFi.gatewayIP().toString().c_str());
Serial.printf("DNS: %s\n", WiFi.dnsIP().toString().c_str());
Serial.printf("MAC: %s\n", WiFi.macAddress().c_str());
}
}
// Gestione WebSocket
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len) {
if(type == WS_EVT_CONNECT){
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
} else if(type == WS_EVT_DISCONNECT){
Serial.printf("WebSocket client #%u disconnected\n", client->id());
} else if(type == WS_EVT_DATA){
AwsFrameInfo *info = (AwsFrameInfo*)arg;
if(info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
data[len] = 0;
String message = String((char*)data);
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, message);
if(!error) {
if(doc.containsKey("samplerate")) {
globalConfig.sampleRate = doc["samplerate"].as<int>();
Serial.printf("Sample rate impostato a: %d\n", globalConfig.sampleRate);
}
if(doc.containsKey("alfaema")) {
emaAlpha = doc["alfaema"].as<float>();
Serial.printf("EMA alpha impostato a: %.2f\n", emaAlpha);
}
}
}
}
}
/*
// Task ADC
void IRAM_ATTR adcTask(void* pvParameters) {
SPIClass spi(VSPI);
spi.begin(18, 19, 23, CS_PIN);
pinMode(CS_PIN, OUTPUT);
pinMode(DRDY_PIN, INPUT);
uint32_t lastSample = 0;
uint32_t sampleInterval = 1000000 / globalConfig.sampleRate;
float emaFilteredValue = 0.0;
while (true) {
if (!globalConfig.streaming) {
vTaskDelay(100 / portTICK_PERIOD_MS);
continue;
}
if (digitalRead(DRDY_PIN) == LOW &&
(micros() - lastSample) >= sampleInterval) {
digitalWrite(CS_PIN, LOW);
uint8_t data[3] = {0x01, 0x02, 0x03};
digitalWrite(CS_PIN, HIGH);
int32_t value = (data[0] << 16) | (data[1] << 8) | data[2];
if (value & 0x800000) value -= 0x1000000;
emaFilteredValue = emaAlpha * value + (1 - emaAlpha) * emaFilteredValue;
// Invia alla coda
xQueueSend(dataQueue, &emaFilteredValue, 0);
lastSample = micros();
}
}
}
*/
void adcTask(void* pvParameters) {
uint32_t lastSample = 0;
uint32_t sampleInterval = 1000000 / globalConfig.sampleRate;
while (true) {
if (!globalConfig.streaming) {
vTaskDelay(100 / portTICK_PERIOD_MS);
continue;
}
if ((micros() - lastSample) >= sampleInterval) {
uint32_t timestamp = micros();
float sample = random(0, 1000); // Campioni casuali (da 0 a 1000)
// Pacchetto JSON con campione e timestamp
char message[128];
snprintf(message, sizeof(message), "{\"timestamp\": %u, \"sample\": %.2f}", timestamp, sample);
// Invia al server WebSocket
xQueueSend(dataQueue, &message, 0);
lastSample = timestamp;
}
}
}
// Task WebSocket
void webSocketDataTask(void* pvParameters) {
float value;
char buffer[32];
while(true) {
if(xQueueReceive(dataQueue, &value, portMAX_DELAY) == pdTRUE) {
if(ws.count() > 0) { // Se ci sono client connessi
snprintf(buffer, sizeof(buffer), "%.2f", value);
ws.textAll(buffer);
}
}
}
}
void setup() {
Serial.begin(115200);
// Abilita log verbose WiFi
esp_log_level_set("wifi", ESP_LOG_VERBOSE);
// Registra handler eventi WiFi
WiFi.onEvent(WiFiEvent);
// Inizializza WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
uint8_t attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
printWiFiDetails();
} else {
Serial.println("\nWiFi connection failed!");
ESP.restart();
}
// Setup WebSocket
ws.onEvent(onWsEvent);
server.addHandler(&ws);
// Avvia server
server.begin();
// Crea la coda
dataQueue = xQueueCreate(1024, sizeof(float));
// Avvia i task
xTaskCreatePinnedToCore(webSocketDataTask, "WS Data Task", 8192, NULL, 1, NULL, 0); // Sul core 0 con WiFi
xTaskCreatePinnedToCore(adcTask, "ADC Task", 16384, NULL, 5, NULL, 1); // Sul core 1
Serial.println("Setup completato");
}
void loop() {
static unsigned long lastDebugTime = 0;
const unsigned long debugInterval = 5000; // Debug ogni 5 secondi
if (millis() - lastDebugTime > debugInterval) {
// Stampa info memoria
Serial.printf("Free Heap: %d bytes\n", ESP.getFreeHeap());
Serial.printf("Min Free Heap: %d bytes\n", ESP.getMinFreeHeap());
Serial.printf("Max Alloc Heap: %d bytes\n", ESP.getMaxAllocHeap());
// Stampa info WiFi
Serial.printf("WiFi RSSI: %d dBm\n", WiFi.RSSI());
Serial.printf("WebSocket Clients: %u\n", ws.count());
lastDebugTime = millis();
}
vTaskDelay(10); // Previene watchdog reset
}
esp:VIN
esp:GND.2
esp:D13
esp:D12
esp:D14
esp:D27
esp:D26
esp:D25
esp:D33
esp:D32
esp:D35
esp:D34
esp:VN
esp:VP
esp:EN
esp:3V3
esp:GND.1
esp:D15
esp:D2
esp:D4
esp:RX2
esp:TX2
esp:D5
esp:D18
esp:D19
esp:D21
esp:RX0
esp:TX0
esp:D22
esp:D23
led1:A
led1:C
led2:A
led2:C
led3:A
led3:C
r1:1
r1:2
r2:1
r2:2
r3:1
r3:2