newLumiereAqua2016.ino 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*MIT License
  2. Copyright (c) <2016> <Benoit FORQUIN>
  3. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
  4. to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  5. and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  6. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  7. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  8. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  9. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  10. IN THE SOFTWARE.
  11. */
  12. #include <Wire.h>
  13. #include <Adafruit_MCP23017.h>
  14. #include <Adafruit_RGBLCDShield.h>
  15. #include <RTClib.h>
  16. #include <EEPROM.h>
  17. //initialisation LCD et RTC
  18. Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
  19. RTC_DS1307 RTC;
  20. #define ON 0x1
  21. #define OFF 0x0
  22. #define TEMPORETRO 120000
  23. #define TEMPOSELECT 3000
  24. #define OUTCHAUD 10
  25. #define OUTFROID 11
  26. //Gestion date
  27. int day = 1;
  28. int month = 1;
  29. int year = 2016;
  30. int h = 12;
  31. int m= 30;
  32. int s = 30;
  33. int dayOfWeek = 1;
  34. int regDay = 1;
  35. int regMonth = 1;
  36. int regYear = 2016;
  37. int regH = 12;
  38. int regM = 30;
  39. int regS = 30;
  40. int validReglage = 0;
  41. //Gestion LED
  42. int lumiereAuto = 1;
  43. int affPuissanceChaud = 50;
  44. int puissanceChaud = 127;
  45. int affPuissanceFroid = 50;
  46. int puissanceFroid = 127;
  47. int puissanceMaxChaud = 127;
  48. int puissanceMaxFroid = 127;
  49. //Bornes horraires
  50. int heuresAubeSemaine = 11;
  51. int minutesAubeSemaine = 0;
  52. int heuresJourSemaine = 11;
  53. int minutesJourSemaine = 20;
  54. int heuresAuroreSemaine = 22;
  55. int minutesAuroreSemaine = 40;
  56. int heuresNuitSemaine = 23;
  57. int minutesNuitSemaine = 0;
  58. int heuresAubeWe = 10;
  59. int minutesAubeWe = 0;
  60. int heuresJourWe = 10;
  61. int minutesJourWe = 20;
  62. int heuresAuroreWe = 22;
  63. int minutesAuroreWe = 40;
  64. int heuresNuitWe = 23;
  65. int minutesNuitWe = 0;
  66. int sauvegarde = 0;
  67. int efface = 0;
  68. /*valeursReglages contient les adresses des variables réglables
  69. Le menu de réglage incrémente et décrémente l'index permettant
  70. ansi d'accéder à la valeurs de ces varibles pour les modifier.
  71. bornesValeurs contient les bornes minimum et maximum que peut
  72. prendree chaque variable.
  73. textesReglages contient les libellés à afficher pour chaque valeur
  74. unitesReglages contient les textes affichés après les valeurs
  75. (unités ou indications de réglage)
  76. Les index correspondent dans les différents tableau pour que les
  77. type d'informations soit cohérente en incrémntant et décrémentant
  78. la varible "menu" par l'appui des boutons UP et DOWN
  79. */
  80. int* valeursReglages[]={&regDay, &regMonth, &regYear, &regH, &regM, &regS, &validReglage,
  81. &lumiereAuto, &affPuissanceChaud, &affPuissanceFroid, &puissanceMaxChaud, &puissanceMaxFroid,
  82. &heuresAubeSemaine, &minutesAubeSemaine, &heuresJourSemaine, &minutesJourSemaine,
  83. &heuresAuroreSemaine, &minutesAuroreSemaine, &heuresNuitSemaine, &minutesNuitSemaine,
  84. &heuresAubeWe, &minutesAubeWe, &heuresJourWe, &minutesJourWe,
  85. &heuresAuroreWe, &minutesAuroreWe, &heuresNuitWe, &minutesNuitWe, &sauvegarde, &efface};
  86. const int bornesValeurs[][2] = {
  87. {1,31},
  88. {1,12},
  89. {0,99},
  90. {0,23},
  91. {0,59},
  92. {0,59},
  93. {0,1},
  94. {0,1},
  95. {0,100},
  96. {0,100},
  97. {0,255},
  98. {0,255},
  99. {0,23},
  100. {0,59},
  101. {0,23},
  102. {0,59},
  103. {0,23},
  104. {0,59},
  105. {0,23},
  106. {0,59},
  107. {0,23},
  108. {0,59},
  109. {0,23},
  110. {0,59},
  111. {0,23},
  112. {0,59},
  113. {0,23},
  114. {0,59},
  115. {0,1},
  116. {0,1}
  117. };
  118. const char* textesReglages[]={"Jour", "Mois", "Annee", "Heures", "Minutes", "Secondes", "Valide Reglages",
  119. "Pilotage", "Puissance Chaud", "Puissance Froid", "P max Chaud", "P max Froid",
  120. "H Aube Sem", "M Aube Sem", "H Jour Sem", "M Jour sem", "H Aurore Semaine", "M Aurore Semaine",
  121. "H Nuit Sem", "M Nuit Sem", "H Aube WE", "M Aube WE", "H Jour WE", "M Jour WE",
  122. "H Aurore WE", "M Aurore WE", "H Nuit WE", "M Nuit WE", "Save EEPROM", "Efface EEPROM"};
  123. const char* unitesReglages[]={"", "", "", "", "", "", " Valid=1 Annule=0",
  124. " Auto=1 Manu=0", "%", "%", " 0 -> 255", " 0 -> 255",
  125. "", "", "", "", "", "",
  126. "", "", "", "", "", "",
  127. "", "", "", "", " Valid=1 Annule=0"," Valid=1 Annule=0"};
  128. //Etat retro-eclairage
  129. boolean retroLcd = true;
  130. boolean lastRetroLcd = retroLcd ;
  131. //Index position Menu
  132. byte menu = 0;
  133. //Gestion EEPROM
  134. byte startRand = 207;
  135. byte endRand = 57;
  136. //Etats précédents boutons
  137. boolean lastUp = false;
  138. boolean lastDown = false;
  139. boolean lastRight = false;
  140. boolean lastLeft = false;
  141. boolean lastSelect = false;
  142. //Etat réglage
  143. boolean reglage = false;
  144. boolean lastReglage = reglage;
  145. //Tempos
  146. unsigned long tempoRetro = 0;
  147. unsigned long tempoDebug = 0;
  148. unsigned long tempoSelect = 0;
  149. //Gestion affichage
  150. String ligne1 = "";
  151. String lastLigne1 = "";
  152. String ligne2 = "";
  153. String lastLigne2 = "";
  154. void raffraichir() {
  155. if (!reglage) {
  156. lcd.noBlink();
  157. lcd.noCursor();
  158. }
  159. if (ligne1 != lastLigne1) {
  160. lcd.noCursor();
  161. lcd.setCursor(0,0);
  162. lcd.print(F(" "));
  163. lcd.setCursor(0,0);
  164. lcd.print(ligne1);
  165. lastLigne1 = ligne1;
  166. }
  167. if (ligne2 != lastLigne2) {
  168. lcd.noCursor();
  169. lcd.setCursor(0,1);
  170. lcd.print(F(" "));
  171. lcd.setCursor(0,1);
  172. lcd.print(ligne2);
  173. lastLigne2 = ligne2;
  174. }
  175. if (reglage) {
  176. lcd.cursor();
  177. lcd.setCursor(0,1);
  178. lcd.blink();
  179. }
  180. }
  181. void affichageMarche () {
  182. lcd.noCursor();
  183. ligne1="";
  184. ligne1 += beautyfullTime(day);
  185. ligne1 += "/";
  186. ligne1 += beautyfullTime(month);
  187. ligne1 += "/";
  188. ligne1 += year;
  189. ligne1 += " ";
  190. ligne1 += beautyfullTime(h);
  191. ligne1 += ":";
  192. ligne1 += beautyfullTime(m);
  193. ligne2="";
  194. ligne2 +="C:";
  195. ligne2 += affPuissanceChaud;
  196. ligne2 += "% F:";
  197. ligne2 += affPuissanceFroid;
  198. ligne2 += "% ";
  199. if (lumiereAuto == 1) {
  200. ligne2 += "A";
  201. }
  202. else {
  203. ligne2 += "M";
  204. }
  205. raffraichir();
  206. }
  207. void affichageReglage() {
  208. ligne1=String(textesReglages[menu]);
  209. ligne2=String(*valeursReglages[menu]);
  210. ligne2+=String(unitesReglages[menu]);
  211. raffraichir();
  212. }
  213. void initReglage() {
  214. DateTime now = RTC.now();
  215. int dateHeure[] = {now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second()};
  216. for (byte i=0; i<6; i++) {
  217. if (dateHeure[i] <= bornesValeurs[i][1] && dateHeure[i] >= bornesValeurs[i][0]) {
  218. *valeursReglages[i] = dateHeure[i];
  219. }
  220. }
  221. }
  222. void setup() {
  223. Serial.begin(9600);
  224. lcd.begin(16, 2);
  225. pinMode(OUTCHAUD, OUTPUT); //Sortie PWM LED chaud
  226. pinMode(OUTFROID, OUTPUT); //Sortie PWM LED froid
  227. //RTC.adjust(DateTime(__DATE__, __TIME__));
  228. if (EEPROM.read(9) == startRand && EEPROM.read(28) == endRand) {
  229. //index à régler de 11 à 29 dans valeursReglages
  230. //Les valeurs sont stockées aux mémoires 11 à 29
  231. //Les adresses EEPROM 10 et 30 servent à vérifier que ce sont les bonne valeurs sauvegardées
  232. for (int i=10; i<=27; i++) {
  233. *valeursReglages[i] = EEPROM.read(i);
  234. }
  235. }
  236. }
  237. String beautyfullTime(int time) {
  238. String buf;
  239. if (time < 10) {
  240. buf += "0";
  241. buf += time;
  242. }
  243. else {
  244. buf+= time;
  245. }
  246. return buf;
  247. }
  248. String sToHour (long time) {
  249. long h= time/3600;
  250. long m= time%3600/60;
  251. return beautyfullTime(int(h))+":"+beautyfullTime(int(m));
  252. }
  253. void loop() {
  254. DateTime now = RTC.now();
  255. year = now.year() -2000;
  256. month = now.month();
  257. day = now.day();
  258. h = now.hour();
  259. m = now.minute();
  260. s = now.second();
  261. //dimanche = 0 -> samedi = 6
  262. dayOfWeek = now.dayOfWeek();
  263. long sNow = long(h)*3600 + long(m)*60+long(s);
  264. //GESTION retro-éclairage
  265. if (retroLcd) {
  266. if (millis()-tempoRetro > TEMPORETRO) {
  267. retroLcd = false;
  268. }
  269. lcd.setBacklight(ON);
  270. }
  271. else {
  272. lcd.setBacklight(OFF);
  273. }
  274. //Gestion Affichage
  275. if (!reglage) {
  276. affichageMarche();
  277. }
  278. else {
  279. affichageReglage();
  280. }
  281. //Gestion LEDS
  282. long Aube=0;
  283. long Jour=0;
  284. long Midi=0;
  285. long Aurore=0;
  286. long Nuit=0;
  287. if (dayOfWeek == 6 || dayOfWeek == 0) {
  288. Aube = long(heuresAubeWe)*3600 + long(minutesAubeWe)*60;
  289. Jour = long(heuresJourWe)*3600 + long(minutesJourWe)*60;
  290. Aurore = long(heuresAuroreWe)*3600+long(minutesAuroreWe)*60;
  291. Nuit = long(heuresNuitWe)*3600+long(minutesNuitWe)*60;
  292. }
  293. else if (dayOfWeek >=1 && dayOfWeek <=5) {
  294. Aube = long(heuresAubeSemaine)*3600 + long(minutesAubeSemaine)*60;
  295. Jour = long(heuresJourSemaine)*3600 + long(minutesJourSemaine)*60;
  296. Aurore = long(heuresAuroreSemaine)*3600+long(minutesAuroreSemaine)*60;
  297. Nuit = long(heuresNuitSemaine)*3600+long(minutesNuitSemaine)*60;
  298. }
  299. Midi = Jour + (Aurore-Jour)/2;
  300. /*Stocker les variables dans un tableau de pointeurs
  301. genre byte* tableau[3]=[&h,&m,&s];
  302. Incréménter directement la variable (h par exemple)
  303. *tableau[0]+=1;
  304. *tableau[0] ++; ne fonctionne pas
  305. */
  306. if (lumiereAuto ==1) {
  307. if (sNow>0 && sNow<=Aube) {
  308. //On est donc le WE entre minuit et l'aube
  309. //Donc, on éteint tout
  310. puissanceChaud = 0;
  311. affPuissanceChaud = 0;
  312. puissanceFroid = 0;
  313. affPuissanceFroid = 0;
  314. }
  315. else if (sNow>Aube && sNow<=Jour) {
  316. //On est donc entre l'aube et le début du jour
  317. //On attaque donc le blanc chaud
  318. puissanceFroid = 0;
  319. puissanceChaud = map((Jour-sNow), (Jour-Aube),0 ,0,puissanceMaxChaud);
  320. }
  321. else if (sNow>Jour && sNow<=Midi) {
  322. //On est entre le jour et midi
  323. //On augmente donc le blanc froid
  324. puissanceChaud = puissanceMaxChaud;
  325. puissanceFroid = map((Midi-sNow), (Midi-Jour),0 ,0,puissanceMaxFroid);
  326. }
  327. else if (sNow>Midi && sNow<=Aurore) {
  328. //On est entre midi et l'aurore
  329. //On descend donc le blanc froid
  330. puissanceChaud = puissanceMaxChaud;
  331. puissanceFroid = map((Aurore-sNow), 0, (Aurore-Midi) ,0 ,puissanceMaxFroid);
  332. }
  333. else if (sNow>Aurore && sNow<=Nuit) {
  334. //On est entre l'aurore et la nuit
  335. //On descend donc le blanc chaud
  336. puissanceFroid = 0;
  337. puissanceChaud = map((Nuit-sNow), 0, (Nuit-Aurore),0 ,puissanceMaxChaud);
  338. }
  339. else {
  340. puissanceChaud =0;
  341. puissanceFroid = 0;
  342. }
  343. affPuissanceChaud = map(puissanceChaud,0,puissanceMaxChaud,0,100);
  344. affPuissanceFroid = map(puissanceFroid,0,puissanceMaxFroid,0,100);
  345. }
  346. else {
  347. puissanceChaud = map(affPuissanceChaud, 0,100,0,255);
  348. puissanceFroid = map(affPuissanceFroid, 0,100,0,255);
  349. }
  350. //Mise à jour des sorties
  351. analogWrite(OUTCHAUD, puissanceChaud);
  352. analogWrite(OUTFROID, puissanceFroid);
  353. uint8_t buttons = lcd.readButtons();
  354. if (buttons) {
  355. if (retroLcd){
  356. if ((buttons & BUTTON_UP) && !lastUp) {
  357. if (menu > 0) {
  358. menu --;
  359. }
  360. else {
  361. menu = (sizeof(valeursReglages)/2)-1;
  362. }
  363. tempoRetro = millis();
  364. lastUp = true;
  365. }
  366. else if ((buttons & BUTTON_DOWN) && !lastDown) {
  367. if (menu < (sizeof(valeursReglages)/2)-1) {
  368. menu ++;
  369. }
  370. else {
  371. menu = 0;
  372. }
  373. tempoRetro=millis();
  374. lastDown = true;
  375. }
  376. else if (reglage && (buttons & BUTTON_RIGHT) && !lastRight) {
  377. if (*valeursReglages[menu] < bornesValeurs[menu][1]) {
  378. *valeursReglages[menu] += 1;
  379. }
  380. else {
  381. *valeursReglages[menu] = bornesValeurs[menu][0];
  382. }
  383. tempoRetro=millis();
  384. }
  385. else if (reglage && (buttons & BUTTON_LEFT) && !lastLeft) {
  386. if (*valeursReglages[menu] > bornesValeurs[menu][0]) {
  387. *valeursReglages[menu] -= 1;
  388. }
  389. else {
  390. *valeursReglages[menu] = bornesValeurs[menu][1];
  391. }
  392. tempoRetro=millis();
  393. }
  394. else if ((buttons & BUTTON_SELECT)) {
  395. tempoRetro= millis();
  396. if (!lastSelect) {
  397. Serial.println("Ping");
  398. tempoSelect = millis();
  399. lastSelect = true;
  400. }
  401. else {
  402. if (millis()- tempoSelect > TEMPOSELECT) {
  403. if (!reglage) {
  404. initReglage();
  405. }
  406. reglage = !reglage;
  407. lastSelect = false;
  408. if (validReglage == 1) {
  409. validReglage = 0;
  410. RTC.adjust(DateTime(regYear, regMonth,regDay,regH,regM,regS));
  411. }
  412. if (sauvegarde == 1) {
  413. Serial.println("save");
  414. sauvegarde = 0;
  415. EEPROM.write(9, startRand);
  416. EEPROM.write(28, endRand);
  417. for (int i=10; i<=27; i++) {
  418. EEPROM.write(i, *valeursReglages[i]);
  419. }
  420. }
  421. if (efface == 1) {
  422. Serial.println("Efface");
  423. efface = 0;
  424. for (int i=0; i<1023; i++) {
  425. EEPROM.write(i,0);
  426. }
  427. }
  428. }
  429. }
  430. }
  431. }
  432. else {
  433. tempoRetro= millis();
  434. retroLcd = true;
  435. }
  436. }
  437. else {
  438. lastUp = false;
  439. lastDown = false;
  440. lastRight = false;
  441. lastLeft = false;
  442. lastSelect = false;
  443. }
  444. //debug();
  445. if (millis()-tempoDebug > 2000) {
  446. tempoDebug=millis();
  447. Serial.print(day);
  448. Serial.print("/");
  449. Serial.print(month);
  450. Serial.print("/");
  451. Serial.println(year);
  452. Serial.println();
  453. Serial.print(F("sNow : "));
  454. Serial.print(sToHour(sNow));
  455. Serial.print(F(":"));
  456. Serial.println(s);
  457. Serial.print(F("Aube : "));
  458. Serial.println(sToHour(Aube));
  459. Serial.print(F("Jour : "));
  460. Serial.println(sToHour(Jour));
  461. Serial.print(F("Midi : "));
  462. Serial.println(sToHour(Midi));
  463. Serial.print(F("Aurore : "));
  464. Serial.println(sToHour(Aurore));
  465. Serial.print(F("Nuit : "));
  466. Serial.println(sToHour(Nuit));
  467. Serial.println();
  468. Serial.print(F("Chaud : "));
  469. Serial.println(puissanceChaud);
  470. Serial.print(F("Froid : "));
  471. Serial.println(puissanceFroid);
  472. Serial.println();
  473. Serial.print(F("DayOfWeek : "));
  474. Serial.println(dayOfWeek);
  475. Serial.print(F("menu : "));
  476. Serial.println(menu);
  477. Serial.print(F("tempoRetro : "));
  478. Serial.println(tempoRetro);
  479. Serial.print(F("tempoSelect : "));
  480. Serial.println(tempoSelect);
  481. Serial.print(F("lastSelect : "));
  482. Serial.println(lastSelect);
  483. Serial.print(F("retroLcd : "));
  484. Serial.println(retroLcd);
  485. Serial.print(F("reglage : "));
  486. Serial.println(reglage);
  487. }
  488. }