Arduino Polska Forum

Pełna wersja: Higrometr FC-28 - zawężony zakres wartości
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Chcę zrobić prosty pomiar wilgotności gleby za pomocą higrometru FC-28 i Arduino UNO.
Podłączyłem VCC - 5V, GND - GND, A0 - A0.
Program wygląda tak:
Kod:
int sensor_pin = A0;
int output_value ;

void setup() {
 Serial.begin(9600);
 Serial.println("Odczyt z czujnika ...");
 delay(2000);
 }

void loop() {

 output_value= analogRead(sensor_pin);
 output_value = map(output_value,812,224,0,100);
 Serial.print("Wilgotność : ");
 Serial.print(output_value);
 Serial.println("%");
 delay(1000);
 }

Wszystko działa, wartość 812 jest dla gleby suchej, 224 dla gleby mokrej, zalanej wodą.
Po włożeniu czujnika w ziemię zakres w procentach mieści się pomiędzy 0-100% natomiast np. po wyjęciu czujnika z ziemi pokazuje się w monitorze szeregowym wartość na poziomie -35%, oczywiście po włożeniu czujnika do wody wartość przekracza 100%. Chciałbym aby wartości mieściły się w zakresie 0-100 w każdych okolicznościach ale chyba zrobienie tego za pomocą zmiany wartości output_value będzie złym pomysłem, bo wtedy wilgotna gleba (obecnie około 60%) będzie wyświetlana jako około 30%, chyba, że źle rozumiem zasadę działania czujnika i muszę podać cały zakres wartości, który mierzy się gdy czujnik jest wyjęty z gleby oraz włożony do wody, wtedy będzie pełen zakres.

Jeżeli powyższe rozumowanie jest błędne i należy zrobić tak jak jest obecnie to trzeba byłoby zrobić aby wartości nie przekraczały 0-100%. Próbowałem zrobić to korzystając z if:
Kod:
 if (output_value > 812) { //Jeśli obliczona wartość jest większa od 812
   output_value = 812; //to ustaw ją na 812 (0% wilgotności)
 }
 if (output_value < 224) { //Jeśli obliczona odległość jest mniejsza od 224
   output_value = 224; //to ustaw ją na 224 (100% wilgotności)
 }
Niestety to nie działa, zmiana znaków >/< nic nie daje, po dodaniu tych linijek przed:
Kod:
Serial.print("Wilgotność : ");
 Serial.print(output_value);
 Serial.println("%");
 delay(1000);
 }
Powoduje, że na monitorze wyświetla się ciągle 224% i w żadnej sytuacji się to nie zmienia.
Może źle interpretujesz pojęcie wilgotności gleby?
Tak dla przypomnienia, nie ma to nic wspólnego z obliczaniem wilgotności powietrza (oprócz nazwy). Nie da się nasycić gleby wodą. Wilgotność wagowa gleby, to stosunek wagowy wody do suchej gleby (wysuszonej w temperaturze 105°).
Jest jeszcze wilgotność objętościowa (sam sobie wydedukuj skąd taka nazwa), oraz stopień wilgotności gleby, który określa jak bardzo zalane są puste przestrzenie pomiędzy stałymi okruchami gleby.
W dwu pierwszych przypadkach wilgotność może przekraczać 100% i to grubo przekraczać.
Zastanów się więc co tak naprawdę mierzysz i dla czego mieszanina błota ma inną przewodność od czystej wody, a sucha gleba inną od powietrza.
Pewnie mu chodzi tylko to by to co on uznaje za w pełni podlane i w pełni suche dawało wyniki w granicach 0-100%.
Na początek pamiętaj, by czujnik zasilać tylko na czas pomiaru, nieco wydłużysz mu życie, nóżki szybko ulegają elektrolizie. Ewentualnie szukaj pojemnościowych, są odizolowane od gleby lakierem.
Co do konwersji zamieniasz max z min i może tu jest problem, nie mam czym dzisiaj przetestować tej funkcji, ale w przykładowym szkicu są takie funkcje:

Kod:
 sensorValue = analogRead(sensorPin);

 // apply the calibration to the sensor reading
 sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);

 // in case the sensor value is outside the range seen during calibration
 sensorValue = constrain(sensorValue, 0, 255);

 // fade the LED using the calibrated value:
 analogWrite(ledPin, sensorValue);
Tu jest jednak pokazane, że podajesz w kolejności min i max. Jak chcesz to odwrócić to wystarczy wstawić 
 output_value = map(1023-output_value,224,812,0,100);
Podmiana z ifami też powinna działać ograniczając odczyty od 224 do 812, może co pomieszałeś w kodzie testowym.
Bardzo łatwo też przetestujesz wszystkie możliwe wartości podstawiając swoją zmienną x 0-1023 w pętli while czy for, drukując wyniki na serial i potem pętla while(1) by spokojnie obejrzeć wyniki.
Tak, chodziło o to co dla mnie oznacza 0-100% ale jeżeli wiedziałbym jak zrobić program, który rzeczywiście pokazałby prawidłowo wilgotność gleby to bardzo chętnie z niego skorzystam. Nie wiem jak to zrobić prawidłowo.
Zmierzyłem suchą ziemię i wartość jaką odczytałem to 812, zalałem ją wodą i po chwili wartość jaką odczytałem to 224. Obecnie gdy czujnik jest poza glebą pokazuje mi wartość -35% dlatego chciałbym aby poniżej 0 nie pokazywało jak również gdy włożę czujnik do samej wody jest ponad 100%.

Opcja
Kod:
output_value = map(1023-output_value,224,812,0,100);
nie pomogła, cały czas wartość na - pokazuje gdy czujnik jest w powietrzu.

Nie wiem jaka częstotliwość pomiaru jest wystarczająca. Teoretycznie gdybym chciał w przyszłości dodać jakąś pompkę do podlewania, wtedy reakcja musi być szybka, ale już dalsze odświeżanie nie musi być takie szybkie. Niestety tutaj będzie problem w moim przypadku z napisaniem takiego programu.

Dostosowałem taki kod:
Kod:
  //////////////////////////////////////////////
 //        ARDUINO SOIL MOISTURE DEMO        //
//                                          //
//           http://www.educ8s.tv           //
/////////////////////////////////////////////



int sensorPin = A0;  
int sensorValue = 0;  
int percent = 0;

void setup() {
 Serial.begin(9600);
 Serial.println("Odczyt z czujnika ...");
 delay(2000);
}

void loop() {
 
 sensorValue = analogRead(sensorPin);
 percent = convertToPercent(sensorValue);
 printValuesToSerial();
 delay(1000);
}

int convertToPercent(int value)
{
 int percentValue = 0;
 percentValue = map(value, 1023, 465, 0, 100);
 return percentValue;
}

void printValuesToSerial()
{
 Serial.print("\n\nWartość analogowa: ");
 Serial.print(sensorValue);
 Serial.print("\nWilgotność: ");
 Serial.print(percent);
 Serial.print("%");
}
Teoretycznie jest lepiej, poniżej 0 nie schodzi ale po włożeniu do wody ponad 135%. Gdy ustawię zamiast 465 niższą wartość wtedy zmienia się zakres (w wodzie czujnik pokazuje minimalnie około 299). Nie wiem jak prawidłowo to skalibrować aby właśnie ta wilgotność miała coś wspólnego z rzeczywistością. A z ograniczeniem wyświetlania wartości póki co nie udało się poradzić.

Dodałem:
Kod:
if (percent < 100) { //Jeśli obliczona wilgotność jest większa od 100%
  percent = 100; //to ustaw ją na 100% wilgotności
}
Niestety żadnej zmiany.
W nowym kodzie nie schodzi Ci do 0 bo rozciągnąłeś wartości do max wartości odczytywanej z ADC, jak zamiast 465 wstawisz 0 to też nie będziesz przekraczał 100%. Po prostu sprawdź sobie jak chciałeś na początku czy jest mniejszy/większy i ustaw do wartości granicznych.
Wystarczyło zrobić prostą pętlę i możesz sobie przetestować wszystkie wartości, masz nowe ustalenia to zmodyfikuj. To daje wartości od 0 -100:
Kod:
void setup() {
 // put your setup code here, to run once:
 Serial.begin(115200);
 for(int i=0;i<1024;i++)
 {
int testowana=i;
 if (testowana<224) testowana =224;
 if (testowana>812) testowana =812;
 

Serial.println(map(testowana, 812, 224, 0, 100) );  
 }

}

void loop() {
 // put your main code here, to run repeatedly:
 

}
Myślałem, że może map nie trawi odwrócenia wartości i stąd to 1023-ADC, ale jest OK.
Tego nie skalibrujesz to jest tylko do nauki...

To nic innego jak dwie elektrody wbite w ziemię i jest odczytywane przejście napięcia wiec żeby skalibrować trzeba uwzględnić glebę , wodę , i długość średnica elektrod. Każda zmiana któregoś składnika powoduje rozkalibrowanie.

Wysusz glebę docelową w doniczce i ustaw jako "0%" podlej docelowa wodą na maxa i ustaw na "100%" Żadne sprawdzanie z szklanką wody albo po wyciągnięciu. Powietrze ma inną rezystancję niż sucha ziemia tak samo mokra ziemia ma inna rezystancję od samej wody..
(06-05-2019, 22:45)Jarewa0606 napisał(a): [ -> ]Tego nie skalibrujesz to jest tylko do nauki...

To nic innego jak dwie elektrody wbite w ziemię  i jest odczytywane przejście napięcia wiec żeby skalibrować trzeba uwzględnić glebę , wodę , i długość średnica elektrod. Każda zmiana któregoś składnika powoduje rozkalibrowanie.

Wysusz glebę docelową  w doniczce i ustaw jako "0%" podlej docelowa wodą na maxa i ustaw na "100%"  Żadne sprawdzanie z szklanką wody albo po wyciągnięciu.  Powietrze ma inną rezystancję niż sucha ziemia  tak samo mokra ziemia ma inna rezystancję od samej wody..

Tak też zrobiłem ale czasami potrafi wyjść poza 0-100% dlatego chciałbym ograniczyć aby nie pokazywało wartości wyższych i niższych niż podany zakres ale w żadnej kombinacji if nie chce zadziałać...
(06-05-2019, 21:17)mrozilla napisał(a): [ -> ]Dodałem:
Kod:
if (percent < 100) { //Jeśli obliczona wilgotność jest większa od 100%
  percent = 100; //to ustaw ją na 100% wilgotności
}
Niestety żadnej zmiany.

Może dla tego, że jest to źle napisany warunek?
Nie ma takiej możliwości, że jeśli napiszesz poprawnie algorytm, to on nie zadziała.
(08-05-2019, 20:43)Robson Kerman napisał(a): [ -> ]
(06-05-2019, 21:17)mrozilla napisał(a): [ -> ]Dodałem:
Kod:
if (percent < 100) { //Jeśli obliczona wilgotność jest większa od 100%
  percent = 100; //to ustaw ją na 100% wilgotności
}
Niestety żadnej zmiany.

Może dla tego, że jest to źle napisany warunek?
Nie ma takiej możliwości, że jeśli napiszesz poprawnie algorytm, to on nie zadziała.

Domyślam się. W tym temacie zamieściłem kilka wersji tego warunku, żaden nie działa. Nie wiem gdzie robię błąd...
Próbowałeś chociaż na próbę wgrać przykład z #5? Jak to Ci nie zadziała pokazując znacznie więcej 0 i 100 niż pozostałych wartości (bo poza skalą są do nich obcięte) to znaczy, że wgrywasz szkice do płytki A, a program testujesz na B.