Some variables optimized, added method for printing on LCD

--- Rubiks_cube_sketch/Rubiks_cube_sketch.ino
+++ Rubiks_cube_sketch/Rubiks_cube_sketch.ino
@@ -12,6 +12,17 @@
 #define S3 12
 #define scanSensor 13

+//Default motors movements limits
+#define minAngleMotor1 0    // minimum limit fur turning
+#define maxAngleMotor1 179  // maximum limit for turning
+#define minAngleMotor2 95   // minimum limit fur turning
+#define maxAngleMotor2 135  // maximum limit for turning
+#define minAngleMotor3 45   // minimum limit fur turning
+#define maxAngleMotor3 95   // maximum limit for turning
+#define minAngleMotor4 35   // minimum limit fur turning
+#define maxAngleMotor4 98   // maximum limit for turning
+#define standardDelay 200   // standard delay for motor movement
+
 //Including libraries
 #include <Servo.h>
 #include <MsTimer2.h>
@@ -22,18 +33,18 @@
 //Defining variables

 //Initialize the variables for color frequences
-int frequency = 0;
-int f_RED = 0;
-int f_GREEN = 0;
-int f_BLUE = 0;
+byte frequency = 0;
+byte f_RED = 0;
+byte f_GREEN = 0;
+byte f_BLUE = 0;

 //Calibration matrix
 byte f[][6] = {{13, 19, 14, 25, 11, 16},         //white
                {12, 21, 18, 23, 22, 27},         //yellow
                {13, 19, 27, 37, 24, 33},         //orange
                {20, 25, 36, 42, 28, 35},         //red
-               {30, 35, 25, 33, 27, 36},         //green
-               {36, 44, 34, 43, 22, 28}          //blue
+               {30, 35, 25, 32, 27, 36},         //green
+               {34, 44, 33, 43, 20, 26}          //blue
                };

 //Default motors positions
@@ -42,31 +53,29 @@
 byte motor_3_Position = 89;
 byte motor_4_Position = 34;

-//Default motors movements limits
-byte minAngleMotor1 = 0;   // minimum limit fur turning
-byte maxAngleMotor1 = 179; // maximum limit for turning
-byte minAngleMotor2 = 95;  // minimum limit fur turning
-byte maxAngleMotor2 = 135; // maximum limit for turning
-byte minAngleMotor3 = 45;  // minimum limit fur turning
-byte maxAngleMotor3 = 95;  // maximum limit for turning
-byte minAngleMotor4 = 35;  // minimum limit fur turning
-byte maxAngleMotor4 = 98;  // maximum limit for turning

 //Flags
-//volatile boolean leftButtonIsPressed = false;
-//volatile boolean rightButtonIsPressed = false;
 volatile char pressedButton;
+volatile byte selectedButton;
 volatile boolean operateFlag = true;
+boolean serialOutput = false;

 //Data arrays and matrixes
 //Arrays for color scanning
-byte Motor_1_ScanAngles [] = {44, 85, 120, 4, 4, 168, 134, 96, 58};
-byte Motor_4_ScanAngles [] = {71, 74, 70, 74, 82, 73, 94, 90, 94};
-String SideScanResult [9];
-String ScannedCube = "";
+byte Motor_1_ScanAngles [9] = {44, 85, 120, 4, 4, 168, 134, 96, 58};
+byte Motor_4_ScanAngles [9] = {71, 74, 70, 74, 82, 73, 94, 90, 94};
+//Arrays for side and cube scanning
+char SideScanResult [10];
+char ScannedCube [55];
 String SolvedCube = "";
-
+//Other global variables
+byte cubeCounter;
+char string1LCD [17];
+char string2LCD [17];
+
+//Constants
+const char defaultLCDstring [17] = "                ";

 //Class that defines the button as object
 class Button {
@@ -99,22 +108,12 @@
 //Setup method
 void setup() {
   // Initializing pins modes
-  pinMode(A0, INPUT);
-  pinMode(A1, INPUT);
-  pinMode(A2, INPUT);
-  pinMode(A3, INPUT);
   pinMode(S0, OUTPUT);
   pinMode(S1, OUTPUT);
   pinMode(S2, OUTPUT);
   pinMode(S3, OUTPUT);
   pinMode(scanSensor, INPUT);

-  //Initializing buttons
-  //leftButton.setPinTime(leftButtonPin, 15);
-  //rightButton.setPinTime(rightButtonPin, 15);
-  //pinMode(leftButtonPin, INPUT_PULLUP);
-  //pinMode(rightButtonPin, INPUT_PULLUP);
-
   //Attaching the motors
   Motor1.attach(rotateMotorPin);
   Motor2.attach(carriageMotorPin);
@@ -125,13 +124,13 @@
   Serial.begin(9600);

   turnMotor1(89, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor3(90, 2);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(105, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor4(35, 7);
-  delay(200);
+  delay(standardDelay);

   // Initialise interruption pins
   //attachInterrupt (0, leftButtonPressed, RISING);
@@ -152,25 +151,15 @@
 //Main operation method
 void loop() {

-  char startOption = selectOption("Select mode", "Solve  Calibrate", "Solve", "       Calibrate");
-  if (startOption == 1) calibrationScan();
-  else {
-    char solvingMode = selectOption("Solving mode?", "Python   Arduino", "Python", "         Arduino");
-    if (solvingMode == 0) {
-      pythonSolveOperation();
-    }
-    else {
-      delay(5000);
-      //arduinoSolveOperation();
-    }
-  }
+  normalFlow();
+
   //solveOrCaliblate();

   //operateOrNot();

   //scanCube();
-  //ScannedCube = "oobwwrbbboboybobwwyyybrrggwrrryyggogwrrggwooywggwoyrby";
-
+
+  //verifyScannedCube();
   //writePortData();
   //delay(500);

@@ -197,12 +186,42 @@
 /////////////////////////////////////////////////METHODS FOR DESCRIBING OPERATION FLOWS///////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

+//Method for normal flow operation
+void normalFlow() {
+  selectedButton = selectOption(F("Select mode"), F("Solve  Calibrate"), F("Solve"), F("       Calibrate"));
+  if (selectedButton == 1) calibrateOptions();
+  else solvingOptions();
+}
+
+
+//Method for selecting the scanning option
+void calibrateOptions() {
+  selectedButton = selectOption(F("Calibrate"), F("Side        Cube"), F("Side"), F("            Cube"));
+  if (selectedButton == 0) {
+    scanNewSide:
+    serialOutput = true;
+    calibrationScan();
+    serialOutput = false;
+    selectedButton = selectOption(F("Scan other side?"), F(" Yes        Back"), F(" Yes"), F("           Back"));
+    if (selectedButton == 0) goto scanNewSide;
+    else normalFlow();      //arduinoSolveOperation();
+  }
+  else calibrationScan();
+}
+
+
+//Method for selecting the solving mode
+void solvingOptions() {
+  selectedButton = selectOption(F("Solving mode?"), F("Python   Arduino"), F("Python"), F("         Arduino"));
+  if (selectedButton == 0) pythonSolveOperation();
+  else delay(5000);      //arduinoSolveOperation();
+}
+
+
 //Method for general process of solving the cube via Python
 void pythonSolveOperation() {
-  attachInterrupt (0, leftButtonPressed, FALLING);
   operateFlag = true;
   scanCube();
-
   detachInterrupt(0);
 }

@@ -213,7 +232,6 @@
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////METHODS FOR MANAGING INTERRUPTIONS AND OPERATION/////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-

 //Method for defining which button was pressed
@@ -259,14 +277,14 @@
   pinMode(_pin, INPUT);
 }

-
+/*
 //Method from class Button for setting the buttons
 void Button::setPinTime(byte pin, byte timeButton)  {
   _pin= pin;
   _timeButton= timeButton;
   pinMode(_pin, INPUT);
 }
-
+*/

 //Method for dealing with timer interruption
 void  timerInterupt() {
@@ -282,7 +300,7 @@

 //Method for showing possible options and pressing the button
-int selectOption(String title, String options, String opt_1, String opt_2) {
+byte selectOption(String title, String options, String opt_1, String opt_2) {
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print(title);
@@ -308,11 +326,9 @@
 void resumeOrRestart() {
   //detachInterrupt(0);
   if (operateFlag == false) {
-    char continueOption = selectOption("Operation paused", "Resume   Restart", "Resume", "         Restart");
-  if (continueOption == 0) {
-    lcd.clear();
-    lcd.setCursor(0, 0);
-    lcd.print("Resuming...");
+    selectedButton = selectOption(F("Operation paused"), F("Resume     Reset"), F("Resume"), F("           Reset"));
+  if (selectedButton == 0) {
+    printLCD();
     operateFlag = true;
     //attachInterrupt (0, leftButtonPressed, RISING);

@@ -320,7 +336,7 @@
   else {
     lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Resetting...");
+    lcd.print(F("Resetting..."));
     delay(1000);
     resetFunc();
   }
@@ -328,7 +344,38 @@

 }

-
+//Method for saving the current string displayed on LCD
+void storeLCD(String text, byte row) {
+  if (row == 0) {
+    for (byte i=0; i<16; i++) {
+      string1LCD[i] = defaultLCDstring[i];
+      string1LCD[i] = text[i];
+      }
+  }
+  else if (row == 1) {
+    for (byte i=0; i<16; i++) {
+      string2LCD[i] = defaultLCDstring[i];
+      string2LCD[i] = text[i];
+      }
+  }
+  else if (row == 2) {
+    for (byte i=0; i<=sizeof(text); i++) {
+      if (text[i] != ' ') {
+        string2LCD[i] = text[i];
+        }
+      }
+  }
+  printLCD();
+}
+
+//Method for printing saved strings to LCD
+void printLCD() {
+  lcd.clear();
+  lcd.setCursor(0, 0);
+  lcd.print(string1LCD);
+  lcd.setCursor(0, 1);
+  lcd.print(string2LCD);
+}

 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -339,11 +386,11 @@
 void readPortData() {
   lcd.clear();
   lcd.setCursor(0, 0);
-  lcd.print("Waiting for data");
+  lcd.print(F("Waiting for data"));
   lcd.setCursor(0, 1);
-  lcd.print("from Python...");
+  lcd.print(F("from Python..."));
   String DataLength = "";
-  long PortTimeout = millis();
+  int PortTimeout = millis();
   String PortReadyFlag = "";
   do {
     PortReadyFlag = "";
@@ -356,7 +403,7 @@

   lcd.clear();
   lcd.setCursor(0, 0);
-  lcd.print("Receiving data..");
+  lcd.print(F("Receiving data.."));
   delay(100);

   PortTimeout = millis();
@@ -371,7 +418,7 @@

   lcd.clear();
   lcd.setCursor(0, 0);
-  lcd.print("Verifying data..");
+  lcd.print(F("Verifying data.."));
   delay(100);

   PortTimeout = millis();
@@ -387,14 +434,14 @@
   if (DataLength.toInt() == SolvedCube.length()) {
     lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Data received");
+    lcd.print(F("Data received"));
     lcd.setCursor(0, 1);
-    lcd.print("successfully");
+    lcd.print(F("successfully"));
     }
   else {
     lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Error, try again");
+    lcd.print(F("Error, try again"));
     }

   PortTimeout = millis();
@@ -402,9 +449,9 @@
     if ((millis() - PortTimeout) >= 10000) {
     lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Timeout error");
+    lcd.print(F("Timeout error"));
     lcd.setCursor(0, 1);
-    lcd.print("try again");
+    lcd.print(F("try again"));
     }
 }

@@ -412,13 +459,13 @@
 void writePortData() {
   lcd.clear();
   lcd.setCursor(0, 0);
-  lcd.print("Waiting for");
+  lcd.print(F("Waiting for"));
   lcd.setCursor(0, 1);
-  lcd.print("connection...");
+  lcd.print(F("connection..."));
   Serial.print("ready");

   String PortReadyFlag = "";
-  long PortTimeout = millis();
+  int PortTimeout = millis();
   do {
     PortReadyFlag = "";
     while (Serial.available()) {
@@ -431,7 +478,7 @@

   lcd.clear();
   lcd.setCursor(0, 0);
-  lcd.print("Sending data...");
+  lcd.print(F("Sending data..."));
   delay(100);
   Serial.print(ScannedCube);

@@ -449,23 +496,23 @@
   if (PortReadyFlag == "ok") {
     lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Data sent");
+    lcd.print(F("Data sent"));
     lcd.setCursor(0, 1);
-    lcd.print("successfully");
+    lcd.print(F("successfully"));
     }
   else {
     lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Error, try again");
+    lcd.print(F("Error, try again"));
     }
   PortTimeout = millis();
   Timeout:
     if ((millis() - PortTimeout) >= 10000) {
     lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Timeout error");
+    lcd.print(F("Timeout error"));
     lcd.setCursor(0, 1);
-    lcd.print("try again");
+    lcd.print(F("try again"));
     }
 }
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -475,41 +522,29 @@
 //Method for scanning the cube
 void scanCube() {
   operateFlag = true;
-  ScannedCube = "";
+  cubeCounter = 0;
   //Print process on LCD
-  lcd.clear();
-  lcd.setCursor(0, 0);
-  lcd.print("Scanning cube");
-  lcd.setCursor(0, 1);
-  lcd.print("Side      of 6");
-  lcd.setCursor(5, 1);
-  lcd.print("1(U)");
-
+  storeLCD(F("Scanning cube"), 0);
+  storeLCD(F("Side 1(U) of 6"), 1);
+
   scanTopSide();
-  addSideToScanCubeString(SideScanResult);

   push();
   turnCubeCW();
   push();
   turnCubeStraight();
-  lcd.setCursor(5, 1);
-  lcd.print("2(R)");
+  storeLCD(F("     2(R)"), 2);
   scanTopSide();
-  addSideToScanCubeString(SideScanResult);

   turnCubeCCW();
   push();
   turnCubeStraight();
-  lcd.setCursor(5, 1);
-  lcd.print("3(F)");
+  storeLCD(F("     3(F)"), 2);
   scanTopSide();
-  addSideToScanCubeString(SideScanResult);
-
-  push();
-  lcd.setCursor(5, 1);
-  lcd.print("4(D)");
+
+  push();
+  storeLCD(F("     4(D)"), 2);
   scanTopSide();
-  addSideToScanCubeString(SideScanResult);

   push();
   push();
@@ -517,18 +552,14 @@
   turnCubeCCW();
   push();
   turnCubeStraight();
-  lcd.setCursor(5, 1);
-  lcd.print("5(L)");
+  storeLCD(F("     5(L)"), 2);
   scanTopSide();
-  addSideToScanCubeString(SideScanResult);

   turnCubeCCW();
   push();
   turnCubeStraight();
-  lcd.setCursor(5, 1);
-  lcd.print("6(B)");
+  storeLCD(F("     6(B)"), 2);
   scanTopSide();
-  addSideToScanCubeString(SideScanResult);

   turnCubeCW();
   push();
@@ -538,12 +569,30 @@
   push();
   push();

-  verifyScannedCube(ScannedCube);
-
-}
+  verifyScannedCube();
+  Serial.println(ScannedCube); /////////////////////////////////////////////////////////////////////////////////
+
+}
+
+
+//Method for vefirying the scanned cube side
+void verifyScannedSide() {
+  boolean sideOK = true;
+  for (byte i=0; i<9; i++) {
+    if (SideScanResult[i] == 'X') sideOK = false;
+  }
+  if (sideOK == false) {
+    selectedButton = selectOption(F("Side scan error"), F("Repeat   Restart"), F("Repeat"), F("         Restart"));
+  if (selectedButton == 0) scanTopSide();
+  else normalFlow();
+  }
+  else addSideToScanCubeString();
+}
+
+

 //Method for verifying whether the cube was scanned correctly
-void verifyScannedCube(String scannedCube) {
+void verifyScannedCube() {
   boolean scanErrorFlag = false;
   byte w_count = 0;
   byte y_count = 0;
@@ -551,55 +600,57 @@
   byte r_count = 0;
   byte g_count = 0;
   byte b_count = 0;
-  if (scannedCube.length() != 54) {scanErrorFlag = true;}
-  else {
-    for (byte i=0; i<54; i++) {
-      if (String(scannedCube[i]) == "w") {w_count++;}
-      else if (String(scannedCube[i]) == "y") {y_count++;}
-      else if (String(scannedCube[i]) == "o") {o_count++;}
-      else if (String(scannedCube[i]) == "r") {r_count++;}
-      else if (String(scannedCube[i]) == "g") {g_count++;}
-      else if (String(scannedCube[i]) == "b") {b_count++;}
-      else {scanErrorFlag = true;}
-    }
-    if ((w_count != 9) || (y_count != 9) || (o_count != 9) || (r_count != 9) || (g_count != 9) || (b_count != 9)) {scanErrorFlag = true;}
-  }
-
+  for (byte i=0; i<54; i++) {
+    if (ScannedCube[i] == 'w') {w_count++;}
+    else if (ScannedCube[i] == 'y') {y_count++;}
+    else if (ScannedCube[i] == 'o') {o_count++;}
+    else if (ScannedCube[i] == 'r') {r_count++;}
+    else if (ScannedCube[i] == 'g') {g_count++;}
+    else if (ScannedCube[i] == 'b') {b_count++;}
+    else {scanErrorFlag = true;}
+  }
+
+  if ((w_count != 9) || (y_count != 9) || (o_count != 9) || (r_count != 9) || (g_count != 9) || (b_count != 9)) {scanErrorFlag = true;}
+
+  Serial.println(ScannedCube);
+
   if (scanErrorFlag == true) {
-    lcd.clear();
-    lcd.setCursor(0, 0);
-    lcd.print("Scan error");
-    lcd.setCursor(0, 1);
-    lcd.print("Repeat scan");
-  }
-  else {
-    lcd.clear();
-    lcd.setCursor(0, 0);
-    lcd.print("Scan completed");
-    lcd.setCursor(0, 1);
-    lcd.print("successfully");
-    Serial.println(ScannedCube);
+    selectedButton = selectOption(F("Cube scan error"), F("Rescan   Restart"), F("Rescan"), F("         Restart"));
+    if (selectedButton == 0) scanCube();
+    else normalFlow();
   }

 }

 //Method for caibration scan of one side - scan each item once and print the RGB values
 void calibrationScan() {
-  attachInterrupt (0, leftButtonPressed, FALLING);
+  attachInterrupt (0, leftButtonPressed, RISING);
   operateFlag = true;
+  lcd.clear();
+  lcd.setCursor(0, 0);
+  lcd.print(F("Calibrating..."));
   turnMotor2(95, 5);
   delay(200);
   turnMotor4(35, 7);
   delay(200);
-  for (int i = 0; i<9; i++) {
+  for (byte i = 0; i<9; i++) {
     turnMotor1(Motor_1_ScanAngles[i], 4);
     turnMotor4(Motor_4_ScanAngles[i], 7);
-    delay(200);
-    calibrate();
-    delay(200);
+    delay(100);
+    scan_item();
+    delay(100);
+    if (serialOutput == true) {
+      Serial.print(F("R= "));//printing name
+      Serial.print(f_RED);//printing RED color frequency
+      Serial.print(F("  G= "));
+      Serial.print(f_GREEN);//printing RED color frequency
+      Serial.print(F("  B= "));
+      Serial.println(f_BLUE);
+    }
   }
   turnMotor4(35, 7);
   turnCubeStraight();
+  detachInterrupt (0);
 }

@@ -609,7 +660,9 @@
   delay(200);
   turnMotor4(35, 7);
   delay(200);
-  for (int i = 0; i<9; i++) {
+  attachInterrupt (0, leftButtonPressed, RISING);
+  operateFlag = true;
+  for (byte i = 0; i<9; i++) {
     turnMotor1(Motor_1_ScanAngles[i], 4);
     delay(50);
     turnMotor4(Motor_4_ScanAngles[i], 5);
@@ -619,15 +672,18 @@
   }
   turnMotor4(35, 7);
   turnCubeStraight();
+  detachInterrupt (0);
+  verifyScannedSide();
 }

 //Method to add the scanned side to the common scanCube variable
-void addSideToScanCubeString(String cubeSide[9]) {
+void addSideToScanCubeString() {
   for (byte i=0; i<9; i++) {
-    ScannedCube += SideScanResult[i];
-  }
-  //Serial.println(ScannedCube);
+    ScannedCube[cubeCounter] = SideScanResult[i];
+    cubeCounter ++;
+  }
+  Serial.println(ScannedCube); ////////////////////////////////////////////////////////////////////////
 }

@@ -656,40 +712,40 @@

 //Function for detecting color (All devices and Arduino connected to power supply)
-String defineColor(int r, int g, int b) {
+char defineColor(byte r, byte g, byte b) {
   if(r>=f[0][0] && r<=f[0][1] && g>=f[0][2] && g<=f[0][3] && b>=f[0][4] && b<=f[0][5]){
-    return "w";
+    return 'w';
   }
   else if(r>=f[1][0] && r<=f[1][1] && g>=f[1][2] && g<=f[1][3] && b>=f[1][4] && b<=f[1][5]){
-    return "y";
+    return 'y';
   }
   else if(r>=f[2][0] && r<=f[2][1] && g>=f[2][2] && g<=f[2][3] && b>=f[2][4] && b<=f[2][5]){
-    return "o";
+    return 'o';
   }
   else if(r>=f[3][0] && r<=f[3][1] && g>=f[3][2] && g<=f[3][3] && b>=f[3][4] && b<=f[3][5]){
-    return "r";
+    return 'r';
   }
   else if(r>=f[4][0] && r<=f[4][1] && g>=f[4][2] && g<=f[4][3] && b>=f[4][4] && b<=f[4][5]){
-    return "g";
+    return 'g';
   }
   else if(r>=f[5][0] && r<=f[5][1] && g>=f[5][2] && g<=f[5][3] && b>=f[5][4] && b<=f[5][5]){
-    return "b";
+    return 'b';
   }
   else {
-    return "undefined";
+    return 'X';
   }
 }

 //Function that repeats scanning up to 3 times if the color was not defined
-String scanResult(){
-  String color = " ";
-  int wrongScan = 0;
+char scanResult(){
+  char color;
+  byte wrongScan = 0;
   do{
     scan_item();
     color = defineColor(f_RED, f_GREEN, f_BLUE);
     wrongScan++ ;
-    if (color != "undefined") {
+    if (color != 'X') {
       break;
       }
   } while (wrongScan < 10);
@@ -697,7 +753,7 @@
 }

 //Supportive function for device calibration
-void calibrate() {
+/*void calibrate() {
   // Setting red filtered photodiodes to be read
   digitalWrite(S2,LOW);
   digitalWrite(S3,LOW);
@@ -728,7 +784,7 @@
   Serial.print(frequency);//printing BLUE color frequency
   Serial.println("  ");
   delay(100);
-}
+}*/

 void printSide(String side[]) {
   byte e = 0;
@@ -748,14 +804,15 @@

 //Method for assembling cube based on the steps string
 void assembleCube(String movementString) {
-for (byte i=0; i<=movementString.length(); i++) {
+  byte solutionLength = movementString.length();
+  for (byte i=0; i<=solutionLength; i++) {
     String stepValue = String(movementString[i]);
     Serial.println(stepValue);

     //Print process on LCD
-    lcd.clear();
+    /*lcd.clear();
     lcd.setCursor(0, 0);
-    lcd.print("Assembling cube");
+    lcd.print(F("Assembling cube"));
     lcd.setCursor(0, 1);
     lcd.print("Step   ( ) of ");
     lcd.setCursor(5, 1);
@@ -763,15 +820,20 @@
     lcd.setCursor(14, 1);
     lcd.print(movementString.length());
     lcd.setCursor(8, 1);
-    lcd.print(stepValue);
-
+    lcd.print(stepValue);*/
+
+    storeLCD(F("Assembling cube"), 0);
+    storeLCD(("Step   of ") + String(solutionLength), 1);
+    storeLCD(("     ") + String(i+1), 2);
+
     makeStep(stepValue);
   }
+
   lcd.clear();
   lcd.setCursor(0, 0);
-  lcd.print("Cube assembled");
+  lcd.print(F("Cube assembled"));
   lcd.setCursor(0, 1);
-  lcd.print("successfully!");
+  lcd.print(F("successfully!"));
 }

 //Method for implementing one defined step
@@ -921,7 +983,9 @@

 }

-/////////////////////////////////////////////////ELEMENTARY MOTORS MOVEMENTS/////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////ELEMENTARY MOTORS MOVEMENTS//////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 //Method for turning the Motor1 (the motor which rotates the cube)
 void turnMotor1(byte degree, byte motorSpeed) {
@@ -929,19 +993,20 @@
   operateFlag = true;
   byte limitedDegree = constrain(degree, minAngleMotor1, maxAngleMotor1);
   if(motor_1_Position < limitedDegree) {
-    for(int i = motor_1_Position; i <=limitedDegree ; i++) {
+    for(byte i = motor_1_Position; i <=limitedDegree ; i++) {
     Motor1.write(i);
     delay(motorSpeed);
     }
   }
   else if (motor_1_Position > limitedDegree) {
-    for(int i = motor_1_Position; i >= limitedDegree; i--) {
+    for(byte i = motor_1_Position; i >= limitedDegree; i--) {
     Motor1.write(i);
     delay(motorSpeed);
     }
   }
   motor_1_Position = limitedDegree;
 }
+

 //Method for turning the Motor2 (the motor which moves the carriage)
 void turnMotor2(byte degree, byte motorSpeed) {
@@ -949,19 +1014,20 @@
   operateFlag = true;
   byte limitedDegree = constrain(degree, minAngleMotor2, maxAngleMotor2);
   if(motor_2_Position < limitedDegree) {
-    for(int i = motor_2_Position; i <=limitedDegree ; i++) {
+    for(byte i = motor_2_Position; i <=limitedDegree ; i++) {
     Motor2.write(i);
     delay(motorSpeed);
     }
   }
   else if (motor_2_Position > limitedDegree) {
-    for(int i = motor_2_Position; i >= limitedDegree; i--) {
+    for(byte i = motor_2_Position; i >= limitedDegree; i--) {
     Motor2.write(i);
     delay(motorSpeed);
     }
   }
   motor_2_Position = limitedDegree;
 }
+

 //Method for turning the Motor3 (the motor that moves the pusher)
 void turnMotor3(byte degree, byte motorSpeed) {
@@ -969,19 +1035,20 @@
   operateFlag = true;
   byte limitedDegree = constrain(degree, minAngleMotor3, maxAngleMotor3);
   if(motor_3_Position < limitedDegree) {
-    for(int i = motor_3_Position; i <=limitedDegree ; i++) {
+    for(byte i = motor_3_Position; i <=limitedDegree ; i++) {
     Motor3.write(i);
     delay(motorSpeed);
     }
   }
   else if (motor_3_Position > limitedDegree) {
-    for(int i = motor_3_Position; i >= limitedDegree; i--) {
+    for(byte i = motor_3_Position; i >= limitedDegree; i--) {
     Motor3.write(i);
     delay(motorSpeed);
     }
   }
   motor_3_Position = limitedDegree;
 }
+

 //Method for turning the Motor4 (the motor that moves the color scanner)
 void turnMotor4(byte degree, byte motorSpeed) {
@@ -989,13 +1056,13 @@
   operateFlag = true;
   byte limitedDegree = constrain(degree, minAngleMotor4, maxAngleMotor4);
   if(motor_4_Position < limitedDegree) {
-    for(int i = motor_4_Position; i <=limitedDegree ; i++) {
+    for(byte i = motor_4_Position; i <=limitedDegree ; i++) {
     Motor4.write(i);
     delay(motorSpeed);
     }
   }
   else if (motor_4_Position > limitedDegree) {
-    for(int i = motor_4_Position; i >= limitedDegree; i--) {
+    for(byte i = motor_4_Position; i >= limitedDegree; i--) {
     Motor4.write(i);
     delay(motorSpeed);
     }
@@ -1007,79 +1074,85 @@
 //Method for pushing the cube
 void push() {
   turnMotor2(105, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor3(45, 2);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(118, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor3(95, 2);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(105, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor3(90, 2);
-  delay(200);
-}
+  delay(standardDelay);
+}
+

 //Method for turning the cube ClockWise
 void turnCubeCW() {
   turnMotor2(95, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor1(5, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(105, 5);
-  delay(200);
-}
+  delay(standardDelay);
+}
+

 //Method for turning the cube CounterClockWise
 void turnCubeCCW() {
   turnMotor2(95, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor1(171, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(105, 5);
-  delay(200);
-}
+  delay(standardDelay);
+}
+

 //Method for turning the cube straight
 void turnCubeStraight() {
   turnMotor2(95, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor1(88, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(105, 5);
-  delay(200);
-}
+  delay(standardDelay);
+}
+

 //Method for turning the bottom layer ClockWise
 void downCW() {
   turnCubeCW();
   turnMotor3(45, 2);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(135, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor1(95, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor1(88, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(105, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor3(90, 2);
-  delay(200);
-}
+  delay(standardDelay);
+}
+

 //Method for turning the bottom layer CounterClockWise
 void downCCW() {
   turnCubeCCW();
   turnMotor3(45, 2);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(135, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor1(80, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor1(88, 3);
-  delay(200);
+  delay(standardDelay);
   turnMotor2(105, 5);
-  delay(200);
+  delay(standardDelay);
   turnMotor3(90, 2);
-  delay(200);
-}
+  delay(standardDelay);
+}
+


Filtros de Média implementados,F. Exponencial com problemas

--- src/arduino/thermocoupleReader/thermocoupleReader.ino
+++ src/arduino/thermocoupleReader/thermocoupleReader.ino
@@ -5,20 +5,51 @@
  * @version 0.12 'Teste Leitura multiplos sensores'
  */

+// Bibliotecas ---------------------------------------------------------------------------------
+#include <math.h>

+// Constantes ----------------------------------------------------------------------------------
+
+// Debug
+#define LED 13
+#define TIME_BLINK 200
+
+// Configuração Pinos
 #define PIN_LM35      A0
 #define PIN_MTK01     A1
+
 #define INTERVAL      500  //ms
 #define SIZE_BUFFER   10
+#define SIZE_BUFFER_F 10   // Parâmentro Filtro Média Móvel
+#define ALPHA         0.8  // Parâmentro Filtro Média Móvel Ponderada

+// Variáveis Globais  --------------------------------------------------------------------------
+
+// Timer
 unsigned long lasttime = millis();

-int bufferLM35[SIZE_BUFFER];
-int bufferMTK01[SIZE_BUFFER];
-int k;
-int i;                        // Contador Leituras
+// Contadores
+int k;                            // Buffer
+int index;                        // Absoluto
+
+// Buffer Dados Brutos
+float bufferLM35[SIZE_BUFFER];
+float bufferMTK01[SIZE_BUFFER];
+
+// Buffer Dados Filtrados
+float bufferAvgFilter[SIZE_BUFFER];
+float bufferMvAvgFilter[SIZE_BUFFER];
+float bufferMvAvgExpFilter[SIZE_BUFFER];
+
+float pMvAvgExpFilter[4]; // Pesos Filtro Média Móvel Ponderada
+
+// Setup ---------------------------------------------------------------------------------

 void setup() {
+  // Prepara Led para Debug
+  pinMode(LED, OUTPUT);
+  digitalWrite(LED,LOW);
+
   // Inicia Porta Serial
   Serial.begin(57600);

@@ -26,15 +57,29 @@
   pinMode(PIN_LM35,INPUT);
   pinMode(PIN_MTK01,INPUT);

-  // Zera Buffer
+  // Zera Buffers
   for(k=0;k<SIZE_BUFFER;k++){
     bufferLM35[k] = 0;
     bufferMTK01[k] = 0;
+    bufferAvgFilter[k] = 0;
+    bufferMvAvgFilter[k] = 0;
+    bufferMvAvgExpFilter[k] = 0;
   }

-  // Zera Contador
-  i=0;
+  blink(4);
+
+  // Zera Contadores
+  index=1;
+  k=0;
+
+  // Calcula Pesos Filtro Média Móvel Ponderada
+  pMvAvgExpFilter[0] = pow(ALPHA,3);
+  pMvAvgExpFilter[1] = (1-ALPHA)*pow(ALPHA,2);
+  pMvAvgExpFilter[2] = (1-ALPHA)*pow(ALPHA,1);
+  pMvAvgExpFilter[0] = (1-ALPHA);
 }
+
+// Loop ----------------------------------------------------------------------------------

 void loop() {
   // Loop com período fixo de Amostragem
@@ -43,41 +88,86 @@
     lasttime = millis();

     // Ler o valor dos sensores
-    int rawTemp1 = analogRead(PIN_LM35);
-    int rawTemp2 = analogRead(PIN_MTK01);
+    float rawTemp1 = analogRead(PIN_LM35);
+    float rawTemp2 = analogRead(PIN_MTK01);

     // Filtragem
     bufferLM35[k] = rawTemp1;
     bufferMTK01[k] = rawTemp2;

-    int filteredData = filterMovingAverenge(bufferLM35,k);
+    filterAverenge(bufferLM35,index,k);
+    filterMovingAverenge(bufferLM35,k);
+    filterMovingAverengeExp(bufferLM35,k);

     // Envia via Serial
-    Serial.print(k);
+    Serial.print(lasttime);
     Serial.print(' ');
     Serial.print(rawTemp1);
     Serial.print(' ');
-    Serial.println(filteredData);
+    Serial.println(bufferMvAvgExpFilter[k]);

     // Incrementa Contadores
-    i = i+1;
+    index = index+1;
     k = (k<(SIZE_BUFFER-1))?k+1:0;
   }
 }

+// Funções Auxliares ---------------------------------------------------------------------
+
 /**
- * Filtro de Média Móvel com tamanho definido por SIZE_BUFFER
+ * Filtro Média Simples
  *
  * @author Rafael Lima
  */
-int filterMovingAverenge(int buffer[],int i){
+ void filterAverenge(float buffer[],int i,int k){
+    // Calcula Endereços
+    int a1 = (k>0)?k-1:SIZE_BUFFER-1;
+
+    //bufferAvgFilter[k] = ((i-1)*bufferAvgFilter[a1])/i + buffer[i]/i;
+    bufferAvgFilter[k] = bufferAvgFilter[a1] + (buffer[k] - bufferAvgFilter[a1])/i;
+ }
+
+/**
+ * Filtro de Média Móvel com tamanho definido por SIZE_BUFFER_F
+ *
+ * @author Rafael Lima
+ */
+void filterMovingAverenge(float buffer[],int k){
   // Calcula Endereços
-  int a1 = (i>0)?i-1:SIZE_BUFFER-1;
-  int a2 = (i<(SIZE_BUFFER-1))?i+1:0; // O próximo termo é igual o i-n por ser um buffer circular
+  int a1 = (k>0)?k-1:SIZE_BUFFER_F-1;
+  int a2 = (k<(SIZE_BUFFER_F-1))?k+1:0; // O próximo termo é igual o i-n por ser um buffer circular

   // Aplica Filtro
-  int filteredData = buffer[a1] + (buffer[i]-buffer[a2])/SIZE_BUFFER;
-
-  return filteredData;
+  bufferMvAvgFilter[k] = bufferMvAvgFilter[a1] + (buffer[k]-buffer[a2])/SIZE_BUFFER_F;
 }

+/**
+ * Filtro de Média Móvel Ponderada Exponencialmente
+ *
+ * @author Rafael Lima
+ */
+void filterMovingAverengeExp(float buffer[],int k){
+  // Calcula Endereços
+  int a1 = (k>0)?k-1:SIZE_BUFFER_F-1;
+  int a2 = (k>1)?k-2:SIZE_BUFFER_F+k-2;
+  int a3 = (k>2)?k-3:SIZE_BUFFER_F+k-3;
+
+  // Aplica Filtro
+  bufferMvAvgExpFilter[k] = buffer[a3]*pMvAvgExpFilter[0];
+  bufferMvAvgExpFilter[k] += buffer[a2]*pMvAvgExpFilter[1];
+  bufferMvAvgExpFilter[k] += buffer[a1]*pMvAvgExpFilter[2];
+  bufferMvAvgExpFilter[k] += buffer[k]*pMvAvgExpFilter[3];
+}
+
+/**
+ * Debug Function - Blink Led 'n' times
+ * @author Rafael
+ */
+void blink(int n){
+  for(k=(n>=0)?n:0;k<n;k++){
+    digitalWrite(LED,HIGH);
+    delay(TIME_BLINK);
+    digitalWrite(LED,LOW);
+    delay(TIME_BLINK);
+  }
+}


отправка T, P. Код требует рефакторинга

отправка T, P. Код требует рефакторинга

--- serialracoon.ino
+++ serialracoon.ino
@@ -1,4 +1,3 @@
-#include <SFE_BMP180.h>

 /* YourDuino.com Example: BlueTooth HC-05 Setup
  - WHAT IT DOES:
@@ -21,6 +20,8 @@

 /*-----( Import needed libraries )-----*/
 #include <SoftwareSerial.h>
+#include <SFE_BMP180.h>
+
 /*-----( Declare Constants and Pin Numbers )-----*/
 #define HC_05_TXD_ARDUINO_RXD 2
 #define HC_05_RXD_ARDUINO_TXD 3
@@ -110,6 +111,8 @@

 BTDevice *bt = new BTDevice();

+SFE_BMP180 pressure;
+
 void setup()   /****** SETUP: RUNS ONCE ******/
 {

@@ -126,6 +129,12 @@
   BTSerial.begin(38400);  // HC-05 default speed in AT command mode

   bt->setState(data);
+
+  if (pressure.begin())
+    Serial.println("BMP180 init success");
+  else
+    Serial.println("BMP180 init failed!!!");
+
 /*
   msg("Pwr on");
   delay(2000);
@@ -155,6 +164,9 @@
 int v3 = 0;
 int d10 = 0;
 int d8 = 0;
+double T = -10.0;
+double P = -10.0;
+

 void loop()
 {
@@ -184,7 +196,6 @@
     //Serial.print(fromSerialStr);
   }

-  char out[80];

   v0 = analogRead(A0);
   v1 = analogRead(A1);
@@ -194,10 +205,34 @@
   d10 = digitalRead(10);
   d8 = digitalRead(8);

+  char status;
+
+  // abirvalg!!!
+
+  status = pressure.startTemperature();
+  if (status != 0)  {
+    delay(status);
+    status = pressure.getTemperature(T);
+    Serial.println(T);
+    if (status != 0) {
+      status = pressure.startPressure(3);
+      if (status != 0) {
+        delay(status);
+
+        status = pressure.getPressure(P,T);
+        if (status != 0) {
+
+        } else { T = -1.0; P = -1.0; }
+      } else { T = -1.0; P = -1.0; }
+    } else { T = -1.0; P = -1.0; }
+  } else { T = -1.0; P = -1.0; }
+
+
   if (board == 0) {
-    //sprintf(out, "seqid %d;%d;;;\r\n", cnt++, val);
-    sprintf(out, "seqid=%d;A0=%d;A1=%d;D8=%d;D10=%d\r\n", cnt, v0, v1, d8, d10);
-    Serial.println(out);
+    char out[80];
+    //sprintf(out, "seqid %d;%d;;;\r\n", cnt++, val); // 0.7501
+    sprintf(out, "seqid=%d;A0=%d;A1=%d;D8=%d;D10=%d;T=%d;P=%d\r\n", cnt, v0, v1, d8, d10, (int)T, (int)(P*0.7501));
+    Serial.print(out);
     BTSerial.write(out);
     delay(100);
   }


only send ultasonic data if we got a reading

--- testing/arduino/servo-radar3-ros-v3.ino
+++ testing/arduino/servo-radar3-ros-v3.ino
@@ -45,9 +45,9 @@
 const uint8_t servoRotationAngel = 5;

 enum direction {
-  left,
-  center,
-  right
+    left,
+    center,
+    right
 };

 uint8_t servoPos = 90;
@@ -127,6 +127,15 @@
 }

+void SendServoAngleToROS(int angle)
+{
+    float pos[2] = {float(angle), float(angle+180%360)};
+    jointMessage.position = pos;
+    jointMessage.header.stamp = nh.now();
+    odometryPublisher.publish(&jointMessage);
+}
+
+
 void SendDistanceToROS(int sensorID, float rangeInCentimeter)
 {
     rangeMessage.range = rangeInCentimeter/100;
@@ -141,7 +150,6 @@
     {
         rangePublisher2.publish(&rangeMessage);
     }
-
 }

@@ -157,16 +165,17 @@
         //delay(5);
     }

-    SendDistanceToROS(1, rangeFront);
-    SendDistanceToROS(2, rangeBack);
+    if(rangeFront > 0)
+    {
+        SendDistanceToROS(1, rangeFront);
+    }

-    // TODO - extra function to send
-    float pos[2] = {float(servoPos), float(servoPos+180%360)};
-    jointMessage.position = pos;
-    jointMessage.header.stamp = nh.now();
-    odometryPublisher.publish(&jointMessage);
+    if(rangeBack > 0)
+    {
+        SendDistanceToROS(2, rangeBack);
+    }
+
+    SendServoAngleToROS(servoPos);

     nh.spinOnce();
 }
-
-


Clean up warnings in compliance sketch, more AVR-isms

--- examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
+++ examples/compliance-otaa-halconfig/compliance-otaa-halconfig.ino
@@ -314,7 +314,7 @@
 }

 #if LMIC_ENABLE_event_logging
-// dump all the registers.  Must have printf setup.
+// dump all the registers.
 void printAllRegisters(void) {
     uint8_t regbuf[0x80];
     regbuf[0] = 0;
@@ -400,21 +400,21 @@
                     u1_t nwkKey[16];
                     u1_t artKey[16];
                     LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
-                    Serial.print("netid: ");
+                    Serial.print(F("netid: "));
                     Serial.println(netid, DEC);
-                    Serial.print("devaddr: ");
+                    Serial.print(F("devaddr: "));
                     Serial.println(devaddr, HEX);
-                    Serial.print("artKey: ");
-                    for (int i=0; i<sizeof(artKey); ++i) {
+                    Serial.print(F("artKey: "));
+                    for (size_t i=0; i<sizeof(artKey); ++i) {
                         if (i != 0)
-                            Serial.print("-");
+                            Serial.print('-');
                         printHex2(artKey[i]);
                     }
-                    Serial.println("");
-                    Serial.print("nwkKey: ");
-                    for (int i=0; i<sizeof(nwkKey); ++i) {
+                    printNl();
+                    Serial.print(F("nwkKey: "));
+                    for (size_t i=0; i<sizeof(nwkKey); ++i) {
                             if (i != 0)
-                                    Serial.print("-");
+                                    Serial.print('-');
                             printHex2(nwkKey[i]);
                     }
                 } while (0);
@@ -432,7 +432,6 @@
                 printFreq(e.freq);
                 printRps(e.rps);
                 printOpmode(e.opmode);
-                printf(" irqLevel %u", hal_getIrqLevel());
 #if LMIC_ENABLE_event_logging
                 printAllRegisters();
 #endif


update

update

--- src/Firmware.ino
+++ src/Firmware.ino
@@ -5,11 +5,10 @@
 OutputPin dirPinY(2);
 OutputPin stepPinY(3);

-
 long xPosition = 0;
 long yPosition = 0;

-double pulsePerMM = 170.2722;
+double pulsePerMM = (360 * 32 / 1.8) / 60; //106.90453618;

 float curve_section = 0.5;
 bool isRelative = false;
@@ -24,32 +23,40 @@
 int motionAcc = 1;
 bool isMoving = false;

-
 void updateMotion()
 {
-    if(isMoving){
-        if(motionDir>0&&currentDuringTime>targetDuringTime){
-            if(motionDir>150){
+    if (isMoving)
+    {
+        if (motionDir > 0 && currentDuringTime > targetDuringTime)
+        {
+            if (motionDir > 150)
+            {
                 motionAcc = -1;
-                motionDir=150;
+                motionDir = 150;
             }
             motionDir += motionAcc;
-            if(motionDir<0){
+            if (motionDir < 0)
+            {
                 motionDir = 0;
             }
             currentDuringTime -= motionDir;
-            if(currentDuringTime<targetDuringTime){
+            if (currentDuringTime < targetDuringTime)
+            {
                 currentDuringTime = targetDuringTime;
                 motionDir = 0;
             }
-        }else if(motionDir<0&&currentDuringTime<50000){
-
-            if(motionDir<-150){
+        }
+        else if (motionDir < 0 && currentDuringTime < 50000)
+        {
+
+            if (motionDir < -150)
+            {
                 motionAcc = -1;
-                motionDir=-150;
+                motionDir = -150;
             }
             motionDir -= motionAcc;
-            if(motionDir>0){
+            if (motionDir > 0)
+            {
                 motionDir = 0;
             }
             currentDuringTime -= motionDir;
@@ -57,253 +64,324 @@
     }
 }

-
-void setup(){
+void setup()
+{
     Serial.begin(115200);
     Timer1.initialize(500);
     Timer1.attachInterrupt(updateMotion);
-    pinMode(7,OUTPUT);
-    analogWrite(7,0);
+    pinMode(7, OUTPUT);
+    analogWrite(7, 0);
     Serial.print("start\n");
-
-}
-
-void loop(){
-    if(Serial.available()){
+}
+
+void loop()
+{
+    if (Serial.available())
+    {
         char c = Serial.read();
-        if(c=='\n'){
+        if (c == '\n')
+        {
             parseGCode();
             gcode = "";
-        }else{
+        }
+        else
+        {
             gcode += c;
         }
     }
 }
-float getX(){
-    return xPosition/pulsePerMM;
-}
-float getY(){
-    return yPosition/pulsePerMM;
-}
-void parseGCode(){
+float getX()
+{
+    return xPosition / pulsePerMM;
+}
+float getY()
+{
+    return yPosition / pulsePerMM;
+}
+void parseGCode()
+{
     gcode.toLowerCase();
     char c;
-    int cmd,index,startIndex,endIndex;
+    int cmd, index, startIndex, endIndex;
     float val;
-    if(gcode.length()>2){
-        if(hasCommand('g')){
+    if (gcode.length() > 2)
+    {
+        if (hasCommand('g'))
+        {
             cmd = getCommand('g');
-            switch(cmd){
-                case 0:
-                case 1:{
-                    if(hasCommand('p')){
-                        analogWrite(7,getCommand('p'));
-                    }
-                    if(hasCommand('f')){
-                        targetDuringTime = (long)(50000/getCommand('f'));
-                    }
-                    double x = hasCommand('x')?getCommand('x'):0;
-                    double y = hasCommand('y')?getCommand('y'):0;
-                    if(isRelative){
-                        move(x*pulsePerMM,y*pulsePerMM,cmd);
-                    }else{
-                        moveTo(hasCommand('x')?(x*pulsePerMM):xPosition,hasCommand('y')?(y*pulsePerMM):yPosition,cmd);
-                        targetX = x;
-                        targetY = y;
-                    }
+            switch (cmd)
+            {
+            case 0:
+            case 1:
+            {
+                if (hasCommand('p'))
+                {
+                    analogWrite(7, getCommand('p'));
+                }
+                if (hasCommand('f'))
+                {
+                    targetDuringTime = (long)(50000 / getCommand('f'));
+                }
+                double x = hasCommand('x') ? getCommand('x') : 0;
+                double y = hasCommand('y') ? getCommand('y') : 0;
+                if (isRelative)
+                {
+                    move(x * pulsePerMM, y * pulsePerMM, cmd);
+                }
+                else
+                {
+                    moveTo(hasCommand('x') ? (x * pulsePerMM) : xPosition, hasCommand('y') ? (y * pulsePerMM) : yPosition, cmd);
+                    targetX = x;
+                    targetY = y;
+                }
+            }
+            break;
+            case 2:
+            case 3:
+            {
+                if (hasCommand('p'))
+                {
+                    analogWrite(7, getCommand('p'));
+                }
+                arc(cmd == 3);
+            }
+            break;
+            case 28:
+            {
+                xPosition = 0;
+                yPosition = 0;
+            }
+            break;
+            case 90:
+            {
+                isRelative = false;
+            }
+            break;
+            case 91:
+            {
+                isRelative = true;
+            }
+            break;
+            }
+        }
+        else if (hasCommand('m'))
+        {
+            cmd = getCommand('m');
+            switch (cmd)
+            {
+            case 4:
+                if (hasCommand('p'))
+                {
+                    analogWrite(7, getCommand('p'));
+                }
+                else
+                {
+                    analogWrite(7, 0);
                 }
                 break;
-                case 2:
-                case 3:{
-                    if(hasCommand('p')){
-                        analogWrite(7,getCommand('p'));
-                    }
-                    arc(cmd==3);
-                }
-                break;
-                case 28:{
-                    xPosition = 0;
-                    yPosition = 0;
-                }
-                break;
-                case 90:{
-                    isRelative = false;
-                }
-                break;
-                case 91:{
-                    isRelative = true;
-                }
-                break;
-            }
-        }else if(hasCommand('m')){
-            cmd = getCommand('m');
-            switch(cmd){
-                case 4:
-                    if(hasCommand('p')){
-                        analogWrite(7,getCommand('p'));
-                    }else{
-                        analogWrite(7,0);
-                    }
-                break;
-            }
-        }
-    }else{
+            }
+        }
+    }
+    else
+    {
     }
     commandEnd();
 }
-void commandEnd(){
+void commandEnd()
+{
     Serial.print("oMGok\n");
 }
-long toDistanceX(double x){
+long toDistanceX(double x)
+{
     return (x - xPosition);
 }
-long toDistanceY(double y){
+long toDistanceY(double y)
+{
     return (y - yPosition);
 }

-void stepX(bool dir){
+void stepX(bool dir)
+{
     dirPinX = dir;
     stepPinX = LOW;
     delayMicroseconds(1);
     stepPinX = HIGH;
-    xPosition+=dir?1:-1;
-}
-void stepY(bool dir){
+    xPosition += dir ? 1 : -1;
+}
+void stepY(bool dir)
+{
     dirPinY = dir;
     stepPinY = LOW;
     delayMicroseconds(1);
     stepPinY = HIGH;
-    yPosition+=dir?1:-1;
-}
-
-void move(long dx,long dy,bool precision){
-    long tx = xPosition+dx;
-    long ty = yPosition+dy;
-    moveTo(tx,ty,precision);
+    yPosition += dir ? 1 : -1;
+}
+
+void move(long dx, long dy, bool precision)
+{
+    long tx = xPosition + dx;
+    long ty = yPosition + dy;
+    moveTo(tx, ty, precision);
 }
 int errX = 1;
 int errY = 1;
-void moveTo(long tx, long ty, bool precision) {
+void moveTo(long tx, long ty, bool precision)
+{
     isMoving = true;
     long x0 = xPosition;
     long y0 = yPosition;
     long x1 = tx;
     long y1 = ty;
-    currentDuringTime = max(targetDuringTime+500,1000);
+    currentDuringTime = max(targetDuringTime + 500, 1000);
     motionDir = 1;
     motionAcc = 1;
-    long dx,dy,sx,sy;
-    if(precision){
-        dx = abs(x1-x0);
-        sx = x0<x1;
-        dy = abs(y1-y0);
-        sy = y0<y1;
-        long err = (dx>dy ? dx : -dy)/2, e2;
+    long dx, dy, sx, sy;
+    if (precision)
+    {
+        dx = abs(x1 - x0);
+        sx = x0 < x1;
+        dy = abs(y1 - y0);
+        sy = y0 < y1;
+        long err = (dx > dy ? dx : -dy) / 2, e2;
         long ttt = millis();
-        while(true){
+        while (true)
+        {
             long distX = toDistanceX(x1);
             long distY = toDistanceY(y1);
-            if(labs(distX)<200&&labs(distY)<200){
+            if (labs(distX) < 200 && labs(distY) < 200)
+            {
                 motionDir = -1;
                 motionAcc = 1;
             }
-            if (distX==0 && distY==0) break;
+            if (distX == 0 && distY == 0)
+                break;
             e2 = err;
-            if (e2 >-dx) {
+            if (e2 > -dx)
+            {
                 err -= dy;
-                stepX(sx);
-            }
-            if (e2 < dy) {
+                stepX(sx);
+            }
+            if (e2 < dy)
+            {
                 err += dx;
                 stepY(sy);
             }
-            if(currentDuringTime>1000){
-                delay((int)(currentDuringTime/1000));
-                delayMicroseconds(currentDuringTime%1000);
-            }else{
+            if (currentDuringTime > 1000)
+            {
+                delay((int)(currentDuringTime / 1000));
+                delayMicroseconds(currentDuringTime % 1000);
+            }
+            else
+            {
                 delayMicroseconds(currentDuringTime);
             }
         }
-    }else{
+    }
+    else
+    {
         motionDir = 1;
-        while(true){
+        while (true)
+        {
             dx = toDistanceX(tx);
             dy = toDistanceY(ty);
-            if(labs(dx)<200&&labs(dy)<200){
+            if (labs(dx) < 200 && labs(dy) < 200)
+            {
                 motionDir = -1;
                 motionAcc = 1;
             }
-            if (dx==0 && dy==0) break;
-            if (dx!=0) {
-                stepX(dx>0);
-            }
-            if (dy!=0) {
-                stepY(dy>0);
-            }
-            if(currentDuringTime>1000){
-                delay((int)(currentDuringTime/1000));
-                delayMicroseconds(currentDuringTime%1000);
-            }else{
+            if (dx == 0 && dy == 0)
+                break;
+            if (dx != 0)
+            {
+                stepX(dx > 0);
+            }
+            if (dy != 0)
+            {
+                stepY(dy > 0);
+            }
+            if (currentDuringTime > 1000)
+            {
+                delay((int)(currentDuringTime / 1000));
+                delayMicroseconds(currentDuringTime % 1000);
+            }
+            else
+            {
                 delayMicroseconds(currentDuringTime);
             }
         }
     }
     isMoving = false;
 }
-void arc(bool ccw){
-    float cx = isRelative?(getX()+getCommand('i')):getCommand('i');
-    float cy = isRelative?(getY()+getCommand('j')):getCommand('j');
-    float endX = isRelative?(getX()+getCommand('x')):getCommand('x');
-    float endY = isRelative?(getY()+getCommand('y')):getCommand('y');
+void arc(bool ccw)
+{
+    float cx = isRelative ? (getX() + getCommand('i')) : getCommand('i');
+    float cy = isRelative ? (getY() + getCommand('j')) : getCommand('j');
+    float endX = isRelative ? (getX() + getCommand('x')) : getCommand('x');
+    float endY = isRelative ? (getY() + getCommand('y')) : getCommand('y');
     float angleA, angleB, angle, radius, length, aX, aY, bX, bY;
     aX = (getX() - cx);
     aY = (getY() - cy);
     bX = (endX - cx);
     bY = (endY - cy);
-    if(ccw){
+    if (ccw)
+    {
         angleA = atan2(aY, aX);
         angleB = atan2(bY, bX);
-    }else{
+    }
+    else
+    {
         angleA = atan2(bY, bX);
         angleB = atan2(aY, aX);
     }
-    if (angleB <= angleA) {
+    if (angleB <= angleA)
+    {
         angleB += 2 * M_PI;
     }
     angle = angleB - angleA;
     radius = sqrt(aX * aX + aY * aY);
     length = radius * angle;
     int steps, s, step;
-    steps = (int) ceil(length / curve_section);
-    for (s = 1; s <= steps; s++) {
-        step = (ccw) ? s : (steps - s);
-        moveTo((cx + radius * cos(angleA + angle * ((float) step / steps)))*pulsePerMM,(cy + radius * sin(angleA + angle * ((float) step / steps)))*pulsePerMM,1);
-    }
-}
-bool hasCommand(char cmd){
+    steps = (int)ceil(length / curve_section);
+    for (s = 1; s <= steps; s++)
+    {
+        step = (ccw) ? s : (steps - s);
+        moveTo((cx + radius * cos(angleA + angle * ((float)step / steps))) * pulsePerMM, (cy + radius * sin(angleA + angle * ((float)step / steps))) * pulsePerMM, 1);
+    }
+}
+bool hasCommand(char cmd)
+{
     int index = 0;
     char c = 0;
-    while(c!=cmd){
-        if(index>=gcode.length()){
+    while (c != cmd)
+    {
+        if (index >= gcode.length())
+        {
             return false;
-        }else{
+        }
+        else
+        {
             c = gcode.charAt(index);
         }
         index++;
     }
     return true;
 }
-double getCommand(char cmd){
+double getCommand(char cmd)
+{
     int index = gcode.indexOf(cmd);
-    int startIndex = gcode.indexOf(cmd)+1;
+    int startIndex = gcode.indexOf(cmd) + 1;
     char c = 0;
-    while(c!=' '){
+    while (c != ' ')
+    {
         index++;
-        if(index>=gcode.length()){
-            break;
-        }else{
+        if (index >= gcode.length())
+        {
+            break;
+        }
+        else
+        {
             c = gcode.charAt(index);
         }
     }
-    return gcode.substring(startIndex,index).toDouble();
+    return gcode.substring(startIndex, index).toDouble();
 }


No need to disable the watchdog

No need to disable the watchdog

--- hardware/esp8266com/esp8266/libraries/esp8266/examples/Blink/Blink.ino
+++ hardware/esp8266com/esp8266/libraries/esp8266/examples/Blink/Blink.ino
@@ -10,8 +10,6 @@

 void setup() {
   pinMode(ledPin, OUTPUT);     // Initialize the ledPin as an output
-  ESP.wdtDisable();            // Disable the watchdog timer built into the ESP8266
-                               // otherwise the ESP8266 reboots during the "delay(1000);"
 }

 // the loop function runs over and over again forever


use preset in zeroth iteration

use preset in zeroth iteration

--- arduino/bridgehead/bridgehead.ino
+++ arduino/bridgehead/bridgehead.ino
@@ -29,7 +29,7 @@
   int PWMS[] = {255, 255, 255, 56, 145, 145, 255, 145}; // streaming
   //int PWMS[] = {255, 255, 255, 140, 160, 160, 255, 160}; // desktop
   for (int i = 0; i < 8; i++) {
-    SoftPWMSet(PINS_PWM[i], 160);
+    SoftPWMSet(PINS_PWM[i], PWMS[i]);
   }
 }


Dialog to pick color for painting.

Dialog to pick color for painting.

--- arduino/led_matrix/led_matrix.ino
+++ arduino/led_matrix/led_matrix.ino
@@ -9,7 +9,7 @@

 CRGB leds[NUM_LEDS];
 int r, g, b;
-int x, y, xx;
+int x, y, yy;

 void setup() {
   FastLED.addLeds<WS2812B, PIN>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
@@ -19,18 +19,18 @@
 }

 void loop() {
-  for (y = 0; y < HEIGHT; y++) {
-    for (x = 0; x < WIDTH; x++) {
+  for (x = 0; x < WIDTH; x++) {
+    for (y = 0; y < HEIGHT; y++) {
       while (Serial.available() < 3);
       g = Serial.read();
       r = Serial.read();
       b = Serial.read();
-      if (y % 2 == 0) {
-        xx = x;
+      if (x % 2 == 0) {
+        yy = y;
       } else {
-        xx = WIDTH - x - 1;
+        yy = HEIGHT - y - 1;
       }
-      leds[xx + y * WIDTH] = CRGB(r, g, b);
+      leds[yy + x * HEIGHT] = CRGB(r, g, b);
     }
     Serial.print('X');
   }


Updating comments

Updating comments

Tested ATtiny84 at 8MHz by modifying the USI_TWI_Master.h file
to use 8MHz instead of 1MHz.

--- examples/SevenSegTest_tiny/SevenSegTest_tiny.ino
+++ examples/SevenSegTest_tiny/SevenSegTest_tiny.ino
@@ -4,6 +4,7 @@
   It requires the TinyWireM library for I2C communication
   and the Tiny_LEDBackpack library for the various display
   functions.
+  TinyWireM library obtained from http://www.scenelight.nl/?wpfb_dl=22

    NOTE: Tested successfully on ATtiny85, using 4700ohm pull-up
    resistors on SCL and SDA lines. Tested using 1MHz internal clock.
@@ -17,7 +18,16 @@

    Tested with and without AVRISP mkII hooked up, works fine both
    ways.
-
+
+   Additionally tested on ATtiny84 using 8MHz internal clock. To
+   enable this functionality, you must alter the USI_TWI_Master.h
+   file in the TinyWireM library to run at 8MHz. Search for the
+   line near the top that reads:
+   #define SYS_CLK   1000.0  // [kHz]	Default for ATtiny2313
+   and change the 1000 to 8000.
+
+   Also tested with 10k ohm pull-up resistors on SDA and SCL lines.
+
   This demo also uses a regular LED attached to
   ATtiny84 physical pin 2 (Arduino pin 10) to show
   that the sketch is running.
@@ -41,6 +51,7 @@
   sevenseg.begin(i2c_addr); // initialize HT16K33 controller
 //  sevenseg.blinkRate(2); // set blink rate (0,1,2 or 3)
   sevenseg.clear(); // clear all digits on display
+  sevenseg.writeDisplay();
   delay(1000);
 }

@@ -60,6 +71,7 @@
   sevenseg.writeDisplay(); // push data to display
   delay(500);
   sevenseg.clear(); // clear display before writing raw digit
+  sevenseg.writeDisplay();
   // The clear command doesn't need a writeDisplay call afterwards

   // Example of writing a single digit to a specified position on the
@@ -156,14 +168,16 @@
 //  sevenseg.writeDigitRaw(0,128); // 128 = "." decimal
 //  sevenseg.writeDigitRaw(0,0); // blank
 //  sevenseg.writeDigitRaw(2,255); // 255 = ":"  colon, always position 2
-//  ****Always follow a writeDigitRaw command with the*****
-//  sevenseg.writeDisplay(); command to push the data to the
-//  display.
-  // Example of using writeDigitRaw to write numbers or characters
+//  ****Always follow a writeDigitRaw command with the
+//  writeDisplay(); command to push the data to the
+//  display.*****
+//  sevenseg.writeDisplay(); // push data to display
+
+  // Example using writeDigitRaw to write numbers or characters
   // to specific digits on the display. This spells 'run'.
-  sevenseg.writeDigitRaw(0,80); // specify position and code
-  sevenseg.writeDigitRaw(1,28);
-  sevenseg.writeDigitRaw(3,84);
+  sevenseg.writeDigitRaw(0,80); // specify position and code, 80 = 'r'
+  sevenseg.writeDigitRaw(1,28); // specify position and code, 28 = 'u'
+  sevenseg.writeDigitRaw(3,84); // specify position and code, 84 = 'n'
   sevenseg.writeDisplay(); // push data to display
   delay(1000);

@@ -175,10 +189,11 @@
   // segments are conveniently set up with bit mask values
   // that are increasing multiples of 2.
   sevenseg.clear();
+  sevenseg.writeDisplay();
   for (int wait = 0; wait < 3; wait++) { // repeat multiple times
     for (int i = 1; i < 64; i *= 2) {
       sevenseg.writeDigitRaw(0,i);
-      sevenseg.writeDisplay();
+      sevenseg.writeDisplay(); // push data to display
       delay(100);
     }
   }
@@ -189,10 +204,10 @@
     for (int i = 0; i < 5; i++) {
      if (i == 2) i++;  // This is needed to skip over position 2
      sevenseg.writeDigitRaw(i,128); // light the decimal at position i
-     sevenseg.writeDisplay();
+     sevenseg.writeDisplay();  // push data to display
      delay(100);
      sevenseg.writeDigitRaw(i,0); // clear the decimal at position i
-     sevenseg.writeDisplay();
+     sevenseg.writeDisplay(); // push data to display
     }
   }


Added transistor to switch power on

Added transistor to switch power on

--- gimbal_control/gimbal_control/gimbal_control.ino
+++ gimbal_control/gimbal_control/gimbal_control.ino
@@ -2,6 +2,7 @@
 // Gimbal controlled by Hobby King ESC. Connect black to ground
 // and white to pin 10. (Note that you can only control servos
 // on pin 9 and 10.) DO NOT CONNECT RED WIRE.
+// Connect gate of transistor to pin 2.

 // Run this sketch and then start the power to ESC when
 // instructed by serial prompt. This needs to be replaced with
@@ -17,7 +18,9 @@
   gimbal.attach(10);
   gimbal.write(0);

-  Serial.println("Start power to motor");
+  // Starts power
+  pinMode(2,OUTPUT);
+  digitalWrite(2,HIGH);

   delay(2000);


Changed temp thresholds

Changed temp thresholds

--- FreezerScreamer.ino
+++ FreezerScreamer.ino
@@ -38,15 +38,15 @@
 int msfiveMinutes = 300000;
 int msOneHour = 3600000;

-float lowFahrenheitThreshhold = -5.0;
+float lowFahrenheitThreshhold = -25.0;
 int lowThreshExceededCounter = 0;
-int numLowTempViolations = msfiveMinutes/msTotalDelayInterval;
-
-float highFahrenheitThreshhold1 = 25.0;
-float highFahrenheitThreshhold2 = 30.0;
+int numLowTempViolations = msOneHour/msTotalDelayInterval;
+
+float highFahrenheitThreshhold1 = 5.0;
+float highFahrenheitThreshhold2 = 15.0;
 int highThreshExceededCounter = 0;

-int numHighTempViolations_level1 = 2;
+int numHighTempViolations_level1 = 5;
 int numHighTempViolations_level2 = msfiveMinutes/msTotalDelayInterval;
 int numHighTempViolations_level3 = msOneHour/msTotalDelayInterval;

@@ -60,7 +60,7 @@
 void setup() {
   Serial.begin(9600);
   Time.zone(-8);
-  Particle.variable("fahrenTemp", &fahrenheitTemp, DOUBLE);
+  Particle.variable("fahrenheitTemp", &fahrenheitTemp, DOUBLE);
   // Set up 'power' pins, comment out if not used!
   /*pinMode(D3, OUTPUT);
   pinMode(D5, OUTPUT);
@@ -247,16 +247,20 @@
       Serial.println(" highTempViolation_level1");
       publishTempEvent("highTempViolation_level1", fahrenheitTemp);
       Particle.publish("fahrenheitTempLog", "highTempViolation_level1");
+      publishTempEvent("fahrenheitTempLog", fahrenheitTemp);
     }
     if(inViolationForExactDuration(highThreshExceededCounter, numHighTempViolations_level2)) {
       Serial.println(" highTempViolation_level2");
       publishTempEvent("highTempViolation_level2", fahrenheitTemp);
       Particle.publish("fahrenheitTempLog", "highTempViolation_level2");
+      publishTempEvent("fahrenheitTempLog", fahrenheitTemp);
     }
     if(inViolationForExactDuration(highThreshExceededCounter, numHighTempViolations_level3)) {
       Serial.println(" highTempViolation_level3");
       publishTempEvent("highTempViolation_level3", fahrenheitTemp);
       Particle.publish("fahrenheitTempLog", "highTempViolation_level3");
+      publishTempEvent("fahrenheitTempLog", fahrenheitTemp);
+
       highThreshExceededCounter = 0; // now reset notification sequence
     }
   }
@@ -280,11 +284,13 @@
 }

 void loop(void) {
+  loopCounter++;
   readCelsiusTemp(&celsiusTemp);
   fahrenheitTemp = calcFahrenheitFromCelsius(getCelsiusTemp());
   checkFreezerScreamerConditions();

-  if(++loopCounter >= numLoopIterationsBeforeLog) {
+  if(loopCounter >= numLoopIterationsBeforeLog) {
+    Serial.println(" fahrenheitTempLog Event");
     publishTempEvent("fahrenheitTempLog", fahrenheitTemp);
     loopCounter = 0;
   }


Calling Animator differently

Calling Animator differently

--- ESP8266HueEmulator/ESP8266HueEmulator.ino
+++ ESP8266HueEmulator/ESP8266HueEmulator.ino
@@ -1,13 +1,13 @@
 /**
  * Emulate Philips Hue Bridge ; so far the Hue app finds the emulated Bridge and gets its config
- * but you cannot actually switch the NeoPixels with it yet (TODO)
+ * and switch on 3 NeoPixels with it so far (TODO)
  **/

 #include <ESP8266WiFi.h>
 #include <ESP8266WebServer.h>
 #include <WiFiUDP.h>
 #include "ESP8266SSDP.h"
-#include <NeoPixelBus.h>
+#include <NeoPixelBus.h> // NeoPixelAnimator branch
 #include <ArduinoJson.h>

 // The follwing is needed in order to fill ipString with a String that contains the IP address
@@ -22,8 +22,8 @@

 // Settings for the NeoPixels
 #define pixelCount 30 // Strip has 30 NeoPixels
+#define pixelPin 2 // Strip is attached to GPIO2 on ESP-01
 #define colorSaturation 128
-NeoPixelBus strip = NeoPixelBus(pixelCount, 2); // Strip is attached to GPIO2 on ESP-01
 RgbColor red = RgbColor(colorSaturation, 0, 0);
 RgbColor green = RgbColor(0, colorSaturation, 0);
 RgbColor blue = RgbColor(0, 0, colorSaturation);
@@ -31,6 +31,9 @@
 RgbColor black = RgbColor(0);
 unsigned int transitionTime = 400; // by default there is a transition time to the new state of 400 milliseconds

+NeoPixelBus strip = NeoPixelBus(pixelCount, pixelPin);
+NeoPixelAnimator animator(&strip); // NeoPixel animation management object
+
 /// X, Y, Z and x, y are values to desvribe colors
 float X;
 float Y;
@@ -46,7 +49,6 @@
 String ipString;

 ESP8266WebServer HTTP(80);
-

 String client = "e7x4kuCaC8h885jo"; // "UjBZ0nvTLu7aMdOe"; // The client string that the client app sends. Need to enter here what the app sends.
 // FIXME: Parse this out of what is being sent by the app.
@@ -84,7 +86,6 @@

     HTTP.send(200, "text/plain", longstr);
     Serial.println(longstr);
-    Serial.println("I assume there is an error in my response since after this the iOS app says Bridge disconnected");
   }

   else if (requestedUri.endsWith(client))
@@ -123,7 +124,7 @@
     // For this to work we need a patched version of esp8266/libraries/ESP8266WebServer/src/Parsing.cpp which hopefully lands in the official channel soon
     // https://github.com/me-no-dev/Arduino/blob/d4894b115e3bbe753a47b1645a55cab7c62d04e2/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/Parsing.cpp
     Serial.println(HTTP.arg("plain"));
-    int numberOfTheLight = atoi(subStr(requestedUri.c_str(), "/", 4)); // The number of the light to be switched; they start with 1
+    int numberOfTheLight = atoi(subStr(requestedUri.c_str(), "/", 4)) - 1; // The number of the light to be switched; they start with 1
     Serial.print("Number of the light --> ");
     Serial.println(numberOfTheLight);

@@ -136,11 +137,32 @@
     bool onValue = root["on"];
     Serial.print("I should --> ");
     Serial.println(onValue);
+    // define the effect to apply, in this case linear blend
+    HslColor originalColor = strip.GetPixelColor(numberOfTheLight);
+
     if (onValue == true)
-      strip.LinearFadePixelColor(transitionTime, numberOfTheLight - 1, white); // For now we ignore the color (FIXME)
+    {
+      AnimUpdateCallback animUpdate = [ = ](float progress)
+      {
+        // progress will start at 0.0 and end at 1.0
+        HslColor updatedColor = HslColor::LinearBlend(originalColor, white, (uint8_t)(255 * progress));
+        strip.SetPixelColor(numberOfTheLight, updatedColor);
+      };
+      strip.SetPixelColor(numberOfTheLight, white); // For now we ignore the color (FIXME)
+      animator.StartAnimation(numberOfTheLight, transitionTime, animUpdate);
+    }
     if (onValue == false)
-      strip.LinearFadePixelColor(transitionTime, numberOfTheLight - 1, black);
-    strip.Show();
+    {
+      AnimUpdateCallback animUpdate = [ = ](float progress)
+      {
+        // progress will start at 0.0 and end at 1.0
+        HslColor updatedColor = HslColor::LinearBlend(originalColor, black, (uint8_t)(255 * progress));
+        strip.SetPixelColor(numberOfTheLight, updatedColor);
+      };
+      strip.SetPixelColor(numberOfTheLight, black);
+      animator.StartAnimation(numberOfTheLight, transitionTime, animUpdate);
+    }
+
   }

   else if (requestedUri == "/description.xml")
@@ -185,12 +207,8 @@

   macString = String(WiFi.macAddress());

-  // ipString = String(WiFi.localIP());
-
-
   os_sprintf(ipChars, IPSTR, IP2STR(WiFi.localIP()));
   ipString = String(ipChars);
-

   Serial.print("Starting HTTP at ");
   Serial.print(WiFi.localIP());
@@ -203,7 +221,6 @@

   // Show that we are connected
   infoLight(green);
-

   Serial.printf("Starting SSDP...\n");
   SSDP.begin();
@@ -221,31 +238,26 @@
 }

 void loop() {
-
   // FIXME: This seems to block everything while a request is being processed which takes about 2 seconds
   // Can we run this in a separate thread, in "the background"?
+  // Makuna has a task library that "helps" manage non-preemptive tasks, but it would require
+  // that HTTP.handleClient() and/or SSDP.update() be modified to do less in a loop at one time.
+  // We might bring this question up on the esp8266/arduino chat to see if there is support
+  // to thread off the networking stuff; but in general, we don't have a multitasking core.
   HTTP.handleClient();
   SSDP.update();

-  // Start animating the NeoPixels
-  strip.StartAnimating();
-
-  // Wait until no more animations are running
-  // FIXME: This seems to block everything while a transition is running
-  // Can we run this in a separate thread, in "the background"?
-  while (strip.IsAnimating())
-  {
-    strip.UpdateAnimations();
+  static unsigned long update_strip_time = 0;  //  keeps track of pixel refresh rate... limits updates to 33 Hz
+  if (millis() - update_strip_time > 30)
+  {
+    if ( animator.IsAnimating() ) animator.UpdateAnimations(100);
     strip.Show();
-    delay(31); // ~30hz change cycle
-  }
-
-  delay(1);
-}
-
-
-void rgb2xy(int R, int G, int B) {
-
+    update_strip_time = millis();
+  }
+}
+
+void rgb2xy(int R, int G, int B)
+{
   // Convert the RGB values to XYZ using the Wide RGB D65 conversion formula
   float X = R * 0.664511f + G * 0.154324f + B * 0.162028f;
   float Y = R * 0.283881f + G * 0.668433f + B * 0.047685f;


Some clients are not quite compliant...

Some clients are not quite compliant...

--- ESP8266HueEmulator/ESP8266HueEmulator.ino
+++ ESP8266HueEmulator/ESP8266HueEmulator.ino
@@ -129,6 +129,9 @@
     }
     Serial.println(HTTP.arg("plain"));
     int numberOfTheLight = atoi(subStr(requestedUri.c_str(), "/", 4)) - 1; // The number of the light to be switched; they start with 1
+    if (numberOfTheLight == -1) {
+      numberOfTheLight = atoi(subStr(requestedUri.c_str(), "/", 3)) - 1;
+    }
     Serial.print("Number of the light --> ");
     Serial.println(numberOfTheLight);
     aJsonObject* parsedRoot = aJson.parse(( char*) HTTP.arg("plain").c_str());


Can switch on and off 3 pixels now

Can switch on and off 3 pixels now

--- ESP8266HueEmulator/ESP8266HueEmulator.ino
+++ ESP8266HueEmulator/ESP8266HueEmulator.ino
@@ -56,102 +56,16 @@
 String client = "e7x4kuCaC8h885jo"; // "UjBZ0nvTLu7aMdOe"; // The client string that the client app sends. Need to enter here what the app sends.
 // FIXME: Parse this out of what is being sent by the app.

-String getLightString(int lightNumber) {
-  String lightString = "\"" + String(lightNumber) + "\": {"
-                       "\"state\": {"
-                       "\"on\": true,"
-                       "\"bri\": 144,"
-                       "\"hue\": 13088,"
-                       "\"sat\": 212,"
-                       "\"xy\": [0.5128,0.4147],"
-                       "\"ct\": 467,"
-                       "\"alert\": \"none\","
-                       "\"effect\": \"none\","
-                       "\"colormode\": \"xy\","
-                       "\"reachable\": true"
-                       "},"
-                       "\"type\": \"Extended color light\","
-                       "\"name\": \"Hue Lamp 1\","
-                       "\"modelid\": \"LCT001\","
-                       "\"swversion\": \"66009461\","
-                       "\"pointsymbol\": {"
-                       "\"1\": \"none\","
-                       "\"2\": \"none\","
-                       "\"3\": \"none\","
-                       "\"4\": \"none\","
-                       "\"5\": \"none\","
-                       "\"6\": \"none\","
-                       "\"7\": \"none\","
-                       "\"8\": \"none\""
-                       "}"
-                       "}";
-  return lightString;
-}
-
-
 void handleAllOthers() {
   Serial.println("===");
   String requestedUri = HTTP.uri();
   Serial.print("requestedUri: ");
   Serial.println(requestedUri);

-String longstr = "{" // No [] around this one!
-                     " \"name\": \"Philips hue\","
-                     " \"zigbeechannel\": 0," // As per spec, 0 is allowed
-                     " \"mac\": \"" + macString + "\","
-                     " \"dhcp\": true,"
-                     " \"ipaddress\": \"" + ipString + "\","
-                     " \"netmask\": \"255.255.255.0\"," // TODO: FIXME
-                     " \"gateway\": \"192.168.0.1\"," // TODO: FIXME
-                     " \"proxyaddress\": \"none\","
-                     " \"proxyport\": 0,"
-                     " \"UTC\": \"2014-07-17T09:27:35\","
-                     //" \"localtime\": \"2014-07-17T11:27:35\"," // This was added in a bridge update at the beginning of 2014
-                     " \"timezone\": \"\","
-                     //" \"timezone\": \"Europe/Berlin\","
-                     " \"whitelist\": {"
-                     " \"" + client + "\": {"
-                     " \"last use date\": \"2015-06-17T07:21:38\","
-                     " \"create date\": \"2014-04-08T08:55:10\","
-                     " \"name\": \"Chroma for Hue\""
-                     " }"
-                     //  " \"pAtwdCV8NZId25Gk\": {"
-                     //   " \"last use date\": \"2014-05-07T18:28:29\","
-                     //   " \"create date\": \"2014-04-09T17:29:16\","
-                     //   " \"name\": \"MyApplication\""
-                     //   " },"
-                     //  " \"gDN3IaPYSYNPWa2H\": {"
-                     //  " \"last use date\": \"2014-05-07T09:15:21\","
-                     //  " \"create date\": \"2014-05-07T09:14:38\","
-                     //  " \"name\": \"iPhone Web 1\""
-                     //  " }"
-                     " },"
-                     " \"swversion\": \"01012917\","
-                     " \"apiversion\": \"1.3.0\","
-                     " \"swupdate\": {"
-                     " \"updatestate\": 0,"
-                     " \"url\": \"\","
-                     " \"text\": \"\","
-                     " \"notify\": false"
-                     " },"
-                     " \"linkbutton\": true,"
-                     " \"portalservices\": false,"
-                     " \"portalconnection\": \"connected\","
-                     " \"portalstate\": {"
-                     " \"signedon\": false,"
-                     " \"incoming\": false,"
-                     " \"outgoing\": true,"
-                     " \"communication\": \"disconnected\""
-                     " }"
-                     "}";
-
   if ( requestedUri.endsWith("/config") )
   {
-
-
-    //if (isAuthorized == false) longstr = "[{\"swversion\":\"01008227\",\"apiversion\":\"1.2.1\",\"name\":\"Smartbridge 1\",\"mac\":\"" + macString + "\",}]";
-    //HTTP.send(200, "text/plain", longstr);
-
+    // Using a library like in the following is probably the way to do; we can even do entirely without using String, saving memory.
+    // However, it is not entirely clear to me how to use it, see https://github.com/bblanchon/ArduinoJson/issues/85
     StaticJsonBuffer<200> jsonBuffer;
     JsonObject& root = jsonBuffer.createObject();
     root["name"] = "Philips hue";
@@ -171,7 +85,7 @@
     //HTTP.send(200, "text/plain", "[" + String(buffer) + "]");
     //Serial.println("[" + String(buffer) + "]");

-    longstr = "{\"portalservices\":false,\"gateway\":\"192.168.2.1\",\"mac\":\""+macString+"\",\"swversion\":\"01005215\",\"linkbutton\":false,\"ipaddress\":\""+ipString+"\",\"proxyport\":0,\"swupdate\":{\"text\":\"\",\"notify\":false,\"updatestate\":0,\"url\":\"\"},\"netmask\":\"255.255.255.0\",\"name\":\"Philips hue\",\"dhcp\":true,\"proxyaddress\":\"\",\"whitelist\":{\"newdeveloper\":{\"name\":\"test user\",\"last use date\":\"2012-10-29T12:00:00\",\"create date\":\"2012-10-29T12:00:00\"},\"e7x4kuCaC8h885jo\":{\"name\":\"appname#devicename\",\"last use date\":\"2015-07-05T17:07:39\",\"create date\":\"2015-07-05T16:58:10\"}},\"UTC\":\"2012-10-29T12:05:00\"}";
+    String longstr = "{\"portalservices\":false,\"gateway\":\"192.168.2.1\",\"mac\":\"" + macString + "\",\"swversion\":\"01005215\",\"linkbutton\":false,\"ipaddress\":\"" + ipString + "\",\"proxyport\":0,\"swupdate\":{\"text\":\"\",\"notify\":false,\"updatestate\":0,\"url\":\"\"},\"netmask\":\"255.255.255.0\",\"name\":\"Philips hue\",\"dhcp\":true,\"proxyaddress\":\"\",\"whitelist\":{\"newdeveloper\":{\"name\":\"test user\",\"last use date\":\"2012-10-29T12:00:00\",\"create date\":\"2012-10-29T12:00:00\"},\"e7x4kuCaC8h885jo\":{\"name\":\"appname#devicename\",\"last use date\":\"2015-07-05T17:07:39\",\"create date\":\"2015-07-05T16:58:10\"}},\"UTC\":\"2012-10-29T12:05:00\"}";

     HTTP.send(200, "text/plain", longstr);
     Serial.println(longstr);
@@ -180,8 +94,8 @@

   else if (requestedUri.endsWith(client))
   {
-    longstr = "{\"lights\":{\"1\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":4444,\"sat\":254,\"xy\":[0.0,0.0],\"ct\":0,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 1\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"2\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":23536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 2\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"3\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":65136,\"sat\":254,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 3\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}}},\"schedules\":{\"1\":{\"time\":\"2012-10-29T12:00:00\",\"description\":\"\",\"name\":\"schedule\",\"command\":{\"body\":{\"on\":true,\"xy\":null,\"bri\":null,\"transitiontime\":null},\"address\":\"/api/newdeveloper/groups/0/action\",\"method\":\"PUT\"}}},\"config\":{\"portalservices\":false,\"gateway\":\"192.168.2.1\",\"mac\":\""+macString+"\",\"swversion\":\"01005215\",\"linkbutton\":false,\"ipaddress\":\""+ipString+"\",\"proxyport\":0,\"swupdate\":{\"text\":\"\",\"notify\":false,\"updatestate\":0,\"url\":\"\"},\"netmask\":\"255.255.255.0\",\"name\":\"Philips hue\",\"dhcp\":true,\"proxyaddress\":\"\",\"whitelist\":{\"newdeveloper\":{\"name\":\"test user\",\"last use date\":\"2012-10-29T12:00:00\",\"create date\":\"2012-10-29T12:00:00\"},\"e7x4kuCaC8h885jo\":{\"name\":\"appname#devicename\",\"last use date\":\"2015-07-05T17:18:04\",\"create date\":\"2015-07-05T16:58:10\"}},\"UTC\":\"2012-10-29T12:05:00\"},\"groups\":{\"1\":{\"name\":\"Group 1\",\"action\":{\"on\":true,\"bri\":254,\"hue\":33536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":null,\"effect\":\"none\",\"colormode\":\"xy\",\"reachable\":null},\"lights\":[\"1\",\"2\"]}},\"scenes\":{}}";
-
+    String longstr = "{\"lights\":{\"1\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":4444,\"sat\":254,\"xy\":[0.0,0.0],\"ct\":0,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 1\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"2\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":23536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 2\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"3\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":65136,\"sat\":254,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 3\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}}},\"schedules\":{\"1\":{\"time\":\"2012-10-29T12:00:00\",\"description\":\"\",\"name\":\"schedule\",\"command\":{\"body\":{\"on\":true,\"xy\":null,\"bri\":null,\"transitiontime\":null},\"address\":\"/api/newdeveloper/groups/0/action\",\"method\":\"PUT\"}}},\"config\":{\"portalservices\":false,\"gateway\":\"192.168.2.1\",\"mac\":\"" + macString + "\",\"swversion\":\"01005215\",\"linkbutton\":false,\"ipaddress\":\"" + ipString + "\",\"proxyport\":0,\"swupdate\":{\"text\":\"\",\"notify\":false,\"updatestate\":0,\"url\":\"\"},\"netmask\":\"255.255.255.0\",\"name\":\"Philips hue\",\"dhcp\":true,\"proxyaddress\":\"\",\"whitelist\":{\"newdeveloper\":{\"name\":\"test user\",\"last use date\":\"2012-10-29T12:00:00\",\"create date\":\"2012-10-29T12:00:00\"},\"e7x4kuCaC8h885jo\":{\"name\":\"appname#devicename\",\"last use date\":\"2015-07-05T17:18:04\",\"create date\":\"2015-07-05T16:58:10\"}},\"UTC\":\"2012-10-29T12:05:00\"},\"groups\":{\"1\":{\"name\":\"Group 1\",\"action\":{\"on\":true,\"bri\":254,\"hue\":33536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":null,\"effect\":\"none\",\"colormode\":\"xy\",\"reachable\":null},\"lights\":[\"1\",\"2\"]}},\"scenes\":{}}";
+
     HTTP.send(200, "text/plain", longstr);
     Serial.println(longstr);
     Serial.println("Responded with complete json as in https://github.com/probonopd/ESP8266HueEmulator/wiki/Hue-API#get-all-information-about-the-bridge");
@@ -189,13 +103,13 @@

   else if (requestedUri.endsWith("UjBZ0nvTLu7aMdOe")) // FIXME: remove this!!! This is the same as above, but for same strange reason the Chroma app is using a different username!
   {
-    longstr = "{\"lights\":{\"1\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":4444,\"sat\":254,\"xy\":[0.0,0.0],\"ct\":0,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 1\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"2\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":23536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 2\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"3\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":65136,\"sat\":254,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 3\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}}},\"schedules\":{\"1\":{\"time\":\"2012-10-29T12:00:00\",\"description\":\"\",\"name\":\"schedule\",\"command\":{\"body\":{\"on\":true,\"xy\":null,\"bri\":null,\"transitiontime\":null},\"address\":\"/api/newdeveloper/groups/0/action\",\"method\":\"PUT\"}}},\"config\":{\"portalservices\":false,\"gateway\":\"192.168.2.1\",\"mac\":\""+macString+"\",\"swversion\":\"01005215\",\"linkbutton\":false,\"ipaddress\":\""+ipString+"\",\"proxyport\":0,\"swupdate\":{\"text\":\"\",\"notify\":false,\"updatestate\":0,\"url\":\"\"},\"netmask\":\"255.255.255.0\",\"name\":\"Philips hue\",\"dhcp\":true,\"proxyaddress\":\"\",\"whitelist\":{\"newdeveloper\":{\"name\":\"test user\",\"last use date\":\"2012-10-29T12:00:00\",\"create date\":\"2012-10-29T12:00:00\"},\"e7x4kuCaC8h885jo\":{\"name\":\"appname#devicename\",\"last use date\":\"2015-07-05T17:18:04\",\"create date\":\"2015-07-05T16:58:10\"}},\"UTC\":\"2012-10-29T12:05:00\"},\"groups\":{\"1\":{\"name\":\"Group 1\",\"action\":{\"on\":true,\"bri\":254,\"hue\":33536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":null,\"effect\":\"none\",\"colormode\":\"xy\",\"reachable\":null},\"lights\":[\"1\",\"2\"]}},\"scenes\":{}}";
-
+    String longstr = "{\"lights\":{\"1\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":4444,\"sat\":254,\"xy\":[0.0,0.0],\"ct\":0,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 1\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"2\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":23536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 2\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}},\"3\":{\"state\":{\"on\":true,\"bri\":254,\"hue\":65136,\"sat\":254,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":\"none\",\"effect\":\"none\",\"colormode\":\"hs\",\"reachable\":true},\"type\":\"Extended color light\",\"name\":\"Hue Lamp 3\",\"modelid\":\"LCT001\",\"swversion\":\"65003148\",\"pointsymbol\":{\"1\":\"none\",\"2\":\"none\",\"3\":\"none\",\"4\":\"none\",\"5\":\"none\",\"6\":\"none\",\"7\":\"none\",\"8\":\"none\"}}},\"schedules\":{\"1\":{\"time\":\"2012-10-29T12:00:00\",\"description\":\"\",\"name\":\"schedule\",\"command\":{\"body\":{\"on\":true,\"xy\":null,\"bri\":null,\"transitiontime\":null},\"address\":\"/api/newdeveloper/groups/0/action\",\"method\":\"PUT\"}}},\"config\":{\"portalservices\":false,\"gateway\":\"192.168.2.1\",\"mac\":\"" + macString + "\",\"swversion\":\"01005215\",\"linkbutton\":false,\"ipaddress\":\"" + ipString + "\",\"proxyport\":0,\"swupdate\":{\"text\":\"\",\"notify\":false,\"updatestate\":0,\"url\":\"\"},\"netmask\":\"255.255.255.0\",\"name\":\"Philips hue\",\"dhcp\":true,\"proxyaddress\":\"\",\"whitelist\":{\"newdeveloper\":{\"name\":\"test user\",\"last use date\":\"2012-10-29T12:00:00\",\"create date\":\"2012-10-29T12:00:00\"},\"e7x4kuCaC8h885jo\":{\"name\":\"appname#devicename\",\"last use date\":\"2015-07-05T17:18:04\",\"create date\":\"2015-07-05T16:58:10\"}},\"UTC\":\"2012-10-29T12:05:00\"},\"groups\":{\"1\":{\"name\":\"Group 1\",\"action\":{\"on\":true,\"bri\":254,\"hue\":33536,\"sat\":144,\"xy\":[0.346,0.3568],\"ct\":201,\"alert\":null,\"effect\":\"none\",\"colormode\":\"xy\",\"reachable\":null},\"lights\":[\"1\",\"2\"]}},\"scenes\":{}}";
+
     HTTP.send(200, "text/plain", longstr);
     Serial.println(longstr);
     Serial.println("Responded with complete json as in https://github.com/probonopd/ESP8266HueEmulator/wiki/Hue-API#get-all-information-about-the-bridge");
   }
-
+
   else if (requestedUri.endsWith("/api"))
     // On the real bridge, the link button on the bridge must have been recently pressed for the command to execute successfully.
     // We try to execute successfully regardless of a button for now.
@@ -206,12 +120,32 @@
     Serial.println(str);
   }

-  else if (requestedUri.endsWith("/lights"))
-    // We simulate one bulb per NeoPixel (TODO: more clever ideas?)
-  {
-    String str = "[{ " + getLightString(1) + "}]";
+  else if (requestedUri.endsWith("/state"))
+  {
+    String str = "{ \"state\": { \"hue\": 50000, \"on\": true, \"effect\": \"none\", \"alert\": \"none\", \"bri\": 200, \"sat\": 200, \"ct\": 500, \"xy\": [0.5, 0.5], \"reachable\": true, \"colormode\": \"hs\" }, \"type\": \"Living Colors\", \"name\": \"LC 1\", \"modelid\": \"LC0015\", \"swversion\": \"1.0.3\", \"pointsymbol\": { \"1\": \"none\", \"2\": \"none\", \"3\": \"none\", \"4\": \"none\", \"5\": \"none\", \"6\": \"none\", \"7\": \"none\", \"8\": \"none\" } }";
     HTTP.send(200, "text/plain", str);
     Serial.println(str);
+    // For this to work we need a patched version of esp8266/libraries/ESP8266WebServer/src/Parsing.cpp which hopefully lands in the official channel soon
+    // https://github.com/me-no-dev/Arduino/blob/d4894b115e3bbe753a47b1645a55cab7c62d04e2/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/Parsing.cpp
+    Serial.println(HTTP.arg("plain"));
+    int numberOfTheLight = atoi(subStr(requestedUri.c_str(), "/", 4)); // The number of the light to be switched; they start with 1
+    Serial.print("Number of the light --> ");
+    Serial.println(numberOfTheLight);
+
+    StaticJsonBuffer<200> jsonBuffer;
+    JsonObject& root = jsonBuffer.parseObject(( char*) HTTP.arg("plain").c_str());
+    if (!root.success()) {
+      Serial.println("parseObject() failed");
+      return;
+    }
+   bool onValue = root["on"];
+    Serial.print("I should --> ");
+    Serial.println(onValue);
+    if (onValue == true)
+      strip.SetPixelColor(numberOfTheLight - 1, white); // For now we ignore the color (FIXME)
+    if (onValue == false)
+      strip.SetPixelColor(numberOfTheLight - 1, black);
+    strip.Show();
   }

   else if (requestedUri == "/description.xml")
@@ -227,6 +161,10 @@
   {
     HTTP.send(404, "text/plain", "File not found");
     Serial.println("FIXME: To be implemented");
+
+    // Print what the client has POSTed
+    for (uint8_t i = 0; i < HTTP.args(); i++) Serial.printf("ARG[%u]: %s=%s\n", i, HTTP.argName(i).c_str(), HTTP.arg(i).c_str());
+
   }
 }

@@ -317,3 +255,18 @@
     strip.Show();
   }
 }
+
+// Function to return a substring defined by a delimiter at an index
+// From http://forum.arduino.cc/index.php?topic=41389.msg301116#msg301116
+char* subStr(const char* str, char *delim, int index) {
+  char *act, *sub, *ptr;
+  static char copy[128]; // Length defines the maximum length of the c_string we can process
+  int i;
+  strcpy(copy, str); // Since strtok consumes the first arg, make a copy
+  for (i = 1, act = copy; i <= index; i++, act = NULL) {
+    //Serial.print(".");
+    sub = strtok_r(act, delim, &ptr);
+    if (sub == NULL) break;
+  }
+  return sub;
+}


Update ffdgjghk.ino

Update ffdgjghk.ino

--- temp/ffdgjghk.ino
+++ temp/ffdgjghk.ino
@@ -21,7 +21,7 @@
   CK_A+=ubx_data;
   CK_B+=CK_A;
 }
-void getUBX(void) //
+void getUBX(void) //Получаем покет и делаем с ним штуки
 {
   if (Serial.available())
   {


Change pin numbers to correlate to the changes during soldering

--- teensy_octo.ino
+++ teensy_octo.ino
@@ -4,7 +4,7 @@
  * Custom-built USB peripheral with eight buttons, a RGB LED and a Piezo speaker.
  * Based on the Teensy 2 microcontroller - http://www.pjrc.com/teensy
  *
- * Made as a birthday present to Waher (http://waher.net/about-waher-net)
+ * Created as a birthday present to Waher (http://waher.net/about-waher-net)
  *
  * @author David <david@sqroot.eu> 2013
  *
@@ -21,7 +21,7 @@
 #define NUMBER_OF_BUTTONS 8

 // Define digital pins for the buttons
-const byte BUTTON_PINS[] = {0, 1, 2, 3, 13, 16, 17, 18};
+const byte BUTTON_PINS[] = {0, 1, 2, 3, 7, 8, 20, 21};

 // Initialize button objects
 Bounce buttons[NUMBER_OF_BUTTONS] = {
@@ -36,12 +36,12 @@
 };

 // Define PWM pins for the RGB LED
-const byte RGB_RED = 4;
-const byte RGB_GREEN = 5;
-const byte RGB_BLUE = 23;
+const byte RGB_RED = 5;
+const byte RGB_GREEN = 9;
+const byte RGB_BLUE = 10;

 // The Piezo buzzer sits in this PWM pin
-const byte BUZZER_PIN = 12;
+const byte BUZZER_PIN = 4;

 /**
  * Setup function - run once on power-on


Improved the example

Improved the example

--- examples/JsonGeneratorExample/JsonGeneratorExample.ino
+++ examples/JsonGeneratorExample/JsonGeneratorExample.ino
@@ -1,5 +1,5 @@
 /*
- * Arduino JSON library
+ * Arduino JSON library - Generator example
  * Benoit Blanchon 2014 - MIT License
  */

@@ -11,22 +11,20 @@
 {
     Serial.begin(9600);

-    JsonHashTable<3> h;
+    JsonHashTable<3> json;

-    h.add("pi", 3.14159265358979323846, 4);
+    json.add("sensor", "gps");
+    json.add("time", 1351824120);

-    JsonArray<3> a;
-    a.add(1);
-    a.add(2);
-    a.add(3);
-    h.add("list", a);
+    JsonArray<3> array;
+    array.add(48.756080, 6);
+    array.add(2.302038, 6);
+    json.add("data", array);

-    h.add("hello", "world");
-
-    Serial.print(h);
+    Serial.print(json); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
 }

 void loop()
 {

-}
+}


example - print files during enumeration by default

--- examples/SmartMatrixGifPlayer/SmartMatrixGifPlayer.ino
+++ examples/SmartMatrixGifPlayer/SmartMatrixGifPlayer.ino
@@ -217,7 +217,7 @@
     }

     // Determine how many animated GIF files exist
-    num_files = enumerateGIFFiles(GIF_DIRECTORY, false);
+    num_files = enumerateGIFFiles(GIF_DIRECTORY, true);

     if(num_files < 0) {
 #if (ENABLE_SCROLLING == 1)