Termometru cu Arduino și ieșire... video

 Autor:   Publicat pe:   Actualizat pe:  2020-02-08T20:48:54Z

Placa Arduino poate genera un semnal video analogic folosind biblioteca TVout. Construiește un termometru simplu care afișează temperatura pe televizor.

Semnalul video analogic a fost înlocuit treptat cu cel digital care oferă o calitate și o rezoluție mai bune ale imaginii, fără perturbări. Astfel, dispozitivele de recepție a semnalului digital au devenit din ce în ce mai ușor de găsit și prețul lor a scăzut. Dar, generarea și modularea în radiofrecvență (RF) a unui semnal video digital (stream) este dificilă, necesitând echipamente costisitoare. În schimb, vechiul semnal video analogic este ușor de generat și poate fi modulat RF cu dispozitive simple. Modulatoare RF pot fi găsite în console de jocuri vechi, receptoare, playere VCR etc.

Un mod simplu de a genera semnalul video analogic este folosind un microcontroller. În continuare voi folosi o placă Arduino compatibilă împreună cu biblioteca TVout. ATmega 328p nu este foarte performant în acest scop, dar poate genera un semnal video alb-negru ce simulează un afișaj de 128x96 pixeli. Biblioteca folosește întreruperi, de aceea unele funcții ale microcontroller-ului nu pot fi folosite concomitent cu generarea semnalului video.

Termometru cu Arduino și ieșire video

Totuși, putem citi un senzor fără a induce întârzieri la generarea impulsurilor specifice semnalului video. Problema este că nu orice senzor. Am încercat inițial cu un senzor pe protocol 1-Wire (DS18B20). Fără succes. La fiecare citire a senzorului, semnalul video este afectat (se pierde sincronizarea). Similar, biblioteca Wire (pentru I2C) interferă cu TVout, făcând imposibilă producerea semnalului video.

Am descoperit că pot folosi senzori analogici fără probleme. Funcția analogRead() nu alterează semnalul video. Senzorii analogici nu sunt mai puțin buni decât cei digitali, dar necesită calibrare. Am realizat următorul circuit în acest scop.

Schema termometrului cu ieșire video

Schema termometrului cu ieșire video

Schema este simplă. Am realizat montajul pe o placă de test de tip breadboard. Eu am folosit un modul senzor de temperatură dintr-un kit, dar acesta poate fi înlocuit, după cum se vede în schemă de un rezistor de 100 ohmi și un termistor. Se obține astfel un divizor de tensiune a cărui ieșire variază cu temperatura.

Montajul termometrului cu ieșire video

Montajul termometrului cu ieșire video

Se observă o mufă tip jack audio. Am folosit-o pentru că se potrivea în breadboard și am aplicat semnalul video pe un pin. Pe celălalt pin va fi generat un semnal audio. Pentru conectarea la TV am folosit un cablu adaptor Jack-RCA.

Termometrul afișează temperatura citită, dar și minima și maxima înregistrate de când rulează programul. Un mic grafic arată variația temperaturii pe aproape 2 minute (mai exact pe 116 secunde). De fiecare dată când este citită o valoare minimă sau maximă un ton de 1 kHz este generat pe ieșirea audio.

Biblioteca TVout este necesară pentru compilarea schiței. Se poate instala din Library Manager, în Arduino IDE. Sunt ceva probleme cu organizarea fișierelor sursă ale acestei biblioteci care vor produce o eroare la compilare. Poți descărca de la sfârșitul acestui articol o variantă modificată, funcțională. Sau poți să ștergi dosarul TVout și să redenumești TVOutfonts în utility. Toate aceste subfoldere se găsesc în folderul bibliotecii. Această problemă a fost raportată dezvoltatorului, dar biblioteca nu a fost modificată (încă).

Codul complet este următorul:

#include <TVout.h>
#include <utility/fontALL.h>

TVout TV;
float minTemp = 100, maxTemp = 0;
byte graph[117] = { 0 };

// Functie pentru conversia tensiunii divizorului in temperatura
// https://tkkrlab.nl/wiki/Arduino_KY-013_Temperature_sensor_module
double readThermistor(int RawADC) {
  double Temp;
  Temp = log(10000.0 * ((1024.0 / RawADC - 1)));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp )) * Temp );
  Temp = Temp - 273.15;            // Kelvin - Celsius
  return Temp;
}

void draw_initial_screen() {
  TV.clear_screen();

  TV.set_cursor(19, 3);
  TV.select_font(font8x8);
  TV.print("Termometru");

  TV.draw_rect(0, 0, 125, 14, 1, 2);

  TV.select_font(font6x8);
  TV.set_cursor(0, 20);
  TV.print("MIN");

  TV.set_cursor(43, 20);
  TV.print("Actual");

  TV.set_cursor(109, 20);
  TV.print("MAX");

  TV.select_font(font4x6);
  TV.set_cursor(4, 86);
  TV.print("0");
  TV.set_cursor(0, 76);
  TV.print("10");
  TV.set_cursor(0, 66);
  TV.print("20");
  TV.set_cursor(0, 56);
  TV.print("30");
  TV.set_cursor(0, 46);
  TV.print("40");

  TV.draw_line(10, 46, 10, 88, 1);
  TV.draw_line(10, 88, 126, 88, 1);
  TV.set_pixel(9, 48, 1);
  TV.set_pixel(11, 48, 1);
  TV.set_pixel(9, 58, 1);
  TV.set_pixel(11, 58, 1);
  TV.set_pixel(9, 68, 1);
  TV.set_pixel(11, 68, 1);
  TV.set_pixel(9, 78, 1);
  TV.set_pixel(11, 78, 1);

  TV.set_cursor(67, 90);
  TV.select_font(font4x6);
  TV.print("Pe doua minute");
}

void display_min(float mt) {
  TV.set_cursor(0, 33);
  TV.select_font(font6x8);
  if (mt < 10) TV.print(" ");
  TV.print(mt, 1);
}

void display_max(float mt) {
  TV.set_cursor(103, 33);
  TV.select_font(font6x8);
  if (mt < 10) TV.print(" ");
  TV.print(mt, 1);
}

void display_current(float t) {
  TV.set_cursor(42, 32);
  TV.select_font(font8x8);
  TV.print(t, 2);
  TV.draw_rect(40, 30, 44, 12, 1, -1);
}

void setup()  {
  TV.begin(PAL, 128, 96);
  draw_initial_screen();
  delay(1000);
}

void display_graph(float ct) {
  for (int i = 0; i < 116; i++) {
    graph[i] = graph[i + 1];
    TV.set_pixel(i + 10, 88 - graph[i], 1);
    if (graph[i + 1] > 0)
      TV.set_pixel(i + 11, 88 - graph[i + 1], 0);
  }
  graph[116] = (byte)ct;
  if (graph[116] > 40) graph[116] = 40;
}

void loop() {
  float currTemp = readThermistor(analogRead(A2));

  display_current(currTemp);
  display_graph(currTemp);

  if (currTemp < minTemp) {
    minTemp = currTemp;
    display_min(minTemp);
    TV.tone(1000, 200);
  }

  if (currTemp > maxTemp) {
    maxTemp = currTemp;
    display_max(maxTemp);
    TV.tone(1000, 200);
  }

  delay(1000);
}

Generarea semnalului video utilizează cam toate resursele microcontroller-ului. Totuși, digitalRead() și digitalWrite(), cât și analogRead() par să funcționeze. Este posibilă astfel interfațarea plăcii cu senzori diverși dar și comanda unor relee sau alte dispozitive. Știind acest lucru, probabil că aș fi putut folosi un senzor digital de tip DHT11/DHT22/AM2302, deoarece citirea acestora se poate face fără folosirea de întreruperi.

Mai departe, ieșirea audio-video poate fi conectată la un modulator RF și integrată într-un sistem video cu circuit închis. Nu poți folosi un modulator RF controlat prin I2C de aceeași placă Arduino. Dar există și modulatoare cu frecvență fixă, care necesită doar tensiune de alimentare și semnal video.

Resurse

Niciun comentariu :

Trimiteți un comentariu

Vă recomandăm să citiți regulamentul comentariilor înainte de a scrie un comentariu.