mercredi 13 avril 2011

Thermo MO

Mise en oeuvre du programme Thermo au niveau hardware avec utilisation d'un transistor sur la sortie destinée au chauffage.





Transistor NPN

J'ai utilisé un BC337 (voir datasheet). Il sert d'interrupteur, ce qui n'est pas indispensable dans ce montage.
Plus tard il sera remplacé par un relais pour éviter les probables retours de tensions.

Thermistor


C'est une résistance dont la capacité change avec la température.
Voir le site Sparkfun.

Le branchement


J'utilise des résistances 330 ohms et 10k ohms.
Ces schémas ont été fait avec Fritzing, les photos et videos avec l'iphone.




La LED jaune est toujours allumée. La LED rouge est pilotée par le transistor, qui laisse passer le courant si la température est inférieure à la température cible (ici 26°C). En mettant le doigt sur le thermistor, la température mesurée augmente, et passe au dessus de la limite, du coup le chauffage symbolisé par la LED rouge s'éteint.


Voici le résultat sur le Serial monitor (capturé avec CamStudio).
SRAM restante - heure jour - température cible - température mesurée




Le programme
Ci-dessous le programme complet.




#include <stdio.h>
#include <avr/pgmspace.h>
#include <EEPROM.h>
/*  
*   0 : initialisation de l'heure
*   1 : secondes
*   2 : minutes
*   3 : heures
*   4 : jours
*/


// Initialisation de l'heure
byte heures = 20;
byte minutes = 45;
byte secondes = 0;
byte jours = 2;
const byte reset = 1;
const unsigned int uneSeconde = 1000;
/* 
*  0 : "Lundi";
*  1 : "Mardi";
*  2 : "Mercredi";
*  3 : "Jeudi";
*  4 : "Vendredi";
*  5 : "Samedi";
*  6 : "Dimanche";
*/


// Horaires de chauffage
const int nbHoraires = 19;


const prog_uint16_t horaireDebutJour[] PROGMEM = {     0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6,    6,     6    };
const prog_uint16_t horaireFinJour[] PROGMEM = {       0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6,    6,     6    };
const prog_uint16_t horaireDebutHeure[] PROGMEM = {    5, 11, 17, 5, 11, 17, 5, 11, 17, 5, 11, 17, 5, 11, 17, 8, 16,   16,    8    };
const prog_uint16_t horaireDebutMinute[] PROGMEM = {  45, 30, 45, 45, 30, 45, 45, 30, 45, 45, 30, 45, 45, 30, 45, 0, 41,   44,    0    };
const prog_uint16_t horaireFinHeure[] PROGMEM = {      8, 14, 23, 8, 14, 23, 8, 14, 23, 8, 14, 23, 8, 14, 23, 23, 16,   16,    23   };
const prog_uint16_t horaireFinMinute[] PROGMEM = {    20, 5, 0, 20, 5, 0, 20, 5, 0, 20, 5, 0, 20, 5, 0, 0, 42,   45,    0    };


const int horaireTemperature[] = {             220, 220, 220, 220, 220, 220, 220, 220, 260, 220, 220, 220, 220, 220, 220, 220, 230,  240,   220  };


//Optimisation des horaires
unsigned int horaireDebut[nbHoraires];
unsigned int horaireFin[nbHoraires];
unsigned int horaireEnCours;


const int temperatureParDefaut = 195;


// Temps de chauffage du jour
int dureeChauffage = 0;


// Horloge
unsigned long previousMillis = 0;


/*
La temperature est calculé à  partir du tableau de valeur à l'index sensorValue - 238.
Taille du tableau : 772
*/
// const prog_uint16_t temperatures[] PROGMEM
const prog_uint16_t temperatures[] PROGMEM = { 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 164, 165, 166, 167, 167, 168, 169, 170, 171, 172, 173, 174, 175, 175, 176, 177, 178, 179, 180, 181, 182, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 197, 198, 199, 200, 201, 202, 203, 204, 205, 205, 206, 207, 208, 209, 210, 211, 212, 212, 213, 214, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 225, 226, 227, 228, 228, 229, 230, 231, 232, 233, 234, 235, 235, 236, 237, 238, 239, 240, 241, 242, 243, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 252, 253, 254, 255, 256, 257, 258, 259, 260, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 422, 423, 424, 425, 426, 427, 428, 429, 430, 432, 433, 434, 435, 436, 437, 438, 439, 441, 442, 443, 444, 445, 446, 448, 449, 450, 451, 452, 453, 455, 456, 457, 458, 459, 460, 462, 463, 464, 465, 466, 468, 469, 470, 471, 472, 474, 475, 476, 477, 479, 480, 481, 482, 484, 485, 486, 487, 489, 490, 491, 492, 494, 495, 496, 498, 499, 500, 501, 503, 504, 505, 507, 508, 509, 511, 512, 513, 515, 516, 517, 519, 520, 521, 523, 524, 525, 527, 528, 530, 531, 532, 534, 535, 537, 538, 539, 541, 542, 544, 545, 547, 548, 550, 551, 552, 554, 555, 557, 558, 560, 561, 563, 564, 566, 567, 569, 570, 572, 574, 575, 577, 578, 580, 581, 583, 585, 586, 588, 589, 591, 593, 594, 596, 598, 599, 601, 603, 604, 606, 608, 609, 611, 613, 614, 616, 618, 620, 621, 623, 625, 627, 628, 630, 632, 634, 636, 638, 639, 641, 643, 645, 647, 649, 651, 653, 654, 656, 658, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 683, 685, 687, 689, 691, 693, 695, 697, 700, 702, 704, 706, 708, 711, 713, 715, 718, 720, 722, 725, 727, 729, 732, 734, 737, 739, 741, 744, 746, 749, 752, 754, 757, 759, 762, 764, 767, 770, 773, 775, 778, 781, 784, 786, 789, 792, 795, 798, 801, 804, 807, 810, 813, 816, 819, 822, 825, 829, 832, 835, 838, 842, 845, 848, 852, 855, 859, 862, 866, 869, 873, 877, 881, 884, 888, 892, 896, 900, 904, 908, 912, 916, 920, 925, 929, 933, 938, 942, 947, 952, 956, 961, 966, 971, 976, 981, 986, 991, 997, 1002, 1007, 1013, 1019, 1024, 1030, 1036, 1042, 1049, 1055, 1061, 1068, 1075, 1082, 1088, 1096, 1103, 1110, 1118, 1126, 1134, 1142, 1150, 1159, 1168, 1177, 1186, 1196, 1206, 1216, 1226, 1237, 1248, 1260, 1272, 1284, 1297, 1310, 1324, 1338, 1353, 1369, 1385, 1402, 1420, 1439, 1459, 1480, 1502 };


const char* NOMS_JOURS[] = { "Lun","Mar","Mer","Jeu","Ven","Sam","Dim" };
const char SEPARATEUR[] = " - ";


void setup() {
  Serial.begin(9600);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  analogWrite(9, 10);
  
  byte init = EEPROM.read(0);
  Serial.println(init,DEC);
  if ((init == 1) && (reset != 1)) {
    secondes = EEPROM.read(1);
    minutes = EEPROM.read(2);
    heures = EEPROM.read(3);
    jours = EEPROM.read(4);
  } else {
    EEPROM.write(1,secondes);
    EEPROM.write(2,minutes);
    EEPROM.write(3,heures);
    EEPROM.write(4,jours);
    EEPROM.write(0,1);
  }
  calculerOptimisationHoraires();
}


void loop() {
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis > uneSeconde) {
    previousMillis = millis();
    
    uneSecondeDePlus();
    int therm = getTemperature();
    int cible = getTemperatureCible();
  
    if(therm < cible) {
      digitalWrite(8, HIGH);
      dureeChauffage ++;
    } else {
      digitalWrite(8, LOW);
    }
    
    Serial.print(availableMemory(),DEC);
    Serial.print(SEPARATEUR);
    Serial.print(getTime(heures,minutes,secondes,jours));
    Serial.print(SEPARATEUR);
    Serial.print(cible,DEC);
    Serial.print(SEPARATEUR);
    Serial.println(therm , DEC);
  }


}


void calculerOptimisationHoraires() {
  for(int i=0;i<nbHoraires;i++) {
    horaireDebut[i] = pgm_read_word_near(horaireDebutJour + i) * 1440 + pgm_read_word_near(horaireDebutHeure + i) * 60 + pgm_read_word_near(horaireDebutMinute + i);
    horaireFin[i] = pgm_read_word_near(horaireFinJour + i) * 1440 + pgm_read_word_near(horaireFinHeure + i) * 60 + pgm_read_word_near(horaireFinMinute + i);
  }
  horaireEnCours = jours * 1440 + heures * 60 + minutes;
}


const int getTemperature() {
  int sensorValue = analogRead(A0);
  int index = constrain(sensorValue - 238, 0, 771);
  return pgm_read_word_near(temperatures + index);
  //return temperatures[index];
}


void uneSecondeDePlus() {
  secondes++;
  if(secondes >= 60) {
    secondes = 0;
    minutes++;
    horaireEnCours = jours * 1440 + heures * 60 + minutes;
  }
  if(minutes >= 60) {
    minutes = 0;
    heures++;
  }
  if(heures >= 24) {
    heures = 0;
    jours++;
    dureeChauffage = 0;
  }
  if(jours >= 7) {
    jours = 0;
  }
  EEPROM.write(1,secondes);
  EEPROM.write(2,minutes);
  EEPROM.write(3,heures);
  EEPROM.write(4,jours);
}


char* getTime(byte hh,byte mm,byte ss,byte jj) {
  char myTime[18];
  sprintf(myTime,"%02d:%02d:%02d %s",hh,mm,ss,NOMS_JOURS[jj]);
  return myTime;
}


const int getTemperatureCible() {
  for(int i=0;i<nbHoraires;i++) {
    if ((horaireDebut[i] <= horaireEnCours) && (horaireFin[i] >= horaireEnCours)) {
      return horaireTemperature[i];
    }
  }
  return temperatureParDefaut;
}


int availableMemory() {
  int size = 2048; // Use 2048 with ATmega328
  byte *buf;
  while ((buf = (byte *) malloc(--size)) == NULL)
    ;
  free(buf);
  return size;
}

Aucun commentaire:

Enregistrer un commentaire