Delete Serre_menuLCD.ino

Delete Serre_menuLCD.ino

Change for version using GreenhouseLib

--- Serre_menuLCD.ino
+++ Serre_menuLCD.ino
@@ -1,1363 +0,0 @@
-#include <Arduino.h>
-
-//*****************LIBRAIRIES************************
-#include <EEPROM.h>
-#include <Wire.h>
-#include <LCD.h>
-#include <LiquidCrystal_I2C.h>
-#include <DS3231.h>
-#include <TimeLord.h>
-#include <Greenhouse.h>
-
-//*****************DEFINITIONS***********************
-//Select your temperature probe
-#define DS18B20
-//define SHT1X
-
-#define NBROLLUPS 1
-#define NBHEATERS 1
-#define NBFANS 1
-#define NBPROGRAMS 5
-
-//Select your input pins
-#define LCDKEYPAD A0
-#define MENU_PIN 2
-const byte SAFETY_SWITCH[NBROLLUPS] = {3};
-
-//Select your output pins
-const byte ROLLUP_OPEN[NBROLLUPS] = {4};
-const byte ROLLUP_CLOSE[NBROLLUPS] = {5};
-const byte CHAUFFAGE[NBHEATERS] = {6};
-const byte FAN[NBFANS] = {7};
-
-//*********************OBJETS************************
-//---------------------LCD-----------------
-#define I2C_ADDR    0x27              // Define I2C Address where the PCF8574A is
-#define BACKLIGHT_PIN     3
-LiquidCrystal_I2C  lcd(I2C_ADDR, 2, 1, 0, 4, 5, 6, 7);
-//---------------------RTC-----------------
-DS3231  rtc(SDA, SCL);                // Init the DS3231 using the hardware interface
-Time  t;
-//--------------------Sonde-------------
-#ifdef DS18B20
-  #include <OneWire.h>
-  #include <DallasTemperature.h>
-  #define ONE_WIRE_BUS A1
-  OneWire oneWire(ONE_WIRE_BUS);
-  DallasTemperature sensors(&oneWire);
-#endif
-#ifdef SHT1X
-  #include <SHT1x.h>
-  #define dataPin  A1
-  #define clockPin A2
-  SHT1x sht1x(dataPin, clockPin);
-#endif
-//-------------------Timelord-------------
-const int TIMEZONE = -5; //PST
-const float LATITUDE = 45.50, LONGITUDE = -73.56; // set your position here
-TimeLord myLord; // TimeLord Object, Global variable
-
-//*********************VARIABLES GLOBALES*************
-//nombre d'items activés
-const int nbPrograms = 5;              //Nombre de programmes de température
-boolean rollups[NBROLLUPS] = {};
-boolean heaters[NBHEATERS] = {};
-boolean fans[NBFANS] = {};
-boolean fanSafety[NBFANS] = {};
-boolean rollupSafety[NBROLLUPS] = {};
-
-//Sonde de température
-boolean failedSensor = false;
-
-//Poisition des Rollups
-volatile byte incrementCounter[NBROLLUPS] = {};               //positionnement des rollups
-boolean firstOpening[NBROLLUPS] = {};
-
-//Programmes horaire
-byte sunTime[6] = {};                      //données de l'horloge
-byte sunRise[3] = {};
-byte sunSet[3] = {};
-byte P[nbPrograms][3] = {};
-byte program;                         //Programme en cour
-byte lastProgram;                    //Dernier programme en cour
-
-//Programmes de température
-float tempCible;
-
-//Ramping
-int newTempCible;                   //Température cible à atteindre
-unsigned long lastCount = 0;         //Compteur
-
-//Autres variables
-const int sleeptime = 1000;           //Temps de pause entre chaque exécution du programme(en mili-secondes)
-
-//-----------------------LCD Menu------------------
-//menuPin
-boolean menuPinState = 1;
-//curseur
-byte currentMenuItem = 1;
-//buttonstate
-byte state = 0;
-byte laststate = 0;
-//menu
-int menu = 0;
-//#items/menu
-byte Nbitems = 6;
-char* menuitems[10] = {};
-int yr; byte mt; byte dy; byte hr; byte mn; byte sc;
-byte nr; byte inc; unsigned int rot; unsigned int p; int mod; byte hys; boolean sfty;
-byte typ; byte tt;
-
-
-//**************************************************************
-//*****************       SETUP      ***************************
-//**************************************************************
-
-void setup() {
-  //Initialisation (moniteur série, horloge, capteurs, affichage, données astronomiques)
-  Serial.begin(9600);
-  rtc.begin();
-  #ifdef DS18B20
-    sensors.begin();
-  #endif
-  initLCD(20,4);
-  initTimeLord();
-
-  //defineProgram(1, SR, 0, -30, 20);
-  //defineProgram(2, SR, 0, 20, 21);
-  //defineProgram(3, CLOCK, 11, 10, 22);
-  //defineProgram(4, SS, 0, -60, 28);
-  //defineProgram(5, SS, 0, 0, 18);
-
-  //defineRollup(1, 5, 5, 1, 0, 1, true);
-  //defineFan(1, 2, 1, true);
-  //defineHeater(1, -3, 1);
-  defineRamping(10);
-
-  initVariables();
-  initOutputs();
-  //Définition des sorties
-  initRollupOutput(1, ROLLUP_OPEN[0], ROLLUP_CLOSE[0], LOW);
-  initFanOutput(1,FAN[0], LOW);
-  initHeaterOutput(1,CHAUFFAGE[0], LOW);
-
-  pinMode(LCDKEYPAD, INPUT_PULLUP);
-  pinMode(SAFETY_SWITCH[0], INPUT_PULLUP);
-  pinMode(MENU_PIN, INPUT_PULLUP);
-  //Affichage LCD
-  lcdDisplay();
-}
-
-
-//**************************************************************
-//******************       LOOP      ***************************
-//**************************************************************
-
-void loop() {
-
-  //MODE MENU
-  if (digitalRead(MENU_PIN) == LOW) {
-    //Programme de menu
-    Menu(menu);
-    delay(50);
-  }
-
-  //MODE CONTROLE
-  else if (digitalRead(MENU_PIN) == HIGH) {
-    //Protocole de controle
-    selectProgram();
-    //Définition de la température d'activation des sorties
-    startRamping();
-    //Protocoles spéciaux (pré-jour/pré-nuit) [VIDE]
-    specialPrograms();
-    //Affichage LCD
-    lcdDisplay();
-    //Activation des relais
-    relayLogic();
-    //Pause entre chaque cycle
-    delay(sleeptime);
-  }
-}
-
-
-//**************************************************************
-//****************    MACROS - SETUP     ***********************
-//**************************************************************
-void initLCD(byte length, byte width){
-  lcd.begin(length, width);
-  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
-  lcd.setBacklight(HIGH);
-  lcd.clear();
-}
-
-void initTimeLord(){
-  myLord.TimeZone(TIMEZONE * 60);
-  myLord.Position(LATITUDE, LONGITUDE);
-  myLord.DstRules(3,2,11,1,60); // DST Rules for USA
-}
-
-void initOutputs(){
-  //Activation des items
-  for (int x = 0; x < NBROLLUPS;x++){
-    rollups[x] = true;
-    firstOpening[x] = true;
-    rollupSafety[x] = rollupSafetyE(x);
-    if (rollupSafety[x] == true) {
-        attachInterrupt(digitalPinToInterrupt(SAFETY_SWITCH[0]), endOfTheRun0, FALLING);
-    }
-  }
-  for (int x = 0; x < NBFANS;x++){
-    fans[x] = true;
-    fanSafety[x] = fanSafetyE(x);
-  }
-  for (int x = 0; x < NBHEATERS;x++){
-    heaters[x] = true;
-  }
-}
-
-void endOfTheRun0(){
-  incrementCounter[0] = incrementsE(0);
-}
-
-
-void initVariables(){
-  //Première lecture d'horloge pour définir le lever et coucher du soleil
-  getDateAndTime();
-  //Définition du lever et du coucher du soleil
-  selectProgram();
-  //Définition de la température cible
-  setTempCible();
-  //Définition de la température d'activation des sorties
-}
-
-void getDateAndTime(){
-  t = rtc.getTime();
-  sunTime[5] = t.year-2000;
-  sunTime[4] = t.mon;
-  sunTime[3] = t.date;
-  sunTime[HEURE] = t.hour;
-  sunTime[MINUTE] = t.min;
-  sunTime[0] = t.sec;
-  myLord.DST(sunTime);
-}
-
-void selectProgram(){
-  //Exécution du programme
-  setSunrise();
-  setSunset();
-  getDateAndTime();
-  setPrograms();
-  selectActualProgram();
-}
-
-void setPrograms(){
-  int PInt[nbPrograms][3] = {};
-  for(byte x = 0; x < nbPrograms; x++){
-    //Serial.println(x);Serial.println (programType[x]);
-    if (programsE(x) == SR){
-      PInt[x][HEURE] = sunRise[HEURE];
-      PInt[x][MINUTE] = sunRise[MINUTE] + srmodE(x);
-      convertDecimalToTime(&PInt[x][HEURE], &PInt[x][MINUTE]);
-      //Serial.print(" Program ");Serial.print(x);Serial.print(" : ");Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
-    }
-    else if (programsE(x) == CLOCK){
-      PInt[x][HEURE] = PROGRAM_TIME(x, HEURE);
-      P[x][MINUTE] = PROGRAM_TIME(x, MINUTE);
-      //Serial.print(" Program ");Serial.print(x);Serial.print(" : ");Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
-    }
-
-    else if (programsE(x) == SS){
-      PInt[x][HEURE] = sunSet[HEURE];
-      PInt[x][MINUTE] = sunSet[MINUTE] + ssmodE(x);
-      convertDecimalToTime(&PInt[x][HEURE], &PInt[x][MINUTE]);
-      //Serial.print(" Program ");Serial.print(x); Serial.print(" : "); Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
-    }
-  }
-  //Convert to byte
-  for(byte x = 0; x < nbPrograms; x++){
-      for(byte y = 0; y < 3; y++){
-        P[x][y] = (byte)PInt[x][y];
-      }
-  }
-}
-
-
-
-void selectActualProgram(){
-  //Sélectionne le programme en cour
-    //Serial.print ("Heure actuelle ");Serial.print(" : ");Serial.print(sunTime[HEURE] );Serial.print(" : ");Serial.println(sunTime[MINUTE]);
-    for (byte y = 0; y < (nbPrograms-1); y++){
-    //Serial.print ("Programme "); Serial.print(y+1);Serial.print(" : ");Serial.print(P[y][HEURE]);Serial.print(" : ");Serial.println(P[y][MINUTE]);
-      if (((sunTime[HEURE] == P[y][HEURE])  && (sunTime[MINUTE] >= P[y][MINUTE]))||((sunTime[HEURE] > P[y][HEURE]) && (sunTime[HEURE] < P[y+1][HEURE]))||((sunTime[HEURE] == P[y+1][HEURE])  && (sunTime[MINUTE] < P[y+1][MINUTE]))){
-          program = y+1;
-          //Serial.println("YES!");
-        }
-    }
-    //  Serial.print ("Programme ");Serial.print(nbPrograms);Serial.print(" : ");Serial.print(P[nbPrograms-1][HEURE]);Serial.print(" : ");Serial.println(P[nbPrograms-1][MINUTE]);
-    if (((sunTime[HEURE] == P[nbPrograms-1][HEURE])  && (sunTime[MINUTE] >= P[nbPrograms-1][MINUTE]))||(sunTime[HEURE] > P[nbPrograms-1][HEURE])||(sunTime[HEURE] < P[0][HEURE])||((sunTime[HEURE] == P[0][HEURE])  && (sunTime[MINUTE] < P[0][MINUTE]))){
-      program = nbPrograms;
-    //Serial.println("YES!");
-    }
-}
-
-
-void setSunrise(){
-  //Définit l'heure du lever et coucher du soleil
-  myLord.SunRise(sunTime); ///On détermine l'heure du lever du soleil
-  myLord.DST(sunTime);//ajuster l'heure du lever en fonction du changement d'heure
-  sunRise[HEURE] = sunTime[HEURE];
-  sunRise[MINUTE] = sunTime[MINUTE];
-  //Serial.print("lever du soleil :");Serial.print(sunRise[HEURE]);  Serial.print(":");  Serial.println(sunRise[MINUTE]);
-
-}
-
-void setSunset(){
-  /* Sunset: */
-  myLord.SunSet(sunTime); // Computes Sun Set. Prints:
-  myLord.DST(sunTime);
-  sunSet[HEURE] = sunTime[HEURE];
-  sunSet[MINUTE] = sunTime[MINUTE];
-  //Serial.print("coucher du soleil :");  Serial.print(sunSet[HEURE]);  Serial.print(":");  Serial.println(sunSet[MINUTE]);
-
-}
-
-void setTempCible(){
-  for (byte x = 0; x < nbPrograms; x++){
-    if(program == x+1){
-      tempCible = targetTempE(x);
-      //Serial.println(tempCible);
-    }
-  }
-}
-
-float greenhouseTemperature() {
-  float temp;
-  #ifdef DS18B20
-    sensors.requestTemperatures();
-    temp = sensors.getTempCByIndex(0);
-    if((temp < -20.00)||(temp > 80)){
-      temp = targetTempE(program-1)+2;
-      return temp;
-      failedSensor = true;
-    }
-    else{
-      return temp;
-      failedSensor = false;
-    }
-  #endif
-  #ifdef SHT1X
-    temp = sht1x.readTemperatureC();
-    if((temp < -20.00)||(temp > 80)){
-      temp = targetTempE(program-1)+2;
-      return temp;
-      failedSensor = true;
-    }
-    else{
-      return temp;
-      failedSensor = false;
-    }
-  #endif
-
-}
-
-void lcdDisplay() {
-  lcd.noBlink();
-  //Si passe du mode menu au mode controle...
-  if (menuPinState == 0) {
-    lcdPrintTemp();
-    lcdPrintTempCible();
-    lcdPrintTime();
-    lcdPrintRollups();
-    lcdPrintOutputsStatus();
-    menuPinState = 1;
-  }
-  //Séquence normale...
-  lcdPrintTemp();
-  lcdPrintTempCible();
-  lcdPrintTime();
-  lcdPrintRollups();
-  lcdPrintOutputsStatus();
-}
-
-
-
-//**************************************************************
-//****************    MACROS - CONTROLE     ********************
-//**************************************************************
-
-//Programme de courbe de température
-void startRamping(){
-  //Définition des variables locales
-  Serial.println(rampingE());
-
-  //Exécution du programme
-  for (byte x = 0; x < nbPrograms; x++){
-    if(program == x+1){
-      newTempCible = targetTempE(x);
-    }
-  }
-
-  if (newTempCible > tempCible){
-    unsigned long rampingCounter = millis();
-    //Serial.println(rampingCounter);
-    //Serial.println(rampingCounter - lastCount);
-    if(rampingCounter - lastCount > rampingE()) {
-      lastCount = rampingCounter;
-      tempCible += 0.5;
-    }
-  }
-  else if (newTempCible < tempCible){
-    unsigned long rampingCounter = millis();
-    if(rampingCounter - lastCount > rampingE()) {
-      lastCount = rampingCounter;
-      tempCible -= 0.5;
-    }
-  }
-}
-
-
-void specialPrograms(){}
-
-float tempRollup(byte index){
-  return tempCible +rmodE(index);
-}         //Température d'activation des rollups (max.2)
-float tempHeater(byte index){
-  return tempCible + hmodE(index);
-}         //Température d'activation des fournaises (max.2)
-
-float tempFan(byte index){
-    return tempCible + vmodE(index);
-}         //Température d'activation des fans (max.2)
-
-
-void relayLogic(){                     //Température cible
-  //Exécution du programme
-  lcd.noBlink();
-  //Programme d'ouverture/fermeture des rollups
-  for(byte x = 0; x < NBROLLUPS; x++){
-    if (rollups[x] == true){
-      if (greenhouseTemperature() < (tempRollup(x) - rhystE(x))) {
-        closeSides(x);
-      } else if (greenhouseTemperature() > tempRollup(x)) {
-        openSides(x);
-      }
-    }
-  }
-
-  //Programme fournaise
-  for(byte x = 0; x < NBHEATERS; x++){
-    if (heaters[x] == true){
-
-      if ((greenhouseTemperature() < tempHeater(x))&&(incrementCounter[0] == 0)) {
-        digitalWrite(CHAUFFAGE[x], ON);
-      } else if ((greenhouseTemperature() > (tempHeater(x) + hhystE(x)))||(incrementCounter[0] != 0)) {
-        digitalWrite(CHAUFFAGE[x], OFF);
-      }
-    }
-  }
-
-  //Programme ventilation forcée
-  for(byte x = 0; x < NBFANS; x++){
-    if (fans[x] == true){
-      if (fanSafety[x] == true){
-        Serial.println(fanSafety[x]);
-        if (greenhouseTemperature() > tempFan(x)&&(digitalRead(SAFETY_SWITCH[0]) == OFF)){
-          Serial.println(digitalRead(SAFETY_SWITCH[0]));
-          digitalWrite(FAN[x], ON);
-        }
-        else if ((greenhouseTemperature() < (tempFan(x) - vhystE(x)))||(digitalRead(SAFETY_SWITCH[0]) == ON)) {
-          Serial.println(digitalRead(SAFETY_SWITCH[0]));
-          digitalWrite(FAN[x], OFF);
-        }
-      }
-      else if (fanSafety[x] == false){
-        if (greenhouseTemperature() > tempFan(x)){
-                    Serial.println(digitalRead(SAFETY_SWITCH[0]));
-          digitalWrite(FAN[x], ON);
-        }
-        else if (greenhouseTemperature() < (tempFan(x) - vhystE(x))) {
-                  Serial.println(digitalRead(SAFETY_SWITCH[0]));
-          digitalWrite(FAN[x], OFF);
-        }
-      }
-    }
-  }
-}
-
-//**************************************************************
-//****************    MACROS - AUTRES     **********************
-//**************************************************************
-
-//Programme d'ouverture des rollup
-void openSides(byte number) {
-  unsigned int pause = pauseE(number);
-
-  if (firstOpening[number] == true){
-    incrementCounter[number] = 0;
-    firstOpening[number] = false;
-  }
-  if (incrementCounter[number] < incrementsE(number)) {
-  incrementCounter[number] += 1;
-    lcd.setCursor(0, 1);
-    lcd.print(F("OUVERTURE"));
-    digitalWrite(ROLLUP_OPEN[number], ON);
-    delay(rotationE(number));
-    digitalWrite(ROLLUP_OPEN[number], OFF);
-    lcd.setCursor(0, 1);
-    lcd.print(F("R-U:     "));
-    lcd.setCursor(5, 1);
-    lcd.print(incrementCounter[number]);
-    delay(pause);
-  }
-
-}
-
-//Programme de fermeture des rollups
-void closeSides(byte number) {
-  unsigned int pause = pauseE(number);
-
-  if (firstOpening[number] == true){
-    incrementCounter[number] = incrementsE(number);
-    firstOpening[number] = false;
-  }
-  if (incrementCounter[number] > 0) {
-    incrementCounter[number] -= 1;
-    lcd.setCursor(0, 1);
-    lcd.print(F("FERMETURE"));
-    digitalWrite(ROLLUP_CLOSE[number], ON);
-    delay(rotationE(number));
-    digitalWrite(ROLLUP_CLOSE[number], OFF);
-    lcd.setCursor(0, 1);
-    lcd.print(F("R-U:     "));
-    lcd.setCursor(5, 1);
-    lcd.print(incrementCounter[number]);
-    delay(pause);
-  }
-}
-
-
-void lcdPrintRollups(){
-    lcd.setCursor(0, 1); lcd.print(F("         "));
-    lcd.setCursor(0, 1); lcd.print(F("R-U: "));
-    lcd.setCursor(5, 1); lcd.print(incrementCounter[0]);
- }
-void lcdPrintTemp(){
-    float temperature = greenhouseTemperature();
-    lcd.setCursor(0,0); lcd.print(F("         "));
-    if(failedSensor == false){
-      lcd.setCursor(0,0); lcd.print(F("T:")); lcd.print(temperature); lcd.print(F("C"));
-    }
-    else{
-      lcd.setCursor(0,0); lcd.print(F("T:")); lcd.print("!!!"); lcd.print(F("("));lcd.print((int)greenhouseTemperature());lcd.print(F(")"));
-    }
-}
-void lcdPrintTempCible(){
-    lcd.setCursor(9,0);lcd.print("|TC:");lcd.print(tempCible); lcd.print(F("C "));
-}
-void lcdPrintTime(){
-    lcd.setCursor(9,1); lcd.print(F("|(P")); lcd.print(program); lcd.print(F(":"));
-    lcd.setCursor(14,1); lcdPrintDigits(sunTime[HEURE]); lcd.print(F(":")); lcdPrintDigits(sunTime[MINUTE]);
-    lcd.setCursor(19,1); lcd.print(F(")"));
-}
-
-void lcdPrintOutputsStatus(){
-  lcd.setCursor(0, 2); lcd.print(F("                    "));
-  lcd.setCursor(0, 3); lcd.print(F("                    "));
-
-  if (fans[0] == true){
-      lcd.setCursor(0, 3); lcd.print(F("FAN:"));
-      if (digitalRead(FAN[0]) == OFF) {lcd.setCursor(5, 3); lcd.print(F("OFF"));    }
-      else if (digitalRead(FAN[0]) == ON) {lcd.setCursor(5, 3); lcd.print(F("ON "));    }
-    }
-
-  if (heaters[0] == true){
-    lcd.setCursor(0, 2); lcd.print(F("H1:"));
-    if (digitalRead(CHAUFFAGE[0]) == OFF) {lcd.setCursor(5, 2); lcd.print(F("OFF |"));    }
-    else if (digitalRead(CHAUFFAGE[0]) == ON) {lcd.setCursor(5, 2); lcd.print(F("ON  |"));    }
-  }
-
-  if (heaters[1] == true){
-    lcd.setCursor(11, 2); lcd.print(F("H2:"));
-    if (digitalRead(CHAUFFAGE[1]) == OFF) {lcd.setCursor(16, 2); lcd.print(F("OFF"));    }
-    else if (digitalRead(CHAUFFAGE[1]) == ON) {lcd.setCursor(16, 2); lcd.print(F("ON "));    }
-  }
-}
-
-void lcdPrintDigits(int digits){
-  // utility function for digital clock display: prints preceding colon and leading 0
-  if(digits < 10)
-  lcd.print("0");
-  lcd.print(digits);
-}
-
-void serialPrintDigits(int digits){
-  // utility function for digital clock display: prints preceding colon and leading 0
-  if(digits < 10)
-  Serial.print("0");
-}
-
-//**************************************************************
-//****************    MACROS - MENU     ***********************
-//**************************************************************
-
-void Menu(int x) {
-
-  if (menuPinState == 1) {
-    displayMenu(menu);
-    menuPinState = 0;
-  }
-
-  int a = analogRead(A0);
-  //Serial.println(a);
-  buttonState(a);
-
-  if ((state == 3) && (state != laststate)) {
-    currentMenuItem = currentMenuItem + 1;
-    real_currentMenuItem(Nbitems);
-    displayMenu(x);
-  } else if ((state == 2) && (state != laststate)) {
-    currentMenuItem = currentMenuItem - 1;
-    real_currentMenuItem(Nbitems);
-    displayMenu(x);
-  } else if ((state == 1) && (state != laststate)) {
-    real_currentMenuItem(Nbitems);
-    selectMenu(x, currentMenuItem);
-  }
-  laststate = state;
-}
-
-void buttonState(int x) {
-  if (x < 50) {
-    state = 0;
-  }
-  else if (x < 80) {
-    state = 1;
-  }
-  else if (x < 100) {
-    state = 2;
-  }
-  else if (x < 200) {
-    state = 3;
-  }
-  else {
-    state = 0;
-  }
-}
-
-void real_currentMenuItem(int x) {
-  if (currentMenuItem < 1) {
-    currentMenuItem = 1;
-  }
-  else if (currentMenuItem > x) {
-    currentMenuItem = x;
-  }
-}
-
-void Scrollingmenu (const char t[6] PROGMEM, int x, const char a[20] PROGMEM, const char b[20] PROGMEM, const char c[20] PROGMEM, const char d[20] PROGMEM, const char e[20] PROGMEM, const char f[20] PROGMEM, const char g[20] PROGMEM, const char h[20] PROGMEM, const char i[20] PROGMEM, const char j[20] PROGMEM, int y) {
-  const int numLcdRows = 3;
-  byte scrollPos = 0;
-  Nbitems = x;
-  const char* menuitems[] PROGMEM = {a, b, c, d, e, f, g, h, i, j};
-
-  if (y > numLcdRows) {
-    scrollPos = y - numLcdRows;
-  } else {
-    scrollPos = 0;
-  }
-  clearPrintTitle();
-  lcd.setCursor(14,0);lcd.print(t);
-  for (byte i = 0; i < numLcdRows; ++i) {
-    lcd.setCursor(0, i + 1);
-    lcd.print(menuitems[i + scrollPos]);
-  }
-  lcd.setCursor(19, (y - scrollPos));
-  lcd.blink();
-}
-
-void Scrollingnumbers(const char t[6] PROGMEM,int x, int y, int z, int a) {
-  const int numLcdRows = 3;
-  int scrollPos = 0;
-  Nbitems = x;
-
-  if (y > numLcdRows) {
-    scrollPos = y - numLcdRows;
-  } else {
-    scrollPos = 0;
-  }
-  clearPrintTitle();
-  lcd.setCursor(14,0);lcd.print(t);
-  for (byte i = 0; i < numLcdRows; ++i) {
-    lcd.setCursor(0, i + 1);
-    if (y < 4) {
-      lcd.print((z - a) + (i * a) + (a));
-    }
-    else if (y < x) {
-      lcd.print((z - a) + (i * a) + ((y - 2)*a));
-    }
-    else if (y == x) {
-      lcd.print("back");
-    }
-    else {}
-  }
-  lcd.setCursor(19, (y - scrollPos));
-  lcd.blink();
-}
-void clearPrintTitle() {
-  lcd.noBlink();
-  lcd.clear();
-  lcd.setCursor(0, 0);
-  lcd.print("**ROBOT-SERRE**V.1**");
-}
-
-void programPrintM(byte index){
-    lcd.noBlink();
-    clearPrintTitle();
-    lcd.setCursor(0, 1);lcd.print(F("Type: "));
-      switch(programsE(index)){
-        case SR: lcd.print(F("SUNRISE"));break;
-        case CLOCK: lcd.print(F("MANUAL"));break;
-        case SS: lcd.print(F("SUNSET"));break;
-      }
-    lcd.setCursor(0, 2);lcd.print(F("HD: "));lcdPrintDigits(P[index][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[index][MINUTE]);
-    lcd.setCursor(9, 2);lcd.print(F("| HF: "));lcdPrintDigits(P[index+1][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[index+1][MINUTE]);
-    lcd.setCursor(0, 3);lcd.print(F("Temp. cible: "));lcd.print(targetTempE(index));lcd.print(F("C"));
-}
-void programPrintE(byte index){
-    lcd.noBlink();
-    clearPrintTitle();
-    lcd.setCursor(0, 1);lcd.print(F("Type: "));
-      switch(programsE(index)){
-        case SR: lcd.print(F("SUNRISE"));break;
-        case CLOCK: lcd.print(F("MANUAL"));break;
-        case SS: lcd.print(F("SUNSET"));break;
-      }
-    lcd.setCursor(0, 2);lcd.print(F("HD: "));lcdPrintDigits(P[index][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[index][MINUTE]);
-    lcd.setCursor(9, 2);lcd.print(F("| HF: "));lcdPrintDigits(P[0][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[0][MINUTE]);
-    lcd.setCursor(0, 3);lcd.print(F("Temp. cible: "));lcd.print(targetTempE(index));lcd.print(F("C"));
-}
-
-//-----------------DISPLAY-------------------------
-//Scrollingmenu(Nbitems, Item1, item2, item3, item4, item5, Item6, item7, item8, item9, item10, currentMenuItem); //leave variable "Itemx" blank if it doesnt exist
-//Scrollingnumbers(Nbitems, currentMenuItem, starting number, multiplicator);
-
-void displayMenu(int x) {
-  switch (x) {
-    case 0: Scrollingmenu("", 6, "Capteurs", "Date/time", "Rollups", "Ventilation", "Chauffage", "Programmes", "", "", "", "", currentMenuItem); break;
-    case 1: Scrollingmenu("TIME*", 6, "Date", "Time", "SetDOW", "Set date", "Set time", "back", "", "", "", "", currentMenuItem); break;
-
-    case 11: Scrollingmenu("DOW**", 8, "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday", "back", "", "", currentMenuItem); break;
-    case 12: Scrollingnumbers("YEAR*",11, currentMenuItem, 2016, 1);  break;
-    case 121: Scrollingnumbers("MONTH", 13, currentMenuItem, 1 , 1);  break;
-    case 1211: Scrollingnumbers("DAY**", 32, currentMenuItem, 1, 1); break;
-    case 13: Scrollingnumbers("HOUR*",25, currentMenuItem, 1, 1); break;
-    case 131: Scrollingnumbers("MIN***",62, currentMenuItem, 0 , 1); break;
-    case 1311: Scrollingnumbers("SEC**",62, currentMenuItem, 0, 1); break;
-
-    case 2: Scrollingmenu("ROLL*", 3, "Parameters", "setParameters", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 21: Scrollingmenu("ITEM*",(NBROLLUPS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 22: Scrollingmenu("ITEM*",(NBROLLUPS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 221: Scrollingnumbers("INCR*",11, currentMenuItem, 1, 1); break;
-    case 222: Scrollingnumbers("ROTA*", 61, currentMenuItem, 2, 2); break;
-    case 223: Scrollingmenu("PAUSE", 10, "5", "15", "20", "30", "45", "60", "75", "90", "120", "back", currentMenuItem); break;
-    case 224: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 225: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-    case 226: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-
-    case 3: Scrollingmenu("FANS*", 3, "Parameters", "setParameters", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 31: Scrollingmenu("ITEM*",(NBFANS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 32: Scrollingmenu("ITEM*",(NBFANS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 321: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 322: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-    case 323: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-
-    case 4: Scrollingmenu("HEATR", 3, "Parameters", "setParameters", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 41: Scrollingmenu("ITEM*",(NBHEATERS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem);break;
-    case 42: Scrollingmenu("ITEM*",(NBHEATERS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem);break;
-    case 421: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 422: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-
-    case 5: Scrollingmenu("PROG*", 3, "Timezones", "setTimezones", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 51: Scrollingnumbers("TIMZ*",(nbPrograms+1),currentMenuItem, 1, 1);break;
-    case 52: Scrollingnumbers("TIMZ*",(nbPrograms+1),currentMenuItem, 1, 1);break;
-    case 521: Scrollingmenu("ITEM*", 4,"SR", "MANUAL", "SS", "back", "", "", "",  "", "", "", currentMenuItem);break;
-    case 5221: Scrollingnumbers("HOUR*",25, currentMenuItem, 1, 1); break;
-    case 5222: Scrollingnumbers("MOD***",122, currentMenuItem, -60 , 1); break;
-    case 523: Scrollingnumbers("MIN***",62, currentMenuItem, 0 , 1); break;
-    case 524: Scrollingnumbers("TEMP", 42, currentMenuItem, 0, 1);break;
-
-  }
-}
-//------------------------SELECT-------------------
-
-void switchmenu(int x) {
-  delay(1000);
-  Serial.print(F(",  "));
-  menu = x;
-  currentMenuItem = 1;
-  Nbitems = 3;
-  displayMenu(menu);
-}
-
-void selectMenu(int x, int y) {
-
-  switch (x) {
-    //------------------------------SelectrootMenu-------------------------------------
-    //"Temperature/humidex","Date/time","Rollups","Ventilation","Chauffage"
-    case 0:
-      switch (y) {
-        case 1:
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1); lcd.print(F("Sonde temp. : ")); lcd.print(greenhouseTemperature()); lcd.print(F("C"));
-          break;
-        case 2: switchmenu(1); break;
-        case 3: switchmenu(2); break;
-        case 4: switchmenu(3); break;
-        case 5: switchmenu(4); break;
-        case 6: switchmenu(5); break;
-      }
-      break;
-    //-------------------------------SelectMenu1-----------------------------------------
-    //"Date","Time","Set DOW" "Set date", "Set time","back"
-    case 1 :
-      switch (y) {
-        case 1:
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1); lcd.print(rtc.getDOWStr());
-          lcd.setCursor(0, 2); lcd.print(F("Date : ")); lcd.print(rtc.getDateStr());
-          break;
-        case 2:
-          lcd.noBlink();
-          clearPrintTitle();
-          getDateAndTime();
-          lcd.setCursor(0, 1); lcd.print(F("Time : ")); lcdPrintDigits(sunTime[HEURE]);lcd.print(":"); lcdPrintDigits(sunTime[MINUTE]);lcd.print(":");lcdPrintDigits(sunTime[MINUTE]);
-          break;
-        case 3: switchmenu(11); break;
-        case 4: switchmenu(12); break;
-        case 5: switchmenu(13); break;
-        case 6: switchmenu(0); break;
-      }
-      break;
-    //-------------------------------SelectMenu12-----------------------------------------
-    //SET DAY OF THE WEEK
-    case 11 :
-      switch (y) {
-        case 1: rtc.setDOW(MONDAY); switchmenu(1); break;
-        case 2: rtc.setDOW(TUESDAY); switchmenu(1); break;
-        case 3: rtc.setDOW(WEDNESDAY); switchmenu(1); break;
-        case 4: rtc.setDOW(THURSDAY); switchmenu(1); break;
-        case 5: rtc.setDOW(FRIDAY); switchmenu(1); break;
-        case 6: rtc.setDOW(SATURDAY); switchmenu(1); break;
-        case 7: rtc.setDOW(SUNDAY); switchmenu(1); break;
-        case 8: switchmenu(1); break;
-      }
-      break;
-    //-------------------------------SelectMenu12-----------------------------------------
-    //SET YEAR
-    case 12 :
-      if (y < Nbitems) {
-        yr = (2015 + y);
-        switchmenu(121);
-      }
-      else {
-        switchmenu(1);
-      }
-      break;
-    //-------------------------------SelectMenu131-----------------------------------------
-    //SET MONTH
-    case 121 :
-      if (y < Nbitems) {
-        mt = y;
-        switchmenu(1211);
-      }
-      else {
-        switchmenu(1);
-      }
-      break;
-    //-------------------------------SelectMenu1311-----------------------------------------
-    //SET DAY
-    case 1211 :
-      if (y < Nbitems) {
-        dy = y;
-        rtc.setDate(dy, mt, yr);
-        switchmenu(1);
-      }
-      else {
-        switchmenu(1);
-      }
-      break;
-    //-------------------------------SelectMenu14-----------------------------------------
-    //SET HOUR
-    case 13 :
-      t = rtc.getTime();
-      sunTime[HEURE] = t.hour;
-      myLord.DST(sunTime);
-
-      if ((t.hour != sunTime[HEURE]) && (y < Nbitems)) {
-        hr = y-1;
-        switchmenu(131);
-      }
-      else if ((t.hour == sunTime[HEURE]) && (y < Nbitems)) {
-        hr = y;
-        switchmenu(131);
-      }
-      else{
-        switchmenu(1);
-      }
-      break;
-    //-------------------------------SelectMenu141-----------------------------------------
-    //SET MINUTES
-    case 131 :
-      if (y < Nbitems) {
-        mn = y - 1;
-        switchmenu(1311);
-      }
-      else {
-        switchmenu(1);
-      }
-      break;
-    //-------------------------------SelectMenu1411-----------------------------------------
-    //SET SECONDS
-    case 1311 :
-      if (y < Nbitems) {
-        sc = y - 1;
-        rtc.setTime(hr, mn, sc);
-        switchmenu(1);
-      }
-      else {
-        switchmenu(1);
-      }
-      break;
-    //-------------------------------SelectMenu2-----------------------------------------
-    //État, setProgram
-    case 2 :
-      switch (y) {
-        case 1:
-          switchmenu(21); break;
-        case 2:
-          switchmenu(22); break;
-        case 3: switchmenu(0); break;
-      }
-      break;
-    //-------------------------------SelectMenu21-----------------------------------------
-    //PROGRAMMES DES ROLLUPS
-    case 21 :
-      if (y < Nbitems) {
-        switch(y){
-          case 1 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1); lcd.print(F("Increments: ")); lcd.print(incrementsE(0)); lcd.print(F(""));
-          lcd.setCursor(0, 2); lcd.print(F("TP: ")); lcd.print(pauseE(0)/1000); lcd.print(F("s")); lcd.setCursor(8,2);lcd.print(F("| TR: ")); lcd.print(rotationE(0)/1000); lcd.print(F("s"));
-          lcd.setCursor(0, 3); lcd.print(F("H: ")); lcd.print(rhystE(0)); lcd.print(F("C")); lcd.setCursor(8,3);lcd.print(F("| TA: ")); lcd.print(tempCible + rmodE(0));lcd.print("C");
-          break;
-          case 2 :
-          lcd.setCursor(0, 1); lcd.print(F("Increment: ")); lcd.print(incrementsE(1)); lcd.print(F("%"));
-          lcd.setCursor(0, 2); lcd.print(F("TP: ")); lcd.print(pauseE(1)/1000); lcd.print(F("s")); lcd.setCursor(8,2);lcd.print(F("| TR:")); lcd.print(rotationE(1)/1000); lcd.print(F("s"));
-          lcd.setCursor(0, 3); lcd.print(F("H: ")); lcd.print(rhystE(1)); lcd.print(F("C")); lcd.setCursor(8,3);lcd.print(F("| TA: ")); lcd.print(tempCible - rmodE(1));lcd.print("C");
-          break;
-        }
-      }
-      else {
-        switchmenu(2);
-      }
-      break;
-    //-------------------------------SelectMenu22-----------------------------------------
-    //SET ROLLUP PROGRAM
-    case 22 :
-      if (y < Nbitems) {
-        nr = y;
-        switchmenu(221);
-      }
-      else {
-        switchmenu(2);
-      }
-      break;
-    //-------------------------------SelectMenu221-----------------------------------------
-    //SET INCREMENTS
-    case 221 :
-      if (y < Nbitems) {
-        inc = y;
-        switchmenu(222);
-      }
-      else {
-        switchmenu(2);
-      }
-      break;
-    //-------------------------------SelectMenu222-----------------------------------------
-    //SET ROTATION TIME
-    case 222 :
-      if (y < Nbitems) {
-        rot = y*2;
-        switchmenu(223);
-      }
-      else {
-        switchmenu(2);
-      }
-      break;
-      //-------------------------------SelectMenu223-----------------------------------------
-      //SET PAUSE TIME
-      case 223 :
-        switch (y) {
-          case 1: p = 5; switchmenu(224);break;
-          case 2: p = 15; switchmenu(224); break;
-          case 3: p = 20; switchmenu(224); break;
-          case 4: p = 30; switchmenu(224); break;
-          case 5: p = 45; switchmenu(224); break;
-          case 6: p = 60; switchmenu(224); break;
-          case 7: p = 75; switchmenu(224); break;
-          case 8: p = 90; switchmenu(224); break;
-          case 9: p = 120; switchmenu(224); break;
-          case 10: switchmenu(2); break;
-          }
-        break;
-      //-------------------------------SelectMenu224-----------------------------------------
-      //SET MODIFICATOR
-      case 224 :
-        if (y < Nbitems) {
-          mod = y-11;
-          switchmenu(225);
-        }
-        else {
-          switchmenu(2);
-        }
-      break;
-      //-------------------------------SelectMenu224-----------------------------------------
-      //SET HYSTERESIS
-      case 225 :
-        if (y < Nbitems) {
-          hys = y;
-          switchmenu(226);
-        }
-        else {
-          switchmenu(2);
-        }
-      break;
-      //-------------------------------SelectMenu224-----------------------------------------
-      //SET SAFETY AND UPDATE EEPROM
-      case 226 :
-        switch (y){
-          case 1: sfty = true;defineRollup(nr,inc,rot,p,mod,hys,sfty); switchmenu(2);break;
-          case 2: sfty = false;defineRollup(nr,inc,rot,p,mod,hys,sfty); switchmenu(2);break;
-          case 3: switchmenu(2);break;
-        }
-      break;
-    //-------------------------------SelectMenu31-----------------------------------------
-  /*  case 3: Scrollingmenu("FANS*", 3, "Program", "setProgram", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 31: Scrollingnumbers("#****",(NBFANS+1), currentMenuItem, 1, 1); break;
-    case 32: Scrollingnumbers("#****", (NBFANS+1), currentMenuItem, 1, 1); break;
-    case 321: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 322: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-    case 323: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-*/
-
-//-------------------------------SelectMenu3-----------------------------------------
-//État, setProgram
-case 3 :
-  switch (y) {
-    case 1:
-      switchmenu(31); break;
-    case 2:
-      switchmenu(32);
-      break;
-    case 3: switchmenu(0); break;
-  }
-break;
-
-//-------------------------------SelectMenu31-----------------------------------------
-    //PROGRAMME DES FANS
-    case 31 :
-      if (y < Nbitems) {
-        switch(y){
-          case 1 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1); lcd.print(F("TA: ")); lcd.print(tempCible + vmodE(0)); lcd.print("C");
-          lcd.setCursor(0, 2); lcd.print(F("H: ")); lcd.print(rhystE(0)); lcd.print(F("C"));
-          lcd.setCursor(0, 3); lcd.print(F("SAFETY: ")); if(fanSafetyE(0)== true){lcd.print(F("Activated"));}else{lcd.print(F("Deactivated"));}
-          break;
-          case 2 :
-          lcd.setCursor(0, 1); lcd.print(F("TA: ")); lcd.print(tempCible + vmodE(1)); lcd.print("C");
-          lcd.setCursor(0, 2); lcd.print(F("H: ")); lcd.print(rhystE(1)); lcd.print(F("C"));
-          lcd.setCursor(0, 3); lcd.print(F("SAFETY: ")); if(fanSafetyE(1)== true){lcd.print(F("Activated"));}else{lcd.print(F("Deactivated"));}
-          break;
-        }
-      }
-      else {
-        switchmenu(3);
-      }
-      break;
-    //-------------------------------SelectMenu32-----------------------------------------
-    //SET FAN PROGRAM
-    case 32 :
-      if (y < Nbitems) {
-        nr = y;
-        switchmenu(321);
-      }
-      else {
-        switchmenu(3);
-      }
-      break;
-    //-------------------------------SelectMenu321-----------------------------------------
-    //SET MOD
-    case 321 :
-      if (y < Nbitems) {
-        mod = y-11;
-        switchmenu(322);
-      }
-      else {
-        switchmenu(2);
-      }
-      break;
-    //-------------------------------SelectMenu322-----------------------------------------
-    //SET HYSTERESIS
-    case 322 :
-      if (y < Nbitems) {
-        hys = y;
-        switchmenu(323);
-      }
-      else {
-        switchmenu(2);
-      }
-      break;
-      //-------------------------------SelectMenu3231-----------------------------------------
-      //SET SAFETY AND UPDATE EEPROM
-      case 323 :
-        switch (y){
-          case 1: sfty = true;defineFan(nr,mod,hys,sfty); switchmenu(3);break;
-          case 2: sfty = false;defineFan(nr,mod,hys,sfty); switchmenu(3);break;
-          case 3: switchmenu(3);break;
-        }
-      break;
-
-/*  case 4: Scrollingmenu("HEATR", 3, "Program", "setProgram", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 41: Scrollingnumbers("ITEM*",(NBFANS+1), currentMenuItem, 1, 1); break;
-    case 42: Scrollingnumbers("ITEM*", (NBFANS+1), currentMenuItem, 1, 1); break;
-    case 421: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 422: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-*/
-
-//-------------------------------SelectMenu4-----------------------------------------
-//État, setProgram
-case 4 :
-  switch (y) {
-    case 1:
-      switchmenu(41); break;
-    case 2:
-      if (NBFANS == 2){switchmenu(42);}
-      else{switchmenu(0);}
-      break;
-    case 3: switchmenu(0); break;
-  }
-break;
-
-//-------------------------------SelectMenu41-----------------------------------------
-    //PROGRAMME DES CHAUFFERETTES
-    case 41 :
-      if (y < Nbitems) {
-        switch(y){
-          case 1 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1); lcd.print(F("TA: ")); lcd.print(tempCible + hmodE(0)); lcd.print("C");
-          lcd.setCursor(0, 2); lcd.print(F("H: ")); lcd.print(hhystE(0)); lcd.print(F("C"));
-          break;
-          case 2 :
-          lcd.setCursor(0, 1); lcd.print(F("TA: ")); lcd.print(tempCible + hmodE(1)); lcd.print("C");
-          lcd.setCursor(0, 2); lcd.print(F("H: ")); lcd.print(hhystE(1)); lcd.print(F("C"));
-          break;
-        }
-      }
-      else {
-        switchmenu(4);
-      }
-      break;
-    //-------------------------------SelectMenu42-----------------------------------------
-    //SET CHAUFFERETTES PROGRAM
-    case 42 :
-      if (y < Nbitems) {
-        nr = y;
-        switchmenu(421);
-      }
-      else {
-        switchmenu(4);
-      }
-      break;
-    //-------------------------------SelectMenu421-----------------------------------------
-    //SET MOD
-    case 421 :
-      if (y < Nbitems) {
-        mod = y-11;
-        switchmenu(422);
-      }
-      else {
-        switchmenu(4);
-      }
-      break;
-    //-------------------------------SelectMenu422-----------------------------------------
-    //SET HYSTERESIS
-    case 422 :
-      if (y < Nbitems) {
-        hys = y;
-        defineHeater(nr,mod,hys);
-        switchmenu(4);
-      }
-      else {
-        switchmenu(4);
-      }
-      break;
-      /*
-      case 5: Scrollingmenu("PROG*", 3, "Timezones", "setTimezones", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-      case 51: Scrollingnumbers("TIMZ*",(NBPROGRAMS+1),currentMenuItem, 1, 1);break;
-      case 52: Scrollingnumbers("TIMZ*",(NBPROGRAMS+1),currentMenuItem, 1, 1);break;
-      case 521: Scrollingmenu("ITEM*", 3,"SR", "MANUAL", "SS", "", "", "", "",  "", "", "", currentMenuItem);break;
-      case 5221: Scrollingnumbers("HOUR*",25, currentMenuItem, 1, 1); break;
-      case 523: Scrollingnumbers("MIN***",62, currentMenuItem, 0 , 1); break;
-      case 5222: Scrollingnumbers("MOD***",122, currentMenuItem, -60 , 1); break;
-      case 524: Scrollingnumbers("TEMP", 42, currentMenuItem, 0, 1);break;
-*/
-      //-------------------------------SelectMenu5-----------------------------------------
-      //État, setProgram
-      case 5 :
-        switch (y) {
-          case 1:
-            switchmenu(51); break;
-          case 2:
-            switchmenu(52); break;
-          case 3: switchmenu(0); break;
-        }
-      break;
-
-      //-------------------------------SelectMenu41-----------------------------------------
-
-      //PROGRAMME DES TIMEZONES
-      case 51 :
-          switch(y){
-            case 1 :
-              if (nbPrograms > 1){
-                programPrintM(0);
-              }
-              else if(nbPrograms == 1){
-                programPrintE(0);
-              }
-              else{switchmenu(5);}
-            break;
-            case 2 :
-              if (nbPrograms > 2){
-                programPrintM(1);
-              }
-              else if(nbPrograms == 2){
-                programPrintE(1);
-              }
-              else{switchmenu(5);}
-            break;
-            case 3 :
-              if (nbPrograms > 3){
-                programPrintM(2);
-              }
-              else if(nbPrograms == 3){
-                programPrintE(2);
-              }
-              else{switchmenu(5);}
-            break;
-            case 4 :
-              if (nbPrograms > 4){
-                programPrintM(3);
-              }
-              else if(nbPrograms == 4){
-                programPrintE(3);
-              }
-              else{switchmenu(5);}
-            break;
-            case 5 :
-              if (nbPrograms > 5){
-                programPrintM(4);
-              }
-              else if(nbPrograms == 5){
-                programPrintE(4);
-              }
-              else{switchmenu(5);}
-            break;
-            case 6 :
-              switchmenu(5);
-            break;
-          }
-        break;
-    //-------------------------------SelectMenu52-----------------------------------------
-    //SET TIMEZONES PROGRAM
-    case 52 :
-      if (y < Nbitems) {
-        nr = y;
-        switchmenu(521);
-      }
-      else {
-        switchmenu(5);
-      }
-      break;
-    //-------------------------------SelectMenu521-----------------------------------------
-    //SET TYPE
-    case 521 :
-      switch(y){
-        case 1:typ = SR;switchmenu(5222);break;
-        case 2:typ = CLOCK;switchmenu(5221);break;
-        case 3:typ = SS;switchmenu(5222);break;
-        case 4:switchmenu(5);break;
-      }
-      break;
-    //-------------------------------SelectMenu5221-----------------------------------------
-    //SET HOUR
-    case 5221 :
-      if (y < Nbitems) {
-        hr = y;
-        switchmenu(523);
-      }
-      else{
-        switchmenu(5);
-      }
-      break;
-    //-------------------------------SelectMenu523-----------------------------------------
-    //SET MINUTES
-    case 523 :
-      if (y < Nbitems) {
-        mn = y - 1;
-        switchmenu(524);
-        Serial.println(mn);
-      }
-      else {
-        switchmenu(5);
-      }
-      break;
-    //-------------------------------SelectMenu5222-----------------------------------------
-    //SET MOD
-    case 5222 :
-      if (y < Nbitems) {
-        mod = y-60;
-        switchmenu(524);
-      }
-      else {
-        switchmenu(5);
-      }
-    break;
-    //-------------------------------SelectMenu524-----------------------------------------
-    //SET TEMP CIBLE AND UPDATE EEPROM
-    case 524 :
-      if (y < Nbitems) {
-        tt = y-1;
-        if (typ == CLOCK){
-          defineProgram(nr,typ,hr,mn,tt);
-          setPrograms();
-            switchmenu(5);
-        }
-        else{
-          defineProgram(nr,typ,0,mod,tt);
-          setPrograms();
-            switchmenu(5);
-        }
-      }
-      else {
-        switchmenu(5);
-      }
-      break;
-    }
-}


initializes with pen up

initializes with pen up

--- robots/maproom/maproom.ino
+++ robots/maproom/maproom.ino
@@ -26,6 +26,7 @@

 void setup() {
   robot = Robot(ROBOT_ID, PIN_DIR_A, PIN_PWM_A, PIN_DIR_B, PIN_PWM_B, PIN_DIR_C, PIN_PWM_C);
+  robot.setPen(PEN_UP);
   robot.stop();

   bufLen = 0;


Updated ESP8266-RN2483-basic for rn2xx3.

--- examples/ESP8266-RN2483-basic/ESP8266-RN2483-basic.ino
+++ examples/ESP8266-RN2483-basic/ESP8266-RN2483-basic.ino
@@ -14,8 +14,8 @@
  * The appropriate line is "myLora.initABP(XXX);" or "myLora.initOTAA(XXX);"
  * When using ABP, it is advised to enable "relax frame count".
  *
- * Connect the RN2483 as follows:
- * RN2483 -- ESP8266
+ * Connect the RN2xx3 as follows:
+ * RN2xx3 -- ESP8266
  * Uart TX -- GPIO4
  * Uart RX -- GPIO5
  * Reset -- GPIO15
@@ -23,16 +23,16 @@
  * Gnd -- Gnd
  *
  */
-#include <rn2483.h>
+#include <rn2xx3.h>
 #include <SoftwareSerial.h>

 #define RESET 15
 SoftwareSerial mySerial(4, 5); // RX, TX !! labels on relay board is swapped !!

-//create an instance of the rn2483 library,
+//create an instance of the rn2xx3 library,
 //giving the software UART as stream to use,
 //and using LoRa WAN
-rn2483 myLora(mySerial);
+rn2xx3 myLora(mySerial);

 // the setup routine runs once when you press reset:
 void setup() {
@@ -59,20 +59,20 @@

 void initialize_radio()
 {
-  //reset RN2483
+  //reset RN2xx3
   pinMode(RESET, OUTPUT);
   digitalWrite(RESET, LOW);
   delay(100);
   digitalWrite(RESET, HIGH);

-  delay(100); //wait for the RN2483's startup message
+  delay(100); //wait for the RN2xx3's startup message
   mySerial.flush();

   //check communication with radio
   String hweui = myLora.hweui();
   while(hweui.length() != 16)
   {
-    Serial.println("Communication with RN2483 unsuccesful. Power cycle the board.");
+    Serial.println("Communication with RN2xx3 unsuccesful. Power cycle the board.");
     Serial.println(hweui);
     delay(10000);
     hweui = myLora.hweui();
@@ -81,7 +81,7 @@
   //print out the HWEUI so that we can register it via ttnctl
   Serial.println("When using OTAA, register this DevEUI: ");
   Serial.println(hweui);
-  Serial.println("RN2483 firmware version:");
+  Serial.println("RN2xx3 firmware version:");
   Serial.println(myLora.sysver());

   //configure your keys and join the network


Simplified generator example

Simplified generator example

--- examples/JsonGeneratorExample/JsonGeneratorExample.ino
+++ examples/JsonGeneratorExample/JsonGeneratorExample.ino
@@ -11,14 +11,13 @@

   StaticJsonBuffer<200> jsonBuffer;

-  JsonArray& array = jsonBuffer.createArray();
-  array.add(48.756080, 6);  // 6 is the number of decimals to print
-  array.add(2.302038, 6);   // if not specified, 2 digits are printed
-
   JsonObject& root = jsonBuffer.createObject();
   root["sensor"] = "gps";
   root["time"] = 1351824120;
-  root["data"] = array;
+
+  JsonArray& data = root.createNestedArray("data");
+  data.add(48.756080, 6);  // 6 is the number of decimals to print
+  data.add(2.302038, 6);   // if not specified, 2 digits are printed

   root.printTo(Serial);
   // This prints:


fixed bug with line of text uncommented which caused a compilation error.

--- examples/ReadPOT_ArduinoSlave/ReadPOT_ArduinoSlave.ino
+++ examples/ReadPOT_ArduinoSlave/ReadPOT_ArduinoSlave.ino
@@ -1,7 +1,8 @@
 /* Read a Potentiometer on Analog input 0 and store in local buffer waiting for Amulet to request the data.
 *  To make Amulet request the proper variable, place this command in a view widget's (bargraph, numericField, etc) Href in GEmstudio:
 *  Amulet:uart1.word(0).value()
-*/ For other ports, change uart1 to your selected port.
+* For other ports, change uart1 to your selected port.
+*/

 #include <AmuletLCD.h>


Multiply arbitrary by a factor to increase range and reach saturation even with static error

--- Arduino/GroundUnit/GroundUnit.ino
+++ Arduino/GroundUnit/GroundUnit.ino
@@ -339,13 +339,13 @@
   }
   if (myPID1.GetMode() == AUTOMATIC)
   {
-    Setpoint1 = atoi(setpos1.value())/127.*posSat1;
+    Setpoint1 = atoi(setpos1.value())/127.*posSat1*1.3;//Factor to go a bit further and be sure to reach saturation (even with static error)
     myPID1.Compute();
     power1 = Output1*127;
   }
   if (myPID2.GetMode() == AUTOMATIC)
   {
-    Setpoint2 = atoi(setpos2.value())/127.*posSat2;
+    Setpoint2 = atoi(setpos2.value())/127.*posSat2*1.3;
     myPID2.Compute();
     power2 = Output2*127;
   }
@@ -386,14 +386,11 @@
   if (speedlim1.isUpdated())
   {
      myPID1.SetOutputLimits(-atoi(speedlim1.value())/127., atoi(speedlim1.value())/127.);
+     speedSat1 = atoi(speedlim1.value())/127.;
   }
   if (speedlim2.isUpdated())
   {
     myPID2.SetOutputLimits(-atoi(speedlim2.value())/127., atoi(speedlim2.value())/127.);
-  }
-  if (speedlim1.isUpdated())
-  {
-    speedSat1 = atoi(speedlim1.value())/127.;
   }
   if (poslim1.isUpdated())
   {


removed timestamp; added root_topic payload

--- yun/Blynk_Arduino_Yun/Blynk_Arduino_Yun.ino
+++ yun/Blynk_Arduino_Yun/Blynk_Arduino_Yun.ino
@@ -1,10 +1,6 @@
-#include <Process.h>
 #include <Bridge.h>
 #include <BridgeClient.h>

-Process date;
-int32_t whenTime;
-int32_t lastTime = -1;
 BridgeClient client;

 #include <BlynkSimpleYun.h>
@@ -12,7 +8,7 @@
 #define VPIN_HUMIDITY V1
 #define VPIN_TEMP V2

-char auth[] = "<AUTH-KEY>";
+char auth[] = "<BLYNK-AUTH-KEY>";

 #include <SimpleTimer.h>

@@ -33,11 +29,13 @@
 #define AIO_SERVER      "<MQTT-SERVER>"
 #define AIO_SERVERPORT  1883

+#define ROOT_TOPIC "arduino/yun"
+
 Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT);
-Adafruit_MQTT_Publish when = Adafruit_MQTT_Publish(&mqtt, "arduino/yun/time");
-Adafruit_MQTT_Publish humidity = Adafruit_MQTT_Publish(&mqtt, "arduino/yun/humidity");
-Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, "arduino/yun/temperature");
-Adafruit_MQTT_Publish heatIndex = Adafruit_MQTT_Publish(&mqtt, "arduino/yun/heatIndex");
+Adafruit_MQTT_Publish yun = Adafruit_MQTT_Publish(&mqtt, ROOT_TOPIC);
+Adafruit_MQTT_Publish humidity = Adafruit_MQTT_Publish(&mqtt, ROOT_TOPIC "/humidity");
+Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, ROOT_TOPIC "/temperature");
+Adafruit_MQTT_Publish heatIndex = Adafruit_MQTT_Publish(&mqtt, ROOT_TOPIC "/heatIndex");

 void setup()
 {
@@ -45,14 +43,6 @@
   delay(10);
   Blynk.begin(auth);
   Bridge.begin();
-
-  // run an initial date process. Should return:
-  // seconds since 1970-01-01 00:00:00 UTC.
-  if (!date.running()) {
-    date.begin("date");
-    date.addParameter("+%s");
-    date.run();
-  }

   // Setup a function to be called every second
   timer.setInterval(2000L, sendValues);
@@ -67,32 +57,26 @@
     return;
   }

-  if (lastTime != whenTime) { // if a second has passed
-    when.publish(whenTime);
-
-    // restart the date process:
-    if (!date.running()) {
-      date.begin("date");
-      date.addParameter("+%s");
-      date.run();
-    }
-  }
-
   float hic = dht.computeHeatIndex(t, h, false);
   Blynk.virtualWrite(1, (int)h);
   Blynk.virtualWrite(2, (int)t);
   Blynk.virtualWrite(3, hic);

+  String json = "{\"humidity\":";
+  json += (int32_t)h;
+  json += ",\"temperature\":";
+  json += (int32_t)t;
+  json += ",\"heatIndex\":";
+  json += hic;
+  json += "}";
+  int json_length = json.length() + 1;
+  char data[json_length];
+  json.toCharArray(data, json_length);
+
+  yun.publish(data);
   humidity.publish((int32_t)h);
   temperature.publish((int32_t)t);
   heatIndex.publish(hic);
-
-  //if there's a result from the date process, parse it:
-  while (date.available() > 0) {
-    String timeString = date.readString();
-    lastTime = whenTime;
-    whenTime = timeString.toInt();
-  }
 }

 void loop()


Default status to quizzical

Default status to quizzical

--- CushionFirmware/CushionFirmware.ino
+++ CushionFirmware/CushionFirmware.ino
@@ -69,8 +69,8 @@
     _pwmDriver.setPin(i, 0);

   // Setup default state
-  //setQuizical();
-  setCalm();
+  setQuizical();
+  //setCalm();

   // Enable bluetooth interface
   _bluetoothSerial.begin(9600);


TG-12 #done - enter into FREQUENCY_STATE

--- AlarmClock.ino
+++ AlarmClock.ino
@@ -1,40 +1,56 @@
 // Libraries
 #include <LiquidCrystal.h>
+#include <string.h>

 // classes
 #include "classes/Menu.h"

-// TIME VARIABLES
-const int enterButton = 22;
-const int lessButton = 23;
-const int moreButton = 24;
-const int exitButton = 25;
-int buttonValues[4];
+// INPUT OUTPUT CONSTANTS
+const int MENU_BUTTON_PIN = 22;
+const int LESS_BUTTON_PIN = 23;
+const int MORE_BUTTON_PIN = 24;
+const int EXIT_BUTTON_PIN = 25;
+const int NUMBER_OF_BUTTONS = 4;
+
+// INPUT OUTPUT VARIABLES
+int buttonValues[NUMBER_OF_BUTTONS];
+int oldButtonValues[NUMBER_OF_BUTTONS];

 // LOGIC
 MenuStruct *menuStruct;

-void readButtons();
+bool readButtons();

 void setup() {
     // HARDWARE INITS
-    pinMode(enterButton, INPUT);
-    pinMode(lessButton, INPUT);
-    pinMode(moreButton, INPUT);
-    pinMode(exitButton, INPUT);
+    pinMode(MENU_BUTTON_PIN, INPUT);
+    pinMode(LESS_BUTTON_PIN, INPUT);
+    pinMode(MORE_BUTTON_PIN, INPUT);
+    pinMode(EXIT_BUTTON_PIN, INPUT);

     // LOGIC INITS
     menuStruct = constructMenuStruct();
 }

 void loop() {
-    readButtons();
-    menuStruct->handleButtons(menuStruct, buttonValues);
+    bool buttonStateChanged = readButtons();
+    if (buttonStateChanged) {
+        menuStruct->handleButtons(menuStruct, buttonValues);
+    }
 }

-void readButtons() {
-    buttonValues[MENU_BUTTON] = digitalRead(enterButton);
-    buttonValues[LESS_BUTTON] = digitalRead(lessButton);
-    buttonValues[MORE_BUTTON] = digitalRead(moreButton);
-    buttonValues[EXIT_BUTTON] = digitalRead(exitButton);
+bool readButtons() {
+    memcpy(oldButtonValues, buttonValues, NUMBER_OF_BUTTONS * sizeof(int));
+    bool buttonStateChanged = false;
+    buttonValues[MENU_BUTTON] = digitalRead(MENU_BUTTON_PIN);
+    buttonValues[LESS_BUTTON] = digitalRead(LESS_BUTTON_PIN);
+    buttonValues[MORE_BUTTON] = digitalRead(MORE_BUTTON_PIN);
+    buttonValues[EXIT_BUTTON] = digitalRead(EXIT_BUTTON_PIN);
+    for (int i = 0; i < NUMBER_OF_BUTTONS; i++) {
+        if (buttonValues[i] != oldButtonValues[i]) {
+            buttonStateChanged = true;
+            break;
+        }
+    }
+    return buttonStateChanged;
 }


Ver 2.3 released

Ver 2.3 released

Ver 2.3 released

--- KillSwitchduino/KillSwitchduino.ino
+++ KillSwitchduino/KillSwitchduino.ino
@@ -1207,9 +1207,7 @@
     {SystemStatusLowBatt = 2;}
  if (MainBattVoltageAverage > MainBattLowVoltageL1) {SystemStatusLowBatt=0;}

-  readCurrentSensorData();
-   Current_quartAverage_mA=(Current_quartAverage_mA + Current_mA) / 2;
-   Current_mAperHourConsumed+=Current_quartAverage_mA / 14400;
+

 //processing RX signal quality
  if ( MainSWPacketsCounter_time == 0 ){
@@ -1232,6 +1230,11 @@

 //dump consumed mA to EEPROM
  if (CurrentSensorEnabled) {
+
+  readCurrentSensorData();
+   Current_quartAverage_mA=(Current_quartAverage_mA + Current_mA) / 2;
+   Current_mAperHourConsumed+=Current_quartAverage_mA / 14400;
+
  if (CurrentDump_time==0) {
    DumpConsToEEPROM();
    CurrentDump_time=39;


Update Wing_Analog with common numbering

--- build/shared/examples/WING_Analog/WING_Analog.ino
+++ build/shared/examples/WING_Analog/WING_Analog.ino
@@ -55,7 +55,7 @@

   delay(1000);
   Serial.begin(115200);
-  analog.begin(CS(WCH4),WISHBONESLOT(5),ADCBITS(SPIADC_12BIT));
+  analog.begin(CS(WING_CH4),WISHBONESLOT(5),ADCBITS(SPIADC_12BIT));
   Serial.println("Channel 0\t1\t2\t3\t4\t5\t6\t7");

 }


Re-fix example.

Re-fix example.

--- res/Examples/MIDI_RPN_NRPN/MIDI_RPN_NRPN.ino
+++ res/Examples/MIDI_RPN_NRPN/MIDI_RPN_NRPN.ino
@@ -198,7 +198,7 @@
         const midi::Channel channel = 1;
         const byte semitones = 12;
         const byte cents     = 42;
-        MIDI.startRpn(midi::PitchBendSensitivity, channel);
+        MIDI.beginRpn(midi::RPN::PitchBendSensitivity, channel);
         MIDI.sendRpnValue(semitones, cents, channel);
         MIDI.endRpn(channel);
     }


Update lcd to display and add loop functionality

--- WeatherThing.ino
+++ WeatherThing.ino
@@ -4,13 +4,14 @@
 #include <Arduino.h>  // enables use of byte pics

 void setup() {
-  LCD::setup();
+  Display::setup();
   Sensor::setup();
 }

 void loop() {
   int temp = Sensor::readTemp();
-  LCD::displayTemp(temp);
-  delay(5000);
-  LCD::clearScreen();
+  int hum = Sensor::readHum();
+  Display::displayTemp(temp);
+  Display::displayHum(hum);
+  delay(3000);
 }


cut-and-paste TYPO (#53)

cut-and-paste TYPO (#53)

--- examples/save_config_demo/save_config_demo.ino
+++ examples/save_config_demo/save_config_demo.ino
@@ -21,7 +21,7 @@

 void createCustomRoute(WebServer *server) {
   server->on("/settings.html", HTTPMethod::HTTP_GET, [server](){
-    configManager.streamFile(settingsHTML, mimeHTML);
+    configManager.streamFile(configHTMLFile, mimeHTML);
   });
 }


Fixed scope issues of myFile.

Fixed scope issues of myFile.

--- code/IMU6050.ino
+++ code/IMU6050.ino
@@ -43,6 +43,8 @@

 extern void measureGyroSum(void);
 extern void measureAccelSum(void);
+
+extern File myfile;

 int16_t gyroRaw[3];
 int16_t accelRaw[3];


fixes

fixes

--- garden.ino
+++ garden.ino
@@ -1,5 +1,3 @@
-// This #include statement was automatically added by the Particle IDE.
-// #include "TimeAlarms/TimeAlarms.h"
 #include "SparkTime.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -22,130 +20,140 @@
 unsigned long last_cloud_time_sync = millis();
 byte zone_state_array[NUM_ZONES] = {0,0,0,0};
 byte zones[NUM_ZONES] = {ZONE1, ZONE2, ZONE3, ZONE4};
-byte test_timer = 20;	// seconds for "relay test heartbeat timer"
-String sString;
-String dString;
+String sString;  // general status string
+String dString;  // duration string
+String zString;  // zone string
 unsigned long currentTime;
-unsigned long stopTime;
+unsigned long stopTime = 0;

 UDP UDPClient;
 SparkTime rtc;

 void setup() {
-
-    rtc.begin(&UDPClient, "north-america.pool.ntp.org");
-    rtc.setTimeZone(-8); // gmt offset
-    rtc.setUseDST(true);

-	// pin setup and initialization
-	for (int i = 0; i < NUM_ZONES; i++){
-		pinMode(zones[i], OUTPUT);
-		digitalWrite(zones[i], LOW);
-	}
-    sString = "Initialized and waiting...";
-    dString = "No duration";
-
-	Particle.publish("striide.garden.online");
-	Particle.function("runZone", runZone);
-	Particle.function("allOff", zones_all_off);
-    Particle.variable("status", sString);
-    Particle.variable("duration", dString);
+		rtc.begin(&UDPClient, "north-america.pool.ntp.org");
+		rtc.setTimeZone(-8); // gmt offset
+		rtc.setUseDST(true);
+
+		// pin setup and initialization
+		for (int i = 0; i < NUM_ZONES; i++)
+		{
+				pinMode(zones[i], OUTPUT);
+				digitalWrite(zones[i], LOW);
+		}
+		sString = "Initialized and waiting...";
+		dString = "-";
+		zString = "-";
+
+		Particle.publish("striide.garden.online");
+
+		Particle.function("runZone", runZone);
+		Particle.function("allOff", zones_all_off);
+		Particle.variable("status", sString);
+		Particle.variable("duration", dString);
+		Particle.variable("zone", zString);
 }

+
 void loop() {
-    currentTime = rtc.nowEpoch();
-
-    if(stopTime < currentTime)
-    {
-        zones_all_off("");
-    }
-    else
-    {
-        dString = (currentTime - stopTime) + " seconds remaining";
-    }
-
-
+		currentTime = rtc.nowEpoch();
+
+		if(stopTime > 0 && stopTime < currentTime)
+		{
+				stopTime = 0;
+				zones_all_off("");
+		}
+
+		// wait 5 seconds
+		delay(5000);
 }
+
 int readZone(String command)
 {
-    int beginIdx = 0;
-    int idx = command.indexOf(",");
-
-    String zone_s = command.substring(beginIdx, idx);
-	zone_s.trim();
-    return zone_s.toInt();
+		int beginIdx = 0;
+		int idx = command.indexOf(",");
+
+		String zone_s = command.substring(beginIdx, idx);
+		zone_s.trim();
+		return zone_s.toInt();
 }

 int readDuration(String command)
 {
-    int beginIdx = 0;
-    int idx = command.indexOf(",");
-
-    beginIdx = idx + 1;
-	String duration_s  = command.substring(beginIdx);
-    duration_s.trim();
-    return duration_s.toInt();
+		int beginIdx = 0;
+		int idx = command.indexOf(",");
+
+		beginIdx = idx + 1;
+		String duration_s  = command.substring(beginIdx);
+		duration_s.trim();
+		return duration_s.toInt();
 }

 // *************** Particle Functions **********************************
 int runZone(String command) {
-
-    int zone_i = readZone(command);
-    int zone_duration = readDuration(command);
-
-    if(zone_i > 0 && zone_duration > 0)
-    {
-
-        // dString = "duration: " + zone_duration;
-        Particle.publish("striide.garden.runzone",command);
-        run_zone_for_duration(zone_i,zone_duration);
-        return zone_i;
-    }
-    else
-    {
-        Particle.publish("striide.garden.error","Error processing runZone command");
-        return 1;
-    }
-
+
+		int zone_i = readZone(command);
+		int zone_duration = readDuration(command);
+
+		if(zone_i > 0 && zone_duration > 0)
+		{
+				Particle.publish("striide.garden.runzone");
+
+				dString = "" + zone_duration;
+				zString = "" + zone_i;
+
+				run_zone_for_duration(zone_i,zone_duration);
+				return zone_i;
+		}
+		else
+		{
+				Particle.publish("striide.garden.error","Error processing runZone command");
+				return 1;
+		}
+
 }

 // ************************* ZONE FUNCTIONS *************************

-void run_zone_for_duration(int zone_number, int duration){
-	// turn on zone for duration
-    // set the stopTime
-    stopTime = currentTime + duration;
-    change_zone_valve(zone_number,true);
-    dString = duration + " seconds";
-
-    char str[80];
-    sprintf(str, "duration(%d):stopTime(%lu):currentTime(%lu)", duration, stopTime, currentTime);
+// turn on zone for duration
+void run_zone_for_duration(int zone_number, int duration)
+{
+		stopTime = currentTime + duration;
+		change_zone_valve(zone_number,true);
 }

-bool change_zone_valve(int zone_number, bool on_or_off){
-	// turn the specified zone on or off
-	String status;
-
-    // turn other zones off
-    zones_all_off("");
-
-	if (on_or_off){
-        status = "on";
-        digitalWrite(zones[zone_number-1], HIGH);
-        sString = zone_number + "is on";
-	}
-
-	return on_or_off;
+// turn the specified zone on or off
+bool change_zone_valve(int zone_number, bool on_or_off)
+{
+		// turn other zones off
+		zones_all_off_helper();
+
+		if (on_or_off)
+		{
+				digitalWrite(zones[zone_number-1], HIGH);
+				sString = "on";
+		}
+		else
+		{
+				sString = "off";
+		}
+
+		return on_or_off;
+}
+int zones_all_off_helper()
+{
+		for (int i = 0; i < NUM_ZONES; i++){
+				digitalWrite(zones[i], LOW);
+		}
+		sString = "off";
+		return 1;
 }

-int zones_all_off(String command){
-	// turn all zones off
-
-	Particle.publish("striide.garden.all_off");
-    for (int i = 0; i < NUM_ZONES; i++){
-		digitalWrite(zones[i], LOW);
-	}
-    sString = "All off";
-    return 1;
+// turn all zones off
+int zones_all_off(String command)
+{
+		Particle.publish("striide.garden.all_off");
+		stopTime = 0;
+		return zones_all_off_helper();
 }


Modified to utilize 'standard' libraries

--- IDCF_MQTT_Subscriber/IDCF_MQTT_Subscriber.ino
+++ IDCF_MQTT_Subscriber/IDCF_MQTT_Subscriber.ino
@@ -1,39 +1,36 @@
-/*
- * References
- *
- * mqtt_subscriber by Ian Tester (originally by Nicholas O'Leary)
- * https://github.com/Imroy/pubsubclient/tree/master/examples/mqtt_subscriber
- */
-
 #include <ESP8266WiFi.h>
 #include <PubSubClient.h>
+#include <ArduinoJson.h>

 #include "config.h"

-#define BUFFER_SIZE 100
+// メッセージを受け取ったらシリアルにプリント
+void callback(char* topic, byte* payload, unsigned int length) {
+  // PubSubClient.hで定義されているMQTTの最大パケットサイズ
+  char buffer[MQTT_MAX_PACKET_SIZE];

-// メッセージを受け取ったらシリアルにプリント
-void callback(const MQTT::Publish& pub) {
-  Serial.print(pub.topic());
-  Serial.print(" => ");
-  if (pub.has_stream()) {
-    // ペイロードのサイズが大きい場合にはローカルに用意したバッファに分割して読み取り
-    // 読み取った単位ごとにシリアルにプリント
-    uint8_t buf[BUFFER_SIZE];
-    int read;
-    while (read = pub.payload_stream()->read(buf, BUFFER_SIZE)) {
-      Serial.write(buf, read);
-    }
-    pub.payload_stream()->stop();
-    Serial.println();
-  } else {
-    // ペイロードのサイズが小さい場合にはそのままシリアルにプリント
-    Serial.println(pub.payload_string());
+  snprintf(buffer, sizeof(buffer), "%s", payload);
+  Serial.print("Received: ");
+  Serial.println(buffer);
+
+  // 受け取ったJSON形式のペイロードをデコードする
+  StaticJsonBuffer<MQTT_MAX_PACKET_SIZE> jsonBuffer;
+  JsonObject& root = jsonBuffer.parseObject(buffer);
+
+  if (!root.success()) {
+    Serial.println("parseObject() failed");
+    return;
+  }
+
+  const char* parsedPayload = root["data"]["payload"];
+  if (parsedPayload != NULL) {
+    Serial.print("payload: ");
+    Serial.println(parsedPayload);
   }
 }

-WiFiClient wclient;
-PubSubClient client(wclient, server);
+WiFiClient wifiClient;
+PubSubClient client(wifiClient);

 void setup() {
   Serial.begin(115200);
@@ -50,23 +47,33 @@
     WiFi.begin(ssid, pass);

     if (WiFi.waitForConnectResult() != WL_CONNECTED) {
+      // Wi-Fiアクスポイントへの接続に失敗したら5秒間待ってリトライ
+      delay(5000);
       return;
-    }
-    Serial.println("WiFi connected");
-  }
-
-  if (!client.connected()) {
-    // アクション1のUUIDとトークンをユーザ名およびパスワードとしてサーバに接続
-    MQTT::Connect mqttConnect(mqtt_client_id);
-    mqttConnect.set_auth(action_1_uuid, action_1_token);
-
-    if (client.connect(mqttConnect)) {
-      client.set_callback(callback);
-      client.subscribe(action_1_uuid);
+    } else {
+      Serial.print("WiFi connected: ");
+      Serial.println(WiFi.localIP());
+      client.setServer(server, 1883);
     }
   }

-  if (client.connected()) {
+  // クライアントがサーバに接続されていなければ
+  if (!client.connected()) {
+    // アクション1のUUIDとトークンをユーザ名およびパスワードとしてサーバに接続
+    client.connect(mqtt_client_id, action_1_uuid, action_1_token);
+
+    if (client.connected()) {
+      Serial.print("MQTT connected: ");
+      Serial.println(server);
+      client.setCallback(callback);
+      client.subscribe(action_1_uuid);
+    } else {
+      Serial.print("MQTT connection failed: ");
+      Serial.println(client.state());
+      delay(5000);
+    }
+  } else {
+    // 既にサーバに接続されていれば通常処理を行う
     client.loop();
   }
 }


New readouts like realSOC and cleanup

New readouts like realSOC and cleanup

--- ED_BMSdiag.ino
+++ ED_BMSdiag.ino
@@ -1,5 +1,5 @@
 //--------------------------------------------------------------------------------
-// ED BMSdiag, v0.31
+// ED BMSdiag, v0.35
 // Retrieve battery diagnostic data from your smart electric drive EV.
 //
 // (c) 2016 by MyLab-odyssey
@@ -21,9 +21,9 @@
 //! \brief   Retrieve battery diagnostic data from your smart electric drive EV.
 //! \brief   Build a diagnostic tool with the MCP2515 CAN controller and Arduino
 //! \brief   compatible hardware.
-//! \date    2016-April
+//! \date    2016-May
 //! \author  My-Lab-odyssey
-//! \version 0.31
+//! \version 0.35
 //--------------------------------------------------------------------------------

 //#define DO_DEBUG_UPDATE        //!< Uncomment to show DEBUG output
@@ -42,11 +42,13 @@
 #include <Average.h>

 //Global definitions
+#define VERSION F("0.35")
 #define DATALENGTH 440
 #define CELLCOUNT 93
 #define SPACER F("-----------------------------------------")
-#define MSG_OK F("OK   ")
-#define MSG_FAIL F("FAIL ")
+#define MSG_OK F("OK")
+#define MSG_FAIL F("FAIL")
+#define MSG_DOT F(".")

 //Data arrays
 unsigned int data[DATALENGTH];
@@ -55,7 +57,6 @@

 //BMS data structure
 typedef struct {
-  //
   unsigned int ADCCvolts_min;    //!< minimum cell voltage in mV, add offset +1500
   unsigned int ADCCvolts_mean;   //!< average cell voltage in mV, no offset
   unsigned int ADCCvolts_max;    //!< maxiimum cell voltage in mV, add offset +1500
@@ -76,6 +77,9 @@
   unsigned int Ccap_max_As;      //!< cell capacity maximum in pack
   int CAP_max_at;                //!< cell number with capacity maximum in pack

+  int CapInit;                   //!< battery initial capacity (As/10)
+  int CapLoss;                   //!< battery capacity loss (x/1000) in %
+
   unsigned long HVoff_time;      //!< HighVoltage contactor off time in seconds
   unsigned long HV_lowcurrent;   //!< counter time of no current, reset e.g. with PLC heater or driving
   unsigned int OCVtimer;         //!< counter time in seconds to reach OCV state
@@ -87,9 +91,18 @@
   byte Month;                    //!< month of battery production
   byte Year;                     //!< year of battery production

+  byte hour;                     //!< time in car: hour
+  byte minutes;                  //!< time in car: minutes
+
   float SOC;                     //!< State of Charge, as reported by vehicle dash
+  unsigned int realSOC;          //!< is this the internal SOC value in % (x/10)
+
+  int Amps;                      //!< battery current in ampere (x/32)
+  int Power;                     //!< power in kW, drivetrain and charge ((x/8192)-1)*300
+
   float HV;                      //!< total voltage of HV system in V
   float LV;                      //!< 12V onboard voltage / LV system
+
   unsigned long ODO;             //!< Odometer count

   int Temps[13];                 //!< three temperatures per battery unit (1 to 3)
@@ -97,8 +110,7 @@

   byte HVcontactState;           //!< contactor state: 0 := OFF, 2 := ON
   long HVcontactCyclesLeft;      //!< counter related to ON/OFF cyles of the car
-  long HVcontactCyclesMax;       //!< static, seems to be maxiumum of contactor cycles
-
+  long HVcontactCyclesMax;       //!< static, seems to be maxiumum of contactor cycles
 } BatteryDiag_t;

 //CAN-Bus declarations
@@ -106,24 +118,27 @@
 unsigned char len = 0;
 unsigned char rxLength = 0;
 unsigned char rxBuf[8];
-unsigned char rqFlowControl[8] = {0x30, 0x08, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 byte rqFC_length = 8;            //!< Interval to send flow control messages (rqFC)
-unsigned char rqBattTemperatures[8] = {0x03, 0x22, 0x02, 0x01, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char rqBattModuleTemperatures[8] = {0x03, 0x22, 0x02, 0x02, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char rqBattADCref[8] = {0x03, 0x22, 0x02, 0x07, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char rqBattVolts[8] = {0x03, 0x22, 0x02, 0x08, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char rqBattDate[8] = {0x03, 0x22, 0x03, 0x04, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char rqBattCapacity[8] = {0x03, 0x22, 0x03, 0x10, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqFlowControl[8]               = {0x30, 0x08, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattTemperatures[8]          = {0x03, 0x22, 0x02, 0x01, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattModuleTemperatures[8]    = {0x03, 0x22, 0x02, 0x02, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattADCref[8]                = {0x03, 0x22, 0x02, 0x07, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattVolts[8]                 = {0x03, 0x22, 0x02, 0x08, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattAmps[8]                  = {0x03, 0x22, 0x02, 0x03, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattDate[8]                  = {0x03, 0x22, 0x03, 0x04, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattCapInit[8]               = {0x03, 0x22, 0x03, 0x05, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattCapLoss[8]               = {0x03, 0x22, 0x03, 0x09, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattCapacity[8]              = {0x03, 0x22, 0x03, 0x10, 0xFF, 0xFF, 0xFF, 0xFF};
 unsigned char rqBattHVContactorCyclesLeft[8] = {0x03, 0x22, 0x03, 0x0B, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char rqBattHVContactorMax[8] = {0x03, 0x22, 0x03, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF};
-unsigned char rqBattHVContactorState[8] = {0x03, 0x22, 0xD0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattHVContactorMax[8]        = {0x03, 0x22, 0x03, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF};
+unsigned char rqBattHVContactorState[8]      = {0x03, 0x22, 0xD0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};

 #define CS     10                //!< chip select pin of MCP2515 CAN-Controller
 #define CS_SD  8                 //!< CS for SD card, if you plan to use a logger...
 MCP_CAN CAN0(CS);                //!< Set CS pin

 BatteryDiag_t BattDiag;
-CTimeout CAN_Timeout(10000);     //!< Timeout value for CAN response in millis
+CTimeout CAN_Timeout(15000);     //!< Timeout value for CAN response in millis

 //--------------------------------------------------------------------------------
 //! \brief   SETUP()
@@ -132,7 +147,6 @@
 {
   Serial.begin(115200);
   while (!Serial); // while the serial stream is not open, do nothing:
-  Serial.println();

   pinMode(CS, OUTPUT);
   pinMode(CS_SD, OUTPUT);
@@ -151,6 +165,8 @@

   Serial.println(SPACER);
   Serial.println(F("--- ED Battery Management Diagnostics ---"));
+  Serial.print(F("--- v")); Serial.print(VERSION);
+  Serial.println(F("                             ---"));
   Serial.println(SPACER);

   //Serial.print(F("SRAM: ")); Serial.println(freeRam());
@@ -161,6 +177,7 @@
     delay(1000);
   } while (digitalRead(2));
   Serial.println(F("CONNECTED"));
+  Serial.println(SPACER);
 }

 //--------------------------------------------------------------------------------
@@ -176,7 +193,7 @@
 //! \brief   Wait for serial data to be avaiable.
 //--------------------------------------------------------------------------------
 void WaitforSerial() {
-  Serial.println(F("Press a key to start query..."));
+  Serial.println(F("Press a key to start query:"));
   while (!Serial.available()) {}                  // Wait for serial input to start
 }

@@ -510,6 +527,48 @@
 }

 //--------------------------------------------------------------------------------
+//! \brief   Read and evaluate initial battery capacity
+//! \param   enable verbose / debug output (boolean)
+//! \return  report success (boolean)
+//--------------------------------------------------------------------------------
+boolean getBatteryCapInit(boolean debug_verbose) {
+  unsigned int items;
+  unsigned int value;
+  items = Request_Diagnostics(rqBattCapInit);
+  if(items){
+    if (debug_verbose) {
+      PrintReadBuffer(items);
+    }
+    ReadDiagWord(&value,data,3,1);
+    BattDiag.CapInit = (signed) value;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+//--------------------------------------------------------------------------------
+//! \brief   Read and evaluate battery capacity loss
+//! \param   enable verbose / debug output (boolean)
+//! \return  report success (boolean)
+//--------------------------------------------------------------------------------
+boolean getBatteryCapLoss(boolean debug_verbose) {
+  unsigned int items;
+  unsigned int value;
+  items = Request_Diagnostics(rqBattCapLoss);
+  if(items){
+    if (debug_verbose) {
+      PrintReadBuffer(items);
+    }
+    ReadDiagWord(&value,data,3,1);
+    BattDiag.CapLoss = (signed) value;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+//--------------------------------------------------------------------------------
 //! \brief   Read and evaluate voltage data
 //! \param   enable verbose / debug output (boolean)
 //! \return  report success (boolean)
@@ -527,6 +586,27 @@
     BattDiag.Cvolts_max = CellVoltage.maximum(&BattDiag.CV_max_at);
     BattDiag.Cvolts_mean = CellVoltage.mean();
     BattDiag.Cvolts_stdev = CellVoltage.stddev();
+    return true;
+  } else {
+    return false;
+  }
+}
+
+//--------------------------------------------------------------------------------
+//! \brief   Read and evaluate current data / ampere
+//! \param   enable verbose / debug output (boolean)
+//! \return  report success (boolean)
+//--------------------------------------------------------------------------------
+boolean getBatteryAmps(boolean debug_verbose) {
+  unsigned int items;
+  unsigned int value;
+  items = Request_Diagnostics(rqBattAmps);
+  if(items){
+    if (debug_verbose) {
+      PrintReadBuffer(items);
+    }
+    ReadDiagWord(&value,data,3,1);
+    BattDiag.Amps = (signed) value;
     return true;
   } else {
     return false;
@@ -626,6 +706,51 @@
 }

 //--------------------------------------------------------------------------------
+//! \brief   Read and evaluate internal SOC - experimental
+//! \return  report success (boolean)
+//--------------------------------------------------------------------------------
+boolean ReadSOCinternal() {
+  setCAN_Filter(0x2D5);
+  CAN_Timeout.Reset();
+
+  if(!digitalRead(2)) {
+    do {
+    CAN0.readMsgBuf(&rxID, &len, rxBuf);
+      if (rxID == 0x2D5) {
+        BattDiag.realSOC =  (unsigned int) rxBuf[4] * 256 + (unsigned int) rxBuf[5];
+        return true;
+      }
+    } while (!CAN_Timeout.Expired(false));
+  }
+  return false;
+}
+
+//--------------------------------------------------------------------------------
+//! \brief   Read and evaluate internal SOC - experimental
+//! \return  report success (boolean)
+//--------------------------------------------------------------------------------
+boolean ReadPower() {
+  setCAN_Filter(0x508);
+  CAN_Timeout.Reset();
+
+  if(!digitalRead(2)) {
+    do {
+    CAN0.readMsgBuf(&rxID, &len, rxBuf);
+      if (rxID == 0x508) {
+        BattDiag.Power =  (unsigned int) (rxBuf[2] & 0x3F) * 256 + (unsigned int) rxBuf[3];
+        /*Serial.println();
+        for (int i = 0; i<8; i++) {
+          Serial.print(rxBuf[i], HEX); Serial.print(" ");
+        }
+        Serial.println(BattDiag.Power_or_Amps,HEX);*/
+        return true;
+      }
+    } while (!CAN_Timeout.Expired(false));
+  }
+  return false;
+}
+
+//--------------------------------------------------------------------------------
 //! \brief   Read and evaluate system High Voltage
 //! \return  report success (boolean)
 //--------------------------------------------------------------------------------
@@ -692,6 +817,27 @@
 }

 //--------------------------------------------------------------------------------
+//! \brief   Read and evaluate odometer
+//! \return  report success (boolean)
+//--------------------------------------------------------------------------------
+boolean ReadTime() {
+  setCAN_Filter(0x512);
+  CAN_Timeout.Reset();
+
+  if(!digitalRead(2)) {
+    do {
+    CAN0.readMsgBuf(&rxID, &len, rxBuf);
+      if (rxID == 0x512) {
+        BattDiag.hour = (unsigned int) rxBuf[0];
+        BattDiag.minutes = (unsigned int) rxBuf[1];
+        return true;
+      }
+    } while (!CAN_Timeout.Expired(false));
+  }
+  return false;
+}
+
+//--------------------------------------------------------------------------------
 //! \brief   LOOP()
 //--------------------------------------------------------------------------------
 void loop()
@@ -701,63 +847,114 @@
    //Wait for start via serial terminal
    WaitforSerial();
    clearSerialBuffer();
-   Serial.println(SPACER);
+   //Serial.println(SPACER);
    delay(500);
-
-   fOK = ReadSOC();
-   fOK = ReadHV();
-   fOK = ReadLV();
-   fOK = ReadODO();

-   setCAN_Filter(0x7EF);
-
+   //Read CAN-messages
    int testStep = 0;
    do {
       switch (testStep) {
         case 0:
-           Serial.print(F("Read Voltages ..."));
+           Serial.print(F("Reading data."));
+           fOK = ReadSOC();
+           break;
+        case 1:
+           fOK = ReadSOCinternal();
+           break;
+        case 2:
+           fOK = ReadPower();
+           break;
+        case 3:
+           fOK = ReadHV();
+           break;
+        case 4:
+           fOK = ReadLV();
+           break;
+        case 5:
+           fOK = ReadODO();
+           break;
+        case 6:
+           fOK = ReadTime();
+           break;
+      }
+      if (testStep < 7) {
+        if (fOK) {
+          Serial.print(MSG_DOT);
+        } else {
+          Serial.print(MSG_FAIL);Serial.print(F("#")); Serial.print(testStep);
+        }
+      }
+      testStep++;
+   } while (fOK && testStep < 7);
+
+
+   //Get diagnostics data
+   setCAN_Filter(0x7EF);
+
+   testStep = 0;
+   do {
+      switch (testStep) {
+        case 0:
            fOK = getBatteryVoltage(false);
            break;
         case 1:
-           Serial.print(F("Read Capacity ..."));
            fOK = getBatteryCapacity(false);
            break;
         case 2:
-           Serial.print(F("Read ADCref.  ..."));
+           fOK = getBatteryAmps(false);
+           break;
+        case 3:
+           fOK = getBatteryCapInit(false);
+           break;
+        case 4:
+           fOK = getBatteryCapLoss(false);
+           break;
+        case 5:
            fOK = getBatteryADCref(false);
            break;
-        case 3:
-           Serial.print(F("Read HV state ..."));
-           fOK = getHVcontactorState(false);
-           break;
-        case 4:
-           Serial.print(F("Read Prod.Date..."));
+        case 6:
            fOK = getBatteryDate(false);
            break;
-        case 5:
-           Serial.print(F("Read Batt.Temp..."));
+        case 7:
            fOK = getBatteryTemperature(false);
            break;
-      }
-      if (fOK) {
-        Serial.print(MSG_OK);
-      } else {
-        Serial.print(MSG_FAIL);
+        case 8:
+           fOK = getHVcontactorState(false);
+           break;
+      }
+      if (testStep < 9) {
+        if (fOK) {
+          Serial.print(MSG_DOT);
+        } else {
+          Serial.print(MSG_FAIL);Serial.print(F("#")); Serial.println(testStep);
+        }
       }
       testStep++;
-      if (testStep % 2 == 0) Serial.println();
-   } while (fOK && testStep < 6);
+   } while (fOK && testStep < 9);

    if (fOK) {
+      Serial.println(MSG_OK);
       digitalWrite(CS, HIGH);
       Serial.println(SPACER);
-      Serial.print(F("Battery-Production (Y/M/D): ")); Serial.print(2000 + BattDiag.Year); Serial.print(F("/"));
-      Serial.print(BattDiag.Month); Serial.print(F("/")); Serial.println(BattDiag.Day);
+      Serial.print(F("Time [hh:mm]: "));
+      if (BattDiag.hour < 9) Serial.print(F("0"));
+      Serial.print(BattDiag.hour); Serial.print(F(":"));
+      if (BattDiag.minutes < 9) Serial.print(F("0"));
+      Serial.print(BattDiag.minutes);
+      Serial.print(F(",   ODO : ")); Serial.print(BattDiag.ODO); Serial.println(F(" km"));
       Serial.println(SPACER);
-      Serial.print(F("SOC : ")); Serial.print(BattDiag.SOC,1);
-      Serial.print(F(" %, HV: ")); Serial.print(BattDiag.HV,1); Serial.print(F(" V"));
-      Serial.print(F(", LV: ")); Serial.print(BattDiag.LV,1); Serial.println(F(" V"));
-      Serial.print(F("ODO : ")); Serial.print(BattDiag.ODO); Serial.println(F(" km"));
+      Serial.print(F("Battery-Production [Y/M/D]: ")); Serial.print(2000 + BattDiag.Year); Serial.print(F("/"));
+      Serial.print(BattDiag.Month); Serial.print(F("/")); Serial.println(BattDiag.Day);
+      Serial.print(F("Initial Capacity : ")); Serial.print(BattDiag.CapInit / 360.0,1); Serial.print(F(" Ah"));
+      Serial.print(F(", Loss: ")); Serial.print((float) BattDiag.CapLoss / 1000, 3); Serial.println(F(" %"));
+      Serial.println(SPACER);
+      Serial.print(F("SOC : ")); Serial.print(BattDiag.SOC,1); Serial.print(F(" %"));
+      Serial.print(F(", realSOC: ")); Serial.print((float) BattDiag.realSOC / 10.0, 1); Serial.println(F(" %"));
+      Serial.print(F("HV  : ")); Serial.print(BattDiag.HV,1); Serial.print(F(" V, "));
+      Serial.print((float) BattDiag.Amps/32.0, 2); Serial.print(F(" A, "));
+      Serial.print(((float) (BattDiag.Power / 8192.0) -1) * 300, 2); Serial.println(F(" kW"));
+      Serial.print(F("LV  : ")); Serial.print(BattDiag.LV,1); Serial.println(F(" V"));
+
       Serial.println(SPACER);
       Serial.print(F("CV mean : ")); Serial.print(BattDiag.ADCCvolts_mean); Serial.print(F(" mV"));
       Serial.print(F(", dV = ")); Serial.print(BattDiag.ADCCvolts_max - BattDiag.ADCCvolts_min); Serial.println(F(" mV"));


Partial Merge with ptressel's branch

Partial Merge with ptressel's branch

--- Elcano_C2_LowLevel/Elcano_C2_LowLevel.ino
+++ Elcano_C2_LowLevel/Elcano_C2_LowLevel.ino
@@ -56,7 +56,7 @@
 volatile unsigned long RC_elapsed[7];
 volatile boolean synced = false;
 volatile unsigned long last_fallingedge_time = 4294967295; // max long
-volatile int RC_Done[7] = {0,0,0,0,0,0,0};
+volatile bool RC_Done[7] = {0,0,0,0,0,0,0};

 long speed_errors[ERROR_HISTORY];
 long old_turn_degx1000;
@@ -146,6 +146,22 @@
   ProcessFallOfINT(RC_RVS);
   RC_Done[RC_RVS] = 1;
   attachInterrupt(IRPT_RVS, ISR_RVS_rise, RISING);
+  interrupts();
+}
+
+void ISR_SWITCH_rise() {
+  noInterrupts();
+  ProcessRiseOfINT(RC_RDR);
+  attachInterrupt(digitalPinToInterrupt(IRPT_SWITCH), ISR_SWITCH_fall, FALLING);
+  //RC_Done[RC_RDR] = 1;
+  interrupts();
+}
+
+void ISR_SWITCH_fall() {
+  noInterrupts();
+  ProcessFallOfINT(RC_RDR);
+  RC_Done[RC_RDR] = 1;
+  attachInterrupt(digitalPinToInterrupt(IRPT_SWITCH), ISR_SWITCH_rise, RISING);
   interrupts();
 }
 /*---------------------------------------------------------------------------------------*/
@@ -179,8 +195,9 @@
 //----------------------------------------------------------------------------
 void setup()
 { //Set up pins
+      STEER_SERVO.attach(STEER_OUT_PIN);
       pinMode(BRAKE_OUT_PIN, OUTPUT);
-      pinMode(STEER_OUT_PIN, OUTPUT);
+
       // SPI: set the slaveSelectPin as an output:
       pinMode (SelectAB, OUTPUT);
       pinMode (SelectCD, OUTPUT);


Display the Dive Screen

Display the Dive Screen

--- DiveIno.ino
+++ DiveIno.ino
@@ -558,6 +558,12 @@
 			}
 			break;
 		}
+	} else if (currentScreen == DIVE_SCREEN) {
+		currentMode = SURFACE_MODE;
+		displayScreen(MENU_SCREEN);
+	} else if (currentScreen == LOGBOOK_SCREEN) {
+		currentMode = SURFACE_MODE;
+		displayScreen(MENU_SCREEN);
 	} else if (currentScreen == SURFACE_TIME_SCREEN) {
 		currentMode = SURFACE_MODE;
 		displayScreen(MENU_SCREEN);
@@ -769,6 +775,12 @@
 			selectedMenuItemIndex = 1;
 			menuSelect(selectedMenuItemIndex);
 			break;
+		case DIVE_SCREEN:
+			displayDiveScreen();
+			break;
+		case LOGBOOK_SCREEN:
+			displayLogbookScreen();
+			break;
 		case SURFACE_TIME_SCREEN:
 			displaySurfaceTimeScreen();
 			break;
@@ -808,6 +820,28 @@

 	//Reset the maximum depth
 	maxDepthInMeter = 0;
+}
+
+void displayDiveScreen()
+{
+	tft.clrScr();
+
+	tft.setColor(VGA_SILVER);
+	tft.setBackColor(VGA_BLACK);
+	tft.drawRect(0, 0, tft.getDisplayXSize()-1, tft.getDisplayYSize()-1);
+
+	tft.drawLine(0, 190, tft.getDisplayXSize()-1, 190);
+	tft.drawLine(220, 0, 220, 190);
+}
+
+void displayLogbookScreen()
+{
+	tft.clrScr();
+	tft.setBackColor(VGA_BLACK);
+	tft.setFont(Grotesk16x32);
+
+	tft.setColor(VGA_MAROON);
+	tft.print("Logbook", CENTER, 100);
 }

 void displaySurfaceTimeScreen()
@@ -1006,7 +1040,7 @@

 void drawDepth(float depth)
 {
-	if (currentScreen == GAUGE_SCREEN) {
+	if (currentScreen == DIVE_SCREEN || currentScreen == GAUGE_SCREEN) {
 		tft.setFont(SevenSeg_XXXL);
 		tft.setColor(VGA_YELLOW);

@@ -1028,7 +1062,7 @@

 void drawMaximumDepth(float maximumDepth)
 {
-	if (currentScreen == GAUGE_SCREEN) {
+	if (currentScreen == DIVE_SCREEN || currentScreen == GAUGE_SCREEN) {
 		tft.setFont(SevenSegNumFontPlusPlus);
 		tft.setColor(VGA_PURPLE);

@@ -1045,7 +1079,7 @@

 void drawCurrentTemperature(float currentTemperature)
 {
-	if (currentScreen == GAUGE_SCREEN) {
+	if (currentScreen == DIVE_SCREEN || currentScreen == GAUGE_SCREEN) {
 		tft.setFont(SevenSegNumFontPlusPlus);
 		tft.setColor(VGA_LIME);

@@ -1062,7 +1096,7 @@

 void drawCurrentPressure(int currentPressure)
 {
-	if (currentScreen == GAUGE_SCREEN) {
+	if (currentScreen == DIVE_SCREEN || currentScreen == GAUGE_SCREEN) {
 		tft.setFont(SevenSegNumFontPlusPlus);
 		tft.setColor(VGA_AQUA);

@@ -1079,7 +1113,7 @@

 void drawDiveDuration(int duration) // The dive duration is always in seconds
 {
-	if (currentScreen == GAUGE_SCREEN) {
+	if (currentScreen == DIVE_SCREEN || currentScreen == GAUGE_SCREEN) {
 		tft.setFont(SevenSegNumFontPlusPlus);
 		tft.setColor(VGA_WHITE);


add function prototypes (now req'd for esp8266)

--- esp8266/trigger/trigger.ino
+++ esp8266/trigger/trigger.ino
@@ -16,6 +16,10 @@
 #include <ESP8266WiFi.h>
 #include <EEPROM.h>
 #include "Adafruit_IO_Client.h"
+
+// function prototypes
+void battery_level();
+void door_open();

 // door gpio pin
 #define DOOR 13


Support for shell wget ftp and fdir

Support for shell wget ftp and fdir

git-svn-id: d8bfcd070c2c81762cca1b3912331324182919ba@17093 0d6f1817-ed0e-0410-87c9-987e46238f29

--- zimodem/zbrowser.ino
+++ zimodem/zbrowser.ino
@@ -874,7 +874,7 @@
         char *tmp=0;
         if((p1.length()<11)
         || ((strcmp(p1.substring(0,6).c_str(),"ftp://") != 0)
-           && (strcmp(p1.substring(0,8).c_str(),"ftps://") != 0)))
+           && (strcmp(p1.substring(0,7).c_str(),"ftps://") != 0)))
           serial.printf("Not a url: %s%s",p1.c_str(),EOLNC);
         /*
         else
@@ -911,7 +911,7 @@
         char *tmp=0;
         if((p1.length()<11)
         || ((strcmp(p1.substring(0,6).c_str(),"ftp://") != 0)
-           && (strcmp(p1.substring(0,8).c_str(),"ftps://") != 0)))
+           && (strcmp(p1.substring(0,7).c_str(),"ftps://") != 0)))
           serial.printf("Not a url: %s%s",p1.c_str(),EOLNC);
         /*
         else


got all of the pH code - apart from the hard bits to actually do it

--- ardesp/waterelf/waterelf.ino
+++ ardesp/waterelf/waterelf.ino
@@ -74,6 +74,7 @@
   float airCelsius;
   float airHumid;
   uint16_t lux;
+  float pH;
 };
 monitor_t monitorData[MONITOR_POINTS];
 int monitorCursor = 0;
@@ -120,7 +121,7 @@
 // setup ////////////////////////////////////////////////////////////////////
 void setup() {
   Serial.begin(115200);
-
+  Serial.println("\nAnd we're off...");
   // huzzah LED
   pinMode(BUILTIN_LED, OUTPUT);
   blink(3);
@@ -433,8 +434,10 @@
   // now we trigger the 433 transmitter
   if(newState == true){
     mySwitch.switchOn(4, 2);
+    Serial.println("Actuator on");
   } else {
     mySwitch.switchOff(4, 2);
+    Serial.println("Actuator off");
   }

   toSend += "
Actuator triggered
\n";
@@ -448,7 +451,6 @@
 /////////////////////////////////////////////////////////////////////////////
 // sensor/actuator stuff ////////////////////////////////////////////////////
 void startPeripherals() {
-  Serial.println("StartPeripherals");
   mySwitch.enableTransmit(13);   // RC Transmitter is connected to Pin #13

   tempSensor.begin();     // Start the onewire temperature sensor
@@ -489,7 +491,7 @@
     //tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)
   }

-  Wire.begin();
+  //Wire.begin();
   Wire.beginTransmission(0x4D);
   error = Wire.endTransmission();
   if(error==0){
@@ -515,6 +517,9 @@
   if(GOT_LIGHT_SENSOR)
     getLight(&now->lux);

+  if(GOT_PH_SENSOR)
+    getPH(&now->pH);
+
   if(SEND_DATA) postSensorData(&monitorData[monitorCursor]);

   if(++monitorCursor == MONITOR_POINTS)
@@ -573,6 +578,11 @@
     buf->concat(", \"lux\": ");
     buf->concat(m->lux);
   }
+  if(GOT_PH_SENSOR){
+  buf->concat(", ");
+  buf->concat(", \"pH\": ");
+  buf->concat(m->pH);
+  }
   buf->concat(" }");
 }
 void printMonitorEntry(monitor_t m, String* buf) {
@@ -597,6 +607,11 @@
     buf->concat(m.lux);
     buf->concat(" lux");
   }
+  if(GOT_PH_SENSOR){
+    buf->concat(", pH: ");
+    buf->concat(m.pH);
+    buf->concat(" pH");
+  }
 }
 void getTemperature(float* waterCelsius) {
   tempSensor.requestTemperatures(); // send command to get temperatures
@@ -607,29 +622,30 @@
   return;
 }
 void getHumidity(float* airCelsius, float* airHumid) {
-  float _airCelsius = *airCelsius;
-  float _airHumid = *airHumid;
-  _airCelsius = dht.readTemperature();
-  _airHumid = dht.readHumidity();
+  (*airCelsius) = dht.readTemperature();
+  (*airHumid) = dht.readHumidity();
   Serial.print("Air Temp: ");
-  Serial.print(_airCelsius);
+  Serial.print(*airCelsius);
   Serial.print(" C, ");
   Serial.print("Humidity: ");
-  Serial.print(_airHumid);
+  Serial.print(*airHumid);
   Serial.println(" %RH, ");
-  *airCelsius = _airCelsius;
-  *airHumid = _airHumid;
   return;
 }
 void getLight(uint16_t* lux) {
-  uint16_t _lux = *lux;
   sensors_event_t event;
   tsl.getEvent(&event);
-  _lux = event.light;
+  (*lux) = event.light;
   Serial.print("Light: ");
-  Serial.print(_lux);
+  Serial.print(*lux);
   Serial.println(" Lux");
-  *lux = _lux;
+  return;
+}
+void getPH(float* pH) {
+  (*pH) = 6.9;
+  Serial.print("pH: ");
+  Serial.print(*pH);
+  Serial.println(" pH");
   return;
 }


tinkering

tinkering

--- ardesp/waterelf/waterelf.ino
+++ ardesp/waterelf/waterelf.ino
@@ -5,36 +5,62 @@
 #include <ESP8266WebServer.h>
 #include <DNSServer.h>

-const char* ssid = "WaterWifi";
-const char* html = "<title>Success</title>"
-                    "

	ON	"
-                    "OFF

	"
-                    "ON	OFF
"
-                    "

ALL ON	"
-                    "
ALL OFF
";
+const char* ssid = "WaterElf";
+const char* html =
+  "<title>WaterElf</title>"
+  "

	ON	"
+  "OFF

	"
+  "ON	OFF
"
+  "

ALL ON	"
+  "
ALL OFF
";
+
+const char* apChoice =
+  "
Choose a wifi access point to join

<form method="POST" action="chz">a "
+  "_ITEMS_
Pass key: <input type="textarea" name="key">

a "
+  "<input type="submit" value="Submit"></form>
]=]"
+
 const byte DNS_PORT = 53;
 IPAddress apIP(192, 168, 1, 1);
 IPAddress netMsk(255, 255, 255, 0);
 DNSServer dnsServer;
 ESP8266WebServer server(80);

+String genAPForm() {
+  return new String("");
+/*
+  if not aptbl then return "No AP data :-(" end
+  buf = ""; checked = " checked"
+  for ssid, _ in pairs(aptbl) do
+    buf = buf .. '<input type="radio" name="ssid" value="' .. ssid .. '"' ..
+      checked .. '>' .. ssid .. '
\n'
+    checked = ""
+  end
+  return string.gsub(wifiform, "_ITEMS_", buf)
+*/
+}
+
 void setup() {
   Serial.begin(115200);
   Serial.setDebugOutput(true);
+
   WiFi.mode(WIFI_AP);
   WiFi.softAPConfig(apIP, apIP, netMsk);
   WiFi.softAP(ssid);
+
   Serial.print("SSID: ");
   Serial.println(ssid);
   Serial.print("IP address: ");
   Serial.println(WiFi.softAPIP());
+
   dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
   dnsServer.start(DNS_PORT, "*", apIP);
-  Serial.println("USP Server started");
+
+  Serial.println("DNS Server started");
+
   server.on("/", handle_root);
   server.on("/generate_204", handle_root); // Android support
   server.on("/L0", handle_L0);
@@ -42,6 +68,7 @@
   server.on("/ALL", handle_ALL);
   server.onNotFound(handleNotFound);
   server.begin();
+
   Serial.println("HTTP server started");
 }


Properly log send errors

Properly log send errors

--- sketches/M2_CAN_in_the_middle/M2_CAN_in_the_middle.ino
+++ sketches/M2_CAN_in_the_middle/M2_CAN_in_the_middle.ino
@@ -79,7 +79,7 @@
         frame = can_tx_frames0.dequeue();
         if(!Can0.sendFrame(frame))
         {
-            Serial.write("Error Sending on CAN0");
+            log("Error Sending on CAN0", 21);
         }
     }
     if(!can_tx_frames1.isEmpty())
@@ -87,7 +87,7 @@
         frame = can_tx_frames1.dequeue();
         if(!Can1.sendFrame(frame))
         {
-            Serial.write("Error Sending on CAN1");
+            log("Error Sending on CAN1", 21);
         }
     }


Added threshold range for tempInsideC

Added threshold range for tempInsideC

--- freezer_monitor_v0_5/freezer_monitor_v0_5.ino
+++ freezer_monitor_v0_5/freezer_monitor_v0_5.ino
@@ -44,6 +44,8 @@
 struct SensorThresholds {
   unsigned int light;
   unsigned int door;
+  float minTempInsideC;
+  float maxTempInsideC;
 };

 // Controller MAC address - must be unique on network for DHCP to work
@@ -137,6 +139,12 @@
   if (sensorData.hall == sensorThresholds.door) {
     status = HIGH;
   }
+  if (sensorData.tempInsideC < sensorThresholds.minTempInsideC) {
+    status = HIGH;
+  }
+  if (sensorData.tempInsideC > sensorThresholds.maxTempInsideC) {
+    status = HIGH;
+  }
   return status;
 }

@@ -144,6 +152,8 @@
 void default_sensor_thresholds() {
   sensorThresholds.light = 50;
   sensorThresholds.door = HIGH;
+  sensorThresholds.minTempInsideC = 19.00;
+  sensorThresholds.maxTempInsideC = 20.00;
 }

 //------------------------------------------------------------------------------
@@ -179,12 +189,16 @@

 //------------------------------------------------------------------------------
 void handle_thresholds(RestRequest *request, EthernetClient *client) {
-  char content[32] = { '\0' };
-  char buffer[16] = { '\0' };
+  char content[128] = { '\0' };
+  char buffer[128] = { '\0' };
   strcat(content, "{");
   sprintf_int_field(buffer, true, "light", sensorThresholds.light);
   strcat(content, buffer);
   sprintf_int_field(buffer, false, "door", sensorThresholds.door);
+  strcat(content, buffer);
+  sprintf_float_field(buffer, false, "minTempInsideC", sensorThresholds.minTempInsideC, 100);
+  strcat(content, buffer);
+  sprintf_float_field(buffer, false, "maxTempInsideC", sensorThresholds.maxTempInsideC, 100);
   strcat(content, buffer);
   strcat(content, "}");
   restServer.generate_response(client, content);


view uploaded scripts

view uploaded scripts

--- esp8266_badUSB/esp8266_badUSB.ino
+++ esp8266_badUSB/esp8266_badUSB.ino
@@ -13,14 +13,13 @@
 extern char* data_getError404();
 extern char* data_getIndexHTML();
 extern char* data_getUploadHTML();
-//extern static char data_websiteBuffer[3000];

-void getScript(){
+void viewScript(){
   int i = 0;
   for(int a=0;a<sizeof(data_websiteBuffer);a++) data_websiteBuffer[a] = 0;
   if(server.hasArg("n")){
-    File f = SPIFFS.open(server.arg("n"), "r");
-    while(f.available()){
+    File f = SPIFFS.open("/"+server.arg("n"), "r");
+    while(f.available() && i<sizeof(data_websiteBuffer)){
       data_websiteBuffer[i] = f.read();
       i++;
     }
@@ -83,7 +82,7 @@
   server.on("/style.css",[](){ server.send(200, "text/css", data_getStyleCSS()); });
   server.on("/functions.js",[](){ server.send(200, "text/javascript", data_getFunctionsJS()); });
   server.on("/list.json", getScriptList);
-  server.on("/view", getScript);
+  server.on("/view", viewScript);
   server.on("/",[](){ server.send(200, "text/html", data_getIndexHTML()); });

   //handle upload