Better makefile, plotting, saving the data, and cleanup

This commit is contained in:
Jonas Hahn
2025-12-20 20:39:35 +01:00
parent 0efab1c8b3
commit ce9b819b18
7 changed files with 103 additions and 77 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
build/
.cache/
sdkconfig*
data/

View File

@@ -1,6 +1,17 @@
help:
# plot - Plot the latest measurement
# monitor - Build and monitor onto esp if connected to /dev/ttyUSB0
# env - Start the esp environment on nix
# server - Start the go server
monitor:
idf.py -p /dev/ttyUSB0 flash monitor
env:
nix --experimental-features 'nix-command flakes' develop github:mirrexagon/nixpkgs-esp-dev#esp32-idf
plot:
nix-shell --pure --run "python plot.py"
server:
go run main.go

47
main.go
View File

@@ -1,12 +1,39 @@
package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"time"
)
var dataFile *os.File
type VoltageData struct {
Voltage float64 `json:"voltage"`
}
func initDataFile() {
// Ensure the data/ directory exists
if err := os.MkdirAll("data", os.ModePerm); err != nil {
log.Fatalf("Failed to create data directory: %v", err)
}
// Generate a filename with timestamp
filename := filepath.Join("data", fmt.Sprintf("voltages_%s.txt", time.Now().Format("20060102_150405")))
file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Fatalf("Failed to open data file: %v", err)
}
dataFile = file
log.Printf("Logging voltage data to %s\n", filename)
}
func handler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "POST only", http.StatusMethodNotAllowed)
@@ -20,13 +47,31 @@ func handler(w http.ResponseWriter, r *http.Request) {
}
defer r.Body.Close()
fmt.Println("Received:", string(body))
// Parse JSON
var v VoltageData
if err := json.Unmarshal(body, &v); err != nil {
http.Error(w, "invalid JSON", http.StatusBadRequest)
return
}
// Print voltage to console
fmt.Println("Received voltage:", v.Voltage)
// Append voltage number to file
if dataFile != nil {
if _, err := dataFile.WriteString(fmt.Sprintf("%f\n", v.Voltage)); err != nil {
log.Printf("Failed to write to file: %v", err)
}
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
}
func main() {
initDataFile()
defer dataFile.Close()
http.HandleFunc("/data", handler)
addr := ":8080"

View File

@@ -1,6 +1,6 @@
/*
Voltage measurement device over wifi from WiFi station Example
*/
*/
#include <string.h>
@@ -33,42 +33,13 @@
// TODO: Determine this
#define CALIBRATION_FACTOR 1650.0f
/* The examples use WiFi configuration that you can set via project configuration menu
If you'd rather not, just change the below entries to strings with
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/
#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID
// Settings for wifi
#define EXAMPLE_ESP_WIFI_SSID "Jaguar"
#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD
#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY
#if CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HUNT_AND_PECK
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK
#define EXAMPLE_H2E_IDENTIFIER ""
#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HASH_TO_ELEMENT
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH
#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH
#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID
#endif
#if CONFIG_ESP_WIFI_AUTH_OPEN
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN
#elif CONFIG_ESP_WIFI_AUTH_WEP
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP
#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK
#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK
#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK
#endif
// Tag for logging
static const char *TAG = "VoltageSensor";
@@ -93,7 +64,7 @@ static void event_handler(void* arg, esp_event_base_t event_base,
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
if (s_retry_num < 3) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to the AP");

31
plot.py Normal file
View File

@@ -0,0 +1,31 @@
import os
import matplotlib.pyplot as plt
import numpy as np
DATA_DIR = "data"
SAMPLE_INTERVAL_MS = 300 # time between measurements in milliseconds
# Find the latest data file
files = [f for f in os.listdir(DATA_DIR) if f.startswith("voltages_") and f.endswith(".txt")]
if not files:
raise FileNotFoundError("No voltage data files found in 'data/'")
latest_file = max(files, key=lambda f: os.path.getmtime(os.path.join(DATA_DIR, f)))
filepath = os.path.join(DATA_DIR, latest_file)
print(f"Plotting data from {filepath}")
# Load voltage values
voltages = np.loadtxt(filepath)
# Create time axis (in seconds)
times = np.arange(len(voltages)) * (SAMPLE_INTERVAL_MS / 1000.0)
# Plot
plt.figure(figsize=(10, 5))
plt.plot(times, voltages, marker='o', linestyle='-')
plt.xlabel("Time (s)")
plt.ylabel("Voltage (V)")
plt.title(f"Voltage Measurements ({latest_file})")
plt.grid(True)
plt.tight_layout()
plt.show()

View File

@@ -1,43 +0,0 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import os
from typing import Callable
from typing import Tuple
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
# diff of esp32s2/esp32s3 ~45K, others ~50K
DIFF_THRESHOLD = {
'esp32s2': 40 * 1000,
'esp32s3': 40 * 1000,
'default': 45 * 1000,
}
@pytest.mark.wifi_two_dut
@pytest.mark.parametrize('count, config, skip_autoflash', [(2, 'default|enable_softap', 'y')], indirect=True)
@idf_parametrize(
'target',
['esp32', 'esp32c2', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'],
indirect=['target'],
)
def test_wifi_sdkconfig_disable_softap_save_binary_size(
dut: Tuple[Dut, Dut],
log_performance: Callable[[str, object], None],
) -> None:
# dut logs are not needed
dut[0].serial.close()
dut[1].serial.close()
app_without_softap = dut[0].app
app_with_softap = dut[1].app
assert app_without_softap.sdkconfig['ESP_WIFI_SOFTAP_SUPPORT'] is False
assert app_with_softap.sdkconfig['ESP_WIFI_SOFTAP_SUPPORT'] is True
diff = os.path.getsize(app_with_softap.bin_file) - os.path.getsize(app_without_softap.bin_file)
log_performance('wifi_disable_softap_save_bin_size', f'{diff} bytes')
diff_threshold = DIFF_THRESHOLD.get(dut[0].target) or DIFF_THRESHOLD['default']
assert diff > diff_threshold

10
shell.nix Normal file
View File

@@ -0,0 +1,10 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [
(pkgs.python313.withPackages (p: with p; [
matplotlib
numpy
]))
];
}