/* © 2023 Leen Nijim CC BY-NC 4.0 * * This code has been adapted from the following libraries: * https://www.arduino.cc/reference/en/libraries/servo/ * https://github.com/d03n3rfr1tz3/HC-SR04 * https://github.com/blackhack/LCD_I2C * https://wiki.seeedstudio.com/Grove-Water-Level-Sensor/ */ /* INCLUDES */ // level #include // lcd #include // ultrasound #include // servo #include /*****************************************************************************************/ /* DEFINES */ // level #define NO_TOUCH 0xFE #define THRESHOLD 100 #define ATTINY1_HIGH_ADDR 0x78 #define ATTINY2_LOW_ADDR 0x77 /*****************************************************************************************/ /* FUNCTION DECLARATIONS */ // level void getHigh12SectionValue(void); void getLow8SectionValue(void); uint8_t getWaterLevel(void); // potentiometer uint16_t getPoti(void); // servo void updateServo(void); // lcd void updateLcd(void); /*****************************************************************************************/ /* GLOBAL VARIABLES */ // level uint8_t low_data[8] = { 0 }; uint8_t high_data[12] = { 0 }; // lcd LCD_I2C lcd(0x27, 20, 4); // ultrasound uint8_t triggerPin = 11; uint8_t echoPin = 12; // potentiometer uint8_t potiPin = A0; // servo Servo myservo; uint8_t servoPin = 9; uint8_t servoPosPerc = 0; /*****************************************************************************************/ /* INIT */ void setup() { // level Serial.begin(115200); Wire.begin(); // lcd lcd.begin(false); // If you are using more I2C devices using the Wire library use lcd.begin(false). This stops the library(LCD_I2C) from calling Wire.begin() lcd.backlight(); // ultrsound HCSR04.begin(triggerPin, echoPin); // servo myservo.attach(servoPin); } /*****************************************************************************************/ /* MAIN */ void loop() { // level Serial.print("water level = "); Serial.print(getWaterLevel()); Serial.println("% "); Serial.println(" "); Serial.println("*********************************************************"); delay(100); // ultrasound double* distance = HCSR04.measureDistanceCm(); Serial.print(distance[0]); Serial.println(" cm"); // potentiometer Serial.print("poti: "); Serial.println(getPoti()); Serial.println(analogRead(potiPin)); // lcd // lcd.print(" Hello"); // You can make spaces using well... spaces // lcd.setCursor(5, 1); // Or setting the cursor in the desired position. // lcd.print("World!"); // delay(1000); // lcd.clear(); // delay(500); updateServo(); updateLcd(); delay(1000); } /*****************************************************************************************/ /* FUNCTIONS */ //level void getHigh12SectionValue(void) { memset(high_data, 0, sizeof(high_data)); Wire.requestFrom(ATTINY1_HIGH_ADDR, 12); while (12 != Wire.available()) ; for (int i = 0; i < 12; i++) { high_data[i] = Wire.read(); } delay(10); } void getLow8SectionValue(void) { memset(low_data, 0, sizeof(low_data)); Wire.requestFrom(ATTINY2_LOW_ADDR, 8); while (8 != Wire.available()) ; for (int i = 0; i < 8; i++) { low_data[i] = Wire.read(); // receive a byte as character } delay(10); } uint8_t getWaterLevel(void) { uint32_t touch_val = 0; uint8_t trig_section = 0; getLow8SectionValue(); getHigh12SectionValue(); for (int i = 0; i < 8; i++) { if (low_data[i] > THRESHOLD) { touch_val |= 1 << i; } } for (int i = 0; i < 12; i++) { if (high_data[i] > THRESHOLD) { touch_val |= (uint32_t)1 << (8 + i); } } while (touch_val & 0x01) { trig_section++; touch_val >>= 1; } return (trig_section * 5); } // ultrasound uint16_t getPressure(void) { uint16_t pressure; double* distance = HCSR04.measureDistanceCm(); if(distance[0] < 0) { pressure = 1; } else if(distance[0] < 5) { pressure = 100; } else if(distance[0] > 70) { pressure = 1; } else { pressure = (uint16_t)((70.0 - (float)distance[0])*100/70.0); } return pressure; } // potentiometer uint16_t getPoti(void) { uint16_t poti = analogRead(potiPin); poti = map(poti, 0, 1022, 100, 0); return poti; } // servo void updateServo(void) { servoPosPerc = 100 - getPressure(); uint8_t servoPos = map(servoPosPerc, 0, 100, 180, 0); myservo.write(servoPos); } // lcd void updateLcd(void) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("RAINWATER LEVEL:"); lcd.print(getWaterLevel()); lcd.print("cm"); lcd.setCursor(0, 1); lcd.print("WATER PRESSURE: "); lcd.print(getPressure()); lcd.print("%"); lcd.setCursor(0, 2); lcd.print("WATER FLOW RATE:"); lcd.print(getPoti()); lcd.print("%"); lcd.setCursor(0, 3); lcd.print("VALVE POSITION: "); lcd.print(servoPosPerc); lcd.print("%"); }