Delete LightSaberOS-1.6.ino

Delete LightSaberOS-1.6.ino

--- LightSaberOS-1.6.ino
+++ LightSaberOS-1.6.ino
@@ -1,1511 +0,0 @@
-/*
- * Created April 1, 2017
- * author:    Andras Kun (kun.andras@yahoo.de), Jason Brinkerhoff (jb@jbkuma.com)
- * source:    https://github.com/Protonerd/FX-SaberOS
- *
- * based on LightSaber OS originally created by Sebastien CAPOU (neskweek@gmail.com)
-
-   Description:	Operating System for Arduino based props inspired by the lightsabers popularized by Star Wars
-
-   This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
-   To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/.
-
-      !!!!!!!!!!!!! IMPORTANT !!! IMPORTANT !!! IMPORTANT !!! IMPORTANT !!!!!!!!!!!!!
-      !!!  PLEASE READ AND CONFIGURE Config.h AND Soundfont.h PRIOR TO INSTALLING !!!
-      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-*/
-/***************************************************************************************************
-* DFPLAYER variables
-*/
-//#define OLD_DPFPLAYER_LIB
-#ifdef OLD_DPFPLAYER_LIB
-#include <SoftwareSerial.h> // interestingly the DFPlayer lib refuses
-#include "DFPlayer_Mini_Mp3.h"
-//SoftwareSerial mp3player(DFPLAYER_TX, DFPLAYER_RX); // TX, RX
-SoftwareSerial mp3player(7, 8); // TX, RX
-#else
-#include <DFPlayer.h>
-DFPlayer dfplayer;
-#endif
-
-#include <Arduino.h>
-#include <I2Cdev.h>
-#include <MPU6050_6Axis_MotionApps20.h>
-#include <EEPROMex.h>
-#include <OneButton.h>
-#include <LinkedList.h>
-
-
-#include "Buttons.h"
-#include "Config.h"
-#include "ConfigMenu.h"
-#include "Light.h"
-#include "SoundFont.h"
-
-#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
-#include <Wire.h>
-#endif
-#if defined PIXELBLADE
-#include <WS2812.h>
-#endif
-
-#ifdef DEEP_SLEEP
-  #include <avr/sleep.h>
-  #include <avr/power.h>
-#endif // DEEP_SLEEP
-
-SoundFont soundFont;
-unsigned long sndSuppress = millis();
-unsigned long sndSuppress2 = millis();
-bool hum_playing = false; // variable to store whether hum is being played
-#ifdef JUKEBOX
-bool jukebox_play = false; // indicate whether a song is being played in JukeBox mode
-uint8_t jb_track;  // sound file track number in the directory designated for music playback
-#endif
-
-
-
-
-/***************************************************************************************************
- * Saber Finite State Machine Custom Type and State Variable
- */
-enum SaberStateEnum {S_STANDBY, S_SABERON, S_CONFIG, S_SLEEP, S_JUKEBOX};
-SaberStateEnum SaberState;
-SaberStateEnum PrevSaberState;
-
-enum ActionModeSubStatesEnum {AS_HUM, AS_IGNITION, AS_RETRACTION, AS_BLADELOCKUP, AS_PREBLADELOCKUP, AS_BLASTERDEFLECTMOTION, AS_BLASTERDEFLECTPRESS, AS_CLASH, AS_SWING, AS_SPIN, AS_FORCE};
-ActionModeSubStatesEnum ActionModeSubStates;
-
-enum ConfigModeSubStatesEnum {CS_VOLUME, CS_SOUNDFONT, CS_MAINCOLOR, CS_CLASHCOLOR, CS_BLASTCOLOR, CS_FLICKERTYPE, CS_IGNITIONTYPE, CS_RETRACTTYPE, CS_SLEEPINIT, CS_BATTERYLEVEL};
-ConfigModeSubStatesEnum ConfigModeSubStates;
-/***************************************************************************************************
- * Motion detection Variables
-*/
-MPU6050 mpu;
-// MPU control/status vars
-volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
-bool dmpReady = false;  // set true if DMP init was successful
-uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
-uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
-uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
-uint8_t fifoBuffer[64]; // FIFO storage buffer
-uint16_t mpuFifoCount;     // count of all bytes currently in FIFO
-// orientation/motion vars
-Quaternion curRotation;           // [w, x, y, z]         quaternion container
-Quaternion prevRotation;           // [w, x, y, z]         quaternion container
-static Quaternion prevOrientation;  // [w, x, y, z]         quaternion container
-static Quaternion curOrientation; // [w, x, y, z]         quaternion container
-VectorInt16 curAccel;
-VectorInt16 prevAccel;
-VectorInt16 curDeltAccel;
-VectorInt16 prevDeltAccel;
-
-/***************************************************************************************************
- * LED String variables
- */
-#if defined LEDSTRINGS
-#ifdef DIYINO_PRIME
-  uint8_t ledPins[] = {LS1, LS2, LS3, LS4, LS5, LS6};
-#else if #ifdef DIYINO_STARDUST
-  uint8_t ledPins[] = {LS1, LS2, LS3};
-#endif
-uint8_t blasterPin;
-#endif
-#if defined STAR_LED
-uint8_t ledPins[] = {LED_RED, LED_GREEN, LED_BLUE};
-cRGB currentColor;
-//uint8_t currentColor[4]; //0:Red 1:Green 2:Blue 3:ColorID
-#endif
-#if defined PIXELBLADE
-#ifdef DIYINO_PRIME
-  uint8_t ledPins[] = {LS1, LS2, LS3, LS4, LS5, LS6};
-#else if #ifdef DIYINO_STARDUST
-  uint8_t ledPins[] = {LS1, LS2, LS3};
-#endif
-WS2812 pixels(NUMPIXELS);
-cRGB color;
-cRGB currentColor;
-uint8_t blasterPixel;
-#endif
-
-uint8_t blaster = 0;
-//bool blasterBlocks = false;
-uint8_t clash = 0;
-bool lockuponclash = false;
-uint8_t blink = 0;
-uint8_t randomBlink = 0;
-/***************************************************************************************************
- * Buttons variables
- */
-OneButton mainButton(MAIN_BUTTON, true);
-#ifndef SINGLEBUTTON
-OneButton lockupButton(LOCKUP_BUTTON, true);
-#endif
-// replaced by Saber State Machine Variables
-//bool actionMode = false; // Play with your saber
-//bool configMode = false; // Configure your saber
-//static bool ignition = false;
-//static bool browsing = false;
-
-/***************************************************************************************************
- * ConfigMode Variables
- */
-int8_t modification = 0;
-int16_t value = 0;
-uint8_t menu = 0;
-bool enterMenu = false;
-bool changeMenu = false;
-bool play = false;
-unsigned int configAdress = 0;
-volatile uint8_t portbhistory = 0xFF;     // default is high because the pull-up
-#if defined LEDSTRINGS
-struct StoreStruct {
-	// This is for mere detection if they are our settings
-	char version[5];
-	// The settings
-	uint8_t volume;     // 0 to 31
-	uint8_t soundFont; // as many Sound font you have defined in Soundfont.h Max:253
-} storage;
-#endif
-#if defined STAR_LED
-struct StoreStruct {
-	// This is for mere detection if they are our settings
-	char version[5];
-	// The settings
-	uint8_t volume;// 0 to 31
-	uint8_t soundFont;// as many as Sound font you have defined in Soundfont.h Max:253
-  struct Profile {
-  #ifdef COLORS
-    uint8_t mainColor;  //colorID
-    uint8_t clashColor;//colorID
-    uint8_t blasterboltColor;//colorID
-  #else
-    cRGB mainColor;
-    cRGB clashColor;
-    cRGB blasterboltColor;
-  #endif
-  }sndProfile[SOUNDFONT_QUANTITY + 2];
-}storage;
-#endif
-
-#if defined PIXELBLADE
-struct StoreStruct {
-	// This is for mere detection if they are our settings
-	char version[5];
-	// The settings
-	uint8_t volume;// 0 to 31
-	uint8_t soundFont;// as many as Sound font you have defined in Soundfont.h Max:253
-  struct Profile {
-  #ifdef COLORS
-    uint8_t mainColor;  //colorID
-    uint8_t clashColor;//colorID
-    uint8_t blasterboltColor;//colorID
-  #else
-    cRGB mainColor;
-    cRGB clashColor;
-    cRGB blasterboltColor;
-  #endif
-  }sndProfile[SOUNDFONT_QUANTITY + 2];
-}storage;
-
-#endif
-
-/***************************************************************************************************
- * Function Prototypes
- * The following prototypes are not correctly generated by Arduino IDE 1.6.5-r5 or previous
- */
-inline void printQuaternion(Quaternion quaternion, long multiplier);
-inline void printAcceleration(VectorInt16 aaWorld);
-
-// ====================================================================================
-// ===        	       	   			SETUP ROUTINE  	 	                			===
-// ====================================================================================
-void setup() {
-
-	// join I2C bus (I2Cdev library doesn't do this automatically)
-#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
-	Wire.begin();
-	TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz). Comment this line if having compilation difficulties with TWBR.
-#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
-			Fastwire::setup(400, true);
-#endif
-	// Serial line for debug
-	Serial.begin(115200);
-
-	/***** LOAD CONFIG *****/
-	// Get config from EEPROM if there is one
-	// or initialise value with default ones set in StoreStruct
-	EEPROM.setMemPool(MEMORYBASE, EEPROMSizeATmega328); //Set memorypool base to 32, assume Arduino Uno board
-	configAdress = EEPROM.getAddress(sizeof(StoreStruct)); // Size of config object
-
-	if (!loadConfig()) {
-		for (uint8_t i = 0; i <= 2; i++)
-			storage.version[i] = CONFIG_VERSION[i];
-		storage.soundFont = SOUNDFONT;
-		storage.volume = VOL;
-#if defined LEDSTRINGS
-#endif
-#if defined STAR_LED
-    for (uint8_t i=2; i<SOUNDFONT_QUANTITY+2;i++){
-      #ifdef COLORS
-      storage.sndProfile[i].mainColor=1;
-      storage.sndProfile[i].clashColor=1;
-      storage.sndProfile[i].blasterboltColor=1;
-      #else
-      storage.sndProfile[i].mainColor.r=20;
-      storage.sndProfile[i].mainColor.g=20;
-      storage.sndProfile[i].mainColor.b=20;
-      storage.sndProfile[i].clashColor.r=20;
-      storage.sndProfile[i].clashColor.g=20;
-      storage.sndProfile[i].clashColor.b=20;
-      storage.sndProfile[i].blasterboltColor.r=20;
-      storage.sndProfile[i].blasterboltColor.g=20;
-      storage.sndProfile[i].blasterboltColor.b=20;
-      #endif
-    }
-#endif
-#if defined PIXELBLADE
-    for (uint8_t i=2; i<SOUNDFONT_QUANTITY+2;i++){
-      #ifdef COLORS
-      storage.sndProfile[i].mainColor=1;
-      storage.sndProfile[i].clashColor=1;
-      storage.sndProfile[i].blasterboltColor=1;
-      #else
-      storage.sndProfile[i].mainColor.r=20;
-      storage.sndProfile[i].mainColor.g=20;
-      storage.sndProfile[i].mainColor.b=20;
-      storage.sndProfile[i].clashColor.r=20;
-      storage.sndProfile[i].clashColor.g=20;
-      storage.sndProfile[i].clashColor.b=20;
-      storage.sndProfile[i].blasterboltColor.r=20;
-      storage.sndProfile[i].blasterboltColor.g=20;
-      storage.sndProfile[i].blasterboltColor.b=20;
-      #endif
-    }
-#endif
-    saveConfig();
-#if defined LS_INFO
-    Serial.println(F("DEFAULT VALUE"));
-#endif
-  }
-#if defined LS_INFO
-  else {
-    Serial.println(F("EEPROM LOADED"));
-  }
-#endif
-  soundFont.setID(storage.soundFont);
-
-  /***** LOAD CONFIG *****/
-
-  /***** MP6050 MOTION DETECTOR INITIALISATION  *****/
-
-  // initialize device
-#if defined LS_INFO
-  Serial.println(F("Initializing I2C devices..."));
-#endif
-  mpu.initialize();
-
-  // verify connection
-#if defined LS_INFO
-  Serial.println(F("Testing device connections..."));
-  Serial.println(
-    mpu.testConnection() ?
-    F("MPU6050 connection successful") :
-    F("MPU6050 connection failed"));
-
-  // load and configure the DMP
-  Serial.println(F("Initializing DMP..."));
-#endif
-  devStatus = mpu.dmpInitialize_light();  // this is a ligter version of the above
-
-  /*
-     Those offsets are specific to each MPU6050 device.
-     they are found via calibration process.
-     See this script http://www.i2cdevlib.com/forums/index.php?app=core&module=attach&section=attach&attach_id=27
-  */
-#ifdef MPUCALOFFSETEEPROM
-  // retreive MPU6050 calibrated offset values from EEPROM
-  EEPROM.setMemPool(MEMORYBASEMPUCALIBOFFSET, EEPROMSizeATmega328);
-  int addressInt = MEMORYBASEMPUCALIBOFFSET;
-  mpu.setXAccelOffset(EEPROM.readInt(addressInt));
-#ifdef LS_INFO
-  int16_t output;
-  output = EEPROM.readInt(addressInt);
-  Serial.print("address: "); Serial.println(addressInt); Serial.print("output: "); Serial.println(output); Serial.println("");
-#endif
-  addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
-  mpu.setYAccelOffset(EEPROM.readInt(addressInt));
-#ifdef LS_INFO
-  output = EEPROM.readInt(addressInt);
-  Serial.print("address: "); Serial.println(addressInt); Serial.print("output: "); Serial.println(output); Serial.println("");
-#endif
-  addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
-  mpu.setZAccelOffset(EEPROM.readInt(addressInt));
-#ifdef LS_INFO
-  output = EEPROM.readInt(addressInt);
-  Serial.print("address: "); Serial.println(addressInt); Serial.print("output: "); Serial.println(output); Serial.println("");
-#endif
-  addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
-  mpu.setXGyroOffset(EEPROM.readInt(addressInt));
-#ifdef LS_INFO
-  output = EEPROM.readInt(addressInt);
-  Serial.print("address: "); Serial.println(addressInt); Serial.print("output: "); Serial.println(output); Serial.println("");
-#endif
-  addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
-  mpu.setYGyroOffset(EEPROM.readInt(addressInt));
-#ifdef LS_INFO
-  output = EEPROM.readInt(addressInt);
-  Serial.print("address: "); Serial.println(addressInt); Serial.print("output: "); Serial.println(output); Serial.println("");
-#endif
-  addressInt = addressInt + 2; //EEPROM.getAddress(sizeof(int));
-  mpu.setZGyroOffset(EEPROM.readInt(addressInt));
-#ifdef LS_INFO
-  output = EEPROM.readInt(addressInt);
-  Serial.print("address: "); Serial.println(addressInt); Serial.print("output: "); Serial.println(output); Serial.println("");
-#endif
-#else // assign calibrated offset values here:
-  /* UNIT1 */
-  mpu.setXAccelOffset(46);
-  mpu.setYAccelOffset(-4942);
-  mpu.setZAccelOffset(4721);
-  mpu.setXGyroOffset(23);
-  mpu.setYGyroOffset(-11);
-  mpu.setZGyroOffset(44);
-#endif
-
-
-
-  // make sure it worked (returns 0 if so)
-  if (devStatus == 0) {
-    // turn on the DMP, now that it's ready
-#if defined LS_INFO
-    Serial.println(F("Enabling DMP..."));
-#endif
-    mpu.setDMPEnabled(true);
-
-    // enable Arduino interrupt detection
-#if defined LS_INFO
-    Serial.println(
-      F(
-        "Enabling interrupt detection (Arduino external interrupt 0)..."));
-#endif
-    //		attachInterrupt(0, dmpDataReady, RISING);
-    mpuIntStatus = mpu.getIntStatus();
-
-    // set our DMP Ready flag so the main loop() function knows it's okay to use it
-#if defined LS_INFO
-    Serial.println(F("DMP ready! Waiting for first interrupt..."));
-#endif
-    dmpReady = true;
-
-    // get expected DMP packet size for later comparison
-    packetSize = mpu.dmpGetFIFOPacketSize();
-  } else {
-    // ERROR!
-    // 1 = initial memory load failed
-    // 2 = DMP configuration updates failed
-    // (if it's going to break, usually the code will be 1)
-#if defined LS_INFO
-    Serial.print(F("DMP Initialization failed (code "));
-    Serial.print(devStatus);
-    Serial.println(F(")"));
-#endif
-  }
-
-  // configure the motion interrupt for clash recognition
-  // INT_PIN_CFG register
-  // in the working code of MPU6050_DMP all bits of the INT_PIN_CFG are false (0)
-  mpu.setDLPFMode(3);
-  mpu.setDHPFMode(0);
-  //mpu.setFullScaleAccelRange(3);
-  mpu.setIntMotionEnabled(true); // INT_ENABLE register enable interrupt source  motion detection
-  mpu.setIntZeroMotionEnabled(false);
-  mpu.setIntFIFOBufferOverflowEnabled(false);
-  mpu.setIntI2CMasterEnabled(false);
-  mpu.setIntDataReadyEnabled(false);
-  //  mpu.setMotionDetectionThreshold(10); // 1mg/LSB
-  mpu.setMotionDetectionThreshold(CLASH_THRESHOLD); // 1mg/LSB
-  mpu.setMotionDetectionDuration(2); // number of consecutive samples above threshold to trigger int
-  mpuIntStatus = mpu.getIntStatus();
-
-  /***** MP6050 MOTION DETECTOR INITIALISATION  *****/
-
-  /***** LED SEGMENT INITIALISATION  *****/
-
-  // initialize ledstrings segments
-  DDRD |= B01101000;
-  DDRB |= B00101110;
-
-  //We shut off all pins that could wearing leds,just to be sure
-  PORTD &= B10010111;
-  PORTB &= B11010001;
-
-#if defined STAR_LED
-  //initialise start color
-  getColor(storage.sndProfile[storage.soundFont].mainColor);
-#endif
-
-#if defined PIXELBLADE
-  pixels.setOutput(DATA_PIN); // This initializes the NeoPixel library.
-  pixelblade_KillKey_Disable();
-  currentColor.r = 0;
-  currentColor.g = 0;
-  currentColor.b = 0;
-  lightOn(currentColor);
-  delay(300);
-  lightOff();
-  getColor(storage.sndProfile[storage.soundFont].mainColor);
-  pixelblade_KillKey_Enable();
-#endif
-
-#if defined CLASHSTRING
-  pinMode(CLASHSTRING, OUTPUT);
-  FoCOff(CLASHSTRING);
-#endif
-
-#if defined ACCENT_LED
-  pinMode(ACCENT_LED, OUTPUT);
-#endif
-
-  //Randomize randomness (no really that's what it does)
-  randomSeed(analogRead(2));
-
-  /***** LED SEGMENT INITIALISATION  *****/
-
-  /***** BUTTONS INITIALISATION  *****/
-
-  // link the Main button functions.
-  mainButton.setClickTicks(CLICK);
-  mainButton.setPressTicks(PRESS_CONFIG);
-  mainButton.attachClick(mainClick);
-  mainButton.attachDoubleClick(mainDoubleClick);
-  mainButton.attachLongPressStart(mainLongPressStart);
-  mainButton.attachLongPressStop(mainLongPressStop);
-  mainButton.attachDuringLongPress(mainLongPress);
-
-#ifndef SINGLEBUTTON
-  // link the Lockup button functions.
-  lockupButton.setClickTicks(CLICK);
-  lockupButton.setPressTicks(PRESS_CONFIG);
-  lockupButton.attachClick(lockupClick);
-  lockupButton.attachDoubleClick(lockupDoubleClick);
-  lockupButton.attachLongPressStart(lockupLongPressStart);
-  lockupButton.attachLongPressStop(lockupLongPressStop);
-  lockupButton.attachDuringLongPress(lockupLongPress);
-#endif
-  /***** BUTTONS INITIALISATION  *****/
-
-
-  /***** Quick Mute *****/
-  if (digitalRead(MAIN_BUTTON) == LOW) {
-    if (storage.volume > 0) {
-      storage.volume = 0;
-      Serial.println("Muted");
-    }
-    else {
-      storage.volume = VOL;
-      Serial.println("Unmuted");
-    }
-    //    EEPROM.write(37, storage.volume); // comment this line to make mute setting temporary
-  }
-
-  while (digitalRead(MAIN_BUTTON) == LOW ) {
-    digitalWrite(ACCENT_LED, HIGH);
-    delay(100);
-    digitalWrite(ACCENT_LED, LOW);
-    delay(100);
-  }
-
-  /***** DF PLAYER INITIALISATION  *****/
-  InitDFPlayer();
-
-  delay(200);
-  pinMode(SPK1, INPUT);
-  pinMode(SPK2, INPUT);
-  SinglePlay_Sound(11);
-  delay(20);
-
-#ifdef DEEP_SLEEP
-  /************ DEEP_SLEEP MODE SETTINGS **********/
-  pinMode(MP3_PSWITCH, OUTPUT);
-  pinMode(FTDI_PSWITCH, OUTPUT);
-  digitalWrite(MP3_PSWITCH, LOW); // enable MP3 player with A0
-  digitalWrite(FTDI_PSWITCH, LOW); // enable FTDI player with A1
-  // pin change interrupt masks (see below list)
-  PCMSK2 |= bit (PCINT20);   // pin 4 Aux button
-  PCMSK0 |= bit (PCINT4);    // pin 12 Main button
-#endif // DEEP_SLEEP
-
-
-  /****** INIT SABER STATE VARIABLE *****/
-  SaberState = S_STANDBY;
-  PrevSaberState = S_SLEEP;
-  ActionModeSubStates = AS_HUM;
-}
-
-// ====================================================================================
-// ===               	   			LOOP ROUTINE  	 	                			===
-// ====================================================================================
-void loop() {
-
-  // if MPU6050 DMP programming failed, don't try to do anything : EPIC FAIL !
-  if (!dmpReady) {
-    return;
-  }
-
-  mainButton.tick();
-#ifndef SINGLEBUTTON
-  lockupButton.tick();
-#endif
-
-  /*//////////////////////////////////////////////////////////////////////////////////////////////////////////
-     ACTION MODE HANDLER
-  */ /////////////////////////////////////////////////////////////////////////////////////////////////////////
-  if (SaberState == S_SABERON) {
-    /*
-      // In case we want to time the loop
-      Serial.print(F("Action Mode"));
-      Serial.print(F(" time="));
-      Serial.println(millis());
-    */
-    if (ActionModeSubStates != AS_HUM) { // needed for hum relauch only in case it's not already being played
-      hum_playing = false;
-    }
-    else { // AS_HUM
-      if ((millis() - sndSuppress > HUM_RELAUNCH and not hum_playing)) {
-        HumRelaunch();
-      }
-    }
-
-    if (ActionModeSubStates == AS_IGNITION) {
-      /*
-          This is the very first loop after Action Mode has been turned on
-      */
-      //attachInterrupt(0, dmpDataReady, RISING);
-      // Reduce lockup trigger time for faster lockup response
-#ifndef SINGLEBUTTON
-      lockupButton.setPressTicks(PRESS_ACTION);
-#endif
-#if defined PIXELBLADE
-      pixelblade_KillKey_Disable();
-#endif
-#if defined LS_INFO
-      Serial.println(F("START ACTION"));
-#endif
-
-      //Play powerons wavs
-      SinglePlay_Sound(soundFont.getPowerOn());
-      // Light up the ledstrings
-#if defined LEDSTRINGS
-      lightIgnition(ledPins, soundFont.getPowerOnTime(),
-                    soundFont.getPowerOnEffect());
-#endif
-#if defined STAR_LED
-      lightIgnition(ledPins, currentColor, soundFont.getPowerOnTime());
-#endif
-#if defined PIXELBLADE
-      for (uint8_t i = 0; i <= 5; i++) {
-        digitalWrite(ledPins[i], HIGH);
-      }
-      lightIgnition(currentColor, soundFont.getPowerOnTime(), 0);
-
-#endif
-      sndSuppress = millis();
-      sndSuppress2 = millis();
-
-      // Get the initial position of the motion detector
-      motionEngine();
-      ActionModeSubStates = AS_HUM;
-      //ignition = true;
-
-#if defined ACCENT_LED
-      // turns accent LED On
-      accentLEDControl(AL_ON);
-      //digitalWrite(ACCENT_LED, HIGH);
-#endif
-    }
-
-    // ************************* blade movement detection ************************************
-    //Let's get our values !
-    motionEngine();
-
-    /*
-       CLASH DETECTION :
-       A clash is a violent deceleration when 2 blades hit each other
-       For a realistic clash detection it's imperative to detect
-       such a deceleration instantenously, which is only feasible
-       using the motion interrupt feature of the MPU6050.
-    */
-    if (mpuIntStatus > 60 and mpuIntStatus < 70 and ActionModeSubStates != AS_BLADELOCKUP) {
-
-#if defined LS_CLASH_DEBUG
-      Serial.print(F("CLASH\tmpuIntStatus="));
-      Serial.println(mpuIntStatus);
-#endif
-      if (lockuponclash) {
-        //if (ActionModeSubStates==AS_PREBLADELOCKUP or lockuponclash) {
-        //Lockup Start
-        ActionModeSubStates = AS_BLADELOCKUP;
-        if (soundFont.getLockup()) {
-          LoopPlay_Sound(soundFont.getLockup());
-          //sndSuppress = millis();
-          //while (millis() - sndSuppress < 50) {
-          //}
-          //Set_Loop_Playback();
-          //sndSuppress = millis();
-          //while (millis() - sndSuppress < 50) {
-          //}
-        }
-      }
-      else { // ordinary clash
-        if (millis() - sndSuppress >= CLASH_SUPRESS) {
-          //blink = 0;
-          //clash = CLASH_FLASH_TIME;
-          SinglePlay_Sound(soundFont.getClash());
-          sndSuppress = millis();
-          sndSuppress2 = millis();
-          /*
-             THIS IS A CLASH  !
-          */
-          ActionModeSubStates = AS_CLASH;
-#if defined STAR_LED
-          getColor(storage.sndProfile[storage.soundFont].clashColor);
-          lightOn(ledPins, currentColor);
-#endif
-#if defined LEDSTRINGS
-          for (uint8_t i = 0; i <= 5; i++) {
-            analogWrite(ledPins[i], 255);
-          }
-#endif
-#if defined PIXELBLADE
-#ifdef FIREBLADE  // simply flash white
-          getColor(14);
-          lightOn(currentColor);
-#else
-          getColor(storage.sndProfile[storage.soundFont].clashColor);
-          lightOn(currentColor);
-#endif
-#endif
-          delay(CLASH_FX_DURATION);  // clash duration
-
-        }
-      }
-    }
-    /*
-       SIMPLE BLADE MOVEMENT DETECTION FOR MOTION  TRIGGERED BLASTER FEDLECT
-       We detect swings as hilt's orientation change
-       since IMUs sucks at determining relative position in space
-    */
-    // movement of the hilt while blaster move deflect is activated can trigger a blaster deflect
-    else if ((ActionModeSubStates == AS_BLASTERDEFLECTPRESS or (ActionModeSubStates == AS_BLASTERDEFLECTMOTION and (abs(curDeltAccel.y) > soundFont.getSwingThreshold() // and it has suffisent power on a certain axis
-              or abs(curDeltAccel.z) > soundFont.getSwingThreshold()
-              or abs(curDeltAccel.x) > soundFont.getSwingThreshold()))) and (millis() - sndSuppress >= BLASTERBLOCK_SUPRESS)) {
-
-      if (soundFont.getBlaster()) {
-        SinglePlay_Sound(soundFont.getBlaster());
-#if defined LEDSTRINGS
-        blasterPin = random(1,5); //momentary shut off one led segment
-        blink = 0;
-        analogWrite(ledPins[blasterPin], LOW);
-#endif
-#if defined STAR_LED
-        getColor(storage.sndProfile[storage.soundFont].blasterboltColor);
-        lightOn(ledPins, currentColor);
-#endif //STAR_LED
-#if defined PIXELBLADE
-#ifdef FIREBLADE
-        getColor(14);
-        lightOn(currentColor);
-#else
-        lightOn(currentColor);
-        blasterPixel = random(NUMPIXELS / 4, NUMPIXELS - 3); //momentary shut off one led segment
-        blink = 0;
-        getColor(storage.sndProfile[storage.soundFont].blasterboltColor);
-        //            lightBlasterEffect(blasterPixel, 3, storage.sndProfile[storage.soundFont].mainColor);
-        lightBlasterEffect(blasterPixel, map(NUMPIXELS, 0, 120, 1, 3), storage.sndProfile[storage.soundFont].blasterboltColor);
-
-#endif
-#endif
-        delay(BLASTER_FX_DURATION);  // blaster bolt deflect duration
-        blaster = BLASTER_FLASH_TIME;
-        // Some Soundfont may not have Blaster sounds
-        if (millis() - sndSuppress > 50) {
-          //SinglePlay_Sound(soundFont.getBlaster());
-          sndSuppress = millis();
-        }
-      }
-    }
-    /*
-       SWING DETECTION
-       We detect swings as hilt's orientation change
-       since IMUs sucks at determining relative position in space
-    */
-    else if (
-      (ActionModeSubStates != AS_BLADELOCKUP or lockuponclash)// end lockuponclash event on a swing
-      and abs(curRotation.w * 1000) < 999 // some rotation movement have been initiated
-      and (
-#if defined BLADE_X
-
-        (
-          (millis() - sndSuppress > SWING_SUPPRESS) // The movement doesn't follow another to closely
-          and (abs(curDeltAccel.y) > soundFont.getSwingThreshold()  // and it has suffisent power on a certain axis
-               or abs(curDeltAccel.z) > soundFont.getSwingThreshold()
-               or abs(curDeltAccel.x) > soundFont.getSwingThreshold() * 10)
-        )
-        or (// A reverse movement follow a first one
-          (millis() - sndSuppress2 > SWING_SUPPRESS)   // The reverse movement doesn't follow another reverse movement to closely
-          // and it must be a reverse movement on Vertical axis
-          and (
-            abs(curDeltAccel.y) > abs(curDeltAccel.z)
-            and abs(prevDeltAccel.y) > soundFont.getSwingThreshold()
-            and (
-              (prevDeltAccel.y > 0
-               and curDeltAccel.y < -soundFont.getSwingThreshold())
-              or (
-                prevDeltAccel.y < 0
-                and curDeltAccel.y	> soundFont.getSwingThreshold()
-              )
-            )
-          )
-        )
-        or (// A reverse movement follow a first one
-          (millis() - sndSuppress2 > SWING_SUPPRESS)  // The reverse movement doesn't follow another reverse movement to closely
-          and ( // and it must be a reverse movement on Horizontal axis
-            abs(curDeltAccel.z) > abs(curDeltAccel.y)
-            and abs(prevDeltAccel.z) > soundFont.getSwingThreshold()
-            and (
-              (prevDeltAccel.z > 0
-               and curDeltAccel.z < -soundFont.getSwingThreshold())
-              or (
-                prevDeltAccel.z < 0
-                and curDeltAccel.z	> soundFont.getSwingThreshold()
-              )
-            )
-          )
-        )
-      )
-
-      // the movement must not be triggered by pure blade rotation (wrist rotation)
-      and not (
-        abs(prevRotation.x * 1000 - curRotation.x * 1000) > abs(prevRotation.y * 1000 - curRotation.y * 1000)
-        and
-        abs(prevRotation.x * 1000 - curRotation.x * 1000) > abs(prevRotation.z * 1000 - curRotation.z * 1000)
-      )
-
-#endif
-#if defined BLADE_Y
-      (
-        (millis() - sndSuppress > SWING_SUPPRESS) // The movement doesn't follow another to closely
-        and (abs(curDeltAccel.x) > soundFont.getSwingThreshold()  // and it has suffisent power on a certain axis
-             or abs(curDeltAccel.z) > soundFont.getSwingThreshold()
-             or abs(curDeltAccel.y) > soundFont.getSwingThreshold() * 10)
-      )
-      or (// A reverse movement follow a first one
-        (millis() - sndSuppress2 > SWING_SUPPRESS)   // The reverse movement doesn't follow another reverse movement to closely
-        // and it must be a reverse movement on Vertical axis
-        and (
-          abs(curDeltAccel.x) > abs(curDeltAccel.z)
-          and abs(prevDeltAccel.x) > soundFont.getSwingThreshold()
-          and (
-            (prevDeltAccel.x > 0
-             and curDeltAccel.x < -soundFont.getSwingThreshold())
-            or (
-              prevDeltAccel.x < 0
-              and curDeltAccel.x	> soundFont.getSwingThreshold()
-            )
-          )
-        )
-      )
-      or (// A reverse movement follow a first one
-        (millis() - sndSuppress2 > SWING_SUPPRESS)  // The reverse movement doesn't follow another reverse movement to closely
-        and ( // and it must be a reverse movement on Horizontal axis
-          abs(curDeltAccel.z) > abs(curDeltAccel.x)
-          and abs(prevDeltAccel.z) > soundFont.getSwingThreshold()
-          and (
-            (prevDeltAccel.z > 0
-             and curDeltAccel.z < -soundFont.getSwingThreshold())
-            or (
-              prevDeltAccel.z < 0
-              and curDeltAccel.z	> soundFont.getSwingThreshold()
-            )
-          )
-        )
-      )
-    )
-
-      // the movement must not be triggered by pure blade rotation (wrist rotation)
-      and not (
-        abs(prevRotation.y * 1000 - curRotation.y * 1000) > abs(prevRotation.x * 1000 - curRotation.x * 1000)
-        and
-        abs(prevRotation.y * 1000 - curRotation.y * 1000) > abs(prevRotation.z * 1000 - curRotation.z * 1000)
-      )
-#endif
-#if defined BLADE_Z
-      (
-        (millis() - sndSuppress > SWING_SUPPRESS) // The movement doesn't follow another to closely
-        and (abs(curDeltAccel.y) > soundFont.getSwingThreshold()  // and it has suffisent power on a certain axis
-             or abs(curDeltAccel.x) > soundFont.getSwingThreshold()
-             or abs(curDeltAccel.z) > soundFont.getSwingThreshold() * 10)
-      )
-      or (// A reverse movement follow a first one
-        (millis() - sndSuppress2 > SWING_SUPPRESS)   // The reverse movement doesn't follow another reverse movement to closely
-        // and it must be a reverse movement on Vertical axis
-        and (
-          abs(curDeltAccel.y) > abs(curDeltAccel.x)
-          and abs(prevDeltAccel.y) > soundFont.getSwingThreshold()
-          and (
-            (prevDeltAccel.y > 0
-             and curDeltAccel.y < -soundFont.getSwingThreshold())
-            or (
-              prevDeltAccel.y < 0
-              and curDeltAccel.y	> soundFont.getSwingThreshold()
-            )
-          )
-        )
-      )
-      or (// A reverse movement follow a first one
-        (millis() - sndSuppress2 > SWING_SUPPRESS)  // The reverse movement doesn't follow another reverse movement to closely
-        and ( // and it must be a reverse movement on Horizontal axis
-          abs(curDeltAccel.x) > abs(curDeltAccel.y)
-          and abs(prevDeltAccel.x) > soundFont.getSwingThreshold()
-          and (
-            (prevDeltAccel.x > 0
-             and curDeltAccel.x < -soundFont.getSwingThreshold())
-            or (
-              prevDeltAccel.x < 0
-              and curDeltAccel.x	> soundFont.getSwingThreshold()
-            )
-          )
-        )
-      )
-      )
-
-      // the movement must not be triggered by pure blade rotation (wrist rotation)
-      and not (
-        abs(prevRotation.z * 1000 - curRotation.z * 1000) > abs(prevRotation.y * 1000 - curRotation.y * 1000)
-        and
-        abs(prevRotation.z * 1000 - curRotation.z * 1000) > abs(prevRotation.x * 1000 - curRotation.x * 1000)
-      )
-#endif
-      ) { // end of the condition definition for swings
-
-
-
-      if ( ActionModeSubStates != AS_BLASTERDEFLECTMOTION and ActionModeSubStates != AS_BLASTERDEFLECTPRESS) {
-        /*
-            THIS IS A SWING !
-        */
-        prevDeltAccel = curDeltAccel;
-#if defined LS_SWING_DEBUG
-        Serial.print(F("SWING\ttime="));
-        Serial.println(millis() - sndSuppress);
-        Serial.print(F("\t\tcurRotation\tw="));
-        Serial.print(curRotation.w * 1000);
-        Serial.print(F("\t\tx="));
-        Serial.print(curRotation.x);
-        Serial.print(F("\t\ty="));
-        Serial.print(curRotation.y);
-        Serial.print(F("\t\tz="));
-        Serial.print(curRotation.z);
-        Serial.print(F("\t\tAcceleration\tx="));
-        Serial.print(curDeltAccel.x);
-        Serial.print(F("\ty="));
-        Serial.print(curDeltAccel.y);
-        Serial.print(F("\tz="));
-        Serial.println(curDeltAccel.z);
-#endif
-
-        ActionModeSubStates = AS_SWING;
-#ifndef FIREBLADE // FIREBLADE triggers false swings due to a random() function all, not yet understood
-        SinglePlay_Sound(soundFont.getSwing());
-#endif
-        /* NORMAL SWING */
-
-
-
-
-        if (millis() - sndSuppress > SWING_SUPPRESS) {
-          sndSuppress = millis();
-        }
-        if (millis() - sndSuppress2 > SWING_SUPPRESS) {
-          sndSuppress2 = millis();
-        }
-
-      }
-    }
-    else { // simply flicker
-      if (ActionModeSubStates != AS_BLASTERDEFLECTMOTION and ActionModeSubStates != AS_BLADELOCKUP) { // do not deactivate blaster move deflect mode in case the saber is idling
-        ActionModeSubStates = AS_HUM;
-      }
-      else if (ActionModeSubStates == AS_BLASTERDEFLECTMOTION) {
-        accentLEDControl(AL_PULSE);
-      }
-      // relaunch hum if more than HUM_RELAUNCH time elapsed since entering AS_HUM state
-      if (millis() - sndSuppress > HUM_RELAUNCH and not hum_playing and ActionModeSubStates != AS_BLADELOCKUP) {
-        HumRelaunch();
-      }
-#ifdef LEDSTRINGS
-      lightFlicker(ledPins, soundFont.getFlickerEffect(), 0, ActionModeSubStates);
-#endif
-
-#ifdef STAR_LED
-      getColor(storage.sndProfile[storage.soundFont].mainColor);
-      lightFlicker(ledPins, currentColor, 0);
-#endif
-
-#ifdef PIXELBLADE
-      getColor(storage.sndProfile[storage.soundFont].mainColor);
-      lightFlicker(0, ActionModeSubStates);
-#endif
-      if (lockuponclash) {
-        accentLEDControl(AL_PULSE);
-      }
-    }
-    // ************************* blade movement detection ends***********************************
-
-  } ////END ACTION MODE HANDLER///////////////////////////////////////////////////////////////////////////////////////
-
-
-  /*//////////////////////////////////////////////////////////////////////////////////////////////////////////
-     CONFIG MODE HANDLER
-  *//////////////////////////////////////////////////////////////////////////////////////////////////////////
-  else if (SaberState == S_CONFIG) {
-    if (PrevSaberState == S_STANDBY) { // entering config mode
-      PrevSaberState = S_CONFIG;
-      SinglePlay_Sound(3);
-      delay(600);
-
-#if defined PIXELBLADE
-      pixelblade_KillKey_Disable();
-#endif
-
-#if defined LS_INFO
-      Serial.println(F("START CONF"));
-#endif
-      enterMenu = true;
-#ifdef BATTERY_CHECK
-      ConfigModeSubStates = CS_BATTERYLEVEL;
-      //      int batLevel = 100 * (1 / batCheck() - 1 / LOW_BATTERY) / (1 / FULL_BATTERY - 1 / LOW_BATTERY);
-      int batLevel = 100 * ((batCheck() - LOW_BATTERY) / (FULL_BATTERY - LOW_BATTERY));
-      Serial.println(batLevel);
-      if (batLevel > 95) {        //full
-        SinglePlay_Sound(19);
-      } else if (batLevel > 60) { //nominal
-        SinglePlay_Sound(15);
-      } else if (batLevel > 30) { //diminished
-        SinglePlay_Sound(16);
-      } else if (batLevel > 0) {  //low
-        SinglePlay_Sound(17);
-      } else {                    //critical
-        SinglePlay_Sound(18);
-      }
-      BladeMeter(batLevel);
-      delay(500);
-#else
-      ConfigModeSubStates = CS_SOUNDFONT;
-      SinglePlay_Sound(5);
-      delay(500);
-#endif
-    }
-#ifndef COLORS
-#if defined(PIXELBLADE) or defined(STAR_LED)
-    if (ConfigModeSubStates == CS_MAINCOLOR or ConfigModeSubStates == CS_CLASHCOLOR or ConfigModeSubStates == CS_BLASTCOLOR) {
-      modification = GravityVector();
-      //Serial.println(modification);
-      switch (modification) {
-        case (0): // red +
-          currentColor.r = 100; currentColor.g = 0; currentColor.b = 0;
-          break;
-        case (1): // red -
-          currentColor.r = 20; currentColor.g = 0; currentColor.b = 0;
-          break;
-        case (2): // green +
-          currentColor.r = 0; currentColor.g = 100; currentColor.b = 0;
-          break;
-        case (3): // green -
-          currentColor.r = 0; currentColor.g = 20; currentColor.b = 0;
-          break;
-        case (4): // blue +
-          currentColor.r = 0; currentColor.g = 0; currentColor.b = 100;
-          break;
-        case (5): // blue -
-          currentColor.r = 0; currentColor.g = 0; currentColor.b = 20;
-          break;
-      }
-      #ifdef PIXELBLADE
-        lightOn(currentColor, NUMPIXELS - 5, NUMPIXELS);
-      #else if STAR_LED
-        //lightOn(currentColor, NUMPIXELS - 5, NUMPIXELS);
-      #endif
-    }
-#endif // PIXELBLADE or STAR_LED
-#endif // not COLORS
-
-  } //END CONFIG MODE HANDLER
-
-  /*//////////////////////////////////////////////////////////////////////////////////////////////////////////
-     STANDBY MODE
-  *//////////////////////////////////////////////////////////////////////////////////////////////////////////
-  else if (SaberState == S_STANDBY) {
-
-    if (ActionModeSubStates == AS_RETRACTION) { // we just leaved Action Mode
-      //detachInterrupt(0);
-
-      SinglePlay_Sound(soundFont.getPowerOff());
-      ActionModeSubStates = AS_HUM;
-      changeMenu = false;
-      //ignition = false;
-      //blasterBlocks = false;
-      modification = 0;
-#if defined LS_INFO
-      Serial.println(F("END ACTION"));
-#endif
-#ifndef SINGLEBUTTON
-      lockupButton.setPressTicks(PRESS_CONFIG);
-#endif
-#if defined STAR_LED
-      lightRetract(ledPins, currentColor, soundFont.getPowerOffTime());
-#endif
-#if defined LEDSTRINGS
-      lightRetract(ledPins, soundFont.getPowerOffTime(),
-                   soundFont.getPowerOffEffect());
-#endif
-#if defined PIXELBLADE
-      lightRetract(soundFont.getPowerOffTime(), soundFont.getPowerOffEffect());
-      pixelblade_KillKey_Enable();
-#endif
-
-    }
-    if (PrevSaberState == S_CONFIG) { // we just leaved Config Mode
-      saveConfig();
-      PrevSaberState = S_STANDBY;
-
-      /*
-         RESET CONFIG
-      */
-      //			for (unsigned int i = 0; i < EEPROMSizeATmega328; i++) {
-      //				//			 if (EEPROM.read(i) != 0) {
-      //				EEPROM.update(i, 0);
-      //				//			 }
-      //			}
-
-      SinglePlay_Sound(3);
-      //browsing = false;
-      enterMenu = false;
-      modification = 0;
-      //dfplayer.setVolume(storage.volume);
-      menu = 0;
-#if defined STAR_LED
-      getColor(storage.sndProfile[storage.soundFont].mainColor);
-#endif
-#if defined PIXELBLADE
-      getColor(storage.sndProfile[storage.soundFont].mainColor);
-#endif
-
-#if defined LS_INFO
-      Serial.println(F("END CONF"));
-#endif
-    }
-
-    // switch of light in Stand-by mode
-#if defined STAR_LED
-    lightOff(ledPins);
-#else
-    lightOff();
-#endif
-
-    accentLEDControl(AL_ON);
-
-
-
-  } // END STANDBY MODE
-#ifdef JUKEBOX
-  /*//////////////////////////////////////////////////////////////////////////////////////////////////////////
-     JUKEBOX MODE (a.k.a. MP3 player mode
-  *//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-  else if (SaberState == S_JUKEBOX) {
-    if (PrevSaberState == S_STANDBY) { // just entered JukeBox mode
-      PrevSaberState = S_JUKEBOX;
-      SinglePlay_Sound(14);  // play intro sound of JukeBox mode
-      delay(2500);
-#ifdef PIXELBLADE
-      pixelblade_KillKey_Disable();
-#endif
-#if defined LS_INFO
-      Serial.println(F("START JUKEBOX"));
-#endif
-      // start playing the first song
-      jb_track = NR_CONFIGFOLDERFILES + 1;
-      SinglePlay_Sound(jb_track);  // JukeBox dir/files must be directly adjecent to config sounds on the SD card
-    }
-    if (jukebox_play) {
-#ifdef LEDSTRINGS
-      JukeBox_Stroboscope(ledPins);
-#endif
-
-#ifdef STAR_LED
-      JukeBox_Stroboscope();
-#endif
-
-#ifdef PIXELBLADE
-      getColor(storage.sndProfile[storage.soundFont].mainColor);
-      JukeBox_Stroboscope(currentColor);
-#endif
-    }
-  }
-#endif  //  JUKEBOX
-#ifdef DEEP_SLEEP
-  else if (SaberState == S_SLEEP) {
-    if (PrevSaberState == S_CONFIG) { // just entered Sleep mode
-
-      byte old_ADCSRA = ADCSRA;
-      // disable ADC to save power
-      // disable ADC
-      ADCSRA = 0;  // reduces another ~100uA!
-      SleepModeEntry();
-
-      // .. and the code will continue from here
-
-      ADCSRA = old_ADCSRA;   // re-enable ADC conversion
-      SleepModeExit();
-      SaberState = S_STANDBY;
-      PrevSaberState = S_SLEEP;
-      // play boot sound
-      SinglePlay_Sound(11);
-      delay(20);
-    }
-  }
-#endif // DEEP_SLEEP
-} //loop
-
-// ====================================================================================
-// ===           	  			MOTION DETECTION FUNCTIONS	            			===
-// ====================================================================================
-inline void motionEngine() {
-  // if programming failed, don't try to do anything
-  if (!dmpReady)
-    return;
-
-  // wait for MPU interrupt or extra packet(s) available
-  //	while (!mpuInterrupt && mpuFifoCount < packetSize) {
-  //		/* other program behavior stuff here
-  //		 *
-  //		 * If you are really paranoid you can frequently test in between other
-  //		 * stuff to see if mpuInterrupt is true, and if so, "break;" from the
-  //		 * while() loop to immediately process the MPU data
-  //		 */
-  //	}
-  // reset interrupt flag and get INT_STATUS byte
-  mpuInterrupt = false;
-  mpuIntStatus = mpu.getIntStatus();
-
-  // get current FIFO count
-  mpuFifoCount = mpu.getFIFOCount();
-
-  // check for overflow (this should never happen unless our code is too inefficient)
-  if ((mpuIntStatus & 0x10) || mpuFifoCount == 1024) {
-    // reset so we can continue cleanly
-    mpu.resetFIFO();
-
-    // otherwise, check for DMP data ready interrupt (this should happen frequently)
-  } else if (mpuIntStatus & 0x02) {
-    // wait for correct available data length, should be a VERY short wait
-    while (mpuFifoCount < packetSize)
-      mpuFifoCount = mpu.getFIFOCount();
-
-    // read a packet from FIFO
-    mpu.getFIFOBytes(fifoBuffer, packetSize);
-
-    // track FIFO count here in case there is > 1 packet available
-    // (this lets us immediately read more without waiting for an interrupt)
-    mpuFifoCount -= packetSize;
-
-    //Making the last orientation the reference for next rotation
-    prevOrientation = curOrientation.getConjugate();
-    prevAccel = curAccel;
-
-    //retrieve current orientation value
-    mpu.dmpGetQuaternion(&curOrientation, fifoBuffer);
-    mpu.dmpGetAccel(&curAccel, fifoBuffer);
-    curDeltAccel.x = prevAccel.x - curAccel.x;
-    curDeltAccel.y = prevAccel.y - curAccel.y;
-    curDeltAccel.z = prevAccel.z - curAccel.z;
-
-    //We calculate the rotation quaternion since last orientation
-    prevRotation = curRotation;
-    curRotation = prevOrientation.getProduct(
-                    curOrientation.getNormalized());
-
-#if defined LS_MOTION_HEAVY_DEBUG
-    // display quaternion values in easy matrix form: w x y z
-    printQuaternion(curRotation);
-#endif
-
-  }
-} //motionEngine
-
-inline void dmpDataReady() {
-  mpuInterrupt = true;
-} //dmpDataReady
-
-#if defined LS_MOTION_DEBUG
-inline void printQuaternion(Quaternion quaternion) {
-  Serial.print(F("\t\tQ\t\tw="));
-  Serial.print(quaternion.w * 1000);
-  Serial.print(F("\t\tx="));
-  Serial.print(quaternion.x);
-  Serial.print(F("\t\ty="));
-  Serial.print(quaternion.y);
-  Serial.print(F("\t\tz="));
-  Serial.println(quaternion.z);
-} //printQuaternion
-#endif
-
-uint8_t GravityVector() {
-  uint8_t Orientation; // 0: +X, 1: -X, 2: +Y, 3: -Y, 4: +Z, 5: -Z
-  int16_t ax, ay, az;
-
-  //mpu.dmpGetAccel(&curAccel, fifoBuffer);
-  mpu.getAcceleration(&ax, &ay, &az);
-  //printAccel(ax, ay, az);
-  if (ax < 0) {
-    Orientation = 1; // -X
-  }
-  else {
-    Orientation = 0; // +X
-  }
-  if (abs(abs(ax) - 16000) > abs(abs(ay) - 16000)) {
-    if (ay < 0) {
-      Orientation = 3; // -Y
-    }
-    else {
-      Orientation = 2; // +Y
-    }
-  }
-  if ( (abs(abs(ay) - 16000) > abs(abs(az) - 16000)) and (abs(abs(ax) - 16000) > abs(abs(az) - 16000)) ) {
-    if (az < 0) {
-      Orientation = 5; // -Z
-    }
-    else {
-      Orientation = 4; // +Z
-    }
-  }
-  //Serial.print(F("\t\Orientation="));
-  //Serial.println(Orientation);
-  return Orientation;
-}
-
-//#if defined LS_MOTION_DEBUG
-//inline void printAccel(int16_t ax, int16_t ay, int16_t az) {
-//  Serial.print(F("\t\tx="));
-//  Serial.print(ax);
-//  Serial.print(F("\t\ty="));
-//  Serial.print(ay);
-//  Serial.print(F("\t\tz="));
-//  Serial.println(az);
-//} //printQuaternion
-//#endif
-
-// ====================================================================================
-// ===           	  			EEPROM MANIPULATION FUNCTIONS	            		===
-// ====================================================================================
-
-inline bool loadConfig() {
-  bool equals = true;
-  EEPROM.readBlock(configAdress, storage);
-  for (uint8_t i = 0; i <= 2; i++) {
-    if (storage.version[i] != CONFIG_VERSION[i]) {
-      equals = false;
-      Serial.println("Wrong config!");
-    }
-  }
-  Serial.println(storage.version);
-  return equals;
-} //loadConfig
-
-inline void saveConfig() {
-  EEPROM.updateBlock(configAdress, storage);
-#ifdef LS_DEBUG
-  // dump values stored in EEPROM
-  for (uint8_t i = 0; i < 255; i++) {
-    Serial.print(i); Serial.print("\t"); Serial.println(EEPROM.readByte(i));
-  }
-#endif
-} //saveConfig
-
-// ====================================================================================
-// ===                          SOUND FUNCTIONS                                     ===
-// ====================================================================================
-
-void HumRelaunch() {
-  LoopPlay_Sound(soundFont.getHum());
-  sndSuppress = millis();
-  hum_playing = true;
-}
-
-void SinglePlay_Sound(uint8_t track) {
-#ifdef OLD_DPFPLAYER_LIB
-  mp3_play_physical(track);
-#else // DFPlayer_LSOS
-  dfplayer.playPhysicalTrack(track);
-#endif
-}
-
-void LoopPlay_Sound(uint8_t track) {
-#ifdef OLD_DPFPLAYER_LIB
-  mp3_loop_play(track);
-#else // DFPlayer_LSOS
-  dfplayer.playSingleLoop(track);
-#endif
-}
-
-void Set_Volume() {
-#ifdef OLD_DPFPLAYER_LIB
-  mp3_set_volume (storage.volume);
-#else
-  dfplayer.setVolume(storage.volume); // Too Slow: we'll change volume on exit
-#endif
-  delay(50);
-}
-
-void Set_Loop_Playback() {
-#ifdef OLD_DPFPLAYER_LIB
-  mp3_single_loop(true);
-#else
-  dfplayer.setSingleLoop(true);;
-#endif
-}
-
-void InitDFPlayer() {
-#ifdef OLD_DPFPLAYER_LIB
-  mp3_set_serial (mp3player);  //set softwareSerial for DFPlayer-mini mp3 module
-  mp3player.begin(9600);
-  delay(50);
-  mp3_set_device(1); //playback from SD card
-  delay(50);
-  mp3_set_volume (storage.volume);
-#else
-  dfplayer.setSerial(DFPLAYER_TX, DFPLAYER_RX);
-  // AK 7.9.2016: if the storage.volume has no or invalid value, it will cause the
-  // sketch to repeat setup (reset itself) - up till now no idea why?
-  // this can happen if the EEPROM is erased (i.e. reflash of bootloader)
-  dfplayer.setVolume(storage.volume);
-
-  //setup finished. Boot ready. We notify !
-#endif
-}
-
-void Pause_Sound() {
-#ifdef OLD_DPFPLAYER_LIB
-  mp3_pause();
-#else
-  dfplayer.pause();
-#endif
-}
-
-void Resume_Sound() {
-#ifdef OLD_DPFPLAYER_LIB
-  mp3_play();
-#else
-  dfplayer.play();
-#endif
-}
-
-#ifdef DEEP_SLEEP
-// ====================================================================================
-// ===                          SLEEP MODE FUNCTIONS                                ===
-// ====================================================================================
-
-void sleepNow()         // here we put the arduino to sleep
-{
-
-    power_all_disable ();   // turn off all modules -> no measurable effect
-
-    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
-
-    sleep_enable();          // enables the sleep bit in the mcucr register
-                             // so sleep is possible. just a safety pin
-
-    // turn off brown-out enable in software -> no measurable effect
-    MCUCR = bit (BODS) | bit (BODSE);
-    MCUCR = bit (BODS);
-
-    PCIFR  |= bit (PCIF0) | bit (PCIF1) | bit (PCIF2);   // clear any outstanding interrupts
-    PCICR  |= bit (PCIE0) | bit (PCIE1) | bit (PCIE2);   // enable pin change interrupts
-
-    sleep_mode();            // here the device is actually put to sleep!!
-                             // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
-
-    sleep_disable();         // first thing after waking from sleep:
-                             // disable sleep...
-    detachInterrupt(0);      // disables interrupt 0 on pin 2 so the
-                             // wakeUpNow code will not be executed
-                             // during normal running time.
-
-}
-
-void SleepModeEntry() {
-  // switch off all LS channels
-  for (uint8_t i = 0; i < sizeof(ledPins); i++) {
-    digitalWrite(ledPins[i], LOW);
-  }
-  mpu.setSleepEnabled(true);
-//  dfplayer.sleep();
-  digitalWrite(A1, HIGH); // A1 to High
-  pinMode(DFPLAYER_RX, OUTPUT);
-  digitalWrite(DFPLAYER_RX, LOW);
-  pinMode(DFPLAYER_TX, OUTPUT);
-  digitalWrite(DFPLAYER_TX, LOW);
-  delay (300);
-  digitalWrite(A2, HIGH); // A2 to High
-  delay(100);     // this delay is needed, the sleep
-  //function will provoke a Serial error otherwise!!
-  sleepNow();     // sleep function called here
-}
-
-void SleepModeExit() {
-
-  // cancel sleep as a precaution
-  sleep_disable();
-  power_all_enable ();   // enable modules again
-  digitalWrite(A2, LOW); // A2 to Low
-  delay (300);
-  mpu.setSleepEnabled(false);
-  delay (300);
-  digitalWrite(A1, LOW); // A1 to Low
-  pinMode(DFPLAYER_RX, OUTPUT);
-  pinMode(DFPLAYER_TX, INPUT);
-  delay (300);
-  setup(); // redo all initializations
-}
-
-
-#endif // DEEP_SLEEP
-
-// ====================================================================================
-// ===                         BATTERY CHECKING FUNCTIONS                           ===
-// ====================================================================================
-
-
-float batCheck() {
-  float sum = 0;
-  analogReference(INTERNAL);
-  for (int i = 0; i < 10; i++) {
-    analogRead(BATTERY_READPIN);  // clear the reads after reference switch
-    delay(1);
-  }
-  // take a number of analog samples and add them up
-  for (int i = 0; i < 10; i++) {
-    sum += analogRead(BATTERY_READPIN);
-    delay(10);
-  }
-  float voltage = ((float)sum / 10 * BATTERY_FACTOR) / 1023.0;
-  analogReference(DEFAULT);
-  for (int i = 0; i < 10; i++) {
-    analogRead(BATTERY_READPIN);  // clear the reads after reference switch
-    delay(1);
-  }
-  Serial.print(F("Battery Level: ")); Serial.println(voltage);
-  return voltage;
-}


added I2C code, removed button debouncing, added repeated button messages after 500 ms pressed

--- explorad_inputDevice.ino
+++ explorad_inputDevice.ino
@@ -1,7 +1,8 @@
+#include <Wire.h>
+
 #include "inputType.h"
-#include <Bounce2.h>

-#define SerialOutputDevice Serial1
+#define SerialOutputDevice Serial// SerialDevice

 #define PIN_LEFT 0
 #define PIN_UP 1
@@ -11,97 +12,120 @@

 struct Button
 {
-  Button(const uint8_t pin, const EInputType button) :
-    debouncer_(),
-    button_(button)
+  Button(const uint8_t pinMask, const EInputType button) :
+    pinMask_(pinMask),
+    button_(button),
+    state_(true)
   {
-    pinMode(pin, INPUT_PULLUP);
-    debouncer_.attach(pin);
-    debouncer_.interval(bounceInterval_);
+  }
+  void update(uint8_t buttons)
+  {
+    bool newState = (buttons & pinMask_);
+    if (newState != state_)
+    {
+      state_ = newState;
+      if (state_ == false)
+      {
+        // button was pressed
+        SerialOutputDevice.printf("b %d 0\n", button_);
+        state_ = newState;
+        timer_ = 0;
+      }
+    }
+    else if ((state_ == false) && (timer_ >= repeatInterval_))
+    {
+      // repeat button press
+      timer_ = 0;
+      SerialOutputDevice.printf("b %d 1\n", button_);
+    }
+  }
+  const uint8_t pinMask_;
+  const EInputType button_;
+  bool state_;
+  elapsedMillis timer_;
+  static const uint32_t repeatInterval_;
+};
+
+const uint32_t Button::repeatInterval_ = 500;
+
+template<uint8_t bufSize = 10>
+struct SerialInputParser
+{
+  SerialInputParser(Stream& device) :
+    stream_(device)
+  {
+
   }
   void update()
   {
-    if(!debouncer_.update())
+    while(stream_.available())
     {
-      return;
-    }
-    int value = debouncer_.read();
-    if (value == LOW)
-    {
-      SerialOutputDevice.printf("b %d 0\n", button_);
+      parseChar(stream_.read());
     }
   }
-  Bounce debouncer_;
-  const EInputType button_;
-  static const uint8_t bounceInterval_;
+  void parseChar(char c)
+  {
+    if (c == '\n')
+    {
+      buf_[index_] = 0;
+      index_++;
+      parseLine();
+    }
+    else
+    {
+      if (index_ > (bufSize-2))
+      {
+        index_ = 0;
+        return;
+      }
+      buf_[index_] = c;
+      index_++;
+    }
+  }
+  void parseLine()
+  {
+    Serial.printf("received line \"%s\"\n", buf_);
+    index_ = 0;
+  }
+  char buf_[bufSize];
+  uint8_t index_;
+  Stream& stream_;
 };

-const uint8_t Button::bounceInterval_ = 5;
-
-//template<uint8_t bufSize = 10>
-//struct SerialInputParser
-//{
-//  SerialInputParser(Stream& device) :
-//    stream_(device)
-//  {
-//
-//  }
-//  void update()
-//  {
-//    while(stream_.available())
-//    {
-//      parseChar(stream_.read());
-//    }
-//  }
-//  void parseChar(char c)
-//  {
-//    if (c == '\n')
-//    {
-//      buf_[index_] = 0;
-//      index_++;
-//      parseLine();
-//    }
-//    else
-//    {
-//      if (index_ > (bufSize-2))
-//      {
-//        index_ = 0;
-//        return;
-//      }
-//      buf_[index_] = c;
-//      index_++;
-//    }
-//  }
-//  void parseLine()
-//  {
-//    Serial.printf("received line \"%s\"\n", buf_);
-//    index_ = 0;
-//  }
-//  char buf_[bufSize];
-//  uint8_t index_;
-//  Stream& stream_;
-//};
-//
 void setup()
 {
   Serial1.begin(9600);//, SERIAL_8N1);
+  Wire.begin();
 }

 void loop()
 {
-  static Button left(PIN_LEFT, eLeft);
-  static Button up(PIN_UP, eUp);
-  static Button right(PIN_RIGHT, eRight);
-  static Button down(PIN_DOWN, eDown);
-  static Button enter(PIN_ENTER, eEnter);
+  static elapsedMillis buttonTimer;
+  static const uint16_t buttonReadInterval = 50;
+  static Button left((1<<eLeft), eLeft);
+  static Button up((1<<eUp), eUp);
+  static Button right((1<<eRight), eRight);
+  static Button down((1<<eDown), eDown);
+  static Button enter((1<<eEnter), eEnter);

-//  static SerialInputParser<10> parser(Serial1);
+  static SerialInputParser<10> parser(Serial1);
+
+  if (buttonTimer >= buttonReadInterval)
+  {
+    buttonTimer -= buttonReadInterval;
+    Wire.requestFrom(0x38, 1);
+    while(Wire.available() == 0);
+    uint8_t buttons =  Wire.receive();
+    while(Wire.available())
+    {
+      Wire.receive();
+    }
+    left.update(buttons);
+    up.update(buttons);
+    right.update(buttons);
+    down.update(buttons);
+    enter.update(buttons);
+  }

-  left.update();
-  up.update();
-  right.update();
-  down.update();
-  enter.update();
-
-//  parser.update();
+  parser.update();
 }


Limited success: It is error-prone, but it can detect the LED and parse the morse characters.  The problem is that the time of blinks estimated in openFrameworks is too variable to make error-free judgements.

--- people/mikewesthad/Week4/Arduino/MorseAdvanced/MorseAdvanced.ino
+++ people/mikewesthad/Week4/Arduino/MorseAdvanced/MorseAdvanced.ino
@@ -7,11 +7,11 @@

 // These units are in seconds
-#define DOT_LENGTH 0.25;
+#define DOT_LENGTH 0.5;
 float dotLength = DOT_LENGTH;
 float dashLength = 3 * DOT_LENGTH;

-String message = "Calibration Calibration This Better Get Picked Up By openFrameworks.  EOM";
+String message = "Calibration Calibration Cali Cali Cali Cali This Better Get Picked Up By openFrameworks.  EOM";

 int led = 13;


analog write for all

analog write for all

--- src/neurite.ino
+++ src/neurite.ino
@@ -1116,9 +1116,9 @@
 		if (strcmp(token, "io") == 0) {
 			log_dbg("hit io, payload: %c\n\r", payload[0]);
 			if (payload[0] == '0')
-				digitalWrite(14, LOW);
+				analogWrite(14, 0);
 			else
-				digitalWrite(14, HIGH);
+				analogWrite(14, 1023);
 		}
 	}
 	if (strcmp(topic, nd->cfg.topic_from) == 0) {
@@ -1131,9 +1131,9 @@
 		    payload[5] == ' ' &&
 		    payload[6] == 'o')
 			if (payload[7] == 'n')
-				digitalWrite(14, LOW);
+				analogWrite(14, 0);
 			else
-				digitalWrite(14, HIGH);
+				analogWrite(14, 1023);
 	}
 	char *token = NULL;
 	char *msg = (char *)malloc(64);
@@ -1214,7 +1214,7 @@
 	log_dbg("called\n\r");
 	myservo.attach(13);
 	pinMode(14, OUTPUT);
-	digitalWrite(14, HIGH);
+	analogWrite(14, 1023);
 	ticker_user.attach_ms(20, ticker_user_task);
 }
 #endif


Commented out Serial print statements - prepping for data collection

--- src/CAN/CAN_receive_v2/CAN_receive_v2.ino
+++ src/CAN/CAN_receive_v2/CAN_receive_v2.ino
@@ -81,7 +81,7 @@
     {
         id = CAN.getCanId(); // get CAN ID
         CAN.readMsgBufID(&id, &dlc, data);    // read data,  len: data length, buf: data buf
-        Serial.println("\n------------------------------\n");
+//        Serial.println("\n------------------------------\n");

         // Increment counter (invalid messages are still received, so count them too)
         numReceived++;
@@ -90,9 +90,9 @@
         if (Authenticate())
         {
           // Display the message
-          PrintMessage();
+//          PrintMessage();

-          Serial.println("\nAUTHENTICATION SUCCESSFUL");
+//          Serial.println("\nAUTHENTICATION SUCCESSFUL");
           TakeAction();     // only respond to authorized messages
         }
     }
@@ -191,13 +191,13 @@
     uint8_t keyLen;
     GetKey(id, &key[0], keyLen);

-    Serial.print("Expected Key: ");
-    for(int i = 0; i < keyLen; i++)
-    {
-        Serial.print(key[i]);
-        Serial.print(" ");
-    }
-    Serial.println();
+//    Serial.print("Expected Key: ");
+//    for(int i = 0; i < keyLen; i++)
+    {
+//        Serial.print(key[i]);
+//        Serial.print(" ");
+//    }
+//    Serial.println();

     // Generate the correct hash according to the data
     spritz_mac(&correct_hash[0], HASH_LEN, &data[0], dlc, &key[0], keyLen);
@@ -224,23 +224,23 @@
     }

     // Print the incoming_hash
-    Serial.print("Received Hash: ");
-    for (int i = 0; i < HASH_LEN; i++)
-    {
-        if (incoming_hash[i] < 0x10)
-          Serial.print('0');
-        Serial.print(incoming_hash[i], HEX);
-        Serial.print(' ');
-    }
-    Serial.print("\nExpected Hash: ");
-    for(int i = 0; i < HASH_LEN; i++)
-    {
-      if (correct_hash[i] < 0x10)
-        Serial.print('0');
-      Serial.print(correct_hash[i], HEX);
-      Serial.print(' ');
-    }
-    Serial.println();
+//    Serial.print("Received Hash: ");
+//    for (int i = 0; i < HASH_LEN; i++)
+//    {
+//        if (incoming_hash[i] < 0x10)
+//          Serial.print('0');
+//        Serial.print(incoming_hash[i], HEX);
+//        Serial.print(' ');
+//    }
+//    Serial.print("\nExpected Hash: ");
+//    for(int i = 0; i < HASH_LEN; i++)
+//    {
+//      if (correct_hash[i] < 0x10)
+//        Serial.print('0');
+//      Serial.print(correct_hash[i], HEX);
+//      Serial.print(' ');
+//    }
+//    Serial.println();
     return (spritz_compare(&correct_hash[0], &incoming_hash[0], HASH_LEN) == 0);
 }

@@ -262,10 +262,10 @@
     else if (id == ENGINE_ID)
       lastStamp = &engine_timestamp;

-    Serial.print("Received Timestamp: ");
-    Serial.println(ms);
-    Serial.print("Last Timestamp: ");
-    Serial.println(*lastStamp);
+//    Serial.print("Received Timestamp: ");
+//    Serial.println(ms);
+//    Serial.print("Last Timestamp: ");
+//    Serial.println(*lastStamp);

     if (*lastStamp > ms) // ms must have exceded max value and started over
     {


minor enhancement on the gui

minor enhancement on the gui

--- Margoulineur2000.ino
+++ Margoulineur2000.ino
@@ -262,10 +262,10 @@
             }
           }
           else if (dormitory == 4)
-          {
               nfc_handler.success = nfc.mifareclassic_AuthenticateBlock (nfc_handler.uid, nfc_handler.uidLength, nfc_handler.currentblock, nfc_handler.keyNumber, nfc_handler.KeyA_D4);
-          }
-
+          else if (dormitory == 13)
+              nfc_handler.success = nfc.mifareclassic_AuthenticateBlock (nfc_handler.uid, nfc_handler.uidLength, nfc_handler.currentblock, nfc_handler.keyNumber, nfc_handler.KeyA_D4);
+
           Serial.println("");
           if (nfc_handler.success)
             nfc_handler.authenticated = true;
@@ -351,25 +351,26 @@
       Serial.println("Ooops ... this doesn't seem to be a Mifare Classic card!");
   }
   lcd.clear();
-  lcd.print("Balance :");
-  lcd.setCursor(0,1);
-  if (!mode)
-  {
+  lcd.setCursor(0,0);
+  if (!mode && nfc_handler.success)
+  {
+    lcd.print("Balance :");
     lcd.print(nfc_handler.currentBalance / 100);
     Serial.println(nfc_handler.currentBalance, DEC);
   }
-  else
-  {
-
+  else if (mode && nfc_handler.success)
+  {
+    lcd.print("New balance :");
     dormitory == 3 ? lcd.print(nfc_handler.newBalance / 100) : lcd.print("40");
     dormitory == 3 ? Serial.println(nfc_handler.newBalance, DEC) : Serial.println(40, DEC);
   }
-  Serial.println("\n\nDONE ! waiting 4 the button");
-  !mode ? digitalWrite(readLedPin, LOW) : digitalWrite(writeLedPin, LOW);
+  else
+  {
+      lcd.print("Something went");
+      lcd.setCursor(0,1);
+      lcd.print("wrong");
+  }
   wait4button();
-  lcd.clear();
-  Serial.print("end read = ");Serial.println(oldPosition);
-
   Serial.flush();
 }

@@ -383,8 +384,14 @@

 void wait4button()
 {
+  Serial.println("\n\nDONE ! waiting 4 the button");
+  digitalWrite(readLedPin, LOW);
+  digitalWrite(writeLedPin, LOW);
   while(digitalRead(encButton))
   {
   }
   delay(500);
-}
+  Serial.print("end read = ");Serial.println(oldPosition);
+  lcd.clear();
+
+}


swap pm10 and pm2.5 (#88)

swap pm10 and pm2.5 (#88)

--- files/template_home_wifi_feinstaub/template_home_wifi_feinstaub.ino
+++ files/template_home_wifi_feinstaub/template_home_wifi_feinstaub.ino
@@ -260,8 +260,8 @@
     pm25 = 0;
     pm10 = 0;
   }
+  addValue(pm10);
   addValue(pm25);
-  addValue(pm10);

   submitValues();


RX filter not needed on 2nd radio

RX filter not needed on 2nd radio

--- Arduino/V0p2_Main/V0p2_Main.ino
+++ Arduino/V0p2_Main/V0p2_Main.ino
@@ -277,7 +277,7 @@
   // Check that the radio is correctly connected; panic if not...
   if(!SecondaryRadio.configure(1, &SecondaryRadioConfig) || !SecondaryRadio.begin()) { panic(); }
   // Apply filtering, if any, while we're having fun...
-  SecondaryRadio.setFilterRXISR(FilterRXISR);
+//  SecondaryRadio.setFilterRXISR(FilterRXISR); // Assume no RX on secondary radio.
 #endif // ENABLE_RADIO_SECONDARY_MODULE


[SRLatchFlipper] fix source reference

[SRLatchFlipper] fix source reference


#18 add battery status display during pano

Also earmarked a few more pins for future devices.

--- pano-controller.ino
+++ pano-controller.ino
@@ -26,9 +26,15 @@
 #define CAMERA_FOCUS 0
 #define CAMERA_SHUTTER 1

+#define BATTERY A0
+
 #define JOYSTICK_X A3
 #define JOYSTICK_Y A2
 #define JOYSTICK_SW 2
+
+#define REMOTE_IN 3
+#define COMPASS_DRDY 4
+#define MPU_INT 7

 #define MOTOR_STEPS 200
 #define MOTORS_ON 13
@@ -52,9 +58,28 @@
 int horiz, vert;
 volatile int running;

+// Battery measurement settings
+// R1/R2 is the voltage divisor in Ω (GND-R1-A0-R2-Vcc)
+// actual measured values will yield a more accurate voltage
+#define BATT_R1 9980
+#define BATT_R2 46500
+#if defined(__AVR__)
+#define VCC 5000
+#else
+#define VCC 3300
+#endif
+#define BATT_RANGE (VCC * (BATT_R1 + BATT_R2) / BATT_R1)

 void setup() {
     Serial.begin(38400);
+
+    pinMode(REMOTE_IN, INPUT_PULLUP);
+    pinMode(COMPASS_DRDY, INPUT_PULLUP);
+    pinMode(MPU_INT, INPUT_PULLUP);
+
+    pinMode(BATTERY, INPUT);
+    analogReadRes(10);
+    analogReadAveraging(32);

     horiz_motor.setMicrostep(32);
     vert_motor.setMicrostep(32);
@@ -69,6 +94,19 @@
     Serial.println(F("Ready\n"));
 }

+int readBattery(void){
+    return map(analogRead(BATTERY), 0, (1<<10)-1, 0, BATT_RANGE);
+}
+
+void displayBatteryStatus(void){
+    int battmV = readBattery();
+    display.print(F("Battery "));
+    display.print(battmV/1000);
+    display.print('.');
+    display.print(battmV/10 % 100);
+    display.println('V');
+}
+
 /*
  * Display current panorama status (photo index, etc)
  */
@@ -85,6 +123,7 @@
     display.print(F(" x "));
     display.println(1+pano.getCurCol());
     displayPanoSize();
+    displayBatteryStatus();
     displayProgress();
     display.display();
 }


Update ArduinoSmartShieldIrrigationController.ino

Finished coding around the configurable pump.  Added a feature where the configurable pump tile will turn blue (on) when its automatically turned on during an irrigation run.  In the previous release, it only turned blue when it was manually switched on or off.

--- ArduinoSmartShieldIrrigationController.ino
+++ ArduinoSmartShieldIrrigationController.ino
@@ -413,6 +413,7 @@
   t.stop(stationTimer[trafficCop]); // Kill any previously started timers.
   stationTimer[trafficCop] = t.after (stationTime[trafficCop],toggleOff);
   scheduleUpdate();
+  schedulePumpUpdate();
 }
 void toggleOff() {
   digitalWrite(relay[trafficCop], relayOff);
@@ -432,6 +433,7 @@
   }
   trafficCop=0; //ready to check queue or watch for new commmonds
   scheduleUpdate();
+  schedulePumpUpdate();
 }

 //added allOff as requirement of SmartThings switch capability.
@@ -454,10 +456,12 @@
   smartthing.shieldSetLED(0, 0, 1);
   trafficCop=0;
   scheduleUpdate();
+  schedulePumpUpdate();
 }

 void timeToUpdate() {
   scheduleUpdate();
+  schedulePumpUpdate();
 }

 int maxvalue () {


Revised sketch to improve slope trigger sensitivity,
when display is running in scope mode

Signed-off-by: jmhrvy <6a3cd8a1b2d47d05877db3d1fefa06cbe0a9a3f0@epbfi.com>

--- CNCSpindleSpeedControl/CNCSpindleSpeedControl.ino
+++ CNCSpindleSpeedControl/CNCSpindleSpeedControl.ino
@@ -89,12 +89,13 @@
 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //initialize Sansmart LCD Display
 LCDKeypad Keypad;
 int trgtRPM = 5000;
-unsigned long timeval = 0;
+unsigned long LstIntTime = 0;
 unsigned long Start = 0;
 unsigned long Stop;
 unsigned long WaitInterval =0;
 unsigned long startPrgm = millis()/1000;
-unsigned long now;
+unsigned long now;
+unsigned long QrtrSecTimeOut = millis() ;
 int SampleCnt = 10; // Number Spindle Relolutions needed to make a new RPM calculation
 unsigned long period;
 unsigned long Maxperiod;
@@ -133,6 +134,7 @@
 bool NewTrgtVal = true; //used to determine if display needs updating
 bool ExitNow = false;
 bool NuInput = true;
+bool ActivIntrpt = false;
 //char *intFlgStat;
 //int ThrtlLpCnt= 0;
 //int Startup = 0; // Locks out pid calcs on startup to give the default throttle setting a chance to take effect before correcting it
@@ -257,11 +259,13 @@
 {
 //   detachInterrupt(InterruptId);
    unsigned long ThisIntTime = micros();
+   LstIntTime = millis();
    if (ThisIntTime < WaitInterval) return;
    WaitInterval = ThisIntTime+3000; //move the next valid interrupt out by 3 milliSeconds (the squivalent of the spindle turning @ 20K RPM )
    if (eventCounter == 1)
      {
       Start = ThisIntTime;
+      ActivIntrpt = true;
      }
    if (eventCounter == SampleCnt+1)
      {
@@ -270,6 +274,7 @@
    eventCounter +=1;
    if (eventCounter >= SampleCnt+2)
     {
+    //ActivIntrpt = false;
     if (period ==0) sprintf (buf,"Too Small");
     else
      {
@@ -343,8 +348,10 @@
 // ================================================================
 void loop()
 {
-  int UsrInput = 0;
+  //int UsrInput = 0;
   int stopCnt = 0;
+  bool UpdtDis = false;
+  unsigned long CurPrdTime;
   lcd.setCursor(0,1);
   lcd.print("Speed Cntl Ready");
   lcd.setCursor(0,0);
@@ -354,35 +361,35 @@
   //then LCD setup seemed to go OK, & you're ready to start the speed control stuff

   // Calc initial dutycycle based on trgtRPM
-   SpndlPWM = (int) 95.0*(trgtRPM/9800.0)*(trgtRPM/9800.0) ; //190.5*(trgtRPM/9800.0)*(trgtRPM/9800.0)
-
-   // display counter value every 1/4 second.
+  // SpndlPWM = (int) 95.0*(trgtRPM/9800.0)*(trgtRPM/9800.0) ; //190.5*(trgtRPM/9800.0)*(trgtRPM/9800.0)
+
+  // display counter value every 1/4 second.
   //sprintf (buf, "Time %d Max %d\n", TotalRunTime, MaxRunTime);
   //Serial1.println(buf);
   while ( TotalRunTime <= MaxRunTime && !ExitNow )
   {
-
-    if(micros()-Start>=Maxperiod ){// if true, it looks like the motor isn't turning
+    CurPrdTime = millis()-LstIntTime;
+     //Serial.println(CurPrdTime);
+    if(CurPrdTime >= Maxperiod/1000 ){// if true, it looks like the motor isn't turning
+
       eventCounter = 0;
       LoopCounter = 0;
-      Start = micros();
+      LstIntTime = millis();
       NewTrgtVal = true;
-    }
-    while (eventCounter == 0 && LoopCounter == 0 &&  TotalRunTime <= MaxRunTime && !ExitNow)
+      ActivIntrpt = false;
+    }
+    //while (eventCounter == 0 && LoopCounter == 0 &&  TotalRunTime <= MaxRunTime && !ExitNow)
+     while (!ActivIntrpt &&  TotalRunTime <= MaxRunTime && !ExitNow)
      {
       //Motor is not running, So initialize PID for next startup
       //SpndlPWM = (int) 190.5*(trgtRPM/9800.0)*(trgtRPM/9800.0) ;
       ResetSpindle();
       SpndlPWM = 15;
-//      SetPoint = 2000;
-//      ITerm = 0.0; //kill any residual Integral component that might be left over from a previous run
-//      lastTime = millis();// reset/establish time mark for initial PID calculation
-//      analogWrite(PWMpin, SpndlPWM); //start the PWM output
       //sprintf (buf, "PWMpin:%02i PWM:%02i", PWMpin, SpndlPWM);
       //Serial.println(buf);
-      //Startup, in this version of the code is not used
-      //Startup = 60; // Locks out pid calcs on startup to give the default throttle setting a chance to take effect before correcting it
-      delay(100);
+      //delay(100);
+      UpdtDis = ScanButtons();
+
       if (NewTrgtVal)
        {
          lcd.setCursor(0,0); //lcd.setCursor(pos,line)
@@ -392,14 +399,9 @@
          lcd.print("Speed Cntl Ready");
          NewTrgtVal = false;
        }
-      UsrInput =  ScanButtons();
-      UpDateSettings(UsrInput, Mode);
-      while (Mode == 3){// Run Scope Mode Routine
-      ScopeMode();
-      UsrInput =  ScanButtons();
-      UpDateSettings(UsrInput, Mode);
+      if (Mode == 3){// Run Scope Mode Routine
+        ScopeMode();
       }
-
       long TotalRunTime = calcruntime();
       //SuspectRdCnt = 3;
       stopCnt = stopCnt+1;
@@ -412,54 +414,57 @@
       lcd.print(buf);
       NewTrgtVal = false;
     }
-   lcd.setCursor(0,1);//lcdPosition (lcdHandle, 0, 1) ;
-   if (Mode == 7) // Original Display Mode; Show Measured RPM, on the 2nd line
-    {
-     //lcdPrintf (lcdHandle, "Actl RPM: %d  ", calcrpm) ;
-     sprintf (buf, "%s %04i  ", "Actl RPM:", calcrpm);
-     lcd.print(buf);
-    }
-   if (Mode == 5) // Display Duty Cycle Mode
-    {
-     char DsplyStr[16];
-     char BlnkChr [1];
-     sprintf(DsplyStr, "Duty Cycle: %d ", dutycycle );// convert SpdEr to a String
-     strncpy( BlnkChr, " ", 1);// now fill out the rest of the display message/line with Blanks
-                               //[to ensure previous message has been erased
-     while (strlen(DsplyStr)<16)
+    if (UpdtDis){
+      lcd.setCursor(0,1);//lcdPosition (lcdHandle, 0, 1) ;
+     if (Mode == 7) // Original Display Mode; Show Measured RPM, on the 2nd line
       {
-       strcat(DsplyStr, BlnkChr);
+       //lcdPrintf (lcdHandle, "Actl RPM: %d  ", calcrpm) ;
+       sprintf (buf, "%s %04i  ", "Actl RPM:", calcrpm);
+       lcd.print(buf);
       }
-     //lcdPrintf (lcdHandle,"%s", DsplyStr);
-     //sprintf (buf, "%s %04i ", "Actl RPM:", calcrpm);
-     lcd.print(DsplyStr);
-    }
-   if (Mode == 6) // show Speed error Mode
-    {
-     char SpdErStr[6];
-     char SgndErStr[8];
-     char *pntr;
-     int SpdEr =  calcrpm-trgtRPM;
-     sprintf(SpdErStr, "%d",SpdEr );// convert SpdEr to a String
-     pntr = strchr (SpdErStr, '-');
-     if(pntr == NULL)
+     if (Mode == 5) // Display Duty Cycle Mode
       {
-       strncpy(SgndErStr, " +", 8);
-       strcat(SgndErStr, SpdErStr);
+       char DsplyStr[16];
+       char BlnkChr [1];
+       sprintf(DsplyStr, "Duty Cycle: %d ", dutycycle );// convert SpdEr to a String
+       strncpy( BlnkChr, " ", 1);// now fill out the rest of the display message/line with Blanks
+                                 //[to ensure previous message has been erased
+       while (strlen(DsplyStr)<16)
+        {
+         strcat(DsplyStr, BlnkChr);
+        }
+       //lcdPrintf (lcdHandle,"%s", DsplyStr);
+       //sprintf (buf, "%s %04i ", "Actl RPM:", calcrpm);
+       lcd.print(DsplyStr);
       }
-     else
+     if (Mode == 6) // show Speed error Mode
       {
-       strncpy(SgndErStr, " ", 8);
-       strcat(SgndErStr, SpdErStr);
+       char SpdErStr[6];
+       char SgndErStr[8];
+       char *pntr;
+       int SpdEr =  calcrpm-trgtRPM;
+       sprintf(SpdErStr, "%d",SpdEr );// convert SpdEr to a String
+       pntr = strchr (SpdErStr, '-');
+       if(pntr == NULL)
+        {
+         strncpy(SgndErStr, " +", 8);
+         strcat(SgndErStr, SpdErStr);
+        }
+       else
+        {
+         strncpy(SgndErStr, " ", 8);
+         strcat(SgndErStr, SpdErStr);
+        }
+       strncpy( SpdErStr, " ", 6);
+       while (strlen(SgndErStr)<8)
+        {
+         strcat(SgndErStr, SpdErStr);
+        }
+       //lcdPrintf (lcdHandle, "Spd Err:%s", SgndErStr ) ;
+       sprintf (buf, "%s%s ", "Spd Err:", SgndErStr);
+       lcd.print(buf);
       }
-     strncpy( SpdErStr, " ", 6);
-     while (strlen(SgndErStr)<8)
-      {
-       strcat(SgndErStr, SpdErStr);
-      }
-     //lcdPrintf (lcdHandle, "Spd Err:%s", SgndErStr ) ;
-     sprintf (buf, "%s%s ", "Spd Err:", SgndErStr);
-     lcd.print(buf);
+
     }
 // ############ Begin BarGraph Mode #################
    if (Mode == 4)// PWM Bar Graph Mode
@@ -469,6 +474,7 @@
      int postn = 0;
      int remainder = 0;
      int rowWeight;
+     lcd.setCursor(0,1);//lcdPosition (lcdHandle, 0, 1) ;
      FullCell =  100/16;//(Maxdutycycle - Mindutycycle)/16;
      rowWeight = FullCell/5;
 //   First, fill in the whole spaces
@@ -522,20 +528,8 @@
    }
 // ############ End O-Scope Mode #################

-   UsrInput =  ScanButtons();
-   UpDateSettings(UsrInput, Mode);
-   delay( 250 ); // wait 1/4 second(s)
-    LoopCounter = LoopCounter + 1;
-
-    if (LoopCounter >= 8)
-     {
-      LoopCounter = 0;
-      eventCounter = 0;
-//      TooHighCnt = 0;
-//      TooLowCnt = 0;
-      NewTrgtVal = true;
-      //Serial1.print("Looks as if Motor has Stopped\n");
-     }
+
+   UpdtDis = ScanButtons();
    long TotalRunTime = calcruntime();
   } //end of 1st while loop
  //kill the PWM signal
@@ -645,17 +639,24 @@
 // ================================================================

-static int ScanButtons()
-{
-  int buttons = 0;
-  int buttonPressed = Keypad.button();
-  if (buttonPressed==KEYPAD_UP) buttons += 1;
-  if (buttonPressed==KEYPAD_DOWN) buttons += 2;
-  if (buttonPressed==KEYPAD_LEFT) buttons += 4;
-  if (buttonPressed==KEYPAD_RIGHT) buttons += 8;
-  if (buttonPressed==KEYPAD_SELECT) buttons += 16;
-  if (buttonPressed==KEYPAD_NONE) NuInput = true;
-  return buttons;
+bool ScanButtons()
+{
+  if (millis()-QrtrSecTimeOut >250){
+    QrtrSecTimeOut = millis();
+    int buttons = 0;
+    int buttonPressed = Keypad.button();
+    if (buttonPressed==KEYPAD_UP) buttons += 1;
+    if (buttonPressed==KEYPAD_DOWN) buttons += 2;
+    if (buttonPressed==KEYPAD_LEFT) buttons += 4;
+    if (buttonPressed==KEYPAD_RIGHT) buttons += 8;
+    if (buttonPressed==KEYPAD_SELECT) buttons += 16;
+    if (buttonPressed==KEYPAD_NONE) NuInput = true;
+    //return buttons;
+    LoopCounter = LoopCounter + 1;
+    UpDateSettings(buttons, Mode);
+    return true;
+  }
+  else return false;
 }

 void UpDateSettings(int UsrInput, int mode)
@@ -664,33 +665,33 @@
     {
       if(UsrInput == 1 || UsrInput == 2) //[Display Up or Down Button]  Speed, $
        {
-         if (mode == 3)
-          {
-           if(UsrInput == 1 )
-            {
-             if (BackLight <7)
-              {
-               BackLight = BackLight+1;
-              }
-             else
-              {
-               BackLight = 1;
-              }
-            }
-           else
-            {
-             if (BackLight >1)
-              {
-               BackLight = BackLight-1;
-              }
-             else
-              {
-               BackLight = 7;
-              }
-            }
-           //setBacklightColour (BackLight) ;
-          }
-         else
+//         if (mode == 3)
+//          {
+//           if(UsrInput == 1 )
+//            {
+//             if (BackLight <7)
+//              {
+//               BackLight = BackLight+1;
+//              }
+//             else
+//              {
+//               BackLight = 1;
+//              }
+//            }
+//           else
+//            {
+//             if (BackLight >1)
+//              {
+//               BackLight = BackLight-1;
+//              }
+//             else
+//              {
+//               BackLight = 7;
+//              }
+//            }
+//           //setBacklightColour (BackLight) ;
+//          }
+//         else
           {
            NewTrgtVal = true;
            if(UsrInput == 1 )
@@ -795,9 +796,11 @@
   AsmplCnt =0;
   int uSWait = (int)((period/(SampleCnt*10))-900)/8; // returns the number of micro seconds to wait/sample to collect 80 data points given the current spindle speed
 //      Serial.println("Mode3");
+  if (!ActivIntrpt) KeepWaiting = !KeepWaiting;
   while(eventCounter == 0 & KeepWaiting){
     LoopTime = micros()-GoNow;
     if (LoopTime > 300000){
+      ActivIntrpt = false;
       KeepWaiting = false;
     }
   }
@@ -805,6 +808,7 @@

     LoopTime = micros()-GoNow;
     if (LoopTime > 300000){
+       ActivIntrpt = false;
       KeepWaiting = false;
     }
   }


fixed offset

fixed offset

--- zamek.ino
+++ zamek.ino
@@ -58,7 +58,7 @@

 const int lockTransitionTime = 2000; // in microseconds

-const int debounceDelay = 50; // miliseconds
+const int debounceDelay = 200; // miliseconds
 const int remoteDelay = 2000;

 bool isDoorLocked = true; //assumed state of door lock on uC power on
@@ -183,7 +183,7 @@
 }

 #ifdef STASZEK_MODE
-	const int offset = 3;
+	const int offset = 0;
 #else
 	const int offset = 1;
 #endif


QTRRCExample.ino: Fixed a type (ot).

QTRRCExample.ino: Fixed a type (ot).

--- QTRSensors/examples/QTRRCExample/QTRRCExample.ino
+++ QTRSensors/examples/QTRRCExample/QTRRCExample.ino
@@ -7,7 +7,7 @@

 // The setup phase of this example calibrates the sensor for ten seconds and turns on
 // the pin 13 LED while calibration is going on.  During this phase, you should expose each
-// reflectance sensor ot the lightest and darkest readings they will encounter.  For
+// reflectance sensor to the lightest and darkest readings they will encounter.  For
 // example, if you are making a line follower, you should slide the sensors across the
 // line during the calibration phase so that each sensor can get a reading of how dark the
 // line is and how light the ground is.  Improper calibration will result in poor readings.


code optimisation

code optimisation

--- Vsens/src/sketch.ino
+++ Vsens/src/sketch.ino
@@ -35,7 +35,7 @@
 void setup()
 {
   pinMode(activityLED, OUTPUT);    // An LED to signal activity
-  Serial.begin(9600);     // Initialise serial port
+  Serial.begin(9600);             // Initialise serial port
 }

 void loop()
@@ -44,21 +44,21 @@
   digitalWrite(activityLED, HIGH)
   sumSamples = 0;

-  // Add up the pre-defined number of samples for Sample Averaging
+  // *** Add up the pre-defined number of samples for Sample Averaging
   for (cntSamples = 0; cntSamples <= numSamples; cntSamples++) {
     sumSamples += analogRead(measurePin);
     delay(10);
   }

-  // Determine the source voltage:
+  // *** Determine the source voltage:
   voltage = (float)sumSamples / (float)numSamples; // Calculate avg raw value.
-  voltage = voltage * scaleRaw2Volts;    // Scale avg raw value to source voltage.
+  voltage *= scaleRaw2Volts;      // Scale avg raw value to source voltage.

   Serial.print(voltage);
   Serial.println (" V");
   digitalWrite(activityLED, LOW);
   elapsedTime = millis() - startTime;

-  // Wait until 5sec have passed.
+  // *** Wait until 5sec have passed.
   delay(abs(5000 - elapsedTime));
 }


Re-adding some comments.

Re-adding some comments.

--- SearialInputReading/SearialInputReading.ino
+++ SearialInputReading/SearialInputReading.ino
@@ -56,18 +56,16 @@
   // read the pushbutton input pin:
   buttonState = digitalRead(buttonPin);

-  // compare the buttonState to its previous state
+  // Read the pushbutton input pin:
   if (buttonState != lastButtonState) {
-  // if the state has changed, increment the counter
+  // If the state has changed, increment the counter
     if (buttonState == HIGH) {
-    // if the current state is HIGH then the button
-    // went from off to on:
+    // If the current state is HIGH then the button went from off to on:
   Serial.print("state");
   Serial.print("1");
   Serial.print(";");
   } else {
-  // if the current state is LOW then the button
-  // went from on to off:
+  // If the current state is LOW, then the button went from on to off
   Serial.print("state");
   Serial.print("0");
   Serial.print(";");
@@ -75,8 +73,7 @@
   // Delay a little bit to avoid bouncing
   delay(50);
   }
-  // save the current state as the last state,
-  //for next time through the loop
+  //Save the current state as the last state, for next time through the loop
   lastButtonState = buttonState;
 }


Fixed types

Fixed types

и доста комитирате код што не работи :)

--- master/master.ino
+++ master/master.ino
@@ -12,7 +12,7 @@
 // Single radio pipe address for the 2 nodes to communicate.
 const uint64_t pipe = 0xE8E8F0F0E1LL;

-uint8_t state = 0;
+int state = 0;
 uint8_t state_size = sizeof(state);

 void setup(void)
@@ -32,7 +32,7 @@

 void loop(void)
 {
-  uint8_t address;
+  int address;
   char cmd[10];
   char c;

@@ -43,7 +43,7 @@
     } else {
       input.toCharArray(cmd,10);
       byte okparse = sscanf(cmd, "%d %d", &address, state);
-      printf(state);
+      printf("%d", state);

       if (okparse == 2 ) {
         radio.openWritingPipe(pipe+(uint64_t)address);


Changed GPIO pins used; Added startup flashes

--- ConnectedXMasTrees/ConnectedXmasWeMos/ConnectedXmasWeMos.ino
+++ ConnectedXMasTrees/ConnectedXmasWeMos/ConnectedXmasWeMos.ino
@@ -6,6 +6,7 @@
  * Using MQTT, motion sensed at one tree will light the other tree
  *
  * Motion sensed also lights the tip of the local tree, to give indication to the local user.
+ * Note that motion sensor will likely need external power. Or use a simple pushbutton
  *
  * free service: https://www.hivemq.com/try-out/
   http://www.mqtt-dashboard.com/
@@ -32,8 +33,7 @@

 // MQTT server
 const char* mqtt_server = "broker.hivemq.com";
-const char* mqtt_topic = "ConnectedXmasTreeTopic"; // Make this unique in case others are doing the same - maybe add your name to the end.
-
+const char* mqtt_topic = "ConnectedXmasTreeTopic";
 char mqtt_message[50];

 const char myTreeID = '1';     // switch these two numbers for the second tree.
@@ -44,9 +44,9 @@
 PubSubClient client(espClient);

 // For Wemos D1 Mini, the built-in LED is D4
-#define MOTION_SENSOR D3  // D8 has built-in 10k pull-down, D3 has pull-up
-#define LED_TREETOP D1
-#define LED_TREE    D2
+#define MOTION_SENSOR D2 // same as button on Witty  // D8 has *external, always-active* 10k pull-down, D3 has pull-up
+#define LED_TREETOP D6   // same as Green RGB LED on Witty
+#define LED_TREE    D8   // same as Red RGB LED on Witty

 #define LED_ON  HIGH
 #define LED_OFF LOW
@@ -72,6 +72,9 @@

   pinMode(LED_TREETOP, OUTPUT);
   pinMode(LED_TREE, OUTPUT);
+  pinMode(LED_BUILTIN, OUTPUT);
+
+  flashBuiltInLED(2);

   digitalWrite(LED_TREETOP, LED_OFF);
   digitalWrite(LED_TREE, LED_OFF);
@@ -79,12 +82,15 @@
   pinMode(MOTION_SENSOR, INPUT);  // use a 10k external resistor to ground

   connectWiFi();
+  flashBuiltInLED(5);

   Serial.println("Setting up MQTT connection");
   client.setServer(mqtt_server, 1883);
   client.setCallback(mqtt_callback);

   Serial.println("Setup is complete.\n");
+
+  flashThisTree(2);
 }

 void connectWiFi() {
@@ -98,6 +104,7 @@
   while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
+    flashBuiltInLED(1);
   }

   Serial.println("");
@@ -121,7 +128,7 @@

   // Switch on this tree if an 1 was received as first character
   if ((char)payload[0] == myTreeID) {
-    flashThisTree();
+    flashThisTree(7);

     if (length == 1) {
       lightThisTree();
@@ -215,8 +222,8 @@
   timeThisTreeTurnedOn = millis();
 }

-void flashThisTree() {
-  for (int i=0; i<7; i++) {
+void flashThisTree(int count) {
+  for (int i=0; i<count; i++) {
     digitalWrite(LED_TREE, LED_ON);
     delay(100);
     digitalWrite(LED_TREE, LED_OFF);
@@ -224,3 +231,13 @@
   }
 }

+void flashBuiltInLED(int count) {
+    for (int i=0; i<count; i++) {
+    digitalWrite(LED_BUILTIN, LOW);
+    delay(100);
+    digitalWrite(LED_BUILTIN, HIGH);
+    delay(100);
+  }
+
+}
+


Update for Arduino 1.0.6 toolchain; does not support C++11 for-loop.

--- examples/IoT/MQTT/CosaMQTTtemperature/CosaMQTTtemperature.ino
+++ examples/IoT/MQTT/CosaMQTTtemperature/CosaMQTTtemperature.ino
@@ -90,7 +90,7 @@
   Watchdog::begin();

   // Connect the sensors and set resolution to 10-bits
-#if (ARDUINO < 150) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
+#if (ARDUINO < 150)
   for (uint8_t i = 0; i < membersof(thermometer); i++) {
     thermometer[i]->connect(i);
     thermometer[i]->set_resolution(10);


rename abort() to emergengyStop() because then it fits in with the logo inteface and also abort() is a special C function that means no code after it runs.

--- software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
+++ software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
@@ -266,7 +266,7 @@

     if (nowColliding == 1) {
       // abort current command
-      abort();
+      emergencyStop();
       buzz(500);

       // insert some recovery steps
@@ -274,7 +274,7 @@
       insertCmd("BK 20");
     } else if (nowColliding == 2) {
       // abort current command
-      abort();
+      emergencyStop();
       buzz(500);

       // insert some recovery steps
@@ -282,7 +282,7 @@
       insertCmd("BK 20");
     } else if (nowColliding == 3) {
       // abort current command
-      abort();
+      emergencyStop();
       buzz(500);

       // insert some recovery steps
@@ -346,7 +346,7 @@
   }
 }

-void abort() {
+void emergencyStop() {
     stepperL.setCurrentPosition(stepperL.currentPosition());
     stepperR.setCurrentPosition(stepperR.currentPosition());
 }


added COEFFICIENT to smooth out the reckoning adjustment

--- arduino_motor/mains/movements.ino
+++ arduino_motor/mains/movements.ino
@@ -38,7 +38,8 @@

       midPID.Compute();
       //SetpointRight = PID_SETPOINT + 0.5 * map(OutputMid,-PID_SETPOINT/2, PID_SETPOINT/2, -PID_SETPOINT, +PID_SETPOINT);
-      //SetpointLeft = PID_SETPOINT -0.5 * map(OutputMid,-PID_SETPOINT/2, PID_SETPOINT/2, -PID_SETPOINT, +PID_SETPOINT);
+      const int COEFFICIENT;
+      SetpointLeft += COEFFICIENT * map(OutputMid,-PID_SETPOINT/2, PID_SETPOINT/2, -PID_SETPOINT, +PID_SETPOINT);
       rightPID.Compute();
       leftPID.Compute();


Testing LED blink when card not detected during job

--- module/module.ino
+++ module/module.ino
@@ -163,7 +163,7 @@
 			sendCommand(CMD_GET_SNR, blockID, machineID, keyA, NULL);
 			// if card is missing, increment a counter and blink LED?? too slow
 			if (!getResponse(serialNumber)) {
-				digitalWrite(ledPin, (digitalRead(ledPin) == HIGH ? LOW : HIGH));
+				//digitalWrite(ledPin, (digitalRead(ledPin) == HIGH ? LOW : HIGH));
 				pollCounter += 1;
 				// if the counter reaches a specified timeout, return
 				if (pollCounter == pollTimeout) {
@@ -253,6 +253,10 @@
 			//delay(pollInterval);
 			lastPollTime = millis();
 		}
+
+		if (pollCounter > 0) {
+			digitalWrite(ledPin, (digitalRead(ledPin) == HIGH ? LOW : HIGH));
+		}
 	}
 }
 /*void soundFeedback(bool isReject) {


Starting over

Starting over

--- module/module.ino
+++ module/module.ino
@@ -147,13 +147,14 @@
 	// some variables used in this scope
 	unsigned long startTime = 0;
 	unsigned int periodX, periodY;
-	unsigned int pulseCount, pollCounter = 0;
+	unsigned int pollCounter = 0;
 	int signals[] = { 0, 0, 0, 0, 0 };
   	int i = 0;
+  	int numValid, numInvalid = 0;

 	// Only here temporarily for debugging
 	if (1) {
-		Serial.print(startTime); Serial.print(" "); Serial.print(elapsedTime); Serial.print(" "); Serial.println(pulseCount);
+		Serial.print(startTime); Serial.print(" "); Serial.print(elapsedTime); Serial.print(" ");
 	}

 	while (1) {
@@ -196,9 +197,8 @@
 			Serial.print("PeriodX: "); Serial.print(periodX);
 			Serial.print(" PeriodY: "); Serial.print(periodY);
 			Serial.print(" "); Serial.print(signals[0]); Serial.print(signals[1]); Serial.print(signals[2]); Serial.print(signals[3]); Serial.print(signals[4]);
-			Serial.print(" "); Serial.print(checkHistory(signals));
-			Serial.print(" Start Time: "); Serial.print(startTime);
-			Serial.print(" Pulse Count: "); Serial.println(pulseCount);
+			Serial.print(" "); Serial.print(numValid); Serial.print(" "); Serial.print(numInvalid);
+			Serial.print(" Start Time: "); Serial.println(startTime);
 		}

 		// if periodX and periodY IS a valid pair
@@ -209,8 +209,6 @@
 				if (startTime == 0) {
 					startTime = millis();
 				}
-				// track number of valid pulses (after job start)
-				pulseCount += 1;
 			}
 		}
 		// if periodX and periodY IS NOT a valid pair
@@ -227,7 +225,6 @@
 				else {
 					startTime = 0;
 					elapsedTime = 0;
-					pulseCount = 0;
 				}
 			}
 		}
@@ -278,34 +275,6 @@
 		return flag.idle;
 	}
 }
-/*
-	Determines if the driver signals are valid. During a job,
-	the period of a pulse is either 0, 5 or 6 microseconds.
-	There are slight deviations at times, so summing the values together
-	and using the maximum possible sum as a check is a reliable way to
-	determine if a signal is valid.
-
-int inRange(unsigned long periodX, unsigned long periodY) {
-	unsigned int sum = periodX + periodY;
-
-	if (0 < sum && sum <= maximumValue) {
-		return 1;
-	}
-	else {
-		return 0;
-	}
-}
-*/
-/*
-	Calculate time elapsed in seconds.
-
-unsigned long calculateTime(unsigned long startTime) {
-	return (millis() - startTime)/1000;
-}
-*/
-/*
-	This will play 3 rapid notes or 1 long note.
-*/
 /*void soundFeedback(bool isReject) {
 	if (isReject) {
 		tone(speakerPin, rejectNote, rejectDuration);


implement threshold for activating fan

implement threshold for activating fan

--- monitoring-temp-arduino-code/monitoring/monitoring.ino
+++ monitoring-temp-arduino-code/monitoring/monitoring.ino
@@ -9,14 +9,16 @@
 int FAN_PWM_PIN = 9;

 // only needed when measuring temperature time series values
-#define SEND_TEMP_VALUES_TO_HOST false
+#define SEND_TEMP_VALUES_TO_HOST true
 #define SEND_TO_HOST_INTERVALL_IN_MILLIS 1000
+
+#define SENSOR_1_TEMP_THRESHOLD_in_CELCIUS 40.0

 /***************************************************************/

-#define RING_BUFFER_SIZE 5
+#define RING_BUFFER_SIZE 10
 #define INVALID_VALUE -273.0
-#define WAIT_MILLIS (SEND_TO_HOST_INTERVALL_IN_MILLIS / RING_BUFFER_SIZE)
+#define ONE_MINUTE_IN_MILLIS 1000

 /***************************************************************/

@@ -89,11 +91,16 @@
 void loop() {
     buffer_write(&tempRingBuf_1, readTemperatureInCelcius(LM35_1_PIN));
     buffer_write(&tempRingBuf_2, readTemperatureInCelcius(LM35_2_PIN));
-    delay(WAIT_MILLIS);
+    delay(ONE_MINUTE_IN_MILLIS / RING_BUFFER_SIZE);
+
+    float lastMinuteTempAverage = averageValues(&tempRingBuf_1);
+    if (lastMinuteTempAverage > SENSOR_1_TEMP_THRESHOLD_in_CELCIUS) {
+        analogWrite(FAN_PWM_PIN, 255);
+    } else {
+        analogWrite(FAN_PWM_PIN, 0);
+    }

     if (SEND_TEMP_VALUES_TO_HOST) {
         sendValuesToHost();
     }
-
-    analogWrite(FAN_PWM_PIN, 255);
 }


Delete RedBear_Duo_BLE.ino

Delete RedBear_Duo_BLE.ino

--- firmware/examples/01_Particle/RedBear_Duo_BLE.ino
+++ firmware/examples/01_Particle/RedBear_Duo_BLE.ino
@@ -1,66 +0,0 @@
-/**************************************************************
- * Blynk is a platform with iOS and Android apps to control
- * Arduino, Raspberry Pi and the likes over the Internet.
- * You can easily build graphic interfaces for all your
- * projects by simply dragging and dropping widgets.
- *
- *   Downloads, docs, tutorials: http://www.blynk.cc
- *   Blynk community:            http://community.blynk.cc
- *   Social networks:            http://www.fb.com/blynkapp
- *                               http://twitter.com/blynk_app
- *
- * Blynk library is licensed under MIT license
- * This example code is in public domain.
- *
- **************************************************************
- *
- * This example shows how to use RedBear Duo BLE
- * to connect your project to Blynk.
- *
- * NOTE: BLE support is in beta!
- *
- **************************************************************/
-
-#if defined(ARDUINO)
-  SYSTEM_MODE(MANUAL);    // If Arduino - do not connect to Particle cloud
-#else
-  SYSTEM_MODE(AUTOMATIC); // Otherwise, connect to Particle cloud
-#endif
-
-//#define BLYNK_DEBUG
-#define BLYNK_PRINT Serial
-
-//#define BLYNK_USE_DIRECT_CONNECT
-
-#include <BlynkSimpleRedBear_Duo_BLE.h>
-
-// You should get Auth Token in the Blynk App.
-// Go to the Project Settings (nut icon).
-char auth[] = "YourAuthToken";
-
-void setup() {
-  Serial.begin(9600);
-  delay(5000);
-
-  Blynk.begin(auth);
-
-  Serial.println("Waiting for connections...");
-}
-
-void loop() {
-  Blynk.run();
-}
-
-// Next functions are optional.
-// Add ZeRGBa Widget on V0 to control onboard LED.
-BLYNK_CONNECTED() {
-  RGB.control(true);
-}
-
-BLYNK_WRITE(V0) {
-  int r = param[0].asInt();
-  int g = param[1].asInt();
-  int b = param[2].asInt();
-  RGB.color(r, g, b);
-}
-


Adjusts constants values for motors and controller input

--- drone_control/drone_control.ino
+++ drone_control/drone_control.ino
@@ -9,11 +9,14 @@

 #define SERVO_OFF  1000
 #define SERVO_HOVER 1000 // TODO: Find the actual value
-#define SERVO_FULL 2000 // TODO: Find the actual value
-#define FRONT_LEFT 0
-#define FRONT_RIGHT 1
-#define BACK_LEFT 2
-#define BACK_RIGHT 3
+#define SERVO_FULL 3000 // TODO: Find the actual value
+
+
+#define FRONT_LEFT  2
+#define FRONT_RIGHT 3
+#define BACK_LEFT   4
+#define BACK_RIGHT  5
+
 #define TEST_CONTROLS

 Servo rotor[4];
@@ -28,6 +31,12 @@
   rotor[MotorID].writeMicroseconds(value);
 }

+void SetAllMotors(int value)
+{
+  for (int i = FRONT_LEFT; i <= BACK_RIGHT; ++i)
+    SetMotor(i, value);
+}
+
 double MicrosToSecond(ulong micro){
   return micro / 1000000.f;
 }
@@ -35,8 +44,7 @@
 void LiftOff(float feet){
   double Height = 0;
   // Read the height from the ultrasonic sensors
-  for (int i = 0; i < 4; ++i)
-    SetMotor(i, SERVO_HOVER + 250); // Put all four motors on low power, but can still go up.
+  SetAllMotors(SERVO_HOVER + 250); // Put all four motors on low power, but can still go up.

   while (Height < feet)
   {
@@ -49,18 +57,17 @@
 void Land()
 {
   double Height = 0;
-  for (int i = 0; i < 4; ++i)
-    SetMotor(i, SERVO_HOVER - 250); // Put all four motors on low power, but can still go up.
+  SetAllMotors(SERVO_HOVER - 250); // Put all four motors on low power, but can still go up.

   while (Height > .5)
   {
     Height = 0; // Fill this in with the actual height-finding code later
   }
-  for (int i = 0; i < 4; ++i)
-    SetMotor(i, SERVO_OFF);
+  SetAllMotors(SERVO_OFF);
 }

 void setup() {
+  Serial.begin(9600);
 #ifdef TEST_CONTROLS
   ManualControl = true;
 #else
@@ -70,18 +77,14 @@
   TimeSinceStart = millis();
   TimeDelta = 0;

-  for (int i = 0; i < 4; ++i){
+  for (int i = FRONT_LEFT; i <= BACK_RIGHT; ++i){
     rotor[i].attach(i); // Set up ESC channels. TODO: Find the offset for i in this case
     SetMotor(i, SERVO_OFF);
   }

   gyro.begin(gyro.L3DS20_RANGE_250DPS);

-  delay(5000);
-  LiftOff(1.5);
-
-  delay(5000);
-  Land();
+  delay(5000); // Delay for the battery
 }

@@ -89,10 +92,10 @@
 {
   ControllerInput Result;

-  const short CONTROL_THROTTLE = 1;
-  const short CONTROL_PITCH = 2;
-  const short CONTROL_YAW = 3;
-  const short CONTROL_ROLL = 4;
+  const short CONTROL_THROTTLE = 6;
+  const short CONTROL_PITCH    = 7;
+  const short CONTROL_YAW      = 8;
+  const short CONTROL_ROLL     = 9;

   Result.Throttle = analogRead(CONTROL_THROTTLE);
   Result.Pitch = analogRead(CONTROL_PITCH);
@@ -108,10 +111,8 @@

   if (ManualControl)
   {
-    const int CONTROLLER_MAX = 5;
+    const int CONTROLLER_MAX = 1024;
     const int CONTROLLER_MIN = 0;
-    const int MOTOR_MAX = 1024;
-    const int MOTOR_MIN = 0;

     ControllerInput Input = GetControllerInput();
     int Throttle = Input.Throttle;
@@ -119,10 +120,10 @@
     int Pitch    = Input.Pitch;
     int Yaw      = Input.Yaw;

-    Throttle = map(Throttle, CONTROLLER_MIN, CONTROLLER_MAX, MOTOR_MIN, MOTOR_MAX);
-    Roll     = map(Roll,     CONTROLLER_MIN, CONTROLLER_MAX, MOTOR_MIN, MOTOR_MAX);
-    Pitch    = map(Pitch,    CONTROLLER_MIN, CONTROLLER_MAX, MOTOR_MIN, MOTOR_MAX);
-    Yaw      = map(Yaw,      CONTROLLER_MIN, CONTROLLER_MAX, MOTOR_MIN, MOTOR_MAX);
+    Throttle = map(Throttle, CONTROLLER_MIN, CONTROLLER_MAX, SERVO_OFF, SERVO_FULL);
+    Roll     = map(Roll,     CONTROLLER_MIN, CONTROLLER_MAX, SERVO_OFF, SERVO_FULL);
+    Pitch    = map(Pitch,    CONTROLLER_MIN, CONTROLLER_MAX, SERVO_OFF, SERVO_FULL);
+    Yaw      = map(Yaw,      CONTROLLER_MIN, CONTROLLER_MAX, SERVO_OFF, SERVO_FULL);

     SetMotor(FRONT_LEFT,  +Yaw + Roll - Pitch + Throttle);
     SetMotor(FRONT_RIGHT, -Yaw - Roll - Pitch + Throttle);