Termómetro conectado sin contacto

Fuente: disk_91 

Recientemente hice un post sobre cómo hacer un sistema de alarma pandémica basado en termómetros conectados de bajo costo. Esta publicación fue más sobre el modelo de organización y el modelo de negocio que sobre la solución tecnológica y la implementación. Así que también quería seguir investigando la solución del termómetro conectado, principalmente por diversión. Como me ha patrocinado digitspace.com para un hardware gratuito, ha tenido la oportunidad de probar el módulo de termómetros sin contacto.

El diseño que voy a proponer en esta publicación no se aplicará a los termómetros conectados de bajo costo ya que la tecnología que voy a usar es mucho más costosa que la que propuse en mi publicación anterior.

Dicho esto, este diseño puede ser útil para empresas, sitios públicos o cabinas de termómetro de acceso libre que cualquiera quisiera diseñar a bajo costo.

PRE-REQUISITOS

Hardware involved (involucrado)

El involved hardware ha sido elegido por su conveniencia porque quiero hacerlo rápidamente y quiero reutilizar la mayoría de los componentes disponibles en mi stock.

  • MKRFOX1200 – Arduino Placa Zero con Módulo de Comunicación Sigfox
  • MLX90614 Sensor de temperatura sin-contacto
  • GP2Y0A02YK Sensor de proximidad infrarrojo
  • 2xLED + 2xR330 Ohm
  • 2xR10K for I2C pullup

El consumo del sensor de proximidad es de aproximadamente 10 mA, por lo que probaré su alimentación desde un GPIO. El GPIO para un SAMD21 (Arduino Zero) se limita a 2-7 mA, necesitamos conducir esta corriente desde el exterior. Para esto podemos agregar:

  • 1x 2N2222 transistor
  • 1x 330 Ohm

El precio total de este sensor es de unos 75 €.

Eventualmente, podríamos agregar un Módulo NFC o un Módulo RFID  para acceder a la identidad del usuario y vincular la información con la apertura de una puerta y para la trazabilidad (siempre que sea legal en su país). Es mejor utilizar estos módulos con un timbre para confirmar la lectura de la tarjeta.

Bibliotecas involucradas

La ventaja de la plataforma Arduino es acceder a todas las bibliotecas ya empaquetadas. Eso es realmente genial para el enfoque rápido y sucio de la creación de prototipos.

  • Todas las bibliotecas para ejecutar el MKRFOX1200 como se documenta en mi publicación anterior linkeada.
  • La biblioteca Arduino MLX90614también se puede instalar desde el administrador de la Biblioteca Arduino buscando MLX90614.
  • La biblioteca ZSharpIR para controlar el sensor de distancia GP2Y0A02YK disponible desde el administrador de la biblioteca Arduino.

Sensor térmico y distancia

El sensor térmico mide la temperatura ambiente y la temperatura de un objeto. La temperatura de este objeto es lo que nos interesa. La resolución es de 0,14 ° C ajustada a la medición del cuerpo humano.

La temperatura del objeto depende de la distancia con el sensor. Entonces necesitamos determinar la distancia correcta para hacer la medición. Para reducir el consumo de energía, también necesitamos activar el sensor de distancia por un corto período de tiempo de forma regular.

Luego, tendremos que gestionar la distancia correcta para tener la misma referencia en las mediciones e indicarle al usuario cuándo debe moverse para encontrarla y cuándo debe estabilizarse. Esto se indicará con un LED. El led verde parpadea rápidamente cuando tiene que encontrar la distancia correcta, luego parpadea lentamente cuando tiene que mantenerse estable. El led finalmente estará encendido durante 5 segundos una vez que se haya capturado la temperatura. El color del led puede cambiar depende del nivel de temperatura.

Necesitamos investigar el nivel de temperatura para cambiar entre la temperatura corporal superior y la inferior y verificar cuál es el impacto de la temperatura ambiental en la temperatura del objeto medido. Ese es un TODO importante para un sistema de este tipo.

Aquí está básicamente el (pseudo) código utilizado para esto

typedef enum {
   WAITFORSOMEONE = 0,
   SOMEONEHERE,
   GOODDISTANCE,
   DISTANCESTABLE,
   WAITFORLEAVING
} state_e;

switch(curentState) {
    case WAITFORSOMEONE:
      // measure distance and compare reference
      if ( distance < DIST_OUT ) {
        curentState = SOMEONEHERE;
      } else {
        // if no-one we can go to low-power and sleep
        sleepTime = 800;
      }
    break;  

    case SOMEONEHERE:
      // wait for the right distance by measuring multiple point
      // and keeping the min & max
      // make the green led flashing fast
      if ( dmin > DIST_MIN && dmax < DIST_MAX ) {
        curentState = GOODDISTANCE;
      } else if ( dmin > DIST_OUT ) {
        curentState = WAITFORSOMEONE;
      } 
      break;

    case GOODDISTANCE:
      // ensure stability of the distance
      // make the green led flashing slowly
      if ( distance > DIST_MIN && distance < DIST_MAX ) {
        curentState = DISTANCESTABLE;
      } else {
        curentState = SOMEONEHERE;
      }
      break;

    case DISTANCESTABLE:
      // measure the temperature
      // measure the distance once again
      if ( distance > DIST_MIN && distance < DIST_MAX ) {
        // reading sounds valid
        // light the right led color according to 
        // the temperature reading and maintain it 5 seconds
        curentState = WAITFORLEAVING;
      } else {
        curentState = SOMEONEHERE;
      }
      break;
      
    case WAITFORLEAVING:
      // wait for distance to be higher than our Noone reference
      // during this time the led stays on
      if ( distance > DIST_OUT ) {
        // Siwtch leds off
        curentState = WAITFORSOMEONE;
      } else {
        // wait a bit for people leaving
      }
      break;
  }

Agregar la capa de comunicación

Necesitamos reportar la información medida en el marco de Sigfox. La temperatura será de 16 bits con signo codificado en grados centígrados.

typedef struct __attribute__ ((packed)) sigfox_message {
  int16_t envTemp;
  int16_t objTemp;
  uint64_t nfcId;
} SigfoxMessage;

Dejo que 64 bits codifiquen los bits inferiores de una tarjeta NFC (agregaré esto más adelante)

Ahora podemos enviar el marco de Sigfox en caso de éxito:

case DISTANCESTABLE:
      digitalWrite(GREENLEDPIN,LOW);
      envTemp = mlx.readAmbientTempC();
      objTemp = mlx.readObjectTempC();
      distance=ZSharpIR.distance();
      if ( distance > DIST_MIN &amp;&amp; distance < DIST_MAX ) {
        // reading sounds valid
        curentState = WAITFORLEAVING;
        // send the message
        msg.envTemp = (int16_t)(envTemp*100);
        msg.objTemp = (int16_t)(objTemp*100);
        msg.nfcId = 0;
        SigFox.beginPacket();
        SigFox.write((uint8_t*)&amp;msg,sizeof(msg));
        SigFox.endPacket(false);
        digitalWrite(GREENLEDPIN,HIGH);
      } else {
        curentState = SOMEONEHERE;
        sleepTime = 1000;
      }
      break;
En el backend de Sigfox podemos configurar la decodificación de cuadros asociada
envTemp::int:16:little-endian objTemp::int:16:little-endian nfcId::uint:64:little-endian
Y ahora para cada una de las temperaturas obtenemos el siguiente resultado en el backend de Sigfox:

Los valores aquí deben dividirse entre 100 para obtener la temperatura en grados Celsius.

Agregar un lector rfid

El lector RFID utiliza la comunicación SPI y es mejor tener un timbre asociado para la retroalimentación del usuario sobre la lectura de la tarjeta. Aquí está el esquema dedicado para una mejor lectura.

El código RFID simplemente se agrega en la cabecera del bucle principal:

// Read the card is present and update the corresponding variable
  if ( rfid.PICC_IsNewCardPresent() ) {
     if(rfid.PICC_ReadCardSerial()) {
        pinMode(BUZZ_PIN, OUTPUT);
        tone(BUZZ_PIN,2000);
        delay(200);
        pinMode(BUZZ_PIN, INPUT); // because noTone seems to be inefficient
        for (byte i = 0; i < rfid.uid.size; ++i) { 
          rfidId <<= 8;
          rfidId |= rfid.uid.uidByte[i];
        }
     }
  }

Con la insignia que tengo, el valor devuelto es un valor de 32 bits. Este valor se agregará en la comunicación Sigfox. Se borra cuando alguien se va o cuando la lectura de temperatura ha sido un éxito.

Exactitud

Lo más importante y la parte más compleja es la precisión. Actualmente la solución no es precisa. Básicamente, la temperatura medida no es la temperatura real del objeto, pero tenemos algo como:

T-medido = F (T-obj, T-ambiente, Distancia)

Necesito investigar sobre la relación. El punto límite principal es actualmente la distancia, ya que el sensor seleccionado no funciona, así que voy a hacer una prueba con sensores de distancia más precisos y de corto alcance como el  VL53L1X.

Conclusión

El sistema ha sido diseñado rápidamente y no es realmente costoso. Dicho esto, veo alguna limitación:

El sensor de proximidad tiene un rango mínimo de alrededor de 20 centímetros, esto está un poco lejos del sensor en mi punto de vista.
Todavía no domino la calibración del sensor para obtener una temperatura corporal confiable. Supongo que esto puede ser factible ya que este tipo de sensor está hecho para esto, pero con respecto al impacto de la temperatura ambiental y la distancia, debemos investigar para que funcione correctamente.
Si está interesado en hacer que esto funcione para continuar investigando sobre esto, puede encontrar el código disponible en mi github.