Skip to content
Open

NVS #17

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ jobs:
- target: esp32c3
display: cu2
custom: supermini
- target: esp32c3
display: cu3
custom: supermini
steps:
- name: Checkout repo
uses: actions/checkout@v3
Expand Down
1 change: 0 additions & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@
"${workspaceFolder}/sdk/idf/components/soc/esp32/include",
"${workspaceFolder}/sdk/idf/components/soc/include",
"${workspaceFolder}/sdk/idf/components/spi_flash/include",
"${workspaceFolder}/sdk/idf/components/littlefs/include",
"${workspaceFolder}/sdk/idf/components/tcp_transport/include",
"${workspaceFolder}/sdk/idf/components/ulp/ulp_common/include",
"${workspaceFolder}/sdk/idf/components/ulp/ulp_common/include/esp32",
Expand Down
2 changes: 1 addition & 1 deletion main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
idf_component_register(SRC_DIRS "." "states"
INCLUDE_DIRS "."
REQUIRES esp32-button driver littlefs esp_timer nvs_flash esp_adc
REQUIRES esp32-button driver esp_timer nvs_flash esp_adc
)
18 changes: 8 additions & 10 deletions main/bat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static const char *TAG = "bat";
// ADC Attenuation
// 11DB = 3.55 voltage gain, reference voltage should be around 1100mv,
// so max theoretical measurement would be 3905mv, actual/recommended(?) is a lot lower.
#define ADC_ATTEN ADC_ATTEN_DB_11
#define ADC_ATTEN ADC_ATTEN_DB_12

static bool cali_enable = false;
static adc_oneshot_unit_handle_t adc1_handle = NULL;
Expand All @@ -22,6 +22,9 @@ static uint32_t batMv = 27600;
static uint32_t history;
static uint8_t batPercentage;

// Get lower/upper limit from configuration
static uint32_t emptyMv = CONFIG_ION_ADC_EMPTY_MV;
static uint32_t fullMv = CONFIG_ION_ADC_FULL_MV;
static void adc_calibration_init(adc_unit_t unit, adc_atten_t atten) {
esp_err_t ret = ESP_FAIL;

Expand Down Expand Up @@ -83,6 +86,7 @@ void adc_init() {
config.atten = ADC_ATTEN;
config.bitwidth = ADC_BITWIDTH_DEFAULT;

// Voltage channel
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, (adc_channel_t)CONFIG_ION_ADC_CHAN, &config));

adc_calibration_init(ADC_UNIT_1, ADC_ATTEN);
Expand All @@ -106,18 +110,12 @@ uint32_t measureBatMv() {

static uint8_t batMvToPercentage(uint32_t batMv) {

// Get lower/upper limit from configuration
uint32_t emptyMv = CONFIG_ION_ADC_EMPTY_MV;
uint32_t fullMv = CONFIG_ION_ADC_FULL_MV;

// Calculate the percentage
uint32_t percentage = (batMv < emptyMv) ? 0 : ((batMv - emptyMv) * 100) / (fullMv - emptyMv);

// Limit to 0-100
uint8_t batterypercentage = 0;
if (percentage < 0) {
batterypercentage = 0;
} else if (percentage > 100) {
if (percentage > 100) {
batterypercentage = 100;
} else {
batterypercentage = (uint8_t)percentage;
Expand All @@ -138,15 +136,15 @@ void measureBat() {
uint32_t avg = history >> 7;
history -= avg;

batPercentage = batMvToPercentage(avg);
batPercentage = batMvToPercentage(avg);
}

uint32_t getBatMv() {
return batMv;
}

uint8_t getBatPercentage() {
if(batPercentage == 0) {
if(batMv == 0) {
// Use a fake value of 50% when we don't have ADC.
return 50;
}
Expand Down
22 changes: 5 additions & 17 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ TimerHandle_t healthCheckTimer ;

static void checkMyTaskHealth(TimerHandle_t xTimer) {
if (!myTaskAlive) {
batDataSave();
esp_restart();
}
myTaskAlive = false; // Reset voor volgende check
Expand Down Expand Up @@ -147,21 +148,8 @@ static messageHandlingResult handleMotorMessage(ion_state * state) {
writeMessage(cmdResp(message.source, MSG_BMS, message.command, payload, sizeof(payload)));
return CONTROL_TO_SENDER;
} else if(message.type == MSG_CMD_REQ && message.payloadSize == 4 && message.command == CMD_GET_DATA && message.payload[1] == 0x38 && message.payload[3] == 0x3a) {
// GET DATA 9438283a 14:38(Calibration A) 28:3a(Calibration B)
uint8_t payload[] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // Data (last 10 bytes) to be replaced

if(calibrationFileExists()) {
if(!readCalibrationData(payload + 1)) {
return CONTROL_TO_SENDER;
}
} else {
// Backup data
// Gold small test: 94 38 4b 13 28 3a 3e 98 ed f3
uint8_t data[] = {0x94, 0x38, 0x4b, 0x15, 0x28, 0x3a, 0x3e, 0x91, 0x79, 0x50}; // This needs to be good calibration data!
memcpy(payload + 1, data, 10);
}

writeMessage(cmdResp(message.source, MSG_BMS, message.command, payload, sizeof(payload)));
uint8_t *payload = calibrationLoad();
writeMessage(cmdResp(message.source, MSG_BMS, message.command, payload, 11));
return CONTROL_TO_SENDER;
} else if(message.type == MSG_CMD_REQ && message.payloadSize == 10 && message.command == CMD_PUT_DATA && message.payload[1] == 0xc0 && message.payload[5] == 0xc1) {
// PUT DATA c0/c1
Expand All @@ -174,7 +162,7 @@ static messageHandlingResult handleMotorMessage(ion_state * state) {
return CONTROL_TO_SENDER;
} else if(message.type == MSG_CMD_REQ && message.payloadSize == 10 && message.command == CMD_PUT_DATA && message.payload[1] == 0x38 && message.payload[5] == 0x3a) {
// PUT DATA 38/3a
if(!writeCalibrationData(message.payload)) {
if(!calibrationSave(message.payload)) {
return CONTROL_TO_SENDER;
}

Expand Down Expand Up @@ -242,7 +230,7 @@ static void my_task(void *pvParameter) {
adc_init();
#endif

init_littlefs();
storageInit();

initUart();

Expand Down
4 changes: 2 additions & 2 deletions main/states/motor_off.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "blink.h"
#include "trip.h"
#include "storage.h"
#include "states.h"

void toMotorOffState(ion_state * state) {

queueBlink(4, 100, 300);

saveDistances();
batDataSave();

state->state = MOTOR_OFF;
state->step = 0;
Expand Down
171 changes: 108 additions & 63 deletions main/storage.cpp
Original file line number Diff line number Diff line change
@@ -1,87 +1,132 @@
#include <sys/stat.h>
#include "esp_log.h"
#include "esp_littlefs.h"
#include "storage.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_log.h"
#include <string.h> // <-- toegevoegd voor memcpy()

static const char *TAG = "storage";

#define CALIBRATION_FILE "/littlefs/calibration.bin"
#define NVS_NAMESPACE "storage"
#define NVS_KEY_BATDATA "batdata"
#define NVS_KEY_CALIB "calibration"

void init_littlefs() {
ESP_LOGI(TAG, "Initializing LittleFS");

esp_vfs_littlefs_conf_t conf = {
.base_path = "/littlefs",
.partition_label = "littlefs", // moet overeenkomen met je partitions.csv
.partition = NULL,
.format_if_mount_failed = true,
.read_only = false,
.dont_mount = false,
.grow_on_mount = true
};
// Centrale instantie van batData
static struct batData bat;

ESP_ERROR_CHECK(esp_vfs_littlefs_register(&conf));
// -----------------------------------------------------------------------------
// Initialisatie
// -----------------------------------------------------------------------------

size_t total = 0, used = 0;
esp_err_t 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);
void storageInit(void)
{
// NVS init
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
nvs_flash_erase();
nvs_flash_init();
}

struct stat st;
if(stat(CALIBRATION_FILE, &st) == 0) {
FILE *fp = fopen(CALIBRATION_FILE, "r");
if(fp == NULL) {
ESP_LOGE(TAG, "Failed to open calibration file for reading");
} else {
uint8_t data[10];
size_t read = fread(data, 1, sizeof(data), fp);
fclose(fp);
ESP_LOGI(TAG, "Calibration file found. Size: %lu, content:", st.st_size);
ESP_LOG_BUFFER_HEX(TAG, data, read);
}
}
}

bool calibrationFileExists() {
return fileExists(CALIBRATION_FILE);
}
// Defaults voor batData
bat.trip1 = 0;
bat.trip2 = 0;
bat.total = 0;

bool readCalibrationData(uint8_t * target) {
return readData(CALIBRATION_FILE, target, 10);
bat.percentage = 0;
bat.mv = 0;
bat.mah = 0;

ESP_LOGI(TAG, "Storage initialized");
}

bool writeCalibrationData(uint8_t * source){
return writeData(CALIBRATION_FILE, source, 10);
// -----------------------------------------------------------------------------
// batData API
// -----------------------------------------------------------------------------

struct batData *batDataGet(void)
{
return &bat;
}

bool fileExists(const char * path) {
struct stat st;
return stat(path, &st) == 0;
bool batDataLoad(void)
{
nvs_handle_t handle;
if (nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle) != ESP_OK)
return false;

size_t size = sizeof(bat);
esp_err_t err = nvs_get_blob(handle, NVS_KEY_BATDATA, &bat, &size);
nvs_close(handle);

return (err == ESP_OK);
}

bool readData(const char * path, void * target, size_t size) {
FILE *fp = fopen(path, "r");
if(fp == NULL) {
ESP_LOGE(TAG, "Failed to open file %s for reading", path);
bool batDataSave(void)
{
nvs_handle_t handle;
if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle) != ESP_OK)
return false;

esp_err_t err = nvs_set_blob(handle, NVS_KEY_BATDATA, &bat, sizeof(bat));
if (err != ESP_OK) {
nvs_close(handle);
return false;
}
fread(target, 1, size, fp);
fclose(fp);

return true;
err = nvs_commit(handle);
nvs_close(handle);

return (err == ESP_OK);
}

// -----------------------------------------------------------------------------
// Calibration API
// -----------------------------------------------------------------------------

uint8_t *calibrationLoad(void)
{
static uint8_t payload[11];

// Byte 0 is altijd 0x00
payload[0] = 0x00;

// Fallback calibratie (10 bytes)
static const uint8_t fallback[10] = {
0x94, 0x38, 0x4b, 0x15, 0x28, 0x3a, 0x3e, 0x91, 0x79, 0x50
};

// Probeer calibratie uit NVS te lezen
nvs_handle_t handle;
esp_err_t err = nvs_open(NVS_NAMESPACE, NVS_READONLY, &handle);

if (err == ESP_OK) {
size_t size = 10;
err = nvs_get_blob(handle, NVS_KEY_CALIB, payload + 1, &size);
nvs_close(handle);

if (err == ESP_OK) {
return payload; // Succesvol geladen
}
}

// Geen calibratie ? fallback
memcpy(payload + 1, fallback, 10);
return payload;
}

bool writeData(const char * path, void * source, size_t size) {
FILE *fp = fopen(path, "w");
if(fp == NULL) {
ESP_LOGE(TAG, "Failed to open file %s for writing", path);
bool calibrationSave(uint8_t *source)
{
nvs_handle_t handle;
if (nvs_open(NVS_NAMESPACE, NVS_READWRITE, &handle) != ESP_OK)
return false;

esp_err_t err = nvs_set_blob(handle, NVS_KEY_CALIB, source, 10);
if (err != ESP_OK) {
nvs_close(handle);
return false;
}
fwrite(source, 1, size, fp);
fclose(fp);

return true;
}
err = nvs_commit(handle);
nvs_close(handle);

return (err == ESP_OK);
}
31 changes: 19 additions & 12 deletions main/storage.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>

#include <sys/unistd.h>
struct batData {
uint32_t trip1;
uint32_t trip2;
uint32_t total;

void init_littlefs();
uint8_t percentage;
uint32_t mv;
uint32_t mah;
};

// Is a calibration file stored?
bool calibrationFileExists();
// Init NVS + defaults
void storageInit(void);

// Reads calibration data to the given buffer, data is 10 bytes long
bool readCalibrationData(uint8_t * target);
// batData API
struct batData *batDataGet(void);
bool batDataLoad(void);
bool batDataSave(void);

// Writes calibration data from the given buffer, data is 10 bytes long
bool writeCalibrationData(uint8_t * source);

bool fileExists(const char * path);
bool readData(const char * path, void * target, size_t size);
bool writeData(const char * path, void * source, size_t size);
// calibration API
uint8_t *calibrationLoad(void);
bool calibrationSave(uint8_t *source);
Loading
Loading