2020/10/30

Algunas mediciones del regulador de velocidad de ventilación del switch

Estas son las mediciones sobre el comportamiento del regulador de ventilación que he incorporado a un switch.

Saga completa

Para comenzar, lo dejé prendido varios días y seguí a ojo el comportamiento apagándolo de noche, luego prendido permanente y finalmente le pasé las conexiones que tenía en el hub.

Mientras, hice adaptaciones al Display Serial para fundamentalmente incorporar la medición de temperatura ambiental y poder realizar las mediciones finales.

 

Ruido

 

2AM, todo cerrado, con un programa medidor en el celular, es lo que hay...

Puse al máximo y lo dejé bajar:

 



Con paciencia tomé nota de los valores en la siguiente tabla:


+-----+------+
| 245 | 71.6 |
+-----+------+
| 234 | 71.0 |
+-----+------+
| 224 | 70.4 |
+-----+------+
| 214 | 70.0 |
+-----+------+
| 204 | 69.7 |
+-----+------+
| 194 | 69.3 |
+-----+------+
| 184 | 68.8 |
+-----+------+
| 174 | 67.8 |
+-----+------+
| 164 | 68.1 |
+-----+------+
| 154 | 67.3 |
+-----+------+
| 144 | 67.8 |
+-----+------+
| 134 | 68.2 |
+-----+------+
| 124 | 67.9 |
+-----+------+
| 114 | 66.0 |
+-----+------+
| 104 | 63.3 |
+-----+------+
|  94 | 63.8 |
+-----+------+
|  84 | 63.0 |
+-----+------+
|   0 | 44.0 |
+-----+------+

 

Subjetivamente no hay dudas de que va bajando el ruido con la velocidad, pero si mirás la tabla hay inconsistencias. Puede ser por la falta de coordinación mía, puede ser que esté muy cerca el celular de la fuente de ruido, se puede estar colando ruido del exterior al que no estoy prestando atención, puede haber algún componente del ruido muy agudo para mí pero que esté siendo medido.


Vibración

 

Entiendo que el ruido debe tener al menos tres componentes:

La hélice contra el aire. Esto depende sin duda de la velocidad y la calidad, la última fuera de mi control.

He leido por ahí una mala elección de frecuencia del PWM podría generar más ruido, algún día lo investigaré. De todos modos la librería de arduino no ofrece cambiarla, no sé por que perverso motivo.

La vibración, resultado de la calidad. Intuyo que distintas velocidades deben producir distintas vibraciones, no necesariamente relacionadas, deben haber algunas velocidades óptimas, para eso hay que ser ingeniero y saber física.

El programa medidor del celular o el sensor mismo no es lo suficientemente sensible, pero mis manos dicen que vibra y bastante, sin números.


 

Temperatura y velocidad en el tiempo

 

Para esto he usado una EDU-CIAA-NXP que recibe los mensajes y le agrega la temperatura exterior y la configuracion, según detallo en https://seguridad-agile.blogspot.com/2020/10/adaptador-usb-rs-232-con-display-usando.html y https://seguridad-agile.blogspot.com/2020/10/modificaciones-al-display-serial.html


Pensé en usar cacti, pues hace dos trabajos, Javier A. lo usaba, pero cuando ví que además de aprender a usarlo y configurarlo había que instalar un mysql, miré fijo y noté que decía "The Complete RRDTool-based Graphing Solution" me pareció mejor ir directo a rrdtool.

Esa noche no podía dormir, así que me machaqué el cerebro contra el teclado y pasé de no entender absolutamente nada a estar en condiciones de darte un introducción muy sencilla, espero que sea correcta, es como un hello world.

 

Instalación


sudo apt install rddtool

 

Configuración


La idea es que rddtool guarda los mensajes en su propia base, que es un buffer circular y pretende que le des datos con regularidad en el tiempo.


  rrdtool create "$DB" --step 60s \
  DS:temp1:GAUGE:120:0:60 \
  DS:temp2:GAUGE:120:0:60 \
  DS:temp3:GAUGE:120:0:60 \
  DS:speed:GAUGE:120:0:255 \
  DS:ref:GAUGE:120:0:60 \
  RRA:LAST:0.5:1:864000


El step es la expectativa de llegada en el tiempo de los mensajes. Cada DS debe ser un DataSet, ponele, tiene un nombre, un tipo, para este caso DERIVE o GAUGE.

Luego heartbeat, tiempo para meter un UNKNOWN. Luego valor mínimo y máximo. Ojo con esos dos valores, si te equivocás, no ves nada pues le pone UNKNOWN.

Luego viene el RRA, que descripción del comportamiento con respecto a como almacenar los valores, por ejemplo LAST es el valor tal como viene pero podrían guardarse el promedio de los últimos N valores recibidos, como para eliminar ruido.

El resto no lo he explorado aún. Entiendo que se pueden poner varios RRA.

 

Insertar


Luego le vas dando mensajes.

Los lees de algún modo y los insertás así, las variables se llaman igual que los DS por disciplina, no hace falta que coincidan, son variables de bash:

rrdtool update "$DB" "N:$temp1:$temp2:$temp3:$speed:$ref"

 

Graficando


y periódicamente podés graficar la información que ya tengas, encontré un RRDTool Wizard muy bonito, ojo que no le pone bien el nombre de la rrd.

  rrdtool graph 'graph.png' \
  --width '800' \
  --height '300' \
  --start end-1h \
  'DEF:t1=temp.rrd:temp1:LAST' \
  'DEF:t2=temp.rrd:temp2:LAST' \
  'DEF:t3=temp.rrd:temp3:LAST' \
  'DEF:sp=temp.rrd:speed:LAST' \
  'DEF:ref=temp.rrd:ref:LAST' \
  'LINE3:ref#FF0000' \
  'LINE2:t2#00f7ff' \
  'LINE2:t3#00FF00' \
  'LINE3:sp#FF00FF' \
  'LINE2:t1#0000FF'


El orden de los LINEx importa pues va pisando.


Graficando temperaturas
Graficando temperaturas

Verde es temperatura ambiente

Rojo temperatura límite

Magenta es la velocidad del cooler

Azul y cyan las temperaturas internas


El programa completo de update


stty -F "$DEV" ispeed "$BAUDRATE" ospeed "$BAUDRATE" \
      cread icanon time 10
exec 99<>$DEV
while true;  do
 read MSG <&99
 #echo $MSG
 MSG=$( echo $MSG | tr "{:,}\"" "     " )
 read _label_cs speed \
      _label_t1 temp1 \
      _label_h1  _h1 \
      _label_t2 temp2 \
      _label_h2 _h2 \
      _label_t3 temp3 \
      _label_h3 _h3 \
      _label_r1 ref \
      _tail  < <(echo $MSG)
 #echo "t1: $temp1 t2: $temp2 t3: $temp3 speed: $speed ref: $ref"
 rrdtool update "$DB" "N:$temp1:$temp2:$temp3:$speed:$ref"
done


Te recuerdo que mis mensajes son así:


{ "CS" : "0", "T1" : "40.10", "H1" : "13.00", "T2" : "40.50", "H2" : "13.00", "T3" : "20.70", "H3" : "51.00", "R1" : "48", "R2" : "48", "R3" : "0", "W1" : "5", "W2" : "5", "W3" : "0", "D2" : "20", "D1" : "10", "D0" : "0", "I1" : "10", "I2" : "20", "I3" : "50", "MS" : "84", "SC" : "1", "DE" : "2", "SI" : "15000"}

y tr "{:,}\"" "     " los convierten en 


CS     0    T1     42.70    H1     14.00    T2     47.90    H2     17.00    T3     23.00    H3     48.00    R1     48    R2     48    R3     0    W1     5    W2     5    W3     0    D2     20    D1     10    D0     0    I1     10    I2     20    I3     50    MS     84    SC     1    DE     2    SI     15000


y el read ... < <(echo $MSG) toma las variables.

 

MQTT


Tambien hice un scriptcito para que mande los mensajes con MQTT

BAUDRATE="19200"
DEV="/dev/ttyUSB2"
TOPIC="/switch/data"
BROKER_IP="127.0.0.1"
BROKER_IP="192.168.1.134"

stty -F "$DEV" ispeed "$BAUDRATE" ospeed "$BAUDRATE" cread icanon time 10
exec 99<>$DEV
while true;  do
  read MSG <&99
  echo "$MSG";
  mosquitto_pub -m "$MSG" -t "$TOPIC" -h "$BROKER_IP"
done

Todo el código en https://github.com/cpantel/CoolerControl




2020/10/15

Modificaciones al display serial

Había hecho un display serial  para poder ver las temperaturas y la velocidad del controlador de ventilación de un switch y cuando me preparé para comenzar a registrar los valores para estudiarlos y poder parametrizar correctamente al algoritmo me encontré con algunos problemas.

Saga completa

 

 

Hardware


El primero, tal como había contado, había sido perder el max232n del poncho educativo debido a falta de pericia. Me pasé entonces al poncho PLC pero no me sirve pues me complica agregar el sensor de temperatura ambiental que necesito como referencia.


Volví al poncho educativo y le saqué el chip, suponiendo que no había roto todo el chip si no la mitad, pero no resultó. Si supiera un poco más o tuviera más dedicación podría haber medido como corresponde, pero fuí directo a "recablear" para usar la mitad supuestamente sana, no funcionó, mala suerte, algún día conseguiré el repuesto, le conecté al poncho educativo el adaptador.


Edu-ciaa-nxp en todo su esplendor
Edu-ciaa-nxp en todo su esplendor

 

En el display las dos temperaturas internas y la externa en la primera linea, en la segunda las temperaturas de referencia y la velocidad, tapada, dice 0. Y luego un "#" que alterna con "@" como heartbeat.


A la izquierda el sensor externo, atras el switch.



La fuente...

 
...calienta más que el resto, cambié uno de los sensores de lugar, lamentablemente no tomé nota de cuál, luego usaré el "peso" para darle mayor o menor participación en las decisiones.



Temperatura ambiental


El display serial tenía que mostrar en la pantallita los valores y dejar pasar los mensajes ida y vuelta y ahora se le agrega incorporar su propia medición. Esto lo resolví agregando un sensor de temperatura a la EDU-CIAA-NXP y actualizando el mensaje JSON recibido desde el controlador.

 

 

La información y el formato de los mensajes


Aquí cometí varios errores. Para comenzar debí haber generado JSON, pues tiene una fácil lectura para el humano y es inmediatamente integrable a cualquier aplicación, más que espero que el 99.99% de los mensajes sean leidos por un proceso, no por humanos.

Otro, siguiendo en la linea de centrada en el usuario, no estoy publicando en cada mensaje la parametría y tengo que pedirla explícitamente. Esto me complica asociar los valores medidos con esta parametría.

En términos de ancho de banda, más que tengo un solo sensor y es por UART que es como una red interna, no me hace diferencia. Esto no significa que de cada mensaje almacene todos los datos, pero esa decisión la hago al momento de almacenar, no de emitir.

Dado que no quiero estar abriendo y cerrando el switch para reprogramar, debo ingeniármelas con lo que hay adentro. Recordemos: hice un sistema parametrizable justamente para evitar reprogramar, hasta que haya una nueva versión, debo lidiar externamente con todo.

Una posibilidad es sumarle la tarea al display serial: como ya tiene que tomar el mensaje que viene y agregarle su propia medición, puede tambien cuando ve pasar la parametría tanto al comienzo como ante cualquier cambio, tomar nota y agregarla.

Tambien puede hacer la conversión a JSON.

La otra es del lado de la compu, que tiene la ventaja de ser mucho más fácil... recalculando... cuál es la gracia de hacerlo fácil...?

Listo, va todo a la edu-ciaa y luego que la app decida qué y cómo almacenar.


+----------+             +--------+
| sensores |             | sensor |
+-----+----+             +---+----+
      |                      |
+-----v--+              +----v-----+          +-----+
|        |  medición +  |          | +        |     |
| Switch |  parametría  | edu-ciaa | medición | app |
|        +-------------->          +---------->     |
+--------+              +----+-----+          +-----+
                             |
                         +---v-----+
                         | display |
                         +---------+

 

Lo que había implementado es una FSM que va buscando los mensajes de reporte y al hallarlos extrae la información y la va pasando caracter a caracter al display.

Voy a tener que cambiar de enfoque, leer por lineas. El problema es que se me bloquea en la lectura, debe ser por ello que la sAPI no lo implementa.

Una manera de lidiar con esto sería pasar a FreeRTOS, una experiencia interesante pero quiero hacerlo así.

Lo que hice finalmente es una sencilla FSM que busca '{'. Si no la encuentra imprime en USB. Si la encuentra, comienza a copiar en un buffer hasta que encuentra '}'.


En ese momento, corre este lindo:


sscanf(buffer,"{ \"T1\" : \"%f\", \"H1\" : \"%f\", \"T2\" : \"%f\", \"H2\" : \"%f\", \"CS\" : \"%d\", \"R1\" : \"%d\", \"R2\" : \"%d\", \"W1\" : \"%d\", \"W2\" : \"%d\", \"D2\" : \"%d\", \"D1\" : \"%d\", \"D0\" : \"%d\", \"I1\" : \"%d\", \"I2\" : \"%d\", \"I3\" : \"%d\", \"MS\" : \"%d\", \"SC\" : \"%d\", \"DE\" : \"%d\", \"SI\" : \"%d\"}", &t1, &h1, &t2, &h2, &cs, &temp_ref_1, &temp_ref_2, &weight_1, &weight_2, &decrement_2, &decrement_1, &decrement_0, &increment_1, &increment_2, &increment_3, &min_speed, &scale, &delta_eq, &sample_interval);

 

lee la temperatura ambiental:

 
float tmp_t3;
float tmp_h3;
if( dht11Read(&tmp_h3, &tmp_t3) ) {
   t3 = tmp_t3;
   h3 = tmp_h3;
} else {
   t3 = -1;
   h3 = -1;
}

 

y luego imprime en USB:


sprintf(buffer,"{ \"CS\" : \"%d\", \"T1\" : \"%.2f\", \"H1\" : \"%.2f\", \"T2\" : \"%.2f\", \"H2\" : \"%.2f\", \"T3\" : \"%.2f\", \"H3\" : \"%.2f\", \"R1\" : \"%d\", \"R2\" : \"%d\", \"R3\" : \"%d\", \"W1\" : \"%d\", \"W2\" : \"%d\", \"W3\" : \"%d\", \"D2\" : \"%d\", \"D1\" : \"%d\", \"D0\" : \"%d\", \"I1\" : \"%d\", \"I2\" : \"%d\", \"I3\" : \"%d\", \"MS\" : \"%d\", \"SC\" : \"%d\", \"DE\" : \"%d\", \"SI\" : \"%d\"}", cs, t1, h1, t2, h2, t3, h3, temp_ref_1, temp_ref_2, temp_ref_3, weight_1, weight_2,weight_3, decrement_2, decrement_1, decrement_0, increment_1, increment_2, increment_3, min_speed, scale, delta_eq, sample_interval);

uartWriteString( UART_USB, buffer);

 

 y display:

 

sprintf(lcdOut0, "%.1f %.1f %.1f\0", t1,t2,t3);
sprintf(lcdOut1, "%d   %d   %d   %c\0",  temp_ref_1, temp_ref_2, cs);
lcdClearAndHome();
lcdSendStringRaw(lcdOut0);
lcdGoToXY( 0, 1 );
lcdSendStringRaw(lcdOut1);

 

El código actual esta en github: controlador y display



Salida JSON
Salida JSON