123 Commits

Author SHA1 Message Date
eeeck 626bbe9dbb Remove task handle: managed in dev-twi main.cpp 2025-12-10 00:27:30 +01:00
eeeck 1a893547b6 Finalize event groups to improve performance 2025-12-09 23:50:26 +01:00
eeeck 06a672d1f7 Remove old code about I2C 2025-12-09 23:40:53 +01:00
eeeck b1a6dfddd3 Wait for Wi-Fi connection before initializing MQTT 2025-12-09 23:23:10 +01:00
eeeck 2e6e829829 Only clear Wi-Fi bit 2025-12-09 23:22:35 +01:00
eeeck 6a2a933002 Better wait implementation with no spinlock from MQTT task 2025-12-09 23:02:21 +01:00
eeeck aa395c381b Remove redundant log 2025-12-09 10:49:32 +01:00
eeeck eaad4469bc Normalize spacing in ESP32 firmware 2025-12-09 10:04:06 +01:00
eeeck 4e78a5f2ed Go in critical error if MQTT is not being initialized 2025-12-09 10:03:06 +01:00
eeeck c53783072e Set MQTT username and password 2025-12-09 10:02:47 +01:00
eeeck 9bad1790a7 Log MQTT errors 2025-12-09 10:02:29 +01:00
eeeck 4cd9a3210c Comment out I2C task handles 2025-12-09 10:01:54 +01:00
eeeck 2c7951c2bb Fix missing code from merge for connectivity_event_group 2025-12-09 01:37:18 +01:00
eeeck 88c7635ed9 Merge branch 'dev-esp32-wifi' into dev-esp32-mqtt 2025-12-09 01:00:26 +01:00
eeeck b0059f6e9f Move user configuration to config.h 2025-12-09 00:24:36 +01:00
eeeck 985642e0fe Fix compilation issues with espressif mqtt lib 2025-12-04 23:00:46 +01:00
eeeck fb98ce800a Add network speed check for future use 2025-12-04 21:51:16 +01:00
eeeck a332c37e72 Replace polling it with a blocking wait on connectivity flag and
notification
2025-12-04 21:51:02 +01:00
eeeck 567fca2916 Tweak logs 2025-12-01 00:55:59 +01:00
eeeck 04b5fb0a7c Fix task event notification 2025-12-01 00:54:00 +01:00
eeeck 6fd2d2523d Add global event group handle for connectivity 2025-12-01 00:53:12 +01:00
eeeck c6c4011a47 Fix vTaskDelay syntax error 2025-11-30 23:48:08 +01:00
eeeck 213f6b399f Changed some logs type from informative to debug 2025-11-30 23:40:59 +01:00
eeeck 0a418805a4 Changed some logs type from informative to verbose 2025-11-30 23:40:24 +01:00
eeeck 3670b58f8e Implement task handle for managing I2C 2025-11-30 23:36:54 +01:00
eeeck 5dd2c00ac0 Parametrize task delay values 2025-11-30 23:36:27 +01:00
eeeck 2fcc3172aa Fix message logs for consistency with codebase 2025-11-30 22:24:33 +01:00
eeeck 665125e07f Implement MQTT event groups 2025-11-30 22:24:09 +01:00
eeeck 401c610a58 Create shared event group 2025-11-30 22:22:26 +01:00
eeeck 1ef2476f78 MQTT initialization 2025-11-30 17:40:54 +01:00
eeeck 28ac3f44b3 Fix task delay duration 2025-11-29 14:16:11 +01:00
eeeck 29ad9350a3 Fix task name 2025-11-29 14:15:17 +01:00
eeeck cd4d2658b9 Initialize MQTT task 2025-11-06 19:19:52 +01:00
eeeck 92e0bcc2f5 Merge branch 'dev-esp32-wifi' 2025-11-06 16:19:08 +01:00
eeeck 4653fe05cb Refactor Wi-Fi connection logic to improve stability, simplify event
handling, and enhance logging and watchdog reliability.
2025-11-06 16:16:38 +01:00
eeeck c74a0501c1 Move esp_netif_create_default_wifi_sta() before initializing Wi-Fi to
align with the ESP-IDF recommended order
2025-11-06 13:22:46 +01:00
eeeck 8e82e21a3d Re-implement Wi-Fi retry limiter by using a maximum timeout tick 2025-11-05 22:06:40 +01:00
eeeck e9c22810a4 Implement Wi-Fi connection max retry limit after connection is lost 2025-11-05 14:42:13 +01:00
eeeck 8e96b0ef37 Restructure loop and remove if branch: it would either always trigger it
or reboot

-
2025-10-30 15:05:39 +01:00
eeeck 1053515ced Remove hardcoded tag from logs 2025-10-30 10:19:53 +01:00
eeeck 91cc34a33e Change log types 2025-10-29 15:34:19 +01:00
eeeck b0a765d0cc Remove old log 2025-10-24 23:36:22 +02:00
eeeck c3766d4e14 Fix STA initialization order 2025-10-24 23:36:15 +02:00
eeeck e20c90a021 Change define names 2025-10-24 22:54:46 +02:00
eeeck cb708d72f7 Create Wi-Fi task 2025-10-24 22:54:13 +02:00
eeeck e986120e66 Fix Wi-Fi config assignment error 2025-10-24 22:48:57 +02:00
eeeck 12be9a6141 Add watchdog library 2025-10-24 22:47:06 +02:00
eeeck 1c7cf84ece Fix designated initializer issue 2025-10-24 22:23:34 +02:00
eeeck a7385654f4 Refactor Wi-Fi task to use event groups 2025-10-24 22:22:40 +02:00
eeeck b54d3c744c Update libraries 2025-10-24 22:04:04 +02:00
eeeck 6582872ed0 Refactor Wi-Fi initialization and connection with event groups 2025-10-24 21:55:47 +02:00
eeeck 969fda6ad4 Refactor wifi initialization with event groups 2025-10-24 21:04:32 +02:00
eeeck 1aa2ebbadc Define event group 2025-10-24 20:39:52 +02:00
eeeck be7234f621 Add logs 2025-10-15 13:38:51 +02:00
eeeck eb897dca9e Reinitialize WDT at runtime
- This is needed because of some issues when compiling without using
menuconfig. Maybe there is a way to do this modifying sdkconfig.defaults
when still inside Docker
2025-10-15 13:38:05 +02:00
eeeck d49c69f647 Add error check 2025-10-14 23:32:27 +02:00
eeeck ebee1553ae Increase max frequency to match ESP32-C3 processor 2025-10-14 23:31:13 +02:00
eeeck 60c6a19f13 FIx build script with correct implementation for flashing firmware 2025-10-14 23:29:02 +02:00
eeeck fafd6a9a7a Directory restructure 2025-10-12 20:39:51 +02:00
eeeck 2b86ff133c Remove trailing whitespace 2025-10-12 13:53:39 +02:00
eeeck a1f687e644 Add wifi-credentials.h with SSID, password and auth defines 2025-10-12 00:58:59 +02:00
eeeck 6f37e0d420 Add volatile to include 2025-10-12 00:54:08 +02:00
eeeck fcff8f9900 Add License 2025-10-12 00:33:33 +02:00
eeeck 4be663e688 Update build script to use modern esptool and correct firmware paths 2025-10-11 23:46:57 +02:00
eeeck 95ee47386d Fix WiFi configuration initialization and add proper logging 2025-10-11 23:46:47 +02:00
eeeck c0758b071e Fix power management API and variable naming for ESP32-C3 compatibility 2025-10-11 23:46:33 +02:00
eeeck 4a9a3ef805 Add ESP-IDF component configuration for main directory 2025-10-11 23:46:23 +02:00
eeeck ed7fb9fda6 Fix ESP32-C3 target configuration in Dockerfile 2025-10-11 23:46:12 +02:00
eeeck 558413df41 Add WiFi connectivity initialization and configuration functions 2025-10-11 20:17:57 +02:00
eeeck 94d2a61cad Implement Wi-Fi task 2025-10-11 15:30:40 +02:00
eeeck eb980d286d Fix watchdog initialization and parameters 2025-10-11 14:15:06 +02:00
eeeck 55c11f2471 Add CMakeLists.txt for ESP32 firmware build 2025-10-11 13:08:10 +02:00
eeeck ba590b982c Fix build error in Dockerfile 2025-10-11 00:05:15 +02:00
eeeck d1cf04ffdb Allocate heap caps 2025-10-10 23:59:50 +02:00
eeeck 3dc234eecb Configure power management 2025-10-10 23:59:39 +02:00
eeeck 3d8962b188 Initialize basic watchdog 2025-10-10 23:59:14 +02:00
eeeck 9f848dcc3f Add Dockerfile and build script for ESP32 firmware 2025-10-10 22:30:32 +02:00
eeeck 618965ccc2 Rename Makefile project name to same name as repository 2025-10-05 23:57:03 +02:00
eeeck d7364a6fdc Make triggerMoistureRead function inline 2025-10-05 23:56:41 +02:00
eeeck 443c62593d Add EEPROM flush function to clear address contents 2025-10-04 14:37:38 +02:00
eeeck c24e032981 Add FreeRTOS and GPIO includes 2025-10-01 15:40:05 +02:00
eeeck fb3fdab7df Fix error in comment 2025-10-01 15:39:52 +02:00
eeeck f4e690cf3c Increase EEPROM lifespan by avoiding overwrites on addresses that
contain identical values
2025-10-01 15:34:11 +02:00
eeeck c60493810c Improve EEPROM handling 2025-10-01 15:32:02 +02:00
eeeck fb8423cd9a Clarify inline function name 2025-10-01 01:40:32 +02:00
eeeck 45464300c7 Correct bitmask for TWI SDA and SCL 2025-10-01 01:39:53 +02:00
eeeck 05aae91d12 Mark internal helpers as static and remove from headers 2025-10-01 01:25:59 +02:00
eeeck 6e845c65da Write configuration values to EEPROM at boot 2025-10-01 01:06:20 +02:00
eeeck 2e6fe9ba6b Implement AVR328 EEPROM handling 2025-10-01 00:08:25 +02:00
eeeck 5cce419c74 Add initial ESP32 main.cpp 2025-05-19 11:41:22 +02:00
eeeck 135823b620 Improve atmega Dockerfile apt handling
- Set DEBIAN_FRONTEND as an environment variable.
- Add --no-install-recommends to apt-get install.
2025-05-19 11:39:07 +02:00
eeeck ff8f6324e5 Use deeper sleep mode to reduce current draw during idle
Using `SLEEP_MODE_PWR_DOWN` turns off everything (I/O, clocks, ADC etc.) except the  watchdog
2025-05-19 11:37:12 +02:00
eeeck 29ecd9be17 Fix return non-zero value in main 2025-05-19 11:34:35 +02:00
eeeck 24c454aa88 Reset readSensors before sleep 2025-05-17 14:28:55 +02:00
eeeck 97d78f7c28 Remove unsed flag 2025-05-17 14:23:56 +02:00
eeeck 2a2cb42b0b Refactor optimization flag in Makefile
Introduce `O_FLAG` variable for `-Os` to centralize optimization setting
for CFLAGS and LDFLAGS.
2025-05-17 14:23:22 +02:00
eeeck 906dfa91f0 Remove unused CMD from Dockerfile 2025-05-17 14:22:58 +02:00
eeeck c03e60e56f Add delay to let actuator pump water 2025-05-17 14:07:45 +02:00
eeeck c7abf18736 Change data types regarding sensor readings and sensor/actuator pins from signed to unsigned 2025-05-17 13:49:37 +02:00
eeeck d6bd1932d3 Make pumps initialization and actuation more dynamic by checking which one are declared in config.h 2025-05-17 13:10:45 +02:00
eeeck 8ad766c377 Make sensor initialization and measurement more dynamic by checking
which one are declared in config.h
2025-05-17 12:56:22 +02:00
eeeck ba10840f50 Rename function 2025-05-16 09:22:34 +02:00
eeeck 64852b2a67 Add pump code to Makefile 2025-05-16 09:22:20 +02:00
eeeck 09fed73696 Add waterPlant stub and update pump usage 2025-05-15 23:39:15 +02:00
eeeck c8c27d440c Implement pump control via port register 2025-05-15 23:30:48 +02:00
eeeck 3973d7b41d Initialize pumps' digital pins 2025-05-15 22:41:14 +02:00
eeeck cf3230c470 Rename functions name for better code clarity 2025-05-15 22:40:33 +02:00
eeeck 412354fe88 Move source code to /firmware and fix build paths 2025-05-15 15:51:46 +02:00
eeeck 6dd4b87a0f Simplify Makefile to exclude Arduino core libraries
- Binary file is now <700 bytes, from ~5500 bytes when using Arduino
libraries and core sources
- Time to flash to MCU is decreased from ~8s to ~0.75s
- Change target object name for better clarity
2025-05-15 11:06:51 +02:00
eeeck fe2e04ee38 Implement multiple sensors reading for moisture 2025-05-15 00:32:00 +02:00
eeeck 1a10abc4d6 Use custom ADC interface using AVR flags 2025-05-14 22:38:32 +02:00
eeeck cbf42aae0a Remove make flash, use build script for flashing
This is not optimal, but could not find a way to make it flash without
verification errors with "make flash".
2025-05-14 14:10:11 +02:00
eeeck 5f154cb20f Refactor loop to main and add explicit while(true)
This change transitions from the Arduino-specific `loop()` to a
standard C++ `main()` function as the program's entry point and
primary execution cycle.
2025-05-14 13:02:17 +02:00
eeeck 82dba30e18 Rename image name to avoid future confusion with ESP board 2025-05-13 20:12:10 +02:00
eeeck af4cb39230 Add ATmega build and flash script
Use Dockerfile for firmware compilation and avrdude for flashing
to ATmega328p via usbasp.
2025-05-13 12:42:50 +02:00
eeeck 4ab01eb3a4 Restructure directory organization 2025-05-13 11:28:18 +02:00
eeeck fff7c84206 Refactor Makefile for compatibility with Docker enviroment and better
AVR dependency management
2025-05-12 22:55:28 +02:00
eeeck 4243734056 Create Dockerfile 2025-05-12 22:54:41 +02:00
eeeck 1e7be9adb6 Restructure AVR compilation with Makefile 2025-05-12 19:24:09 +02:00
eeeck c94f7d2982 Add bootloader circuit 2025-05-04 00:34:31 +02:00
eeeck 2800986f17 Add schematics for ATMega side and initialize MCU 2025-05-03 23:46:02 +02:00
eeeck 1a7858198e Move main to C++ file 2025-05-03 12:38:05 +02:00
eeeck 04a8564d46 Merge pull request 'moisture-library' (#1) from moisture-library into main
Reviewed-on: http://192.168.2.248:3000/erickahmed/plant-manager/pulls/1
2025-05-03 12:16:00 +02:00
33 changed files with 4905 additions and 139 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Erick Ahmed
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+638
View File
@@ -0,0 +1,638 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.05,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": true,
"text_position": 0,
"units_format": 0
},
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.1,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.8,
"height": 1.27,
"width": 2.54
},
"silk_line_width": 0.1,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.1,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.5
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"creepage": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_filters_mismatch": "ignore",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_to_hole": "warning",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"mirrored_text_on_front_layer": "warning",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"nonmirrored_text_on_back_layer": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_on_edge_cuts": "error",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_angle": "error",
"track_dangling": "warning",
"track_segment_length": "error",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.5,
"min_groove_width": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.8,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.0,
"min_via_annular_width": 0.1,
"min_via_diameter": 0.5,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpthpad": true,
"td_onroundshapesonly": false,
"td_onsmdpad": true,
"td_ontrackend": false,
"td_onvia": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_pairs": [],
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"footprint_filter": "ignore",
"footprint_link_issues": "warning",
"four_way_junction": "ignore",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"label_multiple_wires": "warning",
"lib_symbol_issues": "warning",
"lib_symbol_mismatch": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"same_local_global_label": "warning",
"similar_label_and_power": "warning",
"similar_labels": "warning",
"similar_power": "warning",
"simulation_model_issue": "ignore",
"single_global_label": "ignore",
"unannotated": "error",
"unconnected_wire_endpoint": "warning",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "atmega.kicad_pro",
"version": 3
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"priority": 2147483647,
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
}
],
"meta": {
"version": 4
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "${PROJECTNAME}.csv",
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": true,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Description",
"name": "Description",
"show": false
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": false,
"label": "#",
"name": "${ITEM_NUMBER}",
"show": false
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
},
{
"group_by": true,
"label": "Exclude from BOM",
"name": "${EXCLUDE_FROM_BOM}",
"show": true
},
{
"group_by": true,
"label": "Exclude from Board",
"name": "${EXCLUDE_FROM_BOARD}",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"include_excluded_from_bom": true,
"name": "",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"meta": {
"version": 0
},
"model_mode": 4,
"workbook_filename": ""
},
"page_layout_descr_file": "sensing",
"plot_directory": "",
"space_save_all_events": true,
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"90981571-11d1-4805-a2bb-89f0c5021ff9",
"Root"
]
],
"text_variables": {}
}
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends\
build-essential \
gcc-avr \
avrdude \
arduino-core-avr \
make \
&& apt-get clean
WORKDIR /usr/src/
COPY . .
RUN make all
+45
View File
@@ -0,0 +1,45 @@
PROJECT = plant-manager
MCU = atmega328p
F_CPU = 16000000UL
CC = avr-gcc
LD = $(CC)
OC = avr-objcopy
RM = rm -f
O_FLAG = -Os
BUILD_DIR = build
OBJ_DIR = $(BUILD_DIR)/obj
SRCS_C = source/adc.c source/moisture.c source/main.c source/pump.c source/eeprom.c
OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(SRCS_C:.c=.o)))
CFLAGS = -Wall $(O_FLAG) -DF_CPU=$(F_CPU) -mmcu=$(MCU) -Iinclude
LDFLAGS = -Wall $(O_FLAG) -mmcu=$(MCU)
LIBS = -lm
EXEC = atmega
ELF_TARGET = $(BUILD_DIR)/$(EXEC).elf
TARGET = $(BUILD_DIR)/$(EXEC).hex
all: $(TARGET)
$(shell mkdir -p $(OBJ_DIR))
$(shell mkdir -p $(BUILD_DIR))
$(ELF_TARGET): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $@ $(LIBS)
$(OBJ_DIR)/%.o: source/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(TARGET): $(ELF_TARGET)
$(OC) -O ihex -R .eeprom $< $@
clean:
$(RM) $(TARGET) $(ELF_TARGET) $(OBJS)
$(RM) -r $(BUILD_DIR)
.PHONY: all clean
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -e
IMAGE_NAME="vase-control-builder"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
IMAGE_NAME="vase-control-builder"
DOCKERFILE="$SCRIPT_DIR/Dockerfile"
BUILD_CTX="$SCRIPT_DIR"
DEST_HEX="$SCRIPT_DIR/build/atmega.hex"
MCU="atmega328p"; PRG="usbasp"
docker build -t "$IMAGE_NAME" -f "$DOCKERFILE" "$BUILD_CTX"
mkdir -p "$(dirname "$DEST_HEX")"
docker run --rm "$IMAGE_NAME" \
cat /usr/src/build/atmega.hex > "$DEST_HEX"
command -v avrdude >/dev/null || { echo "Install avrdude"; exit 1; }
avrdude -v -p m328p -c usbasp -U flash:w:build/atmega.hex:i
+11
View File
@@ -0,0 +1,11 @@
#ifndef ADC_H
#define ADC_H
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
void adcInit(void);
uint16_t adcRead(uint8_t channel);
#endif
+54
View File
@@ -0,0 +1,54 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <sys/types.h>
#include <stdint.h>
#include <avr/io.h>
#include "eeprom.h"
#define MOISTURE_SENSOR_A0 PC0
//#define MOISTURE_SENSOR_A1 PC1
//#define MOISTURE_SENSOR_A2 PC2
//#define MOISTURE_SENSOR_A3 PC3
//#define MOISTURE_SENSOR_A4 PC4
//#define MOISTURE_SENSOR_A5 PC5
//#define MOISTURE_SENSOR_A6 PC6
//#define MOISTURE_SENSOR_A7 PC7
//#define PUMP_D3 PD3
//#define PUMP_D4 PD4
//#define PUMP_D5 PD5
//#define PUMP_D6 PD6
#define PUMP_D7 PD7
#define TWI_SDA (1 << PD2)
#define TWI_SCL (1 << PD3)
inline void eeprom_init() {
#define DICT_SIZE 4
#define TWI_ADDR 0x22
#define SENSOR_READINGS 0x23
#define MOISTURE_MIN 0x24
#define MOISTURE_MAX 0x25
uint8_t keys[DICT_SIZE] = {
TWI_ADDR,
SENSOR_READINGS,
MOISTURE_MIN,
MOISTURE_MAX
};
uint16_t values[DICT_SIZE] = {
0x20,
5,
400,
200
};
//NOTE: values are not re-initialized if != 0 because they may
// have been changed by the esp32 during previous runs
for (int i = 0; i < DICT_SIZE; i++) if (eepromRead(keys[i]) == 0) eepromWrite(keys[i], values[i]);
}
#endif
+11
View File
@@ -0,0 +1,11 @@
#ifndef EEPROM_H
#define EEPROM_H
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
uint8_t eepromRead(uint8_t address);
void eepromWrite(uint8_t address, uint8_t data);
#endif
+50
View File
@@ -0,0 +1,50 @@
#ifndef MOISTURE_H
#define MOISTURE_H
#include <stdint.h>
#include <stdbool.h>
#include "config.h"
static const int8_t sensorPins[] = {
#ifdef MOISTURE_SENSOR_A0
MOISTURE_SENSOR_A0,
#endif
#ifdef MOISTURE_SENSOR_A1
MOISTURE_SENSOR_A1,
#endif
#ifdef MOISTURE_SENSOR_A2
MOISTURE_SENSOR_A2,
#endif
#ifdef MOISTURE_SENSOR_A3
MOISTURE_SENSOR_A3,
#endif
#ifdef MOISTURE_SENSOR_A4
MOISTURE_SENSOR_A4,
#endif
#ifdef MOISTURE_SENSOR_A5
MOISTURE_SENSOR_A5,
#endif
#ifdef MOISTURE_SENSOR_A6
MOISTURE_SENSOR_A6,
#endif
#ifdef MOISTURE_SENSOR_A7
MOISTURE_SENSOR_A7,
#endif
};
#define SENSORS_NUM (sizeof(sensorPins) / sizeof(sensorPins[0]))
extern volatile bool readSensors;
void sensorsInit(void);
inline void triggerMoistureRead(void);
uint16_t moistureRead(void);
#endif
+38
View File
@@ -0,0 +1,38 @@
#ifndef PUMP_H
#define PUMP_H
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "config.h"
static const int8_t actuatorPins[] = {
#ifdef PUMP_D3
PUMP_D3,
#endif
#ifdef PUMP_D4
PUMP_D4,
#endif
#ifdef PUMP_D5
PUMP_D5,
#endif
#ifdef PUMP_D6
PUMP_D6,
#endif
#ifdef PUMP_D7
PUMP_D7,
#endif
};
#define ACTUATORS_NUM (sizeof(actuatorPins) / sizeof(actuatorPins[0]))
void pumpsInit(void);
void waterPlant(void);
#endif
+27
View File
@@ -0,0 +1,27 @@
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
void adcInit(void) {
// Set reference voltage to AVcc (REFS0 = 1, REFS1 = 0)
ADMUX = (1 << REFS0);
// Enable ADC and set prescaler to 128 (for 16 MHz clock, gives 125 kHz ADC clock)
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
}
uint16_t adcRead(uint8_t channel) {
// Select ADC pin (A0-A7) by setting MUX bits in ADMUX
// Pins A6 and A7 would make an 8 sensor array possible (for large vases).
// Achievable only when using the 328p as a DIP, through port C (PC6, PC7)
ADMUX = (ADMUX & 0xF8) | (channel & 0x07);
// Start conversion
ADCSRA |= (1 << ADSC);
// Wait for conversion to complete (ADSC becomes '0' when done)
while (ADCSRA & (1 << ADSC));
// Read ADC (reading order: ADCL --> ADCH)
return ADC;
}
+35
View File
@@ -0,0 +1,35 @@
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
uint8_t eepromRead(uint8_t address) {
// wait for previous write
while (EECR & (1 << EEPE));
//read from address
EEAR = address;
return EECR |= (1 << EERE);
}
void eepromWrite(uint8_t address, uint8_t data) {
// wait for previous write
while (EECR & (1 << EEPE));
if (eepromRead(address) != data) {
EEAR = address;
EEDR = data;
EECR |= (1 << EEMPE);
EECR |= (1 << EEPE);
}
}
void eepromFlush(uint8_t address) {
if (eepromRead(address) != 0) {
EEAR = address;
EEDR = 0;
EECR |= (1 << EEMPE);
EECR |= (1 << EEPE);
}
}
+51
View File
@@ -0,0 +1,51 @@
#include <stdint.h>
#include <stdbool.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include "adc.h"
#include "moisture.h"
#include "pump.h"
ISR(WDT_vect) {
triggerMoistureRead();
}
void watchdogs(void) {
cli();
MCUSR &= ~(1 << WDRF);
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0);
sei();
}
void enterSleep(void) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
sleep_disable();
}
void setup(void) {
adcInit();
sensorsInit();
pumpsInit();
watchdogs();
}
int main(void) {
setup();
while(true) {
if (readSensors) {
uint16_t result = moistureRead();
//espSend(VASE_NUM, result)
}
// if(espGet("ask if i need to water plants") == true) {waterPlant()}
// or maybe it's better to do this with interrupts?
readSensors = false;
enterSleep();
}
return -1;
}
+44
View File
@@ -0,0 +1,44 @@
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "moisture.h"
#include "config.h"
#include "adc.h"
volatile bool readSensors = false;
void sensorsInit(void) {
uint8_t sensorMask = 0;
for (uint8_t i = 0; i < SENSORS_NUM; i++) {
sensorMask |= (1 << sensorPins[i]);
}
DDRC &= ~sensorMask;
PORTC &= ~sensorMask;
}
inline void triggerMoistureRead(void) {
readSensors = true;
}
static uint16_t moistureAverage(uint8_t sensorPin) {
uint16_t sum = 0;
for (uint8_t i = 0; i < SENSOR_READINGS; i++) {
sum += adcRead(sensorPin);
//TODO: implement variance check (if over a certain variance discard measurements for this cycle)
//TODO IMPORTANT: if value < 1 or > 1022, discard that measurement
}
return sum / SENSOR_READINGS;
}
uint16_t moistureRead(void) {
uint16_t overallSum = 0;
for (uint8_t i = 0; i < SENSORS_NUM; i++) {
uint16_t sensorAverage = moistureAverage(sensorPins[i]);
//TODO: if a sensor gives 1023, discard that sensor entirely (means it is disconnected or not working)
overallSum += sensorAverage;
}
return overallSum / SENSORS_NUM;
}
+32
View File
@@ -0,0 +1,32 @@
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "pump.h"
#include "config.h"
void pumpsInit(void) {
uint8_t actuatorMask = 0;
for (uint8_t i = 0; i < ACTUATORS_NUM; i++) {
actuatorMask |= (1 << actuatorPins[i]);
}
DDRD |= actuatorMask;
//PORTD &= ~(1 << actuatorMask);
}
static void triggerPump(uint8_t pump_pin) {
// Turn on pump
PORTD |= (1 << pump_pin);
_delay_ms(500);
// Here there could be the issue of the AVR hanging when pump is on
// Turn off pump
PORTD &= ~(1 << pump_pin);
}
void waterPlant(void) {
for (uint8_t i=0; i < ACTUATORS_NUM; i++) {
triggerPump(actuatorPins[i]);
}
}
+4
View File
@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(plant-manager)
+48
View File
@@ -0,0 +1,48 @@
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y --no-install-recommends \
git \
wget \
flex \
bison \
gperf \
python3 \
python3-pip \
python3-venv \
cmake \
ninja-build \
ccache \
libffi-dev \
libssl-dev \
dfu-util \
libusb-1.0-0 \
&& apt-get autoremove
WORKDIR /usr/src/
ENV IDF_PATH=/usr/src/esp/esp-idf
ENV IDF_PATH_FORCE=1
RUN mkdir -p /usr/src/esp/firmware
RUN git clone --recursive https://github.com/espressif/esp-idf.git $IDF_PATH
RUN cd $IDF_PATH && ./install.sh esp32c3
COPY . /usr/src/esp/firmware/
WORKDIR /usr/src/esp/firmware/
# Create sdkconfig.defaults with correct flash settings
RUN echo "CONFIG_ESPTOOLPY_FLASHMODE=dio" > sdkconfig.defaults && \
echo "CONFIG_ESPTOOLPY_FLASHFREQ=40m" >> sdkconfig.defaults && \
echo "CONFIG_ESPTOOLPY_FLASHSIZE=4MB" >> sdkconfig.defaults
RUN rm -rf build && /bin/bash -c "source $IDF_PATH/export.sh && idf.py set-target esp32c3 && idf.py build"
RUN mkdir -p /usr/src/build && \
cp build/bootloader/bootloader.bin /usr/src/build/ && \
cp build/partition_table/partition-table.bin /usr/src/build/ && \
cp build/plant-manager.bin /usr/src/build/
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -e
IMAGE_NAME="esp32-builder"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
DOCKERFILE="$SCRIPT_DIR/Dockerfile"
BUILD_CTX="$SCRIPT_DIR"
DEST_DIR="$SCRIPT_DIR/build"
docker build -t "$IMAGE_NAME" -f "$DOCKERFILE" "$BUILD_CTX"
mkdir -p "$DEST_DIR"
docker run --rm -v "$DEST_DIR":/output "$IMAGE_NAME" cp -r /usr/src/build/. /output/
#echo "Erasing flash..."
#esptool --chip esp32c3 --port /dev/tty.usbmodem101 erase-flash
esptool --chip esp32c3 --port /dev/tty.usbmodem101 --baud 115200 write-flash \
--flash-mode dio \
--flash-freq 40m \
--flash-size 4MB \
0x0000 "$DEST_DIR/bootloader.bin" \
0x8000 "$DEST_DIR/partition-table.bin" \
0x10000 "$DEST_DIR/plant-manager.bin"
screen -fn /dev/tty.usbmodem101 115200
+17
View File
@@ -0,0 +1,17 @@
#ifndef CONFIG_H
#define CONFIG_H
// TODO: make this a config.h
// WI-FI
#define SSID "your_wifi_ssid"
#define PASSWORD "your_wifi_password"
#define AUTH_MODE WIFI_AUTH_WPA2_PSK
// MQTT
#define MQTT_ADDR "mqtt://yourmqttserver"
#define MQTT_PORT 1883
#define MQTT_USER "your_username"
#define MQTT_PASS "your_password"
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef MAIN_HPP
#define MAIN_HPP
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
extern volatile bool criticalErrorFlag;
extern EventGroupHandle_t connectivity_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define MQTT_CONNECTED_BIT BIT1
#endif
+6
View File
@@ -0,0 +1,6 @@
#ifndef MQTT_HPP
#define MQTT_HPP
void mqttTask(void *pvParameters);
#endif
+6
View File
@@ -0,0 +1,6 @@
#ifndef WIFI_HPP
#define WIFI_HPP
void wifiTask(void *pvParameters);
#endif
+12
View File
@@ -0,0 +1,12 @@
idf_component_register(SRCS "./main.cpp"
"./wifi.cpp"
"./mqtt.cpp"
INCLUDE_DIRS "../include"
REQUIRES esp_wifi
nvs_flash
esp_pm
esp_hw_support
esp_system
freertos
log
mqtt)
+2
View File
@@ -0,0 +1,2 @@
dependencies:
espressif/mqtt: "*"
+58
View File
@@ -0,0 +1,58 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_pm.h"
#include "esp_task_wdt.h"
#include "wifi.hpp"
#include "mqtt.hpp"
#define WATCHDOG_KEEPALIVE_MS 8000
EventGroupHandle_t connectivity_event_group;
static const char* TAG = "MAIN";
volatile bool criticalErrorFlag = false;
static void watchdogTask(void *pvParameters) {
esp_task_wdt_config_t twdt_config = {
.timeout_ms = 12000,
.idle_core_mask = 0,
.trigger_panic = true,
};
ESP_ERROR_CHECK(esp_task_wdt_deinit());
ESP_ERROR_CHECK(esp_task_wdt_init(&twdt_config));
ESP_ERROR_CHECK(esp_task_wdt_add(NULL));
for(;;) {
if(criticalErrorFlag) {
ESP_LOGE(TAG, "Critical error flag raised. Rebooting.");
esp_restart();
}
ESP_ERROR_CHECK(esp_task_wdt_reset());
ESP_LOGV(TAG, "WDT reset");
vTaskDelay(pdMS_TO_TICKS(WATCHDOG_KEEPALIVE_MS));
}
}
extern "C" void app_main(void)
{
static const esp_pm_config_t pm_cfg = {
.max_freq_mhz = 160,
.min_freq_mhz = 10,
.light_sleep_enable = true
};
esp_pm_configure(&pm_cfg);
connectivity_event_group = xEventGroupCreate();
xTaskCreate(watchdogTask, "watchdogs", 2048, NULL, configMAX_PRIORITIES-1, NULL);
xTaskCreate(wifiTask, "wifi", 4096, NULL, configMAX_PRIORITIES-4, NULL);
xTaskCreate(mqttTask, "mqtt", 2048, NULL, configMAX_PRIORITIES-8, NULL);
}
+106
View File
@@ -0,0 +1,106 @@
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_task_wdt.h"
#include "esp_event.h"
#include "esp_log.h"
#include "mqtt_client.h"
#include "main.hpp"
//#include "i2c.hpp"
#include "config-erick.h"
#define MQTT_TASK_TIMEOUT_MS 3000
static const char* TAG = "MQTT";
static esp_mqtt_client_handle_t mqtt_client = NULL;
static char global_rx_buffer[50];
static void mqtt_subscribe(void) {
esp_mqtt_client_subscribe(mqtt_client, "/topic/qos0", 0);
}
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
esp_mqtt_event_handle_t event =(esp_mqtt_event_handle_t)event_data;
switch(event->event_id) {
case MQTT_EVENT_CONNECTED:
xEventGroupSetBits(connectivity_event_group, MQTT_CONNECTED_BIT);
mqtt_subscribe();
ESP_LOGV(TAG, "Connected to broker");
break;
case MQTT_EVENT_DISCONNECTED:
xEventGroupClearBits(connectivity_event_group, MQTT_CONNECTED_BIT);
ESP_LOGW(TAG, "Disconnected from broker");
break;
case MQTT_EVENT_DATA:
{
ESP_LOGD(TAG, "Data received");
int len = event->data_len;
if(len > sizeof(global_rx_buffer) - 1) len = sizeof(global_rx_buffer) - 1;
memcpy(global_rx_buffer, event->data, len);
global_rx_buffer[len] = '\0';
break;
}
case MQTT_EVENT_ERROR:
ESP_LOGE(TAG, "Error event");
if(event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) ESP_LOGE(TAG, "Network Error: %s", strerror(event->error_handle->esp_transport_sock_errno));
else if(event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) ESP_LOGE(TAG, "Connection Refused! Reason code: 0x%x", event->error_handle->connect_return_code);
break;
default:
break;
}
}
static void mqtt_init(void) {
esp_mqtt_client_config_t mqtt_cfg = {};
mqtt_cfg.broker.address.uri = MQTT_ADDR;
mqtt_cfg.broker.address.port = MQTT_PORT;
mqtt_cfg.credentials.username = MQTT_USER;
mqtt_cfg.credentials.authentication.password = MQTT_PASS;
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
if(mqtt_client == NULL) {
ESP_LOGE(TAG, "esp_mqtt_client_init returned NULL");
criticalErrorFlag = true;
}
esp_mqtt_client_register_event(mqtt_client, (esp_mqtt_event_id_t)ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(mqtt_client);
}
void mqtt_publish(void) {}
void mqttTask(void *pvParameters) {
ESP_LOGV(TAG, "Task started");
ESP_LOGV(TAG, "Waiting for Wi-Fi before initializing server");
xEventGroupWaitBits(connectivity_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY);
ESP_LOGV(TAG, "Server initialized");
mqtt_init();
ESP_ERROR_CHECK(esp_task_wdt_add(NULL));
for(;;) {
ESP_LOGV(TAG, "Checking Wi-Fi connection...");
EventBits_t bits = xEventGroupWaitBits(connectivity_event_group, WIFI_CONNECTED_BIT | MQTT_CONNECTED_BIT, pdFALSE, pdTRUE, pdMS_TO_TICKS(MQTT_TASK_TIMEOUT_MS));
if ((bits & (WIFI_CONNECTED_BIT | MQTT_CONNECTED_BIT)) == (WIFI_CONNECTED_BIT | MQTT_CONNECTED_BIT)) {
ESP_LOGV(TAG, "Wi-Fi and MQTT up");
} else ESP_LOGV(TAG, "Wi-Fi or MQTT down");
ESP_ERROR_CHECK(esp_task_wdt_reset());
ESP_LOGV(TAG, "Task reset");
}
}
+85
View File
@@ -0,0 +1,85 @@
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_task_wdt.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "main.hpp"
#include "config-erick.h"
#define WIFI_TIMEOUT_MS 4500
static const char* TAG = "WIFI";
static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if(event_base == WIFI_EVENT) {
switch(event_id) {
case WIFI_EVENT_STA_START:
ESP_LOGV(TAG, "Process started, connecting...");
esp_wifi_connect();
break;
case WIFI_EVENT_STA_DISCONNECTED: {
wifi_event_sta_disconnected_t* disconn =(wifi_event_sta_disconnected_t*) event_data;
ESP_LOGW(TAG, "Disconnected, reason: %d", disconn->reason);
xEventGroupClearBits(connectivity_event_group, WIFI_CONNECTED_BIT);
esp_wifi_connect();
break;
}
default:
break;
}
}
else if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event =(ip_event_got_ip_t*) event_data;
ESP_LOGD(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
xEventGroupSetBits(connectivity_event_group, WIFI_CONNECTED_BIT);
}
}
static void wifi_init_sta(void) {
esp_err_t nvs_err = nvs_flash_init();
if(nvs_err == ESP_ERR_NVS_NO_FREE_PAGES || nvs_err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ESP_ERROR_CHECK(nvs_flash_init());
}
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));
wifi_config_t wifi_config{};
strncpy((char*)wifi_config.sta.ssid, SSID, sizeof(wifi_config.sta.ssid));
strncpy((char*)wifi_config.sta.password, PASSWORD, sizeof(wifi_config.sta.password));
wifi_config.sta.threshold.authmode = AUTH_MODE;
wifi_config.sta.pmf_cfg.capable = true;
wifi_config.sta.pmf_cfg.required = false;
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
}
void wifiTask(void *pvParameters) {
ESP_LOGV(TAG, "Task started");
wifi_init_sta();
ESP_ERROR_CHECK(esp_task_wdt_add(NULL));
for(;;) {
ESP_ERROR_CHECK(esp_task_wdt_reset());
ESP_LOGV(TAG, "Task reset");
vTaskDelay(pdMS_TO_TICKS(WIFI_TIMEOUT_MS));
}
}
-41
View File
@@ -1,41 +0,0 @@
PROJECT = plant-manager
# Flags
MCU = atmega328p
F_CPU = 16000000UL
CC = avr-gcc
OBJCOPY = avr-objcopy
AVRDUDE = avrdude
CFLAGS = -Wall -Os -DF_CPU=$(F_CPU) -mmcu=$(MCU)
PROGRAMMER = arduino
PORT = /dev/ttyACM0
SRC = main.c
OBJ = $(SRC:.c=.o)
# Default target
all: $(PROJECT).hex
# Compiler
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Linker
$(PROJECT).elf: $(OBJ)
$(CC) $(CFLAGS) -o $@ $^
# Create hex file
$(PROJECT).hex: $(PROJECT).elf
$(OBJCOPY) -O ihex -R .eeprom $< $@
# Uploader
upload: $(PROJECT).hex
$(AVRDUDE) -p $(MCU) -c $(PROGRAMMER) -P $(PORT) -U flash:w:$<:i
# Cleaner
clean:
rm -f *.o *.elf *.hex
.PHONY: all upload clean
-7
View File
@@ -1,7 +0,0 @@
#ifndef CONFIG_H
#define CONFIG_H
#define MOISTURE_SENSOR_A0 A0
#define SENSOR_READINGS 3
#endif
-42
View File
@@ -1,42 +0,0 @@
#include <stdint.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include "config.h"
#include "moisture.h"
ISR(WDT_vect) {
readSensors = true;
}
void watchdogs(void) {
cli();
MCUSR &= ~(1 << WDRF);
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0);
sei();
}
void enterSleep(void) {
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
sleep_cpu();
sleep_disable();
}
void setup(void) {
Serial.begin(9600);
initMoistureSensor();
watchdogs();
}
void loop(void) {
if (readSensors) {
int16_t result = readMoisture();
if (result != -1) {
Serial.println(result);
readSensors = false;
}
}
enterSleep();
}
-36
View File
@@ -1,36 +0,0 @@
#include <Arduino.h>
#include <stdint.h>
#include "moisture.h"
#include "config.h"
static int16_t moistureReadingSum = 0;
static int8_t moistureReadingCount = 0;
volatile bool readSensors = false;
void initMoistureSensor(void) {
pinMode(MOISTURE_SENSOR_A0, INPUT);
}
void triggerSensorRead(void) {
readSensors = true;
}
int16_t readMoisture(void) {
if (!readSensors)
return -1;
moistureReadingSum += analogRead(MOISTURE_SENSOR_A0);
moistureReadingCount++;
if (moistureReadingCount >= SENSOR_READINGS) {
int16_t avg = moistureReadingSum / SENSOR_READINGS;
//Serial.println(avg);
moistureReadingSum = 0;
moistureReadingCount = 0;
readSensors = false;
return avg;
} else readSensors = true;
return -1;
}
-13
View File
@@ -1,13 +0,0 @@
#ifndef MOISTURE_H
#define MOISTURE_H
#include <stdint.h>
#include <stdbool.h>
void initMoistureSensor(void);
int16_t readMoisture(void);
void triggerSensorRead(void);
extern volatile bool readSensors;
#endif