Delete C_xxMULT-Industruino.ino

Delete C_xxMULT-Industruino.ino

--- BMS_Francais/Examples/C_xxMULT-Industruino/C_xxMULT-Industruino.ino
+++ BMS_Francais/Examples/C_xxMULT-Industruino/C_xxMULT-Industruino.ino
@@ -1,363 +0,0 @@
-/* ------------------------------------------------------------------------------------------------------------------------------------------*
- * SE2R : T_COMULT - Fonction de multiplexage d'un tableau de 16 booléens dans un entier non signé               (Compatible IFS) 19/10/2016 *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- *        T_COMULT(int MPX[], int RNG, Boolean FLG[], int CFG)                                                                    19/10/2016 *
- *                MPX : [00] : Entier, Variable porteuse des booléens multiplexés, forcément un tableau de taille au moins 1                 *
- *                RNG : Entier, rang de la variable porteuse dans le tableau des variables porteuses                                         *
- *                FLG : [00] Booléen de rang 0 dans le tableau de taille 16                                                                  *
- *                      [..] Suite du tableau de booléens à multiplexer                                                                      *
- *                      [15] Dernier booléen du tableau à multiplexer                                                                        *
- *                CFG : Commande de forçage                                                                                *
- *                      <0  : la sortie MPX[RNG] reste nulle quelle que soit la valeur des FLG[...]                                          *
- *                      0   : la sortie MPX[RNG] reste figée à sa valeur courante                                                            *
- *                      1   : la sortie MPX[RNG] suit les valeurs de FLG[...] encodés suivant les puissances de 2                            *
- *                      2   : la sortie MPX[RNG] prend pour valeur 65535                                                                     *
- *                      3   : la sortie MPX[RNG] prend pour valeur 65535                                                                     *
- *                      >3  : la sortie MPX[RNG] reste nulle quelle que soit la valeur des FLG[...]                                          *
- *       Interne  NUM : [00] Calcul intermédiaire d'addition des puissances de 2                                                             *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- * Copyright SE2R under the APACHE Licence                                                                                *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- * 19/10/2016 : DD, SE2R : Testée et validée sur banc 32U8, 1286, Arduino Leonardo                                                           *
- * ------------------------------------------------------------------------------------------------------------------------------------------*/
-
- /* ------------------------------------------------------------------------------------------------------------------------------------------*
- * SE2R : T_DEMULT - Fonction de démultiplexage d'un entier non signé dans un tableau de booléens                (Compatible IFS) 19/10/2016 *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- *        T_DEMULT(int MPX[], int RNG, Boolean FLG[], int CFG)                                                                    19/10/2016 *
- *                MPX : [00] : Entier, Variable porteuse des booléens multiplexés, forcément un tableau de taille au moins 1                 *
- *                RNG : Entier, rang de la variable porteuse dans le tableau des variables porteuses                                         *
- *                FLG : [00] : Booléen de rang 0 dans le tableau                                                                             *
- *                      [..] : Suite du tableau de booléens à multiplexer                                                                    *
- *                      [15] : Dernier booléen du tableau à multiplexer                                                                      *
- *                CFG : Commande de forçage                                                                                *
- *                      <0  : les booléens FLG[xx] restent false quelle que soit la valeur de MPX[RNG]                                       *
- *                      0   : les booléens FLG[xx] restent figés à leur valeur courante                                                      *
- *                      1   : les booléens FLG[xx] suivent les valeurs de MPX[RNG] décodé suivant les puissances de 2                        *
- *                      2   : les booléens FLG[xx] restent true quelle que soit la valeur de MPX[RNG]                                        *
- *                      3   : les booléens FLG[xx] restent true quelle que soit la valeur de MPX[RNG]                                        *
- *                      >3  : les booléens FLG[xx] restent false quelle que soit la valeur de MPX[RNG]                                       *
- *       Interne  NUM : [00] Calcul intermédiaire de décodage des puissances de 2                                                            *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- * Copyright SE2R under the APACHE Licence                                                                                *
- * ------------------------------------------------------------------------------------------------------------------------------------------*
- * 19/10/2016 : DD, SE2R : Testée et validée sur banc                                                                                *
- * ------------------------------------------------------------------------------------------------------------------------------------------*/
-
-// Déclaration des bibliothèques nécessaires à l'exécution du programme ---------------------------------------------------------------------*
-#include <Wire.h>			// Biblio   - Gestion des ports de communication
-#include <Indio.h>			// Biblio   - Industruino
-#include <DIS.h>                        // Biblio   - SE2R - Fonctions de dialogue et d'affichage sur l'écran UC1701 Industruino
-static DIS DIS;                         // Biblio   - Activation du constructeur de la bibliothèque de fonctions d'affichage
-static UC1701 lcd;
-#include <BMS.h>                        // Biblio   - SE2R - Fonctions de contrôle et régulation
-static BMS BMS;                         // Biblio   - Activation du constructeur de la bibliothèque de fonctions d'affichage
-
-// Déclaration des variables nécessaires à l'exécution de la fonction -----------------------------------------------------------------------*
-boolean FTM_BOOL[16];			// EEPROM  -  Table commune de codage / décodage des booléens savegardés en EEPROM
-boolean FCX_INPT[16];			// Général  - [00] Valeur digitale d'entrée  0
-					//	      [01] Valeur digitale d'entrée  1
-					//	      [02] Valeur digitale d'entrée  2
-					//	      [03] Valeur digitale d'entrée  3
-					//	      [04] Valeur digitale d'entrée  4
-					//	      [05] Valeur digitale d'entrée  5
-					//	      [06] Valeur digitale d'entrée  6
-					//	      [07] Valeur digitale d'entrée  7
-					//	      [08] Valeur digitale d'entrée  8
-					//	      [09] Valeur digitale d'entrée  9
-					//	      [10] Valeur digitale d'entrée 10
-					//	      [11] Valeur digitale d'entrée 11
-					//	      [12] Valeur digitale d'entrée 12
-					//	      [13] Valeur digitale d'entrée 13
-					//	      [14] Valeur digitale d'entrée 14
-					//	      [15] Valeur digitale d'entrée 15
-boolean FCX_OUTP[16];			// Général  - [00] Valeur digitale de sortie  0
-					//	      [01] Valeur digitale de sortie  1
-					//	      [02] Valeur digitale de sortie  2
-					//	      [03] Valeur digitale de sortie  3
-					//	      [04] Valeur digitale de sortie  4
-					//	      [05] Valeur digitale de sortie  5
-					//	      [06] Valeur digitale de sortie  6
-					//	      [07] Valeur digitale de sortie  7
-					//	      [08] Valeur digitale de sortie  8
-					//	      [09] Valeur digitale de sortie  9
-					//	      [10] Valeur digitale de sortie 10
-					//	      [11] Valeur digitale de sortie 11
-					//	      [12] Valeur digitale de sortie 12
-					//	      [13] Valeur digitale de sortie 13
-					//	      [14] Valeur digitale de sortie 14
-					//	      [15] Valeur digitale de sortie 15
-unsigned int VTM_BOOL[4];		// EEPROM   - Table de sauvegarde des booléens (par série de 16)
-unsigned int VCM_MUIN[1];		// EEPROM   - [00] Valeur de lecture de variables de type insigned int en EEPROM
-int VCO_XXXX[1];                        // C_DISCOR - [00] Commande de forçage par l'extérieur
-
-// Déclaration des variables nécessaires au fonctionnement de l'écran -----------------------------------------------------------------------*
-boolean FCO_PRUP[5];                    // EcranLCD - Information de touche "Up" appuyée
-boolean FCO_PREN[5];                    // EcranLCD - Information de touche "Enter" appuyée
-boolean FCO_PRDN[5];                    // EcranLCD - Information de touche "Down" appuyée
-int VNT_MENU[3];                        // EcranLCD - Table d'adressage des menus
-int VNC_MENU[25];                       // EcranLCD - Table des numéros de menus
-int VNC_PRUP[25];                       // EcranLCD - Table des numéros de menus de destination par la touche "Up"
-int VNC_PREN[25];                       // EcranLCD - Table des numéros de menus de destination par la touche "Enter"
-int VNC_PRDN[25];                       // EcranLCD - Table des numéros de menus de destination par la touche "Down"
-float VTT_SCRN[10];                     // EcranLCD - Table des temporisations
-int VNX_MN02[12];                       // EcranLCD - Table des menus de destimation et des index du menu 02 - Principal
-boolean FCM_IN00[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  0
-boolean FCM_IN01[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  1
-boolean FCM_IN02[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  2
-boolean FCM_IN03[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  3
-boolean FCM_IN04[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  4
-boolean FCM_IN05[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  5
-boolean FCM_IN06[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  6
-boolean FCM_IN07[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  7
-boolean FCM_IN08[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  8
-boolean FCM_IN09[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée  9
-boolean FCM_IN10[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée 10
-boolean FCM_IN11[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée 11
-boolean FCM_IN12[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée 12
-boolean FCM_IN13[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée 13
-boolean FCM_IN14[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée 14
-boolean FCM_IN15[1];                    // G_MODV1B - Mémoire de la commande du bit d'entrée 15
-
-void setup() {                          // Initialisation -----------------------------------------------------------------------------------*
-
-EEPROM.get(18, VTM_BOOL[0]);
-BMS.T_DEMULT(VTM_BOOL, 0, FTM_BOOL, 1);
-FCX_INPT[0] = FTM_BOOL[0];
-FCX_INPT[1] = FTM_BOOL[1];
-FCX_INPT[2] = FTM_BOOL[2];
-FCX_INPT[3] = FTM_BOOL[3];
-FCX_INPT[4] = FTM_BOOL[4];
-FCX_INPT[5] = FTM_BOOL[5];
-FCX_INPT[6] = FTM_BOOL[6];
-FCX_INPT[7] = FTM_BOOL[7];
-FCX_INPT[8] = FTM_BOOL[8];
-FCX_INPT[9] = FTM_BOOL[9];
-FCX_INPT[10] = FTM_BOOL[10];
-FCX_INPT[11] = FTM_BOOL[11];
-FCX_INPT[12] = FTM_BOOL[12];
-FCX_INPT[13] = FTM_BOOL[13];
-FCX_INPT[14] = FTM_BOOL[14];
-FCX_INPT[15] = FTM_BOOL[15];
-
-VTT_SCRN[1] = 180;                      // G_TOUCHx - Temporisation d'inactivité sur le rétroéclairage
-VTT_SCRN[2] = 240;                      // G_TOUCHx - Temporisation d'inactivité de retour à l'écran principal
-VTT_SCRN[3] = 20;                       // G_TOUCHx - Temporisation d'antirebond de la touche "Enter"
-VTT_SCRN[4] = 15;                       // G_TOUCHx - Temporisation d'antiredond des touches "Up" et "Down"
-VNT_MENU[0] = 22;                       // G_NAVIGM - Taille des tables d'index et de destinations
-VNT_MENU[1] = 1;                        // G_NAVIGM - Initialisation du pointeur de destinations
-
-//                                      // G_NAVIGM - Tables d'adressage de l'écran LCD
-VNC_MENU[0] = 1;
-VNC_MENU[1] = 1;
-VNC_MENU[2] = 2;
-VNC_MENU[3] = 11;
-VNC_MENU[4] = 12;
-VNC_MENU[5] = 13;
-VNC_MENU[6] = 14;
-VNC_MENU[7] = 15;
-VNC_MENU[8] = 16;
-VNC_MENU[9] = 17;
-VNC_MENU[10] = 18;
-VNC_MENU[11] = 19;
-VNC_MENU[12] = 20;
-VNC_MENU[13] = 21;
-VNC_MENU[14] = 22;
-VNC_MENU[15] = 23;
-VNC_MENU[16] = 24;
-VNC_MENU[17] = 25;
-VNC_MENU[18] = 26;
-VNC_MENU[19] = 27;
-VNC_MENU[20] = 28;
-VNC_MENU[21] = 29;
-VNC_MENU[22] = 30;
-VNC_PRUP[1] =   1; VNC_PREN[1] =    2; VNC_PRDN[1] =   2;
-VNC_PRUP[2] =   2; VNC_PREN[2] =    2; VNC_PRDN[2] =   2;
-VNC_PRUP[3] =   11; VNC_PREN[3] =  12; VNC_PRDN[3] =  11;
-VNC_PRUP[4] =   12; VNC_PREN[4] =  13; VNC_PRDN[4] =  12;
-VNC_PRUP[5] =   13; VNC_PREN[5] =  14; VNC_PRDN[5] =  13;
-VNC_PRUP[6] =   14; VNC_PREN[6] =  15; VNC_PRDN[6] =  14;
-VNC_PRUP[7] =   15; VNC_PREN[7] =  16; VNC_PRDN[7] =  15;
-VNC_PRUP[8] =   16; VNC_PREN[8] =  17; VNC_PRDN[8] =  16;
-VNC_PRUP[9] =   17; VNC_PREN[9] =  18; VNC_PRDN[9] =  17;
-VNC_PRUP[10] =  18; VNC_PREN[10] =  2; VNC_PRDN[10] = 18;
-VNC_PRUP[11] =   2; VNC_PREN[11] =  2; VNC_PRDN[11] =  2;
-VNC_PRUP[12] =   2; VNC_PREN[12] =  2; VNC_PRDN[12] =  2;
-VNC_PRUP[13] =  21; VNC_PREN[13] = 22; VNC_PRDN[13] = 21;
-VNC_PRUP[14] =  22; VNC_PREN[14] = 23; VNC_PRDN[14] = 22;
-VNC_PRUP[15] =  23; VNC_PREN[15] = 24; VNC_PRDN[15] = 23;
-VNC_PRUP[16] =  24; VNC_PREN[16] = 25; VNC_PRDN[16] = 24;
-VNC_PRUP[17] =  25; VNC_PREN[17] = 26; VNC_PRDN[17] = 25;
-VNC_PRUP[18] =  26; VNC_PREN[18] = 27; VNC_PRDN[18] = 26;
-VNC_PRUP[19] =  27; VNC_PREN[19] = 28; VNC_PRDN[19] = 27;
-VNC_PRUP[20] =  28; VNC_PREN[20] =  2; VNC_PRDN[20] = 28;
-VNC_PRUP[21] =   2; VNC_PREN[21] =  2; VNC_PRDN[21] =  2;
-VNC_PRUP[22] =   2; VNC_PREN[22] =  2; VNC_PRDN[22] =  2;
-
-VNX_MN02[10] = 1;			// G_CHOIX8 - Menu 02 - Initialisation index
-
-//                                      // EcranLCD - Paramétrage spécifique Industruino 1286
-pinMode(23, INPUT);                     // EcranLCD - Spécifique 1286 - Touche flèche basse
-pinMode(24, INPUT);                     // EcranLCD - Spécifique 1286 - Touche entrée
-pinMode(25, INPUT);                     // EcranLCD - Spécifique 1286 - Touche flèche haute
-pinMode(26, OUTPUT);                    // EcranLCD - Spécifique 1286 - Sortie de commande du rétroéclairage
-
-/*                                      // EcranLCD - Paramétrage spécifique Industruino 32U8
-pinMode(13, OUTPUT);                    // EcranLCD - Spécifique 32U8 - Sortie de commande du rétroéclairage
-*/
-lcd.begin();                            // EcranLCD - Initialisation de l'écran LCD
-lcd.clear();                            // EcranLCD - Effacement de l'écran LCD
-}
-
-void loop() {                            // Exécution ---------------------------------------------------------------------------------------*
-FTM_BOOL[0] = FCX_INPT[0];
-FTM_BOOL[1] = FCX_INPT[1];
-FTM_BOOL[2] = FCX_INPT[2];
-FTM_BOOL[3] = FCX_INPT[3];
-FTM_BOOL[4] = FCX_INPT[4];
-FTM_BOOL[5] = FCX_INPT[5];
-FTM_BOOL[6] = FCX_INPT[6];
-FTM_BOOL[7] = FCX_INPT[7];
-FTM_BOOL[8] = FCX_INPT[8];
-FTM_BOOL[9] = FCX_INPT[9];
-FTM_BOOL[10] = FCX_INPT[10];
-FTM_BOOL[11] = FCX_INPT[11];
-FTM_BOOL[12] = FCX_INPT[12];
-FTM_BOOL[13] = FCX_INPT[13];
-FTM_BOOL[14] = FCX_INPT[14];
-FTM_BOOL[15] = FCX_INPT[15];
-BMS.T_COMULT(VTM_BOOL, 0, FTM_BOOL, 1);
-
-EEPROM.get(18, VTM_BOOL[1]);
-if (VTM_BOOL[1] != VTM_BOOL[0]) { EEPROM.put(18, VTM_BOOL[0]); }
-EEPROM.get(18, VTM_BOOL[1]);
-
-BMS.T_DEMULT(VTM_BOOL, 1, FTM_BOOL, 1);
-FCX_OUTP[0] = FTM_BOOL[0];
-FCX_OUTP[1] = FTM_BOOL[1];
-FCX_OUTP[2] = FTM_BOOL[2];
-FCX_OUTP[3] = FTM_BOOL[3];
-FCX_OUTP[4] = FTM_BOOL[4];
-FCX_OUTP[5] = FTM_BOOL[5];
-FCX_OUTP[6] = FTM_BOOL[6];
-FCX_OUTP[7] = FTM_BOOL[7];
-FCX_OUTP[8] = FTM_BOOL[8];
-FCX_OUTP[9] = FTM_BOOL[9];
-FCX_OUTP[10] = FTM_BOOL[10];
-FCX_OUTP[11] = FTM_BOOL[11];
-FCX_OUTP[12] = FTM_BOOL[12];
-FCX_OUTP[13] = FTM_BOOL[13];
-FCX_OUTP[14] = FTM_BOOL[14];
-FCX_OUTP[15] = FTM_BOOL[15];
-
-//                                      // EcranLCD - Gestion des touches spécifique Industruino 1286
-DIS.G_TOUCH2(VNC_MENU, VTT_SCRN, FCO_PRUP, FCO_PREN, FCO_PRDN, VNT_MENU);
-/*                                      // EcranLCD - Gestion des touches spécifique Industruino 32U8
-DIS.G_TOUCH1(VNC_MENU, VTT_SCRN, FCO_PRUP, FCO_PREN, FCO_PRDN, VNT_MENU);
-*/
-
-if (VNT_MENU[2] != VNC_MENU[0]) { lcd.clear(); }
-VNT_MENU[2] = VNC_MENU[0];
-
-if (VNC_MENU[0] ==  1) { lcd.setCursor(0, 0); lcd.clearLine(); }
-DIS.G_MESS1L(VNC_MENU, 1, 1, 0, "   www.eControls.fr  ");
-DIS.G_MESS1L(VNC_MENU, 1, 2, 0, "    SE2R Softwares   ");
-DIS.G_MESS1L(VNC_MENU, 1, 3, 0, "  Industruino  1286  ");
-// DIS.G_MESS1L(VNC_MENU, 1, 3, 0, "  Industruino  32U8  ");
-DIS.G_MESS1L(VNC_MENU, 1, 4, 0, "Fonction BMS.T_COMULT");
-DIS.G_MESS1L(VNC_MENU, 1, 5, 0, "Fonction BMS.T_DEMULT");
-DIS.G_MESS1L(VNC_MENU, 1, 6, 0, "A# TESTS     C# 00001");
-DIS.G_MESS1L(VNC_MENU, 1, 7, 0, "V.1.02     19/10/2016");
-
-VNX_MN02[0] = 0;
-VNX_MN02[1] = 1;
-VNX_MN02[2] = 11;
-VNX_MN02[3] = 21;
-VNX_MN02[4] = 0;
-VNX_MN02[5] = 0;
-VNX_MN02[6] = 0;
-VNX_MN02[7] = 0;
-VNX_MN02[8] = 1;
-VNX_MN02[9] = 3;
-DIS.G_CHOIX8(VNC_MENU, 2, FCO_PRUP, FCO_PREN, FCO_PRDN, VNX_MN02, VNT_MENU);
-DIS.G_MESS1L(VNC_MENU, 2, 0, 0, "- Etats & commandes -");
-DIS.G_MESS1L(VNC_MENU, 2, 1, 6,  "Retour a l'accueil  ");
-DIS.G_MESS1L(VNC_MENU, 2, 2, 6,  "Bits d'entree 00-07 ");
-DIS.G_MESS1L(VNC_MENU, 2, 3, 6,  "Bits d'entree 08-15 ");
-DIS.G_MESS1L(VNC_MENU, 2, 4, 0, "In   ");
-DIS.G_MESS1L(VNC_MENU, 2, 5, 0, "Out  ");
-DIS.G_MESS1L(VNC_MENU, 2, 6, 0, "Porteuse             ");
-DIS.G_MESS1L(VNC_MENU, 2, 7, 0, "EEPROM               ");
-if (VNC_MENU[0] == 2) {
-  lcd.setCursor(122, 4); if (FCX_INPT[0] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor(116, 4); if (FCX_INPT[1] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor(110, 4); if (FCX_INPT[2] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor(104, 4); if (FCX_INPT[3] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 98, 4); if (FCX_INPT[4] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 92, 4); if (FCX_INPT[5] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 86, 4); if (FCX_INPT[6] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 80, 4); if (FCX_INPT[7] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 74, 4); if (FCX_INPT[8] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 68, 4); if (FCX_INPT[9] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 62, 4); if (FCX_INPT[10] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 56, 4); if (FCX_INPT[11] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 50, 4); if (FCX_INPT[12] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 44, 4); if (FCX_INPT[13] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 38, 4); if (FCX_INPT[14] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 32, 4); if (FCX_INPT[15] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor(122, 5); if (FCX_OUTP[0] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor(116, 5); if (FCX_OUTP[1] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor(110, 5); if (FCX_OUTP[2] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor(104, 5); if (FCX_OUTP[3] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 98, 5); if (FCX_OUTP[4] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 92, 5); if (FCX_OUTP[5] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 86, 5); if (FCX_OUTP[6] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 80, 5); if (FCX_OUTP[7] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 74, 5); if (FCX_OUTP[8] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 68, 5); if (FCX_OUTP[9] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 62, 5); if (FCX_OUTP[10] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 56, 5); if (FCX_OUTP[11] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 50, 5); if (FCX_OUTP[12] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 44, 5); if (FCX_OUTP[13] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 38, 5); if (FCX_OUTP[14] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 32, 5); if (FCX_OUTP[15] == true) { lcd.print("1"); } else {lcd.print("0"); }
-  lcd.setCursor( 80, 6); lcd.print(VTM_BOOL[0]);
-  lcd.setCursor( 80, 7); lcd.print(VTM_BOOL[1]);
-  FCM_IN00[0] = FCX_INPT[0];
-  FCM_IN01[0] = FCX_INPT[1];
-  FCM_IN02[0] = FCX_INPT[2];
-  FCM_IN03[0] = FCX_INPT[3];
-  FCM_IN04[0] = FCX_INPT[4];
-  FCM_IN05[0] = FCX_INPT[5];
-  FCM_IN06[0] = FCX_INPT[6];
-  FCM_IN07[0] = FCX_INPT[7];
-  FCM_IN08[0] = FCX_INPT[8];
-  FCM_IN09[0] = FCX_INPT[9];
-  FCM_IN10[0] = FCX_INPT[10];
-  FCM_IN11[0] = FCX_INPT[11];
-  FCM_IN12[0] = FCX_INPT[12];
-  FCM_IN13[0] = FCX_INPT[13];
-  FCM_IN14[0] = FCX_INPT[14];
-  FCM_IN15[0] = FCX_INPT[15];
-  }
-
-DIS.G_MODV1B(VNC_MENU, 11, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  0, FCM_IN00, "-  Bit d'entree 00  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 12, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  1, FCM_IN01, "-  Bit d'entree 01  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 13, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  2, FCM_IN02, "-  Bit d'entree 02  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 14, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  3, FCM_IN03, "-  Bit d'entree 03  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 15, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  4, FCM_IN04, "-  Bit d'entree 04  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 16, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  5, FCM_IN05, "-  Bit d'entree 05  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 17, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  6, FCM_IN06, "-  Bit d'entree 06  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 18, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  7, FCM_IN07, "-  Bit d'entree 07  -" , "- Changer de valeur -", " Off ", "  On ", true);
-
-DIS.G_MODV1B(VNC_MENU, 21, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  8, FCM_IN08, "-  Bit d'entree 08  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 22, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT,  9, FCM_IN09, "-  Bit d'entree 09  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 23, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT, 10, FCM_IN10, "-  Bit d'entree 10  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 24, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT, 11, FCM_IN11, "-  Bit d'entree 11  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 25, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT, 12, FCM_IN12, "-  Bit d'entree 12  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 26, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT, 13, FCM_IN13, "-  Bit d'entree 13  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 27, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT, 14, FCM_IN14, "-  Bit d'entree 14  -" , "- Changer de valeur -", " Off ", "  On ", true);
-DIS.G_MODV1B(VNC_MENU, 28, FCO_PRUP, FCO_PREN, FCO_PRDN, FCX_INPT, 15, FCM_IN15, "-  Bit d'entree 15  -" , "- Changer de valeur -", " Off ", "  On ", true);
-
-DIS.G_NAVIGM(VNC_MENU, VNT_MENU, FCO_PRUP, FCO_PREN, FCO_PRDN , VNC_PRUP, VNC_PREN, VNC_PRDN);
-}


Removes commented code and MQTT publishing

--- njmakerday_20160318/njmakerday_20160318.ino
+++ njmakerday_20160318/njmakerday_20160318.ino
@@ -89,28 +89,6 @@

   // Connect to Wifi
   void connectWiFi();
-
-//	WiFi.begin ( ssid, password );
-//	Serial.println ( "" );
-//
-//	// Wait for connection
-//	while ( WiFi.status() != WL_CONNECTED ) {
-//    digitalWrite ( ledWiFi, 0 );
-//		delay ( 1000 );
-//    Serial.print ( "Connecting...\n" );
-//
-//    Serial.print("Attempting to connect to SSID: ");
-//    Serial.println ( ssid );
-//
-//    Serial.print("Current WiFi Status: ");
-//    Serial.println ( WiFi.status() );
-//	}
-//
-//  Serial.println ( "" );
-//	Serial.print ( "Connected to " );
-//	Serial.println ( ssid );
-//	Serial.print ( "IP address: " );
-//	Serial.println ( WiFi.localIP() );

   // connect to adafruit io
   mqttConnect();
@@ -155,121 +133,10 @@
   Serial.println(humidity_data);

   // Publish data
-  mqttPublish();
-//  if (! temperature_c.publish(temperature_data))
-//    Serial.println(F("Failed to publish temperature"));
-//  else
-//    Serial.println(F("C Temperature published!"));
-//
-//  if (! temperature_f.publish(temperature_data * 9/5 + 32))
-//    Serial.println(F("Failed to publish temperature"));
-//  else
-//    Serial.println(F("F Temperature published!"));
-//
-//  if (! humidity.publish(humidity_data))
-//    Serial.println(F("Failed to publish humidity"));
-//  else
-//    Serial.println(F("Humidity published!"));
-//
+//  mqttPublish();
+
 //  delay(180000); // 3 minutes
   digitalWrite ( ledWiFi, 1 );
 //  delay(30000); // 30 seconds
 }

-//// connect to adafruit io via MQTT
-//void connect() {
-//
-//  Serial.print(F("Connecting to Adafruit IO... "));
-//
-//  int8_t ret;
-//
-//  while ((ret = mqtt.connect()) != 0) {
-//
-//    switch (ret) {
-//      case 1: Serial.println(F("Wrong protocol")); break;
-//      case 2: Serial.println(F("ID rejected")); break;
-//      case 3: Serial.println(F("Server unavail")); break;
-//      case 4: Serial.println(F("Bad user/pass")); break;
-//      case 5: Serial.println(F("Not authed")); break;
-//      case 6: Serial.println(F("Failed to subscribe")); break;
-//      default: Serial.println(F("Connection failed")); break;
-//    }
-//
-//    if(ret >= 0)
-//      mqtt.disconnect();
-//
-//    Serial.println(F("Retrying connection..."));
-//    delay(5000);
-//
-//  }
-//
-//  Serial.println(F("Adafruit IO Connected!"));
-//
-//}
-
-//void handleRoot() {
-// digitalWrite ( ledWiFi, 1 );
-//  char temp[600];
-//  int sec = millis() / 1000;
-//  int min = sec / 60;
-//  int hr = min / 60;
-//
-//  snprintf ( temp, 600,
-//
-//"\
-//  \
-//    <meta http-equiv='refresh' content='5'/>\
-//    <title>ESP8266 Demo</title>\
-//    \
-//  \
-//  \
-//
Hello from ESP8266!
\
-//
Uptime: %02d:%02d:%02d
\
-//  \
-//",
-//
-//    hr, min % 60, sec % 60
-//  );
-//  server.send ( 200, "text/html", temp );
-//  digitalWrite ( ledWiFi, 0 );
-//}
-
-//void handleNotFound() {
-//  digitalWrite ( ledWiFi, 1 );
-//  String message = "File Not Found\n\n";
-//  message += "URI: ";
-//  message += server.uri();
-//  message += "\nMethod: ";
-//  message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
-//  message += "\nArguments: ";
-//  message += server.args();
-//  message += "\n";
-//
-//  for ( uint8_t i = 0; i < server.args(); i++ ) {
-//    message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
-//  }
-//
-//  server.send ( 404, "text/plain", message );
-//  digitalWrite ( ledWiFi, 0 );
-//}
-
-//void handleTemperature() {
-//  String out = "";
-//  out += "[{\"currentTempC\":";
-//  out += hdc.readTemperature();
-//  out += "},{\"currentTempF\":";
-//  out += hdc.readTemperature() * 9/5 + 32;
-//  out += "}]";
-//  server.send ( 200, "application/json", out );
-//}
-
-//void handleHumidity() {
-//  String out = "";
-//  out += "[{\"currentHumidity\":";
-//  out += hdc.readHumidity();
-//  out += "}]";
-//  server.send ( 200, "application/json", out );
-//}
-


Put IR loop outside Re-enabled wifi

Put IR loop outside
Re-enabled wifi

--- arduinofences.ino
+++ arduinofences.ino
@@ -53,7 +53,8 @@
     pinMode(BUTTON_PIN, INPUT);
     pinMode(STATUS_PIN, OUTPUT);
     Serial.begin(9600);
-    //WiFi.init();
+
+    WiFi.init();
     Serial.println("Started webserver ...");
 }

@@ -168,8 +169,7 @@

 int lastButtonState;

-void loop()
-{
+void ir_loop() {
   // If button pressed, send the code.
   int buttonState = digitalRead(BUTTON_PIN);
   if (lastButtonState == HIGH && buttonState == LOW) {
@@ -192,3 +192,9 @@
   }
   lastButtonState = buttonState;
 }
+
+void loop()
+{
+  ir_loop();
+  WiFi.run();
+}


Code cleanup

Code cleanup

--- buttons_animations/buttons_animations.ino
+++ buttons_animations/buttons_animations.ino
@@ -1,6 +1,7 @@
 /*
 Blink-a-tron patterns for 6 LED arcade buttons
 (c) 2015 Ryan Bates, RetroBuiltGames.com
+edited by Benjamin Vitters (2017)
 */
 //LED pin connections for Teensy 2.0++
 //change these for your arduino compatible device
@@ -44,26 +45,34 @@
 }

 //pattern routine that loops forever; arrange, copy, remove these to make your 'light show'
+  //scrollup();
+  //scrolldown();
+  //lightup();
+  //lightdown();
+  //scrollpairup();
+  //scrollpairdown();
+  //loopforward();
+  //loopreverse();
+  //loopspeedUpFwd();
+  //loopspeedDwnRvs();
+  //strobethreeUP();
+  //strobethreeDWN();
+  //strobecrisscross();
+  //strobecircle();
+  //zigzag1();
+  //oneoffloop();
+  //fade();
+  //fade features are for PWM pins only
+  //fadethree();
+  //fadecross();
+  //fadecrossreverse();
+
 void loop(){
 char c = Serial.read();
 if(c == 'a'){
-  ////////scrollup();          scrolldown();
-  ////////lightup();           lightdown();
   scrollpairup();
   scrollpairdown();
   loopforward();
-
-  //loopreverse();
-  ////////loopspeedUpFwd();    loopspeedDwnRvs();
-  //strobethreeUP();
-  //strobethreeDWN();
-  //////strobecrisscross();  strobecircle();
-  //zigzag1();
-  //oneoffloop();
-  //fade();           //fade features are for PWM pins only
-  //fadethree();
-  //fadecross();
-  //fadecrossreverse();
   Serial.println("Inserted coin");
 }
 if(c =='s'){


Added new menu items

Added new menu items

Remove kegweight from menu.

--- Weight.ino
+++ Weight.ino
@@ -48,10 +48,8 @@
 #define BUTTON_PIN   0

 // initialize the library with the numbers of the interface pins
-//LiquidCrystal lcd(13, 12, 8, 9, 10, 11); //DEBUG
 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //PROD
-HX711 scales[] = {
-  HX711 (A1, A2), HX711 (A3, A4)}; //A1 = ANALOG1 = DT // A2=SCK
+HX711 scales[] = {HX711 (A1, A2), HX711 (A3, A4)}; //A1 = ANALOG1 = DT // A2=SCK
 int eepromAddress[WEIGHT_SENSORS] = {0};

 unsigned long last[WEIGHT_SENSORS];
@@ -69,11 +67,12 @@
 // WEIGHT VARIABLES
 float lastValue[WEIGHT_SENSORS];
 unsigned int useFastWeight = 0;
+unsigned int useKegWeight = 0;

 //MENU
 char* EMPTY = "                ";
-char* menu[] = {"Calibrate       " ,"Tare           ", "Beersize       "};
-unsigned int lastItem = sizeof(menu);
+char* menu[] = {"Calibrate       " ,"Tare           ", "Beersize       ", "Keg Weight      "};
+unsigned int lastItem = 4;
 unsigned int menuMarker = 0;

 //GUI VARIABLES
@@ -177,11 +176,15 @@

 void getWeight(const float value, char* buffer) {
   int decimals = 0;
-  if (value > KILO * 10 || (KILO * -10) < value) {
+  float weight = value;
+  if (useKegWeight) {
+    weight -= KEG_WEIGHT;
+  }
+  if (weight > KILO * 10 || (KILO * -10) < weight) {
     if (WEIGHT_SENSORS > 2) {
       decimals = 1;
     } else {
-      if (value < 0) {
+      if (weight < 0) {
         decimals = 2;
       } else {
         decimals = 3;
@@ -194,7 +197,8 @@
       decimals = 2;
     }
   }
-  dtostrf((value / KILO), 1, decimals, buffer);
+  dtostrf((weight / KILO), 1, decimals, buffer);
+
 }

 void printWeightOnLCD(const float value, String weightName) {
@@ -307,9 +311,17 @@
     delay(DELAY);
   }
   lcd.print("Done tare...");
-  delay(DELAY * 3);
-  printGUI = 0;
-  lcd.clear();
+  delay(DELAY * 2);
+}
+
+void kegWeight() {
+    useKegWeight ^= 1 << 0;
+    if (useKegWeight == 0) {
+        lcd.print("Keg is not removed");
+    } else {
+        lcd.print("Keg is removed");
+    }
+    delay(DELAY * 2);
 }

 void doCalibrate() {
@@ -327,16 +339,33 @@
     Serial.println(sum);
 #endif
     EEPROM.writeDouble(eepromAddress[i], sum);
-    delay(DELAY);
-    printGUI = 0;
-    lcd.clear();
-  }
+
+  }
+}
+
+void doSelect(int value) {
+  switch (value) {
+  case 0:
+     doCalibrate();
+     break;
+  case 1:
+    doTare();
+  break;
+    case 3:
+    kegWeight();
+  break;
+  default:
+    break;
+  }
+  delay(DELAY);
+  printGUI = 0;
+  lcd.clear();
 }

 void doButtonAction(int btn) {
   if (btn != btnNONE) {
 #if defined(DEBUG)
-    Serial.print(btn);
+    Serial.println(btn);
 #endif

    switch (btn) {
@@ -351,11 +380,7 @@
     }
     case btnSELECT: {
        if (printGUI) {
-           if (menuMarker == 1) {
-             doTare();
-           } else if (menuMarker == 0) {
-             doCalibrate();
-           }
+         doSelect(menuMarker);
        }
         break;
       }
@@ -391,6 +416,12 @@
         break;
       }
     }
+    #if defined(DEBUG)
+    Serial.print("MenuMarker:");
+    Serial.println(menuMarker);
+    Serial.print("useKegWeight:");
+    Serial.println(useKegWeight);
+    #endif
   }
 }


Let's not mess with pin 13 by default

Let's not mess with pin 13 by default

--- OpenStage/d_setupFunction.ino
+++ OpenStage/d_setupFunction.ino
@@ -21,7 +21,7 @@
      Serial.println("Established serial connection");
   }

-  pinMode(13,OUTPUT); //PIN 13 is optionally used for testing and debugging with an osciliscope
+  //pinMode(13,OUTPUT); //PIN 13 is optionally used for testing and debugging with an osciliscope
   pinMode(beepPin,OUTPUT); //Produce sound on this pin


Add comment on 64x64 panel support

Add comment on 64x64 panel support

--- AnimatedGIFs.ino
+++ AnimatedGIFs.ino
@@ -100,7 +100,7 @@
 const uint8_t kMatrixHeight = 32;       // known working: 16, 32, 48, 64
 const uint8_t kRefreshDepth = 36;       // known working: 24, 36, 48
 const uint8_t kDmaBufferRows = 2;       // known working: 2-4
-const uint8_t kPanelType = SMARTMATRIX_HUB75_32ROW_MOD16SCAN; // use SMARTMATRIX_HUB75_16ROW_MOD8SCAN for common 16x32 panels
+const uint8_t kPanelType = SMARTMATRIX_HUB75_32ROW_MOD16SCAN; // use SMARTMATRIX_HUB75_16ROW_MOD8SCAN for common 16x32 panels, or use SMARTMATRIX_HUB75_64ROW_MOD32SCAN for common 64x64 panels
 const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE);    // see http://docs.pixelmatix.com/SmartMatrix for options
 const uint8_t kBackgroundLayerOptions = (SM_BACKGROUND_OPTIONS_NONE);
 const uint8_t kScrollingLayerOptions = (SM_SCROLLING_OPTIONS_NONE);


Configured switch so that when turned 'off' it would do things, and when turned 'on' would restart sweeping effect.

Only problem was that the leds don't actually clear. There's only one
that remains on....

--- LEDguide_actual/LEDguide_actual.ino
+++ LEDguide_actual/LEDguide_actual.ino
@@ -29,11 +29,17 @@
 // That'll be what we refer to from here on...
 Adafruit_NeoPixel leds = Adafruit_NeoPixel(LED_COUNT, PIN, NEO_GRB + NEO_KHZ800);

+//Variable for the other side of the switch
+int switchPin = A0;
+int switchValue = 0;
+
 void setup()
 {
   leds.begin();  // Call this to start up the LED strip.
   clearLEDs();   // This function, defined below, turns all LEDs off...
   leds.show();   // ...but the LEDs don't actually update until you call this.
+  pinMode(13, OUTPUT);
+  Serial.begin(9600);
 }

 void loop()
@@ -54,21 +60,25 @@
     cylon(INDIGO, 500);  // Indigo cylon eye!
   }
   */
-
+  clearLEDs();
+  leds.show();
   // A light shower of spring green rain
   // This will run the cascade from top->bottom 20 times
-
-  for (int i=0; i<20; i++)
-  {
-    readySetGo(1500);
-    // First parameter is the color, second is direction, third is ms between falls
-    cascade(MEDIUMSPRINGGREEN, TOP_DOWN, 100);
-  }
-
-}
-
-// Implements a little larson "cylon" sanner.
-// This'll run one full cycle, down one way and back the other
+  switchValue = analogRead(switchPin);
+  Serial.println(switchValue);
+  if(switchValue < 100){
+    digitalWrite(13, HIGH);
+    clearLEDs();
+    leds.show();
+  }else{
+  //whenever signal detected to be shut off, reset leds?
+    digitalWrite(13,LOW);
+      readySetGo(1500);
+      // First parameter is the color, second is direction, third is ms between falls
+      cascade(MEDIUMSPRINGGREEN, TOP_DOWN, 100);
+    }
+}
+
 void readySetGo(byte wait)
 {
   leds.setPixelColor(0, RED);


Commented out clear screen on loop

Commented out clear screen on loop

--- AnimatedGIFs.ino
+++ AnimatedGIFs.ino
@@ -141,9 +141,9 @@

     // Do forever
     while (true) {
-        // Clear screen for new animation
-        matrix.fillScreen(COLOR_BLACK);
-        matrix.swapBuffers();
+        // Can clear screen for new animation here, but this might cause flicker with short animations
+        // matrix.fillScreen(COLOR_BLACK);
+        // matrix.swapBuffers();

         getGIFFilenameByIndex(GIF_DIRECTORY, index++, pathname);
         if (index >= numberOfFiles) {


now we have values and percentages for moisture, light and have vars for limits as well. Rewrote output strings for ease of working with them

--- plantstation.ino
+++ plantstation.ino
@@ -42,25 +42,30 @@
 AirMeasurement am;

 //===== For photoresistor =======================
-// todo - change the threshold to base100
+byte lightPercent;
 const byte lightOnThreshold = 90;
 const byte lightPin = A0;
 boolean lightIsOn = false;
+int lightMaxVal = 550;
+int lightMinVal = 6;
 int lightResistorVal;

 //===== For hygrometer ==========================
+byte moisturePercent;
 const byte hygroPin = A1;
 // todo - find right value for this
-// todo - change the threshold to base100
 const int moistureThreshold = 1000; // <- made this up
+int moistureMaxVal = 960;
+int moistureMinVal = 50;
 int moistureSensorVal;

 //===== For water level sensor ===================
 const byte waterSensorPin = A2;
 // todo - find right value for this
-// todo - change the threshold to base100
 const int waterLevelThreshold = 300; // <- made this up
 int waterLevelVal;
+int waterMaxVal = 310;
+int waterMinVal = 90;
 String waterLevelStatus = "OK";

 //===== For water pump ===========================
@@ -127,7 +132,6 @@

 void waterPlantStarts() {
   // todo - figure out how to send a water pump is on event for log even thou its off at time.
-  // todo - change the threshold to base100
   if (!waterPumpIsOn && waterLevelStatus == "OK" && moistureThreshold > moistureSensorVal) {
     prevWatering = millis();
     waterPumpIsOn = true;
@@ -139,7 +143,6 @@
     if (waterPumpIsOn && currentMillis >= prevWatering + wateringSeconds) {
     waterPumpIsOn = false;
     Console.println("Watering stopped");
-  // todo - change the threshold to base100
   } else if (waterPumpIsOn && moistureThreshold < moistureSensorVal) {
     waterPumpIsOn = false;
     Console.println("Watering stopped");
@@ -150,12 +153,10 @@
 }

 void switchLights() {
-  // todo - change the threshold to base100
   if (lightOnThreshold > lightResistorVal && !lightIsOn) {
     digitalWrite(LightSwitch, HIGH);
     lightIsOn = true;
   }
-  // todo - change the threshold to base100
   if (lightOnThreshold < lightResistorVal && lightIsOn) {
     digitalWrite(LightSwitch, LOW);
     lightIsOn = false;
@@ -163,18 +164,18 @@
 }

 void readLightResistor() {
-  int val = analogRead(lightPin);
-  lightResistorVal = map(val, 60, 550, 0, 100);
+  lightResistorVal = analogRead(lightPin);
+  lightPercent = map(lightResistorVal, lightMinVal, lightMaxVal, 0, 100);
 }

 void readMoistureSensor() {
-  int val = analogRead(hygroPin);
-  moistureSensorVal = map(val, 110, 960, 0, 100);
+  moistureSensorVal = analogRead(hygroPin);
+  moisturePercent = map(moistureSensorVal, moistureMinVal, moistureMaxVal, 0, 100);
 }

 void readWaterLevelSensor() {
   int val = analogRead(waterSensorPin);
-  waterLevelVal = map(val, 90, 310, 0, 100);
+  waterLevelVal = map(val, waterMinVal, waterMaxVal, 0, 100);

   if (val < waterLevelThreshold) {
    waterLevelStatus = "LOW";
@@ -236,37 +237,28 @@
 }

 void sendToKeen() {
+
   String my_output = "{";
-  my_output += "\"AppId\":\"";
-  my_output += appId;
-  my_output += "\",\"HumidityPercent\":";
-  my_output += am.humidityAir;
-  my_output += ",\"AirTemperatureCelcius\":";
-  my_output += am.tempAirC;
-  my_output += ",\"AirTemperatureFahrenheit\":";
-  my_output += am.tempAirF;
-  my_output += ",\"HeatIndex\":";
-  my_output += am.heatIndex;
-  my_output += ",\"Light\":";
-  my_output += lightResistorVal;
-  my_output += ",\"ProbeTemperatureCelcius\":";
-  my_output += sm.tempSoilC;
-  my_output += ",\"ProbeTemperatureFahrenheit\":";
-  my_output += sm.tempSoilF;
-  my_output += ",\"Moisture\":";
-  my_output += moistureSensorVal;
-  my_output += ",\"WaterLevelStatus\":\"";
-  my_output += waterLevelStatus;
-  my_output += "\",\"WaterLevelValue\":";
-  my_output += waterLevelVal;
-  my_output += ",\"Location\":\"";
-  my_output += location;
-  my_output += "\",\"LightIsOn\":";
-  my_output += lightIsOn;
-  my_output += ",\"WaterPumptIsOn\":";
-  my_output += waterPumpIsOn;
+  // strings
+  my_output += "\"AppId\":\"";                      my_output += appId;             my_output += "\"";
+  my_output += ",\"Location\":\"";                  my_output += location;          my_output += "\"";
+  my_output += ",\"WaterLevelStatus\":\"";          my_output += waterLevelStatus;  my_output += "\"";
+  // numerics
+  my_output += ",\"AirTemperatureCelcius\":";       my_output += am.tempAirC;
+  my_output += ",\"AirTemperatureFahrenheit\":";    my_output += am.tempAirF;
+  my_output += ",\"HeatIndex\":";                   my_output += am.heatIndex;
+  my_output += ",\"HumidityPercent\":";             my_output += am.humidityAir;
+  my_output += ",\"LightPercent\":";                my_output += lightPercent;
+  my_output += ",\"LightValue\":";                  my_output += lightResistorVal;
+  my_output += ",\"LightIsOn\":";                   my_output += lightIsOn;
+  my_output += ",\"MoisturePercent\":";             my_output += moisturePercent;
+  my_output += ",\"MoistureValue\":";               my_output += moistureSensorVal;
+  my_output += ",\"ProbeTemperatureCelcius\":";     my_output += sm.tempSoilC;
+  my_output += ",\"ProbeTemperatureFahrenheit\":";  my_output += sm.tempSoilF;
+  my_output += ",\"WaterLevelValue\":";             my_output += waterLevelVal;
+  my_output += ",\"WaterPumptIsOn\":";              my_output += waterPumpIsOn;
   my_output += "}";
-
+
   myKeen.setApiVersion(F("3.0"));
   myKeen.setProjectId(KEEN_PROJECT_ID);
   myKeen.setWriteKey(KEEN_WRITE_KEY);
@@ -287,35 +279,25 @@

 void outputEvent() {
   String my_output = "";
-  my_output += "AppId:";
-  my_output += appId;
-  my_output += ";HumidityPercent:";
-  my_output += am.humidityAir;
-  my_output += ";AirTemperatureCelcius:";
-  my_output += am.tempAirC;
-  my_output += ";AirTemperatureFahrenheit:";
-  my_output += am.tempAirF;
-  my_output += ";HeatIndex:";
-  my_output += am.heatIndex;
-  my_output += ";Light:";
-  my_output += lightResistorVal;
-  my_output += ";ProbeTemperatureCelcius:";
-  my_output += sm.tempSoilC;
-  my_output += ";ProbeTemperatureFahrenheit:";
-  my_output += sm.tempSoilF;
-  my_output += ";Moisture:";
-  my_output += moistureSensorVal;
-  my_output += ";WaterLevelStatus:";
-  my_output += waterLevelStatus;
-  my_output += ";WaterLevelValue:";
-  my_output += waterLevelVal;
-  my_output += ";LightIsOn:";
-  my_output += lightIsOn;
-  my_output += ";Location:";
-  my_output += location;
-  my_output += ";WaterPumptIsOn:";
-  my_output += waterPumpIsOn;
-
+  // strings
+  my_output += "AppId:";                        my_output += appId;
+  my_output += ";Location:";                    my_output += location;
+  my_output += ";WaterLevelStatus:";            my_output += waterLevelStatus;
+  // numerics
+  my_output += ";AirTemperatureCelcius:";       my_output += am.tempAirC;
+  my_output += ";AirTemperatureFahrenheit:";    my_output += am.tempAirF;
+  my_output += ";HeatIndex:";                   my_output += am.heatIndex;
+  my_output += ";HumidityPercent:";             my_output += am.humidityAir;
+  my_output += ";LightPercent:";                my_output += lightPercent;
+  my_output += ";LightValue:";                  my_output += lightResistorVal;
+  my_output += ";LightIsOn:";                   my_output += lightIsOn;
+  my_output += ";MoisturePercent:";             my_output += moisturePercent;
+  my_output += ";MoistureValue:";               my_output += moistureSensorVal;
+  my_output += ";ProbeTemperatureCelcius:";     my_output += sm.tempSoilC;
+  my_output += ";ProbeTemperatureFahrenheit:";  my_output += sm.tempSoilF;
+  my_output += ";WaterLevelValue:";             my_output += waterLevelVal;
+  my_output += ";WaterPumptIsOn:";              my_output += waterPumpIsOn;
+
   Console.println(my_output);
 }


added api commands for speed and stop

added api commands for speed and stop

--- Firmware/Api.ino
+++ Firmware/Api.ino
@@ -20,6 +20,10 @@
 void api_init()
 {
     serialCommand.addCommand("v", api_v);
+    serialCommand.addCommand("v1", api_v1);
+    serialCommand.addCommand("v2", api_v2);
+    serialCommand.addCommand("v3", api_v3);
+    serialCommand.addCommand("v4", api_v4);
     serialCommand.addCommand("stop", api_stop);
     serialCommand.addCommand("start", api_start);
     serialCommand.setDefaultHandler(api_unknown);
@@ -31,12 +35,32 @@

 void api_v()
 {
+    int v[4] = {0, 0, 0, 0};
+    for (int i = 0; i < 4; i++)
+    {
+        char *value = serialCommand.next();
+        if (value == NULL)
+        {
+            Serial.println("!Not enough arguments");
+            return;
+        }
+        v[i] = atoi(value);
+    }
+
+    for (int i = 0; i < 4; i++)
+    {
+        robot_setMotorSpeed(i, v[i]);
+    }
+}
+
+void api_v1()
+{
     char *arg1 = serialCommand.next();

     // No arguments -> show usage
     if (arg1 == NULL)
     {
-        Serial.println("# V [Steps / second]");
+        Serial.println("#v1 [Steps / second]");
         return;
     }

@@ -45,16 +69,82 @@
     {
         // Converts a char string to a long
         int v = atoi(arg1);
-        robot_setMotorSpeed(0x01, v);
+        robot_setMotorSpeed(1, v);
+    }
+}
+
+void api_v2()
+{
+    char *arg1 = serialCommand.next();
+
+    // No arguments -> show usage
+    if (arg1 == NULL)
+    {
+        Serial.println("#v2 [Steps / second]");
+        return;
+    }
+
+    // there are arguments (number of steps)
+    if (arg1 != NULL)
+    {
+        // Converts a char string to a long
+        int v = atoi(arg1);
+        robot_setMotorSpeed(2, v);
+    }
+}
+
+void api_v3()
+{
+    char *arg1 = serialCommand.next();
+
+    // No arguments -> show usage
+    if (arg1 == NULL)
+    {
+        Serial.println("#v3 [Steps / second]");
+        return;
+    }
+
+    // there are arguments (number of steps)
+    if (arg1 != NULL)
+    {
+        // Converts a char string to a long
+        int v = atoi(arg1);
+        robot_setMotorSpeed(3, v);
+    }
+}
+
+void api_v4()
+{
+    char *arg1 = serialCommand.next();
+
+    // No arguments -> show usage
+    if (arg1 == NULL)
+    {
+        Serial.println("#v4 [Steps / second]");
+        return;
+    }
+
+    // there are arguments (number of steps)
+    if (arg1 != NULL)
+    {
+        // Converts a char string to a long
+        int v = atoi(arg1);
+        robot_setMotorSpeed(4, v);
     }
 }

 void api_stop()
 {
-    robot_quickStop(0x01);
+    for (int i = 1; i < 5; i++)
+    {
+        robot_quickStop(i);
+    }
 }

 void api_start()
 {
-    robot_initNode(0x01);
+    for (int i = 1; i < 5; i++)
+    {
+        robot_initNode(i);
+    }
 }


Changed delay for Sharp sensor to microseconds. Modified grove sensor timing.

--- frontbox_solo/frontbox_solo.ino
+++ frontbox_solo/frontbox_solo.ino
@@ -5,13 +5,13 @@

 //  Sensor PINOUTS
 //  PINS		ARDUINO		ATMEGA
-//  GROVE		D3			5
-//  SHARP		AI3			26
-//  SHARP_LED	D4			6
-//  MQ7			AI0			23
-//  MQ7_VOLTAGE	D2			4
-//  TEMP		AI1			24
-//  PULSE		AI2			25
+//  GROVE		D3		5
+//  SHARP		A3		26
+//  SHARP_LED	        D4		6
+//  MQ7			A0		23
+//  MQ7_VOLTAGE	        D2		4
+//  TEMP		A1		24
+//  PULSE		A2		25

 // Memory PINOUTS
 // Arduino-- SD shield
@@ -43,16 +43,18 @@

 // **************** FOR SD CARD ******************
 #define CHIP_SELECT_PIN 10
-File myFile;
+File data_file;
 String file_name;

 // **************** FOR GROVE SENSOR ****************
 #define GROVE_READ_PIN 3 // Digital PIN 3 ATMEGA 5
 unsigned long grove_duration;
-unsigned long grove_sample_time = 1000; //sample 1s ;  FIXME- used in calulation
+unsigned long grove_start_time;
+unsigned long grove_stop_time;
 unsigned long lowpulseoccupancy = 0;
 float ratio = 0;
 float concentration = 0;
+

 // **************** FOR SHARP SENSOR ****************
 #define SHARP_READ_PIN 3 // Analog PIN 3 ATMEGA 26
@@ -60,7 +62,7 @@
 float sharp_voltage=0;

 #define SHARP_LED_PIN 4      // Digital PIN 4 ATMEGA 6
-#define SHARP_DELAY_TIME 280
+

 // **************** FOR MQ7 SENSOR ****************
 #define CO_PWR_SEL_PIN 2    // Digital PIN 2 ATMEGA PIN 4
@@ -105,6 +107,7 @@
   // **************** FOR GROVE SENSOR ****************
   pinMode(8, INPUT);
   pinMode(13, OUTPUT);
+  grove_start_time=millis();

   // **************** FOR MQ7 SENSOR ****************
   pinMode(CO_PWR_SEL_PIN, OUTPUT);
@@ -124,31 +127,20 @@
   DateTime rtc_time=rtc.now();
   file_name = String( rtc_time.month() ) + '-' + String( rtc_time.day() ) + '-' +
       String( rtc_time.hour() ) + ".txt";
-
-  if ( !SD.begin(CHIP_SELECT_PIN) ) {
-#ifdef DEGUB
-    Serial.println("SD card initialization failed!");
-#endif
-  }
+#ifndef DEBUG
+  SD.begin(CHIP_SELECT_PIN);
   delay(100); // otherwise open() will fail

   // write header

-#ifdef DEBUG
-    Serial.println("Writing header to SD");
-    Serial.flush();
-#endif
-
-  myFile = SD.open(file_name.c_str(), FILE_WRITE);
-  if (myFile) {
-    myFile.print("Rec. #\tDD/MM/YYYY\tHH:MM:SS\tlatitude\tlongitude\t");
-    myFile.println("Sharp value\tGrove value\tCO read\tCO heat\tHumidity\tTemp (celsius)");
-    myFile.close();
-  } else {
-#ifdef DEBUG
-    Serial.println("Error opening SD file to write header");
-#endif
-  }
+  data_file = SD.open(file_name.c_str(), FILE_WRITE);
+  if (data_file) {
+    data_file.print("Rec. #\tMM/DD/YYYY\tHH:MM:SS (UTC)\tlatitude\tlongitude\t");
+    data_file.println("Sharp\tGrove\tCO read\tCO heat\tHumidity\tTemp (celsius)");
+    data_file.close();
+  }
+
+ #endif

   // **************** FOR SENOR READING TIMER ****************
   sensors_read_time_start = millis();
@@ -181,11 +173,11 @@
       if(!haveClock) { // set clock
         gps.crack_datetime(&gps_year, &gps_month, &gps_day, &gps_hour, &gps_minute, &gps_second);
          // adjust UTC FIXME!
-         if ( gps_hour < 7) {  // don't subtract from unsigned types
-           gps_day -= 1;
-           gps_hour += 17;     // instead add 24 - 7
-         } else
-            gps_hour -=7;     // OK to subtract here
+         //if ( gps_hour < 7) {  // don't subtract from unsigned types
+         //  gps_day -= 1;
+         //  gps_hour += 17;     // instead add 24 - 7
+         //} else
+         //   gps_hour -=7;     // OK to subtract here
          //  Wants years since 1900?
          rtc.adjust( DateTime(gps_year-2000, gps_month, gps_day, gps_hour, gps_minute, gps_second));
          haveClock=true;
@@ -211,8 +203,9 @@
   // **************** FOR GROVE SENSOR ****************
   // continuous reading
   grove_duration = pulseIn(GROVE_READ_PIN, LOW);
-  lowpulseoccupancy = lowpulseoccupancy + grove_duration;
-
+  lowpulseoccupancy += grove_duration;
+  grove_stop_time=millis();
+
   // **************** FOR MQ7 SENSOR ****************
   // nothing

@@ -227,14 +220,14 @@
 #endif

   if( (millis() - sensors_read_time_start) > SENSORS_READ_TIME ) {
-    ReadSensors();
+    RecordSensors();
     sensors_read_time_start = millis();
   }

 } // void loop()

-void ReadSensors()
+void RecordSensors()
 {

 #ifdef DEBUG
@@ -244,30 +237,26 @@
   // **************** SENSOR READING STAMP TIME ****************
   now = rtc.now();

+
   // **************** FOR SHARP SENSOR ****************
   digitalWrite(SHARP_LED_PIN, LOW); // power on the LED
-  delay(SHARP_DELAY_TIME);  // wait 280ms
+  delayMicroseconds(280);  // wait 280us
   sharp_dust_val = analogRead(SHARP_READ_PIN); // read the dust value via pin 5 on the sensor
+  delayMicroseconds(40);  // wait 40us, may not be necessary
   digitalWrite(SHARP_LED_PIN, HIGH); // turn the LED off
   sharp_voltage = sharp_dust_val*4.9/1024;   // convert to voltage
-  sharp_voltage = (sharp_voltage - 0.0356) * 120000; // convert to particles / .01 ft^3
+  sharp_voltage = (sharp_voltage - 0.0356) * 120000; // convert to particles per .01 ft^3
   if( sharp_voltage < 0 )
     sharp_voltage = 0;

-  // **************** FOR GROVE SENSOR ****************
-  ratio = lowpulseoccupancy / (grove_sample_time*10.0);  // Integer percentage 0=>100
-  // using spec sheet curve, gives particles per 0.01 cubic foot
-  concentration = 1.1*pow(ratio, 3) - 3.8*pow(ratio, 2) + 520 * ratio + 0.62;
-  lowpulseoccupancy = 0;  // reset
-

   // **************** FOR MQ7 SENSOR ****************
-    if (millis() > CO_switch_time) {         // time to switch
-      if (heaterInHighPhase) {
-        digitalWrite(CO_PWR_SEL_PIN, HIGH);  // 1.4v phase
-        heaterInHighPhase = false;
-        CO_switch_time = millis() + CO_READ_TIME;
-      } else {                               // switch to 5V phase
+  if (millis() > CO_switch_time) {         // time to switch
+    if (heaterInHighPhase) {
+      digitalWrite(CO_PWR_SEL_PIN, HIGH);  // 1.4v phase
+      heaterInHighPhase = false;
+      CO_switch_time = millis() + CO_READ_TIME;
+    } else {                               // switch to 5V phase
         digitalWrite(CO_PWR_SEL_PIN, LOW);   // 5v phase
         heaterInHighPhase = true;
         CO_switch_time = millis() + CO_HEAT_TIME;
@@ -278,14 +267,23 @@

   // **************** FOR TEMP & HUMIDITY SENSOR ****************
-  // Reading can take 200 milliseconds, can only be done every 2 seconds
   float h = dht.readHumidity();
   float f = dht.readTemperature(false); // change to true for Farenheit
   if (isnan(h) || isnan(f)) { // Check if any reads failed and set to error value.
     h=255;    f=255;
   }

-  // ********** KEEP TRACK OF HOW MANY RECORDINGS WE'VE TAKEN *********
+
+  // **************** FOR GROVE SENSOR ****************
+    // Integer percentage 0=>100
+  ratio = lowpulseoccupancy / ((grove_stop_time - grove_start_time) * 10.0);
+    // using spec sheet curve, gives particles per 0.01 cubic foot
+  concentration = 1.1*pow(ratio, 3) - 3.8*pow(ratio, 2) + 520 * ratio + 0.62;
+  lowpulseoccupancy = 0;  // reset
+  grove_start_time=millis();
+
+
+  // ********** KEEP TRACK OF NUMBER OF RECORDS *********
   num_records++;

 #ifdef DEBUG
@@ -334,61 +332,56 @@
   Serial.flush();
 #endif

-  myFile = SD.open(file_name.c_str(), FILE_WRITE);
-
-/* #ifdef DEBUG
-  if (!myFile) {
-    Serial.println("Error opening SD file. Record not logged.");
-    Serail.flush();
-    return;
-  }
-#endif
-*/
+#ifndef DEBUG
+  data_file = SD.open(file_name.c_str(), FILE_WRITE);

   // record number
-  myFile.print(num_records); myFile.print('\t');
+  data_file.print(num_records); data_file.print('\t');

   // date and time
-  myFile.print(String(now.month()).length()==1 ? String('0') + String(now.month()) : now.month() );
-  myFile.print('/');
-  myFile.print(String(now.day()).length()==1 ? String('0') + String(now.day()) : now.day() );
-  myFile.print('/');
-  myFile.print(now.year());
-  myFile.print('\t');
-  myFile.print(String(now.hour()).length()==1 ? String('0') + String(now.hour()) : now.hour() );
-  myFile.print(':');
-  myFile.print(String(now.minute()).length()==1 ? String('0') + String(now.minute()) : now.minute() );
-  myFile.print(':');
-  myFile.print(String(now.second()).length()==1 ? String('0') + String(now.second()) : now.second() );
-  myFile.print('\t');
+  data_file.print(String(now.month()).length()==1 ? String('0') + String(now.month()) : now.month() );
+  data_file.print('/');
+  data_file.print(String(now.day()).length()==1 ? String('0') + String(now.day()) : now.day() );
+  data_file.print('/');
+  data_file.print(now.year());
+  data_file.print('\t');
+  data_file.print(String(now.hour()).length()==1 ? String('0') + String(now.hour()) : now.hour() );
+  data_file.print(':');
+  data_file.print(String(now.minute()).length()==1 ? String('0') + String(now.minute()) : now.minute() );
+  data_file.print(':');
+  data_file.print(String(now.second()).length()==1 ? String('0') + String(now.second()) : now.second() );
+  data_file.print('\t');

   // gps
-  myFile.print(flat,6); myFile.print('\t');
-  myFile.print(flon,6); myFile.print('\t');
+  data_file.print(flat,6); data_file.print('\t');
+  data_file.print(flon,6); data_file.print('\t');
   // altitude, speed?

   // sharp sensor value
-  myFile.print(sharp_voltage); myFile.print('\t');
+  data_file.print(sharp_voltage); data_file.print('\t');

   //  grove sensor value
-  myFile.print(concentration);  myFile.print('\t');
+  data_file.print(concentration);  data_file.print('\t');

   // MQ7 CO sensor value
    if(heaterInHighPhase) {
-    myFile.print("--\t");
-    myFile.print(gasLevel);
+    data_file.print("--\t");
+    data_file.print(gasLevel);
   } else {
-    myFile.print(gasLevel); myFile.print('\t');
-    myFile.print("--");
-  }
-  myFile.print('\t');
+    data_file.print(gasLevel); data_file.print('\t');
+    data_file.print("--");
+  }
+  data_file.print('\t');

   // DHT22 sensor values
-  myFile.print(h);  myFile.print('\t');
-  myFile.print(f);  myFile.println();
-  myFile.close();
-
-
-} // ReadSensors()
-
+  data_file.print(h);  data_file.print('\t');
+  data_file.print(f);  data_file.println();
+  data_file.close();
+#endif
+
+  // Reset the grove sample time
+  grove_start_time=millis();
+
+} // RecordSensors()
+


update

update

--- src/Firmware.ino
+++ src/Firmware.ino
@@ -81,13 +81,13 @@
 {
     Serial.begin(115200);
     delay(1000);
+    initTimer();
+#ifdef MAKEBLOCK
     pinMode(MISO, OUTPUT);
     // turn on SPI in slave mode
     SPCR |= _BV(SPE);
     // turn on interrupts
     SPCR |= _BV(SPIE);
-    initTimer();
-#ifdef MAKEBLOCK
     pinMode(47, OUTPUT);
     pinMode(48, OUTPUT);
     pinMode(6, OUTPUT);


Move volatiles into private members and move ISR code into internal callback methods.

--- examples/qntzr/qntzr.ino
+++ examples/qntzr/qntzr.ino
@@ -55,8 +55,6 @@
   0x60, 0x63, 0x0f, 0x0f, 0x0f, 0x63, 0x60  // trigger mode on
 };

-volatile bool triggered;
-
 void trig_isr();

 void trigger_mode_scroll_callback(int delta);
@@ -104,6 +102,7 @@
     }
     container_notes_->attach_click_callback_array(notes_click_callback);

+    triggered = false;
     trigger_mode = false;
     key = 0;
     scale_id = 0;
@@ -225,6 +224,11 @@
     }
   }

+  void trig_callback()
+  {
+    triggered = true;
+  }
+
   void widget_trigger_mode_scroll_callback(int delta)
   {
     trigger_mode = delta > 0;
@@ -471,6 +475,7 @@
   DUINO_DisplayWidget * widget_scale_;
   DUINO_DisplayWidget * widgets_notes_[12];

+  volatile bool triggered;
   bool trigger_mode;
   int8_t key;
   int scale_id;
@@ -482,10 +487,7 @@

 DU_Quantizer_Function * function;

-void trig_isr()
-{
-  triggered = true;
-}
+void trig_isr() { function->trig_callback(); }

 void trigger_mode_scroll_callback(int delta) { function->widget_trigger_mode_scroll_callback(delta); }
 void key_scroll_callback(int delta) { function->widget_key_scroll_callback(delta); }
@@ -496,8 +498,6 @@
 {
   function = new DU_Quantizer_Function();

-  triggered = false;
-
   function->begin();
 }


Laggy mouse pedal working.

Laggy mouse pedal working.

--- arduinoHm/arduinoHm.ino
+++ arduinoHm/arduinoHm.ino
@@ -1,6 +1,9 @@
 int serValue = 0;
 int serData[10];
 int controlM = 0;
+// Button values are reversed because of pullup resistors
+int pedalUp = 1;
+int pedalDown = 0;

 void setup() {
   //Setup mouse buttons
@@ -45,34 +48,55 @@
       yCarryOver -= y;
     }

+    //Temporary pedal logic
+    if(readLeftPedal() == pedalDown){
+      while (readLeftPedal() == pedalDown){
+        delay(10);
+      }
+
+      Mouse.click();
+    }
+

     if (Serial1.find("c")) {
       // We've received the start of a control code
       ctrlCode = Serial1.parseInt();

-      if (ctrlCode == 0) {
-        // Request for device info
-        Serial1.println("hm0.0.1");
-      }
-
-      if (ctrlCode == 1) {
-        // Received code to move mouse
-
-        xCarryOver += Serial1.parseInt();
-        yCarryOver += Serial1.parseInt();
-      }
-
-      if (ctrlCode == 2) {
-        maxMove = Serial1.parseInt();
-      }
-
-      if (ctrlCode == 3) {
-        Serial1.println("echo");
-      }
-
-    }
-
+      switch (ctrlCode) {
+        case 0:
+          // Request for device info
+          Serial1.println("hm0.0.1");
+          break;
+        case 1:
+          // Received code to move mouse
+          xCarryOver += Serial1.parseInt();
+          yCarryOver += Serial1.parseInt();
+          break;
+        case 2:
+          maxMove = Serial1.parseInt();
+          break;
+        case 3:
+          //Serial1.println("echo");
+          //print out the value of the pushbutton
+          Serial1.println();
+          break;
+        default:
+          // if nothing else matches, do the default
+          // default is optional
+        break;
+      }
+    } else {
+        //Serial1.println("No command received.");
+    }
   }
+}
+
+int readLeftPedal() {
+  return digitalRead(2);
+}
+
+int readRightPedal() {
+  return digitalRead(3);
 }

 int absMax(int val, int maxVal) {


I added in rotary encoder stuff for the time and alarm and the display brightness, but its not working.  My suspicion is that the timer pwm for the old light is not working and its getting in the way.

--- SunriseAlarm.ino
+++ SunriseAlarm.ino
@@ -9,6 +9,7 @@
 #include "Adafruit_GFX.h"
 #include "RTClib.h"
 #include "AT24Cxx.h"
+#include <ClickEncoder.h>

 // 2013-04-06 TODO:  Add a temperature sensor to the lamp and if it exceeds a particular temperature, then turn it off or down
@@ -47,6 +48,20 @@
     fixTime();
     return result;
   }
+  ClockTime operator+=(int16_t delta)
+  {
+    ClockTime result(*this);
+    this->minute += delta;
+    fixTime();
+    return result;
+  }
+  ClockTime operator-=(int16_t delta)
+  {
+    ClockTime result(*this);
+    this->minute -= delta;
+    fixTime();
+    return result;
+  }
   ClockTime operator--(int) {
     ClockTime result(*this);
     --this->minute;
@@ -153,13 +168,20 @@
   return !(lhs == rhs);
 }

-const int LEDpinA = 9;
-
-const int AlarmButton = 2;
-const int TimeButton = 3;
-const int FwdButton = 4;
-const int RewButton = 5;
-const int OffButton = 6;
+ClickEncoder *encoder;
+const int ENCODER_PIN0 = 11;
+const int ENCODER_PIN1 = 12;
+
+const int LEDpinA = 6;
+
+const int AlarmButton = 7;
+const int AlarmLED = 8;
+const int TimeButton = 9;
+const int TimeLED = 13;
+const int FwdButton = 2; // rotary encoder
+const int RewButton = 3; // rotary encoder
+const int OffButton = A0;
+const int AlarmEnabledButton = 5;

 bool alarmEnabled = true;
 bool alarmActive = false;
@@ -178,8 +200,8 @@

 AT24Cxx eeprom;
 // This is the time you want to get up.  Lights will start 30 minutes before.
-ClockTime alarmTime(5,00);
-ClockTime startTime(4,30);
+ClockTime alarmTime(6,00);
+ClockTime startTime(5,30);

 const int alarm_address = 0;
 const int sundown_address = 2;
@@ -203,6 +225,11 @@
 unsigned long synchronized_clock_millis;
 ClockTime synchronized_clock_time;
 ClockTime current_clock_time;
+
+void timerIsr() {
+  encoder->service();
+}
+

 bool readAlarmTimeFromEEPROM() {
   if (eeprom.isPresent()) {
@@ -476,23 +503,23 @@
   //          )
   //);
   pinMode(LEDpinA,OUTPUT); digitalWrite(LEDpinA,0);
-  pinMode(AlarmButton,INPUT);
-  pinMode(TimeButton,INPUT);
+  pinMode(AlarmButton,INPUT_PULLUP);
+  pinMode(TimeButton,INPUT_PULLUP);
   pinMode(RewButton,INPUT);
   pinMode(FwdButton,INPUT);
   pinMode(OffButton,INPUT);
+  encoder = new ClickEncoder(ENCODER_PIN0, ENCODER_PIN1);
   timer.initialize(timerPeriod);
   timer.pwm(LEDpinA, 0); //set up pin 9
   matrix.begin(0x70);
   display_todd();
+  //while (!eeprom.isPresent()) { delay(1); }
   readBrightnessFromEEPROM();
   matrix.setBrightness(matrixBrightness); // 0-15
   readSunDownDeltaFromEEPROM();
   updateClockTime(true);
   updateCurrentTime(true);
-  if (!readAlarmTimeFromEEPROM()) {
-    alarmTime = ClockTime(5,45);
-  }
+  readAlarmTimeFromEEPROM();
   updateStartTime();
 }

@@ -555,56 +582,19 @@
 }

-void forwardTime(ClockTime & t) {
-  while (digitalRead(FwdButton)==LOW) {
-    ++t.minute;
-    if (t.minute > 59) {
-      ++t.hour;
-      t.minute = 0;
-    }
-    if (t.hour > 23) {
-      t.hour = 0;
-    }
-    updateTimeDisplay(t,true,true);
-    delay(forward_delay);
-  }
-}
-
-void rewindTime(ClockTime & t) {
-  while (digitalRead(RewButton)==LOW) {
-    --t.minute;
-    if (t.minute < 0) {
-      --t.hour;
-      t.minute = 59;
-    }
-    if (t.hour < 0) {
-      t.hour = 23;
-    }
-    updateTimeDisplay(t,true,true);
-    delay(rewind_delay);
-  }
-
-}
-
-void forwardAlarm() {
-  while (digitalRead(FwdButton)==LOW) {
-    ++alarmTime;
-    updateTimeDisplay(alarmTime,true,true);
-    delay(forward_delay);
-  }
-}
-
-void rewindAlarm() {
- while (digitalRead(RewButton)==LOW) {
-    --alarmTime;
-    updateTimeDisplay(alarmTime,true,true);
-    delay(rewind_delay);
-  }
-}
-
+void updateTime(ClockTime & t, int16_t delta) {
+  t.minute += delta;
+  updateTimeDisplay(t,true,true);
+}
+
+void updateAlarm(int16_t delta) {
+  alarmTime += delta;
+  updateTimeDisplay(alarmTime,true,true);
+}

 void setTime() {
+  digitalWrite(TimeLED,HIGH);
   DateTime currentTime = RTC.now();
   ClockTime t(currentTime);
   display_Cloc();
@@ -614,13 +604,9 @@
   unsigned long modeActive = millis();
   bool normalExit = true;
   while (debounceDigitalRead(TimeButton)==HIGH) {
-    if (digitalRead(FwdButton)==LOW) {
-      forwardTime(t);
-      modeActive = millis();
-    } else if (digitalRead(RewButton)==LOW) {
-      rewindTime(t);
-      modeActive = millis();
-    }
+    int16_t encoderDelta = encoder->getValue();
+    updateTime(t,encoderDelta);
+    modeActive = millis();
     if (static_cast<unsigned long>(millis() - modeActive) > modeInactivePeriod) {
       normalExit = false;
       break;
@@ -645,9 +631,11 @@
   synchronized_clock_millis = millis();
   current_clock_time = synchronized_clock_time;
   updateCurrentTime(true);
+  digitalWrite(TimeLED,LOW);
 }

 void setAlarm() {
+  digitalWrite(AlarmLED,HIGH);
   display_ALAr();
   delay(1000);
   updateTimeDisplay(alarmTime,true,true);
@@ -655,13 +643,9 @@
   unsigned long modeActive = millis();
   bool normalExit = true;
   while (debounceDigitalRead(AlarmButton)==HIGH) {
-    if (digitalRead(FwdButton)==LOW) {
-      forwardAlarm();
-      modeActive = millis();
-    } else if (digitalRead(RewButton)==LOW) {
-      rewindAlarm();
-      modeActive = millis();
-    }
+    int16_t encoderDelta = encoder->getValue();
+    updateAlarm(encoderDelta);
+    modeActive = millis();
     if (static_cast<unsigned long>(millis() - modeActive) > modeInactivePeriod) {
       normalExit = false;
       break;
@@ -676,6 +660,7 @@
   updateCurrentTime(true);
   updateTimeDisplay(current_clock_time,false,false);
   writeAlarmTimeToEEPROM();
+  digitalWrite(AlarmLED,LOW);
 }

 void forwardSunSet(int & minutes) {
@@ -775,7 +760,7 @@
   else if (digitalRead(TimeButton)==LOW && debounceDigitalRead(TimeButton)==LOW) {
     setTime();
   }
-  else if (digitalRead(OffButton)==LOW && debounceDigitalRead(OffButton)==LOW) {
+  else if (digitalRead(OffButton)==HIGH && debounceDigitalRead(OffButton)==HIGH) {
     if (alarmActive) {
       alarmActive = false;
       alarmEnabled = false;
@@ -791,18 +776,14 @@
       setSunSet();
     }
   }
-  else if (digitalRead(FwdButton)==LOW && debounceDigitalRead(FwdButton)==LOW) {
-    matrixBrightness = max(min(15,matrixBrightness+1),0);
+  int16_t encoderDelta = encoder->getValue();
+  if (encoderDelta != 0)
+  {
+    int delta = (encoderDelta>0 ? 1 : -1);
+    matrixBrightness = max(min(15,matrixBrightness+delta),0);
     matrix.setBrightness(matrixBrightness); // 0-15
-    waitForButtonDepress(FwdButton);
     writeBrightnessToEEPROM();
-  }
-  else if (digitalRead(RewButton)==LOW && debounceDigitalRead(RewButton)==LOW) {
-    matrixBrightness = max(min(15,matrixBrightness-1),0);
-    matrix.setBrightness(matrixBrightness); // 0-15
-    waitForButtonDepress(RewButton);
-    writeBrightnessToEEPROM();
-  }
+  }
   updateLight();
   updateCurrentTime();
   updateClockTime();


Fixed pulse max detection

Fixed pulse max detection

--- heartbeat_with_pulse.ino
+++ heartbeat_with_pulse.ino
@@ -231,7 +231,7 @@
   offset = (offset + 1) % beatLength;

 //  serialOutput();
-  if (pulseFound == true && bpm <= maxBpm) {
+  if (pulseFound == true && pulseBpm <= maxBpm) {
 //    serialOutputWhenBeatHappens();
     bpm = pulseBpm;
     digitalWrite(CTRL_LED_RED_PIN, HIGH);


Added expandMiddle to actually implement the insertMiddle method.

--- Robot_Lights_Display/Robot_Lights_Display.ino
+++ Robot_Lights_Display/Robot_Lights_Display.ino
@@ -43,6 +43,7 @@
   for (int c = 50; c > 0; c--) {
     alternate(YELLOW, BLUE);
   }
+  expandMiddle(YELLOW, BLUE);
 }

 void rotatingCogs(CRGB colorOne, CRGB colorTwo) {
@@ -173,6 +174,21 @@
   }
 }

+void expandMiddle(CRGB colorOne, CRGB colorTwo) {
+  displayColor(colorTwo);
+  FastLED.show();
+  for (int i = 0; i < 10; i++) {
+    for (int c = 0; c < COG_SIZE; c++) {
+      insertMiddle(colorOne);
+      FastLED.show();
+    }
+    for (int c = 0; c < COG_SIZE; c++) {
+      insertMiddle(colorTwo);
+      FastLED.show();
+    }
+  }
+}
+
 //moves every led up one, and inserts colorIn at leds[0]
 void shiftUp(CRGB colorIn) {
   for (int i = (NUM_LEDS - 1); i > 0; i--) {


Added insertMiddle(colorIn)

Added insertMiddle(colorIn)

--- Robot_Lights_Display/Robot_Lights_Display.ino
+++ Robot_Lights_Display/Robot_Lights_Display.ino
@@ -159,6 +159,20 @@
   }
 }

+void insertMiddle(CRGB colorIn) {
+  for (int i = 0; i < (NUM_LEDS/2 - 1); i++) {
+    leds[i] = leds[i+1];
+    leds[NUM_LEDS - i - 1] = leds[NUM_LEDS - i - 2];
+  }
+  if ((NUM_LEDS & 1) == 1) {
+    leds[(NUM_LEDS - 1)/2] = colorIn;
+  }
+  else {
+    leds[NUM_LEDS/2 - 1] = colorIn;
+    leds[NUM_LEDS/2] = colorIn;
+  }
+}
+
 //moves every led up one, and inserts colorIn at leds[0]
 void shiftUp(CRGB colorIn) {
   for (int i = (NUM_LEDS - 1); i > 0; i--) {


Updatet ble_proximity_template

Updatet ble_proximity_template

--- libraries/BLE/examples/ble_proximity_template/ble_proximity_template.ino
+++ libraries/BLE/examples/ble_proximity_template/ble_proximity_template.ino
@@ -331,7 +331,12 @@

             case ACI_DEVICE_STANDBY:
               Serial.println(F("Evt Device Started: Standby"));
-              {
+              if (aci_evt->params.device_started.hw_error)
+              {
+                delay(20); //Magic number used to make sure the HW error event is handled correctly.
+              }
+              else
+              {
                 //Manage the bond in EEPROM of the AVR
                 {
                   uint8_t eeprom_status = 0;
@@ -353,7 +358,7 @@
                     }
                   }
                 }
-
+
                 // Start bonding as all proximity devices need to be bonded to be usable
                 if (ACI_BOND_STATUS_SUCCESS != aci_state.bonded)
                 {
@@ -383,8 +388,8 @@
           //all other ACI commands will have status code of ACI_STATUS_SCUCCESS for a successful command
           Serial.print(F("ACI Command "));
           Serial.println(aci_evt->params.cmd_rsp.cmd_opcode, HEX);
-          Serial.println(F("Evt Cmd respone: Error. Arduino is in an while(1); loop"));
-          while (1);
+          Serial.print(F("Evt Cmd respone: Status "));
+          Serial.println(aci_evt->params.cmd_rsp.cmd_status, HEX);
         }
         if (ACI_CMD_GET_DEVICE_VERSION == aci_evt->params.cmd_rsp.cmd_opcode)
         {
@@ -513,7 +518,54 @@
           aci_state.data_credit_available++;
         }
         break;
-
+
+      case ACI_EVT_HW_ERROR:
+        Serial.print(F("HW error: "));
+        Serial.println(aci_evt->params.hw_error.line_num, DEC);
+
+        for(uint8_t counter = 0; counter <= (aci_evt->len - 3); counter++)
+        {
+        Serial.write(aci_evt->params.hw_error.file_name[counter]); //uint8_t file_name[20];
+        }
+        Serial.println();
+
+                //Manage the bond in EEPROM of the AVR
+                {
+                  uint8_t eeprom_status = 0;
+                  eeprom_status = EEPROM.read(0);
+                  if (eeprom_status != 0x00)
+                  {
+                    Serial.println(F("Previous Bond present. Restoring"));
+                    Serial.println(F("Using existing bond stored in EEPROM."));
+                    Serial.println(F("   To delete the bond stored in EEPROM, connect Pin 6 to 3.3v and Reset."));
+                    Serial.println(F("   Make sure that the bond on the phone/PC is deleted as well."));
+                    //We must have lost power and restarted and must restore the bonding infromation using the ACI Write Dynamic Data
+                    if (ACI_STATUS_TRANSACTION_COMPLETE == bond_data_restore(&aci_state, eeprom_status, &bonded_first_time))
+                    {
+                      Serial.println(F("Bond restored successfully"));
+                    }
+                    else
+                    {
+                      Serial.println(F("Bond restore failed. Delete the bond and try again."));
+                    }
+                  }
+                }
+
+                // Start bonding as all proximity devices need to be bonded to be usable
+                if (ACI_BOND_STATUS_SUCCESS != aci_state.bonded)
+                {
+                  lib_aci_bond(180/* in seconds */, 0x0050 /* advertising interval 50ms*/);
+                  Serial.println(F("No Bond present in EEPROM."));
+                  Serial.println(F("Advertising started : Waiting to be connected and bonded"));
+                }
+                else
+                {
+                    //connect to an already bonded device
+                    //Use lib_aci_direct_connect for faster re-connections with PC, not recommended to use with iOS/OS X
+                    lib_aci_connect(100/* in seconds */, 0x0020 /* advertising interval 20ms*/);
+                    Serial.println(F("Already bonded : Advertising started : Waiting to be connected"));
+                }
+        break;

     }
   }


in example properly wait for NTP to be set (#4000)

fix #3905

--- libraries/ESP8266WiFi/examples/HTTPSRequestCACert/HTTPSRequestCACert.ino
+++ libraries/ESP8266WiFi/examples/HTTPSRequestCACert/HTTPSRequestCACert.ino
@@ -53,7 +53,7 @@
   Serial.print("Setting time using SNTP");
   configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov");
   time_t now = time(nullptr);
-  while (now < 1000) {
+  while (now < 8 * 3600 * 2) {
     delay(500);
     Serial.print(".");
     now = time(nullptr);


Removed secondary colour buffer to save RAM. Random colours are now created predicatably based random 32-bit seed.

--- arduino/ClockFOUR_TiM/LED_Display.ino
+++ arduino/ClockFOUR_TiM/LED_Display.ino
@@ -131,11 +131,9 @@
 	#define COLOUR_UPDATE	5		// Defines the rate at which the colour mode gets updated, in multiples of LETTER_FADE

 	static uint32_t lastRefresh = 0;
-
 	static uint8_t colourIteration = 0;
 	static int16_t fadeBrightness = 255;
 	static uint8_t colourUpdate = 0;
-	static uint8_t ledColours[MATRIX_WIDTH * MATRIX_HEIGHT * 3];

 	uint32_t currentMillis = millis();

@@ -172,24 +170,14 @@
 	// Loop through every LED
 	for(uint16_t pixIdx = 0; pixIdx < MATRIX_HEIGHT * MATRIX_WIDTH; pixIdx++) {

-		uint32_t pixColour = 0;
-
 		// Get the current pixel transition
 		PixelTransition pixTran = pixels.getPixel(pixIdx);
-
+
 		// Get the colour for the given pixel
+		uint32_t pixColour = 0;
+
 		if(pixTran != PIX_OFF) {
-			if(colourUpdate == 0) {
-				// Get new colour if we need to
-				pixColour = getPixColour(pixIdx, mode, colour, colourIteration);
-
-				ledColours[pixArrIdx] = (uint8_t)(pixColour >> 16);
-				ledColours[pixArrIdx + 1] = (uint8_t)(pixColour >>  8);
-				ledColours[pixArrIdx + 2] = (uint8_t)pixColour;
-			} else {
-				// Get the old colour
-				pixColour = strip.Color(ledColours[pixArrIdx], ledColours[pixArrIdx + 1], ledColours[pixArrIdx + 2]);
-			}
+			pixColour = getPixColour(pixIdx, mode, colour, colourIteration);
 		}

 		// Determine the pixel transitions
@@ -238,6 +226,26 @@

 // This function returns the colours of the different pixels given pixel index, colour mode, input colour and colour iteration
 inline uint32_t getPixColour(uint16_t pixIdx, uint8_t mode, uint32_t colour, uint8_t colourIteration)  {
+	static uint8_t prevIteration = 0;
+	static uint32_t randomSeed = 0;
+
+	uint32_t randomVal;
+
+	// Get a new random value whenever we enter a new iteration
+	if(prevIteration != colourIteration) {
+		randomSeed = random();
+		prevIteration = colourIteration;
+	}
+
+	// Perform a hashing operation based on the random seed and the pixIdx
+	randomVal = randomSeed + pixIdx;
+	randomVal += randomVal << 10;
+	randomVal ^= randomVal >> 6;
+	randomVal += randomVal << 3;
+	randomVal ^= randomVal >> 11;
+	randomVal += randomVal << 15;
+
+
 	switch(mode) {
 	case CM_ALL_WHITE:
 		return strip.Color(235,   255,   255);
@@ -256,7 +264,7 @@
 		break;

 	case CM_PARTY:
-		return wheel(random(0, 255));
+		return wheel(randomVal & 0xFF);
 		break;

 	default:


crash report message needs motor id!;

crash report message needs motor id!;

--- arduino/motor_driver/motor_driver.ino
+++ arduino/motor_driver/motor_driver.ino
@@ -273,6 +273,7 @@

 void setupWatchdog() {
   OscMessage msg("/crashreport");
+  msg.add(MOTOR_ID);
   ApplicationMonitor.Dump(msg);
   ApplicationMonitor.EnableWatchdog(Watchdog::CApplicationMonitor::Timeout_4s);
   etherOSC.send(msg, destination);


disconnect unused encoder pin Z from arduino pin 4

--- arduino/motor_driver/motor_driver.ino
+++ arduino/motor_driver/motor_driver.ino
@@ -60,7 +60,7 @@
 const byte encoder0PinAMask = 0x04;
 const int encoder0PinB = 3;  // black   PORTD BIT 3
 const byte encoder0PinBMask = 0x08;
-const int encoder0PinZ = 4;  // orange
+//const int encoder0PinZ = 4;  // orange
 volatile long encoder0Pos __attribute__ ((section (".noinit")));
 volatile long encoder0Checksum __attribute__ ((section (".noinit")));
 const long encoder0ChecksumKey = 314159265L;
@@ -107,6 +107,7 @@

 // NETWORK SETUP  -------
+const int SS_SD_CARD = 4; // chip select for sd card reader on ethernet card (keep high to disable)

 // get motor id (0 for NW motor, 1 for NE, 2 for SE, 3 for SW) from EEPROM address 0
 int MOTOR_ID = EEPROM.read(EEPROM_MOTOR_ID);
@@ -305,6 +306,9 @@

 void setupEthernet() {
+  pinMode(SS_SD_CARD, OUTPUT);
+  digitalWrite(SS_SD_CARD, 1);
+
   Ethernet.begin(mac,listeningIP);
   UDP.begin(listeningPort);
 }
@@ -342,7 +346,7 @@

   pinMode(encoder0PinA, INPUT);
   pinMode(encoder0PinB, INPUT);
-  pinMode(encoder0PinZ, INPUT);
+  //pinMode(encoder0PinZ, INPUT);
   // encoder pin on interrupt 0 (pin 2)
   attachInterrupt(0, doEncoderA, RISING);


Added support for Raspberry PI remote control.

--- arduino/motion/src/drive/drive.ino
+++ arduino/motion/src/drive/drive.ino
@@ -25,6 +25,8 @@
 const int SPEED_FASTEST=70;
 const int SPEED_RIDICULOUS=70;
 const int SPEED_LUDICROUS=80;
+const int NO_ROTATION=0;
+const int YES_ROTATION=1;
 const int compassI2CAddress=0x1E;
 const int ultrasonicRangeFinderPin= 4;
 const float pi=3.14159;
@@ -33,9 +35,14 @@
 int ch1; // Here's where we'll keep our channel values
 int ch2;
 int ch3;
+int ch4;

 float lastHeading=-2;
 float lastRange=-1;
+float persistantBias=0;
+int persistantDirection=0;
+int persistantSpeed=0;
+int persistantRotation=0;

 void setup() {
   // Megamoto
@@ -53,6 +60,7 @@
   pinMode(5, INPUT); // Set our input pins as such
   pinMode(6, INPUT);
   pinMode(7, INPUT);
+  pinMode(2, INPUT);

   // Set up compass
   Wire.begin();
@@ -68,6 +76,7 @@
 }

 void loop() {
+  //Serial.println(".");
   // To drive the motor in H-bridge mode
   // the power chip inputs must be opposite polarity
   // and the Enable input must be HIGH
@@ -89,49 +98,55 @@
   ch1 = pulseIn(5, HIGH, 25000); // Read the pulse width of
   ch2 = pulseIn(6, HIGH, 25000); // each channel
   ch3 = pulseIn(7, HIGH, 25000);
+  ch4 = pulseIn(2, HIGH, 25000);
   float bias=0;
-  //Serial.print("CH3=");Serial.println(ch3);
-  if(ch3<1500&&ch3>1490)
+  //Serial.print("CH$=");Serial.println(ch4);
+  if(ch4<1500&&ch3>1490)
     bias=0;
-  if(ch3<=1490)
+  if(ch4<=1490)
     bias=-((ch3-1490)/190.0)*0.8;
-  if(ch3>=1500)
+  if(ch4>=1500)
     bias=((ch3-1500)/200.0)*0.8;
-  //Serial.print("Bias=");Serial.println(bias);
+//  Serial.print("persistantSpeed=");Serial.println(persistantSpeed);

   if(ch1<996){ // This sets SWB as the master motor cut off
-    controlMotor(0,0,bias);
+    if(persistantSpeed>0)
+      if(currentRange>10.0)
+        controlMotor(persistantSpeed,persistantDirection,persistantBias,persistantRotation);
+    else {
+      controlMotor(0,0,bias,NO_ROTATION);
+    }
   } else {
      if(ch2<1400){
-        controlMotor(SPEED_FASTER,DIRECTION_BACKWARD,bias);
+        controlMotor(SPEED_FASTER,DIRECTION_BACKWARD,bias,NO_ROTATION);
      }
      if(ch2>=1400&&ch2<1425){
-        controlMotor(SPEED_FAST,DIRECTION_BACKWARD,bias);
+        controlMotor(SPEED_FAST,DIRECTION_BACKWARD,bias,NO_ROTATION);
       }
       if(ch2>=1425&&ch2<1450){
-          controlMotor(SPEED_SLOW,DIRECTION_BACKWARD,bias);
+          controlMotor(SPEED_SLOW,DIRECTION_BACKWARD,bias,NO_ROTATION);
       }
       if(ch2>=1450&&ch2<1500){
-        controlMotor(0,DIRECTION_STOP,bias);
+        controlMotor(0,DIRECTION_STOP,bias,NO_ROTATION);
       }
       if(currentRange>12.0){
         if(ch2>=1500&&ch2<1525){
-            controlMotor(SPEED_SLOW,DIRECTION_FORWARD,bias);
+            controlMotor(SPEED_SLOW,DIRECTION_FORWARD,bias,NO_ROTATION);
         }
         if(ch2>=1525&&ch2<1550){
-            controlMotor(SPEED_FAST,DIRECTION_FORWARD,bias);
+            controlMotor(SPEED_FAST,DIRECTION_FORWARD,bias,NO_ROTATION);
          }
          if(ch2>=1550&&ch2<1575){
-            controlMotor(SPEED_FASTER,DIRECTION_FORWARD,bias);
+            controlMotor(SPEED_FASTER,DIRECTION_FORWARD,bias,NO_ROTATION);
          }
          if(ch2>=1575&&ch2<1600){
-            controlMotor(SPEED_FASTEST,DIRECTION_FORWARD,bias);
+            controlMotor(SPEED_FASTEST,DIRECTION_FORWARD,bias,NO_ROTATION);
          }
          if(ch2>=1600&&ch2<1625){
-            controlMotor(SPEED_RIDICULOUS,DIRECTION_FORWARD,bias);
+            controlMotor(SPEED_RIDICULOUS,DIRECTION_FORWARD,bias,NO_ROTATION);
          }
          if(ch2>=1625){
-            controlMotor(SPEED_LUDICROUS,DIRECTION_FORWARD,bias);
+            controlMotor(SPEED_LUDICROUS,DIRECTION_FORWARD,bias,NO_ROTATION);
          }
        }

@@ -153,8 +168,7 @@
   return 1;
 }

-void controlMotor(int speed,int direction,float bias){
-
+void controlMotor(int speed,int direction,float bias,int rotate){
   int biasSpeedL=0.0;
   int biasSpeedR=0.0;
   if(bias==0){
@@ -173,29 +187,56 @@
 //  Serial.print("Speed=");Serial.println(speed);
 //  Serial.print("L=");Serial.println(biasSpeedL);
 //  Serial.print("R=");Serial.println(biasSpeedR);
-
-  if(direction==0){
-    // Stop the motor fast
-    speed=0;
-    analogWrite(PWMPin, 0);
-    analogWrite(PWMPinA, 0);
-    analogWrite(PWMPin2, 0);
-    analogWrite(PWMPinA2, 0);
-    digitalWrite(EnablePin, LOW);
-  } if(direction>0){
-    // Forward
-    analogWrite(PWMPin, biasSpeedL);
-    analogWrite(PWMPinA, biasSpeedR);
-    analogWrite(PWMPin2, 0);
-    analogWrite(PWMPinA2, 0);
-    digitalWrite(EnablePin, HIGH);
+  if(rotate==0){
+    if(direction==0){
+      // Stop the motor fast
+      speed=0;
+      analogWrite(PWMPin, 0);
+      analogWrite(PWMPinA, 0);
+      analogWrite(PWMPin2, 0);
+      analogWrite(PWMPinA2, 0);
+      digitalWrite(EnablePin, LOW);
+    } if(direction>0){
+      // Forward
+      analogWrite(PWMPin, biasSpeedL);
+      analogWrite(PWMPinA, biasSpeedR);
+      analogWrite(PWMPin2, 0);
+      analogWrite(PWMPinA2, 0);
+      digitalWrite(EnablePin, HIGH);
+    } else {
+      // Backward
+      analogWrite(PWMPin, 0);
+      analogWrite(PWMPinA, 0);
+      analogWrite(PWMPin2, biasSpeedL);
+      analogWrite(PWMPinA2,biasSpeedR);
+      digitalWrite(EnablePin, HIGH);
+    }
   } else {
-    // Backward
-    analogWrite(PWMPin, 0);
-    analogWrite(PWMPinA, 0);
-    analogWrite(PWMPin2, biasSpeedL);
-    analogWrite(PWMPinA2,biasSpeedR);
-    digitalWrite(EnablePin, HIGH);
+    // Rotation makes wheels always run in opposite directions
+    if(direction==0){
+      // Stop the motor fast
+      speed=0;
+      analogWrite(PWMPin, 0);
+      analogWrite(PWMPinA,0);
+      analogWrite(PWMPin2, 0);
+      analogWrite(PWMPinA2, 0);
+      digitalWrite(EnablePin, LOW);
+    } if(rotate>0){
+      // Left
+      //Serial.println("lf");
+      analogWrite(PWMPin, 30);
+      analogWrite(PWMPinA, 0);
+      analogWrite(PWMPin2, 0);
+      analogWrite(PWMPinA2,30);
+      digitalWrite(EnablePin, HIGH);
+    } if(rotate<0) {
+      // Backward
+      analogWrite(PWMPin, 0);
+      analogWrite(PWMPinA,30 );
+      analogWrite(PWMPin2,30);
+      analogWrite(PWMPinA2,0);
+      digitalWrite(EnablePin, HIGH);
+    }
   }
 }

@@ -366,33 +407,54 @@
       String direction=(String(rotate->valuestring));
       float bias=0;
       if(direction.equals("LEFT")){
-        bias=1;
-        controlMotor(SPEED_SLOW,DIRECTION_FORWARD,bias);
+        persistantSpeed=SPEED_FAST;
+        persistantDirection=DIRECTION_FORWARD;
+        persistantBias=0.5;
+        persistantRotation=YES_ROTATION;
       } else {
-        bias=-1;
-        controlMotor(SPEED_SLOW,DIRECTION_FORWARD,bias);
+        persistantSpeed=SPEED_FAST;
+        persistantDirection=DIRECTION_FORWARD;
+        persistantBias=-0.5;
+        persistantRotation=-1;
       }
-      Serial.println("{\"response\":\"OK\"}");
+      Serial.println("{\"response\":\"OK rotate\"}");
+    }
+    if (goforward->type == aJson_Int) {
+      int aspeed=goforward->valueint;
+      persistantSpeed=aspeed;
+      persistantDirection=DIRECTION_FORWARD;
+      persistantBias=0;
+      persistantRotation=NO_ROTATION;
+      Serial.println("{\"response\":\"OK goforward\"}");
     }

-   if (goforward->type == aJson_String) {
-      //lcd.print(String(line2->valuestring));
-      float bias=0;
-      controlMotor(SPEED_SLOW,DIRECTION_FORWARD,bias);
-      Serial.println("{\"response\":\"OK\"}");
-    }
+    if (gobackward->type == aJson_Int) {
+      int aspeed=gobackward->valueint;
+      persistantSpeed=aspeed;
+      persistantDirection=DIRECTION_BACKWARD;
+      persistantBias=0;
+      persistantRotation=NO_ROTATION;
+     Serial.println("{\"response\":\"OK gobackward\"}");
+    }
+

     if (gobackward->type == aJson_String) {
       //lcd.print(String(line3->valuestring));
-      float bias=0;
-      controlMotor(SPEED_SLOW,DIRECTION_FORWARD,bias);
-      Serial.println("{\"response\":\"OK\"}");
+      persistantSpeed=SPEED_FAST;
+      persistantDirection=DIRECTION_BACKWARD;
+      persistantBias=0;
+      persistantRotation=NO_ROTATION;
+     Serial.println("{\"response\":\"OK gobackward\"}");
     }

     if (stopnow->type == aJson_True) {
       float bias=0;
-      controlMotor(0,DIRECTION_STOP,bias);
-      Serial.println("{\"response\":\"OK\"}");
+      controlMotor(0,DIRECTION_STOP,bias,NO_ROTATION);
+      persistantSpeed=SPEED_STOP;
+      persistantDirection=DIRECTION_STOP;
+      persistantBias=0;
+      persistantRotation=NO_ROTATION;
+      Serial.println("{\"response\":\"OK stopnow\"}");
     }
 }


some simple savings, prepping for better explosions

--- arduboy-game/arduboy-game.ino
+++ arduboy-game/arduboy-game.ino
@@ -79,6 +79,11 @@
 // General purpose text buffer for string concatenation and read from progmem
 char textBuf[23];

+void display() {
+  arduboy.display();
+}
+
+
 void playMusic(byte song) {
     if (! soundOn) {
       return;
@@ -135,7 +140,7 @@
 //  arduboy.fillRect(10,54, 128, 64,1);
 //
 //  drawBitmap(10, 16, moduslogo_graffiti_small, 0);
-  arduboy.display();
+  display();

   arduboy.initRandomSeed();

@@ -147,6 +152,7 @@
 void drawRectAroundPlayMenuOption(byte color) {
   arduboy.drawRect(2, 48, 28, 12, color);
 }
+

 byte titleScreen() {
   byte selectedItem = TITLE_PLAY_GAME;
@@ -166,12 +172,12 @@
   drawBitmap(93, 14, title_planet, 0);

-  drawChrs(4, 51, titleScreenText1, 30);
+  drawChrs(4,  51, titleScreenText1, 30);
   drawChrs(34, 51, titleScreenText2, 30);
   drawChrs(79, 51, titleScreenText3, 30);
 //  arduboy.drawRect(2, 48, 28, 12, 1);
   drawRectAroundPlayMenuOption(1);
-  arduboy.display();
+  display();

 //  playMusic(5);

@@ -234,7 +240,7 @@
       arduboy.drawRect(77, 48, 50, 12, 0);
 //      arduboy.drawRect(32, 48, 42, 12, 1);
       drawRectAroundSettingsMenuOption(1);
-      arduboy.display();
+      display();
       return TITLE_CREDITS;
       break;

@@ -244,7 +250,7 @@
 //      arduboy.drawRect(2, 48, 28, 12, 1);
       drawRectAroundPlayMenuOption(1);

-      arduboy.display();
+      display();
       return  TITLE_PLAY_GAME;
       break;

@@ -266,14 +272,14 @@

 //      arduboy.drawRect(32, 48, 42, 12, 1);
       drawRectAroundSettingsMenuOption(1);
-      arduboy.display();
+      display();
       return TITLE_CREDITS;
       break;

     case TITLE_CREDITS:
       arduboy.drawRect(32, 48, 42, 12, 0);
       arduboy.drawRect(77, 48, 50, 12, 1);
-      arduboy.display();
+      display();
       return TITLE_SETTINGS;
       break;

@@ -300,7 +306,7 @@
     printText(textBuf, 15, 26 + (12 * i), 1);
   }

-  arduboy.display();
+  display();

   unsigned long lastDebounceTime = millis();

@@ -342,7 +348,7 @@
         curs += pgm_read_byte(alphabet[letter]) + 1;
     }

-    arduboy.display();
+    display();

     if (delayTimer) {
       playTone(100, delayTimer - 10);
@@ -426,7 +432,7 @@
           default: break;
         }

-        arduboy.display();
+        display();
         delay(250);
         lastDebounceTime = currentMilliseconds; //set the current time
       }
@@ -446,7 +452,7 @@
           selectedItem = SETTINGS_SOUND;
         }

-        arduboy.display();
+        display();
         delay(250);
         lastDebounceTime = currentMilliseconds; //set the current time
       }
@@ -476,13 +482,13 @@
           default: break;
         }

-        arduboy.display();
+        display();
         delay(250);

         lastDebounceTime = currentMilliseconds; //set the current time
       }

-//      arduboy.display();
+//      display();
       delay(15);
     }

@@ -597,7 +603,7 @@
     drawStarLayer();
     drawLives();

-    arduboy.display();
+    display();

     updateStarFieldVals();

@@ -871,7 +877,7 @@

   printText("GAME", 50, 5, 3);
   printText("OVER", 50, 33, 3);
-  arduboy.display();
+  display();

   playMusic(4);
   delay(4500);
@@ -909,7 +915,7 @@
   printText(textBuf, 44, 45, 2);
   drawHighScoreEntryCursor(currPos);

-  arduboy.display();
+  display();

   while(! allDone) {
     unsigned long currentMilliseconds = millis();
@@ -968,7 +974,7 @@
           printText(textBuf, 44, 45, 2);
           lastDebounceTime = currentMilliseconds;
        }
-       arduboy.display();
+       display();

     }
   }


Initial grouping of like functions in main sketch.

--- arduboy-game/arduboy-game.ino
+++ arduboy-game/arduboy-game.ino
@@ -40,13 +40,9 @@
     playerGunCharge = MAX_GUN_CHARGE;
 }

-void display() {
-  arduboy.display();
-}
-
-void stopMusic(){
-  arduboy.tunes.stopScore();
-}
+/*******************************************************************************
+ * MUSIC / SOUNDS                                                              *
+ *******************************************************************************/

 void playMusic(byte song) {
     if (! soundOn) {
@@ -80,7 +76,19 @@
     if (! arduboy.tunes.playing()) {
       arduboy.tunes.playScore(music);
     }
-}
+}
+
+void stopMusic(){
+  arduboy.tunes.stopScore();
+}
+
+bool shouldPlayAButtonTone() {
+  return (inGameAButtonLastPress > (inGameFrame - 20));
+}
+
+bool shouldPlayBButtonTone() {
+  return (inGameBButtonLastPress > (inGameFrame - 50));
+}

 void redAlert() {
   arduboy.clear();
@@ -114,12 +122,59 @@
   }
 }

+/*******************************************************************************
+ * UTILITY FUNCTIONS                                                           *
+ *******************************************************************************/
+
+void display() {
+  arduboy.display();
+}
+
 void printText(char *message, byte x, byte y, byte textSize) {
   arduboy.setCursor(x, y);
   arduboy.setTextSize(textSize);
   arduboy.print(message);
 }

+void delayAndDisplay() {
+  delay(250);
+  display();
+}
+
+void drawChrs(byte cPos, byte yPos, const uint8_t *letters, unsigned long delayTimer) {
+  byte curs = cPos,
+       strLen = pgm_read_byte(letters),
+       letter;
+
+  for (byte i = 0; i <  strLen; i++) {
+    letter = pgm_read_byte(++letters);
+
+    // Space chr
+    if (letter == 255) {
+       curs += 5;
+    }
+    else {
+        drawBitmap(curs,yPos, alphabet[letter], 0);
+        curs += pgm_read_byte(alphabet[letter]) + 1;
+    }
+
+    display();
+
+    if (delayTimer) {
+      playTone(100, delayTimer - 10);
+      delay(delayTimer);
+    }
+  }
+
+  if (delayTimer) {
+      playTone(800, 15);
+      delay(15);
+      playTone(1200, 30);
+      delay(40);
+  }
+}
+
+
 void introScreen() {
   arduboy.clear();
   drawBitmap(2, 8, modusLogo, 0);
@@ -136,10 +191,6 @@
   arduboy.drawRect(2, 48, 28, 12, color);
 }

-void delayAndDisplay() {
-  delay(250);
-  display();
-}

 byte titleScreen() {
   arduboy.clear();
@@ -309,39 +360,6 @@
       totalDelay += 15;
     }
   }
-}
-
-void drawChrs(byte cPos, byte yPos, const uint8_t *letters, unsigned long delayTimer) {
-  byte curs = cPos,
-       strLen = pgm_read_byte(letters),
-       letter;
-
-  for (byte i = 0; i <  strLen; i++) {
-    letter = pgm_read_byte(++letters);
-
-    // Space chr
-    if (letter == 255) {
-       curs += 5;
-    }
-    else {
-        drawBitmap(curs,yPos, alphabet[letter], 0);
-        curs += pgm_read_byte(alphabet[letter]) + 1;
-    }
-
-    display();
-
-    if (delayTimer) {
-      playTone(100, delayTimer - 10);
-      delay(delayTimer);
-    }
-  }
-
-  if (delayTimer) {
-      playTone(800, 15);
-      delay(15);
-      playTone(1200, 30);
-      delay(40);
-  }
 }

 void creditsScreen() {
@@ -1026,15 +1044,10 @@
   }
 }

-bool shouldPlayAButtonTone() {
-  return (inGameAButtonLastPress > (inGameFrame - 20));
-}
-
-bool shouldPlayBButtonTone() {
-  return (inGameBButtonLastPress > (inGameFrame - 50));
-}
-
-// Initialization runs once only
+/*******************************************************************************
+ * ENTRY POINTS                                                                *
+ *******************************************************************************/
+
 void setup() {
   arduboy.beginNoLogo();

@@ -1086,7 +1099,6 @@
   alphabet[28] = exclamation;
 }

-// Main program loop
 void loop() {
   byte newHiScorePos;


Restores attract mode title/hi score loop.

--- arduboy-game/arduboy-game.ino
+++ arduboy-game/arduboy-game.ino
@@ -157,7 +157,7 @@

 byte titleScreen() {
   byte selectedItem = TITLE_PLAY_GAME;
-  unsigned short totalDelay = 0;
+  unsigned long totalDelay = 0;
   long lastDebounceTime = millis();  // the last time the button was pressed

   arduboy.clear();
@@ -203,8 +203,6 @@
       }
     }

-
-//    delay(40);
     totalDelay ++;

   }