Hi everyone, I'm working on my project to build a water monitoring with hc-sr04 sensor and esp8266 as microcontroller. Everything is working fine with my code for giving the water level measurement, buzzer as warning sound and i created code to calculate percent value of the water level measurement which results are displayed on the 16x2 LCD, but i'm still confused n can't find a way to make code for showing my realtime data to the percentage widget on iot cloud because the sensor value on percentage widget stays zero/"--". Can anyone help me to figure out how to complete this code? or give me an insight so i can finish my project,
thx
#include <ESP8266WiFi.h>
#include <NewPing.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include "thingProperties.h"
#define triggerPin D6 // Pin D6 NodeMCU sebagai OUTPUT ke Trig Pin HC-SR04
#define echoPin D7 // Pin D7 NodeMCU sebagai INPUT dari Echo Pin HC-SR04
#define MAX_DISTANCE 36 // Maksimal jarak yang diukur berdasarkan ketinggian bak
#define MIN_DISTANCE 5
#define BUZZER D5 // Pin D3 BUZZER sebagai OUTPUT
hd44780_I2Cexp lcd;
long currentMillis, lastMillis; // Gunakan non blocking delay, millis()
const long interval = 1000; // Interval untuk menampilkan hasil pengukuran setiap 1000ms / 1 detik
NewPing sonar (triggerPin, echoPin, MAX_DISTANCE);// NewPing konstruk sonar
int percentage;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.backlight();
pinMode(D5, OUTPUT);
digitalWrite(D5, HIGH);
initProperties();
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
}
double getDistance() {
int distance = sonar.ping_cm();
return distance;
}
void loop() {
ArduinoCloud.update();
currentMillis = millis();
int distance = sonar.ping_cm();
if (distance <= 0) {
Serial.println("Out of range");
}
}
void onDistanceSensorChange() {
int distance = sonar.ping_cm();
float percentage = 100 - ((100 / 36) * (distance - 5)); // mendapatkan nilai persen dari jarak hasil pengukuran sensor
if (distance <= 0) {
percentage = 0;
} else if (distance > 36) {
percentage = 0;
}
if (currentMillis - lastMillis >= interval) { // tampilkan hasil pengukuran pada serial monitor setiap 1 detik
Serial.print("Jarak : ");
Serial.print(getDistance(), 1); // menampilkan 1 angka desimal
Serial.println("cm");
lastMillis = currentMillis;
}
Serial.print(getDistance());
Serial.println(percentage);
lcd.setCursor(0, 0);
lcd.print("JUMLAH AIR BAK 1");
lcd.setCursor(0, 1);
lcd.print(percentage);
lcd.print("% ");
delay(1000);
if (percentage < 40) { // Jika air pada bak kurang dari 40% maka buzzer akan menyala
digitalWrite(D5, LOW);
delay(50);
digitalWrite(D5, HIGH);
delay(50);
} else if (percentage > 100){ // Jika air pada bak lebih dari 100% maka buzzer akan mati
digitalWrite(D5, LOW);
delay(50);
digitalWrite(D5, HIGH);
delay(50);
}
}
Thanks for that. Unfortunately I'm not sure I can help you, because I don't understand myself what is going on!
I would expect that onDistanceSensorChange() function would get called only when the variable distanceSensor changes. This variable is never changed by your code, so I would expect that onDistanceSensorChange() would never be called.
However, you said that the LCD display is getting updated. The only place in your code where the LCD is updated is in the function onDistanceSensorChange(), so that must be getting called somehow. That's what I don't understand.
a parameter is given which is 1 second. So maybe onDistanceSensorChange() gets called every second even if the value of distanceSensor has not changed.
What I suggest is to add this line at the end of onDistanceSensorChange() (meaning just before the final } of the function):
again i tried delete the code of distanceSensor = percentage; and make the measurement to 24cm
and the result changes once on value widget and the measurement as well
This leads me to the conclusion that the data/value on the widget will only change if there is a code change, while if there is a change in the measurement distance does not affect data changes.
And yeah this makes me even more confused
But I think my theory is correct, the widget will only update when your code changes the value of distanceSensor. This is the variable which the ArduinoIoTCloud.h or Arduino_ConnectionHandler.h library is monitoring. It will not monitor other variables in your code and will not react in any way when their values change.
No, I don't. There must be some documentation about the Arduino IoT cloud on the Arduino website somewhere, but I have not read it or used Arduino IoT cloud before.
@akbarafiq the onDistanceSensorChange callback is only called when you manually change the value from the dashboard or suring the connection phase of the board due to the sync event.
What i suggest you is to assign the value of the distanceSensor property inside you loop() function:
void loop() {
ArduinoCloud.update();
currentMillis = millis();
distanceSensor = sonar.ping_cm();
if (distanceSensor <= 0) {
Serial.println("Out of range");
}
}
I've tried changing the formula a few days ago as your suggested, either because I'm stupid and a beginner like there's no difference and I haven't found the right formula
can you specifically show me the exact formula or fix the formula in loop() based on the code above as you suggested?
#include <Wire.h>
#include "thingProperties.h"
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#define triggerPin D6
#define echoPin D7
#define buzer D5
long duration, jarak;
int tinggi_wadah = 36;
int flag = 0;
hd44780_I2Cexp lcd;
void buz() {
for (int i = 0; i <= 1; i++){
digitalWrite(buzer, LOW);
delay(100);
digitalWrite(buzer, HIGH);
delay(100);
}
}
void waterFullMessage(){
lcd.setCursor(0, 1);
lcd.print("AIR PENUH");
}
void waterDropMessage() {
lcd.setCursor(0, 1);
lcd.print("AIR HABIS");
}
void clear_lcd(){
lcd.setCursor(0, 1);
lcd.print(" ");
}
void setup() {
// Initialize serial and wait for port to open:
Serial.begin(9600);
// This delay gives the chance to wait for a Serial Monitor without blocking if none is found
delay(1500);
lcd.begin(16, 2);
lcd.backlight();
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(buzer, OUTPUT);
initProperties();
ArduinoCloud.begin(ArduinoIoTPreferredConnection); // Connect to Arduino IoT Cloud
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
buz();
flag = 0;
}
void loop() {
ArduinoCloud.update();
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
duration = pulseIn(echoPin, HIGH);
jarak = (duration / 2) / 29.1;
tinggi = tinggi_wadah - jarak;
tinggi = map(tinggi, 0, 36, 0, 110);
Serial.println("Jarak :");
Serial.print(tinggi);
Serial.println(" cm");
lcd.setCursor(0, 0);
lcd.print(String() + "Tinggi:" + tinggi + " %" + " ");
if (tinggi <= 30) {
waterDropMessage();
buz();
}
else if (tinggi >= 90 && flag == 0) {
waterFullMessage();
digitalWrite(D5, LOW);
delay(100);
digitalWrite(D5, HIGH);
delay(100);
}
else if (tinggi <= 89) {
clear_lcd();
flag = 0;
}
else {
digitalWrite(buzer, HIGH);
}
delay(500);
}
void onTinggiChange() {
}
@pennam i've tried to assign the value inside the loop() then i changed the distance formula sonar.ping_cm with pulseIn and then i'm using map(). but actually I still want to use sonar.ping_cm instead of pulseIn but I don't know how to put it in the loop()
all of the code work for me, but i think there's some of lack in my code especially how to clear the lcd after send a waterdrop and waterfull message