DHT22 reads nan

I’m building a weather station using an Arduino. After about 10 hours (approximately) of continuous operation, I observe the following issues:

  • The DHT22 sensor stops responding (returns NaN or fails to read).
  • Hardware interrupts for the anemometer and rain gauge start triggering constantly, even with no input.
  • About 2 hours later (approximately), the interrupt behavior returns to normal, but the DHT22 remains unresponsive until I reset the board.

I use an Arduino Mega with an Ethernet Shield. Any advice would be appreciated. I can share code if needed.

Thanks.

What else could cause the problems?

That sounds suspiciously like a memory problem, possibly caused by writing outside the bounds of an array or maybe the use of a variable of the wrong type or size

Without your code it is impossible to say

Please post your full sketch, using code tags when you do

Posting your code using code tags prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

It is also helpful to post error messages in code tags as it makes it easier to scroll through them and copy them for examination

Could be floating inputs. They can appear to work for some time, then randomly not, then randomly start working again.

Share also a wiring diagram and tell us about the wire lengths and power connections. A picture of a hand-drawn sketch is perfectly Ok.

How do you power the Mega.
An Ethernet shield is fairly power-hungry.
Powering the Mega externally via the DC socket could overheat the Mega's 5volt regulator over time, cutting in and out.

We need to see every aspect of your project to help you. Code, wiring, etc.
Please read the "How to get the best out of this forum".
Leo..

I power the Mega using a typical wall adapter, connected through the DC jack (not via USB).

I do not know exactly the amperage and voltage since I do not have it with me.

Could it be the problem? How could I solve it?

/**
 * @file Arduino_Placas.ino
 * @author Arturo Olivares Martos
 * 
 * Informaremos, cada FREC_MEDICION segundos:
 * - Dirección del viento.
 * - Velocidad del viento.
 * - Temperatura exterior.
 * - Temperatura en el cuadro de placas.
 * - Llueve o no. Consideraremos que llueve si, en esos FREC_MEDICION segundos, ha habido al menos un click en el pluviómetro (0.2794mm).
 * - Del acumulado de lluvia en la última hora.
 * 
 * 
 * @see https://learn.sparkfun.com/tutorials/weather-meter-hookup-guide     (guía de montaje)
 * @see Documento de documentación
 * 
 * @note * 
 * ================================================
 * Pluviómetro
 * ================================================
 * Para la conexión, ver la documentación.
 * Cada click del pluviómetro cierra un circuito. Se puede detectar empleando una interrupción en FALLING.
 * Cada click equivale a 0.2794mm. * 
 * 
 * 
 * ================================================
 * Anemómetro
 * ================================================
 * Para la conexión, ver la documentación. Misma que el pluviómetro.
 * Cada revolución del anemómetro cierra un circuito. Se puede detectar empleando una interrupción en FALLING.
 * Cada revolución equivale a 2.4 km/h.
 * *Observación:* No es cada revolución, creo que es cada 1/3 de rev. Pero da igual, cada interrupción es un click.
 * 
 * 
 * ================================================
 * Veleta
 * ================================================
 * Para la conexión, ver la documentación.
 * Usaremos un divisor de tensión para medir el voltaje en el pin analógico, que variará en función de la resistencia de la veleta.
 * 
 * Usando una resistencia de 10K, nuestra lectura en el sensor analógico será:
 *   1023 * (R/(10000+R))
 * donde R es la resistencia desconocida de la veleta.
 * 
                  +5V
                   |
                   <
                   >     10K
                   <   Resistor
                   <
                   >
                   |
 Analog Pin  ------|
                   |
                   -----------| To weather vane
                              | (mystery resistance)
                   -----------|
                   |
                   |
                 -----
                  ---
                   -
 *
 * ================================================
 * Sensor Temperatura Cuadro de Placas (LM35)
 * ================================================
 * Lee 10mV/ºC. Por tanto, para obtener la temperatura en ºC:
 *  temp = (voltage * 100)
 * Como Arduino solo puede leer de 0 a 5V, la temperatura estará limitada a temperaturas positivas.
 * 
 */
 


#include <DHT.h>
#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoModbus.h>


#define PIN_ANEMOMETRO			2
#define PIN_PLUVIOMETRO			3
#define PIN_VELETA				A0
#define PIN_TEMP_CUADRO_PLACAS	A1
#define PIN_DHT22_EXTERIOR		5
#define PIN_RELAY_ABEJAS		6
#define PIN_VOLATE_BATERIA		A2


// Configuración ethernet y modbus
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF };
IPAddress ip(192, 168, 0, 152);
EthernetServer ethernetServer(502);		// Puerto Modbus TCP
ModbusTCPServer modbusTCPServer;		// Servidor Modbus


// Sensor DHT22
#define DHT_EXT_TYPE DHT22
DHT dht_exterior(PIN_DHT22_EXTERIOR, DHT_EXT_TYPE);
float humExterior = 0;
float tempExterior = 0;

// Sensor LM35
#define GRADOS_POR_VOLTIO 100
float tempCuadroPlacas = 0;


// Frecuencia de las mediciones (segundos)
#define FREC_MEDICION 3
unsigned long nextMedicion = 0;
unsigned long tiempoActual = 0;


// Variables para el pluviómetro y el anemómetro. Modificadas por las interrupciones.
volatile unsigned long numClicksPluviometro = 0;
volatile unsigned long numClicksAnemometro = 0;
#define DEBOUNCE_TIME_PLUVIOMETRO 100000UL 	// Debounce time en microsegundos para contar sólo un click. Para evitar ruido.
#define DEBOUNCE_TIME_ANEMOMETRO 30
volatile unsigned long last_pluviometro = 0;		// Último tiempo en el que se contó un click.
volatile unsigned long last_anemometro = 0;
#define MM_POR_CLICK 0.2794
#define KMH_POR_CLICK 2.4
float velViento = 0;
bool lluviaDetectada = false;

// Variables para la veleta
// Correspondencia de dirección del viento con ángulo.
#define NUM_DIR_POSIBLES 16
const float dirAng[NUM_DIR_POSIBLES] = {112.5,67.5,90,157.5,135,202.5,180,22.5,45,247.5,225,337.5,0,292.5,315,270};
const char* dirCard[NUM_DIR_POSIBLES] = {"ESE","ENE","E","SSE","SE","SSW","S","NNE","NE","WSW","SW","NNW","N","WNW","NW","W"};
const float correccion = 200.0;

// Cada una de las 16 direcciones tiene una resistencia asociada (ver documentación).
// Usando un divisor de tensión, para cada valor de resistencia, tenemos un valor de tensión asociado.
// En nuestro caso (Vin=Vout=5V, R1=10K), la tensión en el pin analógico se puede ver en la documentación.
// Convertiendo dichas lecturas de V a valores de 0 a 1023 (que es lo que lee el Arduino), tenemos los siguientes valores.
const int sensorVal[NUM_DIR_POSIBLES] = {66,84,93,126,184,244,287,406,461,599,630,702,785,827,886,945};

// Dándole un rango a cada dirección, podemos saber la dirección del viento.
const int sensorMin[NUM_DIR_POSIBLES] = {63,80,89,120,175,232,273,385,438,569,613,667,746,812,869,931};
const int sensorMax[NUM_DIR_POSIBLES] = {69,88,98,133,194,257,301,426,484,612,661,737,811,868,930,993};

// Valores de la veleta
float angulo = 0;
const char* dir = "TMP";

// Variable para hacer medias
#define NUM_LECTURAS 20


// Acumulaciones horarias de clicks.
// Usa un array circular que almacena el acumulado de clicks en la última hora.
// Un índice apunta al valor más antiguo, que se va sobreescribiendo.
const int NUM_ACTUALIZACIONES_HORA = 60*60/FREC_MEDICION;
#define VENTANA_AISLADO 3
unsigned int clicks_por_medicion[NUM_ACTUALIZACIONES_HORA] = {0};
unsigned long acumulado_clicks_hora = 0;		// Aunque es redundante, evitamos tener que sumar todo el array cada vez
unsigned int indice_actual = 0;
float lluvia_ultima_hora = 0;


// Variables para control de las abejas
const unsigned long MINUTOS_ENCENDIDO = 1;
const unsigned long MINUTOS_TRAS_ENCENDIDO = 2*60;	// Apagado tras encendido
#define VOLTAJE_MINIMO_PLACA 12.0
#define TEMP_MINIMA_RELE 2.0							// Temperatura mínima para encender el relé. Para evitar congelación
unsigned long nextActivacionRele = 0;					// Tiempo en el que se activará el relé
unsigned long nextApagadoRele = 0;						// Tiempo en el que se apagará el relé. Se configura al encenderlo
float voltajeBateria = 0;								// Voltaje de la batería. Se usa para comprobar si está baja
bool releEncendido = false;								// Indica si el relé está encendido
bool bateriaBaja = false;								// Indica si la batería está baja
bool tempMuyBaja = false;								// Indica si la temperatura es muy baja para encender el relé
bool ordenEnciendoRele = false;							// Indica si se ha dado la orden de encender el relé
bool ordenApagoRele = false;							// Indica si se ha dado la orden de apagar el relé
float restanteEncendido = 0;							// Segundos que aún queda encendido
float hastaSigMedicion = 0;								// Segundos que aún quedan hasta la siguiente medición




/**
 * @brief Función para controlar los desbordamientos de las variables de tiempo.
 * 
 * Millis se desborda cada 50 días. Micros cada 70 minutos.
 *  
 */
void overflows(){
	if (tiempoActual > millis()){ //Millis ha desbordado
		tiempoActual = millis();
		Serial.println("MILLIS se ha desbordado");

		// Descartamos las mediciones anteriores
		numClicksPluviometro = 0;
		numClicksAnemometro = 0;
		nextMedicion = 0;
		nextActivacionRele = 0;
		nextApagadoRele = 0;

	}

	if ((last_anemometro > micros()) || (last_pluviometro > micros())){ //Micros se ha desbordado
		Serial.println("MICROS se ha desbordado");

		// Este será el nuevo tiempo de la última medición. Si llueve mucho/hay mucho viento, podrá haber pequeños errores.
		last_anemometro = 0;
		last_pluviometro = 0;
	}
}


/**
 * @brief Interrupción para el pluviómetro. Llamada cada vez que hay un click.
 */
void intrPluviometro(){
	if((micros() - last_pluviometro) >= DEBOUNCE_TIME_PLUVIOMETRO) {
		numClicksPluviometro++;
		last_pluviometro = micros();
	}
}

/**
 * @brief Interrupción para el anemómetro. Llamada cada vez que hay un click.
 */
void intrAnemometro(){
	if((micros() - last_anemometro) >= DEBOUNCE_TIME_ANEMOMETRO) {
		numClicksAnemometro++;
		last_anemometro = micros();
	}
}


/**
 * @brief Obtiene la velocidad del viento, reseteando el contador de clicks.
 * 
 * @return float Velocidad del viento en km/h.
 */
float getVelocidadViento(){
	float revs_por_segundo = ((float)numClicksAnemometro) / FREC_MEDICION;
	numClicksAnemometro = 0;
	return revs_por_segundo * KMH_POR_CLICK;
}

/**
 * @brief Obtiene la cantidad de lluvia en la última hora.
 * 
 * @return float Cantidad de lluvia en mm en la última hora.
 * 
 * @post El contador de clicks de la interrupción del pluviómetro se resetea.
 */
float actualizaLluviaHoraria(){

	// x x x o x x x [ ]    Ahora estoy en [ ]. Si todas las x son 0 y o es positivo, han sido aislados; los descartamos
	int centro_ventana = (indice_actual - VENTANA_AISLADO - 1 + NUM_ACTUALIZACIONES_HORA) % NUM_ACTUALIZACIONES_HORA;	// Índice del centro de la ventana de aislamiento
	if (centro_ventana > 0){
		// Comprobamos si los valores de la ventana de aislamiento son todos 0
		bool aislado = true;
		int izq = centro_ventana;
		int der = centro_ventana;
		for (int i=0; i<VENTANA_AISLADO && aislado; i++){
			izq = (izq - 1 + NUM_ACTUALIZACIONES_HORA) % NUM_ACTUALIZACIONES_HORA;	// Índice a la izquierda
			der = (der + 1) % NUM_ACTUALIZACIONES_HORA;
			aislado &= (clicks_por_medicion[izq] == 0) && (clicks_por_medicion[der] == 0);
		}


		if (aislado){
			acumulado_clicks_hora -= clicks_por_medicion[centro_ventana];	// Si todos los valores de la ventana son 0, descartamos el valor del centro
			clicks_por_medicion[centro_ventana] = 0;	// Reseteamos el valor del centro
		}
	}

	// Actualizamos el acumulado. Sumamos los nuevos clicks y restamos los más antiguos.
	acumulado_clicks_hora += numClicksPluviometro;
	acumulado_clicks_hora -= clicks_por_medicion[indice_actual];

	// Actualizamos el array y el índice
	clicks_por_medicion[indice_actual] = numClicksPluviometro;
	numClicksPluviometro = 0;
	indice_actual = (indice_actual + 1) % NUM_ACTUALIZACIONES_HORA;

	return acumulado_clicks_hora * MM_POR_CLICK;
}

/**
 * @brief Informa si ha llovido en el último intervalo de tiempo.
 * 
 * @note Se considera que ha llovido si ha habido al menos un click en el pluviómetro.
 * 
 * @return true Ha llovido.
 * @return false No ha llovido.
 */
bool haLlovido(){
	return numClicksPluviometro > 0;
}

/**
 * @brief Obtiene la dirección del viento.
 * 
 * @return float Angulo del viento en grados (0-360).
 */
float getDireccionViento(){
	float angulo = 0;
	for (int i=0; i<NUM_LECTURAS; i++) {
		int value = analogRead(PIN_VELETA);
		for (int j=0; j<NUM_DIR_POSIBLES; j++) {
			if(sensorMin[j] <= value && value <= sensorMax[j]) {
				angulo += dirAng[j];
				break;
			}
		}
	}

	angulo /= NUM_LECTURAS;	// Media de las lecturas
	angulo = (int)(angulo + correccion) % 360;	// Ajustamos

	return angulo;
}


/**
 * @brief Obtiene la temperatura del interior del Cuadro de Placas.
 * 
 * @return float Temperatura en ºC.
 */
float getTemperaturaCuadroPlacas(){
	int sensorValue = 0;
	for (int i=0; i<NUM_LECTURAS; ++i){
		sensorValue += analogRead(PIN_TEMP_CUADRO_PLACAS);
	}

	sensorValue /= NUM_LECTURAS;
	
	float voltage = sensorValue * (5.0 / 1023.0);
	float temp = voltage * GRADOS_POR_VOLTIO;
	return temp;
}

#define VOLTAJE_MAX 25.0
/**
 * @brief Obtiene el voltaje de la batería.
 * 
 * @return float Voltaje de la batería en V.
 * 
 * @note Se calcula como media de 20 lecturas del pin analógico.
 */
float getVoltajeBateria(){
	float valor = 0;	// Calculamos la media de 20 lecturas
	for (int i=0; i<NUM_LECTURAS; i++)
		valor += analogRead(PIN_VOLATE_BATERIA);
	
	valor /= NUM_LECTURAS;
	float voltaje = valor * (VOLTAJE_MAX / 1023.0);

	#ifdef DEBUG_VOLTAJE_PLACA
		Serial.print("Voltaje Placa: ");
		Serial.println(voltaje);
	#endif

	return voltaje;
}




/**
 * @brief Indica si la batería está baja.
 * 
 * @return true La batería está baja.
 * @return false La batería no está baja.
 */
bool bateriaEstaBaja(){
	return voltajeBateria < VOLTAJE_MINIMO_PLACA;
}

/**
 * @brief Indica si la temperatura exterior es muy baja.
 * 
 * @return true La temperatura exterior es muy baja.
 * @return false La temperatura exterior no es muy baja.
 */
bool temperaturaEstaMuyBaja(){
	return tempExterior < TEMP_MINIMA_RELE;
}


//=======================================================
// Setup
//=======================================================
void setup() {
	Serial.begin(9600);
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, LOW);

	dht_exterior.begin();
	pinMode(PIN_ANEMOMETRO, INPUT);
	pinMode(PIN_PLUVIOMETRO, INPUT);
	attachInterrupt(digitalPinToInterrupt(PIN_ANEMOMETRO), intrAnemometro, FALLING);
	attachInterrupt(digitalPinToInterrupt(PIN_PLUVIOMETRO), intrPluviometro, FALLING);

	pinMode(PIN_RELAY_ABEJAS, OUTPUT);

	// Aseguramos que clicks_por_medicion está inicializado a 0
	for(int i=0; i<NUM_ACTUALIZACIONES_HORA; i++)
		clicks_por_medicion[i] = 0;

	
	// Inicializamos el Ethernet
  	Ethernet.begin(mac, ip);
	if (Ethernet.hardwareStatus() == EthernetNoHardware)
		Serial.println("Ethernet shield was not found.");
	else if (Ethernet.hardwareStatus() == EthernetW5100)
		Serial.println("W5100 Ethernet controller detected.");
	else if (Ethernet.hardwareStatus() == EthernetW5200)
		Serial.println("W5200 Ethernet controller detected.");
	else if (Ethernet.hardwareStatus() == EthernetW5500)
		Serial.println("W5500 Ethernet controller detected.");

	ethernetServer.begin();				// start listening for clients
  	modbusTCPServer.begin();			// start listening for clients

	// Configuramos los registros del servidor Modbus
	modbusTCPServer.configureHoldingRegisters(0, 100);	// Desde la dirección 0, ocupa 100 registros
	modbusTCPServer.configureInputRegisters(0, 100);
	modbusTCPServer.configureCoils(0, 100);
}


/**
 * @brief Funcionalidad del Arduino de las placas.
 * 
 */
void funcionalidad(){
	delay(50);	// Para evitar errores en el overflow
	overflows();	// Control de desbordamientos
	tiempoActual = millis();		// Tiempo común para toda la medición


	// Comprobación para la medición
	if(tiempoActual > nextMedicion) {	// Medimos cada FREC_MEDICION segundos
		
		nextMedicion = tiempoActual + (FREC_MEDICION*1000UL);
		velViento = getVelocidadViento();
		lluviaDetectada = haLlovido();
		angulo = getDireccionViento();
		tempCuadroPlacas = getTemperaturaCuadroPlacas();
		tempExterior = dht_exterior.readTemperature();
		humExterior = dht_exterior.readHumidity();
		
		lluvia_ultima_hora = actualizaLluviaHoraria();
	}

	// Comprobación del estado de la batería
	voltajeBateria = getVoltajeBateria();
	bateriaBaja = bateriaEstaBaja();
	tempMuyBaja = temperaturaEstaMuyBaja();

	bool hayPeligroRele = bateriaBaja || tempMuyBaja; // Si la batería está baja o la temperatura es muy baja, apagamos el relé

	// Control del relé de las abejas
	if (!releEncendido && !hayPeligroRele && (ordenEnciendoRele || (tiempoActual > nextActivacionRele))) {
		digitalWrite(PIN_RELAY_ABEJAS, HIGH);
		releEncendido = true;
		nextApagadoRele = tiempoActual + (MINUTOS_ENCENDIDO * 60 * 1000UL);
	}
	else if (releEncendido && (hayPeligroRele || ordenApagoRele || (tiempoActual > nextApagadoRele))) {
		digitalWrite(PIN_RELAY_ABEJAS, LOW);
		releEncendido = false;
		nextActivacionRele = tiempoActual + (MINUTOS_TRAS_ENCENDIDO * 60 * 1000UL);
	}

	if (releEncendido){
		restanteEncendido 	= (nextApagadoRele - tiempoActual)/1e3;
		hastaSigMedicion 	= 0;
	}else{
		restanteEncendido	= 0;
		hastaSigMedicion 	= (nextActivacionRele - tiempoActual)/1e3;
	}
}


/**
 * @brief Comunicación por Serial. Muestra los datos de la estación meteorológica.
 * 
 * @note Esta función se usa para depuración y no es necesaria para el funcionamiento del sistema.
 */
void comunicacionSerial(){
	Serial.print("Velocidad viento: ");
	Serial.print(velViento);
	Serial.println(" km/h");

	Serial.print("Temperatura exterior: ");
	Serial.print(tempExterior);
	Serial.println(" ºC");

	Serial.print("Humedad exterior: ");
	Serial.print(humExterior);
	Serial.println(" %");

	Serial.print("Temperatura cuadro placas: ");
	Serial.print(tempCuadroPlacas);
	Serial.println(" ºC");

	Serial.print("Lluvia última hora: ");
	Serial.print(lluvia_ultima_hora);
	Serial.println(" mm");

	Serial.print("Lluvia detectada: ");
	if (lluviaDetectada)
		Serial.println("Sí");
	else
		Serial.println("No");

	getDireccionViento();
	
	// Mostramos la dirección del viento
	if (angulo >= 0) {
		Serial.print("Dirección del viento: ");
		Serial.println(angulo);
	}
	else {
		Serial.println("Dirección del viento no disponible");
	}

	if (releEncendido)
	  Serial.println("Rele encendido");
	else{
	  Serial.println("Rele apagado");
	}
	Serial.print("Voltaje batería: ");
	Serial.print(voltajeBateria);
	Serial.println(" V");
	Serial.print("Batería baja: ");
	if (bateriaBaja)
		Serial.println("Sí");
	else
		Serial.println("No");
	Serial.print("Temperatura muy baja: ");
	if (tempMuyBaja)
		Serial.println("Sí");
	else
		Serial.println("No");

	Serial.print("Restante Encendido: ");
	Serial.print(restanteEncendido);
	Serial.println(" s");
	Serial.print("HastaSigMedicion: ");
	Serial.print(hastaSigMedicion);
	Serial.println(" s");



	Serial.println("------------------------------------------------\n");
}

#define FACTOR 1e2	// Número de decimales. Por Modbus, solo se envían enteros. La pantalla ajustará los decimales.
/**
 * @brief Comunicación Modbus con la pantalla. 
 */
void comunicacionModbus(){
	
	modbusTCPServer.holdingRegisterWrite(0x00, velViento * FACTOR);
	modbusTCPServer.holdingRegisterWrite(0x01, tempExterior * FACTOR);
	modbusTCPServer.holdingRegisterWrite(0x02, humExterior * FACTOR);
	modbusTCPServer.holdingRegisterWrite(0x03, tempCuadroPlacas * FACTOR);
	modbusTCPServer.holdingRegisterWrite(0x04, lluvia_ultima_hora * FACTOR);
	modbusTCPServer.holdingRegisterWrite(0x05, angulo * FACTOR);
	modbusTCPServer.holdingRegisterWrite(0x06, restanteEncendido * FACTOR);	// Tiempo restante para el apagado
	modbusTCPServer.holdingRegisterWrite(0x07, hastaSigMedicion * FACTOR);	// Tiempo restante para la siguiente medición
	modbusTCPServer.holdingRegisterWrite(0x08, voltajeBateria * FACTOR);
	
	modbusTCPServer.coilWrite(0x00, lluviaDetectada);
	modbusTCPServer.coilWrite(0x01, bateriaBaja);
	modbusTCPServer.coilWrite(0x02, releEncendido);
	modbusTCPServer.coilWrite(0x03, tempMuyBaja);
	ordenEnciendoRele = modbusTCPServer.coilRead(0x04);
	ordenApagoRele = modbusTCPServer.coilRead(0x05);

	// Actualizamos los valores de las órdenes de encendido o apagado del relé
	if (releEncendido && ordenEnciendoRele) {
		ordenEnciendoRele = false;
		modbusTCPServer.coilWrite(0x04, false);
	}
	else if (!releEncendido && ordenApagoRele) {
		ordenApagoRele = false;
		modbusTCPServer.coilWrite(0x05, false);
	}
}






//=======================================================
// Main loop
//=======================================================
void loop() {
	
	funcionalidad();
	#ifdef DEBUG_SERIAL
	comunicacionSerial();
	#endif
	comunicacionModbus();

	// Esperamos a un cliente
	EthernetClient client = ethernetServer.available();

	// Cuando se conecta un cliente, comenzamos
	if (client) {
		Serial.println("Nuevo cliente");

		// Aceptamos la conexión
		modbusTCPServer.accept(client);

		while (client.connected()) {
			if (client.available()) {
				// Procesamos la petición
				modbusTCPServer.poll();				
			}

			// Actualizamos los datos
			funcionalidad();
			#ifdef DEBUG_SERIAL
			comunicacionSerial();
			#endif
			comunicacionModbus();
		}

		Serial.println("Cliente desconectado");
	}
	
}

I know the code is quite big, but I hope it his clear and organized in different functions.

The hardware I use is:

The LM35 and the wind vane always work perfectly. The anemometer and wain gauge work perfectly except for the time I have mentioned when interruptions start triggering constantly. The DHT22 sensor works perfectly until that time, but then answers nan.

This is the wire connections.

  • The weather meter wires have a length of 3m aprox (as the anemometer needs to be high)
  • The DHT22 initially had wires of 4m, but I then changed to wires of 20-30cm, but the problem is still there.

All positives ares connected to the 5V pin, and all negatives to the GND pin.

Less than 7volt or more than 8volt, and this could well be your problem.
Try to power the Mega with a 5volt cellphone/tablet charger, connected to the USB socket. Ths is much safer, because it bypasses the Mega's 5volt regulator.
Leo..