ayuda Funciones en paralelo ??? y consulta

antes que nada agradezco el tiempo que le dedicaran a la lectura de este problema .
soy principiante en el entorno arduino y estoy intentando realizar lo siguiente..

control de reles por medio de un ehternet shield, un lector de temperatura con dth 11 que muestra la temperatura y la humedad en un lcd conectado de forma I2C la idea de esto es hacer un panel de control para una casa semiautomática, donde el control por Internet seria el panel de control manual ,

planeo meter también un sensor de pir el cual active una salida mientras detecte movimiento
y que de manera automática el sensor de temperatura active o desactive una salida cuando llegue a determinada temperatura , pero no tengo idea de como hacerlo ;

en este código tengo algo básico con el modulo de Internet y el sensor mas sin embargo al anexarle algún código mas como es una secuencia la parte de Internet tiene que esperar a que se termine de ejecutar el resto del código y tarda en reaccionar

mis preguntas son : hay alguna forma de hacer que las funciones se ejecuten en paralelo y no en serie??

y si alguien me pudiera orientar con la parte de controlar una salida cuando llegue a un limite superior de temperatura y desactivarlo al limite inferior

este es el código que tengo hasta ahora :

#include <Wire.h>   // Libreria de protocolo i2c
#include <LiquidCrystal_I2C.h> // Libreria de Convertidor LCD-i2c
LiquidCrystal_I2C lcd(0x27,16,2);
#include "DHT.h" 
#define DHTPIN 6 // cambio de pin por cuestion de choque  
#define DHTTYPE DHT11 
DHT dht(DHTPIN, DHTTYPE); 

byte charGrado[8] = 
{ 0b01110,
  0b01010,
  0b01110,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000};

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

byte mac[]={0xDE,0xAD,0xBE,0xEF,0xFE,0xED}; //MAC 
IPAddress ip(192,168,0,20); //IP 192.168.0.254
EthernetServer servidor(80); 

int rele1=2; int rele2=3; int rele3=4; int rele4 =5;

String readString=String(30);
String estado1=String(3);String estado2=String(3);String estado3=String(3);String estado4=String(3);

void setup(){
Ethernet.begin(mac, ip); 
servidor.begin(); 
pinMode(rele1,OUTPUT); digitalWrite(rele1,HIGH);
pinMode(rele2,OUTPUT); digitalWrite(rele2,HIGH);
pinMode(rele3,OUTPUT); digitalWrite(rele3,HIGH);
pinMode(rele4,OUTPUT); digitalWrite(rele4,HIGH);

estado1="OFF";estado2="OFF";estado3="OFF";estado4="OFF";

lcd.init();//inicia la lcd
  dht.begin();//se inicia el sensor
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("INICIANDO ...");
  delay(1000);
  lcd.clear();
  
  lcd.createChar(0, charGrado);//llama el caracter °
}

void loop(){ 
  
  //inica lector de temperatura 
int h = dht.readHumidity(); //se lee la humedad
int t= dht.readTemperature(); // se lee la temperatura
lcd.backlight();
lcd.setCursor(0,0);
  lcd.print("HUMEDAD:");
  lcd.print( h);
  lcd.print("%");
  
 lcd.setCursor(0,1);
 lcd.print("TEMPERTURA:");
 lcd.print(t);
  lcd.write(byte(0)); 
  lcd.print("C");

  // se imprime las variables de temperatura y humedad
 // delay(10000); 
  //lcd.clear();
  //lcd.print("ESCANEANDO...");
  //delay (12000);
  //lcd.clear();

 //termina lector de temperatura 
// control manual empieza aqui...
  EthernetClient cliente= servidor.available(); 
if(cliente) {
boolean lineaenblanco=true; 
while(cliente.connected()) {
if(cliente.available()) {
char c=cliente.read(); 
if(readString.length()<30) {
readString.concat(c);
} 
if(c=='\n' && lineaenblanco) 
{
int LED1 = readString.indexOf("LED1="); 
int LED2 = readString.indexOf("LED2="); 
int LED3 = readString.indexOf("LED3="); 
int LED4 = readString.indexOf("LED4="); 


if(readString.substring(LED1,LED1+6)=="LED1=T") {digitalWrite(rele1,LOW);
estado1="ON";}
if (readString.substring(LED1,LED1+6)=="LED1=F") {digitalWrite(rele1,HIGH); 
estado1="OFF";}

if (readString.substring(LED2,LED2+6)=="LED2=T") {digitalWrite(rele2,LOW);
estado2="ON"; } 
if (readString.substring(LED2,LED2+6)=="LED2=F") {digitalWrite(rele2,HIGH); 
estado2="OFF";}

if(readString.substring(LED3,LED3+6)=="LED3=T") {digitalWrite(rele3,LOW);
estado3="ON"; } 
if (readString.substring(LED3,LED3+6)=="LED3=F") {digitalWrite(rele3,HIGH); 
estado3="OFF";}

if(readString.substring(LED4,LED4+6)=="LED4=T") {digitalWrite(rele4,LOW);
estado4="ON"; } 
if (readString.substring(LED4,LED4+6)=="LED4=F") {digitalWrite(rele4,HIGH); 
estado4="OFF";}

cliente.println("HTTP/1.1 200 OK"); 
cliente.println("Content-Type: text/html"); 
cliente.println("Connection: close");
cliente.println("Refresh: ");  
cliente.println(); 
cliente.println("<!DOCTYPE HTML>");
cliente.println("<html>"); 
cliente.println("<head>"); 
cliente.println("<title>CONTROL MANUAL</title>"); 
cliente.println("</head>");

cliente.println("<body>");
cliente.println("<body bgcolor=#819FF7 height=150% width=150%>");
cliente.println("<center>"); 
cliente.println("<h1>PANEL DE CONTROL MANUAL</h1>");
cliente.println("<h2>PROTOTIPO DE SALON INTELIGENTE</h2>");

cliente.print("ILUMINACION");
cliente.print("
");
cliente.println("<input type=submit value=ENCENDIDO style=width:150px;height:100px onClick=location.href='./?LED1=T\'><input type=submit value=APAGADO style=width:150px;height:100px onClick=location.href='./?LED1=F\'>"); 
cliente.println("STATUS=");  cliente.println(estado1);  cliente.print("<p>&nbsp;</p>");  


cliente.print("VENTILADORES");
cliente.print("
");
cliente.println("<input type=submit value=ENCENDIDO style=width:150px;height:100px onClick=location.href='./?LED2=T\'><input type=submit value=APAGADO style=width:150px;height:100px onClick=location.href='./?LED2=F\'>"); 
cliente.println("STATUS=");  cliente.println(estado2);  cliente.print("<p>&nbsp;</p>");  


cliente.print("CLIMAS");
cliente.print("
");
cliente.println("<input type=submit value=ENCENDIDO style=width:150px;height:100px onClick=location.href='./?LED3=T\'><input type=submit value=APAGADO style=width:150px;height:100px onClick=location.href='./?LED3=F\'>"); 
cliente.println(" STATUS=");  cliente.println(estado3);  cliente.print("<p>&nbsp;</p>");  


cliente.print("CONTACTOS");
cliente.print("
");
cliente.println("<input type=submit value=ENCENDIDO style=width:150px;height:100px onClick=location.href='./?LED4=T\'><input type=submit value=APAGADO style=width:150px;height:100px onClick=location.href='./?LED4=F\'>"); 
cliente.println("STATUS=");  cliente.println(estado4);  cliente.print("<p>&nbsp;</p>");  

cliente.println("<h2>TEMPERATURA:</h2>");
cliente.print(t);
cliente.print("°C");
cliente.println("<h2>HUMEDAD RELATIVA:</h2>");
cliente.print(h);
cliente.print("%");

cliente.println("</body>"); 
cliente.println("</html>"); 
cliente.stop();

readString="";// termina control manual
 

   
}

}
}
}
}

eh intentado crear las funciones y llamarlas en el loop pero se ejecutan de igual manera auxilio !!!

Bueno, creo que has hecho muy poca investigación sobre la tecnología RISC que mueve un ATMEL.
No existe nada que funcione en paralelo a nivel de 8bits en un ARDUINO.
Lo mas cercano es time scheduling y es dividir las tareas y asignarles tiempo de CPU a cada una.
Algo que cumple con esa tarea es FREERTOS (enlace está en el otro post indicado mas abajo)

Está respondido en este enlace de hace 1 o 2 días que pensé que era tuyo.

Como comenté en el otro post, lo mejor que se puede hacer es no usar delay en tu programa y si usar millis() en su lugar.

Un par de comentarios de tu programa:

  1. Cuidado con el uso de tantas variables String. Consumen mucha RAM y la RAM está limitada.
  2. He visto delay(10000) comentado... eso no lo puedes usar sin comentado, me entiendes.
    No puedes pretender trabajo paralelo y programar de ese modo. Repito lo que te dije antes, suplanta todo delay por millis() con el uso apropiado que corresponde porque no son reemplazos directos.
    un if(millis()-time > TIMEenMSEG) permite que hagas cosas mientras no se cumpla esta función y cuando lo hace tomas acción por ejemplo prender un led o un activar un relé.
    un if(millis()-time < TIMEenMSEG) ejecutará lo que tenga dentro del if hasta que no sea superado el TIMEenMSEG y de nuevo devuelve el control al programa.
    en cambio un delay(TIMEenMSEG) no deja que hagas nada mientras se cumple eso.

Ves la gran diferencia.
3) Luego si tienes eventos rápidos puedes usar interrupciones externas, lo que de nuevo de dará idea a un procesamiento paralelo.

Como ves hay muchas herramientas a tener en cuenta usando los recursos de ARDUINO.

muchas gracias amigo surbyte ya lo corregiré y como comentas si no eh echo una muy buena investigación
gracias por el enlace y las recomendaciones si hay gran diferencia entre lo que me comentas enseguida lo aplico

surbyte ¿a que te refieres con limpiar los "chars"?, (en otro post que no recuerdo cual era), vi una sugerencia semejante y le he dado vueltas a la duda. Debo decir que hasta ahora el Due no se ha quedado sin memoria, no tiene comportamientos extraños y me da la impresión de que todo funciona bien.

Soy fan de los chars porque con ellos se pueden presentar valores que cambian con el tiempo y permiten que los números no se encimen y se llene la pantalla de pixeles sin sentido. Me he acostumbrado a usar solo char para imprimir en pantalla variables numéricas, en lugar de usar el Monitor Serie.

Por ejemplo defino solo "este char" para mostrar en pantalla fecha, hora, temperaturas, voltajes, contadores, niveles de cada banda de los analizadores de espectro de audio, etc.

char textBuff[20];

Y con el presento todo en pantalla, por ejemplo, muestro la temperatura de un sensor

         sprintf(textBuff, "%02d", Tempe);
         t1.drawString(textBuff, 280, 5);

Y enseguida, presento la lectura de los milivolts que entrega el sensor, con la idea de ajustar la calibración, usando la misma variable char, pero en otra posición en pantalla:

          sprintf(textBuff, "%03d", Lectura1);
                  t1.drawString(textBuff, 280, 50);

También uso las variables tipo char para poder tener un mejor control de acceso a las imagenes .RAW, .JPG, .BMP o .565, como fondos de pantalla para animar las cosas un poco. Por el momento solo quiero usar las imagenes tipo .565, mediante esta linea:

char BMP565onSDCard[4][10]={"u2.565","6oB.565","CH1.565","sun.565"};

Luego solo llamo el índice de la imagen que quiero que se muestre en pantalla:

bmpDraw(BMP565onSDCard[pic], 0, 0);

Resumiendo: tengo solo dos variables tipo char (textBuff y BMP565onSDCard) pero nunca he limpiado ninguna antes de usarla para cargar una nueva imagen o una nueva lectura numérica, incluso dejando el proyecto en modo autónomo por mas de unos días de forma continua sin reiniciar el arduino.

Vienen las dudas luego del planteamiento general: al aumentar el tiempo sin supervisión o reinicios del arduino, ¿afectará la memoria disponible del arduino usando así las variables tipo char?, ¿es necesario limpiar cada variable char antes de volver a usarla? o ¿dejo todo como lo he usado hasta ahora?

No se a que te refieres TFTLCDCyg. Yo tambien los uso como tu.

Saludos
Me salta una pregunta: realmente sirve limpiar una variable char? Creo que la unica forma de recuperar memoria seria destruir la variable, porque si defino una arreglo de por ejemplo 30 char y luego de usarla coloco todo el arreglo en /0 igualmente el arduino hace reserva para los 30 caracteres o no?

Por supuesto. El ponerla en 0 no recupera nada. No estan usando variables de uso dinámico que entonces si podrian liberarse pero eso es con punteros y con el uso de malloc que asigna memoria.
Aca no se libera nada, la idea creo que tiene que ver con no imprimir cosas que no quiero.

YO creo que el problema esta en que si defines una variable

char textBuff[20];

y luego usas digamos sprintf(textBuff, "%02d", Tempe);
yo entiendo que ocuparas cuanto bytes? en este caso reserva 2 lugares o sea 2 bytes y si Tempe fuera de 1 digitos lo mostraría como 0X entonces son 2 bytes mas un \0 supongo para poder detectar el fin.
Si tiene 20 bytes disponibles y usamos 2/3 inicializarlo tiene por objeto no imprimir basura en otro momento.
Yo cuando es asi uso sprinft de otro modo pero es un recurso torpe si se quiere.
sprintf(textBuff, "%02d ", Tempe);[/code] con 18 espacios luego de la %02d
O sea completo el buffer.
eso asegura la limpieza.

Cuando el programa se vuelve grande y el buffer se usa una y otra vez, es dificil saber con que basura esta.
Esa es la posible razón de su inicialización, sería como un clear buffer.