diff options
| -rw-r--r-- | .vscode/settings.json | 10 | ||||
| -rw-r--r-- | Kconfig | 8 | ||||
| -rw-r--r-- | nrf9160dk_nrf9160_ns.overlay | 16 | ||||
| -rw-r--r-- | prj.conf | 10 | ||||
| -rw-r--r-- | src/main.c | 179 |
5 files changed, 211 insertions, 12 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c9c54ff --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "nrf-connect.topdir": "/home/mh/Documents/skola/bc/mqtt_simple", + "nrf-connect.toolchain.path": "${nrf-connect.toolchain:2.2.0}", + "files.associations": { + "certificates.h": "c", + "w1.h": "c", + "shell.h": "c", + "nrf9160.h": "c" + } +}
\ No newline at end of file @@ -7,14 +7,14 @@ menu "MQTT simple sample" config MQTT_PUB_TOPIC string "MQTT publish topic" - default "my/publish/topic" + default "pub/topic" config MQTT_SUB_TOPIC string "MQTT subscribe topic" - default "my/subscribe/topic" + default "subs/topic" config MQTT_CLIENT_ID - string "MQTT Client ID" + string "nrf" help Use a custom Client ID string. If not set, the client ID will be generated based on IMEI number (for nRF9160 based targets) or @@ -23,7 +23,7 @@ config MQTT_CLIENT_ID config MQTT_BROKER_HOSTNAME string "MQTT broker hostname" - default "test.mosquitto.org" + default "mikehanus.xyz" config MQTT_BROKER_PORT int "MQTT broker port" diff --git a/nrf9160dk_nrf9160_ns.overlay b/nrf9160dk_nrf9160_ns.overlay new file mode 100644 index 0000000..8f6d2f9 --- /dev/null +++ b/nrf9160dk_nrf9160_ns.overlay @@ -0,0 +1,16 @@ +// To get started, press Ctrl+Space to bring up the completion menu and view the available nodes. + +// You can also use the buttons in the sidebar to perform actions on nodes. +// Actions currently available include: + +// * Enabling / disabling the node +// * Adding the bus to a bus +// * Removing the node +// * Connecting ADC channels + +// For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html +// You can also visit the nRF DeviceTree extension documentation at https://nrfconnect.github.io/vscode-nrf-connect/devicetree/nrfdevicetree.html + +&adc { + status = "ok"; +};
\ No newline at end of file @@ -47,3 +47,13 @@ CONFIG_NEWLIB_LIBC=y # Shell support CONFIG_SHELL=y CONFIG_HW_ID_LIBRARY=y + +CONFIG_MQTT_SUB_TOPIC="sub/topic" +#CONFIG_MODEM_ANTENNA_AT_MAGPIO="AT%XMAGPIO=1,0,0,1,1,1574,1577" +#CONFIG_MODEM_ANTENNA_AT_COEX0="AT%XCOEX0=1,1,1565,1586" +#CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=2048 +#CONFIG_LTE_NETWORK_MODE_NBIOT=y +#CONFIG_SENSOR=y +#CONFIG_W1=y +CONFIG_ADC=y +CONFIG_ADC_NRFX_SAADC=y
\ No newline at end of file @@ -25,6 +25,67 @@ #include "certificates.h" +#include <nrf9160.h> +#include <stdio.h> +#include <string.h> +#include <zephyr/drivers/adc.h> + +struct device *adc_dev; +uint8_t sensors_enabled = 0xff; // bit 0 - PIR, bit 1 - HAL, bit 2 - temperature, bit 3 - gas + +#include <hal/nrf_saadc.h> +#define ADC_DEVICE_NAME DT_NODELABEL(adc) +#define ADC_RESOLUTION 10 +#define ADC_GAIN ADC_GAIN_1_2 +#define ADC_REFERENCE ADC_REF_INTERNAL +#define ADC_ACQUISITION_TIME ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10) + +static const struct adc_channel_cfg adc_temp_channel_cfg = { + .gain = ADC_GAIN, + .reference = ADC_REFERENCE, + .acquisition_time = ADC_ACQUISITION_TIME, + .channel_id = 4, +#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS) + .input_positive = 5, +#endif +}; + +static const struct adc_channel_cfg adc_gas_channel_cfg = { + .gain = ADC_GAIN, + .reference = ADC_REFERENCE, + .acquisition_time = ADC_ACQUISITION_TIME, + .channel_id = 5, +#if defined(CONFIG_ADC_CONFIGURABLE_INPUTS) + .input_positive = 6, +#endif +}; + + +static int16_t adc_sample(uint8_t idx) +{ + int ret; + int16_t temp; //mV + + if(idx > 1) return -1; + + const struct adc_sequence sequence = { + .channels = BIT(idx + 4), // choose AIN4 on AIN5 + .buffer = &temp, // only single value, make to pointer to simulate array + .buffer_size = sizeof(temp), + .resolution = ADC_RESOLUTION, + }; + + if (!adc_dev) { + return -1; + } + + ret = adc_read(adc_dev, &sequence); + + temp = (temp * 6) / 5; // simple aproximation of 0-1023 range to 0-1200 mV range + + return temp; +} + LOG_MODULE_REGISTER(mqtt_simple, CONFIG_MQTT_SIMPLE_LOG_LEVEL); /* Buffers for MQTT client. */ @@ -87,16 +148,16 @@ static void data_print(uint8_t *prefix, uint8_t *data, size_t len) LOG_INF("%s%s", (char *)prefix, (char *)buf); } -/**@brief Function to publish data on the configured topic +/**@brief Function to publish data on a topic */ -static int data_publish(struct mqtt_client *c, enum mqtt_qos qos, +static int data_publish(struct mqtt_client *c, enum mqtt_qos qos, const char *topic, uint8_t *data, size_t len) { struct mqtt_publish_param param; param.message.topic.qos = qos; - param.message.topic.topic.utf8 = CONFIG_MQTT_PUB_TOPIC; - param.message.topic.topic.size = strlen(CONFIG_MQTT_PUB_TOPIC); + param.message.topic.topic.utf8 = topic; + param.message.topic.topic.size = strlen(topic); param.message.payload.data = data; param.message.payload.len = len; param.message_id = sys_rand32_get(); @@ -211,8 +272,14 @@ void mqtt_evt_handler(struct mqtt_client *const c, if (err >= 0) { data_print("Received: ", payload_buf, p->message.payload.len); + + // for both way communication demonstration: ox turn on led x, [any other char]x turns off led x + if(p->message.payload.len >= 2 && payload_buf[1] >= '0' && payload_buf[1] <= '3') { + dk_set_led(payload_buf[1] - 48, payload_buf[0] == 'o'); + } + /* Echo back received data */ - data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, + data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, "nrf/echo", payload_buf, p->message.payload.len); } else if (err == -EMSGSIZE) { LOG_ERR("Received payload (%d bytes) is larger than the payload buffer " @@ -434,19 +501,56 @@ static int fds_init(struct mqtt_client *c) #if defined(CONFIG_DK_LIBRARY) static void button_handler(uint32_t button_states, uint32_t has_changed) { + // After inicializtion pressed button and active switch make sensor disabled + if(sensors_enabled == 0xff) { + sensors_enabled = (~button_states) & 0xf; // mask only 4 real buttons + } + if (has_changed & button_states & BIT(CONFIG_BUTTON_EVENT_BTN_NUM - 1)) { int ret; ret = data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, - CONFIG_BUTTON_EVENT_PUBLISH_MSG, - sizeof(CONFIG_BUTTON_EVENT_PUBLISH_MSG)-1); + "nrf/button", + "1 pressed", + 9); + if (ret) { + LOG_ERR("Publish failed: %d", ret); + } + } + + if ((has_changed & BIT(4)) && (sensors_enabled & BIT(0))) { + int ret; + + dk_set_led(0, button_states & BIT(4)); + + ret = data_publish(&client, + MQTT_QOS_1_AT_LEAST_ONCE, + "nrf/pir", + (button_states & BIT(4))? "1":"0", + 1); + if (ret) { + LOG_ERR("Publish failed: %d", ret); + } + } + + if (has_changed & BIT(5) && (sensors_enabled & BIT(1))) { + int ret; + + dk_set_led(1, button_states & BIT(5)); + + ret = data_publish(&client, + MQTT_QOS_1_AT_LEAST_ONCE, + "nrf/magnet", + (has_changed & BIT(5))? "1":"0", + 1); if (ret) { LOG_ERR("Publish failed: %d", ret); } } } + #endif static int shell_mqtt_publish(const struct shell *shell, size_t argc, char **argv) @@ -458,6 +562,7 @@ static int shell_mqtt_publish(const struct shell *shell, size_t argc, char **arg ret = data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, + CONFIG_MQTT_PUB_TOPIC, CONFIG_BUTTON_EVENT_PUBLISH_MSG, sizeof(CONFIG_BUTTON_EVENT_PUBLISH_MSG) - 1); if (ret) { @@ -512,7 +617,10 @@ static int modem_configure(void) void main(void) { int err; - uint32_t connect_attempt = 0; + uint32_t connect_attempt = 0, last_measurement = 0; + + uint16_t adcval = 0; + uint8_t buf[10]; LOG_INF("The MQTT simple sample started"); @@ -541,6 +649,23 @@ void main(void) #if defined(CONFIG_DK_LIBRARY) dk_buttons_init(button_handler); + dk_leds_init(); + + adc_dev = DEVICE_DT_GET(ADC_DEVICE_NAME); + + if (!adc_dev) { + printk("device_get_binding ADC failed\n"); + while(1); + } + err = adc_channel_setup(adc_dev, &adc_temp_channel_cfg); + if (err) { + printk("Error in adc setup: %d\n", err); + } + + err = adc_channel_setup(adc_dev, &adc_gas_channel_cfg); + if (err) { + printk("Error in adc setup: %d\n", err); + } #endif do_connect: @@ -561,6 +686,11 @@ do_connect: return; } + // One second blink with all led to inform abot + dk_set_leds(0b1111); + k_msleep(1000); + dk_set_leds(0b1111); + while (1) { err = poll(&fds, 1, mqtt_keepalive_time_left(&client)); if (err < 0) { @@ -591,6 +721,39 @@ do_connect: LOG_ERR("POLLNVAL"); break; } + + if(last_measurement < (NRF_RTC1->COUNTER) || last_measurement + 1000000 > (NRF_RTC1->COUNTER)) + { + last_measurement = (NRF_RTC1->COUNTER); + if (sensors_enabled & BIT(2)) { //enabled temperature + // Sample AIN4 - LM35 + adcval = adc_sample(0); + printk("Temp: %d mV\n", adcval); + + if(adcval > 280) { // 26 deg C + snprintf(buf, 10, "%d", adcval); + data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, "nrf/temp", buf, strlen(buf)); + dk_set_led(2, 1); + k_msleep(1000); + } + else dk_set_led(2, 0); + } + + if (sensors_enabled & BIT(3)) { // enabled gas + // Sample AIN5 - gas sensor + adcval = adc_sample(1); + printk("Gas: %d mV %d\n", adcval, sensors_enabled); + + if(adcval > 200) { // reliable limit got by testing + snprintf(buf, 10, "%d", adcval); + data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE, "nrf/gas", buf, strlen(buf)); + dk_set_led(3, 1); + k_msleep(1000); + } + else dk_set_led(3, 0); + } + } + } LOG_INF("Disconnecting MQTT client..."); |
