marți, 22 ianuarie 2013

Arduino ca termometru folosind senzorul KTY81-110 (partea a 2-a)




   Deoarece programul pentru calcularea temperaturii cu termistorul KTY81-110 de pe site-ul Arduino este destul de "ciudat" folosindu-se de calculatiile de la http://www.sprut.de/electronic/temeratur/temp.htm#ptc iar eu am gasit valorile coeficientilor de variatie a rezistentei termistorilor PTC de tipul KTY putin diferiti la http://www.nxp.com/documents/other/SC17_GENERAL_TEMP_1996_3.pdf, m-am apucat sa verific si eu calculele sa vad daca sunt diferente mari.
    Variatia rezistentei unui terrmistor cu variatie pozitiva a rezistentei (PTC) din seria KTY are formula:
    Pentru KTY81-110, la 25 de grade Celsius rezistenta lui este de 1000 ohmi.
    In imaginea de mai jos sunt prezentate valorile gasite pentru A si B din cele 2 surse mentionate mai sus si ce rezultate am obtinut (solutii in ecuatia de gradul 2, diferente, erori, etc) si am constatat ca valorile sunt foarte apropiate si erorile prea mici... calculatia s-a facut exact cum e montat termistorul inseriat cu o rezistenta de 2k7:


    Acum o sa pot scrie un program pentru Arduino mult mai usor de interpretat si apoi sa il pot folosi, de exemplu, la un termostat sau un termometru cu mai multe zone de masurare.

    Am realizat un programior, care respecta modul de calcul indicat mai sus:


/*
  LiquidCrystal Library 

  The circuit - see https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZfMYmYSvTFan1Gb1cHkI7MoWO93ywKD3k6pbVL2ld7No9_YImJHRk-huKGWK4uZljuyAqq_qmEzkhIg7m4zHzGlq-Gsw2wvEysCrFw7pfLpP1qF8udSOUYxjAyRAhFujrCAXf015wDX57/s1600/arduino_1602A_LCD_thermometer_KTY81_110.png
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe 
 modified 22 Nov 2010
 by Tom Igoe

 This example code is in the public domain.

 http://arduino.cc/en/Tutorial/LiquidCrystalDisplay
 http://arduino.cc/en/Tutorial/AnalogInput
 http://arduino.cc/forum/index.php/topic,21371.0.html (for grade sign)
 http://www.tehnic.go.ro
 http://www.niqro.3x.ro
 http://nicuflorica.blogspot.ro
  */

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int sensorPin = A0;  // select the input pin for the KTY81-110 (resistor 2k7 at +5V and A0 + thermistor at A0 and GND)

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("www.tehnic.go.ro");  
  lcd.setCursor(0, 1);
  lcd.print("creat de niq_ro");
  delay (5000);
  lcd.clear();

lcd.print(" termometru cu");  
  lcd.setCursor(3, 1);
  lcd.print("KTY81-110");
  delay (5000);
  lcd.clear();
}

void loop() {
// citire valoare pe intrarea analogica 
  float temp = analogRead(sensorPin); 
  // float sqrt(float temp);
  float ukty = 5 * temp / 1023.0 ;

float a = 0.00001874*1000;
float b = 0.007884*1000;
float c = 1000 - 2700*ukty/(5-ukty);
float delta = b * b - 4 * a * c;
float delta1 = sqrt (delta);
float x2 =(-b + delta1)/(2 * a);
float temp1 = x2 + 25 ;

// partea de afisare
    lcd.setCursor(0, 0);
    lcd.print("temperatura este");
    lcd.setCursor(5, 1);
    lcd.print(temp1);
    // put sign
   lcd.write(0b11011111);
    lcd.print("C");
// se odihneste si el 1,5 secunde
    delay(1500);
// sterge cu buretele tabla :-D
  lcd.clear();
    }

    Spre surprinderea mea, reactia este mai buna la modificarea temperaturii...

    Un scurt filmulet cu noul sketch scris de mine:

    Am mai modificat sketch-ul anterior, punamd mai multe explicatii (comentarii) si facand inainte de afisare o mediere cu valoarea anterioara...


/*
  LiquidCrystal Library 

  The circuit - see https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZfMYmYSvTFan1Gb1cHkI7MoWO93ywKD3k6pbVL2ld7No9_YImJHRk-huKGWK4uZljuyAqq_qmEzkhIg7m4zHzGlq-Gsw2wvEysCrFw7pfLpP1qF8udSOUYxjAyRAhFujrCAXf015wDX57/s1600/arduino_1602A_LCD_thermometer_KTY81_110.png
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe 
 modified 22 Nov 2010
 by Tom Igoe

 This example code is in the public domain.

 http://arduino.cc/en/Tutorial/LiquidCrystalDisplay
 http://arduino.cc/en/Tutorial/AnalogInput
 http://arduino.cc/forum/index.php/topic,21371.0.html (for grade sign)
 http://www.tehnic.go.ro
 http://www.niqro.3x.ro
 http://nicuflorica.blogspot.ro
  */

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int sensorPin = A0;  // se impuna ca intrarea analogica 0 sa fie folosita
// termisorul PTC model KTY81-110 este conectat intre masa si intrarea Ao
// intre plus si intrarea A0 este montata o rezistenta de 2k7 (2700 ohmi)
// consideram ca temperatura initiala este de 20 grade Celsius
float temp2 = 20;
float temp0 = 20;
// valoarea rezistentei inseriate
float R = 2700;

void setup() {
  // anuntam ca afisajul LCD are 16 coloane si 2 randuri
  lcd.begin(16, 2);
  // afisam pe primul rand un mesaj
  lcd.print("www.tehnic.go.ro");  
  // mutam scrierea pe randul 2 si coloana 0 (prima)
    lcd.setCursor(0, 1);
  lcd.print("creat de niq_ro");
  // lasam 5 secunde textele
  delay (5000);
  // stergem ecranul
  lcd.clear();
  
// afisam un al doilea mesaj
lcd.print("  termometru cu");  
  lcd.setCursor(1, 1);
  lcd.print("KTY81-110 ver.2");
  delay (5000);
  lcd.clear();
}

void loop() {
// citire valoare pe intrarea analogica 
  float temp = analogRead(sensorPin); 
  // tensiunea pe senzorul KTY81-110 este
  float ukty = 5 * temp / 1023.0 ;

// definim coeficientii ecuatiei de gradul 2
// coeficintul lui dT^2 este B x R25
float a = 0.00001874*1000;
// coeficientul lui dT este A x R25
float b = 0.007884*1000;
// coeficientul liber 
float c = 1000 - R * ukty / (5 - ukty);
// calculam pe delta
float delta = b * b - 4 * a * c;
// extragem radical din delta
float delta1 = sqrt (delta);
// calculam solutia
float x2 =(-b + delta1)/(2 * a);
// temperatura fata de 0 grade Celsius
float temp1 = x2 + 25 ;
// facem o medie cu valoarea anterioara
float temp2 = (temp1 + temp0) /2.0; 
// partea de afisare
    lcd.setCursor(0, 0);
    lcd.print("temperatura este");
    lcd.setCursor(5, 1);
    lcd.print(temp2);
    // afisam semnul de grad
   lcd.write(0b11011111);
    lcd.print("C");
// se odihneste si el 1,5 secunde
    delay(1500);
// memoreaza ultima temperatura calculata
    temp0 = temp2;
// sterge cu buretele tabla :-D
  lcd.clear();
    }

    Am facut un nou filmulet cu termometrul... de la initializare, apoi cum creste temperatura daca tin senzorul intre degete:

     Deoarece inca nu sunt foarte stabile rezultatele, trebuie sa fac mai multe masuratori, apoi sa fac media si, abia, atunci sa afisez rezultatele...
    M-am hotarat sa faca 100 masuratori la 100ms diferenta intre ele si apoi sa afisez temperatura medie plus o mica pauza de o secunda jumate:


/*
  LiquidCrystal Library 

  The circuit - see https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZfMYmYSvTFan1Gb1cHkI7MoWO93ywKD3k6pbVL2ld7No9_YImJHRk-huKGWK4uZljuyAqq_qmEzkhIg7m4zHzGlq-Gsw2wvEysCrFw7pfLpP1qF8udSOUYxjAyRAhFujrCAXf015wDX57/s1600/arduino_1602A_LCD_thermometer_KTY81_110.png
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe 
 modified 22 Nov 2010
 by Tom Igoe

 This example code is in the public domain.

 http://arduino.cc/en/Tutorial/LiquidCrystalDisplay
 http://arduino.cc/en/Tutorial/AnalogInput
 http://arduino.cc/forum/index.php/topic,21371.0.html (for grade sign)
 http://www.tehnic.go.ro
 http://www.niqro.3x.ro
 http://nicuflorica.blogspot.ro
  */

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int sensorPin = A0;  // se impuna ca intrarea analogica 0 sa fie folosita
// termisorul PTC model KTY81-110 este conectat intre masa si intrarea Ao
// intre plus si intrarea A0 este montata o rezistenta de 2k7 (2700 ohmi)
// valoarea rezistentei inseriate
int R = 2700; // asta e valoare standard
              // dar pot fi variatii de pana  la +/-10%
              // faceti corectiile aici !!!

void setup() {
  // anuntam ca afisajul LCD are 16 coloane si 2 randuri
  lcd.begin(16, 2);
  // afisam pe primul rand un mesaj
  lcd.print("www.tehnic.go.ro");  
  // mutam scrierea pe randul 2 si coloana 0 (prima)
    lcd.setCursor(0, 1);
  lcd.print("creat de niq_ro");
  // lasam 5 secunde textele
  delay (5000);
  // stergem ecranul
  lcd.clear();
  
// afisam un al doilea mesaj
lcd.print("  termometru cu");  
  lcd.setCursor(1, 1);
  lcd.print("KTY81-110 ver.3");
  //delay (5000);
  
}
      
void loop() {

float tempmedie = 0;
float sumatemp;
   // facem o bucla sa citim 100 de valori ale temperaturii
   for (int i=0; i <= 100; i++){
 // citire valoare pe intrarea analogica 
  int temp = analogRead(sensorPin); 
  // tensiunea pe senzorul KTY81-110 este
  float ukty = 5 * temp / 1023.0 ;

// definim coeficientii ecuatiei de gradul 2
// coeficintul lui dT^2 este B x R25
float a = 0.00001874*1000;
// coeficientul lui dT este A x R25
float b = 0.007884*1000;
// coeficientul liber 
float c = 1000 - R * ukty / (5 - ukty);
// calculam pe delta
float delta = b * b - 4 * a * c;
// extragem radical din delta
float delta1 = sqrt (delta);
// calculam solutia
float x2 =(-b + delta1)/(2 * a);
// temperatura fata de 0 grade Celsius
float temp1 = x2 + 25 ;
// aduna temperatura cu suma valoarilor anterioare
 sumatemp = sumatemp + temp1;
// se mai odihneste si el 100ms 
 delay(100);
   }
   tempmedie = sumatemp / 100;

 // partea de afisare 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("temperatura este");
    lcd.setCursor(5, 1);
    lcd.print(tempmedie);
    // afisam semnul de grad
   lcd.write(0b11011111);
    lcd.print("C ");
   delay(1500);
  // sterge cu buretele tabla :-D
 // lcd.clear();
  return;
  } 

   Varianta 3 se prezinta cam asa:

    
    Am zis sa fac si niste corectii, in sensul ca rezistenta mea nu are exact 2700 ohmi, am considerat ca am cam 2650 ohmi (e facuta dintr-o rezistenta de 2k2 care are 2140 ohmi la masurare si din 2 rezistente de 1k in paralel care au cam 1027 ohmi, deci masurat 2153 ohmi)
si la temperatura medie am facut o mica ajustare (de 0,3 grade Celsius).







    Sketch-ul modificat (versiunea 3m) este:
/*
  LiquidCrystal Library 



 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)


 Library originally added 18 Apr 2008

 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe 
 modified 22 Nov 2010
 by Tom Igoe


 This example code is in the public domain.




  */


// include the library code:

#include <LiquidCrystal.h>


// initialize the library with the numbers of the interface pins

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int sensorPin = A0;  // se impuna ca intrarea analogica 0 sa fie folosita
// termisorul PTC model KTY81-110 este conectat intre masa si intrarea Ao
// intre plus si intrarea A0 este montata o rezistenta de 2k7 (2700 ohmi)
// valoarea rezistentei inseriate
int R = 2650; // valoatre standard 2700
// corectia bruta s-a facut pentru a arata 0 in apa de deasupra unei bucati de gheata


void setup() {

  // anuntam ca afisajul LCD are 16 coloane si 2 randuri
  lcd.begin(16, 2);
  // afisam pe primul rand un mesaj
  lcd.print("www.tehnic.go.ro");  
  // mutam scrierea pe randul 2 si coloana 0 (prima)
    lcd.setCursor(0, 1);
  lcd.print("creat de niq_ro");
  // lasam 5 secunde textele
  delay (5000);
  // stergem ecranul
  lcd.clear();
  
// afisam un al doilea mesaj
lcd.print("  termometru cu");  
  lcd.setCursor(0, 1);
  lcd.print("KTY81-110 ver.3m");
  //delay (2000);
}


      

void loop() {

float tempmedie = 0;
float sumatemp;
   // facem o bucla sa citim 100 de valori ale temperaturii
   for (int i=1; i <= 100; i++){
 // citire valoare pe intrarea analogica 
  int temp = analogRead(sensorPin); 
  // tensiunea pe senzorul KTY81-110 este
  float ukty = 5 * temp / 1023.0 ;


// definim coeficientii ecuatiei de gradul 2

// coeficintul lui dT^2 este B x R25
float a = 0.00001874*1000;
// coeficientul lui dT este A x R25
float b = 0.007884*1000;
// coeficientul liber 
float c = 1000 - R * ukty / (5 - ukty);
// calculam pe delta
float delta = b * b - 4 * a * c;
// extragem radical din delta
float delta1 = sqrt (delta);
// calculam solutia
float x2 =(-b + delta1)/(2 * a);
// temperatura fata de 0 grade Celsius
float temp1 = x2 + 25 ;
// aduna temperatura cu suma valoarilor anterioare
 sumatemp = sumatemp + temp1;
// se mai odihneste si el 100ms 
 delay(100);
   }
   tempmedie = sumatemp / 100;
 // aplicam corectie fina si la rezultat
   tempmedie = tempmedie + 0.3;
 // partea de afisare 
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("temperatura este");
    lcd.setCursor(5, 1);
    lcd.print(tempmedie);
    // afisam semnul de grad
   lcd.write(0b11011111);
    lcd.print("C ");
   delay(1500);
  // sterge cu buretele tabla :-D
 // lcd.clear();
  return;
  } 
    Un filmulet cu o calite mai buna a imaginii, fata de celelalte, este:

Niciun comentariu:

Trimiteți un comentariu