Compare commits

..

No commits in common. "55fbfaf1d5e3f945ca6a2c55375618694c1cb73e" and "607a089510d1b1ddf11e07429b3b7af66b220dd2" have entirely different histories.

15 changed files with 121 additions and 269 deletions

10
.vscode/settings.json vendored
View File

@ -7,12 +7,6 @@
"log.h": "c",
"mlx90614.h": "c",
"sensor.h": "c",
"sht4x.h": "c",
"array": "c",
"string_view": "c",
"initializer_list": "c",
"stm32-pinctrl-common.h": "c",
"printk.h": "c"
},
"cmake.sourceDirectory": "C:/Users/xlemmingx/Documents/PlatformIO/Projects/embedded_raumsenor_lorawan/zephyr"
"sht4x.h": "c"
}
}

View File

@ -1,50 +0,0 @@
#include <gpio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(gpio_relais);
#if !DT_NODE_EXISTS(DT_NODELABEL(load_switch))
#error "Overlay for power output node not properly defined."
#endif
static const struct gpio_dt_spec load_switch =
GPIO_DT_SPEC_GET_OR(DT_NODELABEL(load_switch), gpios, {0});
void init_gpio()
{
int err;
if (!gpio_is_ready_dt(&load_switch))
{
LOG_ERR("The load switch pin GPIO port is not ready.\n");
return 0;
}
LOG_INF("Initializing pin with inactive level.\n");
err = gpio_pin_configure_dt(&load_switch, GPIO_OUTPUT_INACTIVE);
if (err != 0)
{
LOG_ERR("Configuring GPIO pin failed: %d\n", err);
return 0;
}
/* Make sure relais is switched off */
set_relais_state(false);
}
void set_relais_state(bool state)
{
int err = gpio_pin_set_dt(&load_switch, state);
if (err != 0)
{
LOG_ERR("Setting GPIO pin level failed: %d\n", err);
}
}
uint8_t get_relais_state()
{
return (uint8_t)gpio_pin_get_dt(&load_switch);
}

View File

@ -1,7 +0,0 @@
#include <zephyr/kernel.h>
void init_gpio();
void set_relais_state(bool state);
uint8_t get_relais_state();

View File

@ -1,81 +1,52 @@
#include <zephyr/kernel.h>
#include <zephyr/lorawan/lorawan.h>
#include <zephyr/logging/log.h>
#include <zephyr/settings/settings.h>
#include <zephyr/random/random.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <lora/lorawan.h>
#include <gpio.h>
#define SETTINGS_KEY "LORAWAN_DEV_NONCE"
/*
TODO:
- DEV NONCE in non volatile memory and increase
- format packets
- send: check if still in network
- downlink callback
LOG_MODULE_REGISTER(lorawan_class_a);
extern bool relais_state;
const static struct device *lora_dev;
static struct lorawan_join_config join_cfg;
static uint8_t dev_eui[8];
static uint8_t app_key[] = LORAWAN_APP_KEY;
static uint8_t join_eui[] = LORAWAN_APP_EUI;
// Build payload byte array
uint8_t uplinkPayload[6];
uplinkPayload[0] = uint8_t (int(temp_room_mlx));
uplinkPayload[1] = uint8_t (int((temp_room_mlx-int(temp_room_mlx)*100))); // See notes for high/lowByte functions
uplinkPayload[2] = uint8_t (int(temp_floor));
uplinkPayload[3] = uint8_t (int((temp_floor-int(temp_floor)*100))); // See notes for high/lowByte functions
uplinkPayload[4] = uint8_t (int(humidity));
uplinkPayload[5] = uint8_t (relaisstate); // See notes for high/lowByte functions
*/
static void dl_callback(uint8_t port, uint8_t flags, int16_t rssi, int8_t snr, uint8_t len,
const uint8_t *hex_data)
{
LOG_INF("Port %d, Pending %d, RSSI %ddB, SNR %ddBm, Len: %d, Time %d", port,
flags & LORAWAN_DATA_PENDING, rssi, snr, len, !!(flags & LORAWAN_TIME_UPDATED));
if (hex_data)
{
LOG_HEXDUMP_INF(hex_data, len, "Payload: ");
}
const struct device *lora_dev;
struct lorawan_join_config join_cfg;
uint8_t dev_eui[] = LORAWAN_DEV_EUI;
uint8_t join_eui[] = LORAWAN_JOIN_EUI;
uint8_t app_key[] = LORAWAN_APP_KEY;
/* Could be moved in a separate thread so we only have to set the variable here */
if (len > 3 && hex_data[0] == 'r' && hex_data[1] == '1')
{
uint8_t relais_value = hex_data[3];
LOG_INF("Received relais1 state change: %d", relais_value);
if (get_relais_state() != relais_value)
{
set_relais_state(relais_value);
LOG_INF("Set relais 1 value");
}
relais_state = relais_value;
}
}
void init_lorawan() {
int ret;
struct lorawan_downlink_cb downlink_cb = {
.port = LW_RECV_PORT_ANY,
.cb = dl_callback};
void init_lorawan()
{
/* set dev eui from MCU-ID (UID) of STM32WL */
uint32_t uid_l = HAL_GetUIDw0();
uint32_t uid_h = HAL_GetUIDw1();
dev_eui[0] = (uid_h >> 24) & 0xFF;
dev_eui[1] = (uid_h >> 16) & 0xFF;
dev_eui[2] = (uid_h >> 8) & 0xFF;
dev_eui[3] = (uid_h) & 0xFF;
dev_eui[4] = (uid_l >> 24) & 0xFF;
dev_eui[5] = (uid_l >> 16) & 0xFF;
dev_eui[6] = (uid_l >> 8) & 0xFF;
dev_eui[7] = (uid_l) & 0xFF;
int err;
lora_dev = DEVICE_DT_GET(DT_ALIAS(lora0));
if (!device_is_ready(lora_dev))
{
LOG_ERR("%s: device not ready.", lora_dev->name);
return;
return 0;
}
err = lorawan_start();
if (err < 0)
ret = lorawan_start();
if (ret < 0)
{
LOG_ERR("lorawan_start failed: %d", err);
return;
LOG_ERR("lorawan_start failed: %d", ret);
return 0;
}
else
{
@ -83,65 +54,70 @@ void init_lorawan()
}
lorawan_register_downlink_callback(&downlink_cb);
lorawan_register_dr_changed_callback(lorwan_datarate_changed);
join_cfg.mode = LORAWAN_ACT_OTAA;
join_cfg.dev_eui = dev_eui;
join_cfg.otaa.join_eui = join_eui;
join_cfg.otaa.app_key = app_key;
join_cfg.otaa.nwk_key = app_key;
join_cfg.otaa.dev_nonce = 14u; // TODO
}
void join_network_otaa()
{
int8_t ret = -1;
while (lorawan_join(&join_cfg) < 0)
{
void join_network_otaa() {
int8_t status = -1;
while (lorawan_join(&join_cfg) < 0) {
LOG_ERR("lorawan_join_network failed: %d, retrying..", ret);
k_sleep(K_MSEC(5000));
}
LOG_INF("Succesfully joined network over OTAA");
LOG_INF("Joining network over OTAA");
}
void send_data_packet(char *data, uint8_t data_len)
{
void send_data_packet(char *data) {
LOG_INF("Sending data...");
while (1)
{
int8_t ret = lorawan_send(LORAWAN_PORT, (uint8_t *)data, data_len, LORAWAN_MSG_UNCONFIRMED);
int8_t ret = lorawan_send(LORAWAN_PORT, data, sizeof(data), LORAWAN_MSG_CONFIRMED);
if (ret == -EAGAIN)
{
LOG_ERR("lorawan_send failed: %d. Continuing...", ret);
k_sleep(RETRY_DELAY);
k_sleep(DELAY);
continue;
}
else if (ret < 0)
if (ret < 0)
{
LOG_ERR("lorawan_send failed: %d", ret);
k_sleep(RETRY_DELAY);
break;
k_sleep(DELAY);
continue;
}
else
{
LOG_INF("Data sent!");
break;
}
k_sleep(RETRY_DELAY);
k_sleep(DELAY);
}
}
void create_data_package(char *buffer, float temp_room_mlx, float temp_floor, float humidity, uint8_t relais_state)
static void dl_callback(uint8_t port, uint8_t flags, int16_t rssi, int8_t snr, uint8_t len,
const uint8_t *hex_data)
{
int16_t temp = (int16_t)(temp_room_mlx * 100);
int16_t floor_temp = (int16_t)(temp_floor * 100);
int16_t hum = (int16_t)(humidity * 100);
// Packen der Daten in das Byte-Array
buffer[0] = (temp >> 8) & 0xFF;
buffer[1] = temp & 0xFF;
buffer[2] = (floor_temp >> 8) & 0xFF;
buffer[3] = floor_temp & 0xFF;
buffer[4] = (hum >> 8) & 0xFF;
buffer[5] = hum & 0xFF;
buffer[6] = relais_state;
LOG_INF("Port %d, Pending %d, RSSI %ddB, SNR %ddBm, Time %d", port,
flags & LORAWAN_DATA_PENDING, rssi, snr, !!(flags & LORAWAN_TIME_UPDATED));
if (hex_data)
{
LOG_HEXDUMP_INF(hex_data, len, "Payload: ");
}
}
static void lorwan_datarate_changed(enum lorawan_datarate dr)
{
uint8_t unused, max_size;
lorawan_get_payload_sizes(&unused, &max_size);
LOG_INF("New Datarate: DR_%d, Max Payload %d", dr, max_size);
}

View File

@ -1,22 +1,23 @@
#include <zephyr/kernel.h>
#include <zephyr/lorawan/lorawan.h>
#define LORAWAN_PORT 2
/* Customize based on network configuration */
#define LORAWAN_DEV_EUI { 0x2D, 0xBF, 0xF6, 0xC2, 0xA1, 0x20,\
0x01, 0x4A }
#define LORAWAN_JOIN_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
0x00, 0x00 }
/* #define LORAWAN_APP_KEY { 0x71, 0x5A, 0x39, 0xB2, 0x86, 0xC3,\
0x37, 0xA3, 0xC4, 0xF0, 0x78, 0xF9,\
0x0F, 0x33, 0x07, 0x7D } */
#define LORAWAN_APP_KEY { 0x71, 0x5A, 0x39, 0xB2, 0x86, 0xC3,\
0x37, 0xA3, 0xC4, 0xF0, 0x78, 0xF9,\
0x0F, 0x33, 0x07, 0x7D }
#define LORAWAN_APP_EUI {0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, \
0x0F, 0x0F}
#define RETRY_DELAY K_MSEC(1000)
#define SEND_INTERVALL K_MINUTES(5)
void init_lorawan();
static void dl_callback(uint8_t port, uint8_t flags, int16_t rssi, int8_t snr, uint8_t len,
const uint8_t *hex_data);
void join_network_otaa();
void send_data_packet(char *data, uint8_t data_len);
void create_data_package(char *package, float temp_room_mlx, float temp_floor, float humidity, uint8_t relais_state);
static void lorwan_datarate_changed(enum lorawan_datarate dr);

View File

@ -2,54 +2,28 @@
#include <zephyr/logging/log.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/printk.h>
#include <zephyr/lorawan/lorawan.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor/sht4x.h>
#include <zephyr/drivers/gpio.h>
#include <lora/lorawan.h>
#include <sensors/mlx90614.h>
#include <sensors/sht4x.h>
#include <gpio.h>
LOG_MODULE_REGISTER(g2h_heat_main);
volatile bool relais_state = false;
#define DELAY K_MSEC(10000)
#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
LOG_MODULE_REGISTER(lorawan_class_a);
/* MAIN */
int main(void)
{
/* Initialization */
init_gpio();
init_mlx90614();
init_sht4x();
init_lorawan();
join_network_otaa();
float humidity, temp, floor_temp;
while (true)
{
/* Get values from SHT4X */
request_sensor_data_sht4x();
humidity = get_value_from_current_sample_sht4x(SENSOR_CHAN_HUMIDITY);
printk("hum: %.2f%%\n", humidity);
/* Get values from MLX90614 */
request_sensor_data_mlx90614(MLX90614_INTERNAL_TEMP_ADDR);
temp = get_temp_from_raw_data_mlx90614();
printk("temp: %.2f °C\n", temp);
request_sensor_data_mlx90614(MLX90614_IR_TEMP_ADDR);
floor_temp = get_temp_from_raw_data_mlx90614();
printk("floor_temp: %.2f °C\n", floor_temp);
/* Pack and send values */
char data[7];
create_data_package(data, temp, floor_temp, humidity, relais_state);
LOG_HEXDUMP_DBG(data, 7, "data");
send_data_packet(data, 7);
/* Delay until next cycle */
k_sleep(SEND_INTERVALL);
}
}

View File

@ -3,16 +3,13 @@
#include <zephyr/kernel.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mlx90614);
static struct device *i2c_dev;
static uint16_t i2c_addr = 0x00;
static const struct device *i2c_dev;
static const uint16_t i2c_addr = 0x5A;
static uint8_t read_data_buffer[3];
int init_mlx90614() {
void init_mlx90614() {
i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c1));
i2c_addr = DT_PROP(DT_NODELABEL(mlx90614), reg);
if (!i2c_dev) {
LOG_ERR("I2C device not found!");
@ -20,27 +17,27 @@ int init_mlx90614() {
} else {
LOG_INF("I2C device initialized.");
}
if (i2c_addr == 0x00) {
LOG_ERR("MLX90614 I2C address fetch from device tree failed!");
} else {
LOG_INF("MLX90614 I2C address found.");
}
}
void request_sensor_data_mlx90614(uint8_t target_addr) {
uint8_t err;
for (int i = 0; i < MLX90614_RETRY_COUNT; i++)
{
err = i2c_write_read(i2c_dev, 0x5A, &target_addr, sizeof(target_addr), &read_data_buffer, sizeof(read_data_buffer));
if (err == 0)
{
void request_sensor_data_mlx90614(uint16_t target_addr, const uint8_t *read_data) {
for (int i = 0; i < MLX90614_RETRY_COUNT; i++) {
if (i2c_write_read(i2c_dev, i2c_addr, &target_addr, sizeof(target_addr), &read_data, sizeof(read_data) == 0)) {
LOG_INF("MLX90614 sensor values successfully read after %d tries", i+1);
return;
}
else
{
} else {
k_sleep(K_MSEC(100));
}
}
LOG_ERR("MLX90614 reading sensor values failed %d times with error %d!", MLX90614_RETRY_COUNT, err);
LOG_ERR("MLX90614 reading sensor values failed %d times!", MLX90614_RETRY_COUNT);
}
float get_temp_from_raw_data_mlx90614() {
int16_t temperature = (read_data_buffer[1] << 8) | read_data_buffer[0]; // Temperaturwert aus den empfangenen Daten
float get_temp_from_raw_data_mlx90614(const uint8_t *read_data) {
int16_t temperature = (read_data[1] << 8) | read_data[0]; // Temperaturwert aus den empfangenen Daten
return temperature * 0.02 - 273.15; // Umrechnung in Celsius
}

View File

@ -6,6 +6,6 @@
int init_mlx90614();
void request_sensor_data_mlx90614(uint8_t target_addr);
int request_sensor_data_mlx90614(uint16_t target_addr, const uint8_t *read_data);
float get_temp_from_raw_data_mlx90614();
float get_temp_from_raw_data_mlx90614(const uint8_t *read_data);

View File

@ -5,9 +5,7 @@
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/sensor/sht4x.h>
LOG_MODULE_REGISTER(sht4x);
static const struct device *sht;
static struct device *sht;
void init_sht4x()
{
@ -48,10 +46,10 @@ float get_value_from_current_sample_sht4x(enum sensor_channel sensor)
float result;
if (sensor_channel_get(sht, sensor, &value) == 0) {
result = sensor_value_to_double(&value);
printf("Value '%s' successfully read [%f]", sensor, result);
LOG_INF("Value '%s' successfully read [%f]", sensor, result);
} else {
LOG_ERR("Can't read sensor value '%s' from sample!", sensor);
return 0.0;
}
return result;
return value;
}

View File

@ -6,4 +6,4 @@ void init_sht4x();
void request_sensor_data_sht4x();
float get_value_from_current_sample_sht4x(enum sensor_channel sensor);
float get_value_from_raw_data_sht4x(enum sensor_channel sensor);

View File

@ -10,7 +10,6 @@
#include "arduino_r3_connector.dtsi"
#include "st_morpho_connector.dtsi"
#include <zephyr/dt-bindings/input/input-event-codes.h>
//#include "g2h_lorawan_heat_control.dtsi"
/ {
model = "G2H LoraWAN Heat control based on STM32WL55JC-NUCLEO";

View File

@ -1,8 +0,0 @@
#include <zephyr/dt-bindings/pinctrl/stm32-pinctrl.h>
#include <st/wl/stm32wl55jcix-pinctrl.dtsi>
&pinctrl {
gpio_pc0: gpio_pc0 {
pinmux = <STM32_PINMUX(STM32_PORTC, 0, STM32_GPIO)>;
};
};

View File

@ -1,10 +0,0 @@
description: GPIO pin to switch a power output on or off
compatible: "power-switch"
properties:
gpios:
type: phandle-array
required: true
description: |
The GPIO connected to the gate driver for the MOSFET.

View File

@ -1,6 +0,0 @@
/ {
load_switch: load_switch {
compatible = "power-switch";
gpios = <&gpioc 0 GPIO_ACTIVE_HIGH>;
};
};

View File

@ -1,18 +1,12 @@
CONFIG_LOG=y
CONFIG_SENSOR=y
CONFIG_GPIO=y
CONFIG_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_ZMS=y
CONFIG_I2C=y
CONFIG_SHT4X=y
CONFIG_LORA=y
CONFIG_LORAWAN=y
CONFIG_LORAMAC_REGION_EU868=y
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_NEWLIB_LIBC=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
CONFIG_ENTROPY_GENERATOR=y