Initial committ: Fish feeder and temp monitor

This commit is contained in:
2025-12-05 16:07:03 +11:00
commit 73cdedb939
4 changed files with 661 additions and 0 deletions

6
.vscode/arduino.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"configuration": "JTAGAdapter=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,LoopCore=1,EventsCore=1,DebugLevel=none,EraseFlash=none,ZigbeeMode=default",
"board": "esp32:esp32:esp32",
"port": "/dev/ttyUSB0",
"sketch": "fish_feeder.ino"
}

453
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,453 @@
{
"version": 4,
"configurations": [
{
"name": "Arduino",
"compilerPath": "/home/sam/.arduino15/packages/esp32/tools/esp-x32/2411/bin/xtensa-esp32-elf-g++",
"compilerArgs": [
"-MMD",
"-w",
"-Werror=return-type",
"-iprefix"
],
"intelliSenseMode": "gcc-x64",
"includePath": [
"/media/sam/8294CD2994CD2111/Users/Dell/Documents/Arduino/fish_feeder",
"/home/sam/.arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.5-129cd0d2-v4/esp32/qio_qspi/include",
"/home/sam/.arduino15/packages/esp32/hardware/esp32/3.3.1/cores/esp32",
"/home/sam/.arduino15/packages/esp32/hardware/esp32/3.3.1/variants/esp32",
"/home/sam/.arduino15/packages/esp32/hardware/esp32/3.3.1/libraries/WiFi/src",
"/home/sam/.arduino15/packages/esp32/hardware/esp32/3.3.1/libraries/Network/src",
"/home/sam/Arduino/libraries/PubSubClient/src",
"/home/sam/Arduino/libraries/OneWire",
"/home/sam/Arduino/libraries/DallasTemperature",
"/home/sam/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0",
"/home/sam/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0/xtensa-esp-elf/esp32",
"/home/sam/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include/c++/14.2.0/backward",
"/home/sam/.arduino15/packages/esp32/tools/esp-x32/2411/lib/gcc/xtensa-esp-elf/14.2.0/include",
"/home/sam/.arduino15/packages/esp32/tools/esp-x32/2411/lib/gcc/xtensa-esp-elf/14.2.0/include-fixed",
"/home/sam/.arduino15/packages/esp32/tools/esp-x32/2411/xtensa-esp-elf/include"
],
"forcedInclude": [
"/home/sam/.arduino15/packages/esp32/hardware/esp32/3.3.1/cores/esp32/Arduino.h"
],
"cStandard": "c11",
"cppStandard": "c++11",
"defines": [
"F_CPU=240000000L",
"ARDUINO=10607",
"ARDUINO_ESP32_DEV",
"ARDUINO_ARCH_ESP32",
"ARDUINO_BOARD=\"ESP32_DEV\"",
"ARDUINO_VARIANT=\"esp32\"",
"ARDUINO_PARTITION_default",
"ARDUINO_HOST_OS=\"linux\"",
"ARDUINO_FQBN=\"esp32:esp32:esp32:JTAGAdapter=default,PSRAM=disabled,PartitionScheme=default,CPUFreq=240,FlashMode=qio,FlashFreq=80,FlashSize=4M,UploadSpeed=921600,LoopCore=1,EventsCore=1,DebugLevel=none,EraseFlash=none,ZigbeeMode=default\"",
"ESP32=ESP32",
"CORE_DEBUG_LEVEL=0",
"ARDUINO_RUNNING_CORE=1",
"ARDUINO_EVENT_RUNNING_CORE=1",
"ARDUINO_USB_CDC_ON_BOOT=0",
"__DBL_MIN_EXP__=(-1021)",
"__XCHAL_HAVE_FP=1",
"__cpp_nontype_template_parameter_auto=201606L",
"__UINT_LEAST16_MAX__=0xffff",
"__ATOMIC_ACQUIRE=2",
"__FLT_MIN__=1.1754943508222875e-38F",
"__GCC_IEC_559_COMPLEX=0",
"__XCHAL_HAVE_PREDICTED_BRANCHES=0",
"__cpp_aggregate_nsdmi=201304L",
"__UINT_LEAST8_TYPE__=unsigned char",
"__INTMAX_C(c)=c ## LL",
"__XCHAL_HAVE_ADDX=1",
"__CHAR_BIT__=8",
"__XCHAL_DCACHE_LINESIZE=16",
"__XTENSA_MARCH_EARLIEST=260003",
"__XCHAL_DCACHE_LINEWIDTH=4",
"__UINT8_MAX__=0xff",
"__WINT_MAX__=0xffffffffU",
"__FLT32_MIN_EXP__=(-125)",
"__cpp_static_assert=201411L",
"__ORDER_LITTLE_ENDIAN__=1234",
"__SIZE_MAX__=0xffffffffU",
"__WCHAR_MAX__=0xffff",
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1=1",
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2=1",
"__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4=1",
"__DBL_DENORM_MIN__=double(4.9406564584124654e-324L)",
"__GCC_ATOMIC_CHAR_LOCK_FREE=2",
"__GCC_IEC_559=0",
"__FLT32X_DECIMAL_DIG__=17",
"__FLT_EVAL_METHOD__=0",
"__cpp_binary_literals=201304L",
"__FLT64_DECIMAL_DIG__=17",
"__cpp_noexcept_function_type=201510L",
"__GCC_ATOMIC_CHAR32_T_LOCK_FREE=2",
"__cpp_variadic_templates=200704L",
"__UINT_FAST64_MAX__=0xffffffffffffffffULL",
"__SIG_ATOMIC_TYPE__=int",
"__DBL_MIN_10_EXP__=(-307)",
"__FINITE_MATH_ONLY__=0",
"__cpp_variable_templates=201304L",
"__XCHAL_HAVE_L32R=1",
"__FLT32X_MAX_EXP__=1024",
"__GNUC_PATCHLEVEL__=0",
"__FLT32_HAS_DENORM__=1",
"__UINT_FAST8_MAX__=0xffffffffU",
"__cpp_rvalue_reference=200610L",
"__XCHAL_HAVE_LOOPS=1",
"__cpp_nested_namespace_definitions=201411L",
"__XCHAL_DEBUGLEVEL=6",
"__INT8_C(c)=c",
"__XCHAL_HAVE_DFP_RECIP=0",
"__INT_LEAST8_WIDTH__=8",
"__cpp_variadic_using=201611L",
"__UINT_LEAST64_MAX__=0xffffffffffffffffULL",
"__INT_LEAST8_MAX__=0x7f",
"__cpp_attributes=200809L",
"__cpp_capture_star_this=201603L",
"__SHRT_MAX__=0x7fff",
"__LDBL_MAX__=1.7976931348623157e+308L",
"__cpp_if_constexpr=201606L",
"__XCHAL_ICACHE_LINESIZE=16",
"__LDBL_IS_IEC_60559__=1",
"__UINT_LEAST8_MAX__=0xff",
"__GCC_ATOMIC_BOOL_LOCK_FREE=2",
"__UINTMAX_TYPE__=long long unsigned int",
"__cpp_nsdmi=200809L",
"__FLT_EVAL_METHOD_TS_18661_3__=0",
"__UINT32_MAX__=0xffffffffUL",
"__GXX_EXPERIMENTAL_CXX0X__=1",
"__LDBL_MAX_EXP__=1024",
"__WINT_MIN__=0U",
"__FLT32X_IS_IEC_60559__=1",
"__XCHAL_HAVE_THREADPTR=1",
"__INT_LEAST16_WIDTH__=16",
"__SCHAR_MAX__=0x7f",
"__WCHAR_MIN__=0",
"__XCHAL_ICACHE_LINEWIDTH=4",
"__INT64_C(c)=c ## LL",
"__GCC_ATOMIC_POINTER_LOCK_FREE=2",
"__ATOMIC_SEQ_CST=5",
"__SIZEOF_INT__=4",
"__FLT32X_MANT_DIG__=53",
"__GCC_ATOMIC_CHAR16_T_LOCK_FREE=2",
"__cpp_aligned_new=201606L",
"__XCHAL_HAVE_FP_RECIP=1",
"__FLT32_MAX_10_EXP__=38",
"__STDC_HOSTED__=1",
"__XCHAL_HAVE_MUL32=1",
"__XTENSA_EL__=1",
"__cpp_decltype_auto=201304L",
"__DBL_DIG__=15",
"__XCHAL_HAVE_MUL16=1",
"__FLT_EPSILON__=1.1920928955078125e-7F",
"__GXX_WEAK__=1",
"__SHRT_WIDTH__=16",
"__FLT32_IS_IEC_60559__=1",
"__LDBL_MIN__=2.2250738585072014e-308L",
"__DBL_IS_IEC_60559__=1",
"__cpp_threadsafe_static_init=200806L",
"__cpp_enumerator_attributes=201411L",
"__XCHAL_HAVE_MMU=0",
"__FLT32X_HAS_INFINITY__=1",
"__INT32_MAX__=0x7fffffffL",
"__XCHAL_HAVE_DIV32=1",
"__INT_WIDTH__=32",
"__XTENSA_MARCH_LATEST=260003",
"__DECIMAL_DIG__=17",
"__FLT64_EPSILON__=2.2204460492503131e-16F64",
"__INT16_MAX__=0x7fff",
"__FLT64_MIN_EXP__=(-1021)",
"__XCHAL_DCACHE_SIZE=0",
"__LDBL_HAS_QUIET_NAN__=1",
"__cpp_return_type_deduction=201304L",
"__XCHAL_HAVE_BOOLEANS=1",
"__FLT64_MANT_DIG__=53",
"__XTHAL_ABI_WINDOWED=0",
"__GNUC__=14",
"__GXX_RTTI=1",
"__FLT_HAS_DENORM__=1",
"__SIZEOF_LONG_DOUBLE__=8",
"__XCHAL_HAVE_CONST16=0",
"__BIGGEST_ALIGNMENT__=16",
"__STDC_UTF_16__=1",
"__FLT64_MAX_10_EXP__=308",
"__cpp_delegating_constructors=200604L",
"__DBL_MAX__=double(1.7976931348623157e+308L)",
"__cpp_raw_strings=200710L",
"__INT_FAST32_MAX__=0x7fffffff",
"__DBL_HAS_INFINITY__=1",
"__cpp_deduction_guides=201703L",
"__HAVE_SPECULATION_SAFE_VALUE=1",
"__cpp_fold_expressions=201603L",
"__INTPTR_WIDTH__=32",
"__UINT_LEAST32_MAX__=0xffffffffUL",
"__FLT32X_HAS_DENORM__=1",
"__INT_FAST16_TYPE__=int",
"__XCHAL_HAVE_RELEASE_SYNC=1",
"__LDBL_HAS_DENORM__=1",
"__cplusplus=201703L",
"__cpp_ref_qualifiers=200710L",
"__INT_LEAST32_MAX__=0x7fffffffL",
"__DEPRECATED=1",
"__cpp_rvalue_references=200610L",
"__DBL_MAX_EXP__=1024",
"__WCHAR_WIDTH__=16",
"__FLT32_MAX__=3.4028234663852886e+38F32",
"__GCC_ATOMIC_LONG_LOCK_FREE=2",
"__PTRDIFF_MAX__=0x7fffffff",
"__FLT32_HAS_QUIET_NAN__=1",
"__GNUG__=14",
"__LONG_LONG_MAX__=0x7fffffffffffffffLL",
"__SIZEOF_SIZE_T__=4",
"__SIZEOF_WINT_T__=4",
"__FLT32X_DIG__=15",
"__LONG_LONG_WIDTH__=64",
"__cpp_initializer_lists=200806L",
"__FLT32_MAX_EXP__=128",
"__XCHAL_HAVE_MINMAX=1",
"__cpp_hex_float=201603L",
"__XCHAL_NUM_IBREAK=2",
"__GXX_ABI_VERSION=1019",
"__FLT_MIN_EXP__=(-125)",
"__cpp_lambdas=200907L",
"__INT_FAST64_TYPE__=long long int",
"__FP_FAST_FMAF=1",
"__FLT64_DENORM_MIN__=4.9406564584124654e-324F64",
"__DBL_MIN__=double(2.2250738585072014e-308L)",
"__SIZEOF_POINTER__=4",
"__DBL_HAS_QUIET_NAN__=1",
"__FLT32X_EPSILON__=2.2204460492503131e-16F32x",
"__XSHAL_HAVE_TEXT_SECTION_LITERALS=1",
"__FLT64_MIN_10_EXP__=(-307)",
"__REGISTER_PREFIX__",
"__UINT16_MAX__=0xffff",
"__XSHAL_USE_ABSOLUTE_LITERALS=0",
"__LDBL_HAS_INFINITY__=1",
"__FLT32_MIN__=1.1754943508222875e-38F32",
"__UINT8_TYPE__=unsigned char",
"__FLT_DIG__=6",
"__NO_INLINE__=1",
"__DEC_EVAL_METHOD__=2",
"__FLT_MANT_DIG__=24",
"__LDBL_DECIMAL_DIG__=17",
"__VERSION__=\"14.2.0\"",
"__UINT64_C(c)=c ## ULL",
"__XCHAL_NUM_AREGS=64",
"__cpp_unicode_characters=201411L",
"__XCHAL_HAVE_XEA3=0",
"__GCC_ATOMIC_INT_LOCK_FREE=2",
"__XCHAL_HAVE_DENSITY=1",
"__FLT32_MANT_DIG__=24",
"__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__",
"__XCHAL_HAVE_CLAMPS=0",
"__XCHAL_HAVE_DFP_RSQRT=0",
"__cpp_aggregate_bases=201603L",
"__XCHAL_HAVE_NSA=1",
"__XCHAL_HAVE_WINDOWED=1",
"__SCHAR_WIDTH__=8",
"__INT32_C(c)=c ## L",
"__ORDER_PDP_ENDIAN__=3412",
"__INT_FAST32_TYPE__=int",
"__UINT_LEAST16_TYPE__=short unsigned int",
"__DBL_HAS_DENORM__=1",
"__XCHAL_HAVE_DEBUG=1",
"__cpp_rtti=199711L",
"__SIZE_TYPE__=unsigned int",
"__UINT64_MAX__=0xffffffffffffffffULL",
"__FLT_IS_IEC_60559__=1",
"__GNUC_WIDE_EXECUTION_CHARSET_NAME=\"UTF-16LE\"",
"__INT8_TYPE__=signed char",
"__cpp_digit_separators=201309L",
"__ELF__=1",
"__XSHAL_ABI=0",
"__xtensa__=1",
"__FLT_RADIX__=2",
"__INT_LEAST16_TYPE__=short int",
"__LDBL_EPSILON__=2.2204460492503131e-16L",
"__UINTMAX_C(c)=c ## ULL",
"__FLT32X_MIN__=2.2250738585072014e-308F32x",
"__XCHAL_HAVE_DFP_SQRT=0",
"__SIG_ATOMIC_MAX__=0x7fffffff",
"__XCHAL_HAVE_MAC16=1",
"__GCC_ATOMIC_WCHAR_T_LOCK_FREE=2",
"__USER_LABEL_PREFIX__",
"__SIZEOF_PTRDIFF_T__=4",
"__XCHAL_MMU_MIN_PTE_PAGE_SIZE=1",
"__XCHAL_DCACHE_IS_WRITEBACK=0",
"__SIZEOF_LONG__=4",
"__LDBL_DIG__=15",
"__FLT64_IS_IEC_60559__=1",
"__XCHAL_MAX_INSTRUCTION_SIZE=3",
"__FLT32X_MIN_EXP__=(-1021)",
"__INT_FAST16_MAX__=0x7fffffff",
"__GCC_CONSTRUCTIVE_SIZE=32",
"__FLT64_DIG__=15",
"__UINT_FAST32_MAX__=0xffffffffU",
"__UINT_LEAST64_TYPE__=long long unsigned int",
"__FLT_HAS_QUIET_NAN__=1",
"__FLT_MAX_10_EXP__=38",
"__FLT_HAS_INFINITY__=1",
"__GNUC_EXECUTION_CHARSET_NAME=\"UTF-8\"",
"__CHAR_UNSIGNED__=1",
"__cpp_unicode_literals=200710L",
"__UINT_FAST16_TYPE__=unsigned int",
"__INT_FAST32_WIDTH__=32",
"__CHAR16_TYPE__=short unsigned int",
"__PRAGMA_REDEFINE_EXTNAME=1",
"__SIZE_WIDTH__=32",
"__INT_LEAST16_MAX__=0x7fff",
"__INT64_MAX__=0x7fffffffffffffffLL",
"__FLT32_DENORM_MIN__=1.4012984643248171e-45F32",
"__SIG_ATOMIC_WIDTH__=32",
"__INT_LEAST64_TYPE__=long long int",
"__INT16_TYPE__=short int",
"__INT_LEAST8_TYPE__=signed char",
"__cpp_structured_bindings=201606L",
"__INT_FAST8_MAX__=0x7fffffff",
"__INTPTR_MAX__=0x7fffffff",
"__cpp_sized_deallocation=201309L",
"__cpp_guaranteed_copy_elision=201606L",
"__FLT64_HAS_QUIET_NAN__=1",
"__FLT32_MIN_10_EXP__=(-37)",
"__EXCEPTIONS=1",
"__UINT16_C(c)=c",
"__XCHAL_M_STAGE=3",
"__PTRDIFF_WIDTH__=32",
"__LDBL_MANT_DIG__=53",
"__cpp_range_based_for=201603L",
"__FLT64_HAS_INFINITY__=1",
"__STDCPP_DEFAULT_NEW_ALIGNMENT__=8",
"__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)",
"__XCHAL_ICACHE_SIZE=0",
"__cpp_nontype_template_args=201411L",
"__INTPTR_TYPE__=int",
"__UINT16_TYPE__=short unsigned int",
"__WCHAR_TYPE__=short unsigned int",
"__XCHAL_HAVE_DEPBITS=0",
"__SIZEOF_FLOAT__=4",
"__UINTPTR_MAX__=0xffffffffU",
"__INT_FAST64_WIDTH__=64",
"__cpp_decltype=200707L",
"__FLT32_DECIMAL_DIG__=9",
"__INT_FAST64_MAX__=0x7fffffffffffffffLL",
"__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1",
"__FLT_NORM_MAX__=3.4028234663852886e+38F",
"__XCHAL_HAVE_DFP=0",
"__FLT32_HAS_INFINITY__=1",
"__UINT_FAST64_TYPE__=long long unsigned int",
"__cpp_inline_variables=201606L",
"__INT_MAX__=0x7fffffff",
"__XCHAL_HAVE_EXCLUSIVE=0",
"__STDCPP_THREADS__=1",
"__INT64_TYPE__=long long int",
"__XCHAL_HAVE_DFP_DIV=0",
"__FLT_MAX_EXP__=128",
"__XCHAL_INST_FETCH_WIDTH=4",
"__DBL_MANT_DIG__=53",
"__cpp_inheriting_constructors=201511L",
"__INT_LEAST64_MAX__=0x7fffffffffffffffLL",
"__FP_FAST_FMAF32=1",
"__WINT_TYPE__=unsigned int",
"__UINT_LEAST32_TYPE__=long unsigned int",
"__SIZEOF_SHORT__=2",
"__FLT32_NORM_MAX__=3.4028234663852886e+38F32",
"__LDBL_MIN_EXP__=(-1021)",
"__XCHAL_HAVE_S32C1I=1",
"__FLT64_MAX__=1.7976931348623157e+308F64",
"__WINT_WIDTH__=32",
"__cpp_template_auto=201606L",
"__INT_LEAST64_WIDTH__=64",
"__FLT32X_MAX_10_EXP__=308",
"__cpp_namespace_attributes=201411L",
"__WCHAR_UNSIGNED__=1",
"__LDBL_MAX_10_EXP__=308",
"__ATOMIC_RELAXED=0",
"__DBL_EPSILON__=double(2.2204460492503131e-16L)",
"__XCHAL_HAVE_SEXT=1",
"__INT_LEAST32_TYPE__=long int",
"__XTENSA_WINDOWED_ABI__=1",
"__UINT8_C(c)=c",
"__FLT64_MAX_EXP__=1024",
"__SIZEOF_WCHAR_T__=2",
"__XCHAL_HAVE_FP_POSTINC=1",
"__FLT64_NORM_MAX__=1.7976931348623157e+308F64",
"__INTMAX_MAX__=0x7fffffffffffffffLL",
"__INT_FAST8_TYPE__=int",
"__XCHAL_HAVE_MUL32_HIGH=1",
"__GNUC_STDC_INLINE__=1",
"__FLT64_HAS_DENORM__=1",
"__FLT32_EPSILON__=1.1920928955078125e-7F32",
"__DBL_DECIMAL_DIG__=17",
"__STDC_UTF_32__=1",
"__XCHAL_HAVE_FP_DIV=1",
"__INT_FAST8_WIDTH__=32",
"__FLT32X_MAX__=1.7976931348623157e+308F32x",
"__DBL_NORM_MAX__=double(1.7976931348623157e+308L)",
"__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__",
"__GCC_DESTRUCTIVE_SIZE=32",
"__XTENSA__=1",
"__INTMAX_WIDTH__=64",
"__ORDER_BIG_ENDIAN__=4321",
"__XTHAL_ABI_CALL0=1",
"__cpp_runtime_arrays=198712L",
"__FLT32_DIG__=6",
"__UINT64_TYPE__=long long unsigned int",
"__UINT32_C(c)=c ## UL",
"__cpp_alias_templates=200704L",
"__FLT_DENORM_MIN__=1.4012984643248171e-45F",
"__INT8_MAX__=0x7f",
"__LONG_WIDTH__=32",
"__UINT_FAST32_TYPE__=unsigned int",
"__FLT32X_NORM_MAX__=1.7976931348623157e+308F32x",
"__CHAR32_TYPE__=long unsigned int",
"__FLT_MAX__=3.4028234663852886e+38F",
"__cpp_constexpr=201603L",
"__XCHAL_HAVE_FP_RSQRT=1",
"__INT32_TYPE__=long int",
"__SIZEOF_DOUBLE__=8",
"__cpp_exceptions=199711L",
"__FLT_MIN_10_EXP__=(-37)",
"__FLT64_MIN__=2.2250738585072014e-308F64",
"__INT_LEAST32_WIDTH__=32",
"__INTMAX_TYPE__=long long int",
"__XCHAL_HAVE_ABS=1",
"__FLT32X_HAS_QUIET_NAN__=1",
"__ATOMIC_CONSUME=1",
"__XCHAL_NUM_DBREAK=2",
"__XCHAL_HAVE_WIDE_BRANCHES=0",
"__GNUC_MINOR__=2",
"__INT_FAST16_WIDTH__=32",
"__UINTMAX_MAX__=0xffffffffffffffffULL",
"__FLT32X_DENORM_MIN__=4.9406564584124654e-324F32x",
"__cpp_template_template_args=201611L",
"__DBL_MAX_10_EXP__=308",
"__LDBL_DENORM_MIN__=4.9406564584124654e-324L",
"__INT16_C(c)=c",
"__STDC__=1",
"__PTRDIFF_TYPE__=int",
"__LONG_MAX__=0x7fffffffL",
"__XCHAL_HAVE_FP_SQRT=1",
"__UINT32_TYPE__=long unsigned int",
"__FLT32X_MIN_10_EXP__=(-307)",
"__UINTPTR_TYPE__=unsigned int",
"__LDBL_MIN_10_EXP__=(-307)",
"__cpp_generic_lambdas=201304L",
"__SIZEOF_LONG_LONG__=8",
"__cpp_user_defined_literals=200809L",
"__GCC_ATOMIC_LLONG_LOCK_FREE=1",
"__FLT_DECIMAL_DIG__=9",
"__UINT_FAST16_MAX__=0xffffffffU",
"__LDBL_NORM_MAX__=1.7976931348623157e+308L",
"__GCC_ATOMIC_SHORT_LOCK_FREE=2",
"__XCHAL_HAVE_BE=0",
"__UINT_FAST8_TYPE__=unsigned int",
"__cpp_init_captures=201304L",
"__ATOMIC_ACQ_REL=4",
"__ATOMIC_RELEASE=3",
"USBCON"
]
}
]
}

76
README.md Normal file
View File

@ -0,0 +1,76 @@
# Smart Fish Feeder (ESP32 + MQTT)
An automated aquarium feeder system based on the ESP32. It dispenses food via a motor pulse triggered by Home Assistant and continuously monitors tank temperature.
## ⚡ Features
* **Remote Feeding:** Trigger a measured feed pulse via MQTT (`tank/feed`).
* **Temperature Monitoring:** Reports water temp every 10 seconds via MQTT (`tank/temperature`).
* **Home Assistant Integration:** Fully compatible with HA Dashboards and Automation.
* **Safe Power Design:** Optically isolated power rails (ESP32 vs Motor) to prevent brownouts.
## 🛠 Hardware List
* **Microcontroller:** ESP32-D0WD-V3 (DevKitC)
* **Actuator:** DC Motor (3V-6V) with auger/screw mechanism
* **Switching:** N-Channel MOSFET (IRFZ44N)
* **Sensor:** DS18B20 Waterproof Temperature Sensor
* **Protection:**
* 1N5822 Schottky Diode (Flyback protection)
* 10kΩ Pull-down Resistor (Gate to GND)
* **Power:**
* USB-C (5V) for ESP32
* External 5V/12V DC Adapter for Motor
## 🔌 Wiring & Pinout
**⚠️ CRITICAL:** The ESP32 and Motor Power Supply must share a **Common Ground**, but 5V lines should remain separate to prevent noise/brownouts.
### GPIO Config
| Component | Pin | ESP32 GPIO | Notes |
| :--- | :--- | :--- | :--- |
| **MOSFET Gate** | Left Leg | **GPIO 27** | Use 10kΩ Pull-down to GND |
| **Temp Data** | Yellow Wire | **GPIO 14** | Requires 4.7kΩ Pull-up (if not on module) |
### Circuit Diagram (MOSFET)
* **Gate (Left):** -> GPIO 27
* **Drain (Middle):** -> Motor Negative (-)
* **Source (Right):** -> Common GND
* **Motor (+):** -> External Power 5V
* **Diode:** Across Motor Terminals (Silver stripe to +5V)
## 💻 Firmware Configuration
**Dependencies (Arduino IDE):**
* `PubSubClient` (Nick O'Leary)
* `OneWire`
* `DallasTemperature`
**Setup:**
1. Update `ssid`, `pass`, and `mqtt_server` in `fish_feeder.ino`.
2. Set `MOTOR_PIN` (Default: 27) and `TEMP_PIN` (Default: 14).
3. Upload.
## 🏠 Home Assistant Integration
### 1. Manual Configuration (YAML)
Add to `configuration.yaml` to create entities:
```yaml
mqtt:
sensor:
- name: "Fish Tank Temperature"
state_topic: "tank/temperature"
unit_of_measurement: "°C"
device_class: temperature
unique_id: "fishtank_temp_01"
button:
- name: "Feed Fish"
command_topic: "tank/feed"
payload_press: "pulse"
icon: mdi:fish
unique_id: "fishtank_feed_btn"
```
### 2. Dashboard (Lovelace)
* **Temperature:** Use a `Gauge` card linked to `sensor.fish_tank_temperature`.
* **Feeder:**

126
fish_feeder.ino Normal file
View File

@ -0,0 +1,126 @@
// fish_feeder_final_fixed.ino
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// --- PIN DEFINITIONS ---
#define TEMP_PIN 14 // Signal wire from DS18B20
#define MOTOR_PIN 2 // Gate of MOSFET (Also the Blue LED)
// --- NETWORK SETTINGS ---
const char* ssid = "Aussie Broadband 8729";
const char* pass = "Ffdfmunfca";
const char* mqtt_server = "192.168.20.30";
WiFiClient net;
PubSubClient mqtt(net);
OneWire oneWire(TEMP_PIN);
DallasTemperature sensors(&oneWire);
void setup() {
Serial.begin(115200);
// 1. Setup Motor (Safety First)
pinMode(MOTOR_PIN, OUTPUT);
digitalWrite(MOTOR_PIN, LOW); // Ensure motor is OFF
// 2. Setup Sensor
sensors.begin();
sensors.setWaitForConversion(false);
Serial.println("--------------------------------");
Serial.println("🔌 System Start");
// 3. Connect WiFi
Serial.print("📶 Connecting to WiFi...");
WiFi.begin(ssid, pass);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
attempts++;
if(attempts > 20) {
Serial.println("\n❌ WiFi Failed! Check credentials.");
break;
}
}
if (WiFi.status() == WL_CONNECTED) {
Serial.printf("\n✅ WiFi Connected! IP: %s\n", WiFi.localIP().toString().c_str());
}
// 4. Setup MQTT
mqtt.setServer(mqtt_server, 1883);
mqtt.setCallback([](char* topic, byte* payload, unsigned int len) {
Serial.println("⚡ MQTT Message Received!");
triggerFeed(); // Run the feed function
});
Serial.println("✅ System Ready. Type 'pulse' in Serial Monitor to test.");
}
// Separate function to handle the motor logic
void triggerFeed() {
Serial.println("⚡ Feeding Fish...");
digitalWrite(MOTOR_PIN, HIGH);
delay(500); // Run motor for 0.5 seconds
digitalWrite(MOTOR_PIN, LOW);
Serial.println("✅ Feed Cycle Complete");
}
void loop() {
// 1. Maintain MQTT
if (WiFi.status() == WL_CONNECTED && !mqtt.connected()) {
if (mqtt.connect("fish-feeder", "mqtt-user", "sam4jo")) {
Serial.println("🔌 MQTT Reconnected");
mqtt.subscribe("tank/feed");
const char* discovery_topic = "homeassistant/sensor/fishtank_temp/config";
const char* payload =
"{"
"\"name\": \"Fish Tank Temp\","
"\"state_topic\": \"tank/temperature\","
"\"unit_of_measurement\": \"°C\","
"\"device_class\": \"temperature\","
"\"unique_id\": \"fishtank_temp_auto\""
"}";
// Publish with 'true' for Retain (so HA sees it even after restart)
mqtt.publish(discovery_topic, payload, true);
// ----------------------------------------------------
} else {
Serial.print("failed, rc=");
Serial.print(mqtt.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
mqtt.loop();
// 2. LISTEN FOR SERIAL COMMANDS (This was missing)
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim(); // Remove spaces/enter keys
if (cmd == "pulse") {
triggerFeed();
}
}
// 3. Temperature Logic
static unsigned long lastTemp = 0;
if (millis() - lastTemp > 60000) { // Every 10 seconds
sensors.requestTemperatures();
float t = sensors.getTempCByIndex(0);
Serial.printf("🌡️ Temp: %.2f°C\n", t);
if (mqtt.connected() && t > -100) {
char buf[10];
snprintf(buf, sizeof(buf), "%.2f", t);
mqtt.publish("tank/temperature", buf);
}
lastTemp = millis();
}
}