various implementations to increase measurement precision and lorawan performance
This commit is contained in:
parent
7be7ef0081
commit
71c0386229
95
setup_framework.sh
Normal file
95
setup_framework.sh
Normal file
@ -0,0 +1,95 @@
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
# Script to setup framework modifications for STM32WL LoRaWAN project
|
||||
# Usage: ./setup_framework.sh
|
||||
|
||||
set -e
|
||||
|
||||
echo "Setting up framework modifications for STM32WL LoRaWAN build..."
|
||||
|
||||
# Find PlatformIO packages directory
|
||||
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
|
||||
# Windows
|
||||
PIO_PACKAGES="$HOME/.platformio/packages"
|
||||
else
|
||||
# Linux/macOS
|
||||
PIO_PACKAGES="$HOME/.platformio/packages"
|
||||
fi
|
||||
|
||||
FRAMEWORK_ZEPHYR="$PIO_PACKAGES/framework-zephyr"
|
||||
LORAMAC_NODE="$FRAMEWORK_ZEPHYR/_pio/modules/lib/loramac-node"
|
||||
|
||||
echo "PlatformIO packages: $PIO_PACKAGES"
|
||||
echo "Framework Zephyr: $FRAMEWORK_ZEPHYR"
|
||||
|
||||
# Check if framework exists
|
||||
if [ ! -d "$FRAMEWORK_ZEPHYR" ]; then
|
||||
echo "Error: Zephyr framework not found at $FRAMEWORK_ZEPHYR"
|
||||
echo "Please run 'pio run' first to download the framework"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$LORAMAC_NODE" ]; then
|
||||
echo "Error: LoRaMAC-Node not found at $LORAMAC_NODE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✓ Framework directories found"
|
||||
|
||||
# 1. Remove conflicting sx126x.c from LoRaMAC-Node
|
||||
CONFLICTING_FILE="$LORAMAC_NODE/src/radio/sx126x/sx126x.c"
|
||||
if [ -f "$CONFLICTING_FILE" ]; then
|
||||
echo "Removing conflicting sx126x.c..."
|
||||
rm "$CONFLICTING_FILE"
|
||||
echo "✓ Removed $CONFLICTING_FILE"
|
||||
else
|
||||
echo "✓ sx126x.c already removed"
|
||||
fi
|
||||
|
||||
# 2. Create radio_sx126x.c from original sx126x.c
|
||||
RADIO_SX126X="$LORAMAC_NODE/src/radio/sx126x/radio_sx126x.c"
|
||||
if [ ! -f "$RADIO_SX126X" ]; then
|
||||
echo "Creating radio_sx126x.c from git repository..."
|
||||
cd "$LORAMAC_NODE"
|
||||
git show HEAD:src/radio/sx126x/sx126x.c > src/radio/sx126x/radio_sx126x.c
|
||||
echo "✓ Created radio_sx126x.c"
|
||||
else
|
||||
echo "✓ radio_sx126x.c already exists"
|
||||
fi
|
||||
|
||||
# 3. Update CMakeLists.txt
|
||||
CMAKE_FILE="$FRAMEWORK_ZEPHYR/modules/loramac-node/CMakeLists.txt"
|
||||
echo "Updating CMakeLists.txt..."
|
||||
|
||||
# Create backup
|
||||
cp "$CMAKE_FILE" "$CMAKE_FILE.backup"
|
||||
|
||||
# Replace the CONFIG_HAS_SEMTECH_SX126X section
|
||||
sed -i '/zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_SX126X/,/^)/{
|
||||
/zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_SX126X/!{
|
||||
/^)/!d
|
||||
}
|
||||
}' "$CMAKE_FILE"
|
||||
|
||||
# Insert the new configuration
|
||||
sed -i '/zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_SX126X/a\
|
||||
${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/radio/sx126x/radio.c\
|
||||
${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/radio/sx126x/radio_sx126x.c' "$CMAKE_FILE"
|
||||
|
||||
echo "✓ Updated $CMAKE_FILE"
|
||||
|
||||
echo ""
|
||||
echo "🎉 Framework setup complete!"
|
||||
echo ""
|
||||
echo "Summary of changes:"
|
||||
echo " - Removed: $CONFLICTING_FILE"
|
||||
echo " - Created: $RADIO_SX126X"
|
||||
echo " - Updated: $CMAKE_FILE"
|
||||
echo ""
|
||||
echo "You can now run 'pio run' to build the project."
|
||||
echo ""
|
||||
echo "To restore original framework:"
|
||||
echo " git restore $CONFLICTING_FILE"
|
||||
echo " rm $RADIO_SX126X"
|
||||
echo " mv $CMAKE_FILE.backup $CMAKE_FILE"
|
||||
@ -185,6 +185,29 @@ void init_lorawan()
|
||||
LOG_INF("LoraWan started successfully");
|
||||
}
|
||||
|
||||
/* Apply LoRaWAN performance optimizations */
|
||||
LOG_INF("Applying LoRaWAN performance optimizations...");
|
||||
|
||||
/* Enable ADR for automatic datarate optimization */
|
||||
lorawan_enable_adr(true);
|
||||
LOG_INF("✓ ADR (Adaptive Data Rate) enabled");
|
||||
|
||||
/* Set to SF12 (DR0) for maximum range - good for 5-10min intervals */
|
||||
int ret = lorawan_set_datarate(LORAWAN_DR_0);
|
||||
if (ret == 0) {
|
||||
LOG_INF("✓ Datarate set to DR0 (SF12) for maximum range");
|
||||
} else {
|
||||
LOG_WRN("Could not set datarate (ADR may override): %d", ret);
|
||||
}
|
||||
|
||||
/* Increase confirmation retries for better reliability */
|
||||
ret = lorawan_set_conf_msg_tries(8);
|
||||
if (ret == 0) {
|
||||
LOG_INF("✓ Confirmation retries set to 8 for better reliability");
|
||||
} else {
|
||||
LOG_WRN("Could not set confirmation retries: %d", ret);
|
||||
}
|
||||
|
||||
/* Print all LoRaWAN configuration for debugging */
|
||||
print_lorawan_ids();
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
0x0F, 0x0F}
|
||||
|
||||
#define RETRY_DELAY K_MSEC(1000)
|
||||
#define SEND_INTERVALL K_MINUTES(5)
|
||||
#define SEND_INTERVALL K_MINUTES(10)
|
||||
|
||||
void init_lorawan();
|
||||
|
||||
|
||||
25
src/main.c
25
src/main.c
@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(g2h_heat_main);
|
||||
volatile bool relais_state = false;
|
||||
volatile bool relais_manual_override = false;
|
||||
volatile uint8_t temperature_threshold = 21;
|
||||
volatile uint8_t floor_temp_threshold = 22;
|
||||
volatile uint8_t floor_temp_threshold = 24;
|
||||
|
||||
/* MAIN */
|
||||
int main(void)
|
||||
@ -37,29 +37,32 @@ int main(void)
|
||||
|
||||
while (true)
|
||||
{
|
||||
/* Get values from SHT4X */
|
||||
request_sensor_data_sht4x();
|
||||
humidity = get_value_from_current_sample_sht4x(SENSOR_CHAN_HUMIDITY);
|
||||
temp = get_value_from_current_sample_sht4x(SENSOR_CHAN_AMBIENT_TEMP);
|
||||
/* Get stable values from sensors */
|
||||
humidity = get_stable_value_sht4x(SENSOR_CHAN_HUMIDITY);
|
||||
temp = get_stable_value_sht4x(SENSOR_CHAN_AMBIENT_TEMP);
|
||||
printk("hum: %d.%02d%%\n", (int)humidity, (int)(humidity * 100) % 100);
|
||||
printk("temp: %d.%02d °C\n", (int)temp, (int)(temp * 100) % 100);
|
||||
request_sensor_data_mlx90614(MLX90614_IR_TEMP_ADDR);
|
||||
floor_temp = get_temp_from_raw_data_mlx90614();
|
||||
floor_temp = get_stable_value_mlx90614(MLX90614_IR_TEMP_ADDR);
|
||||
printk("floor_temp: %d.%02d °C\n", (int)floor_temp, (int)(floor_temp * 100) % 100);
|
||||
|
||||
/* Set relais based on temperature if not manually overridden */
|
||||
if (!relais_manual_override) {
|
||||
if (!relais_manual_override)
|
||||
{
|
||||
bool temp_condition = temp < temperature_threshold;
|
||||
bool floor_condition = true; // Default: ignore floor temp if sensor not available
|
||||
|
||||
// Only check floor temperature if MLX sensor is working
|
||||
if (mlx90614_sensor_available) {
|
||||
if (mlx90614_sensor_available)
|
||||
{
|
||||
floor_condition = floor_temp < floor_temp_threshold;
|
||||
}
|
||||
|
||||
if (temp_condition && floor_condition) {
|
||||
if (temp_condition && floor_condition)
|
||||
{
|
||||
relais_state = 1; // Heat on below thresholds
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
relais_state = 0; // Heat off if any threshold exceeded
|
||||
}
|
||||
set_relais_state(relais_state);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include <sensors/mlx90614.h>
|
||||
#include <sensors/sensor_utils.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
@ -52,3 +53,42 @@ float get_temp_from_raw_data_mlx90614()
|
||||
int16_t temperature = (read_data_buffer[1] << 8) | read_data_buffer[0]; // Temperaturwert aus den empfangenen Daten
|
||||
return temperature * 0.02 - 273.15; // Umrechnung in Celsius
|
||||
}
|
||||
|
||||
static float read_mlx_ambient_temp(void)
|
||||
{
|
||||
// Schnell-Check: wenn bereits bekannt dass Sensor nicht verfügbar ist
|
||||
if (!mlx90614_sensor_available) return 0.0;
|
||||
|
||||
request_sensor_data_mlx90614(MLX90614_INTERNAL_TEMP_ADDR);
|
||||
if (!mlx90614_sensor_available) return 0.0;
|
||||
return get_temp_from_raw_data_mlx90614();
|
||||
}
|
||||
|
||||
static float read_mlx_object_temp(void)
|
||||
{
|
||||
// Schnell-Check: wenn bereits bekannt dass Sensor nicht verfügbar ist
|
||||
if (!mlx90614_sensor_available) return 0.0;
|
||||
|
||||
request_sensor_data_mlx90614(MLX90614_IR_TEMP_ADDR);
|
||||
if (!mlx90614_sensor_available) return 0.0;
|
||||
return get_temp_from_raw_data_mlx90614();
|
||||
}
|
||||
|
||||
float get_stable_value_mlx90614(uint8_t target_addr)
|
||||
{
|
||||
// Früher Ausstieg wenn Sensor nicht verfügbar
|
||||
if (!mlx90614_sensor_available) {
|
||||
LOG_DBG("MLX90614 not available, returning 0.0");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
const float TEMP_THRESHOLD = 2.0; // °C
|
||||
|
||||
if (target_addr == MLX90614_INTERNAL_TEMP_ADDR) {
|
||||
return get_stable_sensor_value(read_mlx_ambient_temp, TEMP_THRESHOLD);
|
||||
} else if (target_addr == MLX90614_IR_TEMP_ADDR) {
|
||||
return get_stable_sensor_value(read_mlx_object_temp, TEMP_THRESHOLD);
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
@ -12,3 +12,5 @@ int init_mlx90614();
|
||||
void request_sensor_data_mlx90614(uint8_t target_addr);
|
||||
|
||||
float get_temp_from_raw_data_mlx90614();
|
||||
|
||||
float get_stable_value_mlx90614(uint8_t target_addr);
|
||||
80
src/sensors/sensor_utils.c
Normal file
80
src/sensors/sensor_utils.c
Normal file
@ -0,0 +1,80 @@
|
||||
#include "sensor_utils.h"
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <math.h>
|
||||
|
||||
LOG_MODULE_REGISTER(sensor_utils);
|
||||
|
||||
float get_stable_sensor_value(sensor_read_func_t read_func, float outlier_threshold)
|
||||
{
|
||||
const int MAX_SAMPLES = 5;
|
||||
float measurements[MAX_SAMPLES];
|
||||
int valid_count = 0;
|
||||
|
||||
// Sammle bis zu 5 Messungen
|
||||
for (int i = 0; i < MAX_SAMPLES && valid_count < 3; i++) {
|
||||
if (i > 0) {
|
||||
k_sleep(K_MSEC(500)); // Pause gegen Selbsterhitzung
|
||||
}
|
||||
|
||||
float value = read_func();
|
||||
|
||||
if (value != 0.0) {
|
||||
measurements[valid_count] = value;
|
||||
valid_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_count == 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Bei nur 1-2 Messungen, einfach mitteln
|
||||
if (valid_count <= 2) {
|
||||
float sum = 0;
|
||||
for (int i = 0; i < valid_count; i++) {
|
||||
sum += measurements[i];
|
||||
}
|
||||
return sum / valid_count;
|
||||
}
|
||||
|
||||
// Ausreißer entfernen: Median-basierte Filterung
|
||||
// Sortiere die Messungen
|
||||
for (int i = 0; i < valid_count - 1; i++) {
|
||||
for (int j = i + 1; j < valid_count; j++) {
|
||||
if (measurements[i] > measurements[j]) {
|
||||
float temp = measurements[i];
|
||||
measurements[i] = measurements[j];
|
||||
measurements[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Median berechnen
|
||||
float median = measurements[valid_count / 2];
|
||||
|
||||
// Werte filtern die zu weit vom Median entfernt sind
|
||||
float sum = 0;
|
||||
int filtered_count = 0;
|
||||
|
||||
for (int i = 0; i < valid_count; i++) {
|
||||
if (fabs(measurements[i] - median) <= outlier_threshold) {
|
||||
sum += measurements[i];
|
||||
filtered_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtered_count > 0) {
|
||||
float result = sum / filtered_count;
|
||||
LOG_INF("Stable sensor value: %.2f (filtered %d/%d samples)",
|
||||
result, filtered_count, valid_count);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Fallback: einfacher Mittelwert wenn alle gefiltert wurden
|
||||
float fallback = 0;
|
||||
for (int i = 0; i < valid_count; i++) {
|
||||
fallback += measurements[i];
|
||||
}
|
||||
return fallback / valid_count;
|
||||
}
|
||||
8
src/sensors/sensor_utils.h
Normal file
8
src/sensors/sensor_utils.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef SENSOR_UTILS_H
|
||||
#define SENSOR_UTILS_H
|
||||
|
||||
typedef float (*sensor_read_func_t)(void);
|
||||
|
||||
float get_stable_sensor_value(sensor_read_func_t read_func, float outlier_threshold);
|
||||
|
||||
#endif
|
||||
@ -1,4 +1,5 @@
|
||||
#include <sensors/sht4x.h>
|
||||
#include <sensors/sensor_utils.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
@ -57,3 +58,30 @@ float get_value_from_current_sample_sht4x(enum sensor_channel sensor)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static float read_sht4x_temp(void)
|
||||
{
|
||||
request_sensor_data_sht4x();
|
||||
return get_value_from_current_sample_sht4x(SENSOR_CHAN_AMBIENT_TEMP);
|
||||
}
|
||||
|
||||
static float read_sht4x_humidity(void)
|
||||
{
|
||||
request_sensor_data_sht4x();
|
||||
return get_value_from_current_sample_sht4x(SENSOR_CHAN_HUMIDITY);
|
||||
}
|
||||
|
||||
float get_stable_value_sht4x(enum sensor_channel sensor)
|
||||
{
|
||||
const float TEMP_THRESHOLD = 2.0; // °C
|
||||
const float HUMIDITY_THRESHOLD = 2.0; // %RH
|
||||
|
||||
if (sensor == SENSOR_CHAN_AMBIENT_TEMP) {
|
||||
return get_stable_sensor_value(read_sht4x_temp, TEMP_THRESHOLD);
|
||||
} else if (sensor == SENSOR_CHAN_HUMIDITY) {
|
||||
return get_stable_sensor_value(read_sht4x_humidity, HUMIDITY_THRESHOLD);
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
@ -7,3 +7,5 @@ void init_sht4x();
|
||||
void request_sensor_data_sht4x();
|
||||
|
||||
float get_value_from_current_sample_sht4x(enum sensor_channel sensor);
|
||||
|
||||
float get_stable_value_sht4x(enum sensor_channel sensor);
|
||||
Loading…
Reference in New Issue
Block a user