control pid de la temperatura de varios terrarios

Buenas, la verdad es que no se si estoy en la seccion adecuda, si no es asi ruego al responsable me cambie el post de sitio.
El tema es que llebo un tiempo con un proyecto, mi idea es utilizar el arduino para controlar una sala en la que hay varios terrarios, el tema que mas me interesa es el control de la temperatura(estos animales son increiblemente sensibles a la temperatura)hasta ahora utilizaba termostatos diming de habistat bastante caros y sensibles.
No tengo problemas con el software (o yo creo) ni con las sondaqs de temperatura estoy utilizando las onewire y son fascinantes , el problema viene al dimmear la resistencia(ya sea una bombilla o un calefactor) con la salida pwm.
estoy utilizando un circuito de para detectar el paso por zero con dos opto y un triac como rea en el siguiente diagrama

el problema viene que la bombilla luze hasta un 25 % aprox y apartir de hay empieza a descender , no consigo encenderla de todo ni siquiera que sea estable...
os pongo el codigo que estoy utilizando

int AC_pin = 10; //Pin to MOC3020 - OptoTriac
byte dim = 0; //Initial brightness level from 0 to 255, change as you like!

void setup() {
Serial.begin(9600);
pinMode(AC_pin, OUTPUT);
attachInterrupt(0, light, FALLING);//When arduino Pin 2 is FALLING from HIGH to LOW, run light procedure!
}

void light() {
if (Serial.available()) {
dim = Serial.read();
if (dim < 1) { //Turn TRIAC completely OFF if dim is 0
digitalWrite(AC_pin, LOW);
}
if (dim > 254) { //Turn TRIAC completely ON if dim is 255
digitalWrite(AC_pin, HIGH);
}
}
if (dim > 0 && dim < 255) { //Dimming part, if dim is not 0 and not 255
delayMicroseconds(34*(255-dim));
digitalWrite(AC_pin, HIGH);
delayMicroseconds(500);
digitalWrite(AC_pin, LOW);
}
}

void loop() {

}

Realmente no se que puede estar pasando cualquier comentario es bienvenido
Muchas gracias de antemano.

Para mi la parte que tiene que ver con la lectura del puerto serie debe estar en el loop. Jamas en una ISR, demora demasiado.

int AC_pin = 10;           //Pin to MOC3020 - OptoTriac
byte dim = 0;              //Initial brightness level from 0 to 255, change as you like!

void setup() {
  Serial.begin(9600);
  pinMode(AC_pin, OUTPUT);
  attachInterrupt(0, light, FALLING);//When arduino Pin 2 is FALLING from HIGH to LOW, run light procedure!
}

void light() {
  
  if (dim < 1) {                  //Turn TRIAC completely OFF if dim is 0
      digitalWrite(AC_pin, LOW);
    }
    if (dim > 254) {                //Turn TRIAC completely ON if dim is 255
      digitalWrite(AC_pin, HIGH);
    }

  if (dim > 0 && dim < 255) {      //Dimming part, if dim is not 0 and not 255
    delayMicroseconds(34*(255-dim));
    digitalWrite(AC_pin, HIGH);
    delayMicroseconds(500);
    digitalWrite(AC_pin, LOW);
  }
}

void loop() {
  if (Serial.available()) {
    dim = Serial.read();
  }

}

Podría ser, haber si mañana puedo realizar la prueba, de todas maneras he estado trasteando un poco por la tarde y montando la placa con el programa s4a utilizándola solamente para leer los puertos, en cuanto conecto la corriente alterna empiezan a loquear y a dar valores erráticos :fearful: no entiendo el porque incluso he probado quitando los opto por si acaso mandaban alguna señal pero ni con esas...
me tiene loco el tema este

He encontrado un código muy bien hecho, que incluye una librería TimerOne que esta en este blog

Tiene la curva de brillo para hacer que luzca lineal
Usa tu misma interrupción y en
int output [] = { // assign a pin for each channel.
10, // Output 0
3, // output 1
5, // output 2
0, // output 3
0, // output 4
0, // output 5
0, // output 6
0, // output 7
};

Eliges el pin a usar, aca esta con el 4 para la salida 0 pero usa el 10 si quieres.
He puesto un NroDimmer 1 que limita el uso a solo un dimmer que es tu caso. Esta pensando para 8.

A ver si te sirve y se porta bien.
Aca cito las ventajas
Cruce por cero como el tuyo, de hecho usa la misma electrónica de cruce por cero.
Interrupción de tiempo variable que obtiene una curva lineal con el brillo. La potencia es cuadrática por lo tanto requieres de esto para que luzca como un brillo progresivo y parejo.
Tienes comandos via puerto serie como en tu caso, curiosamente ubicados ... EN EL LOOP como yo te habia sugerido.
que comandan todo

 /*
    by Gromain59
    Translated By Mike Deuschle
    mike.dausch@gmail.com

    Material part:
    - Triac driven by a digital output via an optocoupler
    - AC opto-coupler for detecting the zero crossing of phase

    Software part:
    - A hardware interrupt input 2 at the zero crossing of phase
    - A software interrupt that occurs between 100us and 1400us.
    => Interrupt interval is variable to obtain a light curve by linear orders, because of the shape of the sinusoidal signal.
    we have:
    1. Detection of the transition to zero on input 2
    2. execution of detection_zero (): processing channel with a setpoint of 0% and 100%
    3. deactivating hardware interrupt, enabling the software interrupt on the basis of delay [0]
    4. interrupt after delay [c2] ?s (c2 = 0)
    5. execution of controle_canaux ()
    => Index increment c2
    and if c2 is greater than 49, then this is the last cycle
    => Turn OFF of all channels
    => Activate the hardware interrupt
    otherwise:
    => Activation of output channels with 98% to record (either a 469?s delay) or if
    => Interrupt reconfiguration of time with another delay, delay [c2]

    To change the setpoint of a channel, you must send via the serial monitor a frame of the form:
    " D/0/45/F"
    => Space
    => "D" to indicate the start of the frame
    => "/" As separator
    => The affected channel (0 to 7 here)
    => "/" As separator
    => The desired level (from 0% to 100%)
    => "/" As separator
    => "F" to indicate the end of the frame

    Once the frame received, the function sscanf is responsible for retrieving data.
    It converts the received record levels (0 to 50 levels)

    Resources:
    http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230333861/30 for first test
    http://www.hoelscher-hi.de/hendrik/english/dimmer.htm for electronics
    http://www.abcelectronique.com/bigonoff/domocan.php?par=3efd4 for electronics and soft (PIC)
    arduino forum

    */

    #include <TimerOne.h>   // for the interruption time http://www.arduino.cc/playground/Code/Timer1
    #include <stdio.h>   // for the treatment of the frame containing the change orders

    #define NroDimmers 1
    // timeout value for the reception of the frame
    int tps_max_lecture = 200; // reading code, counter max between all the characters of a code
    int tps_max_carte = 1000; // max meter between reception of a character

DimmerAC.ino (9.31 KB)

Bueno párace que me cuesta mas de lo que yo pensaba jaja y es que pruebo el sketch con la lectura del serial en el loop y hace lo que que le da la gana ... y en el segundo sketch que me parece increible no soy capaz de escribir en el serial los datos sin que me de error entiendo por lo que veo en el codigo que debo conectar el detector en el pin nº2 y la salida en el que yo quiera siempre que sea pwm claro...

Tu usas pin 10 para comandar el triac, asi te lo puse en el código (que no es mío) y pin 2 es el de la interrupción que detecta el cruce por cero, eso esta igual.
No veo que problema tienes?

el problema viene aal escribir las ordenes en el monitor serial que no me reconoze nada

ahhh eso es porque lo tienes mal configurado al monitor serie. Mira las opciones abajo a la derecha. Veras que dispone de lo necesario para que ahora si funcionen los comandos

Debes hacer click en No line ending

Yo uso frecuentemente este monitor serie Hercules HW Group

Si ya lo tengo no line ending o en mi caso sin ajuste de linea pero lo que me sale es totalmente diferente

este es el texto que me sale:

Gromain 8-CHANNEL DIMMER v0.2
FRAME EXPECTED: 'D' / 'Output Port' / 'Value of DIM' / 'F'

Si.. bueno es un cartel de presentación.
Lee en el codigo como tenes que enviar los comandos.
ejemplo envia "D/0/45/F"
todo esta claro en el comienzo del codigo
D comienza el mensaje
F lo termina
0 el puerto que queres usar para dimmer
45 el angulo de conducción.

Solo tenes una salida asi que siempre sera 0

Si eso habia intentado pero... ponga lo que ponga y de la manera que lo ponga me da un code unknow

Pero cambiaste la linea: sin ajuste de linea?
En el simulador no lo puedo hacer funcionar.
Bueno lo subi a un NANO y me hace lo qeu te hace a ti. Problema con la librería stido y la función sscanf(buf, "%c/%d/%d/%c", &c1, &n1, &n2, &c2); // decoding frame

Hay que estudiarlo.
Mas tarde lo veo.