Hello there! I'm making a weather station that reads air temperature, soil temperature, air humidity, CO2 levels, soil humidity and amount of rain, while using a datalogger shield.
Ive managed to make all the sensors work together, but the pluviometer. I believe that its a code problem, id be so glad if you could help me! Thank you!
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <DHT.h>
#define DHTPIN 7
#define DS18B20 8
OneWire ourWire(DS18B20);
DallasTemperature sensors(&ourWire);
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#define anInput A0 //analog feed from MQ135
#define digTrigger 2 //digital feed from MQ135
#define co2Zero 11 //calibrated CO2 0 level
int chk;
float hum;
float temp;
int chipSelect = 53;
File mySensorData;
const int REED = 9; //The reed switch outputs to digital pin 9
int val = 0; //Current value of reed switch
int old_val = 0; //Old value of reed switch
int REEDCOUNT = 0;
String time ;
tmElements_t tm;
String Now(){
String time = "";
if (RTC.read(tm)) {
//time = String(tm.Hour+":"+tm.Minute+":"+tm.Secnd+" DAY : "+tm.Day+"/"+tm.Month+"/"+tmYearToCalendar(tm.Year));
time+=tm.Hour;
time+=":";
time+=tm.Minute;
time+=":";
time+=tm.Second;
time+=" DIA:";
time+=tm.Day;
time+="/";
time+=tm.Month;
time+="/";
time+=tmYearToCalendar(tm.Year);
}
else {
time = "NO";
if (RTC.chipPresent()) {
Serial.println("The DS1307 is stopped. Please run the SetTime");
Serial.println("example to initialize the time and begin running.");
Serial.println();
}
else {
Serial.println("DS1307 read error! Please check the circuitry.");
Serial.println();
}
}
return time;
}
void setup()
{
Serial.begin(9600);
pinMode (REED, INPUT_PULLUP); //This activates the internal pull up resistor
sensors.begin();
dht.begin();
pinMode(anInput,INPUT); //MQ135 analog feed set for input
pinMode(digTrigger,INPUT); //MQ135 digital feed set for input
pinMode(53, OUTPUT);
SD.begin(chipSelect);
digitalWrite(9,HIGH);
}
void loop()
{
mySensorData= SD.open("test.txt", FILE_WRITE);
if (mySensorData) {
time = Now()+" Sensor Values: ";
Serial.println(time);
val = digitalRead(REED); //Read the status of the Reed swtich
hum = dht.readHumidity();
temp= dht.readTemperature();
Serial.print("Humidade do Ar: ");
Serial.print(hum);
Serial.print("%, Temperatura do Ar: ");
Serial.print(temp);
Serial.println("ºC");
sensors.requestTemperatures();//SOLICITA QUE A FUNÇÃO INFORME A TEMPERATURA DO SENSOR
Serial.print("Temperatura do Solo: "); //IMPRIME O TEXTO NA SERIAL
Serial.print(sensors.getTempCByIndex(0)); //IMPRIME NA SERIAL O VALOR DE TEMPERATURA MEDIDO
Serial.println("ºC"); //IMPRIME O TEXTO NA SERIAL
int co2now[10]; //int array for co2 readings
int co2raw = 0; //int for raw value of co2
int co2comp = 0; //int for compensated co2
int co2ppm = 0; //int for calculated ppm
int zzz = 0; //int for averaging
for (int x = 0;x<10;x++){ //sample co2 10x over 2 seconds
co2now[x]=analogRead(A0);
}
for (int x = 0;x<10;x++){ //add samples together
zzz=zzz + co2now[x];
}
co2raw = zzz/10; //divide samples by 10
co2comp = co2raw - co2Zero; //get compensated value
co2ppm = map(co2comp,0,1023,400,5000); //map value for atmospheric levels
Serial.print("CO2 Level: "); //print title
Serial.print(co2ppm); //print co2 ppm
Serial.println(" PPM"); //print units
mySensorData.print(time);
mySensorData.print(temp);
mySensorData.print(", ");
mySensorData.print(hum);
mySensorData.print(", ");
mySensorData.print(sensors.getTempCByIndex(0));
mySensorData.print(", ");
mySensorData.println(co2ppm);
mySensorData.close();
delay(5000);
{
if ((val == LOW) && (old_val == HIGH)){ //Check to see if the status has changed
delay(10); // Delay put in to deal with any "bouncing" in the switch.
REEDCOUNT = REEDCOUNT + 1; //Add 1 to the count of bucket tips
old_val = val; //Make the old value equal to the current value
Serial.print(time);
Serial.print("Medida de chuva (contagem): ");
Serial.print(REEDCOUNT);//*0.2794);
Serial.println(" pulso");
Serial.print("Medida de chuva (calculado): ");
Serial.print(REEDCOUNT*0.25);
Serial.println(" mm");
}
else {
old_val = val; //If the status hasn't changed then do nothing
}
}
}
}
First of all: edit your post and insert code tags!
Post a link to your pluviometer!
My guess is that you don't get the changes on the reed contact because your other sensors need too much time to read. You either have to restructure the code to read that input pin much more often or use an interrupt to count those changes. But depending on the construction of the meter this might not be necessary, most cheap rain gauges only give a short pulse so you need that.
The forum software has made a bit of a mess of your improperly posted code. Read the forum guidelines to see how to post code. Please use the IDE autoformat tool (ctrl-t or Tools, Auto Format) before posting code.
Have you written a small program that reads the pluviometer, only, to make sure that it works in isolation?
My rain gauge uses an interrupt so as not to miss pulses.
pylon:
First of all: edit your post and insert code tags!
Post a link to your pluviometer!
My guess is that you don't get the changes on the reed contact because your other sensors need too much time to read. You either have to restructure the code to read that input pin much more often or use an interrupt to count those changes. But depending on the construction of the meter this might not be necessary, most cheap rain gauges only give a short pulse so you need that.
.
Tried to do an interrupt but came out with nothing :u
#include <DS1307RTC.h>
#include <Time.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <DHT.h>
#define DHTPIN 7
#define DS18B20 8
OneWire ourWire(DS18B20);
DallasTemperature sensors(&ourWire);
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#define anInput A0 //analog feed from MQ135
#define digTrigger 2 //digital feed from MQ135
#define co2Zero 11 //calibrated CO2 0 level
int chk;
float hum;
float temp;
int chipSelect = 53;
File mySensorData;
const int REED = 3; //The reed switch outputs to digital pin 9
long int val = 0; //Current value of reed switch
long int old_val = 0; //Old value of reed switch
long int REEDCOUNT = 0;
String time ;
tmElements_t tm;
void chovendoPluvi();
String Now(){
String time = "";
if (RTC.read(tm)) {
//time = String(tm.Hour+":"+tm.Minute+":"+tm.Secnd+" DAY : "+tm.Day+"/"+tm.Month+"/"+tmYearToCalendar(tm.Year));
time+=tm.Hour;
time+=":";
time+=tm.Minute;
time+=":";
time+=tm.Second;
time+=" DIA:";
time+=tm.Day;
time+="/";
time+=tm.Month;
time+="/";
time+=tmYearToCalendar(tm.Year);
}
else {
time = "NO";
if (RTC.chipPresent()) {
Serial.println("The DS1307 is stopped. Please run the SetTime");
Serial.println("example to initialize the time and begin running.");
Serial.println();
}
else {
Serial.println("DS1307 read error! Please check the circuitry.");
Serial.println();
}
}
return time;
}
void setup()
{
Serial.begin(9600);
pinMode (REED, INPUT_PULLUP); //This activates the internal pull up resistor
sensors.begin();
dht.begin();
pinMode(anInput,INPUT); //MQ135 analog feed set for input
pinMode(digTrigger,INPUT); //MQ135 digital feed set for input
pinMode(53, OUTPUT);
SD.begin(chipSelect);
digitalWrite(3,HIGH);
attachInterrupt(digitalPinToInterrupt(REED), chovendoPluvi, CHANGE);
}
void loop()
{
mySensorData= SD.open("test.txt", FILE_WRITE);
if (mySensorData) {
time = Now()+": ";
Serial.println(time);
val = digitalRead(REED); //Read the status of the Reed swtich
hum = dht.readHumidity();
temp= dht.readTemperature();
Serial.print("Humidade do Ar: ");
Serial.print(hum);
Serial.print("%, Temperatura do Ar: ");
Serial.print(temp);
Serial.println("ºC");
sensors.requestTemperatures();//SOLICITA QUE A FUNÇÃO INFORME A TEMPERATURA DO SENSOR
Serial.print("Temperatura do Solo: "); //IMPRIME O TEXTO NA SERIAL
Serial.print(sensors.getTempCByIndex(0)); //IMPRIME NA SERIAL O VALOR DE TEMPERATURA MEDIDO
Serial.println("ºC"); //IMPRIME O TEXTO NA SERIAL
int co2now[10]; //int array for co2 readings
int co2raw = 0; //int for raw value of co2
int co2comp = 0; //int for compensated co2
int co2ppm = 0; //int for calculated ppm
int zzz = 0; //int for averaging
for (int x = 0;x<10;x++){ //sample co2 10x over 2 seconds
co2now[x]=analogRead(A0);
}
for (int x = 0;x<10;x++){ //add samples together
zzz=zzz + co2now[x];
}
co2raw = zzz/10; //divide samples by 10
co2comp = co2raw - co2Zero; //get compensated value
co2ppm = map(co2comp,0,1023,400,5000); //map value for atmospheric levels
Serial.print("CO2 Level: "); //print title
Serial.print(co2ppm); //print co2 ppm
Serial.println(" PPM"); //print units
mySensorData.print(time);
mySensorData.print(temp);
mySensorData.print(", ");
mySensorData.print(hum);
mySensorData.print(", ");
mySensorData.print(sensors.getTempCByIndex(0));
mySensorData.print(", ");
mySensorData.println(co2ppm);
mySensorData.close();
delay(5000);
}
}
void chovendoPluvi() {
if ((val == LOW) && (old_val == HIGH)){ //Check to see if the status has changed
delay(10); // Delay put in to deal with any "bouncing" in the switch.
REEDCOUNT = REEDCOUNT + 1; //Add 1 to the count of bucket tips
old_val = val; //Make the old value equal to the current value
Serial.print(time);
Serial.print("Medida de chuva (contagem): ");
Serial.print(REEDCOUNT);//*0.2794);
Serial.println(" pulso");
Serial.print("Medida de chuva (calculado): ");
Serial.print(REEDCOUNT*0.25);
Serial.println(" mm");
}
else {
old_val = val; //If the status hasn't changed then do nothing
}
}
In an interrupt handler you must not use the Serial object or any other function the depends on interrupts (as interrupts are disabled inside interrupt handlers) such as delay().
You don't need to check the old value as the interrupt will only fire if there was a change in the signal state. So remove everything from the handler except that line:
REEDCOUNT = REEDCOUNT + 1; //Add 1 to the count of bucket tips
void chovendoPluvi()
{
if ((val == LOW) && (old_val == HIGH)) //Check to see if the status has changed
{
delay(10); // Delay put in to deal with any "bouncing" in the switch.
REEDCOUNT = REEDCOUNT + 1; //Add 1 to the count of bucket tips
old_val = val; //Make the old value equal to the current value
Serial.print(time);
Serial.print("Medida de chuva (contagem): ");
Serial.print(REEDCOUNT);//*0.2794);
Serial.println(" pulso");
Serial.print("Medida de chuva (calculado): ");
Serial.print(REEDCOUNT * 0.25);
Serial.println(" mm");
}
else
{
old_val = val; //If the status hasn't changed then do nothing
}
}
There is a lot wrong with that ISR. Any variable that is changed in an ISR should be declared volatile. You should not use delay() in an ISR. You should not print in an ISR. An ISR should be very short. Increment the count and set a flag that tells loop() that the ISR fired. Then, in loop(), do the processing and clear the flag. In loop() you need to guard against the ISR variable from changing while you read it. Disable interrupts just long enough to read or copy the variable and then enable interrupts.
pylon:
In an interrupt handler you must not use the Serial object or any other function the depends on interrupts (as interrupts are disabled inside interrupt handlers) such as delay().
You don't need to check the old value as the interrupt will only fire if there was a change in the signal state. So remove everything from the handler except that line:
REEDCOUNT = REEDCOUNT + 1; //Add 1 to the count of bucket tips
{
if ((val == LOW) && (old_val == HIGH)) //Check to see if the status has changed
{
delay(10); // Delay put in to deal with any "bouncing" in the switch.
REEDCOUNT = REEDCOUNT + 1; //Add 1 to the count of bucket tips
old_val = val; //Make the old value equal to the current value
Serial.print(time);
Serial.print("Medida de chuva (contagem): ");
Serial.print(REEDCOUNT);//*0.2794);
Serial.println(" pulso");
Serial.print("Medida de chuva (calculado): ");
Serial.print(REEDCOUNT * 0.25);
Serial.println(" mm");
}
else
{
old_val = val; //If the status hasn't changed then do nothing
}
}
There is a lot wrong with that ISR. Any variable that is changed in an ISR should be declared volatile. You should not use delay() in an ISR. You should not print in an ISR. An ISR should be very short. Increment the count and set a flag that tells loop() that the ISR fired. Then, in loop(), do the processing and clear the flag. In loop() you need to guard against the ISR variable from changing while you read it. Disable interrupts just long enough to read or copy the variable and then enable interrupts.
I'm having some troubles to understand this:
Increment the count and set a flag that tells loop() that the ISR fired. Then, in loop(), do the processing and clear the flag. In loop() you need to guard against the ISR variable from changing while you read it. Disable interrupts just long enough to read or copy the variable and then enable interrupts.
Here is a demo to show what I meant. Tested on my Uno with a pushbutton switch attached to pin 2 to simulate a reed switch. Switch is hardware debounced with a 0.1uF cap across the switch. For a reed switch, software debouncing would probably be better as the contacts on a reed switch are very small and could be subject to arcing with the cap.
groundFungus:
Here is a demo to show what I meant. Tested on my Uno with a pushbutton switch attached to pin 2 to simulate a reed switch. Switch is hardware debounced with a 0.1uF cap across the switch. For a reed switch, software debouncing would probably be better as the contacts on a reed switch are very small and could be subject to arcing with the cap.