Fixed typo error in code

Fixed typo error in code

--- src/HC_NodeMcuCode.ino
+++ src/HC_NodeMcuCode.ino
@@ -118,8 +118,8 @@
 float targetCoolerTemperature = 25;

 // Target temperature Hysteresis
-const float targetHeaterTemperatureHyst = 1; // DHT22 has 0.5 accuracy
-const float targetCoolerTemperatureHyst = 1; // DHT22 has 0.5 accuracy
+const float targetHeaterTemperatureHyst = 2; // DHT22 has 0.5 accuracy
+const float targetCoolerTemperatureHyst = 3; // DHT22 has 0.5 accuracy

 // Output powered status
 bool outputHeaterPoweredStatus = false;
@@ -475,7 +475,7 @@
         Serial.print(F("Output heater state published to [")), Serial.print(publishHeaterOutputState), Serial.println("] ");

       String strCoolerOutput = String(outputCoolerPoweredStatus);
-      if (!mqttClient.publish(publishHeaterOutputState, strCoolerOutput.c_str()))
+      if (!mqttClient.publish(publishCoolerOutputState, strCoolerOutput.c_str()))
         Serial.print(F("Failed to output cooler state to [")), Serial.print(publishCoolerOutputState), Serial.print("] ");
       else
         Serial.print(F("Output cooler state published to [")), Serial.print(publishCoolerOutputState), Serial.println("] ");


bug fix

bug fix

--- WeatherStation/WeatherStation.ino
+++ WeatherStation/WeatherStation.ino
@@ -106,8 +106,8 @@
       lx = 0xFFFF;
   }
   Serial.print("'AmbientLight':"); printValue(lx);
-  Serial.print("'BroadbandLight':"); printValue(broadband);
-  Serial.print("'Infrared':"); printValue(infrared);
+  Serial.print("'BroadbandLight':"); printValue((long)broadband);
+  Serial.print("'Infrared':"); printValue((long)infrared);

   Serial.println("}}");

@@ -117,6 +117,17 @@
   digitalWrite(XBEESLEEPPIN, HIGH);  //Put XBEE to sleep

   sleep(60000);
+}
+
+void printValue(float value){
+  if (!isnan(value))
+  {
+    Serial.print(value); Serial.print(", ");
+  }
+  else
+  {
+    Serial.print("'NaN', ");
+  }
 }

 void printValue(long value){


sketch now works with analog pins, reports are nicer looking too

--- examples/StandardFirmata/StandardFirmata.ino
+++ examples/StandardFirmata/StandardFirmata.ino
@@ -34,6 +34,9 @@
 #include <SPI.h>
 #include <BLE_Firmata.h>
 #include "Adafruit_BLE_UART.h"
+
+
+#define AUTO_INPUT_PULLUPS true

 // Connect CLK/MISO/MOSI to hardware SPI
 // e.g. On UNO & compatible: CLK = 13, MISO = 12, MOSI = 11
@@ -140,7 +143,7 @@
   portValue = portValue & portConfigInputs[portNumber];
   // only send if the value is different than previously sent
   if(forceSend || previousPINs[portNumber] != portValue) {
-    Serial.println(F("Sending update"));
+    Serial.print(F("Sending update for port ")); Serial.print(portNumber); Serial.print(" = 0x"); Serial.println(portValue, HEX);
     BLE_Firmata.sendDigitalPort(portNumber, portValue);
     previousPINs[portNumber] = portValue;
   }
@@ -201,16 +204,15 @@
     break;
   case INPUT:
     if (IS_PIN_DIGITAL(pin)) {
-      Serial.println("input");
+      Serial.print("Set pin #"); Serial.print(pin); Serial.println(" to input");
       pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
-      digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+      if (AUTO_INPUT_PULLUPS) {
+        digitalWrite(PIN_TO_DIGITAL(pin), HIGH); // enable internal pull-ups
+      } else {
+        digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
+      }
       pinConfig[pin] = INPUT;

-      // MEME update so we have an update report
-      uint8_t tempport = pin/8;
-      uint8_t temppin = reportPINs[tempport];
-      reportDigitalCallback(tempport, temppin | (1<<(pin % 8)));
-      //
     }
     break;
   case OUTPUT:
@@ -312,7 +314,7 @@
 void reportDigitalCallback(byte port, int value)
 {
   if (port < TOTAL_PORTS) {
-    Serial.print("Report 0x"); Serial.print(value, HEX); Serial.print(" digital on "); Serial.println(port);
+    Serial.print("Will report 0x"); Serial.print(value, HEX); Serial.print(" digital mask on port "); Serial.println(port);
     reportPINs[port] = (byte)value;
   }
   // do not disable analog reporting on these 8 pins, to allow some
@@ -658,12 +660,6 @@
     BLEserial.write(Serial.read());

   }
-  pinMode(4, INPUT);
-  if (! digitalRead(4)) {
-     uint8_t foo[3] = {'a', 'b', 'c'};
-     BLEserial.write(foo, 3);
-    delay(500);
-  }
   byte pin, analogPin;

   /* DIGITALREAD - as fast as possible, check for changes and output them to the


Allow a little bigger bandwidth

Allow a little bigger bandwidth

--- fanatec_standalone_shifter_and_handbrake.ino
+++ fanatec_standalone_shifter_and_handbrake.ino
@@ -35,7 +35,7 @@
   int x = analogRead(PIN_SHIFTER_X);
   int y = analogRead(PIN_SHIFTER_Y);

-  if (y > 1000) {
+  if (y > 900) {
     if (x < 100) {
       return GEAR_7;
     }


Extract common strings to save bytes

Extract common strings to save bytes

--- battlestation/arduino/arduino.ino
+++ battlestation/arduino/arduino.ino
@@ -68,9 +68,9 @@

     if (c == '\n') {
       cmd[cmd_idx] = 0;
-      exec_cmd();
+      exec_cmd(cmd);
     } else {
-      Serial.println  ("command too long");
+      Serial.print("command too long\n");
     }

     // Done executing or buffer is full before newline
@@ -80,7 +80,7 @@
   }
 }

-void exec_cmd(const char * cmd) {
+void exec_cmd(char * cmd) {
   boolean ok = false;
   char * tok = NULL;
   const char * cmd_name = strtok_r(cmd, " ", &tok);
@@ -92,30 +92,36 @@
     // the "ok" is the result
     ok = true;
   } else if (strcmp(cmd_name, "h") == 0) {
-    Serial.println("f(lash) s");
-    Serial.println("h(elp)");
-    Serial.println("s(core) s t # t # t #");
-    Serial.println("p(ing)");
+    Serial.print("f(lash) s\n");
+    Serial.print("h(elp)\n");
+    Serial.print("s(core) s t # t # t #\n");
+    Serial.print("p(ing)\n");
     ok = true;
   }

   if (ok) {
-    Serial.println("ok");
+    Serial.print("ok\n");
   } else {
-    Serial.println("err");
-  }
-}
+    Serial.print("err\n");
+  }
+}
+
+static const char * e_strip_required = "strip required\n";
+static const char * e_strip_nums = "strip is 0,1,2,3\n";
+static const char * e_team_required = "team required\n";
+static const char * e_team_nums = "team is 0,1,2\n";
+static const char * e_led_required = "led # required\n";

 boolean exec_flash(char * tok) {
   // Read strip number
   char * arg = strtok_r(NULL, " ", &tok);
   if (arg == NULL) {
-    Serial.println("strip required");
+    Serial.print(e_strip_required);
     return false;
   }
   int strip = atoi(arg);
   if (strip > 3) {
-    Serial.println("strip is 0,1,2,3");
+    Serial.print(e_strip_nums);
     return false;
   }
   flash(*score_strips[strip], Adafruit_NeoPixel::Color(255, 255, 0), 5, 80);
@@ -126,12 +132,12 @@
   // Read strip number
   char * arg = strtok_r(NULL, " ", &tok);
   if (arg == NULL) {
-    Serial.println("strip required");
+    Serial.print(e_strip_required);
     return false;
   }
   int strip = atoi(arg);
   if (strip > 3) {
-    Serial.println("strip is 0,1,2,3");
+    Serial.print(e_strip_nums);
     return false;
   }

@@ -141,19 +147,19 @@
     // Read the team
     arg = strtok_r(NULL, " ", &tok);
     if (arg == NULL) {
-      Serial.println("team required");
+      Serial.print(e_team_required);
       return false;
     }
     int team = atoi(arg);
     if (team > 2) {
-      Serial.println("team is 0,1,2");
+      Serial.print(e_team_nums);
       return false;
     }

     // Read the LED count
     arg = strtok_r(NULL, " ", &tok);
     if (arg == NULL) {
-      Serial.println("led # required");
+      Serial.print(e_led_required);
       return false;
     }
     int team_leds = atoi(arg);


Added uS_MAX

Added uS_MAX

--- Arduino/PaddleEmulator/PaddleEmulator.ino
+++ Arduino/PaddleEmulator/PaddleEmulator.ino
@@ -7,7 +7,8 @@
 #define PIN_POTX_OUT   8
 #define PIN_POTY_OUT   7

-#define uS_MIN  3   // Smallest permissible value.  See http://www.arduino.cc/en/Reference/DelayMicroseconds
+#define uS_MIN  3    // Smallest permissible value.  See http://www.arduino.cc/en/Reference/DelayMicroseconds
+#define uS_MAX  243  // Larger values cause the interrupt to take too long

 volatile uint16_t potXleads=1;        // if 0, y leads
 volatile uint16_t potXdelay=uS_MIN;
@@ -60,9 +61,9 @@
      delayX -= delayY;
    }

-   if (delayX > 250)    delayX = 250;     // Larger values cause the interrupt to take too long
+   if (delayX > uS_MAX) delayX = uS_MAX;
    if (delayX < uS_MIN) delayX = uS_MIN;
-   if (delayY > 250)    delayY = 250;
+   if (delayY > uS_MAX) delayY = uS_MAX;
    if (delayY < uS_MIN) delayY = uS_MIN;

    potXdelay = delayX;


Garbage Cleanup Simplification

Garbage Cleanup Simplification

--- ArduinoController/ArduinoController.ino
+++ ArduinoController/ArduinoController.ino
@@ -5,8 +5,10 @@

 #if defined(__AVR_ATmega328P__)
 #define UNO
+#define GARBAGE 240
 #elif defined(__AVR_ATSAM3X8E__)
 #define DUE
+#define GARBAGE 0
 #endif

 #include "Accessories/LedController.h"
@@ -62,11 +64,7 @@
 void clearBuffer() {
   while(true) {
     if(Serial.available()) {
-#ifdef UNO
-      if(Serial.read() != 240)
-#else
-      if(Serial.read() != 0)
-#endif
+      if(Serial.read() != GARBAGE)
         break;
     }
   }


Optimized port operations

Optimized port operations

Sketch uses 14750 bytes (45%) of program storage space.
Global variables use 634 bytes (30%) of dynamic memory

--- Rubiks_cube_sketch/Rubiks_cube_sketch.ino
+++ Rubiks_cube_sketch/Rubiks_cube_sketch.ino
@@ -108,12 +108,12 @@
 //Setup method
 void setup() {
   // Initializing pins modes
-  pinMode(S0, OUTPUT);
-  pinMode(S1, OUTPUT);
-  pinMode(S2, OUTPUT);
-  pinMode(S3, OUTPUT);
-  //DDRB = B01111000;
-  pinMode(scanSensor, INPUT);
+  //pinMode(S0, OUTPUT);
+  //pinMode(S1, OUTPUT);
+  //pinMode(S2, OUTPUT);
+  //pinMode(S3, OUTPUT);
+  //pinMode(scanSensor, INPUT);
+  DDRB = B00011110;

   //Attaching the motors
   Motor1.attach(rotateMotorPin);
@@ -134,8 +134,9 @@
   delay(standardDelay);

   // Setting frequency-scaling to 20%
-  digitalWrite(S0, HIGH);
-  digitalWrite(S1, LOW);
+  //digitalWrite(S0, HIGH);
+  //digitalWrite(S1, LOW);
+  PORTB = B00000010;

   //Initialize LCD
   lcd.init();
@@ -254,7 +255,8 @@

 //Method from class Button to perform digital debouncing
 void Button::filterAvarage() {
-  if (flagPress != !digitalRead(_pin) ) {
+  //if (flagPress != !digitalRead(_pin) ) {
+  if (flagPress != !bitRead(PIND, _pin)) {
     if ( _buttonCount != 0 ) _buttonCount--;
     }
   else {
@@ -272,7 +274,7 @@
 Button::Button(byte pin, byte timeButton) {
   _pin= pin;
   _timeButton= timeButton;
-  pinMode(_pin, INPUT);
+  //pinMode(_pin, INPUT);
 }

@@ -824,20 +826,23 @@
 void scan_item() {
   delay(50);
   // Setting red filtered photodiodes to be read
-  digitalWrite(S2,LOW);
-  digitalWrite(S3,LOW);
+  //digitalWrite(S2,LOW);
+  //digitalWrite(S3,LOW);
+  PORTB = B00000010;
   // Reading the output frequency
   f_RED = pulseIn(scanSensor, LOW);
   delay(50);
   // Setting Green filtered photodiodes to be read
-  digitalWrite(S2,HIGH);
-  digitalWrite(S3,HIGH);
+  //digitalWrite(S2,HIGH);
+  //digitalWrite(S3,HIGH);
+  PORTB = B00011010;
   // Reading the output frequency
   f_GREEN = pulseIn(scanSensor, LOW);
   delay(50);
   // Setting Blue filtered photodiodes to be read
-  digitalWrite(S2,LOW);
-  digitalWrite(S3,HIGH);
+  //digitalWrite(S2,LOW);
+  //digitalWrite(S3,HIGH);
+  PORTB = B00010010;
   // Reading the output frequency
   f_BLUE = pulseIn(scanSensor, LOW);
   delay(50);


fix docs

fix docs

--- sketches/EnerginoBattery/EnerginoBattery.ino
+++ sketches/EnerginoBattery/EnerginoBattery.ino
@@ -22,7 +22,7 @@
  *  #Z, print settings
  *
  * Serial putput:
- *   #Energino,0,<voltage>,<current>,<power>,<relay>,<period>,<samples>,<voltage_error>,<current_error>
+ *   #Energino,0,<voltage>,<current>,<power>,<relay>,<period>,<samples>,<voltage_error>,<current_error>,<battery>,<battery_fitted>
  *
  * created 31 October 2012
  * by Roberto Riggio


include test code for OLED

include test code for OLED

--- ksp-gegi-microusb/ksp-gegi-microusb.ino
+++ ksp-gegi-microusb/ksp-gegi-microusb.ino
@@ -5,6 +5,9 @@
 #include <LiquidCrystal_I2C.h> // Using version 1.2.1
 // https://github.com/MHeironimus/ArduinoJoystickLibrary
 #include <Joystick.h>
+#include "U8glib.h"
+
+U8GLIB_SSD1306_128X64_2X u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST); // more RAM used, FAST transfer

 // IDE: Arduino/Genuino Micro

@@ -346,11 +349,53 @@
   }
 }

+uint8_t offset = 0;
+
+void draw(void) {
+  // graphic commands to redraw the complete screen should be placed here
+  u8g.setFont(u8g_font_unifont);
+  u8g.drawStr( 0+0, 20+0, "Hello!");
+  u8g.drawStr( 0+2, 20+16, "Hello!");
+
+  u8g.drawBox(0, 0, 17, 17);
+  u8g.drawBox(u8g.getWidth()-20, 0, 3, 3);
+  u8g.drawBox(u8g.getWidth()-9, u8g.getHeight()-9, 9, 9);
+  u8g.drawBox(0, u8g.getHeight()-12, 12, 12);
+}
+
+void rotate(void) {
+  static  uint8_t dir = 0;
+  static  unsigned long next_rotation = 0;
+
+  if ( next_rotation < millis() )
+  {
+    switch(dir) {
+      case 0: u8g.undoRotation(); break;
+      case 1: u8g.setRot90(); break;
+      case 2: u8g.setRot180(); break;
+      case 3: u8g.setRot270(); offset = ( offset + 1 ) & 0x0f; break;
+    }
+
+    dir++;
+    dir &= 3;
+    next_rotation = millis();
+    next_rotation += 1000;
+  }
+}
+
 void loop() {
   checkSerialInputUSBtoUART();
   checkSerialInputUARTtoUSB();
   updatePins(false);
   updateAnalogs(false);
   delay(50);
-}
-
+  // screen rotation
+  rotate();
+
+  // picture loop
+  u8g.firstPage();
+  do {
+    draw();
+  } while( u8g.nextPage() );
+}
+


added reverse to drive.ino

added reverse to drive.ino


Add libraries and more buttons

Add libraries and more buttons

--- midicontroller.ino
+++ midicontroller.ino
@@ -1,12 +1,32 @@
+#include <Bounce2.h>
+
+#include <Adafruit_GFX.h>
+
+#include <SPI.h>
+
+#include <Wire.h>
+
+#include <Adafruit_SSD1306.h>
+
 #include "base64/Base64.h"

-const int ledPin = 13;
 byte counter;
 const byte CLOCK = 248;
 const byte START = 250;
 const byte CONTINUE = 251;
 const byte STOP = 252;
-const int redLed = 1;
+const int ledPin = 13;
+
+const byte channelButtonStart = 0;
+//const byte channelButtonLedStart = 14;
+const byte numberOfChannelButtons = 2;
+const byte ledPins[] = {/*10, 11, 12,*/ 14, 15, 16};
+Bounce channelButtons[numberOfChannelButtons];
+boolean channelButtonStates[numberOfChannelButtons];
+boolean channelButtonDown[numberOfChannelButtons];
+
+const byte bpmLed = 22;
+

 void OnNoteOn(byte channel, byte note, byte velocity)
 {
@@ -32,25 +52,79 @@

 }

+void setupButtons() {
+  for (byte i = 0; i < numberOfChannelButtons; i++) {
+    pinMode(channelButtonStart + i, INPUT_PULLUP);
+    channelButtons[i].attach(channelButtonStart + i);
+    channelButtons[i].interval(10);
+    channelButtonStates[i] = false;
+    channelButtonDown[i] = false;
+  }
+}
+
+void setupLeds() {
+  pinMode(ledPin, OUTPUT);
+  pinMode(bpmLed, OUTPUT);
+  for (byte i = 0; i < numberOfChannelButtons; i++) {
+    pinMode(ledPins[i], OUTPUT);
+  }
+}
+
+
 void setup()
 {
-  pinMode(ledPin, OUTPUT);
-  pinMode(redLed, OUTPUT);
+  setupButtons();
+  setupLeds();
+
   Serial.begin(9600);
   usbMIDI.setHandleNoteOff(OnNoteOff);
   usbMIDI.setHandleNoteOn(OnNoteOn);
-  digitalWrite(ledPin, HIGH);
-  delay(1000);
-  digitalWrite(ledPin, LOW);
-  delay(1000);
   usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
   usbMIDI.setHandleSysEx(SystemExclusiveMessage);
+
+  ledTest();
+
   Serial.println("start");
+}
+
+void ledTest() {
+  ledTest(ledPin);
+  ledTest(bpmLed);
+  for (byte i = 0; i < numberOfChannelButtons; i++) {
+    ledTest(ledPins[i]);
+    //    digitalWrite(channelButtonLedStart +i,HIGH);
+  }
+}
+
+void ledTest(byte pin) {
+  digitalWrite(pin, HIGH);
+  delay(200);
+  digitalWrite(pin, LOW);
+  delay(200);
+}
+
+void updateButtons() {
+  for (byte i = 0; i < numberOfChannelButtons; i++) {
+    if (channelButtons[i].update()) {
+      if (channelButtons[i].read() == LOW) {
+        channelButtonDown[i] = true;
+      } else if (channelButtonDown[i]) {
+        channelButtonStates[i] = 1 - channelButtonStates[i];
+        channelButtonDown[i] = false;
+        if (channelButtonStates[i]) {
+          digitalWrite(ledPins[i], HIGH);
+        } else {
+          digitalWrite(ledPins[i], LOW);
+        }
+      }
+    }
+  }
 }

 void loop()
 {
   usbMIDI.read();
+  updateButtons();
 }

 void RealTimeSystem(byte realtimebyte) {
@@ -58,24 +132,24 @@
     counter++;
     if (counter == 24) {
       counter = 0;
-      digitalWrite(redLed, HIGH);
+      digitalWrite(bpmLed, HIGH);
     }
     if (counter == 23) {
-      digitalWrite(redLed, HIGH);
+      digitalWrite(bpmLed, HIGH);
     }

     if (counter == 6) {
-      digitalWrite(redLed, LOW);
+      digitalWrite(bpmLed, LOW);
     }
   }

   if (realtimebyte == START || realtimebyte == CONTINUE) {
     counter = 0;
-    digitalWrite(redLed, HIGH);
+    digitalWrite(bpmLed, HIGH);
   }

   if (realtimebyte == STOP) {
-    digitalWrite(redLed, LOW);
+    digitalWrite(bpmLed, LOW);
   }
 }


Modified main to include new classes.

Modified main to include new classes.

--- oktopus-autopilote/oktopus-autopilote.ino
+++ oktopus-autopilote/oktopus-autopilote.ino
@@ -5,6 +5,8 @@
 // Revision: v0.0.1
 // Licence: Apache License Version 2.0, January 2004 http://www.apache.org/licenses/

+#include "PIDController.h"
+#include "ESC.h"
 #include "GPS.h"
 #include "Gyroscope.h"
 #include "Moisture.h"
@@ -16,14 +18,17 @@
 int averageDataSamples(int dataSamples[], int numberOfSamples);

 LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
+PIDController PIDController;
+ESC esc(1500, 2000, 3);
 GPS gps;
 Gyroscope gyroscope;
 Moisture moistureSensor;
 RudderServo rudderServo;
 Temperature temperatureSensor;

-int heading[15];
-NMEAData gpsData;
+double heading;
+NMEAData currentGpsData;
+NMEAData nextGpsData;
 String moisture = "Unknown";
 short temperature = 0;
 int angle = 0;
@@ -41,51 +46,48 @@
   lcd.print("Oktopus");
   lcd.setCursor(0, 1);
   lcd.print("autopilot");
+
+  rudderServo.setAngle(-40);
+  delay(500);
+  rudderServo.setAngle(0);
+  delay(500);
+  rudderServo.setAngle(40);
+  delay(500);
 }

 uint32_t timer1 = millis();
 uint32_t timer2 = millis();
 uint8_t count = 0;
+double theta = 0.0;
+double rudder = 0.0;

 void loop() {

-  gpsData = gps.getData();
-
+  currentGpsData = gps.getData();
+  nextGpsData.longitude = currentGpsData.longitude + 5;
+  nextGpsData.latitude = currentGpsData.latitude + 5;
   // if millis() or timer wraps around, we'll just reset it
   if (timer1 > millis())  timer1 = millis();
   if (timer2 > millis())  timer2 = millis();
-

-  if (millis() - timer1 > 100) {
+  if (millis() - timer1 > 1000) {
     timer1 = millis(); // reset the time
-    heading[count] = gyroscope.getData();
-    if (count < 14) {
-      count++;
-    } else {
-      count = 0;
-    }
+    heading = gyroscope.getData(LSM_303);
+    theta = PIDController.compute_theta(currentGpsData, nextGpsData, heading);
+    rudder = PIDController.control_rudder(theta);
+    cycleDataOnLCD();
   }
+
   if (millis() - timer2 > 2500) {
-    gps.printData(gpsData);
-    rudderServo.setAngle(-40);
-    delay(500);
-    rudderServo.setAngle(0);
-    delay(500);
-    rudderServo.setAngle(40);
-    delay(500);
+    gps.printData(currentGpsData);
   }
   if (millis() - timer2 > 5000) {
       timer2 = millis(); // reset the time
-
-      angle = rudderServo.getData();
       moisture = moistureSensor.getData();
       temperature = temperatureSensor.getData();

-      gyroscope.printData(averageDataSamples(heading, 15));
       moistureSensor.printData(moisture);
-      rudderServo.printData(angle);
       temperatureSensor.printData(temperature);
-      cycleDataOnLCD();
   }
 }

@@ -93,14 +95,28 @@
   lcd.clear();
   lcd.setCursor(0, 0);
   lcd.print("GYR:");
-  lcd.print(averageDataSamples(heading, 15));
+  lcd.print((int)heading);
+  lcd.print(" SAF:");
+  lcd.print((int)rudder);
+  lcd.setCursor(0, 1);
+  lcd.print("TTA:");
+  lcd.print((int)theta);
+  /*
+  lcd.print(" LAT:");
+  lcd.print((int)currentGpsData.latitude);
+  */
+  /*
+  lcd.print(" LON:");
+  lcd.print((int)currentGpsData.longitude);
+  */
+  /*
   lcd.print(" HUM:");
   lcd.print(moisture);
-  lcd.setCursor(0, 1);
-  lcd.print("ANG:");
-  lcd.print(angle);
+  */
+  /*
   lcd.print(" TMP: ");
   lcd.print(temperature);
+  */
 }

 int averageDataSamples(int dataSamples[], int numberOfSamples){


payload to struct, rename gps serial

payload to struct, rename gps serial

--- onboard_controller/onboard_controller.ino
+++ onboard_controller/onboard_controller.ino
@@ -15,10 +15,12 @@
 byte* buf_curr; //current position of buffer

 //fake data
-long latitude = 0;//42.4439;
-long longitude = 0;//-76.5018;
-int altitude = 0;//9999
-byte flags = 0xF;
+struct Payload {
+  long latitude; //42.4439;
+  long longitude;//-76.5018;
+  int altitude;//9999
+  byte flags;//0xF;
+} payload, *ptr_payload;

 enum States {
   STOPPED, PRE_LAUNCH, POST_LAUNCH, SEND_DATA, READ_DATA, READ_GPS, ERROR
@@ -30,8 +32,8 @@
 // XBee's DIN (RX) is connected to pin 9 (Arduino's Software TX)
 SoftwareSerial XBee(10,9); // RX, TX

-SoftwareSerial mySerial(8, 7);
-Adafruit_GPS GPS(&mySerial);
+SoftwareSerial gpsSerial(8, 7);
+Adafruit_GPS GPS(&gpsSerial);

 void setup()
 {
@@ -57,7 +59,7 @@
   delay(1000);

   // Ask for firmware version
-  mySerial.println(PMTK_Q_RELEASE);
+  gpsSerial.println(PMTK_Q_RELEASE);

 }

@@ -81,19 +83,19 @@
     timer = millis(); // reset the timer

     if (GPS.fix) {
-      latitude = convertDegMinToDecDeg(GPS.latitude)*10000;
-      longitude = convertDegMinToDecDeg(GPS.longitude)*10000;
-      altitude = GPS.altitude;
+      payload.latitude = convertDegMinToDecDeg(GPS.latitude)*10000;
+      payload.longitude = convertDegMinToDecDeg(GPS.longitude)*10000;
+      payload.altitude = GPS.altitude;

       //set every byte in array to 0
       memset( buf_start, 0, MAX_BUF );

       //buf_start is pointer to first allocated space
       //buf_curr is pointer to next free space
-      buf_curr = stream(MARKER_LAT, buf_start, (void*)&latitude, sizeof(latitude));
-      buf_curr = stream(MARKER_LON, buf_curr, (void*)&longitude, sizeof(longitude));
-      buf_curr = stream(MARKER_ALT, buf_curr, (void*)&altitude, sizeof(altitude));
-      buf_curr = stream(MARKER_FLAG, buf_curr, (void*)&flags, sizeof(flags));
+      buf_curr = stream(MARKER_LAT, buf_start, (void*)ptr_payload->latitude, sizeof(payload.latitude));
+      buf_curr = stream(MARKER_LON, buf_curr, (void*)ptr_payload->longitude, sizeof(payload.longitude));
+      buf_curr = stream(MARKER_ALT, buf_curr, (void*)ptr_payload->altitude, sizeof(payload.altitude));
+      buf_curr = stream(MARKER_FLAG, buf_curr, (void*)ptr_payload->flags, sizeof(payload.flags));

       //buffer size is the difference between the current and start pointers
       buf_size = buf_curr - buf_start;
@@ -152,9 +154,3 @@

   return decDeg;
 }
-
-
-
-
-
-


Modificación serial-server

Modificación serial-server

--- ClienteServidor/espinoClient/espinoClient.ino
+++ ClienteServidor/espinoClient/espinoClient.ino
@@ -85,8 +85,7 @@
   Serial.write(data, length);
 }

-//------------------------
-//------------------------
+
 // TCP callbacks
 void onConnectCb(ESP8266Client& client)
 {


Expect single letter representations of the current emotional state. See http://www.asciitable.com/ for more information

--- RoverMain/RoverMain.ino
+++ RoverMain/RoverMain.ino
@@ -108,25 +108,25 @@
 	//we should read in the serial from here
 	//and determine the contexts we have and want to get to
 	if (Serial.available() > 0) {
-		int incomingByte = Serial.read();
+		char incomingByte = Serial.read();

 		//now that we have the byte corresponding to the current ctx,
 		//determine which ctx we want to trigger

 		switch(incomingByte) {
-			case SAD:
+			case 's':
 				return (SAD << 4) | HAPPY;
-			case FEARFUL:
+			case 'f':
 				return (FEARFUL << 4) | CALM;
-			case DISTRACTED:
+			case 'd':
 				return (DISTRACTED << 4) | FOCUSED;
-			case MAD:
+			case 'a':
 				return (MAD << 4) | CALM;
-			case HAPPY:
+			case 'h':
 				return (HAPPY << 4) | HAPPY;
-			case FOCUSED:
+			case 'o':
 				return (FOCUSED << 4) | FOCUSED;
-			case CALM:
+			case 'c':
 				return (CALM << 4) | CALM;
 			default:
 				return (UNKNOWN << 4) | UNKNOWN;


Update _10_Second_Timer.ino

Update _10_Second_Timer.ino

--- Example/_10_Second_Timer/_10_Second_Timer.ino
+++ Example/_10_Second_Timer/_10_Second_Timer.ino
@@ -6,7 +6,7 @@
 {
   Serial.begin(115200);
   pinMode(2, INPUT_PULLUP);
-  T.SetTimer(0,1,0);
+  T.SetTimer(0,0,0,10);
   T.StartTimer();
 }


Put a bunch of pin defs in, and max/min values. Used to map claw and swivel servos.

--- Project/map_angular_data/map_angular_data.ino
+++ Project/map_angular_data/map_angular_data.ino
@@ -6,7 +6,7 @@
  * @author:    Tyler Lucas
  * Student ID: 3305203
  * Date:       October 9, 2017
- * Version     1.0
+ * Version     1.1
  *
  * References: N/A
  *
@@ -15,19 +15,28 @@

 #include <Servo.h>  // servo library

-#define servo0PWMPin 11
-#define servo0sensorPin A0
+#define boomArmPin 11   // max 110, min ?
+#define mainArmPin 10   // max ?, min ?
+#define clawPin 9       // max 140, min 69
+#define swivelPin 6     // max 180, min 10

-#define angleMax 110
-#define angleMin 30
+#define boomArmSensorPin A0
+#define mainArmSensorPin A1
+#define clawSensorPin A2
+#define swivelSensorPin A3
+
+#define angleMin 69
+#define angleMax 140
+#define angleInitial 90
+#define angleAdjustmentMagnitude 1

 Servo servo;
 int angle = angleMin;
-int angleAdjustment = 1;
+int angleAdjustment = angleAdjustmentMagnitude;

 void setup()
 {
-  servo.attach( servo0PWMPin );
+  servo.attach( clawPin );

   Serial.begin(9600);

@@ -46,7 +55,7 @@
     {
       Serial.print( angle );
       Serial.write(',');
-      Serial.println( analogRead(servo0sensorPin) );
+      Serial.println( analogRead( clawSensorPin ) );
     }

     angle += angleAdjustment;
@@ -54,12 +63,3 @@

   angleAdjustment *= -1;    // reverse direction
 }
-
-double analogReadAverage(int pin, unsigned int points)
-{
-  double sum = 0;
-  for (unsigned int i=0; i<points; i++)
-    sum += analogRead(pin);
-  return sum / points;
-}
-


edit serial dummy generator

edit serial dummy generator

--- server/serial/serial_test/serial_test.ino
+++ server/serial/serial_test/serial_test.ino
@@ -189,7 +189,7 @@
   Serial.write(time[1]);
   Serial.write(time[2]);
   Serial.write(time[3]);
-  Serial.write(x&0xFF00);
+  Serial.write(x&0xFF00 >> 8);
   Serial.write(x&0xFF);
   Serial.write(2);
   Serial.write(2);


Add ability to adjust measuring period of devices.

--- JnGeneral/JnGeneral.ino
+++ JnGeneral/JnGeneral.ino
@@ -282,6 +282,45 @@
             }
             break;

+        case 'r': // Set measurement period
+            if (parseInt(&values[0]) && parseInt(&values[1])) {
+                // Check and convert period
+                byte exp = 0, mant;
+                if(values[1] > 30000 || values[1] < 0) {
+                    myputs("Periods must be 0<=X<=30000\n");
+                    break;
+                }
+                while(values[1] && (values[1] % 10) == 0) {
+                    exp++;
+                    values[1] /= 10;
+                }
+                if(values[1] > 15 || values[1] < 0) {
+                    myputs("Periods must be A*10^B, 0<=A<=15, 0<=B<=7\n");
+                    break;
+                }
+                mant = values[1];
+                if(mant == 0)
+                    exp = 0;
+
+                // Check device number
+                byte device = values[0];
+                if(device < 0 || device >= numPlugs) {
+                    myputs("Device number out of range\n");
+                    break;
+                }
+
+                plugs[device].period = SCALE(mant, exp);
+                saveConfig();
+
+                // Start/stop timer as appropriate
+                if(mant && scheduler.idle(TASK_MEASURE0+device))
+                    scheduler.timer(TASK_MEASURE0+device, 10); // Start in 1 second
+                if(!mant && !scheduler.idle(TASK_MEASURE0+device))
+                    scheduler.cancel(TASK_MEASURE0+device);
+                scheduler.timer(TASK_ANNOUNCE, 0);
+            }
+            break;
+
         default:
             myputs("Unknown command.\n");
             break;
@@ -325,6 +364,7 @@
                  "  a <port> <device>   Add device to port\r\n"
                  "  d <port> <device>   Remove device from port\r\n"
                  "  c <port>            Clear all devices from port\r\n"
+                 "  r <device> <delay>  Set measurement period for device (in 0.1s)\r\n"
                  "  l                   List defined devices\r\n"
                  "  p                   Print current configuration\r\n"
                  "  m                   Do test measurements\r\n"
@@ -356,13 +396,14 @@
 {
     myputs("Current configuration:\n");
     for(byte i=0; i<numPlugs; i++) {
-        myprintf("  port %d ", plugs[i].port);
+        myprintf("  dev %d: port %d ", i, plugs[i].port);
         Device *dev = getDevice(plugs[i].device_id);
         if(!dev) {
             myputs("(Unknown)\n");
             continue;
         }
-        myprintf("%s measuring: ", dev->name);
+        int period = scale_as_int(plugs[i].period);
+        myprintf("%s measuring (every %d.%ds): ", dev->name, period/10, period%10);
         for(byte j=0; j<dev->num_measurements; j++) {
             Unit *unit = getUnit(dev->measurements[j].unit);
             if(!unit)
@@ -675,7 +716,9 @@
         // Take the measurement for the given plug and then schedule a report
         Plug &plug = plugs[event-TASK_MEASURE0];

-        scheduler.timer(event, scale_as_int(plug.period));
+        int period = scale_as_int(plug.period);
+        if(period)
+            scheduler.timer(event, period);

         measurePlug(plug, 1);
         if(scheduler.idle(TASK_REPORT))


Deskheight: error LED and http authentication

--- personal/deskheight/main/main.ino
+++ personal/deskheight/main/main.ino
@@ -30,11 +30,15 @@
 // HTTP
 String      HTTP_HOST              = SECRET_HTTP_HOST;
 const int   HTTP_PORT              = SECRET_HTTP_PORT;
-String      HTTP_URI               = "stats/deskheight";
+const char* HTTP_USER              = SECRET_HTTP_USER;
+const char* HTTP_PASSWORD          = SECRET_HTTP_PASSWORD;
+String      HTTP_URI               = "/sensors/deskheight"; // leading slash is required

 // MISC
 const int   LOOP_INTERVAL_MSEC     = 5000; // How often do we measure desk height
-const int   LED_STATUS_PIN         = D7;  // LED pin that is used to blink on success
+const int   HTTP_LED_SUCCESS_PIN   = D7;   // LED pin that is used to blink on http success
+const int   HTTP_LED_ERROR_PIN     = D10;  // LED pin that is used to blink on http success
+
 // --------------------------------------------------------------

 // With Wemos D1, use the provided constants, like D3 (and not 3) because the actual numbers are different
@@ -107,7 +111,8 @@
   Serial.begin(115200);
   Serial.println("Starting...");
   pinMode(WIFI_STATUS_LED_PIN, OUTPUT);
-  pinMode(LED_STATUS_PIN, OUTPUT);
+  pinMode(HTTP_LED_SUCCESS_PIN, OUTPUT);
+  pinMode(HTTP_LED_ERROR_PIN, OUTPUT);
   connectToWifi();
 }

@@ -118,14 +123,22 @@
     const int deskheight = ultrasonic.distanceRead();
     Serial.printf("Desk height: %d CM\n", deskheight);

-    Serial.printf("Sending desk height of '%d' to %s:%i/%s\n", deskheight, HTTP_HOST.c_str(), HTTP_PORT, HTTP_URI.c_str());
+    Serial.printf("Sending desk height of '%d' to %s:%i%s\n", deskheight, HTTP_HOST.c_str(), HTTP_PORT, HTTP_URI.c_str());

     // Create http client
+    // https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266HTTPClient/
     HTTPClient http;
     http.begin(HTTP_HOST, HTTP_PORT, HTTP_URI);
-    http.addHeader("User-Agent", "Desk height sensor - Wemos D1");
+    http.setAuthorization(HTTP_USER, HTTP_PASSWORD);
+
+    http.setUserAgent("Deskheight sensor - Wemos D1");
+    http.addHeader("content-type", "application/json");

-    int httpCode = http.POST(String(deskheight));
+    // '{"value": "<deskheight>", "homeassistant_sensor": { "name": "deskheight", "state": "<deskheight>", "attributes": { "friendly_name": "Desk Height", "unit_of_measurement": "cm" }}}'
+    String payload = String("{ \"value\": \"") + deskheight + String("\", \"homeassistant_sensor\": { \"name\": \"deskheight\",\"state\": \"") + deskheight + String("\", \"attributes\": { \"friendly_name\": \"Desk Height\", \"unit_of_measurement\": \"cm\" }}}");
+
+    int httpCode = http.POST(payload);
+    int statusLed = HTTP_LED_ERROR_PIN;

     // httpCode will be negative on error
     if(httpCode > 0) {
@@ -136,6 +149,7 @@
         if(httpCode == HTTP_CODE_OK) {
             String payload = http.getString();
             Serial.println(payload);
+            statusLed = HTTP_LED_SUCCESS_PIN;
         }
     } else {
         Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
@@ -145,10 +159,10 @@

     Serial.printf("Next loop in %d msec", LOOP_INTERVAL_MSEC);

-    // Blink success led
-    digitalWrite(LED_STATUS_PIN, HIGH);
+    // Blink led
+    digitalWrite(statusLed, HIGH);
     delay(500);
-    digitalWrite(LED_STATUS_PIN, LOW);
+    digitalWrite(statusLed, LOW);

     delay(LOOP_INTERVAL_MSEC);


Changed to c delay statement

Changed to c delay statement

--- arduino/morse/morse.ino
+++ arduino/morse/morse.ino
@@ -1,6 +1,6 @@
-#define DELAY_MS 100
+#define DELAY_MS 80

-int led = 0; //attiny84 pin 13
+int led = 10; //attiny84 pin 2
 //int led = 4; //attiny85 pin 3

 // the setup routine runs once when you press reset:
@@ -19,13 +19,13 @@
     for ( j=0; j<=15; j++ ) {
       if ( (morseWord[i] & (1<<(15-j))) > 0 ) {
         digitalWrite(led, HIGH);
-        delay(DELAY_MS);
+        _delay_ms(DELAY_MS);
       } else {
         digitalWrite(led, LOW);
-        delay(DELAY_MS);
+        _delay_ms(DELAY_MS);
       }
     }
     digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
-    delay(DELAY_MS*14);               // wait for a while
+    _delay_ms(DELAY_MS*14);               // wait for a while
   }
 }


more cleanup

more cleanup

--- yun-control-light-all-strips-together.ino
+++ yun-control-light-all-strips-together.ino
@@ -14,13 +14,17 @@
 // example for more information on possible values.
 Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIXELS_PIN, NEO_GRB + NEO_KHZ800);

-int delayval = 50; // delay for half a second
-int ledState = LOW; // the current state of the output pin
-long previousMillis = 0; // will store last time LED was updated
-int neoPixelToChange = 0; //track which neoPixel to change
-int neoPixel_j = 0; //stores values for program cycles
-int defaultBrightness = 255;
-long delayMillis = 0; // will store the last time the
+//int delayval = 50; // delay for half a second
+//int ledState = LOW; // the current state of the output pin
+//int neoPixelToChange = 0; //track which neoPixel to change
+//int neoPixel_j = 0; //stores values for program cycles
+//int defaultBrightness = 255;
+//long delayMillis = 0; // will store the last time the
+
+
+
+long previousMillis = 0; // for wait times
+

 int currentLightScheme = 0;

@@ -126,9 +130,9 @@

           waitTime = client.parseInt();

-              client.stop();
-
-
+          client.stop();
+
+
           uint32_t c;
           uint32_t wait;

@@ -138,13 +142,13 @@
             wait = 50;
           }

-//          client.print("waitTime: " );
-//          client.println(wait);
+          //          client.print("waitTime: " );
+          //          client.println(wait);

           c = strip.Color(redVal, greenVal, blueVal);
           neoPixelToChange = 0;
           while (neoPixelToChange <= NUMPIXELS) {
-           YunClient client = server.accept();
+            YunClient client = server.accept();
             if (client) {
               break;
               client.stop();
@@ -198,7 +202,7 @@
           }
           break;
         case 5:
-          rainbowCycle(10);
+         // rainbowCycle(10);
           break;
         case 6:
           redRaw = client.parseInt();
@@ -211,25 +215,6 @@
           break;
         case 7:

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-          //
-          //      int R = 0;
-          //      int G = 0;
-          //      int B = 0;
           //Fade in
           while (1) { //using an inf loop to be more custom.
             //Protect the strand from higher then 255 values
@@ -283,24 +268,6 @@
             delay(waitT);
           }

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
           break;
         case 8:
           allColor(strip.Color(redVal, greenVal, blueVal)); //off
@@ -330,7 +297,6 @@
           allColor(strip.Color(redStartVal, greenStartVal, blueStartVal));
           strip.show();

-
           client.println("before while loop");

           while ( totalCycles > currentCycles ) {
@@ -342,8 +308,6 @@
             }

             currentMillis = millis();
-            //          client.println(previousMillis);
-            //          client.println(currentMillis);

             if (currentMillis - previousMillis > wait) {
               previousMillis = currentMillis;
@@ -355,17 +319,7 @@
               int redNow = 0;
               int greenNow = 0;
               int blueNow = 0;
-              //
-              //              client.println(redDif);
-              //              client.println(greenDif);
-              //              client.println(blueDif);
-
-              //              for (g = 0; g < greenDif; g++) {
-              //                greenNow = greenStartVal + g;
-              //              }
-              //              for (b = 0; b < blueDif; b++) {
-              //                blueNow = blueStartVal + b;
-              //              }
+
               for (r = 0; r < redDif; r++) {
                 redNow = redStartVal + r;
                 allColor(strip.Color(constrain(redNow, 0, 255), constrain(greenNow, 0, 255), constrain(blueNow, 0, 255)));
@@ -376,14 +330,6 @@

               client.println(redNow);

-
-
-              //
-              //                    client.print("red: " );
-              //                    client.println(redStartVal + r);
-
-
-              //strip.show();
               currentCycles++;
             }

@@ -403,237 +349,6 @@
   client.stop();
   delay(50);

-}
-//
-//void process(YunClient client) {
-//  // read the command
-//  String command = client.readStringUntil('/');
-//
-//  // is "message" command?
-//  if (command == "light") {
-//    lightCommand(client);
-//  }
-//}
-//
-//void lightCommand(YunClient client) {
-//
-//
-//  int programMode = client.parseInt();
-//  int redRaw = client.parseInt();
-//  int redVal = constrain(redRaw, 0, 255);
-//  client.print("redval: " );
-//  client.println(redVal);
-//
-//  int greenRaw = client.parseInt();
-//  int greenVal = constrain(greenRaw, 0, 255);
-//  client.print("greenval: " );
-//  client.println(greenVal);
-//
-//  int blueRaw = client.parseInt();
-//  int blueVal = constrain(blueRaw, 0, 255);
-//  client.print("blueval: " );
-//  client.println(blueVal);
-//
-//  // Send feedback to client
-//  client.print("Command found is ");
-//  client.println(programMode);
-//
-//      switch (programMode) {
-//        case 0:
-//          allColor(strip.Color(0, 0, 0)); //off
-//          break;
-//        case 1:
-//          softBlink(strip.Color(redVal, greenVal, blueVal), 255, 50); // blue
-//          break;
-//        case 2:
-//          colorWipeCycle(strip.Color(0, defaultBrightness, 0), 500); // green
-//          break;
-//        case 3:
-//          softBlink(strip.Color(0, 0, 255), defaultBrightness, 50); // blue
-//          break;
-//        case 4:
-//        // rainbow
-//        currentCycles = wait;
-//  while ( wait > currentCycles ) {
-//
-//  unsigned long currentMillis = millis();
-//  if (currentMillis - previousMillis > wait) {
-//    // save the last time you changed a NeoPixel
-//    previousMillis = currentMillis;
-//
-//    //change the colors of the pixels
-//    uint16_t i;
-//    for (i = 0; i < strip.numPixels(); i++) {
-//      strip.setPixelColor(i, Wheel((i + neoPixel_j) & 255));
-//    }
-//    strip.show();
-//    neoPixel_j = (neoPixel_j + 1) % 255; //increment j until all colors are used, then start over
-//  }
-//  currentCycles++;
-//
-//  }
-//
-//
-//
-//
-//
-//          break;
-//        case 5:
-//          rainbowCycle(10);
-//          break;
-//        case 6:
-//          client.println("in program 6");
-//          client.println();
-//          client.println(redVal);
-//          client.println(greenVal);
-//          client.println(blueVal);
-//          client.println();
-//          allColor(strip.Color(redVal, greenVal, blueVal)); //off
-//          client.println("end program 6");
-//          break;
-//        case 7:
-//          break;
-//        case 8:
-//          allColor(strip.Color(redVal, greenVal, blueVal)); //off
-//          break;
-//        default:
-//          // if nothing else matches, do the default
-//          allColor(strip.Color(0, 0, 0)); //off
-//      }
-//
-//}
-
-// Fill all the dots with one color
-void allColor(uint32_t c) {
-  for (uint16_t i = 0; i < strip.numPixels(); i++) {
-    strip.setPixelColor(i, c);
-    strip.show();
-  }
-} // note for a random color, use:
-// allColor((unsigned long)random(0x01000000));
-
-
-
-void blinkColor(uint32_t c, uint8_t wait) {
-  unsigned long currentMillis = millis();
-
-
-  if (currentMillis - previousMillis > wait) {
-    // save the last time you blinked the LED
-    previousMillis = currentMillis;
-    // if the LED is off turn it on and vice-versa:
-    if (ledState == LOW) {
-      ledState = HIGH;
-      allColor(c);
-    } else {
-      ledState = LOW;
-      allColor(strip.Color(0, 0, 0)); // off
-    }
-  }
-}
-
-
-
-// Fill the dots one after the other with a color
-void colorWipe(uint32_t c, uint8_t wait) {
-  unsigned long currentMillis = millis();
-  //only do this if some of the pixels still need to be lit
-  if (neoPixelToChange <= NUMPIXELS) {
-    if (currentMillis - previousMillis > wait) {
-      // save the last time you changed a NeoPixel
-      previousMillis = currentMillis;
-      //change a pixel
-      strip.setPixelColor(neoPixelToChange, c);
-      strip.show();
-      neoPixelToChange++;
-    }
-  }
-}
-
-
-
-// Fill the dots one after the other with a color
-void colorWipeCycle(uint32_t c, uint8_t wait) {
-  unsigned long currentMillis = millis();
-  //only do this if some of the pixels still need to be lit
-  if (neoPixelToChange <= NUMPIXELS) {
-    if (currentMillis - previousMillis > wait) {
-      // save the last time you changed a NeoPixel
-      previousMillis = currentMillis;
-      //change a pixel
-      strip.setPixelColor(neoPixelToChange, c);
-      strip.show();
-      neoPixelToChange++;
-    }
-  } else {
-    // reset the cycle
-    previousMillis = 0;
-    neoPixelToChange = 0;
-    allColor(strip.Color(0, 0, 0));
-  }
-}
-
-
-
-void rainbow(uint8_t wait) {
-  currentCycles = wait;
-  while ( wait > currentCycles ) {
-
-    unsigned long currentMillis = millis();
-    if (currentMillis - previousMillis > wait) {
-      // save the last time you changed a NeoPixel
-      previousMillis = currentMillis;
-
-      //change the colors of the pixels
-      uint16_t i;
-      for (i = 0; i < strip.numPixels(); i++) {
-        strip.setPixelColor(i, Wheel((i + neoPixel_j) & 255));
-      }
-      strip.show();
-      neoPixel_j = (neoPixel_j + 1) % 255; //increment j until all colors are used, then start over
-    }
-    currentCycles++;
-
-  }
-
-
-}
-
-
-
-
-
-// Slightly different, this makes the rainbow equally distributed throughout
-void rainbowCycle(uint8_t wait) {
-  unsigned long currentMillis = millis();
-  if (currentMillis - previousMillis > wait) {
-    // save the last time you changed a NeoPixel
-    previousMillis = currentMillis;
-    //change the colors of the pixels
-    uint16_t i;
-    for (i = 0; i < strip.numPixels(); i++) {
-      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + neoPixel_j) & 255));
-    }
-    strip.show();
-    neoPixel_j = (neoPixel_j + 1) % 1279; // 5 cycles of all colors on wheel, then start over
-  }
-}
-
-
-void softBlink(uint32_t c, uint8_t brightness, uint8_t wait) {
-  unsigned long currentMillis = millis();
-  if (currentMillis - previousMillis > wait) {
-    //set the color of all pixels
-    allColor(c); // is there a way to set this only once per program ????????????????????
-    // save the last time you changed a NeoPixel
-    previousMillis = currentMillis;
-    uint16_t i;
-    int b = (neoPixel_j * brightness) / brightness;
-    strip.setBrightness(b);
-    strip.show();
-    // sometime figure out how to get this to fade down too instead of just restarting //////////////////////
-    neoPixel_j = (neoPixel_j + 1) % brightness;
-  }
 }

 // Input a value 0 to 255 to get a color value.


Stop at zero speed when changing direction rather than starting up again

--- code/MotorController/MotorController.ino
+++ code/MotorController/MotorController.ino
@@ -153,10 +153,13 @@
   if (currentSpeed == 0 && currentDirection != targetDirection)
   {
     // We're at zero speed and want to switch directions.
-    delay(0);
     digitalWrite(directionOutPin, targetDirection);
     currentDirection = targetDirection;
     UpdateDirectionDisplay();
+
+    // We don't want to actually start moving the other direction,
+    // wait for the user to hit the power button again
+    powerEnabled = false;
   }

   currentSpeed += SlewToward(currentSpeed, targetSpeed);


Update BasicShutters.ino

Update BasicShutters.ino

--- examples/BasicShutters/BasicShutters.ino
+++ examples/BasicShutters/BasicShutters.ino
@@ -24,6 +24,9 @@
 void setup(void)
 {
   Serial.begin(9600);
+  #ifdef ESP8266
+  EEPROM.begin(4); // Only one byte will be used, but 4 is the minimum for ESP8266 begin()
+  #endif
   shutters.begin(); // Might take some time first time, as it will open the shutters
   shutters.requestLevel(50); // Go to 50%
 }


Added more instructions to microstepping example.

--- examples/MicroStepping/MicroStepping.ino
+++ examples/MicroStepping/MicroStepping.ino
@@ -11,7 +11,18 @@
 #include <Arduino.h>
 #include "DRV8834.h"

-static DRV8834 drv8834;
+// All the wires needed for full functionality
+#define DIR 8
+#define STEP 9
+#define M0 10
+#define M1 11
+#define ENBL 12
+
+// 3-wire basic config, microstepping is hardwired on the driver
+// stepper stepper(DIR, STEP, ENBL);
+
+// complete wiring
+DRV8834 stepper(DIR, STEP, ENBL, M0, M1);

 void setup() {
     /*
@@ -19,30 +30,38 @@
      * These motors can do up to about 200rpm.
      * Too high will result in a high pitched whine and the motor does not move.
      */
-    drv8834.setRPM(120);
+    stepper.setRPM(120);
 }

 void loop() {
-    drv8834.enable();
+    // energize coils - the motor will hold position
+    stepper.enable();

-    int mode = 1;
-    while (mode <= 32){
-        /*
-         * Set microstepping mode: 1,2,4,8,16 or 32
-         * Mode 1 is full speed.
-         * Mode 32 is 32 microsteps per step.
-         * The motor should rotate just as fast, but movement precision is
-         * increased.
-         */
-        drv8834.stepMode(mode);
-
-        // 200*microsteps covers one full rotation for a 200-step motor
-        drv8834.move(200*mode);
+    /*
+     * Moving motor at full speed is simple:
+     */
+    stepper.stepMode(1); // make sure we are in full speed mode
+
+    // one full rotation for a 200-step motor
+    stepper.move(200);

-        mode *= 2;
-    }
-    // allow the motor to be moved by hand
-    drv8834.disable();
+    // one full reverse rotation
+    stepper.move(-200);
+
+    /*
+     * Microstepping mode: 1,2,4,8,16 or 32
+     * Mode 1 is full speed.
+     * Mode 32 is 32 microsteps per step.
+     * The motor should rotate just as fast (set RPM),
+     * but movement precision is increased.
+     */
+    stepper.stepMode(32);
+
+    // one full rotation now takes 200 * 32 microsteps
+    stepper.move(200*32);
+
+    // pause and allow the motor to be moved by hand
+    stepper.disable();

     delay(5000);
 }


Improving Shell example sketch.

Improving Shell example sketch.

1. Fixed idle time calculation.
2. Correct idle time capture on "repeat" and "delay" commands.
3. Redefine iowait() as the yield() implementation.

--- examples/Sandbox/CosaShell/CosaShell.ino
+++ examples/Sandbox/CosaShell/CosaShell.ino
@@ -25,6 +25,7 @@
 #include "Commands.h"
 #include "Cosa/RTC.hh"
 #include "Cosa/Tone.hh"
+#include "Cosa/Power.hh"
 #include "Cosa/Watchdog.hh"
 #include "Cosa/IOStream/Driver/UART.hh"

@@ -34,8 +35,9 @@
 void iowait()
 {
   uint32_t start = RTC::micros();
-  yield();
-  idle += (RTC::micros() - start);
+  Power::sleep();
+  uint32_t stop = RTC::micros();
+  idle = idle + (stop - start);
 }

 void setup()
@@ -44,11 +46,12 @@
   Tone::begin();
   RTC::begin();
   uart.begin(9600);
+  yield = iowait;
 }

 void loop()
 {
   shell.run(ios);
-  iowait();
+  yield();
 }


fixed up and functional

fixed up and functional

removed unnecessary "}", and removed getFreeRam() which was dependent on "utility/debug.h"

--- examples/mqtt_ethernet/mqtt_ethernet.ino
+++ examples/mqtt_ethernet/mqtt_ethernet.ino
@@ -74,8 +74,6 @@

   Serial.println(F("Adafruit MQTT demo"));

-  Serial.print(F("Free RAM: ")); Serial.println(getFreeRam(), DEC);
-
   // Initialise the Client
   Serial.print(F("\nInit the Client..."));
   Ethernet.begin(mac);
@@ -83,8 +81,6 @@

   mqtt.subscribe(&onoffbutton);
-
-  }
 }

 uint32_t x=0;


Final commit of the day

Final commit of the day

--- HIH6130_Nimbits.ino
+++ HIH6130_Nimbits.ino
@@ -84,7 +84,7 @@
    Serial.println("HIH6130 Nimbits 2013 Aug 31");
    delay(3000);  // wait for all devices to stabilize and complete any internal startup
    Serial.print("Sample interval ");  // just to be sure things are working
-   dtime = MIN_1;  //delay between readings
+   dtime = MIN_15;  //delay between readings
    Serial.print(dtime/1000);
    Serial.println(" sec");


Minor tweaks to descriptions

Minor tweaks to descriptions

--- ROVMain/ROVMain.ino
+++ ROVMain/ROVMain.ino
@@ -15,10 +15,6 @@

 //#define DEBUG_PRINTOUT // this will cause issues with arming modules as the GUI expects a delay in ms to be returned upon sending "armModules,1"; either fix or don't use the GUI in conjuction with this flag

-/* TODO TODO TODO
-- figure out which ESC sends alarm at arming (throttle not zero?) (port hor?)
-*/
-
 // Custom includes.
 #include "Module.h"
 #include "BrushlessDCMotor.h"
@@ -30,8 +26,8 @@
 #include <stdio.h>

 // ROV identifiers.
-const String ROV_MODEL = "zy3b";
-const String ROV_SW_VERSION = "2.1.2";
+const String ROV_MODEL = "ROVing Drone";
+const String ROV_SW_VERSION = "2.2.0r";

 /* =============================================================================
  * FUNCTION DECLARATIONS.


Speed up html request

Speed up html request

Re-defined  HTTP_MAX_CLOSE_WAIT to 0 to speed up multiple http request.

--- esp32LightServerRGB.ino
+++ esp32LightServerRGB.ino
@@ -9,7 +9,7 @@
 #include <Preferences.h>
 #include <ArduinoOTA.h>
 #include "BluetoothSerial.h"
-
+#define HTTP_MAX_CLOSE_WAIT 0
 Preferences preferences;

 BluetoothSerial SerialBT;
@@ -1290,15 +1290,17 @@
   thingchanel = preferences.getString("thingchanel", "none");
   xTaskCreatePinnedToCore(loop1, "loop1", 2048, NULL, 0, NULL, 0);
   lesliens();
+  delay(5000);
   WiFiManager wifiManager;
   wifiManager.setTimeout(240);
-  WiFi.disconnect(); // pour prevenir de bugs de power et autres
+  //WiFi.disconnect(); // pour prevenir de bugs de power et autres
   delay(1000);
   if (!wifiManager.autoConnect()) {
     delay(3000);
     ESP.restart();
     delay(5000);
   }
+  delay(5000);
   if (!sensors.getAddress(insideThermometer, 0)) {
     int ereur = 0;
     int marchetu = 1;
@@ -1319,7 +1321,7 @@
   sensors.setResolution(insideThermometer, 12);// 9 ou 12 9 plus rapide mais moin prÃ©Ã§is
   MDNS.begin("lumiere");
   ArduinoOTA.setHostname("lumiere");
-  ArduinoOTA.setPasswordHash("password");
+  ArduinoOTA.setPasswordHash("otapassword");
   ArduinoOTA
   .onStart([]() {
     String type;


Reimplementing network communication [WiFi shied somehow doesn't flush buffer when not using print], optimizing connection handling, dumping web client response to serial bus

--- arduino/arduino.ino
+++ arduino/arduino.ino
@@ -33,7 +33,7 @@
 #define TRIGGER_PIN 8

 // TIMEFRAME defines the datastorages time segmenting (256 hits in that time frame max)
-#define TIMEFRAME 15
+#define TIMEFRAME 30

 // STORAGE_HOURS defines how many hours of detailed information are stored in RAM
 #define STORAGE_HOURS 1
@@ -55,7 +55,10 @@
 void networkConnect();
 void wifiConnect();
 void ethernetConnect();
+
 void serverCheck();
+void networkCheck();
+
 String serverHeader(String);
 bool networkRequestIP(IPAddress, String);

@@ -77,6 +80,7 @@
 #ifdef USE_ETHERNET_SHIELD
   #define USE_NETWORK
   EthernetClient client;
+  EthernetClient connection;
   EthernetServer server = EthernetServer(SERVER_PORT);
   EthernetUDP udp;
   byte ethernetMac[] = ETHERNET_MAC;
@@ -85,13 +89,15 @@
 #ifdef USE_WIFI_SHIELD
   #define USE_NETWORK
   WiFiClient client;
+  WiFiClient connection;
   WiFiServer server = WiFiServer(SERVER_PORT);
   WiFiUDP udp;
   int connectionStatus = WL_IDLE_STATUS;
 #endif

 #ifdef USE_NETWORK
-  char requestBuffer[96];
+  char requestBuffer[128];
+  boolean lastConnected = false;
 #endif

 #ifdef USE_STROMBEWUSST_SERVER
@@ -147,53 +153,66 @@
   #ifdef USE_NETWORK
     // Check if we got an incoming connection to our server
     serverCheck();
-  #endif
-}
-
+    networkCheck();
+  #endif
+}
+
+void networkCheck()
+{
+  // dump all pending data from network connections to the serial interface
+  while (client.available())
+  {
+    char c = client.read();
+    Serial.print(c);
+  }
+
+  // stop the client if we lost the connection since the last loop
+  if (!client.connected() && lastConnected) {
+    Serial.println("[network] closing connection");
+    client.stop();
+  }
+  lastConnected = client.connected();
+}
+
+#ifdef USE_NETWORK
 void serverCheck()
 {
-  #ifdef USE_ETHERNET_SHIELD
-    EthernetClient client = server.available();
-  #endif
-  #ifdef USE_WIFI_SHIELD
-    WiFiClient client = server.available();
-  #endif
-  #ifdef USE_NETWORK
-    // Check for a new connection
-    char headerBuffer[10];
-    if (client)
-    {
-      Serial.println("new client");
-      while (client.connected()) {
-        if (client.available()) {
-          // Get the first couple of bytes
-          for (int i=0; i<10; i++)
-          {
-            headerBuffer[i] = client.read();
-          }
-          client.flush();
-
-          String header = headerBuffer;
-          if (header.startsWith("GET / "))
-          {
-            client.print(serverHeader("text/html"));
-            client.println("Hello from StromBewusst!");
-          }
-
-          if(header.startsWith("GET /json "))
-          {
-            client.print(serverHeader("text/json"));
-            client.print(generateJSON());
-          }
-
-          delay(1);
-          client.stop();
+  connection = server.available();
+  // Check for a new connection
+  char headerBuffer[10];
+  if (connection)
+  {
+    Serial.println("new client");
+    while (connection.connected()) {
+      if (connection.available()) {
+        // Get the first couple of bytes
+        for (int i=0; i<10; i++)
+        {
+          headerBuffer[i] = connection.read();
         }
+        connection.flush();
+        Serial.println(headerBuffer);
+        String header = headerBuffer;
+        if (header.startsWith("GET / "))
+        {
+          connection.print(serverHeader("text/html"));
+          connection.println("Hello from StromBewusst!");
+        }
+
+        if(header.startsWith("GET /json "))
+        {
+          connection.print(serverHeader("text/json"));
+          connection.print(generateJSON());
+        }
+
+        delay(1);
+        connection.stop();
       }
-      Serial.println("client disconnected");
-    }
-  #endif
-}
+    }
+    Serial.println("client disconnected");
+  }
+}
+#endif

 #ifdef USE_NETWORK
 String serverHeader(String contentType)
@@ -323,15 +342,21 @@
 #ifdef USE_NETWORK
 bool networkRequestIP(IPAddress ip, String url)
 {
+  if (client.connected())
+  {
+    client.stop();
+  }
+
   if (client.connect(ip, 80))
   {
-    String request = "GET "+url;
-    request += " HTTP/1.1\r\nConnection: close\r\n\r\n";
-    request.toCharArray(requestBuffer, 96);
+    Serial.println("[network] sending request");
+
+    client.print("GET ");
+    client.print(url);
+    client.println(" HTTP/1.0");
+    client.println("Connection: close");
+    client.println();

-    Serial.println("[network] sending request:");
-    client.write(requestBuffer);
-    client.stop();
     return true;
   } else
   {


Inserted code from Boschs bno055_support.c. Compiles okay.

--- test/Arduino/Bosch_BNO055/Bosch_BNO055.ino
+++ test/Arduino/Bosch_BNO055/Bosch_BNO055.ino
@@ -21,6 +21,540 @@
 #include <MicroView.h>

 const int fontHeight = 10;
+
+
+//
+// start code from Boschs bno055_support.c
+// - - - -
+/*----------------------------------------------------------------------------*
+ *  The following APIs are used for reading and writing of
+ *  sensor data using I2C communication
+*----------------------------------------------------------------------------*/
+#ifdef  BNO055_API
+#define BNO055_I2C_BUS_WRITE_ARRAY_INDEX  ((u8)1)
+/*  \Brief: The API is used as I2C bus read
+ *  \Return : Status of the I2C read
+ *  \param dev_addr : The device address of the sensor
+ *  \param reg_addr : Address of the first register,
+ *   will data is going to be read
+ *  \param reg_data : This data read from the sensor,
+ *   which is hold in an array
+ *  \param cnt : The no of byte of data to be read
+ */
+s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
+/*  \Brief: The API is used as SPI bus write
+ *  \Return : Status of the SPI write
+ *  \param dev_addr : The device address of the sensor
+ *  \param reg_addr : Address of the first register,
+ *   will data is going to be written
+ *  \param reg_data : It is a value hold in the array,
+ *  will be used for write the value into the register
+ *  \param cnt : The no of byte of data to be write
+ */
+s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt);
+/*
+ * \Brief: I2C init routine
+*/
+s8 I2C_routine(void);
+#endif
+/********************End of I2C APIs declarations***********************/
+/*  Brief : The delay routine
+ *  \param : delay in ms
+*/
+void BNO055_delay_msek(u32 msek);
+/* This API is an example for reading sensor data
+ *  \param: None
+ *  \return: communication result
+ */
+s32 bno055_data_readout_template(void);
+/*----------------------------------------------------------------------------*
+ *  struct bno055_t parameters can be accessed by using BNO055
+ *  BNO055_t having the following parameters
+ *  Bus write function pointer: BNO055_WR_FUNC_PTR
+ *  Bus read function pointer: BNO055_RD_FUNC_PTR
+ *  Burst read function pointer: BNO055_BRD_FUNC_PTR
+ *  Delay function pointer: delay_msec
+ *  I2C address: dev_addr
+ *  Chip id of the sensor: chip_id
+*---------------------------------------------------------------------------*/
+struct bno055_t bno055;
+/* This API is an example for reading sensor data
+ *  \param: None
+ *  \return: communication result
+ */
+s32 bno055_data_readout_template(void)
+{
+  /* Variable used to return value of
+  communication routine*/
+  s32 comres = BNO055_ERROR;
+  /* variable used to set the power mode of the sensor*/
+  u8 power_mode = BNO055_INIT_VALUE;
+  /*********read raw accel data***********/
+  /* variable used to read the accel x data */
+  s16 accel_datax = BNO055_INIT_VALUE;
+   /* variable used to read the accel y data */
+  s16 accel_datay = BNO055_INIT_VALUE;
+  /* variable used to read the accel z data */
+  s16 accel_dataz = BNO055_INIT_VALUE;
+  /* variable used to read the accel xyz data */
+  struct bno055_accel_t accel_xyz;
+
+  /*********read raw mag data***********/
+  /* variable used to read the mag x data */
+  s16 mag_datax  = BNO055_INIT_VALUE;
+  /* variable used to read the mag y data */
+  s16 mag_datay  = BNO055_INIT_VALUE;
+  /* variable used to read the mag z data */
+  s16 mag_dataz  = BNO055_INIT_VALUE;
+  /* structure used to read the mag xyz data */
+  struct bno055_mag_t mag_xyz;
+
+  /***********read raw gyro data***********/
+  /* variable used to read the gyro x data */
+  s16 gyro_datax = BNO055_INIT_VALUE;
+  /* variable used to read the gyro y data */
+  s16 gyro_datay = BNO055_INIT_VALUE;
+   /* variable used to read the gyro z data */
+  s16 gyro_dataz = BNO055_INIT_VALUE;
+   /* structure used to read the gyro xyz data */
+  struct bno055_gyro_t gyro_xyz;
+
+  /*************read raw Euler data************/
+  /* variable used to read the euler h data */
+  s16 euler_data_h = BNO055_INIT_VALUE;
+   /* variable used to read the euler r data */
+  s16 euler_data_r = BNO055_INIT_VALUE;
+  /* variable used to read the euler p data */
+  s16 euler_data_p = BNO055_INIT_VALUE;
+  /* structure used to read the euler hrp data */
+  struct bno055_euler_t euler_hrp;
+
+  /************read raw quaternion data**************/
+  /* variable used to read the quaternion w data */
+  s16 quaternion_data_w = BNO055_INIT_VALUE;
+  /* variable used to read the quaternion x data */
+  s16 quaternion_data_x = BNO055_INIT_VALUE;
+  /* variable used to read the quaternion y data */
+  s16 quaternion_data_y = BNO055_INIT_VALUE;
+  /* variable used to read the quaternion z data */
+  s16 quaternion_data_z = BNO055_INIT_VALUE;
+  /* structure used to read the quaternion wxyz data */
+  struct bno055_quaternion_t quaternion_wxyz;
+
+  /************read raw linear acceleration data***********/
+  /* variable used to read the linear accel x data */
+  s16 linear_accel_data_x = BNO055_INIT_VALUE;
+  /* variable used to read the linear accel y data */
+  s16 linear_accel_data_y = BNO055_INIT_VALUE;
+  /* variable used to read the linear accel z data */
+  s16 linear_accel_data_z = BNO055_INIT_VALUE;
+  /* structure used to read the linear accel xyz data */
+  struct bno055_linear_accel_t linear_acce_xyz;
+
+  /*****************read raw gravity sensor data****************/
+  /* variable used to read the gravity x data */
+  s16 gravity_data_x = BNO055_INIT_VALUE;
+  /* variable used to read the gravity y data */
+  s16 gravity_data_y = BNO055_INIT_VALUE;
+  /* variable used to read the gravity z data */
+  s16 gravity_data_z = BNO055_INIT_VALUE;
+  /* structure used to read the gravity xyz data */
+  struct bno055_gravity_t gravity_xyz;
+
+  /*************read accel converted data***************/
+  /* variable used to read the accel x data output as m/s2 or mg */
+  double d_accel_datax = BNO055_INIT_VALUE;
+  /* variable used to read the accel y data output as m/s2 or mg */
+  double d_accel_datay = BNO055_INIT_VALUE;
+  /* variable used to read the accel z data output as m/s2 or mg */
+  double d_accel_dataz = BNO055_INIT_VALUE;
+  /* structure used to read the accel xyz data output as m/s2 or mg */
+  struct bno055_accel_double_t d_accel_xyz;
+
+  /******************read mag converted data********************/
+  /* variable used to read the mag x data output as uT*/
+  double d_mag_datax = BNO055_INIT_VALUE;
+  /* variable used to read the mag y data output as uT*/
+  double d_mag_datay = BNO055_INIT_VALUE;
+  /* variable used to read the mag z data output as uT*/
+  double d_mag_dataz = BNO055_INIT_VALUE;
+  /* structure used to read the mag xyz data output as uT*/
+  struct bno055_mag_double_t d_mag_xyz;
+
+  /*****************read gyro converted data************************/
+  /* variable used to read the gyro x data output as dps or rps */
+  double d_gyro_datax = BNO055_INIT_VALUE;
+  /* variable used to read the gyro y data output as dps or rps */
+  double d_gyro_datay = BNO055_INIT_VALUE;
+  /* variable used to read the gyro z data output as dps or rps */
+  double d_gyro_dataz = BNO055_INIT_VALUE;
+  /* structure used to read the gyro xyz data output as dps or rps */
+  struct bno055_gyro_double_t d_gyro_xyz;
+
+  /*******************read euler converted data*******************/
+  /* variable used to read the euler h data output
+  as degree or radians*/
+  double d_euler_data_h = BNO055_INIT_VALUE;
+  /* variable used to read the euler r data output
+  as degree or radians*/
+  double d_euler_data_r = BNO055_INIT_VALUE;
+  /* variable used to read the euler p data output
+  as degree or radians*/
+  double d_euler_data_p = BNO055_INIT_VALUE;
+  /* structure used to read the euler hrp data output
+  as as degree or radians */
+  struct bno055_euler_double_t d_euler_hpr;
+
+  /*********read linear acceleration converted data**********/
+  /* variable used to read the linear accel x data output as m/s2*/
+  double d_linear_accel_datax = BNO055_INIT_VALUE;
+  /* variable used to read the linear accel y data output as m/s2*/
+  double d_linear_accel_datay = BNO055_INIT_VALUE;
+  /* variable used to read the linear accel z data output as m/s2*/
+  double d_linear_accel_dataz = BNO055_INIT_VALUE;
+  /* structure used to read the linear accel xyz data output as m/s2*/
+  struct bno055_linear_accel_double_t d_linear_accel_xyz;
+
+  /********************Gravity converted data**********************/
+  /* variable used to read the gravity sensor x data output as m/s2*/
+  double d_gravity_data_x = BNO055_INIT_VALUE;
+  /* variable used to read the gravity sensor y data output as m/s2*/
+  double d_gravity_data_y = BNO055_INIT_VALUE;
+  /* variable used to read the gravity sensor z data output as m/s2*/
+  double d_gravity_data_z = BNO055_INIT_VALUE;
+  /* structure used to read the gravity xyz data output as m/s2*/
+  struct bno055_gravity_double_t d_gravity_xyz;
+/*---------------------------------------------------------------------------*
+ *********************** START INITIALIZATION ************************
+ *--------------------------------------------------------------------------*/
+ #ifdef BNO055_API
+/*  Based on the user need configure I2C interface.
+ *  It is example code to explain how to use the bno055 API*/
+  I2C_routine();
+ #endif
+/*--------------------------------------------------------------------------*
+ *  This API used to assign the value/reference of
+ *  the following parameters
+ *  I2C address
+ *  Bus Write
+ *  Bus read
+ *  Chip id
+ *  Page id
+ *  Accel revision id
+ *  Mag revision id
+ *  Gyro revision id
+ *  Boot loader revision id
+ *  Software revision id
+ *-------------------------------------------------------------------------*/
+  comres = bno055_init(&bno055);
+
+/*  For initializing the BNO sensor it is required to the operation mode
+  of the sensor as NORMAL
+  Normal mode can set from the register
+  Page - page0
+  register - 0x3E
+  bit positions - 0 and 1*/
+  power_mode = BNO055_POWER_MODE_NORMAL;
+  /* set the power mode as NORMAL*/
+  comres += bno055_set_power_mode(power_mode);
+/*----------------------------------------------------------------*
+************************* END INITIALIZATION *************************
+*-----------------------------------------------------------------*/
+
+/************************* START READ RAW SENSOR DATA****************/
+
+/*  Using BNO055 sensor we can read the following sensor data and
+  virtual sensor data
+  Sensor data:
+    Accel
+    Mag
+    Gyro
+  Virtual sensor data
+    Euler
+    Quaternion
+    Linear acceleration
+    Gravity sensor */
+/*  For reading sensor raw data it is required to set the
+  operation modes of the sensor
+  operation mode can set from the register
+  page - page0
+  register - 0x3D
+  bit - 0 to 3
+  for sensor data read following operation mode have to set
+   * SENSOR MODE
+    *0x01 - BNO055_OPERATION_MODE_ACCONLY
+    *0x02 - BNO055_OPERATION_MODE_MAGONLY
+    *0x03 - BNO055_OPERATION_MODE_GYRONLY
+    *0x04 - BNO055_OPERATION_MODE_ACCMAG
+    *0x05 - BNO055_OPERATION_MODE_ACCGYRO
+    *0x06 - BNO055_OPERATION_MODE_MAGGYRO
+    *0x07 - BNO055_OPERATION_MODE_AMG
+    based on the user need configure the operation mode*/
+  comres += bno055_set_operation_mode(BNO055_OPERATION_MODE_AMG);
+/*  Raw accel X, Y and Z data can read from the register
+  page - page 0
+  register - 0x08 to 0x0D*/
+  comres += bno055_read_accel_x(&accel_datax);
+  comres += bno055_read_accel_y(&accel_datay);
+  comres += bno055_read_accel_z(&accel_dataz);
+  comres += bno055_read_accel_xyz(&accel_xyz);
+/*  Raw mag X, Y and Z data can read from the register
+  page - page 0
+  register - 0x0E to 0x13*/
+  comres += bno055_read_mag_x(&mag_datax);
+  comres += bno055_read_mag_y(&mag_datay);
+  comres += bno055_read_mag_z(&mag_dataz);
+  comres += bno055_read_mag_xyz(&mag_xyz);
+/*  Raw gyro X, Y and Z data can read from the register
+  page - page 0
+  register - 0x14 to 0x19*/
+  comres += bno055_read_gyro_x(&gyro_datax);
+  comres += bno055_read_gyro_y(&gyro_datay);
+  comres += bno055_read_gyro_z(&gyro_dataz);
+  comres += bno055_read_gyro_xyz(&gyro_xyz);
+
+/************************* END READ RAW SENSOR DATA****************/
+
+/************************* START READ RAW FUSION DATA ********
+  For reading fusion data it is required to set the
+  operation modes of the sensor
+  operation mode can set from the register
+  page - page0
+  register - 0x3D
+  bit - 0 to 3
+  for sensor data read following operation mode have to set
+  *FUSION MODE
+    *0x08 - BNO055_OPERATION_MODE_IMUPLUS
+    *0x09 - BNO055_OPERATION_MODE_COMPASS
+    *0x0A - BNO055_OPERATION_MODE_M4G
+    *0x0B - BNO055_OPERATION_MODE_NDOF_FMC_OFF
+    *0x0C - BNO055_OPERATION_MODE_NDOF
+    based on the user need configure the operation mode*/
+  comres += bno055_set_operation_mode(BNO055_OPERATION_MODE_NDOF);
+/*  Raw Euler H, R and P data can read from the register
+  page - page 0
+  register - 0x1A to 0x1E */
+  comres += bno055_read_euler_h(&euler_data_h);
+  comres += bno055_read_euler_r(&euler_data_r);
+  comres += bno055_read_euler_p(&euler_data_p);
+  comres += bno055_read_euler_hrp(&euler_hrp);
+/*  Raw Quaternion W, X, Y and Z data can read from the register
+  page - page 0
+  register - 0x20 to 0x27 */
+  comres += bno055_read_quaternion_w(&quaternion_data_w);
+  comres += bno055_read_quaternion_x(&quaternion_data_x);
+  comres += bno055_read_quaternion_y(&quaternion_data_y);
+  comres += bno055_read_quaternion_z(&quaternion_data_z);
+  comres += bno055_read_quaternion_wxyz(&quaternion_wxyz);
+/*  Raw Linear accel X, Y and Z data can read from the register
+  page - page 0
+  register - 0x28 to 0x2D */
+  comres += bno055_read_linear_accel_x(&linear_accel_data_x);
+  comres += bno055_read_linear_accel_y(&linear_accel_data_y);
+  comres += bno055_read_linear_accel_z(&linear_accel_data_z);
+  comres += bno055_read_linear_accel_xyz(&linear_acce_xyz);
+/*  Raw Gravity sensor X, Y and Z data can read from the register
+  page - page 0
+  register - 0x2E to 0x33 */
+  comres += bno055_read_gravity_x(&gravity_data_x);
+  comres += bno055_read_gravity_y(&gravity_data_y);
+  comres += bno055_read_gravity_z(&gravity_data_z);
+  comres += bno055_read_gravity_xyz(&gravity_xyz);
+/************************* END READ RAW FUSION DATA  ************/
+
+/******************START READ CONVERTED SENSOR DATA****************/
+/*  API used to read accel data output as double  - m/s2 and mg
+  float functions also available in the BNO055 API */
+  comres += bno055_convert_double_accel_x_msq(&d_accel_datax);
+  comres += bno055_convert_double_accel_x_mg(&d_accel_datax);
+  comres += bno055_convert_double_accel_y_msq(&d_accel_datay);
+  comres += bno055_convert_double_accel_y_mg(&d_accel_datay);
+  comres += bno055_convert_double_accel_z_msq(&d_accel_dataz);
+  comres += bno055_convert_double_accel_z_mg(&d_accel_dataz);
+  comres += bno055_convert_double_accel_xyz_msq(&d_accel_xyz);
+  comres += bno055_convert_double_accel_xyz_mg(&d_accel_xyz);
+
+/*  API used to read mag data output as double  - uT(micro Tesla)
+  float functions also available in the BNO055 API */
+  comres += bno055_convert_double_mag_x_uT(&d_mag_datax);
+  comres += bno055_convert_double_mag_y_uT(&d_mag_datay);
+  comres += bno055_convert_double_mag_z_uT(&d_mag_dataz);
+  comres += bno055_convert_double_mag_xyz_uT(&d_mag_xyz);
+
+/*  API used to read gyro data output as double  - dps and rps
+  float functions also available in the BNO055 API */
+  comres += bno055_convert_double_gyro_x_dps(&d_gyro_datax);
+  comres += bno055_convert_double_gyro_y_dps(&d_gyro_datay);
+  comres += bno055_convert_double_gyro_z_dps(&d_gyro_dataz);
+  comres += bno055_convert_double_gyro_x_rps(&d_gyro_datax);
+  comres += bno055_convert_double_gyro_y_rps(&d_gyro_datay);
+  comres += bno055_convert_double_gyro_z_rps(&d_gyro_dataz);
+  comres += bno055_convert_double_gyro_xyz_dps(&d_gyro_xyz);
+  comres += bno055_convert_double_gyro_xyz_rps(&d_gyro_xyz);
+
+/*  API used to read Euler data output as double  - degree and radians
+  float functions also available in the BNO055 API */
+  comres += bno055_convert_double_euler_h_deg(&d_euler_data_h);
+  comres += bno055_convert_double_euler_r_deg(&d_euler_data_r);
+  comres += bno055_convert_double_euler_p_deg(&d_euler_data_p);
+  comres += bno055_convert_double_euler_h_rad(&d_euler_data_h);
+  comres += bno055_convert_double_euler_r_rad(&d_euler_data_r);
+  comres += bno055_convert_double_euler_p_rad(&d_euler_data_p);
+  comres += bno055_convert_double_euler_hpr_deg(&d_euler_hpr);
+  comres += bno055_convert_double_euler_hpr_rad(&d_euler_hpr);
+
+/*  API used to read Linear acceleration data output as m/s2
+  float functions also available in the BNO055 API */
+  comres += bno055_convert_double_linear_accel_x_msq(
+  &d_linear_accel_datax);
+  comres += bno055_convert_double_linear_accel_y_msq(
+  &d_linear_accel_datay);
+  comres += bno055_convert_double_linear_accel_z_msq(
+  &d_linear_accel_dataz);
+  comres += bno055_convert_double_linear_accel_xyz_msq(
+  &d_linear_accel_xyz);
+
+/*  API used to read Gravity sensor data output as m/s2
+  float functions also available in the BNO055 API */
+  comres += bno055_convert_gravity_double_x_msq(&d_gravity_data_x);
+  comres += bno055_convert_gravity_double_y_msq(&d_gravity_data_y);
+  comres += bno055_convert_gravity_double_z_msq(&d_gravity_data_z);
+  comres += bno055_convert_double_gravity_xyz_msq(&d_gravity_xyz);
+/*-----------------------------------------------------------------------*
+************************* START DE-INITIALIZATION ***********************
+*-------------------------------------------------------------------------*/
+/*  For de - initializing the BNO sensor it is required
+  to the operation mode of the sensor as SUSPEND
+  Suspend mode can set from the register
+  Page - page0
+  register - 0x3E
+  bit positions - 0 and 1*/
+  power_mode = BNO055_POWER_MODE_SUSPEND;
+  /* set the power mode as SUSPEND*/
+  comres += bno055_set_power_mode(power_mode);
+
+/*---------------------------------------------------------------------*
+************************* END DE-INITIALIZATION **********************
+*---------------------------------------------------------------------*/
+return comres;
+}
+
+#ifdef  BNO055_API
+/*--------------------------------------------------------------------------*
+* The following API is used to map the I2C bus read, write, delay and
+* device address with global structure bno055_t
+*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*
+ *  By using bno055 the following structure parameter can be accessed
+ *  Bus write function pointer: BNO055_WR_FUNC_PTR
+ *  Bus read function pointer: BNO055_RD_FUNC_PTR
+ *  Delay function pointer: delay_msec
+ *  I2C address: dev_addr
+ *--------------------------------------------------------------------------*/
+s8 I2C_routine(void)
+{
+  bno055.bus_write = BNO055_I2C_bus_write;
+  bno055.bus_read = BNO055_I2C_bus_read;
+  bno055.delay_msec = BNO055_delay_msek;
+  bno055.dev_addr = BNO055_I2C_ADDR1;
+
+  return BNO055_INIT_VALUE;
+}
+
+/************** I2C buffer length******/
+
+#define I2C_BUFFER_LEN 8
+#define I2C0 5
+/*-------------------------------------------------------------------*
+*
+* This is a sample code for read and write the data by using I2C
+* Use either I2C  based on your need
+* The device address defined in the bno055.h file
+*
+*--------------------------------------------------------------------*/
+
+/*  \Brief: The API is used as I2C bus write
+ *  \Return : Status of the I2C write
+ *  \param dev_addr : The device address of the sensor
+ *  \param reg_addr : Address of the first register,
+ *   will data is going to be written
+ *  \param reg_data : It is a value hold in the array,
+ *    will be used for write the value into the register
+ *  \param cnt : The no of byte of data to be write
+ */
+s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
+{
+  s32 BNO055_iERROR = BNO055_INIT_VALUE;
+  u8 array[I2C_BUFFER_LEN];
+  u8 stringpos = BNO055_INIT_VALUE;
+
+  array[BNO055_INIT_VALUE] = reg_addr;
+  for (stringpos = BNO055_INIT_VALUE; stringpos < cnt; stringpos++)
+    array[stringpos + BNO055_I2C_BUS_WRITE_ARRAY_INDEX] =
+      *(reg_data + stringpos);
+  }
+  /*
+  * Please take the below APIs as your reference for
+  * write the data using I2C communication
+  * "BNO055_iERROR = I2C_WRITE_STRING(DEV_ADDR, ARRAY, CNT+1)"
+  * add your I2C write APIs here
+  * BNO055_iERROR is an return value of I2C read API
+  * Please select your valid return value
+  * In the driver BNO055_SUCCESS defined as 0
+    * and FAILURE defined as -1
+  * Note :
+  * This is a full duplex operation,
+  * The first read data is discarded, for that extra write operation
+  * have to be initiated. For that cnt+1 operation done
+  * in the I2C write string function
+  * For more information please refer data sheet SPI communication:
+  */
+  return (s8)BNO055_iERROR;
+}
+
+ /* \Brief: The API is used as I2C bus read
+ *  \Return : Status of the I2C read
+ *  \param dev_addr : The device address of the sensor
+ *  \param reg_addr : Address of the first register,
+ *  will data is going to be read
+ *  \param reg_data : This data read from the sensor,
+ *   which is hold in an array
+ *  \param cnt : The no of byte of data to be read
+ */
+s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
+{
+  s32 BNO055_iERROR = BNO055_INIT_VALUE;
+  u8 array[I2C_BUFFER_LEN] = {BNO055_INIT_VALUE};
+  u8 stringpos = BNO055_INIT_VALUE;
+
+  array[BNO055_INIT_VALUE] = reg_addr;
+
+  /* Please take the below API as your reference
+   * for read the data using I2C communication
+   * add your I2C read API here.
+   * "BNO055_iERROR = I2C_WRITE_READ_STRING(DEV_ADDR,
+   * ARRAY, ARRAY, 1, CNT)"
+   * BNO055_iERROR is an return value of SPI write API
+   * Please select your valid return value
+     * In the driver BNO055_SUCCESS defined as 0
+     * and FAILURE defined as -1
+   */
+  for (stringpos = BNO055_INIT_VALUE; stringpos < cnt; stringpos++)
+    *(reg_data + stringpos) = array[stringpos];
+  return (s8)BNO055_iERROR;
+}
+/*  Brief : The delay routine
+ *  \param : delay in ms
+*/
+void BNO055_delay_msek(u32 msek)
+{
+  /*Here you can write your own delay routine*/
+}
+
+#endif
+// - - - -
+// end code from Boschs bno055_support.c
+

 /* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
  which provides a common 'type' for sensor data and some helper functions.


demo animation mostly working except for effects

--- Arduino/linkit_duo_led6/linkit_duo_led6.ino
+++ Arduino/linkit_duo_led6/linkit_duo_led6.ino
@@ -1,3 +1,5 @@
+//efade is broken, brightness wrong after demo animation
+

 #include <PololuLedStrip.h>
 PololuLedStrip<12> ledStrip;
@@ -5,8 +7,10 @@
 #define RANDOM_SEED_PIN A1

 #define EASE_EXPONENT 3 // cubic
-#define EASE_COUNT 64
-#define EASE_DELAY 4
+#define EASE_COUNT 32
+#define POWER_EASE_COUNT 24
+#define EASE_DELAY 2
+#define POWER_EASE_DELAY 2
 #define EASE_ANIM_MARGIN 15

 #define ANIM_LED_COUNT 64
@@ -14,10 +18,12 @@
 #define MAX_LED (LED_COUNT)
 rgb_color colors[LED_COUNT];
 rgb_color render[LED_COUNT];
+rgb_color backbuffer[LED_COUNT];

 int effects[LED_COUNT];

-float ease[ANIM_LED_COUNT];
+float elastic_ease[EASE_COUNT];
+float power_ease[EASE_COUNT];

 #define BRIGHTNESS_DIVISOR 15.0
 #define DEFAULT_BRIGHTNESS_PERCENT 20
@@ -48,8 +54,8 @@
 rgb_color dkgray = {5, 5, 5};

 #define NPALETTE 16
-#define NPRETTY_COLORS 13
-rgb_color palette[NPALETTE] = { white, red, orange, yellow, ltgreen, green, seafoam, cyan, ltblue, blue, purple, magenta, pink, black, gray, dkgray };
+#define NPRETTY_COLORS 12
+rgb_color palette[NPALETTE] = { red, orange, yellow, ltgreen, green, seafoam, cyan, ltblue, blue, purple, magenta, pink, white, black, gray, dkgray };
 rgb_color adjusted_palette[NPALETTE];

 rgb_color scale_color(rgb_color color, float scale){
@@ -75,13 +81,18 @@
 //  }
 //}

+void display_buffer(rgb_color * pbuffer = render){
+  ledStrip.write(pbuffer, ANIM_LED_COUNT);
+}
+
 void erase(bool display = false){
   for(int i = 0; i < ANIM_LED_COUNT; i++){
     colors[i] = black;
     effects[i] = 0;
   }
   if(display){
-    ledStrip.write(colors, ANIM_LED_COUNT);
+    //ledStrip.write(colors, ANIM_LED_COUNT);
+    display_buffer(colors);
   }
 }

@@ -112,6 +123,7 @@
   memcpy(adjusted_palette, palette, sizeof(palette));
 }

+#define LEAVE_EFFECT -1
 #define NO_EFFECT 0
 #define BREATHE_ON 1
 #define RANDOM 2
@@ -135,18 +147,44 @@

 #define STATIC_ON 101

-void push_color(rgb_color color, bool display = false){
-  for(int i = MAX_LED - 1; i >= 1; i--){
-    colors[i] = colors[i-1];
-    effects[i] = effects[i-1];
-  }
-  colors[0] = color;
-  effects[0] = NO_EFFECT;
-
+#define RANDOM_EFFECTS 12
+int random_effects[] = { NO_EFFECT, BREATHE_ON, RANDOM, BLINK_ON, BLINK_ON_1, BLINK_ON_2, BLINK_ON_3, BLINK_ON_4, BLINK_ON_5, BLINK_ON_6, BLINK_ON_A, BLINK_ON_B };
+
+void shift_buffer(rgb_color * buffer, bool include_effects = true, int max = ANIM_LED_COUNT){
+  for(int i = max - 1; i >= 1; i--){
+    buffer[i] = buffer[i-1];
+    if(include_effects){
+      effects[i] = effects[i-1];
+    }
+  }
+}
+
+void push_color(rgb_color color, bool display = false, int effect = NO_EFFECT, rgb_color *buffer = colors, int max = ANIM_LED_COUNT){
+  shift_buffer(buffer, effect = LEAVE_EFFECT ? false : true, max);
+
+  buffer[0] = color;
+
+  if(effect != LEAVE_EFFECT){
+    effects[0] = effect;
+  }
+
   if(display){
-    ledStrip.write(colors, ANIM_LED_COUNT);
-  }
-}
+    display_buffer(buffer);
+  }
+}
+
+void set_color(int pos, rgb_color color, bool display = false, int effect = NO_EFFECT, rgb_color *buffer = colors){
+  buffer[pos] = color;
+
+  if(effect != LEAVE_EFFECT){
+    effects[pos] = effect;
+  }
+
+  if(display){
+    display_buffer(buffer);
+  }
+}
+

 #define MAX_BLINK 6000
 #define BLINK_0 0
@@ -265,11 +303,36 @@
 void do_fade(float rate = FADE_RATE){
   for(int i = 0; i < FADE_TIMES; i++){
     fade(rate);
-    ledStrip.write(colors, ANIM_LED_COUNT);
+    //ledStrip.write(colors, ANIM_LED_COUNT);
+    display_buffer(colors);
     delay(FADE_DELAY);
   }
+//  for(int i = 0; i < ANIM_LED_COUNT; i++){
+//    effects[i] = NO_EFFECT;
+//  }
+  erase();
+}
+
+void exhale_fade(int level){
+  unsigned char *p;
+  p = (unsigned char *)colors;
+  for(int i = 0; i < ANIM_LED_COUNT * 3; i++){
+    *(p + i) *= breathe_steps[i];
+  }
+}
+
+void do_exhale_fade(){
+  for(int i = 0; i < BREATHE_MAX_STEP; i++){
+    exhale_fade(i);
+    display_buffer(colors);
+    delay(FADE_DELAY);
+  }
+  erase();
+}
+
+void copy_buffer(rgb_color *source, rgb_color *destination, int count = ANIM_LED_COUNT){
   for(int i = 0; i < ANIM_LED_COUNT; i++){
-    effects[i] = NO_EFFECT;
+    destination[i] = source[i];
   }
 }

@@ -288,6 +351,10 @@
   return palette[random(NPRETTY_COLORS)];
 }

+int random_effect(){
+  return random_effects[random(RANDOM_EFFECTS)];
+}
+
 void do_random(){
   push_color(random_color());
   effects[0] = RANDOM;
@@ -295,8 +362,8 @@

 void do_mirror(){
   for(int i = 0; i < ANIM_LED_COUNT / 2; i++){
-    colors[ANIM_LED_COUNT - i - 1] = colors[i];
-    effects[ANIM_LED_COUNT - i - 1] = effects[i];
+    colors[(ANIM_LED_COUNT - 1) - i] = colors[i];
+    effects[(ANIM_LED_COUNT - 1) - i] = effects[i];
   }
 }

@@ -339,9 +406,9 @@
   }
 }

-void display_buffer(){
-  ledStrip.write(render, ANIM_LED_COUNT);
-}
+//void display_buffer(int i = 0){
+//
+//}

 bool paused = false;

@@ -378,8 +445,8 @@
   float midpoint = count / 2;
   for(int i = 0; i < midpoint; i++){
     float percent = i / midpoint;
-    ease[i] = 0.5 * (ease_power_in(percent, power));
-    ease[i + int(midpoint)] = (0.5 * (ease_power_out(percent, power))) + 0.5;
+    power_ease[i] = 0.5 * (ease_power_in(percent, power));
+    power_ease[i + int(midpoint)] = (0.5 * (ease_power_out(percent, power))) + 0.5;
   }
 }

@@ -388,68 +455,96 @@
   float midpoint = count / 2;
   for(int i = 0; i < midpoint; i++){
     float percent = i / midpoint;
-    ease[i] = 0.5 * (ease_power_in(percent, power));
-    ease[i + int(midpoint)] = (0.5 * (ease_elastic_out(percent))) + 0.5;
-  }
-}
-
-void shift(int count){
+    elastic_ease[i] = 0.5 * (ease_power_in(percent, power));
+    elastic_ease[i + int(midpoint)] = (0.5 * (ease_elastic_out(percent))) + 0.5;
+  }
+}
+
+// animate by shifting frame (future: shift in from back buffer)
+void shift(int count, int max = ANIM_LED_COUNT){
   for(int i = 0; i < count; i++){
     render[i] = black;
   }
-  for(int i = count; i < ANIM_LED_COUNT; i++){
+  for(int i = count; i < max; i++){
     render[i] = scale_color(colors[i - count], DEFAULT_BRIGHTNESS_SCALE);
   }

-  ledStrip.write(render, ANIM_LED_COUNT);
-}
-
-void unshift(int count){
-  for(int i = 0; i < ANIM_LED_COUNT - count; i++){
-    render[i] = scale_color(colors[i + count], DEFAULT_BRIGHTNESS_SCALE);
-  }
-
-  ledStrip.write(render, ANIM_LED_COUNT);
-}
-
-void do_elastic_shift(int count){
+  display_buffer();
+}
+
+void finalize_shift(int count, int max){
+  for(int i = 0; i < count; i++){
+    push_color(black, false, NO_EFFECT, colors, max);
+  }
+}
+
+//    push_color(black, false, LEAVE_EFFECT, backbuffer);
+
+void do_elastic_shift(int count, int max = ANIM_LED_COUNT, bool display_only = false){
   count = count == 0 ? 1 : count;
   if(count >= 1){
     for(int i = 0; i < EASE_COUNT; i++){
-      int pos = ease[i] * count;
+      int pos = elastic_ease[i] * count;
       delay(EASE_DELAY);
-      shift(pos);
-    }
-    for(int i = 0; i < count; i++){
-      push_color(black);
-    }
-
-//    for(int i = 0; i < ANIM_LED_COUNT; i++){
-//      colors[i] = render[i];
-//    }
-//    for(int i = 0; i < count; i++){
-//      effects[i] = NO_EFFECT;
-//    }
-//    for(int i = ANIM_LED_COUNT - 1; i >= count; i--){
-//      effects[i] = effects[i - count];
-//    }
-
-    for(int i = 0; i < ANIM_LED_COUNT; i++){
-      int index = ANIM_LED_COUNT - 1;
-      if(i >= count){
-        effects[index] = effects[index - count];
-      } else {
-        effects[index] = NO_EFFECT;
-      }
-    }
-  } else {
-//    count *= -1;
-//    for(int i = 0; i < EASE_COUNT; i++){
-//      int pos = ease[i] * count;
-//      delay(EASE_DELAY);
-//      unshift(count - pos); // broken
-//    }
-  }
+      shift(pos, max);
+    }
+    if(!display_only){
+      finalize_shift(count, max);
+    }
+  }
+}
+
+void do_power_shift(int count, int max = ANIM_LED_COUNT, bool display_only = false){
+  count = count == 0 ? 1 : count;
+  if(count >= 1){
+    for(int i = 0; i < POWER_EASE_COUNT; i++){
+      int pos = power_ease[i] * count;
+      delay(POWER_EASE_DELAY);
+      shift(pos+1, max);
+    }
+    if(!display_only){
+      finalize_shift(count, max);
+    }
+  }
+}
+
+#define DEMO_OBJECT_SIZE 3
+#define DEMO_GAP_SIZE 1
+#define DEMO_TOTAL_SIZE (DEMO_OBJECT_SIZE + DEMO_GAP_SIZE)
+
+// be able to reverse shift/animation direction
+
+void do_demo(int count = ANIM_LED_COUNT / DEMO_TOTAL_SIZE){
+
+  // set some pattern of colors and effects
+  // set window including last place it should animate to
+  // animate N positions
+  // during animation, render
+
+  if(count < 1) count = 1;
+  int window = ANIM_LED_COUNT;
+
+  for(int i = 0; i < count; i++){
+    rgb_color color = random_color();
+    do_power_shift(window, window + DEMO_TOTAL_SIZE);
+    window -= DEMO_TOTAL_SIZE;
+
+    int effect = BREATHE_ON; //random_effect();
+
+    for(int j = DEMO_GAP_SIZE; j < DEMO_TOTAL_SIZE; j++){
+      set_color(j, color, false, effect);
+//      push_color(color, false, LEAVE_EFFECT, backbuffer);
+    }
+  }
+
+//  copy_buffer(backbuffer, colors);
+//  rgb_color color = random_color();
+//  int effect = random_effect();
+//
+//  // fill final position
+//  for(int j = 0; j < DEMO_OBJECT_SIZE; j++){
+//    set_color(j, color, false, effect);
+//  }
 }

 void setup() {
@@ -461,11 +556,14 @@

   random_seed();
   setup_colors(false);
+  set_brightness(DEFAULT_BRIGHTNESS_PERCENT);
   erase(true);
   generate_elastic_ease(EASE_COUNT, EASE_EXPONENT);
-}
-
-#define MAX_STRING_LENGTH 16
+  generate_power_ease(POWER_EASE_COUNT, EASE_EXPONENT);
+  do_demo();
+}
+
+#define MAX_STRING_LENGTH 100

 bool is_command(char *str, char *command){
   return strcmp(str, command) == 0;
@@ -474,12 +572,14 @@
 void loop(){
   char str[MAX_STRING_LENGTH];
   char arg[MAX_STRING_LENGTH];
+  //char last[MAX_STRING_LENGTH];
   rgb_color color;

   if(Serial1.available() > 0){
     int c = Serial1.readBytesUntil('|', str, MAX_STRING_LENGTH);
     str[c] = 0;

+replay:
     // reset the effects so the automatic render won't interfere
     blink_state = true;
     blink_state_1 = false;
@@ -513,12 +613,14 @@
 // transitions
 // if something is not recognized assume it's an argument for the next command
 // copy -- everything up to black is copied on top of black
-// repeat x the unrecognized argument as an integer
 // stop sign timing and opposite timing
 // reverse, inverse mirror
 // brief flash, or something, to alert to a new (green?) build
 // some way to visually tell which are changes from a little while ago (like the fading yellow highlight on web pages)
 // demo - do random stuff
+// full frame animation in/out using back buffer
+// need a window on animations so later parts of buffer can remain untouched
+// separate velocities per type of animation

     if(is_command(str, "repeat")){
       int times = String(arg).toInt();
@@ -541,16 +643,20 @@
     else if(is_command(str, "blinka"))   start_effect(BLINK_ON_A);
     else if(is_command(str, "blinkb"))   start_effect(BLINK_ON_B);
     else if(is_command(str, "breathe"))  start_effect(BREATHE_ON);
+    //else if(is_command(str, "replay"))   { strcpy(arg, last); goto replay; }
     else if(is_command(str, "flush"))    flush();
     else if(is_command(str, "blend"))    do_blend();
     else if(is_command(str, "max"))      do_max();
     else if(is_command(str, "dim"))      do_dim();
     else if(is_command(str, "bright"))   do_bright();
     else if(is_command(str, "fade"))     do_fade();
+    else if(is_command(str, "efade"))    do_exhale_fade();
     else if(is_command(str, "flood"))    do_flood();
     else if(is_command(str, "random"))   do_random();
     else if(is_command(str, "mirror"))   do_mirror();
     else if(is_command(str, "eshift"))   do_elastic_shift(String(arg).toInt());
+    else if(is_command(str, "pshift"))   do_power_shift(String(arg).toInt());
+    else if(is_command(str, "demo"))     do_demo();
     else if(is_command(str, "static"))   start_static();
     else if(is_command(str, "red"))      push_color(red);
     else if(is_command(str, "green"))    push_color(green);
@@ -569,13 +675,15 @@
     else if(is_command(str, "ltblue"))   push_color(ltblue);
     else if(is_command(str, "dkgray"))   push_color(dkgray);
     else strcpy(arg, str);
+
+    //strcpy(last, arg);
   }
   else
   {
     bool should_flush = false;

     blink_counter = (blink_counter + 1) % MAX_BLINK;
-    if(blink_counter == BLINK_0){
+    if(blink_counter == BLINK_1){
       if(blink_state){
         blink_state = false;
       } else {