Finally project is up and running
Finally project is up and running: đ Finally! Finally my water hose has arrived â I had to wait a long time to be able to continue. ⢠IoT ⢠pcb, lcd
đ Finally!
Finally my water hose has arrived â I had to wait a long time to be able to continue.
đż Mistakes (things that went sideways)
- While waiting, I kept the project in the living room on the sofa table. One of my cats ran through the wiring and disconnected most of the cables.
- I forgot to push the latest changes to my git repo. :(
đ§ Recovery & planning
I spent a couple of days recreating most of the build, making it catâsafe with glued-down wiring, and refining the final shape of the system.
đĄ Ultrasonic Sensor
At first I wanted to display a water percentage compared to what remains in the tank. After thinking it through, it feels better to simply display how many centimeters remain in the tank.
đť Firmware (Arduino)
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define TCAADDR 0x70 // TCA9548A Encoder address
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 columns, 2 rows
// Letters/messages
String Message_1 = "Mindre än 5%";
String Message_2 = "Mindre 20%";
String Message_3 = "Mindre än 75%";
String Message_4 = "Mer än 75%";
String Message_end = "Vatten i tank";
// Water tank pins
int trigPin = 9; // TRIG pin
int echoPin = 8; // ECHO pin
float duration_us, distance_cm;
/* -----( Custom Swedish characters )----- */
byte AwithRing[8] = { // ĂĽ
B00100, B01010, B01110, B00001, B01111, B10001, B01111,
};
byte AwithDots[8] = { // ä
B01010, B00000, B01110, B00001, B01111, B10001, B01111,
};
byte OwithDots[8] = { // Ăś
B01010, B00000, B01110, B10001, B10001, B10001, B01110,
};
byte BigAwithRing[8] = { // Ă
0b00100, 0b01010, 0b01110, 0b10001, 0b11111, 0b10001, 0b10001, 0b00000
};
byte BigAwithDots[8] = { // Ă
0b01010, 0b00000, 0b01110, 0b10001, 0b11111, 0b10001, 0b10001, 0b00000
};
byte BigOwithDots[8] = { // Ă
0b01010, 0b01110, 0b10001, 0b10001, 0b10001, 0b10001, 0b01110, 0b00000
};
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
// Tank pins
pinMode(trigPin, OUTPUT); // trigger pin as output
pinMode(echoPin, INPUT); // echo pin as input
}
void loop() {
// repeatedly render the small tank screen
screenSmallTank();
}
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
void screenSmallTank() {
String Message_1 = "Mindre än ---> ";
String Message_2 = "i Tank";
Wire.begin();
tcaselect(3);
lcd.begin(16, 4);
lcd.setCursor(1, 0);
lcd.createChar(1, AwithRing); // ĂĽ
lcd.createChar(2, AwithDots); // ä
lcd.createChar(3, OwithDots); // Ăś
lcd.createChar(4, BigAwithRing); // Ă
lcd.createChar(5, BigAwithDots); // Ă
lcd.createChar(6, BigOwithDots); // Ă
// generate 10 Âľs pulse to TRIG pin
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// measure duration of pulse from ECHO pin
duration_us = pulseIn(echoPin, HIGH);
// calculate the distance (speed of sound ~ 0.034 cm/Âľs -> divide by 2 for round-trip)
distance_cm = 0.017 * duration_us;
lcd.clear();
lcd.setCursor(1, 0); // first row
Message_1.replace("ä", "\2");
lcd.print(Message_1);
lcd.setCursor(1, 1); // second row
lcd.print(distance_cm);
lcd.print(" cm ");
lcd.print(Message_2);
delay(5000);
}đą Soil Moisture with Relay & Water Pumps
Iâve decided to treat each soilâmoisture + relay + pump as its own module. Each plant has unique properties, and Iâve seen inconsistent behavior when looping over objects, so Iâm prototyping perâplant handlers first.
đ§Ş Recent test snippet
// MAP
// Planta [0] Hylla hĂśger hĂśrn.
// Planta [1] Hylla vänster.
// Planta [2] Pinträd hÜger sida fÜnster.
// Planta [3] Hängande i gardinstüng i mitten.
// Planta [4] Ogräsplanta näst längst in till vänster.
// Planta [5] Ogräsplanta längst in vänster.
// Planta [6] Bonsai träd pü golv
// Planta [0]
#define SOIL_MOISTURE_0 A0 // Arduino pin that connects to AOUT pin of moisture sensor
// constants won't change
const int RELAY_1_PIN = A12; // Arduino pin that connects to relay IN
int SOIL_MOISTURE_0_THRESHOLD_DRY = 550;
int SOIL_MOISTURE_0_THRESHOLD_PERFECT = 450;
int SOIL_MOISTURE_0_THRESHOLD_WET = 390;
void setup() {
Serial.begin(9600);
// Plant [0]
pinMode(RELAY_1_PIN, OUTPUT);
pinMode(SOIL_MOISTURE_0, INPUT);
}
void loop() {
// Keep the water pump off by default
digitalWrite(RELAY_1_PIN, LOW); // turn off pump
delay(1000);
}
void PlantZero() {
Serial.print("Moisture: ");
int SOIL_MOISTURE_0_VALUE = analogRead(SOIL_MOISTURE_0);
if (SOIL_MOISTURE_0_VALUE > SOIL_MOISTURE_0_THRESHOLD_DRY) {
Serial.println(SOIL_MOISTURE_0_VALUE);
Serial.println("SOIL_MOISTURE_0 = DRY");
digitalWrite(RELAY_1_PIN, HIGH); // turn on pump 5 seconds
} else if (SOIL_MOISTURE_0_VALUE > SOIL_MOISTURE_0_THRESHOLD_WET &&
SOIL_MOISTURE_0_VALUE < SOIL_MOISTURE_0_THRESHOLD_PERFECT) {
Serial.println("SOIL_MOISTURE_0 = PERFECT");
digitalWrite(RELAY_1_PIN, LOW); // turn off pump
} else if (SOIL_MOISTURE_0_VALUE < SOIL_MOISTURE_0_THRESHOLD_WET) {
Serial.println("SOIL_MOISTURE_0 = WET");
digitalWrite(RELAY_1_PIN, LOW); // turn off pump
}
}