dimanche 15 mai 2011

Branchement thermo3

La version thermo3 comprend la thermorésistance, le relais avec transistor, un bouton poussoir (pour changer de mode d'affichage), le LCD et le module USB.










Mode d'affichage

Le bouton poussoir permet de changer de mode d'affichage.

  • Premier mode : date, heure, température actuelle et température cible.
  • Deuxième mode : Durée de chauffage de la semaine passée, par jour, en minutes.


Vu que le contenu du deuxième mode ne tient pas sur l'afficheur, j'utilise la fonction scrollDisplayLeft pour faire défiler le contenu facilement.
Les durées de chauffage sont conservées dans l'EEPROM. Pour lire et écrire un int en mémoire, j'utilise les fonctions EEPROMWriteInt et EEPROMReadInt, trouvées sur le forum Arduino.


Code Source


#include <stdio.h>
#include <avr/pgmspace.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
/*
*   0 : initialisation de l'heure
*   1 : secondes
*   2 : minutes
*   3 : heures
*   4 : jours
*   6 et 7 : durée de chauffage en cours
*   8 et 9 : durée de chauffage de Lundi
*   10 et 11 : durée de chauffage de Mardi
*   12 et 13 : durée de chauffage de Mercredi
*   14 et 15 : durée de chauffage de Jeudi
*   16 et 17 : durée de chauffage de Vendredi
*   18 et 19 : durée de chauffage de Samedi
*   20 et 21 : durée de chauffage de Dimanche
*/

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

// Initialisation de l'heure
byte heures = 16;
byte minutes = 40;
byte secondes = 0;
byte jours = 6;
const byte reset = 1;
const unsigned int uneSeconde = 0;
/*
*  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,   50,    0    };

const int horaireTemperature[] = {             220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 280,  280,   280  };

//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;
int tabDureeChauffage[7];

// 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[] = " - ";

int modeAffichage = 0;
int positionLcd = 0;

void setup() {
  lcd.begin(16, 2);
  Serial.begin(9600);
  pinMode(8, OUTPUT);
  pinMode(13, OUTPUT);
 
  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();
 
  dureeChauffage = EEPROMReadInt(6);
}

void loop() {
  unsigned long currentMillis = millis();
  digitalWrite(13, LOW);
 
  if (digitalRead(A1) == HIGH) {
    modeAffichage++;
    if(modeAffichage >= 2) modeAffichage = 0;
  }
 
  if(currentMillis - previousMillis > uneSeconde) {
    previousMillis = millis();
    digitalWrite(13, HIGH);
   
    uneSecondeDePlus();
   
    int therm = getTemperature();
    int cible = getTemperatureCible();
   
    // on peut changer d'état toutes les minutes
    if (secondes % 60 == 0) {
      if (therm < cible) {
        digitalWrite(8, HIGH);
        dureeChauffage ++;
        EEPROMWriteInt(6,dureeChauffage);
      } else {
        digitalWrite(8, LOW);
      }
    }
   
    affichage(cible, therm);
  }

}

void affichage(int cible, int therm) {
  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.print(therm, DEC);
  Serial.print(SEPARATEUR);
  Serial.println(modeAffichage, DEC);
 
  char myTemp[28];
 
  if(modeAffichage == 0) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(getTime(heures,minutes,secondes,jours));
   
    lcd.setCursor(0, 1);
    sprintf(myTemp,"%d.%d",therm/10,therm%10);
    lcd.print(myTemp);
   
    lcd.setCursor(6, 1);
    sprintf(myTemp,"%d.%d",cible/10,cible%10);
    lcd.print(myTemp);
   
    lcd.setCursor(13, 1);
    sprintf(myTemp,"%03d",dureeChauffage);
    lcd.print(myTemp);
   
  } else if(modeAffichage == 1) {
    lcd.scrollDisplayLeft();
   
    lcd.setCursor(0, 0);
    sprintf(myTemp," %s %s %s %s %s %s %s",NOMS_JOURS[0],NOMS_JOURS[1],NOMS_JOURS[2],NOMS_JOURS[3],NOMS_JOURS[4],NOMS_JOURS[5],NOMS_JOURS[6]);
    lcd.print(myTemp);
   
    lcd.setCursor(0, 1);
    sprintf(myTemp," %03d %03d %03d %03d %03d %03d %03d",tabDureeChauffage[0],tabDureeChauffage[1],tabDureeChauffage[2],tabDureeChauffage[3],tabDureeChauffage[4],tabDureeChauffage[5],tabDureeChauffage[6]);
    lcd.print(myTemp);
  }
}

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%10==0) heures=24;
  }
  if(minutes >= 60) {
    minutes = 0;
    heures++;
  }
  if(heures >= 24) {
    heures = 0;
    EEPROMWriteInt(8+(jours*2),dureeChauffage);
    tabDureeChauffage[jours] = dureeChauffage;
    dureeChauffage = 0;
    jours++;
  }
  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[16];
  sprintf(myTime,"%s %02d:%02d:%02d",NOMS_JOURS[jj],hh,mm,ss);
  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;
}

//This function will write a 2 byte integer to the eeprom at the specified address and address + 1
void EEPROMWriteInt(int p_address, int p_value)
{
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);
  EEPROM.write(p_address, lowByte);
  EEPROM.write(p_address + 1, highByte);
}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
{
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);
  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

Aucun commentaire:

Enregistrer un commentaire