126 lines
3.5 KiB
C++
126 lines
3.5 KiB
C++
// 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();
|
|
}
|
|
} |