add "configuration" instructions at top to make it clearer

--- AnimatedGIFs.ino
+++ AnimatedGIFs.ino
@@ -26,33 +26,43 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */

- /*
-  * This example displays 32x32 GIF animations loaded from a SD Card connected to the Teensy 3.1
-  * The GIFs can be up to 32 pixels in width and height.
-  * This code has been tested with 32x32 pixel and 16x16 pixel GIFs, but is optimized for 32x32 pixel GIFs.
-  *
-  * Wiring is on the default Teensy 3.1 SPI pins, and chip select can be on any GPIO,
-  * set by defining SD_CS in the code below
-  * Function     | Pin
-  * DOUT         |  11
-  * DIN          |  12
-  * CLK          |  13
-  * CS (default) |  15
-  *
-  * This code first looks for .gif files in the /gifs/ directory
-  * (customize below with the GIF_DIRECTORY definition) then plays random GIFs in the directory,
-  * looping each GIF for DISPLAY_TIME_SECONDS
-  *
-  * This example is meant to give you an idea of how to add GIF playback to your own sketch.
-  * For a project that adds GIF playback with other features, take a look at
-  * Light Appliance and Aurora:
-  * https://github.com/CraigLindley/LightAppliance
-  * https://github.com/pixelmatix/aurora
-  *
-  * If you find any GIFs that won't play properly, please attach them to a new
-  * Issue post in the GitHub repo here:
-  * https://github.com/pixelmatix/AnimatedGIFs/issues
-  */
+/*
+ * This example displays 32x32 GIF animations loaded from a SD Card connected to the Teensy 3.1
+ * The GIFs can be up to 32 pixels in width and height.
+ * This code has been tested with 32x32 pixel and 16x16 pixel GIFs, but is optimized for 32x32 pixel GIFs.
+ *
+ * Wiring is on the default Teensy 3.1 SPI pins, and chip select can be on any GPIO,
+ * set by defining SD_CS in the code below
+ * Function     | Pin
+ * DOUT         |  11
+ * DIN          |  12
+ * CLK          |  13
+ * CS (default) |  15
+ *
+ * This code first looks for .gif files in the /gifs/ directory
+ * (customize below with the GIF_DIRECTORY definition) then plays random GIFs in the directory,
+ * looping each GIF for DISPLAY_TIME_SECONDS
+ *
+ * This example is meant to give you an idea of how to add GIF playback to your own sketch.
+ * For a project that adds GIF playback with other features, take a look at
+ * Light Appliance and Aurora:
+ * https://github.com/CraigLindley/LightAppliance
+ * https://github.com/pixelmatix/aurora
+ *
+ * If you find any GIFs that won't play properly, please attach them to a new
+ * Issue post in the GitHub repo here:
+ * https://github.com/pixelmatix/AnimatedGIFs/issues
+ */
+
+/*
+ * CONFIGURATION:
+ *  - update the "SmartMatrix configuration and memory allocation" section to match the width and height and other configuration of your display
+ *  - Note for 128x32 and 64x64 displays - need to reduce RAM:
+ *    set kRefreshDepth=24 and kDmaBufferRows=2 or set USB Type: "None" in Arduino,
+ *    decrease refreshRate in setup() to 90 or lower to get good an accurate GIF frame rate
+ *  - WIDTH and HEIGHT are defined in GIFParseFunctions.cpp, update to match the size of your GIFs
+ *    only play GIFs that are size WIDTHxHEIGHT or smaller
+ */

 #include <SmartMatrix3.h>
 #include <SPI.h>
@@ -69,8 +79,6 @@
 const rgb24 COLOR_BLACK = {
     0, 0, 0 };

-// WIDTH and HEIGHT are defined in GIFParseFunctions.cpp, only play GIFs that are size WIDTHxHEIGHT or smaller
-// Note for 128x32 and 64x64 displays - set kRefreshDepth=24 and kDmaBufferRows=2 to reduce RAM, decrease refreshRate in setup() to 90 to get good GIF frame rate

 /* SmartMatrix configuration and memory allocation */
 #define COLOR_DEPTH 24                  // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24
@@ -127,8 +135,8 @@

     matrix.begin();

-    // for large panels, set the refresh lower to give more CPU time to decoding GIFs
     //matrix.setRefreshRate(90);
+    // for large panels, set the refresh rate lower to leave more CPU time to decoding GIFs (needed if GIFs are playing back slowly)

     // Clear screen
     backgroundLayer.fillScreen(COLOR_BLACK);


activate device identifiers

activate device identifiers

--- examples/LightDependentResistanceValue/LightDependentResistanceValue.ino
+++ examples/LightDependentResistanceValue/LightDependentResistanceValue.ino
@@ -30,7 +30,7 @@
 void loop() {
   // put your main code here, to run repeatedly:
   if (!isActive) {
-    IvenResponse i = client.activateDevice("dasd", "asdasd");
+    IvenResponse i = client.activateDevice("your_device_secret_key(40 characters)", "your_device_id(on the Iven Cloud)");
     Serial.println(i.error);
     Serial.println(i.httpStatus);
     Serial.println(i.ivenCode);


Changed working demo to support safe mode swapping.  Refactoring coming up, then a push to master.

--- scr_arduino/scr_arduino.ino
+++ scr_arduino/scr_arduino.ino
@@ -33,7 +33,7 @@
 #define PMD_RESET 8

 // Ros Initialization stuff
-ros::NodeHandle_<ArduinoHardware, 5, 5, 256, 256>  nh;
+ros::NodeHandle_<ArduinoHardware, 10, 10, 256, 256>  nh;

 // Wheel Speed Messages
 std_msgs::Float32 l_wheel_msg;
@@ -41,6 +41,7 @@

 // Motors Command Message
 scr_proto::SpeedCommand motor_msg;
+std_msgs::Int32 mode_msg;

 // Initialize Publishers
 ros::Publisher left_wheel_pub("lw_speed", &l_wheel_msg);
@@ -85,18 +86,20 @@
 PID L_DCMotorPID(&L_WheelVelocity,
                  &L_PIDout,
                  &lw_cmd_spd,
-                 0.65,
+                 0.15,
                  0.00,
-                 0.10,
+                 0.010,
                  REVERSE);

 PID R_DCMotorPID(&R_WheelVelocity,
                  &R_PIDout,
                  &rw_cmd_spd,
-                 0.6,
+                 0.15,
                  0.00,
-                 0.10,
+                 0.010,
                  REVERSE);
+
+int mode = 0;

 // Motor Callbacks
 void MotorCallback(const scr_proto::SpeedCommand& motor_com){
@@ -104,44 +107,58 @@
   rw_cmd_spd = motor_com.right_motor_w;
 }

+// Command Callback
+void CommandCallback(const std_msgs::Int32& mode_msg){
+
+  if(mode_msg.data == 1){
+    mode = mode_msg.data;
+    nh.loginfo("Arduino Normal Mode Active");
+  }
+  else if(mode_msg.data == 0){
+    mode = mode_msg.data;
+    nh.loginfo("Arduino Safe Mode Active");
+  }
+  else{
+    nh.loginfo("Invalid Mode Command. Modes are 0 for Safe mode and 1 for normal mode");
+  }
+
+}
+
 void updateEncoderReading() {
   // Get raw ticks
   long L_encoderValue = L_DCMotorEncoder.read();
   long R_encoderValue = R_DCMotorEncoder.read();

-  // Get position in revolutions (includes multiple revolutions)
-// Serial.println(encoderValue);
+  // Current time in micro seconds
+  long now = micros();
+
+  long dt = (now - last_encoder_time);
+
+  // Get position in ticks with low pass filter
   L_EncoderDelta = (double)(L_encoderValue - L_LastEncoderValue) * (1-beta) + L_LastEncoderDelta * beta;
   R_EncoderDelta = (double)(R_encoderValue - R_LastEncoderValue) * (1-beta) + R_LastEncoderDelta * beta;
-// Serial.println(g_EncoderAngle);
-
-  //double dt = nh.now().toSec() - last_encoder_time.toSec();
-  double dt = micros() - last_encoder_time;
-
-  // Get velocity in ticks/sec
-  L_EncoderVelocity = 1000000*(double)(L_EncoderDelta)/(double)dt;
-  R_EncoderVelocity = 1000000*(double)(R_EncoderDelta)/(double)dt;
-
-  // Convert to revolutions/sec
-  L_EncoderVelocity /= (double)TICKS_PER_REVOLUTION;
-  R_EncoderVelocity /= (double)TICKS_PER_REVOLUTION;
-
-  // Convert to rad/s
+
+  // Get velocity in revs/sec
+  L_EncoderVelocity = 1000000.0/dt * L_EncoderDelta/TICKS_PER_REVOLUTION;
+  R_EncoderVelocity = 1000000.0/dt * R_EncoderDelta/TICKS_PER_REVOLUTION;
+
+  // Convert to rad/sec
   L_WheelVelocity = L_EncoderVelocity * 2 * PI;
   R_WheelVelocity = R_EncoderVelocity * 2 * PI;

-  // Set last known encoder ticks
+  // Update previous values
   L_LastEncoderValue = L_encoderValue;
   R_LastEncoderValue = R_encoderValue;

+  last_encoder_time = now;
+
   L_LastEncoderDelta = L_EncoderDelta;
   R_LastEncoderDelta = R_EncoderDelta;

-  last_encoder_time = micros();
 }

 ros::Subscriber<scr_proto::SpeedCommand> motor_sub("speed_command", MotorCallback);
-
+ros::Subscriber<std_msgs::Int32> command_sub("arduino_mode", CommandCallback);

 // Rx, Tx, Reset Pins
 PololuQik2s12v10 pmd(PMD_RX, PMD_TX, PMD_RESET);
@@ -157,6 +174,7 @@

   //Command Subscriber
   nh.subscribe(motor_sub);
+  nh.subscribe(command_sub);

   // Wheel Speeds in rad/s
   nh.advertise(right_wheel_pub);
@@ -176,6 +194,10 @@

 void loop()
 {
+  if(mode == 0){
+    lw_cmd_spd = 0;
+    rw_cmd_spd = 0;
+  }
   // Get Freshest Values
   updateEncoderReading();

@@ -187,6 +209,10 @@
   lm_cmd += L_PIDout;
   rm_cmd += R_PIDout;

+ if(mode == 0){
+    lm_cmd = 0;
+    rm_cmd = 0;
+  }
   // Populate messages
   l_wheel_msg.data = L_WheelVelocity;
   r_wheel_msg.data = R_WheelVelocity;


Final cleanup in .ino file for functional embedded layer

--- scr_arduino/scr_arduino.ino
+++ scr_arduino/scr_arduino.ino
@@ -46,8 +46,6 @@
 // Initialize Publishers
 ros::Publisher left_wheel_pub("lw_speed", &l_wheel_msg);
 ros::Publisher right_wheel_pub("rw_speed", &r_wheel_msg);
-
-//os::Time last_encoder_time = nh.now();

 double last_encoder_time = micros();


Modified Nodehandle and rate to attempt to fix comms with Bb.

--- scr_arduino/scr_arduino.ino
+++ scr_arduino/scr_arduino.ino
@@ -33,7 +33,7 @@
 #define PMD_RESET 8

 // Ros Initialization stuff
-ros::NodeHandle_<ArduinoHardware, 10, 10, 256, 256>  nh;
+ros::NodeHandle_<ArduinoHardware, 3, 3, 128, 128>  nh;

 // Wheel Speed Messages
 std_msgs::Float32 l_wheel_msg;
@@ -227,6 +227,6 @@
   // Write Speeds to motor driver
   pmd.setSpeeds(lm_cmd, rm_cmd);

-  delay(20);
-}
-
+  delay(30);
+}
+


make blinky better with more patterns

make blinky better with more patterns

--- src/blinky.ino
+++ src/blinky.ino
@@ -7,15 +7,55 @@
 #include "FastLED.h"
 #include "hsv.h"

-#define PIXEL_COUNT 24
+struct DeckSettings {
+  uint8_t label;
+  float crossfadePositionActive;
+  uint8_t pattern;
+  uint8_t palette;
+  uint8_t animationIndex;
+  NSFastLED::CRGBPalette16 currentPalette; // current color palette
+  unsigned long tPatternStart;  // time last pattern changed
+  unsigned long tPaletteStart;  // time last palette changed
+};
+
+DeckSettings deckSettingsA;
+DeckSettings deckSettingsB;
+DeckSettings* deckSettingsAll[] = {&deckSettingsA, &deckSettingsB};
+
+typedef void (*FP)(NSFastLED::CRGB*, DeckSettings*);
+
+// Use qsuba for smooth pixel colouring and qsubd for non-smooth pixel colouring
+#define qsubd(x, b)  ((x>b)?b:0)
+#define qsuba(x, b)  ((x>b)?x-b:0)
+#define NUM_PATTERNS sizeof(patternBank) / sizeof(FP)
+#define RGB_COLOR_CONTROL false // should we control the center LED or not?
+#define NUM_LEDS 24
 #define PIXEL_PIN 6
 #define PIXEL_TYPE NSFastLED::NEOPIXEL
 #define HUE_STEP 2 // 1..255, each loop increments hue by this value
-#define LOOP_DELAY_MS 50 //ms
+#define UPDATES_PER_SECOND 40
 /* set this to match the number of patterns you flip
 between when holding the setup button */
 #define N_PATTERNS 3
 #define SETUP_BUTTON_HOLD_DURATION_MS 800
+#define MAX_BRIGHTNESS 255
+
+#define BOOTUP_ANIM_DURATION_MS 6000
+#define PATTERN_CHANGE_INTERVAL_MS 30000
+#define PALETTE_CHANGE_INTERVAL_MS 30000
+#define VJ_CROSSFADING_ENABLED 1
+#define VJ_CROSSFADE_DURATION_MS 6000
+#define VJ_NUM_DECKS 2
+// switch between deck a and b with this interval
+#define VJ_DECK_SWITCH_INTERVAL_MS 15000
+#define AUTO_CHANGE_PALETTE 1
+bool AUTO_PATTERN_CHANGE = true;
+unsigned long t_now;                // time now in each loop iteration
+unsigned long t_boot;               // time at bootup
+
+/* state for controlling user-mode button for pattern changes */
+uint8_t button_state = 0;
+unsigned long button_timer = 0;

 // PORNJ!!!! These values are selected to look decent on RBG LEDs
 #define DISORIENT_PINK_R 252
@@ -27,203 +67,586 @@
 #define CRGB_DIS_PINK NSFastLED::CRGB(DISORIENT_PINK_R, DISORIENT_PINK_G, DISORIENT_PINK_B)
 #define CRGB_DIS_ORAN NSFastLED::CRGB(DISORIENT_ORANGE_R, DISORIENT_ORANGE_G, DISORIENT_ORANGE_B)

-NSFastLED::CRGB leds[PIXEL_COUNT];
 uint8_t base_hue = 0;
-uint8_t pattern = 0;
-unsigned long gBrightness = 10;
+//unsigned long GLOBAL_BRIGHTNESS = 10;
+unsigned long GLOBAL_BRIGHTNESS = 10;
 // this is ghetto debouncing, and will ignore input to the pattern button
 // for X cycles of LOOP_DELAY_MS once triggered
 uint8_t ignore_button_cycles = 0;

 NSFastLED::CFastLED* gLED; // global CFastLED object

-// for palette support
-uint8_t gAnimIndex = 0;
-uint8_t gPalette = 0;
-NSFastLED::CRGBPalette16 currentPalette = NSFastLED::RainbowColors_p;
+
+/* custom color palettes */
+// orange 255,102,0 FF6600
+// pink 255,0,255 #ff00ff
+// pornj 255,51,51 #ff3333
+extern const NSFastLED::TProgmemRGBGradientPalette_byte Disorient_gp[] = {
+      0,   0,   0,   0,    // black
+     75, 255,  26, 153,    // pink
+    147, 255,  51,  51,    // pornj
+    208, 255, 111,  15,    // orange
+    255, 255, 255, 255, }; // white
+extern const NSFastLED::TProgmemRGBGradientPalette_byte es_pinksplash_08_gp[] = {
+    0, 126, 11,255,
+  127, 197,  1, 22,
+  175, 210,157,172,
+  221, 157,  3,112,
+  255, 157,  3,112};
+extern const NSFastLED::TProgmemRGBGradientPalette_byte es_pinksplash_07_gp[] = {
+    0, 229,  1,  1,
+   61, 242,  4, 63,
+  101, 255, 12,255,
+  127, 249, 81,252,
+  153, 255, 11,235,
+  193, 244,  5, 68,
+  255, 232,  1,  5};
+extern const NSFastLED::TProgmemRGBGradientPalette_byte Sunset_Real_gp[] {
+    0, 120,  0,  0,
+   22, 179, 22,  0,
+   51, 255,104,  0,
+   85, 167, 22, 18,
+  135, 100,  0,103,
+  198,  16,  0,130,
+  255,   0,  0,160};
+extern const NSFastLED::TProgmemRGBGradientPalette_byte rgi_15_gp[] {
+    0,   4,  1, 31,
+   31,  55,  1, 16,
+   63, 197,  3,  7,
+   95,  59,  2, 17,
+  127,   6,  2, 34,
+  159,  39,  6, 33,
+  191, 112, 13, 32,
+  223,  56,  9, 35,
+  255,  22,  6, 38};
+extern const NSFastLED::TProgmemRGBGradientPalette_byte BlacK_Red_Magenta_Yellow_gp[] {
+    0,   0,  0,  0,
+   42,  42,  0,  0,
+   84, 255,  0,  0,
+  127, 255,  0, 45,
+  170, 255,  0,255,
+  212, 255, 55, 45,
+  255, 255,255,  0};
+
+// for effects that are palette based
+NSFastLED::CRGBPalette16 palettes[] = {
+  Disorient_gp,
+  NSFastLED::CloudColors_p,
+  es_pinksplash_08_gp,
+  BlacK_Red_Magenta_Yellow_gp,
+  es_pinksplash_07_gp,
+  Sunset_Real_gp,
+  rgi_15_gp,
+  NSFastLED::ForestColors_p,
+  NSFastLED::OceanColors_p,
+  NSFastLED::LavaColors_p,
+};
+#define PALETTES_COUNT (sizeof(palettes)/sizeof(*palettes))
+
 NSFastLED::TBlendType currentBlending = NSFastLED::LINEARBLEND;
+NSFastLED::CRGB masterOutput[NUM_LEDS];
+NSFastLED::CRGB deckA[NUM_LEDS];
+NSFastLED::CRGB deckB[NUM_LEDS];
+float crossfadePosition = 1.0;  // 0.0 is deckA, 1.0 is deckB
+int crossfadeDirection = (crossfadePosition == 1.0) ? -1 : 1; // start going B -> A
+uint8_t crossfadeInProgress = 0;
+unsigned long tLastCrossfade = 0;

 // make sure we disable wifi cause we dont need that shit!
 SYSTEM_MODE(SEMI_AUTOMATIC);
+
+
+/*vars for pattern_phase_shift_palette*/
+int wave1=0;
+void pattern_phase_shift_palette(NSFastLED::CRGB* leds, DeckSettings* s) {
+  // phase shift
+  wave1 += 8;
+  int phase2 = NSFastLED::beatsin8(7,-64,64);
+
+  for (int k=0; k<NUM_LEDS; k++) {
+    int phase1 = NSFastLED::sin8(3*k + wave1/128);
+    int colorIndex = NSFastLED::cubicwave8((k)+phase1)/2 + NSFastLED::cos8((k*3)+phase2)/2;
+
+    //int bri8 = NSFastLED::cubicwave8(t_now/10.0 + k*10.0); // nice pulsy one direction intensity modulator
+    // generate undulating intensity phases
+    int bri8 = NSFastLED::cubicwave8(t_now/10.0 + NSFastLED::cubicwave8(k*10.0));
+
+    //Serial.printlnf("%d %d", k, bri8);
+    leds[k] = ColorFromPalette(s->currentPalette, colorIndex, bri8, currentBlending);
+  }
+}
+
+void pattern_from_palette(NSFastLED::CRGB* leds, DeckSettings* s) {
+  uint8_t b = NSFastLED::beatsin8(4, 0, 255);
+  for( int i = 0; i < NUM_LEDS; i++) {
+    leds[i] = NSFastLED::ColorFromPalette(s->currentPalette, s->animationIndex + i + b, MAX_BRIGHTNESS, currentBlending);
+  }
+  // slow down progression by 1/3
+  if (t_now%3 == 0) {
+    s->animationIndex = NSFastLED::addmod8(s->animationIndex, 1, 255);
+  }
+}
+
+void pattern_slow_pulse_with_sparkles(NSFastLED::CRGB* leds, DeckSettings* s) {
+  // pick a color, and pulse it
+  uint8_t cBrightness = NSFastLED::beatsin8(20, 140, 255);
+  uint8_t cHue = NSFastLED::beatsin8(4, 0, 255);
+  NSFastLED::CHSV hsv_led = NSFastLED::CHSV(cHue, 255, cBrightness);
+  NSFastLED::CRGB rgb_led;
+  hsv2rgb_rainbow(hsv_led, rgb_led);
+  for( int i = 0; i < NUM_LEDS; i++) {
+    if (random(NUM_LEDS*3) == 0) {
+      leds[i] = NSFastLED::CRGB::White;
+    } else {
+      leds[i] = rgb_led;
+    }
+  }
+}
+
+// cycle a rainbow, varying how quickly it rolls around the board
+void pattern_rainbow_waves_with_sparkles(NSFastLED::CRGB* leds, DeckSettings* s) {
+  for(int i = 0; i < NUM_LEDS; ++i) {
+    if (random(NUM_LEDS*3) == 0) {
+      leds[i] = NSFastLED::CRGB::White;
+    } else {
+      uint8_t h = (t_now/12+i)%256;
+      NSFastLED::CHSV hsv_led = NSFastLED::CHSV(h, 255, 255);
+      NSFastLED::CRGB rgb_led;
+      hsv2rgb_rainbow(hsv_led, rgb_led);
+      leds[i] = rgb_led;
+    }
+  }
+}
+
+// NOTE: lifted and tweaked from https://learn.adafruit.com/rainbow-chakra-led-hoodie/the-code
+// This function draws color waves with an ever-changing,
+// widely-varying set of parameters, using a color palette.
+void pattern_palette_waves(NSFastLED::CRGB* leds, DeckSettings* s) {
+  uint8_t numleds = NUM_LEDS;
+  static uint16_t sPseudotime = 0;
+  static uint16_t sLastMillis = 0;
+  static uint16_t sHue16 = 0;
+
+  //uint8_t sat8 = NSFastLED::beatsin88( 87, 220, 250);
+  uint8_t brightdepth = NSFastLED::beatsin88( 341, 96, 224);
+  uint16_t brightnessthetainc16 = NSFastLED::beatsin88( 203, (25 * 256), (40 * 256));
+  uint8_t msmultiplier = NSFastLED::beatsin88(147, 23, 60);
+
+  uint16_t hue16 = sHue16;//gHue * 256;
+  uint16_t hueinc16 = NSFastLED::beatsin88(113, 300, 1500);
+
+  uint16_t ms = millis();
+  uint16_t deltams = ms - sLastMillis ;
+  sLastMillis  = ms;
+  sPseudotime += deltams * msmultiplier;
+  sHue16 += deltams * NSFastLED::beatsin88( 400, 5,9);
+  uint16_t brightnesstheta16 = sPseudotime;
+
+  for( uint16_t i = 0 ; i < numleds; i++) {
+    hue16 += hueinc16;
+    uint8_t hue8 = hue16 / 256;
+    uint16_t h16_128 = hue16 >> 7;
+    if( h16_128 & 0x100) {
+      hue8 = 255 - (h16_128 >> 1);
+    } else {
+      hue8 = h16_128 >> 1;
+    }
+
+    brightnesstheta16  += brightnessthetainc16;
+    uint16_t b16 = NSFastLED::sin16( brightnesstheta16  ) + 32768;
+
+    uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
+    uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
+    bri8 += (255 - brightdepth);
+
+    uint8_t index = hue8;
+    index = NSFastLED::scale8( index, 240);
+
+    NSFastLED::CRGB newcolor = NSFastLED::ColorFromPalette(s->currentPalette, index, bri8);
+
+    uint16_t pixelnumber = i;
+    pixelnumber = (numleds-1) - pixelnumber;
+
+    nblend(leds[pixelnumber], newcolor, 128);
+  }
+}
+
+void  pattern_plasma(NSFastLED::CRGB* leds, DeckSettings* s) {
+
+  int thisPhase = NSFastLED::beatsin8(6,-64,64);
+  int thatPhase = NSFastLED::beatsin8(7,-64,64);
+
+  for (int k=0; k<NUM_LEDS; k++) {
+
+    int colorIndex = NSFastLED::cubicwave8((k*23)+thisPhase)/2 + NSFastLED::cos8((k*15)+thatPhase)/2;
+    int thisBright = NSFastLED::cubicwave8(t_now/10.0 + k*10.0); // nice pulsy one direction intensity modulator
+    //int thisBright = qsuba(colorIndex, NSFastLED::beatsin8(7,0,96));
+
+    leds[k] = ColorFromPalette(s->currentPalette, colorIndex, thisBright, currentBlending);
+  }
+}
+
+// pattern 0
+void pattern_disorient_0(NSFastLED::CRGB* leds, DeckSettings* s){
+  long t = t_now*0.01;
+  uint8_t offset = t % NUM_LEDS;
+  uint8_t new_i = 0;
+  for (int i = 0 ; i < NUM_LEDS ; ++i){
+    new_i = (i + offset) % NUM_LEDS;
+    if (random(NUM_LEDS*2) == 0) {
+      leds[new_i] = NSFastLED::CRGB::White;
+    } else {
+      if (i >= NUM_LEDS/2) {
+        leds[new_i] = CRGB_DIS_PINK;
+      } else {
+        leds[new_i] = CRGB_DIS_ORAN;
+      }
+    }
+  }
+}
+
+// random disorient sparkles
+void pattern_disorient_sparkles(NSFastLED::CRGB* leds, DeckSettings* s){
+  for (int i = 0 ; i < NUM_LEDS ; ++i){
+    if (random(NUM_LEDS*3) == 0) {
+      // pixel is sparkly
+      leds[i] = NSFastLED::CRGB::White;
+    } else {
+      if (random(2) == 0) {
+        leds[i] = CRGB_DIS_PINK;
+      } else {
+        leds[i] = CRGB_DIS_ORAN;
+      }
+    }
+  }
+}
+
+
+// pattern 2
+void pattern_hsv_offset_circle_loop(NSFastLED::CRGB* leds, DeckSettings* s){
+  uint8_t offset = 0;
+  NSFastLED::CRGB rgb;
+  NSFastLED::CHSV hsv;
+  for (int i = 0 ; i < NUM_LEDS ; ++i){
+    offset = ((float)i/(NUM_LEDS-1))*255;
+    hsv = NSFastLED::CHSV(base_hue+offset, 255, 255);
+    NSFastLED::hsv2rgb_rainbow(hsv, rgb);
+    leds[i] = rgb;
+  }
+
+  // set the center pixel to mirror what pixel 0 is
+  hsv = NSFastLED::CHSV(base_hue+offset, 255, 255);
+  hsv2rgb_rainbow(hsv, rgb);
+  if (RGB_COLOR_CONTROL) {
+    RGB.color(rgb.r, rgb.g, rgb.b);
+  }
+
+  base_hue += HUE_STEP;
+}
+
+// cycle thru color palettes
+void pattern_color_palettes(NSFastLED::CRGB* leds, DeckSettings* s) {
+  for( int i = 0; i < NUM_LEDS; ++i) {
+    uint8_t pIndex = (i + 6*i*NUM_LEDS/NUM_LEDS + s->animationIndex)%256;
+    leds[i] = NSFastLED::ColorFromPalette(s->currentPalette, pIndex, 255, currentBlending);
+  }
+  s->animationIndex = (s->animationIndex+3)%256;
+}
+
+void pattern_color_palettes_with_sparkle(NSFastLED::CRGB* leds, DeckSettings* s) {
+  for( int i = 0; i < NUM_LEDS; ++i) {
+    if (random(NUM_LEDS*2) == 0) {
+      leds[i] = NSFastLED::CRGB::White;
+    } else {
+      uint8_t pIndex = (i + 6*i*NUM_LEDS/NUM_LEDS + s->animationIndex)%256;
+      leds[i] = NSFastLED::ColorFromPalette(s->currentPalette, pIndex, 255, currentBlending);
+    }
+  }
+  s->animationIndex = (s->animationIndex+3)%256;
+}
+
+
+// rainbow pulsing with varied breathing cycles
+void pattern_phase_rainbow_pulse(NSFastLED::CRGB* leds, DeckSettings* s) {
+  uint8_t cBrightness = NSFastLED::beatsin8(128, 0, 255);
+  NSFastLED::CHSV hsv = NSFastLED::CHSV(base_hue, 255, cBrightness);
+  NSFastLED::CRGB rgb;
+  NSFastLED::hsv2rgb_rainbow(hsv, rgb);
+  for (int i = 0 ; i < NUM_LEDS ; ++i){
+    leds[i] = rgb;
+  }
+  // set the center pixel to mirror what pixel 0 is
+  if (RGB_COLOR_CONTROL) {
+    RGB.color(rgb.r, rgb.g, rgb.b);
+  }
+  base_hue += 2;
+}
+
+// pattern 3
+void pattern_hsv_circle_loop(NSFastLED::CRGB* leds, DeckSettings* s){
+  NSFastLED::CHSV hsv = NSFastLED::CHSV(base_hue, 255, 255);
+  NSFastLED::CRGB rgb;
+  NSFastLED::hsv2rgb_rainbow(hsv, rgb);
+  for (int i = 0 ; i < NUM_LEDS ; ++i){
+    leds[i] = rgb;
+  }
+  // set the center pixel to mirror what pixel 0 is
+  if (RGB_COLOR_CONTROL) {
+    RGB.color(rgb.r, rgb.g, rgb.b);
+  }
+  base_hue += HUE_STEP;
+}
+
+// pattern 4
+void pattern_disorient_2(NSFastLED::CRGB* leds, DeckSettings* s){
+  // same as pattern 0, but in quadrants
+  uint8_t offset_0, offset_1, offset_2, offset_3;
+  offset_0 = 0;
+  offset_1 = NUM_LEDS/4;
+  offset_2 = NUM_LEDS/2;
+  offset_3 = offset_1+offset_2;
+  long t = t_now*0.25;
+  uint8_t offset = t % NUM_LEDS;
+  uint8_t new_i = 0;
+  for (int i = 0 ; i < NUM_LEDS ; ++i){
+    new_i = (i + offset) % NUM_LEDS;
+    if ((i >= offset_0 && i < offset_1) || (i >= offset_2 && i < offset_3)) {
+      leds[new_i] = NSFastLED::CRGB(DISORIENT_PINK_R, DISORIENT_PINK_G, DISORIENT_PINK_B);
+    } else {
+      leds[new_i] = NSFastLED::CRGB(DISORIENT_ORANGE_R, DISORIENT_ORANGE_G, DISORIENT_ORANGE_B);
+    }
+    if (random(100) <= 5) {
+      // random sparkles
+      leds[new_i] = NSFastLED::CRGB::White;
+    }
+  }
+}
+
+void pattern_disorient_palette_sparkles(NSFastLED::CRGB* leds, DeckSettings* s) {
+  uint8_t b = NSFastLED::beatsin8(4, 0, 255);
+  for( int i = 0; i < NUM_LEDS; i++) {
+    if (random(NUM_LEDS*4) == 0) {
+      leds[i] = NSFastLED::CRGB::White;
+    } else {
+      leds[i] = ColorFromPalette((NSFastLED::CRGBPalette16)Disorient_gp, s->animationIndex + i + b, MAX_BRIGHTNESS, currentBlending);
+    }
+  }
+  // slow down progression by 1/3
+  if (t_now%3 == 0) {
+    s->animationIndex = NSFastLED::addmod8(s->animationIndex, 1, 255);
+  }
+}
+
+
+/** update this with patterns you want to be cycled through **/
+const FP patternBank[] = {
+  &pattern_phase_shift_palette,
+  &pattern_plasma,
+  &pattern_from_palette,
+  &pattern_disorient_palette_sparkles,
+  &pattern_slow_pulse_with_sparkles,
+  &pattern_palette_waves,
+  &pattern_rainbow_waves_with_sparkles,
+};
+
+void randomPattern(DeckSettings* deck, DeckSettings* otherDeck) {
+  uint8_t old = deck->pattern;
+  while (deck->pattern == old || deck->pattern == otherDeck->pattern) {
+    deck->pattern = NSFastLED::random8(0, NUM_PATTERNS);
+  }
+  deck->tPatternStart = t_now;
+}
+
+void randomPalette(DeckSettings* deck, DeckSettings* otherDeck) {
+  uint8_t old = deck->palette;
+  while (deck->palette == old || deck->palette == otherDeck->palette) {
+    deck->palette = NSFastLED::random8(0, PALETTES_COUNT);
+  }
+  deck->currentPalette = palettes[deck->palette];
+  deck->tPaletteStart = t_now;
+}
+

 // setup() runs once, when the device is first turned on.
 void setup() {
   Serial.println("Booting up");
   randomSeed(analogRead(0));
+
+  t_now = millis();
+  t_boot = t_now;
+  tLastCrossfade = t_now;
+
+  deckSettingsA = {
+    1,
+    0.0,
+    0,
+    0,
+    0,
+    palettes[0],
+    t_now,
+    t_now,
+  };
+  deckSettingsB = {
+    2,
+    1.0,
+    0,
+    0,
+    0,
+    palettes[0],
+    t_now,
+    t_now,
+  };
+
+  randomPattern(&deckSettingsA, &deckSettingsB);
+  randomPalette(&deckSettingsA, &deckSettingsB);
+  randomPattern(&deckSettingsB, &deckSettingsA);
+  randomPalette(&deckSettingsB, &deckSettingsA);
+
   gLED = new NSFastLED::CFastLED();
-  gLED->addLeds<PIXEL_TYPE, PIXEL_PIN>(leds, PIXEL_COUNT);
-  gLED->setBrightness(gBrightness);
+  gLED->addLeds<PIXEL_TYPE, PIXEL_PIN>(masterOutput, NUM_LEDS);
+  gLED->setBrightness(GLOBAL_BRIGHTNESS);

   RGB.control(true); // take over the LED
-  RGB.color(DISORIENT_PINK_R, DISORIENT_PINK_G, DISORIENT_PINK_B);
+  if (RGB_COLOR_CONTROL) {
+    RGB.color(DISORIENT_PINK_R, DISORIENT_PINK_G, DISORIENT_PINK_B);
+  } else {
+    RGB.color(0,0,0);
+  }
   Serial.println("Finished setup");
 }

-// pattern 0
-void pattern_disorient_0(){
-  long t = millis()*0.01;
-  uint8_t offset = t % PIXEL_COUNT;
-  uint8_t new_i = 0;
-  for (int i = 0 ; i < PIXEL_COUNT ; ++i){
-    new_i = (i + offset) % PIXEL_COUNT;
-    if (random(PIXEL_COUNT*2) == 0) {
-      leds[new_i] = NSFastLED::CRGB::White;
-    } else {
-      if (i >= PIXEL_COUNT/2) {
-        leds[new_i] = CRGB_DIS_PINK;
-      } else {
-        leds[new_i] = CRGB_DIS_ORAN;
-      }
-    }
-  }
-}
-
-// random disorient sparkles
-void pattern_disorient_sparkles(){
-  for (int i = 0 ; i < PIXEL_COUNT ; ++i){
-    if (random(PIXEL_COUNT*3) == 0) {
-      // pixel is sparkly
-      leds[i] = NSFastLED::CRGB::White;
-    } else {
-      if (random(2) == 0) {
-        leds[i] = CRGB_DIS_PINK;
-      } else {
-        leds[i] = CRGB_DIS_ORAN;
-      }
-    }
-  }
-}
-
-
-// pattern 2
-void pattern_hsv_offset_circle_loop(){
-  uint8_t offset = 0;
-  NSFastLED::CRGB rgb;
-  NSFastLED::CHSV hsv;
-  for (int i = 0 ; i < PIXEL_COUNT ; ++i){
-    offset = ((float)i/(PIXEL_COUNT-1))*255;
-    hsv = NSFastLED::CHSV(base_hue+offset, 255, 255);
-    NSFastLED::hsv2rgb_rainbow(hsv, rgb);
-    //if (random(PIXEL_COUNT*2) == 0) {
-    //  leds[i] = NSFastLED::CRGB::White;
-    //} else {
-    leds[i] = rgb;
-    //}
-  }
-
-  // set the center pixel to mirror what pixel 0 is
-  hsv = NSFastLED::CHSV(base_hue+offset, 255, 255);
-  hsv2rgb_rainbow(hsv, rgb);
-  RGB.color(rgb.r, rgb.g, rgb.b);
-
-  base_hue += HUE_STEP;
-}
-
-// cycle thru color palettes
-void pattern_color_palettes() {
-  for( int i = 0; i < PIXEL_COUNT; ++i) {
-    uint8_t pIndex = (i + 6*i*PIXEL_COUNT/PIXEL_COUNT + gAnimIndex)%256;
-    leds[i] = NSFastLED::ColorFromPalette(currentPalette, pIndex, 255, currentBlending);
-  }
-  gAnimIndex = (gAnimIndex+3)%256;
-}
-
-void pattern_color_palettes_with_sparkle() {
-  for( int i = 0; i < PIXEL_COUNT; ++i) {
-    if (random(PIXEL_COUNT*2) == 0) {
-      leds[i] = NSFastLED::CRGB::White;
-    } else {
-      uint8_t pIndex = (i + 6*i*PIXEL_COUNT/PIXEL_COUNT + gAnimIndex)%256;
-      leds[i] = NSFastLED::ColorFromPalette(currentPalette, pIndex, 255, currentBlending);
-    }
-  }
-  gAnimIndex = (gAnimIndex+3)%256;
-}
-
-
-// rainbow pulsing with varied breathing cycles
-void pattern_phase_rainbow_pulse() {
-  uint8_t cBrightness = NSFastLED::beatsin8(128, 0, 255);
-  NSFastLED::CHSV hsv = NSFastLED::CHSV(base_hue, 255, cBrightness);
-  NSFastLED::CRGB rgb;
-  NSFastLED::hsv2rgb_rainbow(hsv, rgb);
-  for (int i = 0 ; i < PIXEL_COUNT ; ++i){
-    leds[i] = rgb;
-  }
-  // set the center pixel to mirror what pixel 0 is
-  RGB.color(rgb.r, rgb.g, rgb.b);
-  base_hue += 2;
-}
-
-// pattern 3
-void pattern_hsv_circle_loop(){
-  NSFastLED::CHSV hsv = NSFastLED::CHSV(base_hue, 255, 255);
-  NSFastLED::CRGB rgb;
-  NSFastLED::hsv2rgb_rainbow(hsv, rgb);
-  for (int i = 0 ; i < PIXEL_COUNT ; ++i){
-    leds[i] = rgb;
-  }
-  // set the center pixel to mirror what pixel 0 is
-  RGB.color(rgb.r, rgb.g, rgb.b);
-  base_hue += HUE_STEP;
-}
-
-// pattern 4
-void pattern_disorient_2(){
-  // same as pattern 0, but in quadrants
-  uint8_t offset_0, offset_1, offset_2, offset_3;
-  offset_0 = 0;
-  offset_1 = PIXEL_COUNT/4;
-  offset_2 = PIXEL_COUNT/2;
-  offset_3 = offset_1+offset_2;
-  long t = millis()*0.25;
-  uint8_t offset = t % PIXEL_COUNT;
-  uint8_t new_i = 0;
-  for (int i = 0 ; i < PIXEL_COUNT ; ++i){
-    new_i = (i + offset) % PIXEL_COUNT;
-    if ((i >= offset_0 && i < offset_1) || (i >= offset_2 && i < offset_3)) {
-      leds[new_i] = NSFastLED::CRGB(DISORIENT_PINK_R, DISORIENT_PINK_G, DISORIENT_PINK_B);
-    } else {
-      leds[new_i] = NSFastLED::CRGB(DISORIENT_ORANGE_R, DISORIENT_ORANGE_G, DISORIENT_ORANGE_B);
-    }
-    if (random(100) <= 5) {
-      // random sparkles
-      leds[new_i] = NSFastLED::CRGB::White;
-    }
-  }
-}
+

 // loop() runs over and over again, as quickly as it can execute.
 void loop() {
+  t_now = millis();
+
+  // handle user interaction with reset button
   if (HAL_Core_Mode_Button_Pressed(SETUP_BUTTON_HOLD_DURATION_MS)) {
-    if (ignore_button_cycles > 0) {
-      --ignore_button_cycles;
-      RGB.color(0, 255, 0); // green when ignoring press
-    } else {
-      RGB.color(255, 0, 0); // red on pattern change
-      ignore_button_cycles = 20;
-      ++pattern;
-      if (pattern >= N_PATTERNS) {
-        pattern = 0;
-      }
+    switch (button_state) {
+    case 0:
+      // we werent pressed before, so start timer!
+      button_state = 1;
+      button_timer = t_now;
+      break;
+    case 1:
+      if (t_now - button_timer > SETUP_BUTTON_HOLD_DURATION_MS) {
+        // we have been held longer than
+        button_state = 2;
+      }
+      break;
+    // we are waiting to take action now
+    case 2: break;
+    // action already taken, do nothing until release!
+    case 3: break;
+    default:
+        button_state = 0;
+      break;
     }
   } else {
-    ignore_button_cycles = 0;
-    RGB.color(DISORIENT_PINK_R, DISORIENT_PINK_G, DISORIENT_PINK_B);
-  }
-
-  if (pattern == 0){
-    pattern_disorient_0();
-  } else if (pattern == 1) {
-    pattern_hsv_offset_circle_loop();
-  } else if (pattern == 2) {
-    pattern_color_palettes_with_sparkle();
-  }
-
-  gLED->setBrightness(gBrightness);
+    button_state = 0;
+  }
+
+  if (button_state == 2) {
+    /*
+    BRIGHTNESS_INDEX++;
+    button_state = 3;
+    if (BRIGHTNESS_INDEX >= BRIGHTNESS_COUNT){
+      BRIGHTNESS_INDEX = 0;
+    }
+    Serial.printlnf("set brightness to %d/255", GLOBAL_BRIGHTNESS);
+    */
+  }
+
+
+  // increment pattern every PATTERN_CHANGE_INTERVAL_MS, but not when a deck is active!
+  if (AUTO_PATTERN_CHANGE) {
+    if (t_now > deckSettingsA.tPatternStart+PATTERN_CHANGE_INTERVAL_MS && !crossfadeInProgress) {
+      if (crossfadePosition == 1.0) {
+        randomPattern(&deckSettingsA, &deckSettingsB);
+        Serial.printlnf("deckA.pattern=%d", deckSettingsA.pattern);
+      }
+    }
+    if (t_now > deckSettingsB.tPatternStart+PATTERN_CHANGE_INTERVAL_MS && !crossfadeInProgress) {
+      if (crossfadePosition == 0.0) {
+        randomPattern(&deckSettingsB, &deckSettingsA);
+        Serial.printlnf("deckB.pattern=%d", deckSettingsB.pattern);
+      }
+    }
+  }
+
+  // increment palette every PALETTE_CHANGE_INTERVAL_MS, but not when crossfading!
+  if (AUTO_CHANGE_PALETTE && !crossfadeInProgress) {
+    for (int x = 0; x < VJ_NUM_DECKS ; x++){
+      int xOther = (x == 0) ? 1 : 0;
+      DeckSettings* deck = deckSettingsAll[x];
+      DeckSettings* otherdeck = deckSettingsAll[xOther];
+      if ((deck->crossfadePositionActive != crossfadePosition) &&
+          (deck->tPaletteStart + PALETTE_CHANGE_INTERVAL_MS < t_now)) {
+        randomPalette(deck, otherdeck);
+        Serial.printlnf("deck%d.palette=%d", deck->label, deck->palette);
+      }
+    }
+  }
+
+  // fill in patterns on both decks! we will crossfade master output later
+  // NOTE: only render to a deck if its "visible" through the crossfader
+  if ( !VJ_CROSSFADING_ENABLED || crossfadePosition < 1.0 ) {
+    patternBank[deckSettingsA.pattern](deckA, &deckSettingsA);
+  }
+  if ( VJ_CROSSFADING_ENABLED && crossfadePosition > 0 ) {
+    patternBank[deckSettingsB.pattern](deckB, &deckSettingsB);
+  }
+
+
+    // perform crossfading increment if we are mid pattern change
+  if (VJ_CROSSFADING_ENABLED) {
+    //Serial.printf("%d %d %d\n", t_now, tLastCrossfade + VJ_DECK_SWITCH_INTERVAL_MS, crossfadeInProgress);
+    if (t_now > tLastCrossfade + VJ_DECK_SWITCH_INTERVAL_MS && !crossfadeInProgress) {
+      // start switching between decks
+      Serial.printf("starting fading to %c\n", (crossfadePosition == 1.0) ? 'A' : 'B');
+      crossfadeInProgress = 1;
+      tLastCrossfade = t_now;
+    }
+    if (crossfadeInProgress) {
+      float step = (float)1.0/(VJ_CROSSFADE_DURATION_MS/1000*UPDATES_PER_SECOND);
+      // Serial.printf("fader increment %f %d\n", step, crossfadeDirection);
+      crossfadePosition = crossfadePosition + crossfadeDirection * step;
+
+      // is it time to change decks?
+      // we are cut over to deck B, break this loop
+      if (crossfadePosition > 1.0) {
+        crossfadePosition = 1.0;
+        crossfadeDirection = -1; // 1->0
+        crossfadeInProgress = 0;
+        Serial.printf("finished fading to B\n");
+      }
+      // we are cut over to deck B
+      if (crossfadePosition < 0.0) {
+        crossfadePosition = 0.0;
+        crossfadeDirection = 1;  // 0->1
+        crossfadeInProgress = 0;
+        Serial.printf("finished fading to A\n");
+      }
+    }
+  }
+
+  // perform crossfading between deckA and deckB, by filling masterOutput
+  // FIXME for now, lets just take a linear interpolation between deck a and b
+  for (int i = 0; i < NUM_LEDS; ++i) {
+    if (VJ_CROSSFADING_ENABLED) {
+      masterOutput[i] = deckA[i].lerp8(deckB[i], NSFastLED::fract8(255*crossfadePosition));
+    } else {
+      masterOutput[i] = deckA[i];
+    }
+    if (t_now < + BOOTUP_ANIM_DURATION_MS) {
+      // ramp intensity up slowly, so we fade in when turning on
+      int8_t bri8 = (uint8_t)((t_now*1.0)/BOOTUP_ANIM_DURATION_MS*255.0);
+      masterOutput[i] = masterOutput[i].fadeToBlackBy(255-bri8);
+    }
+ }
+
+  gLED->setBrightness(GLOBAL_BRIGHTNESS);
   gLED->show();
-  // TODO(gabe) this doesnt work apparently? Contraray to documentation,
-  // FastLED::delay() doesnt perform any delay...
-  //gLED->delay(LOOP_DELAY_MS);
-  delay(LOOP_DELAY_MS);
-}
+  delay(1000.0 / UPDATES_PER_SECOND);
+}


1. Added command mappings to the firmware sketch. 2. Added servo commands to the firmware sketch.

--- Firmware/Source/v1.2/grove_pi_v1_2_5/grove_pi_v1_2_5.ino
+++ Firmware/Source/v1.2/grove_pi_v1_2_5/grove_pi_v1_2_5.ino
@@ -8,6 +8,7 @@
 //#include "IRSendRev.h"
 //#include "Encoder.h"
 //#include "TimerOne.h"
+#include <Servo.h>

 MMA7660 acc;
 DS1307 ds_clock;
@@ -16,19 +17,74 @@
 TM1637 fourdigit[6];      // 7 instances for D2-D8, however, max 4 displays, you can't use adjacent sockets, 4 pin display
 ChainableLED rgbled[6];   // 7 instances for D2-D8

-#define SLAVE_ADDRESS 0x03
-
-#define dust_sensor_read_cmd    10
-#define dust_sensor_en_cmd		14
-#define dust_sensor_dis_cmd		15
-
-#define encoder_read_cmd        11
-#define encoder_en_cmd			16
-#define encoder_dis_cmd			17
-
-#define flow_read_cmd           12
-#define flow_en_cmd				18
-#define flow_dis_cmd       		13
+#define SLAVE_ADDRESS 0x04
+
+//Command Values
+#define CMD_DIGITAL_READ         1
+#define CMD_DIGITAL_WRITE        2
+#define CMD_ANALOG_READ          3
+#define CMD_ANALOG_WRITE         4
+#define CMD_PIN_MODE             5
+
+#define CMD_ULTRASONIC_READ      7
+#define CMD_FIRMWARE_VERSION     8
+
+#define CMD_DUST_SENSOR_READ     10
+#define CMD_ENCODER_READ         11
+#define CMD_FLOW_READ            12
+#define CMD_FLOW_DIS             13
+#define CMD_DUST_SENSOR_EN       14
+#define CMD_DUST_SENSOR_DIS      15
+#define CMD_ENCODER_EN           16
+#define CMD_ENCODER_DIS          17
+#define CMD_FLOW_EN              18
+
+#define CMD_ACCEl_XYZ_READ       20
+#define CMD_IR_RECV              21
+#define CMD_IR_RECV_PIN_SET      22
+
+#define CMD_RTC_TIME_READ        30
+
+#define CMD_SERVO_ATTACH         35
+#define CMD_SERVO_DETACH         35
+#define CMD_SERVO_WRITE          36
+#define CMD_SERVO_READ           37
+
+#define CMD_TEMP_HUMIDITY_READ   40
+
+#define CMD_LED_BAR_INIT         50
+#define CMD_LED_BAR_SET_GTOR     51
+#define CMD_LED_BAR_SET_LEVEL    52
+#define CMD_LED_BAR_SET_LED      53
+#define CMD_LED_BAR_TOGGLE_LED   54
+#define CMD_LED_BAR_SET_STATE    55
+#define CMD_LED_BAR_RET_STATE    56
+
+#define CMD_4D_INIT              70
+#define CMD_4D_SET_BRIGHT        71
+#define CMD_4D_VAL_W_ZERO        72
+#define CMD_4D_VAL_WO_ZERO       73
+#define CMD_4D_SET_DIGIT         74
+#define CMD_4D_SET_SEGMENT       75
+#define CMD_4D_SET_COLON         76
+#define CMD_4D_ANALOG_READ       77
+#define CMD_4D_DISPLAY_ON        78
+#define CMD_4D_DISPLAY_OFF       79
+
+#define CMD_CLED_STORE_COLOR     90
+#define CMD_CLED_INIT_CHAIN      91
+#define CMD_CLED_INIT_SET_TEST   92
+#define CMD_CLED_SET_PATTERN     93
+#define CMD_CLED_SET_MODULO      94
+#define CMD_CLED_SET_lEVEL       95
+
+//Servo pin numbers start at 2, but array starts at 0
+#define SERVO_PIN_OFFSET 2
+
+//Array of pointers to servos
+//used for attaching with and controlling servos.
+Servo *servos[11];
+int servoRead = 0;

 int cmd[5];
 int idx=0;
@@ -65,6 +121,7 @@
 long flow_read_start;
 byte flow_val[3];        //Given it's own I2C buffer so that it does not corrupt the data from other sensors when running in background

+
 void setup()
 {
     Serial.begin(57600);         // start serial for output
@@ -86,12 +143,12 @@
   {
     flag=1;
     //IR reciever pin set command
-    if(cmd[0]==22)
+    if(cmd[0]==CMD_IR_RECV_PIN_SET)
     {
        //IR.Init(cmd[1]);
     }
     //Grove IR recieve command
-    else if(cmd[0]==21)
+    else if(cmd[0]==CMD_IR_RECV)
     {/*
         if(IR.IsDta())
         {
@@ -104,7 +161,7 @@
     }

     //Digital Read
-    else if(cmd[0]==1)
+    else if(cmd[0]==CMD_DIGITAL_READ)
     {
       val=digitalRead(cmd[1]);

@@ -114,11 +171,11 @@
       //Serial.println(val);
     }
     //Digital Write
-    else if(cmd[0]==2)
+    else if(cmd[0]==CMD_DIGITAL_WRITE)
       digitalWrite(cmd[1],cmd[2]);

     //Analog Read
-    else if(cmd[0]==3)
+    else if(cmd[0]==CMD_ANALOG_READ)
     {
       aRead=analogRead(cmd[1]);
       b[1]=aRead/256;
@@ -131,21 +188,18 @@
     }

     //Set up Analog Write
-    else if(cmd[0]==4)
-    {
-      if(run_once)
-      {
-        analogWrite(cmd[1],cmd[2]);
-
-        //Serial.print("Analog Write. Pin: ");
-        //Serial.print(cmd[1]);
-        //Serial.print(", Value: ");
-        //Serial.println(cmd[2]);
-        run_once = false;
-      }
+    else if(cmd[0]==CMD_ANALOG_WRITE && run_once)
+    {
+      analogWrite(cmd[1],cmd[2]);
+
+      //Serial.print("Analog Write. Pin: ");
+      //Serial.print(cmd[1]);
+      //Serial.print(", Value: ");
+      //Serial.println(cmd[2]);
+      run_once = false;
     }
     //Set up pinMode
-    else if(cmd[0]==5)
+    else if(cmd[0]==CMD_PIN_MODE)
     {
       pinMode(cmd[1],cmd[2]);

@@ -155,7 +209,7 @@
       //Serial.println(cmd[2]);
     }
     //Ultrasonic Read
-    else if(cmd[0]==7)
+    else if(cmd[0]==CMD_ULTRASONIC_READ)
     {
       pin=cmd[1];
       pinMode(pin, OUTPUT);
@@ -173,14 +227,14 @@
       //Serial.println(b[2]);
     }
     //Firmware version
-    else if(cmd[0]==8)
+    else if(cmd[0]==CMD_FIRMWARE_VERSION)
     {
       b[1] = 1;
       b[2] = 2;
       b[3] = 5;
     }
     //Accelerometer x,y,z, read
-    else if(cmd[0]==20)
+    else if(cmd[0]==CMD_ACCEl_XYZ_READ)
     {
       if(accFlag==0)
       {
@@ -193,7 +247,7 @@
       b[3]=accv[2];
     }
     //RTC tine read
-    else if(cmd[0]==30)
+    else if(cmd[0]==CMD_RTC_TIME_READ)
     {
       if(clkFlag==0)
       {
@@ -215,9 +269,82 @@
       b[7]=ds_clock.dayOfMonth;
       b[8]=ds_clock.dayOfWeek;
     }
+    else if(cmd[0]==CMD_SERVO_ATTACH && run_once)
+    {
+      //Servo pins on Due are offset by 2
+      int pin = cmd[1];
+      int pin_idx = pin-SERVO_PIN_OFFSET;
+
+      Serial.print("Servo Attach. Pin: ");
+      Serial.println(pin);
+
+      if(servos[pin_idx] == nullptr) {
+        servos[pin_idx] = new Servo;
+      }
+
+      servos[pin_idx]->attach(pin);
+      run_once = false;
+    }
+    else if(cmd[0]==CMD_SERVO_DETACH && run_once)
+    {
+      //Servo pins on Due are offset by 2
+      int pin = cmd[1];
+      int pin_idx = pin-SERVO_PIN_OFFSET;
+
+      Serial.print("Servo Detach. Pin: ");
+      Serial.println(pin);
+
+      if(servos[pin_idx] != nullptr) {
+        servos[pin_idx]->detach();
+
+        //delete the servo
+        delete servos[pin_idx];
+        servos[pin_idx] = nullptr;
+      }
+
+      run_once = false;
+    }
+    else if(cmd[0]==CMD_SERVO_WRITE && run_once)
+    {
+      //Servo pins on Due are offset by 2
+      int pin = cmd[1];
+      int pin_idx = pin-SERVO_PIN_OFFSET;
+      int angle = (b[1] << 8) +b[2];
+
+      Serial.print("Servo Write. Pin: ");
+      Serial.print(pin);
+      Serial.print(", Angle: ");
+      Serial.println(angle);
+
+      if(servos[pin_idx] != nullptr) {
+        servos[pin_idx]->write(angle);
+      }
+
+      run_once = false;
+    }
+    else if(cmd[0]==CMD_SERVO_READ && run_once)
+    {
+      //Servo pins on Due are offset by 2
+      int pin = cmd[1];
+      int pin_idx = pin-SERVO_PIN_OFFSET;
+
+      Serial.print("Servo Read. Pin: ");
+      Serial.print(pin);
+
+      if(servos[pin_idx] != nullptr) {
+        servoRead = servos[pin_idx]->read();
+        b[1]=servoRead/256;
+        b[2]=servoRead%256;
+      }
+
+      Serial.print(", Angle: ");
+      Serial.println(servoRead);
+
+      run_once = false;
+    }
     //Grove temp and humidity sensor pro
     //40- Temperature
-    else if(cmd[0]==40)
+    else if(cmd[0]==CMD_TEMP_HUMIDITY_READ)
     {
 		if(run_once)
 		{
@@ -258,7 +385,7 @@

     // Initialise
     // [50, pin, orientation, unused]
-    else if(cmd[0] == 50)
+    else if(cmd[0] == CMD_LED_BAR_INIT)
     {
       // clock pin is always next to the data pin
       ledbar[cmd[1]-2].begin(cmd[1]+1, cmd[1], cmd[2]); // clock, data, orientation
@@ -267,7 +394,7 @@
     // Change the orientation
     // Green to red, or red to green
     // [51, pin, greenToRed, unused]
-    else if(cmd[0] == 51 && ledbar[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_LED_BAR_SET_GTOR && ledbar[cmd[1]-2].ready())
     {
       ledbar[cmd[1]-2].setGreenToRed(cmd[2]);
     }
@@ -276,7 +403,7 @@
     // Level 0 means all leds off
     // Level 10 means all leds on
     // [52, pin, level, unused]
-    else if(cmd[0] == 52 && ledbar[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_LED_BAR_SET_LEVEL && ledbar[cmd[1]-2].ready())
     {
       ledbar[cmd[1]-2].setLevel(cmd[2]);
     }
@@ -285,7 +412,7 @@
     // led (1-10)
     // state (0=off, 1=on)
     // [53, pin, led, state]
-    else if(cmd[0] == 53 && ledbar[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_LED_BAR_SET_LED && ledbar[cmd[1]-2].ready())
     {
       ledbar[cmd[1]-2].setLed(cmd[2], cmd[3]);
     }
@@ -293,7 +420,7 @@
     // Toggle a single led
     // led (1-10)
     // [54, pin, led, unused]
-    else if(cmd[0] == 54 && ledbar[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_LED_BAR_TOGGLE_LED && ledbar[cmd[1]-2].ready())
     {
       ledbar[cmd[1]-2].toggleLed(cmd[2]);
     }
@@ -306,14 +433,14 @@
     //                       |        |
     //                       10       1
     // [55, pin, bits 1-8, bits 9-10]
-    else if(cmd[0] == 55 && ledbar[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_LED_BAR_SET_STATE && ledbar[cmd[1]-2].ready())
     {
       ledbar[cmd[1]-2].setBits(cmd[2] ^ (cmd[3] << 8));
     }

     // Return the current state
     // [56, pin, unused, unused]
-    else if(cmd[0] == 56 && ledbar[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_LED_BAR_RET_STATE && ledbar[cmd[1]-2].ready())
     {
       unsigned int state = ledbar[cmd[1]-2].getBits();
       b[1] = state & 0xFF;
@@ -340,7 +467,7 @@

     // initialise a 4 digit display
     // [70, pin, unused, unused]
-    else if(cmd[0] == 70)
+    else if(cmd[0] == CMD_4D_INIT)
     {
       // clock pin is always next to the data pin
       fourdigit[cmd[1]-2].begin(cmd[1], cmd[1]+1);  // clock, data
@@ -348,28 +475,28 @@

     // set brightness
     // [71, pin, brightness, unused]
-    else if(cmd[0] == 71 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_SET_BRIGHT && fourdigit[cmd[1]-2].ready())
     {
       fourdigit[cmd[1]-2].setBrightness(cmd[2]);  // setBrightness(brightness)
     }

     // show right aligned decimal value without leading zeros
     // [72, pin, bits 1-8, bits 9-16]
-    else if(cmd[0] == 72 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_VAL_W_ZERO && fourdigit[cmd[1]-2].ready())
     {
       fourdigit[cmd[1]-2].showNumberDec(cmd[2] ^ (cmd[3] << 8), false);  // showNumberDec(number, leading_zero)
     }

     // show right aligned decimal value with leading zeros
     // [73, pin, bits 1-8, bits 9-16]
-    else if(cmd[0] == 73 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_VAL_WO_ZERO && fourdigit[cmd[1]-2].ready())
     {
       fourdigit[cmd[1]-2].showNumberDec(cmd[2] ^ (cmd[3] << 8), true);  // showNumberDec(number, leading_zero)
     }

     // set individual digit
     // [74, pin, index, dec]
-    else if(cmd[0] == 74 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_SET_DIGIT && fourdigit[cmd[1]-2].ready())
     {
       uint8_t data[] = {};
       data[0] = fourdigit[cmd[1]-2].encodeDigit(cmd[3]);  // encodeDigit(number)
@@ -378,7 +505,7 @@

     // set individual segment
     // [75, pin, index, binary]
-    else if(cmd[0] == 75 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_SET_SEGMENT && fourdigit[cmd[1]-2].ready())
     {
       // 0xFF = 0b11111111 = Colon,G,F,E,D,C,B,A
       // Colon only works on 2nd segment (index 1)
@@ -394,7 +521,7 @@

     // set left and right with colon separator
     // [76, pin, left, right]
-    else if(cmd[0] == 76 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_SET_COLON && fourdigit[cmd[1]-2].ready())
     {
       uint8_t data[] = {};
       // 1st segment
@@ -413,7 +540,7 @@

     // analog read
     // [77, pin, analog pin, seconds]
-    else if(cmd[0] == 77 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_ANALOG_READ && fourdigit[cmd[1]-2].ready())
     {
       int pin = cmd[2];
       int reads = 4 * cmd[3];  // 1000/250 * cmd[3]
@@ -427,7 +554,7 @@

     // display on
     // [78, pin, unused, unused]
-    else if(cmd[0] == 78 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_DISPLAY_ON && fourdigit[cmd[1]-2].ready())
     {
       uint8_t data[] = { 0xFF, 0xFF, 0xFF, 0xFF };
       fourdigit[cmd[1]-2].setSegments(data, 4, 0);  // setSegments(segments[], length, position)
@@ -435,7 +562,7 @@

     // display off
     // [79, pin, unused, unused]
-    else if(cmd[0] == 79 && fourdigit[cmd[1]-2].ready())
+    else if(cmd[0] == CMD_4D_DISPLAY_OFF && fourdigit[cmd[1]-2].ready())
     {
       uint8_t data[] = { 0x00, 0x00, 0x00, 0x00 };
       fourdigit[cmd[1]-2].setSegments(data, 4, 0);  // setSegments(segments[], length, position)
@@ -457,7 +584,7 @@

     // Store RGB color for later use
     // [90, red, green, blue]
-    else if(cmd[0] == 90)
+    else if(cmd[0] == CMD_CLED_STORE_COLOR)
     {
       rgb[0] = cmd[1];
       rgb[1] = cmd[2];
@@ -466,7 +593,7 @@

     // Initialise a RGB LED chain
     // [91, pin, num leds, unused]
-    else if(cmd[0] == 91)
+    else if(cmd[0] == CMD_CLED_INIT_CHAIN)
     {
       rgbled[cmd[1]-2].begin(cmd[1], cmd[1]+1, cmd[2]);  // clock, data, num leds
     }
@@ -474,7 +601,7 @@
     // Test colors, repeating red green blue
     // color code: 0 black (off), 1 blue, 2 green, 3 cyan, 4 red, 5 magenta, 6 yellow, 7 white
     // [92, pin, num leds, color code]
-    else if(cmd[0] == 92)
+    else if(cmd[0] == CMD_CLED_INIT_SET_TEST)
     {
       rgbled[cmd[1]-2].begin(cmd[1], cmd[1]+1, cmd[2]);

@@ -494,7 +621,7 @@
     // pattern: 0 = this led only, 1 all leds except this led, 2 this led and all leds inwards, 3 this led and all leds outwards
     // which led: 0 = led closest to the GrovePi, 1 = second led counting outwards
     // [93, pin, pattern, which led]
-    else if(cmd[0] == 93)
+    else if(cmd[0] == CMD_CLED_SET_PATTERN)
     {
       if(cmd[2] == 0) {
         // set an individual led to the stored color
@@ -520,7 +647,7 @@
     // led offset: 0 = led closest to the GrovePi, counting outwards
     // modulo divisor: when 1 (default) sets stored color on all leds >= offset, when 2 sets every 2nd led >= offset and so on
     // [94, pin, led offset, modulo divisor]
-    else if(cmd[0] == 94)
+    else if(cmd[0] == CMD_CLED_SET_MODULO)
     {
       // modulo divisor must be >= 1
       if(cmd[3] < 1) {
@@ -542,7 +669,7 @@

     // Set level (0 to num leds), counting outwards from the GrovePi, 0 = all off, 1 = first led, reversible to count inwards
     // [95, pin, level, reverse]
-    else if(cmd[0] == 95)
+    else if(cmd[0] == CMD_CLED_SET_lEVEL)
     {
       // get the chain length
       byte num_leds = rgbled[cmd[1]-2].getNumLeds();
@@ -573,20 +700,20 @@
         }
       }
     }
-    else if(cmd[0]==dust_sensor_en_cmd)
+    else if(cmd[0]==CMD_DUST_SENSOR_EN)
 	{
 		attachInterrupt(0,readPulseDust,CHANGE);
 		dust_run_bk=1;
 		starttime=millis();
 		cmd[0]=0;
 	}
-	else if(cmd[0]==dust_sensor_dis_cmd)
+	else if(cmd[0]==CMD_DUST_SENSOR_DIS)
 	{
 		detachInterrupt(0);
 		dust_run_bk=0;
 		cmd[0]=0;
 	}
-	else if(cmd[0]==dust_sensor_read_cmd)
+	else if(cmd[0]==CMD_DUST_SENSOR_READ)
 	{
 		if(run_once==1)
 		{
@@ -598,18 +725,18 @@
 		run_once=0;
 		}
 	}
-	else if(cmd[0]==encoder_en_cmd)
+	else if(cmd[0]==CMD_ENCODER_EN)
 	{
 		//encoder.Timer_init();
 		//enc_run_bk=1;
 		//cmd[0]=0;
 	}
-	else if(cmd[0]==encoder_dis_cmd)
+	else if(cmd[0]==CMD_ENCODER_DIS)
 	{
 		//encoder.Timer_disable();
 		//enc_run_bk=0;
 	}
-	else if(cmd[0]==flow_en_cmd)
+	else if(cmd[0]==CMD_FLOW_EN)
 	{
 		pinMode(2, INPUT);
 		attachInterrupt(0, rpm, RISING);
@@ -618,7 +745,7 @@
 		flow_run_bk=1;
 		cmd[0]=0;
 	}
-	else if(cmd[0]==flow_dis_cmd)
+	else if(cmd[0]==CMD_FLOW_DIS)
     {
 		flow_run_bk=0;
         detachInterrupt(0);
@@ -695,9 +822,12 @@
 {
   //Serial.println("sendData");

-  if(cmd[0] == 1)
+  if(cmd[0] == CMD_DIGITAL_READ)
     Wire.write(val);
-  if(cmd[0] == 3 || cmd[0] == 7 || cmd[0] == 56)
+  if(cmd[0] == CMD_ANALOG_READ ||
+     cmd[0] == CMD_ULTRASONIC_READ ||
+     cmd[0] == CMD_LED_BAR_RET_STATE ||
+     cmd[0] == CMD_SERVO_READ)
   {
     Wire.write(b, 3);

@@ -708,37 +838,38 @@
     //Serial.print(", ");
     //Serial.println(b[2]);
   }
-  if(cmd[0] == 8 || cmd[0] == 20)
+  if(cmd[0] == CMD_FIRMWARE_VERSION ||
+     cmd[0] == CMD_ACCEl_XYZ_READ)
     Wire.write(b, 4);
-  if(cmd[0] == 30)
+  if(cmd[0] == CMD_RTC_TIME_READ)
     Wire.write(b, 9);
-  if(cmd[0] == 40)
+  if(cmd[0] == CMD_TEMP_HUMIDITY_READ)
     Wire.write(dht_b, 9);

-  if(cmd[0]==21)
+  if(cmd[0]==CMD_IR_RECV)
   {
-    Wire.write(b,21);
+    Wire.write(b,CMD_IR_RECV);
     b[0]=0;
   }
-  if(cmd[0]==dust_sensor_read_cmd)
+  if(cmd[0]==CMD_DUST_SENSOR_READ)
   {
     Wire.write(b,4);
 	dust_latest=0;
 	cmd[0]=0;
   }
-  if(cmd[0]==encoder_read_cmd)
+  if(cmd[0]==CMD_ENCODER_READ)
   {
     Wire.write(enc_val,2);
     enc_val[0]=0;
 	cmd[0]=0;
   }
-  if(cmd[0]==flow_read_cmd)
+  if(cmd[0]==CMD_FLOW_READ)
   {
     Wire.write(flow_val,3);
     flow_val[0]=0;
 	cmd[0]=0;
   }
-
+
 }

 //ISR for the flow sensor


COH-80: WIP

COH-80: WIP

--- Arduino/COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
+++ Arduino/COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
@@ -334,6 +334,7 @@
 #if defined(ENABLE_OTSECUREFRAME_ENCODING_SUPPORT)
 #ifdef ALLOW_CC1_SUPPORT_RELAY
 // Support for secure TX side using FHT8V ID plus 0x80 padding from relay.
+// (High bits of trailing bytes should be high for traffic from node whose ID is in header.)
 // ID is of length OTV0P2BASE::OpenTRV_Node_ID_Bytes.
 static bool getTXID(uint8_t *const id)
   {


Remove hack since it didn't work...

Remove hack since it didn't work...

--- Arduino/libraries/UA_Sensors/examples/BridgeSensorGSM/BridgeSensorGSM.ino
+++ Arduino/libraries/UA_Sensors/examples/BridgeSensorGSM/BridgeSensorGSM.ino
@@ -99,22 +99,6 @@
   }

-  // Hack to handle strange behavior where SD card receives no
-  // power.
-  if (isFirstReading)
-  {
-    // Turn on GSM MOSFET.
-    digitalWrite(MOSFET_GSM_PIN, HIGH);
-    delay(2000);
-
-    // Turn off GSM MOSFET.
-    digitalWrite(MOSFET_GSM_PIN, LOW);
-    delay(1000);
-
-    isFirstReading = false;
-  }
-
-
   // 2. Turn on thermistor.
   // ----------------------
   digitalWrite(THERM_PIN, HIGH);


Update tft_weatherstation_v5.ino

Update tft_weatherstation_v5.ino

--- tft_weatherstation/tft_weatherstation_v5/tft_weatherstation_v5.ino
+++ tft_weatherstation/tft_weatherstation_v5/tft_weatherstation_v5.ino
@@ -1,409 +1,383 @@
-#include <Adafruit_GFX.h>    // Core graphics library
-#include <Adafruit_TFTLCD.h> // Hardware-specific library
-#include "TSL2561.h"
-#include <SFE_BMP180.h>
-#include <Wire.h>
-#include "DHT.h"
-#include <MCUFRIEND_kbv.h>
-
-#define LCD_CS A3 // Chip Select goes to Analog 3
-#define LCD_CD A2 // Command/Data goes to Analog 2
-#define LCD_WR A1 // LCD Write goes to Analog 1
-#define LCD_RD A0 // LCD Read goes to Analog 0
-
-#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
-#define LDR A10
-#define DHTPIN 22
-#define DHTTYPE DHT22
-#define PIN_LED 24 //Serial Data LED
-#define SERIALWAIT 200
-#define interruptPin 19
-
-// Assign human-readable names to some common 16-bit color values:
-#define BLACK   0x0000
-#define BLUE    0x001F
-#define RED     0xF800
-#define GREEN   0x07E0
-#define CYAN    0x07FF
-#define MAGENTA 0xF81F
-#define YELLOW  0xFFE0
-#define WHITE   0xFFFF
-
-//RGB LED
-#define LEDblau 44 // Farbe blau an Pin 3
-#define LEDrot 46 // Farbe rot an Pin 5
-#define LEDgruen 45 // Farbe gruen an Pin 6
-#define delayRGB 500 // p ist eine Pause mit 1000ms also 1 Sekunde
-#define brightness1a 150 // Zahlenwert zwischen 0 und 255 – gibt die Leuchtstärke der einzelnen Farbe an
-#define brightness1b 150 // Zahlenwert zwischen 0 und 255 – gibt die Leuchtstärke der einzelnen Farbe an
-#define brightness1c 150 // Zahlenwert zwischen 0 und 255 – gibt die Leuchtstärke der einzelnen Farbe an
-#define dunkel 0 // Zahlenwert 0 bedeutet Spannung 0V – also LED aus.
-
-//cycle will be increased in the loop(), if cycle == CYCLE_UPDATE_TFT --> update TFT and reset cycle to 0
-//this will avoid updating the TFT each time when a serial data is sent (no need to update the TFT that often)
-#define CYCLE_UPDATE_TFT 6
-int cycle = CYCLE_UPDATE_TFT;
-
-#define DELAY_TIME 10000 //Delay Time between each processData() call
-TSL2561 tsl(TSL2561_ADDR_FLOAT);
-MCUFRIEND_kbv tft;
-DHT dht(DHTPIN, DHTTYPE);
-SFE_BMP180 pressure;
-volatile bool ledTestRun = false;
-volatile bool UPDATE_TFT_DATA = false;
-volatile bool dataAvailable = false;
-
-float h = NAN;     //Luftfeuchte auslesen
-float t = NAN;  //Temperatur auslesen
-float r = NAN; //Heat-Index berechnen
-double p0 = 0; //Wert fuer Luftdruck
-uint32_t lux = 0;
-
-/*
-#define MAXARRAY 5
-float tempArray [MAXARRAY] = {0};
-int lenTempArray = 0;
-
-float calculateTrendY(float y [], int len)
-{
-    float sumMultXY = 0;
-    float sumX = 0;
-    float sumY = 0;
-    float resBOne = 0;
-    float resBTwo = 0;
-
-    for(size_t i=0; i<len; i++)
-    {
-       sumMultXY += i * y[i];
-       sumX += i;
-       sumY += y[i];
-       resBOne += i * i;
-    }
-
-    resBOne *= len;
-    resBTwo = sumX * sumX;
-    float oben = (len * sumMultXY) - (sumX * sumY);
-    float unten = resBOne - resBTwo;
-
-    return (oben / unten);
-}
-
-void addValueToArray(float value)
-{
-  if (lenTempArray >= MAXARRAY)
-  {
-    for ( int i = 0; i<MAXARRAY-1; i++)
-    {
-        tempArray[i] = tempArray[i+1];
-    }
-    tempArray [MAXARRAY-1] = value;
-  } else
-  {
-      tempArray [lenTempArray++] = value;
-  }
-}*/
-
-void initSerial(void)
-{
-  Serial.begin(9600);
-  Serial.flush();
-}
-
-void initSensors(void)
-{
-  dht.begin();
-  pressure.begin();
-  tsl.begin();
-  tft.reset();
-  tsl.setGain(TSL2561_GAIN_16X);
-  tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS);
-}
-
-void initTFT(void)
-{
-  uint16_t identifier = tft.readID();
-  if(identifier == 0x9325) {
-  } else if(identifier == 0x9328) {
-  } else if(identifier == 0x4535) {
-  } else if(identifier == 0x7575) {
-  } else if(identifier == 0x9341) {
-  } else if(identifier == 0x7783) {
-  } else if(identifier == 0x8230) {
-  } else if(identifier == 0x8357) {
-  } else if(identifier==0x0101)
-  {
-    identifier=0x9341;
-  } else {
-    identifier=0x9341;
-  }
-
-  tft.begin(identifier);
-  tft.setRotation(1);
-}
-
-void initIOs(void)
-{
-  pinMode(PIN_LED, OUTPUT);
-  digitalWrite(PIN_LED, LOW);
-  pinMode(LEDblau, OUTPUT);
-  pinMode(LEDgruen, OUTPUT);
-  pinMode(LEDrot, OUTPUT);
-  attachInterrupt(digitalPinToInterrupt(interruptPin), interruptCall, RISING);
-}
-
-
-void setup(void)
-{
-  initSerial();
-  initSensors();
-  initTFT();
-  initIOs();
-  ledTest();
-}
-
-void loop(void)
-{
-  bool sendSerialData = false;
-  if (Serial.available() > 0)
-  {
-    String input = Serial.readString();
-    if (input == "GetInformation")
-      sendSerialData = true;
-  }
-  processData(sendSerialData);
-  delay(DELAY_TIME);
-  cycle++;
-}
-
-unsigned long writeTextToTFT(double temp, double humanity, double heatindex, double airpressure, uint32_t lightvalue)
-{
-  tft.fillScreen(BLACK);
-  unsigned long start = micros();
-  tft.setCursor(0, 0);
-  tft.setTextSize(1);
-  tft.println(" ");
-  tft.setTextSize(3);
-  tft.setTextColor(GREEN);
-  tft.println("Sensor INNEN:");
-  tft.println(" ");
-  tft.setTextSize(2);
-  tft.print("Temperatur: ");
-  tft.print(temp);
-  tft.println(" C");
-  tft.println(" ");
-  tft.print("Luftfeuchtigkeit: ");
-  tft.print(humanity);
-  tft.println(" %");
-  tft.println(" ");
-  tft.print("Heat-Index: ");
-  tft.print(heatindex);
-  tft.println(" C");
-  tft.println(" ");
-  tft.print("Luftdruck: ");
-  tft.print(airpressure);
-  tft.println(" mb");
-  tft.println(" ");
-  tft.print("Lichtwert: ");
-  tft.print(lightvalue);
-  tft.println(" Lux");
-  tft.setTextSize(1);
-  tft.println(" ");
-  if (Serial)
-    tft.println("Serial connected");
-  else
-    tft.println("Serial _not_ connected");
-  return micros() - start;
-}
-
-void showError(void)
-{
-  tft.fillScreen(BLACK);
-  tft.setCursor(0, 0);
-  tft.setTextSize(1);
-  tft.println(" ");
-  tft.setTextSize(3);
-  tft.setTextColor(RED);
-  tft.println("Sensor INNEN:");
-  tft.println(" ");
-  tft.println("Daten konnten");
-  tft.println("nicht");
-  tft.println("gelesen werden!");
-}
-
-void writeSerialProtocolV1(float humanity, float temperature, float heatIndex)
-{
-  digitalWrite(LEDgruen, HIGH);
-  Serial.print("START");
-  Serial.print("|"); // delim
-  Serial.print(humanity); // Luftfeuchte
-  Serial.print("|"); // delim
-  Serial.print(temperature); // Temperatur
-  Serial.print("|"); // delim
-  Serial.print(heatIndex); // HeatIndex
-  Serial.print("|"); // delim
-  Serial.println("EOF");
-  Serial.flush();
-  delay(SERIALWAIT);
-  digitalWrite(LEDgruen, LOW);
-}
-
-void writeSerialProtocolV2(float humanity, float temperature, float heatIndex, double airPressure)
-{
-  digitalWrite(LEDgruen, HIGH);
-  Serial.print("START");
-  Serial.print("|"); // delim
-  Serial.print("LEN:4"); //4 Werte werden uebertragen
-  Serial.print("|"); // delim
-  Serial.print(humanity); // Luftfeuchte
-  Serial.print("|"); // delim
-  Serial.print(temperature); // Temperatur
-  Serial.print("|"); // delim
-  Serial.print(heatIndex); // HeatIndex
-  Serial.print("|");
-  Serial.print(airPressure); //Luftdruck millibar
-  Serial.print("|"); // delim
-  Serial.println("EOF");
-  Serial.flush();
-  delay(SERIALWAIT);
-  digitalWrite(LEDgruen, LOW);
-}
-
-void writeSerialProtocolV3(float humanity, float temperature, float heatIndex, double airPressure, int lux)
-{
-  digitalWrite(LEDgruen, HIGH);
-  Serial.print("START");
-  Serial.print("|"); // delim
-  Serial.print("LEN:5"); //5 Werte werden uebertragen
-  Serial.print("|"); // delim
-  Serial.print(humanity); // Luftfeuchte
-  Serial.print("|"); // delim
-  Serial.print(temperature); // Temperatur
-  Serial.print("|"); // delim
-  Serial.print(heatIndex); // HeatIndex
-  Serial.print("|"); // delim
-  Serial.print(airPressure); //Luftdruck millibar
-  Serial.print("|"); // delim
-  Serial.print(lux); // Lichtstaerke
-  Serial.print("|"); // delim
-  Serial.println("EOF");
-  Serial.flush();
-  delay(SERIALWAIT);
-  digitalWrite(LEDgruen, LOW);
-}
-
-bool getPressure(double * value)
-{
-  double T,P;
-  char st;
-
-  st = pressure.startTemperature();
-
-  if (st != 0)
-  {
-    delay(st);
-    st = pressure.getTemperature(T);
-  }
-
-  st = pressure.startPressure(3);
-
-  if (st != 0)
-  {
-    delay(st);
-
-    st = pressure.getPressure(P,T);
-
-    if (st != 0)
-    {
-      *value = P;
-      return true;
-    }
-  }
-  return false;
-}
-
-void processData(bool sendSerialData)
-{
-  h = dht.readHumidity();     //Luftfeuchte auslesen
-  t = dht.readTemperature();  //Temperatur auslesen
-  r = dht.computeHeatIndex(t, h, false); //Heat-Index berechnen
-  bool pressAvailable = getPressure(&p0); //Luftdruck lesen
-  static bool errorOccured = false;
-  uint16_t x = tsl.getLuminosity(TSL2561_VISIBLE);
-  uint32_t lum = tsl.getFullLuminosity();
-  uint16_t ir, full;
-  ir = lum >> 16;
-  full = lum & 0xFFFF;
-  lux = tsl.calculateLux(full, ir);
-
-  if (isnan(t) || isnan(h) || isnan(r) || !pressAvailable) //Fehler beim Lesen eines der Daten
-  {
-    showError();
-    errorOccured = true;
-    digitalWrite(LEDrot, HIGH);
-    if (sendSerialData)
-    {
-      Serial.println("Fehler: Daten konnten gelesen werden!");
-      Serial.flush();
-    }
-
-
-  }
-  else
-  {
-    digitalWrite(LEDrot, LOW);
-    //update TFT only the CYCLE_UPDATE_TFT times when a processData is called
-    //to avoid each time update of the TFT
-    //or if an error occured, update the TFT the next OK time
-    if (cycle >= CYCLE_UPDATE_TFT || errorOccured || UPDATE_TFT_DATA)
-    {
-      writeTextToTFT(t, h, r, p0, lux);
-      errorOccured = false;
-      UPDATE_TFT_DATA = false;
-    }
-
-    if (sendSerialData)
-    {
-      writeSerialProtocolV3(h, t, r, p0, lux);
-    }
-  }
-
-  if (cycle >= CYCLE_UPDATE_TFT)  //otherwise, if it this is done within the else block above AND
-  {                               //in case an error occurs and persists a longer time, the cycle will increase more and more
-    cycle = 1;                    //which could then cause an overflow of the cycle value
-  }
-}
-
-void printIPInfoOnTFT(void)
-{
-  tft.fillScreen(BLACK);
-  tft.setCursor(0, 0);
-  tft.setTextSize(1);
-  tft.println(" ");
-  tft.setTextSize(2);
-  tft.setTextColor(WHITE);
-  tft.println("IP:");
-  tft.println("127.0.0.1");
-  tft.println("Signal Staerke:");
-  tft.println("-71 dBm");
-}
-
-void ledTest(void)
-{
-  analogWrite(LEDblau, brightness1a); // blau einschalten
-  delay(delayRGB);
-  analogWrite(LEDblau, dunkel); // blau ausschalten
-  analogWrite(LEDrot, brightness1b); // rot einschalten
-  delay(delayRGB);
-  analogWrite(LEDrot, dunkel); // rotausschalten
-  analogWrite(LEDgruen, brightness1c); // gruen einschalten
-  delay(delayRGB);
-  analogWrite(LEDgruen, dunkel); // gruenausschalten
-}
-
-void interruptCall(void)
-{
-  printIPInfoOnTFT();
-  UPDATE_TFT_DATA = true;
-}
-
-
+#include <Adafruit_GFX.h>    // Core graphics library
+#include <Adafruit_TFTLCD.h> // Hardware-specific library
+#include "TSL2561.h"
+#include <SFE_BMP180.h>
+#include <Wire.h>
+#include "DHT.h"
+#include <MCUFRIEND_kbv.h>
+
+#define LCD_CS A3 // Chip Select goes to Analog 3
+#define LCD_CD A2 // Command/Data goes to Analog 2
+#define LCD_WR A1 // LCD Write goes to Analog 1
+#define LCD_RD A0 // LCD Read goes to Analog 0
+
+#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
+#define LDR A10
+#define DHTPIN 22
+#define DHTTYPE DHT22
+#define PIN_LED 24 //Serial Data LED
+#define SERIALWAIT 200
+#define interruptPin 19
+
+// Assign human-readable names to some common 16-bit color values:
+#define BLACK   0x0000
+#define BLUE    0x001F
+#define RED     0xF800
+#define GREEN   0x07E0
+#define CYAN    0x07FF
+#define MAGENTA 0xF81F
+#define YELLOW  0xFFE0
+#define WHITE   0xFFFF
+
+//RGB LED
+#define LEDblau 44 // Farbe blau an Pin 3
+#define LEDrot 46 // Farbe rot an Pin 5
+#define LEDgruen 45 // Farbe gruen an Pin 6
+#define delayRGB 500 // p ist eine Pause mit 1000ms also 1 Sekunde
+#define brightness1a 125 // Zahlenwert zwischen 0 und 255 – gibt die Leuchtstärke der einzelnen Farbe an
+#define brightness1b 125 // Zahlenwert zwischen 0 und 255 – gibt die Leuchtstärke der einzelnen Farbe an
+#define brightness1c 125 // Zahlenwert zwischen 0 und 255 – gibt die Leuchtstärke der einzelnen Farbe an
+#define dunkel 0 // Zahlenwert 0 bedeutet Spannung 0V – also LED aus.
+
+//cycle will be increased in the loop(), if cycle == CYCLE_UPDATE_TFT --> update TFT and reset cycle to 0
+//this will avoid updating the TFT each time when a serial data is sent (no need to update the TFT that often)
+#define CYCLE_UPDATE_TFT 6
+int cycle = CYCLE_UPDATE_TFT;
+
+#define DELAY_TIME 10000 //Delay Time between each processData() call
+TSL2561 tsl(TSL2561_ADDR_FLOAT);
+MCUFRIEND_kbv tft;
+DHT dht(DHTPIN, DHTTYPE);
+SFE_BMP180 pressure;
+volatile bool ledTestRun = false;
+volatile bool UPDATE_TFT_DATA = false;
+
+void initSerial(void)
+{
+  Serial.begin(112000);
+  Serial.flush();
+}
+
+void initSensors(void)
+{
+  dht.begin();
+  pressure.begin();
+  tsl.begin();
+  tft.reset();
+  tsl.setGain(TSL2561_GAIN_16X);
+  tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS);
+}
+
+void initTFT(void)
+{
+  uint16_t identifier = tft.readID();
+  if(identifier == 0x9325) {
+  } else if(identifier == 0x9328) {
+  } else if(identifier == 0x4535) {
+  } else if(identifier == 0x7575) {
+  } else if(identifier == 0x9341) {
+  } else if(identifier == 0x7783) {
+  } else if(identifier == 0x8230) {
+  } else if(identifier == 0x8357) {
+  } else if(identifier==0x0101)
+  {
+    identifier=0x9341;
+  } else {
+    identifier=0x9341;
+  }
+
+  tft.begin(identifier);
+  tft.setRotation(1);
+}
+
+void initIOs(void)
+{
+  pinMode(PIN_LED, OUTPUT);
+  digitalWrite(PIN_LED, LOW);
+  pinMode(LEDblau, OUTPUT);
+  pinMode(LEDgruen, OUTPUT);
+  pinMode(LEDrot, OUTPUT);
+  attachInterrupt(digitalPinToInterrupt(interruptPin), interruptCall, RISING);
+}
+
+
+void setup(void)
+{
+  initSerial();
+  initSensors();
+  initTFT();
+  initIOs();
+  ledTest();
+}
+
+void checkSerialData()
+{
+  for (int i = 1; i <=100; i++)
+  {
+    if ((Serial.available() > 0))
+    {
+      processIncomingData(Serial.readString());
+      Serial.flush();
+    }
+    delay(DELAY_TIME / 100);
+  }
+}
+
+void loop(void)
+{
+  processData();
+  checkSerialData();
+  cycle++;
+}
+
+void processIncomingData(String data)
+{
+  if (data == "LED")
+  {
+    digitalWrite(LEDblau, !digitalRead(LEDblau));
+    Serial.println("REPLY|BLAU-OK|EOF");
+    return;
+  } else if (data == "STATUSLED")
+  {
+    if (digitalRead(LEDblau) == HIGH)
+      Serial.println("REPLY|BLAU-IST-AN|EOF");
+    else
+      Serial.println("REPLY|BLAU-IST-AUS|EOF");
+    return;
+  } else if (data == "PROTOCOL_VERSION")
+  {
+    Serial.println("REPLY|V3|EOF");
+    return;
+  } else if (data == "GET_TEMP_ARDUINO")
+  {
+    Serial.println("REPLY|FOUND_ARDUINO|EOF");
+    return;
+  }
+
+  Serial.println("REPLY|FEHLER: Nicht Implementiert!|EOF");
+}
+
+unsigned long writeTextToTFT(double temp, double humanity, double heatindex, double airpressure, uint32_t lightvalue)
+{
+  tft.fillScreen(BLACK);
+  unsigned long start = micros();
+  tft.setCursor(0, 0);
+  tft.setTextSize(1);
+  tft.println(" ");
+  tft.setTextSize(3);
+  tft.setTextColor(GREEN);
+  tft.println("Sensor INNEN:");
+  tft.println(" ");
+  tft.setTextSize(2);
+  tft.print("Temperatur: ");
+  tft.print(temp);
+  tft.println(" C");
+  tft.println(" ");
+  tft.print("Luftfeuchtigkeit: ");
+  tft.print(humanity);
+  tft.println(" %");
+  tft.println(" ");
+  tft.print("Heat-Index: ");
+  tft.print(heatindex);
+  tft.println(" C");
+  tft.println(" ");
+  tft.print("Luftdruck: ");
+  tft.print(airpressure);
+  tft.println(" mb");
+  tft.println(" ");
+  tft.print("Lichtwert: ");
+  tft.print(lightvalue);
+  tft.println(" Lux");
+  tft.setTextSize(1);
+  tft.println(" ");
+  if (Serial)
+    tft.println("Serial connected");
+  else
+    tft.println("Serial _not_ connected");
+  return micros() - start;
+}
+
+void showError(void)
+{
+  tft.fillScreen(BLACK);
+  tft.setCursor(0, 0);
+  tft.setTextSize(1);
+  tft.println(" ");
+  tft.setTextSize(3);
+  tft.setTextColor(RED);
+  tft.println("Sensor INNEN:");
+  tft.println(" ");
+  tft.println("Daten konnten");
+  tft.println("nicht");
+  tft.println("gelesen werden!");
+}
+
+void writeSerialProtocolV1(float humanity, float temperature, float heatIndex)
+{
+  analogWrite(LEDgruen, brightness1c);
+  Serial.print("START");
+  Serial.print("|"); // delim
+  Serial.print(humanity); // Luftfeuchte
+  Serial.print("|"); // delim
+  Serial.print(temperature); // Temperatur
+  Serial.print("|"); // delim
+  Serial.print(heatIndex); // HeatIndex
+  Serial.print("|"); // delim
+  Serial.println("EOF");
+  Serial.flush();
+  delay(SERIALWAIT);
+  analogWrite(LEDgruen, dunkel);
+}
+
+void writeSerialProtocolV2(float humanity, float temperature, float heatIndex, double airPressure)
+{
+  analogWrite(LEDgruen, brightness1c);
+  Serial.print("START");
+  Serial.print("|"); // delim
+  Serial.print("LEN:4"); //4 Werte werden uebertragen
+  Serial.print("|"); // delim
+  Serial.print(humanity); // Luftfeuchte
+  Serial.print("|"); // delim
+  Serial.print(temperature); // Temperatur
+  Serial.print("|"); // delim
+  Serial.print(heatIndex); // HeatIndex
+  Serial.print("|");
+  Serial.print(airPressure); //Luftdruck millibar
+  Serial.print("|"); // delim
+  Serial.println("EOF");
+  Serial.flush();
+  delay(SERIALWAIT);
+  analogWrite(LEDgruen, dunkel);
+}
+
+void writeSerialProtocolV3(float humanity, float temperature, float heatIndex, double airPressure, int lux)
+{
+  analogWrite(LEDgruen, brightness1c);
+  Serial.print("START");
+  Serial.print("|"); // delim
+  Serial.print("LEN:5"); //5 Werte werden uebertragen
+  Serial.print("|"); // delim
+  Serial.print(humanity); // Luftfeuchte
+  Serial.print("|"); // delim
+  Serial.print(temperature); // Temperatur
+  Serial.print("|"); // delim
+  Serial.print(heatIndex); // HeatIndex
+  Serial.print("|"); // delim
+  Serial.print(airPressure); //Luftdruck millibar
+  Serial.print("|"); // delim
+  Serial.print(lux); // Lichtstaerke
+  Serial.print("|"); // delim
+  Serial.println("EOF");
+  Serial.flush();
+  delay(SERIALWAIT);
+  analogWrite(LEDgruen, dunkel);
+}
+
+bool getPressure(double * value)
+{
+  double T,P;
+  char st;
+
+  st = pressure.startTemperature();
+
+  if (st != 0)
+  {
+    delay(st);
+    st = pressure.getTemperature(T);
+  }
+
+  st = pressure.startPressure(3);
+
+  if (st != 0)
+  {
+    delay(st);
+
+    st = pressure.getPressure(P,T);
+
+    if (st != 0)
+    {
+      *value = P;
+      return true;
+    }
+  }
+  return false;
+}
+
+void processData()
+{
+  float h = dht.readHumidity();     //Luftfeuchte auslesen
+  float t = dht.readTemperature();  //Temperatur auslesen
+  float r = dht.computeHeatIndex(t, h, false); //Heat-Index berechnen
+  double p0 = 0; //Wert fuer Luftdruck
+  bool pressAvailable = getPressure(&p0); //Luftdruck lesen
+  static bool errorOccured = false;
+  uint16_t x = tsl.getLuminosity(TSL2561_VISIBLE);
+  uint32_t lum = tsl.getFullLuminosity();
+  uint16_t ir, full;
+  ir = lum >> 16;
+  full = lum & 0xFFFF;
+  uint32_t lux = tsl.calculateLux(full, ir);
+
+  if (isnan(t) || isnan(h) || isnan(r) || !pressAvailable) //Fehler beim Lesen eines der Daten
+  {
+    showError();
+    errorOccured = true;
+    if (Serial)
+    {
+      Serial.println("Fehler: Daten konnten gelesen werden!");
+      Serial.flush();
+    }
+  }
+  else
+  {
+    //update TFT only the CYCLE_UPDATE_TFT times when a processData is called
+    //to avoid each time update of the TFT
+    //or if an error occured, update the TFT the next OK time
+    if (cycle >= CYCLE_UPDATE_TFT || errorOccured || UPDATE_TFT_DATA)
+    {
+      writeTextToTFT(t, h, r, p0, lux);
+      errorOccured = false;
+      UPDATE_TFT_DATA = false;
+    }
+
+    writeSerialProtocolV3(h, t, r, p0, lux);
+  }
+
+  if (cycle >= CYCLE_UPDATE_TFT)  //otherwise, if it this is done within the else block above AND
+  {                               //in case an error occurs and persists a longer time, the cycle will increase more and more
+    cycle = 1;                    //which could then cause an overflow of the cycle value
+  }
+}
+
+void printIPInfoOnTFT(void)
+{
+  tft.fillScreen(BLACK);
+  tft.setCursor(0, 0);
+  tft.setTextSize(1);
+  tft.println(" ");
+  tft.setTextSize(2);
+  tft.setTextColor(WHITE);
+  tft.println("IP:");
+  tft.println("127.0.0.1");
+  tft.println("Signal Staerke:");
+  tft.println("-71 dBm");
+}
+
+void ledTest(void)
+{
+  analogWrite(LEDblau, brightness1a); // blau einschalten
+  delay(delayRGB);
+  analogWrite(LEDblau, dunkel); // blau ausschalten
+  analogWrite(LEDrot, brightness1b); // rot einschalten
+  delay(delayRGB);
+  analogWrite(LEDrot, dunkel); // rotausschalten
+  analogWrite(LEDgruen, brightness1c); // gruen einschalten
+  delay(delayRGB);
+  analogWrite(LEDgruen, dunkel); // gruenausschalten
+}
+
+void interruptCall(void)
+{
+  printIPInfoOnTFT();
+  UPDATE_TFT_DATA = true;
+}


Initial vehicle implementation: simple beacon sender

--- arduino/vehicle/vehicle.ino
+++ arduino/vehicle/vehicle.ino
@@ -0,0 +1,88 @@
+#include <SPI.h>
+#include <RH_RF69.h>
+
+#include "cmdproc.h"
+
+// Singleton instance of the radio driver
+static RH_RF69 rf69;
+
+void setup()
+{
+    Serial.begin(9600);
+    if (!rf69.init())
+        Serial.println("init failed");
+    else
+        Serial.println("init success!");
+
+    if (!rf69.setFrequency(869.850))
+        Serial.println("setFrequency failed");
+
+    const RH_RF69::ModemConfig config = {
+        (RH_RF69_DATAMODUL_DATAMODE_PACKET |
+         RH_RF69_DATAMODUL_MODULATIONTYPE_FSK |
+         RH_RF69_DATAMODUL_MODULATIONSHAPING_FSK_BT0_5),
+        0x01, 0x00,             // bit rate
+        0x02, 0x00,             // freq dev
+        0xe1, 0xe1,
+        (RH_RF69_PACKETCONFIG1_PACKETFORMAT_VARIABLE |
+         RH_RF69_PACKETCONFIG1_DCFREE_WHITENING |
+         RH_RF69_PACKETCONFIG1_CRC_ON |
+         RH_RF69_PACKETCONFIG1_ADDRESSFILTERING_NODE_BC)
+    };
+    rf69.setModemRegisters(&config);
+    rf69.setTxPower(0);
+}
+
+static bool sendit(int len, const uint8_t * data, int retries)
+{
+    int i;
+    for (i = 0; i < retries; i++) {
+        int rssi = rf69.rssiRead();
+        if (rssi < -80) {
+            // channel clear, send it
+            rf69.send(data, len);
+            rf69.waitPacketSent();
+            rf69.setModeRx();
+            return true;
+        }
+        delay(2);
+    }
+    return false;
+}
+
+// forward declaration
+static int do_help(int argc, char *argv[]);
+
+static const cmd_t commands[] = {
+    {"help", do_help, "lists all commands"}
+};
+
+static int do_help(int argc, char *argv[])
+{
+    (void) argc;
+    (void) argv;
+    for (const cmd_t * cmd = commands; cmd->cmd != NULL; cmd++) {
+        Serial.print(cmd->name);
+        Serial.print(" ");
+        Serial.println(cmd->help);
+    }
+}
+
+
+void loop()
+{
+    static long int last_sent = 0;
+
+    long int m = millis();
+    if ((m - last_sent) > 100) {
+        last_sent += 100;
+
+        // send with listen-before-talk
+        char data[32];
+        memset(data, 0, sizeof(data));
+        strcpy(data, "THIS IS A BEACON");
+        if (!sendit(sizeof(data), (uint8_t *) data, 3)) {
+            last_sent += 3;
+        }
+    }
+}


Insierimento ritardo di 1 secondo alla trasmissione bluetooth dei dati per evitare perdite nella trasmissione in modalità di controllo manuale.

--- Smart_Green_House_codiceArduino/Smart_Green_House_codiceArduino.ino
+++ Smart_Green_House_codiceArduino/Smart_Green_House_codiceArduino.ino
@@ -219,9 +219,9 @@
   bluetooth.print(umidi_terra);    //trasmetto il valore dell'altezza della pianta
   bluetooth.print(" ");
   bluetooth.println("#");
-  delay(500);            //inserisco un ritardo di 0,5 secondi al fine di evitare l'intasamento del buffer seriale su cui trasmetto i dati
+  delay(1000);            //inserisco un ritardo di 1 secondi al fine di evitare l'intasamento del buffer seriale su cui trasmetto i dati
                          //N.B. pur aggiornando l app Android, la medesima rileva i vecchi pacchetti inviati. In questo modo vado ad ottenere sempre il valore attuale dello stato sull APP
-                         //svantaggio: ritardo di 0,5 secondi l'abilitazione dei vari switch in modalità di CONTROLLO MANUALE(tramite app) sul sistema
+                         //svantaggio: ritardo di 1 secondi l'abilitazione dei vari switch in modalità di CONTROLLO MANUALE(tramite app) sul sistema
 }

 //Funzione in grado di abilitare i controlli sull'impianto tramite il pilotaggio di opportuni switch presenti nell'applicazione Android nella finestra CONTROLLO MANUALE


Tidy up code

Tidy up code

--- Code/OricKeyboardReader.ino
+++ Code/OricKeyboardReader.ino
@@ -26,12 +26,12 @@
 // Array of characters
 // Refer to https://www.arduino.cc/en/Reference/KeyboardModifiers for modifier keys

-char keycodes[NUM_KEYS] = { '7', 'n', '5', 'v', '3', 'x', '1', ' ',	                      // R0
+char keycodes[NUM_KEYS] = { '7', 'n', '5', 'v', '3', 'x', '1', ' ',	        // R0
 							'j', 't', 'r', 'f', 'd', 'q', KEY_ESC, ' ',	                  // R1
 							'm', '6', 'b', '4', 'c', '2', 'z', KEY_LEFT_CTRL,             // R2
 							'k', '9', ';', '-', '\'', '\\', ' ', ' ',                     // R3
 							' ', ',', '.', KEY_UP_ARROW, KEY_RIGHT_ARROW, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_LEFT_SHIFT,  // R4
-							'u', 'i', 'o', 'p', '[', ']', KEY_BACKSPACE, KEY_TAB,         // R5  KEY_TAB is FUNCT, handled seperately
+							'u', 'i', 'o', 'p', '[', ']', KEY_BACKSPACE, KEY_TAB,         // R5  KEY_TAB is FUNCT (handled seperately)
 							'y', 'h', 'g', 'e', 'w', 's', 'a', ' ',                       // R6
 							'8', 'l', '0', '/', '=', ' ', KEY_RETURN, KEY_RIGHT_SHIFT };  // R7


Turns will hold for longer

Turns will hold for longer

--- gps_arduino/gps_arduino.ino
+++ gps_arduino/gps_arduino.ino
@@ -63,7 +63,7 @@
 SoftwareSerial mySerial(2, 255);    //used for gps rx and tx pins in use

 //Minimum distance in meters to get to the current waypoint before heading to the next
-#define MIN_DISTANCE 1
+#define MIN_DISTANCE 2

 //Compass Stuff
 LSM303 compass;
@@ -122,6 +122,9 @@
 //Kalman filter for smoothing compass value
 //Kalman compassFilter(0.125,32,1023,0); //suggested initial values for high noise filtering

+/* true if in a turn */
+boolean turning = false;
+
 //Method definitions
 void gpsdump(TinyGPS &gps);
 bool feedgps();
@@ -160,10 +163,10 @@
     program to determine appropriate values for your particular unit.
     */
     //min: {  -525,   -547,   -614}    max: {  +689,   +562,   +438}
-    //compass.m_min = (LSM303::vector<int16_t>){-767, -642, -379};  /Josh
-    //compass.m_max = (LSM303::vector<int16_t>){+322, +647, +616};
-    compass.m_min = (LSM303::vector<int16_t>){-525, -547, -624}; //Atom
-    compass.m_max = (LSM303::vector<int16_t>){+689, +562, +438};
+    compass.m_min = (LSM303::vector<int16_t>){-767, -642, -379};  //Josh
+    compass.m_max = (LSM303::vector<int16_t>){+322, +647, +616};
+    //compass.m_min = (LSM303::vector<int16_t>){-525, -547, -624}; //Atom
+    //compass.m_max = (LSM303::vector<int16_t>){+689, +562, +438};

     //Setup test waypoint. Start 38.631514, -90.271908
     mLat[0] = 38.631158;
@@ -473,7 +476,7 @@
     }

   }
-
+
  /**
  * Main navitation code
  */
@@ -499,7 +502,7 @@
    int distance = getDistance(mCurrentWayPoint, flat, flon);

    //Check if distance is less then 2 meters
-   if(distance < MIN_DISTANCE){
+   if(distance <= MIN_DISTANCE){
      lcd2.setCursor(0,3);
      //Advance to next way point
      mCurrentWayPoint++;
@@ -509,19 +512,32 @@
        lcd2.print(F("**Finish Reached**"));
      } else {
        lcd2.print(F("**Waypoint Reached**"));
-       delay(2000);
+       delay(30000);
      }
    } else {
      //Navigate to the way point
-     if(abs(compassHeading - heading) < 5){
+     //Adjust max amount to be off course
+     int highTurnRange = 30;
+     if(turning){
+       highTurnRange = 10;
+     }
+     //Base turning range off of distance
+     int turnRange = constrain(map(distance, 0, 100, 5, 30), 5, highTurnRange);
+     if(abs(compassHeading - heading) < turnRange){
+       //Forward
+       turning = false;
        lcd2.setCursor(0,3);
        lcd2.print(F("  Command: FORWARD"));
        forward();
      } else if (compassHeading > heading) {
+       //Left
+       turning = true;
        lcd2.setCursor(0,3);
        lcd2.print(F("  Command: LEFT"));
        left();
      } else {
+       //Right
+       turning = true;
        lcd2.setCursor(0,3);
        lcd2.print(F("  Command: RIGHT"));
        right();
@@ -584,7 +600,11 @@
  }

  float formatDistance(int meters){
-  return meters / (float) 1000;
+   if(meters > 1000){
+    return meters / (float) 1000;
+   } else {
+    return meters;
+   }
  }

   void gpsdump(TinyGPS &gps){


Changed the json generation Method, to generate nested objects

--- code/demonstration/Arduino/Umgebungskachel/UmgebungskachelCommunication.ino
+++ code/demonstration/Arduino/Umgebungskachel/UmgebungskachelCommunication.ino
@@ -7,7 +7,24 @@

 String datastructureToJson() {

-	String json = "{";
+        DynamicJsonBuffer jsonBuffer;
+        JsonObject& root = jsonBuffer.createObject();
+        JsonObject& ledToggle = root.createNestedObject("LedToggle");
+        JsonObject& alertTemp = root.createNestedObject("AlertThresholdTemperature");
+        JsonObject& alertBright = root.createNestedObject("AlertThresholdBrightness");
+
+        ledToggle["led"] = get_SensorState_led(&sensorState);
+        alertTemp["threshold_temperature"] = get_SensorState_thresholdtemperature(&sensorState);
+        alertBright["threshold_brightness"] = get_SensorState_thresholdbrightness(&sensorState);
+
+        root["temperature"] = get_SensorState_temperaturec(&sensorState);
+        root["brightness"] = get_SensorState_brightness(&sensorState);
+
+        int len = root.measurePrettyLength();
+        char json[len+1];
+        root.prettyPrintTo(json, sizeof(json));
+        return json;
+        /*String json = "{";
 	json += "\"led\":\"" + (String)get_SensorState_led(&sensorState) + "\",";
 	json += "\"temperature_f\":"+ dtostrf(get_SensorState_temperaturef(&sensorState),0,4) + ",";
         json += "\"temperature_c\":"+ dtostrf(get_SensorState_temperaturec(&sensorState),0,4) + ",";
@@ -15,7 +32,7 @@
 	json += "\"threshold_brightness\":"+ dtostrf(get_SensorState_thresholdbrightness(&sensorState),0,4) + ",";
 	json += "\"threshold_temperature\":"+ dtostrf(get_SensorState_thresholdtemperature(&sensorState),0,4);
 	json += "}";
-	return json;
+	return json;*/
 }

 void parseDatastructureFromJson(String json) {