- renamed sketch for IDE compatibility

- renamed sketch for IDE compatibility

--- geheimtuer.ino
+++ geheimtuer.ino
@@ -1,774 +0,0 @@
-#include <WS2812.h>
-
-// LED stripe length
-#define MAXPIX 20
-// animation buffer, read windows moves back and forth EXTRAPIX pixels
-#define EXTRAPIX 3
-
-// WS2812 output
-const int ledPin = 11;
-
-cRGB leds[MAXPIX+EXTRAPIX];
-cRGB tmp_leds[MAXPIX]; // temp array for fading and blinking
-cRGB *ledptr; // read pointer for WS2812 library, points to start of window
-
-// requires custom changes to accept uint8_t** argument
-WS2812 LED(MAXPIX, &ledptr);
-
-enum ledModes { ledSolid, ledFade, ledBlink, ledForward, ledBackward } ledMode;
-
-// mode-dependent state
-union ledState {
-  unsigned int ledidx;
-  signed int fader;
-  bool blink_on;
-} ledState;
-
-// pre-defined colors. GRB order, g++ doesn't implement out-of-order initializers
-const struct cRGB traktor = {g: 0xB8/4, r: 0x67/4, b: 0xDC/4}; // https://wiki.attraktor.org/Corporate_Identity
-const struct cRGB black = {g: 0x00, r: 0x00, b: 0x00};
-const struct cRGB white = {g: 0x1F, r: 0x1F, b: 0x1F};
-const struct cRGB red = {g: 0x00, r: 0x1F, b: 0x00};
-const struct cRGB green = {g: 0x1F, r: 0x00, b: 0x00};
-const struct cRGB blue = {g: 0x00, r: 0x00, b: 0x1F};
-
-// macro instead of inline function. TODO: compare generated code again
-// fill LED buffer with solid color, reset state, set mode
-#define setLeds1(color1, mode) {\
-  for (uint8_t i = 0; i < MAXPIX+EXTRAPIX; i++) {\
-    leds[i] = (color1);\
-  }\
-  memset(&ledState, 0x00, sizeof(ledState));\
-  ledMode = (mode);\
-}
-
-// fill LED buffer with alternating colors every $modulo pixels, reset state, set mode
-#define setLeds2(color1, color2, modulo, mode) {\
-  for (uint8_t i = 0; i < MAXPIX+EXTRAPIX; i++) {\
-    leds[i] = (i % (modulo)) ? ((color2)) : ((color1));\
-  }\
-  memset(&ledState, 0x00, sizeof(ledState));\
-  ledMode = (mode);\
-}
-
-
-// global motor direction variable, required for PWM-brake & coasting
-// TODO: PWM-brake is never used, maybe refactor & remove
-enum motorDir { forward, backward } motorDir;
-
-// I/O connections to bridge driver module
-// https://www.olimex.com/Products/RobotParts/MotorDrivers/BB-VNH3SP30/
-// https://www.olimex.com/Products/RobotParts/MotorDrivers/BB-VNH3SP30/resources/BB-VNH3SP30_schematic.pdf
-const int motorDiagAPin = 5;
-const int motorDiagBPin = 6;
-const int motorInAPin = 7;
-const int motorInBPin = 8;
-const int motorPWMPin = 9;
-
-// ad-hoc acceleration profile
-struct accelProfile {
-  unsigned long maxMillis; // time until next step, 0 == end of profile
-  unsigned long stepMillis; // modify PWM value every stepMillis ms
-  double factor; // newValue = (oldValue + add) * factor
-  signed int add;
-  byte minPWM; // lower limit
-  byte maxPWM; // upper limit
-  byte startPWM; // initial value
-  bool useStartPWM; // overwrite PWM value with startPWM, ignored on first element
-  bool brake; // short motor if true, reset to motorDir if false
-};
-
-// slow seek to end-stop, used if door is in unknown position
-const struct accelProfile accelProfileLow[] = {
-  {
-    maxMillis: 13000,
-    stepMillis: 50,
-    factor: 1,
-    add: 4,
-    minPWM: 0,
-    maxPWM: 64,
-    startPWM: 0,
-    useStartPWM: true,
-    brake: false
-  },
-  {
-    maxMillis: 0
-  }
-};
-
-// normal operation
-// try accelerating as fast as possible without skipping belt teeth
-// TODO: install less stiff spring between belt and door to dampen the initial pull
-const struct accelProfile accelProfileHigh[] = {
-{ // slow start
-    maxMillis: 350,
-    stepMillis: 50,
-    factor: 1,
-    add: 5,
-    minPWM: 0,
-    maxPWM: 30,
-    startPWM: 0,
-    useStartPWM: true, // first element always sets initial PWM value
-    brake: false
-  },
-  { // accelerate to full-ish speed and keep running
-    maxMillis: 3000,
-    stepMillis: 50,
-    factor: 1.05,
-    add: 0,
-    minPWM: 0,
-    maxPWM: 180,
-    startPWM: 0,
-    useStartPWM: false,
-    brake: false
-  },
-/*
-  { // coast
-    maxMillis: 1000,
-    stepMillis: 50,
-    factor: 1,
-    add: 0,
-    minPWM: 0,
-    maxPWM: 0,
-    startPWM: 0,
-    useStartPWM: true,
-    brake: true
-  },
-  { // PWM-brake
-    maxMillis: 1000,
-    stepMillis: 50,
-    factor: 1,
-    add: 0,
-    minPWM: 1,
-    maxPWM: 1,
-    startPWM: 1,
-    useStartPWM: true,
-    brake: true
-  },
-*/
-  { // slow down before end-stop
-    maxMillis: 1000,
-    stepMillis: 100,
-    factor: 0.9,
-    add: 0,
-    minPWM: 64,
-    maxPWM: 255,
-    startPWM: 0,
-    useStartPWM: false,
-    brake: false
-  },
-  { // seek end-stop
-    maxMillis: 5000,
-    stepMillis: 100,
-    factor: 1,
-    add: -1,
-    minPWM: 32,
-    maxPWM: 64,
-    startPWM: 64,
-    useStartPWM: true,
-    brake: false
-  },
-  {
-    maxMillis: 0
-  }
-};
-
-const struct accelProfile *accelProfile; // variable pointer to a const struct
-int accelProfileIdx = 0;
-
-// switch inputs, active-low
-const int switchFront = 3; // front is at the closed position
-const int switchFrontIRQ = 1; // TODO: maybe use interrupts & sleep
-
-const int switchBack = 4;
-
-// wire-ORed buttons, active-low
-const int switchTrigger = 2;
-const int switchTriggerIRQ = 0;
-
-
-// unsorted variables below. TODO: refactor & cleanup
-
-// buttons & switches do different things in different states
-enum doorStates { doorClosed, doorOpening, doorOpen, doorClosing, doorBlocked, doorError } doorState;
-
-double drivePWM = 0;
-const double drivePWMscale = 1; // fiddling aid, constant factor applied to calculated PWM value. TODO: update profile & remove
-
-// TODO: the timing system has some quirks. think again or document
-
-unsigned long lastMillis = 0; // last loop's millis() result
-
-unsigned long driveMillis = 0;
-unsigned long driveStepMillis = 0;
-
-const unsigned long openInterval = 3000; // ms before the door closes again, unless blocked by button
-unsigned long openMillis = 0;
-
-const unsigned long debounceInterval = 2; // shift inputs into debounce register every debounceInterval ms
-unsigned long debounceMillis = 0;
-
-// TODO: use structured profiles
-const unsigned long ledSolidInterval = 250; // constantly update LED stripe in solid mode
-const unsigned long ledFadeInterval = 20;
-const unsigned long ledBlinkInterval = 1000;
-const unsigned long ledMoveInterval = 250; // shift LED window every X ms
-unsigned long ledMillis = 0;
-
-bool swFront, swBack, swTrigger, motorDiagA, motorDiagB; // debounced inputs
-uint16_t swFrontDebounce, swBackDebounce, swTriggerDebounce, motorDiagADebounce, motorDiagBDebounce; // debounce shift registers
-
-
-void setup() {
-  Serial.begin(115200);
-  Serial.print(F("\nDoor control init\n"));
-
-  // disable driver bridges until setup complete
-  motorDisable();
-
-  digitalWrite(motorInAPin, LOW);
-  pinMode(motorInAPin, OUTPUT);
-
-  digitalWrite(motorInBPin, LOW);
-  pinMode(motorInBPin, OUTPUT);
-
-  digitalWrite(motorPWMPin, LOW);
-  pinMode(motorPWMPin, OUTPUT);
-
-// TODO: measure real PWM frequeny. any value other than 1 makes the motor whine
-// the code says base frequency is ~31kHz
-// VNH3SP30 datasheet limits the input PWM frequency to 10kHz - and yet it works
-setPwmFrequency(motorPWMPin, 1);
-
-  pinMode(switchFront, INPUT_PULLUP);
-  pinMode(switchBack, INPUT_PULLUP);
-
-  pinMode(switchTrigger, INPUT_PULLUP);
-
-  setLeds1(traktor, ledSolid);
-  ledptr = &leds[0];
-  LED.setOutput(ledPin);
-  LED.sync();
-
-  // initialize debounce registers, assume steady state
-  swFrontDebounce = (swFront = digitalRead(switchFront)) * 0xFFFF;
-  swBackDebounce = (swBack = digitalRead(switchBack)) * 0xFFFF;
-  swTriggerDebounce = (swTrigger = digitalRead(switchTrigger)) * 0xFFFF;
-
-  Serial.print(F("Door status: "));
-
-  if (swTrigger == LOW || (swFront == LOW && swBack == LOW)) {
-    doorState = doorError;
-    Serial.print(F("ERROR\n"));
-  } else if (swFront == LOW) {
-    doorState = doorClosed;
-    Serial.print(F("closed\n"));
-  } else if (swBack == LOW) {
-    doorState = doorOpen;
-    Serial.print(F("open\n"));
-  } else {
-    doorState = doorBlocked;
-    Serial.print(F("blocked\n"));
-  }
-
-  if (doorState != doorError) {
-    // enable driver
-    motorEnable();
-
-    // diag pull-ups should have brought the lines up by now
-    motorDiagADebounce = (motorDiagA = digitalRead(motorDiagAPin)) * 0xFFFF;
-    motorDiagBDebounce = (motorDiagB = digitalRead(motorDiagBPin)) * 0xFFFF;
-
-    if (doorState != doorBlocked) {
-      motorBrake();
-    } else {
-      motorFree();
-      setLeds1(red, ledSolid);
-    }
-  } else {
-    setLeds1(red, ledBlink);
-  }
-
-// TODO: on-board status LEDs, independent of ws2812 stripe
-digitalWrite(13, LOW);
-pinMode(13, OUTPUT);
-
-//  attachInterrupt(switchFrontIRQ, switchFrontInterrupt, CHANGE);
-//  attachInterrupt(switchTriggerIRQ, switchTriggerInterrupt, FALLING);
-}
-
-void loop() {
-  unsigned long currentMillis;
-  unsigned long elapsedMillis;
-
-  currentMillis = millis();
-  // millis() will overflow after approximately 50 days.
-  if (currentMillis < lastMillis) {
-    elapsedMillis = (~0UL - lastMillis) + currentMillis;
-  } else {
-    elapsedMillis = currentMillis - lastMillis;
-  }
-  lastMillis = currentMillis;
-  // assume that none of the following intervals overflow
-
-/*
-  Serial.print(F("Elapsed millis: "));
-  Serial.println(elapsedMillis);
-*/
-
-  debounceMillis += elapsedMillis;
-  if (debounceMillis >= debounceInterval) {
-    debounceMillis = 0;
-
-    debounce(switchTrigger, &swTrigger, &swTriggerDebounce);
-    debounce(switchFront, &swFront, &swFrontDebounce);
-    debounce(switchBack, &swBack, &swBackDebounce);
-  }
-
-  // fast debounce driver error signals to filter short glitches
-  debounce(motorDiagAPin, &motorDiagA, &motorDiagADebounce);
-  debounce(motorDiagBPin, &motorDiagB, &motorDiagBDebounce);
-
-  // The WAM's overheating!
-  if ((motorDiagA == LOW || motorDiagB == LOW) && doorState != doorError) {
-    motorFree();
-    Serial.print(F("Motor driver error condition - door disabled\n"));
-    setLeds1(red, ledFade);
-    doorState = doorError;
-  }
-
-  switch(doorState) {
-    case doorClosed:
-      // wait until a button is pressed or the front switch opens
-      if (swFront == HIGH || swTrigger == LOW) {
-        if (swFront == HIGH) {
-          // maybe someone tried to pull the door open
-          // TODO: or the door slams too fast into the end-stop and rebounds. align profile & inertial reality
-          Serial.print(F("Front switch triggered - opening door\n"));
-          initDrive(backward, accelProfileLow);
-        } else {
-          Serial.print(F("Button switch triggered - opening door\n"));
-          initDrive(backward, accelProfileHigh);
-// TODO: think again. re-arming swTrigger disables deglitching
-swTrigger = HIGH;
-        }
-        setLeds2(white, black, 3, ledBackward);
-        doorState = doorOpening;
-      }
-      break;
-
-    case doorOpen:
-      // hold the door open if button pressed during openInterval
-      if (swTrigger == LOW) {
-        Serial.print(F("Button switch triggered - door blocked\n"));
-        motorFree();
-        setLeds1(red, ledSolid);
-        doorState = doorBlocked;
-swTrigger = HIGH;
-        break;
-      }
-
-      openMillis += elapsedMillis;
-      if (openMillis >= openInterval || swBack == HIGH) {
-        if (swBack == HIGH) {
-          // maybe someone tried to pull the door close
-          // TODO: or the door slams too fast into the end-stop and rebounds. align profile & inertial reality
-          Serial.print(F("Back switch triggered - closing door\n"));
-          initDrive(forward, accelProfileLow);
-        } else {
-          Serial.print(F("openInterval timeout - closing door\n"));
-          initDrive(forward, accelProfileHigh);
-        }
-        setLeds2(white, black, 3, ledForward);
-        doorState = doorClosing;
-      }
-      break;
-
-    case doorOpening:
-      // are we there yet?
-      if (swBack == LOW) {
-        motorBrake();
-        Serial.print(F("Back switch triggered - door open\n"));
-        openMillis = 0;
-        setLeds1(green, ledFade);
-        doorState = doorOpen;
-        break;
-      }
-      // fall-through to next case
-
-    case doorClosing:
-      if (doorState == doorClosing && swFront == LOW) {
-        motorBrake();
-        Serial.print(F("Front switch triggered - door closed\n"));
-        setLeds1(green, ledFade);
-        doorState = doorClosed;
-        break;
-      }
-
-      // stop if button pressed while in motion
-      if (swTrigger == LOW) {
-        motorFree(); // TODO: motorBrake() might be better for an emergency stop. doesn't make much different in our case, the belt skips and the door stops in both cases
-        Serial.print(F("Button switch triggered - door blocked\n"));
-        setLeds1(red, ledSolid);
-        doorState = doorBlocked;
-swTrigger = HIGH;
-        break;
-      }
-
-      driveStepMillis += elapsedMillis;
-      if (driveStepMillis >= accelProfile[accelProfileIdx].stepMillis) {
-        driveMillis += driveStepMillis;
-        driveStepMillis = 0;
-
-        // switch to next profile step
-        if (driveMillis >= accelProfile[accelProfileIdx].maxMillis) {
-          driveMillis = 0;
-
-          // end-stop not reached at end of profile, someone might be in the way
-          if (accelProfile[++accelProfileIdx].maxMillis == 0) {
-            motorFree();
-            Serial.print(F("End of profile - door blocked\n"));
-            setLeds1(red, ledBlink);
-            doorState = doorBlocked;
-            break;
-          }
-
-          if (accelProfile[accelProfileIdx].brake) {
-            // short motor if PWM is HIGH, coast otherwise
-            _motorFree();
-          } else {
-            switch(motorDir) {
-              case forward:
-                motorForward(); break;
-              case backward:
-                motorBackward(); break;
-            }
-          }
-
-          // overwrite current PWM value
-          if (accelProfile[accelProfileIdx].useStartPWM) {
-            drivePWM = accelProfile[accelProfileIdx].startPWM;
-          }
-
-          Serial.print(F("accelProfileIdx: "));
-          Serial.println(accelProfileIdx);
-        }
-
-        // update PWM value
-        drivePWM = min(accelProfile[accelProfileIdx].maxPWM, max(accelProfile[accelProfileIdx].minPWM,
-                        (drivePWM + accelProfile[accelProfileIdx].add) * accelProfile[accelProfileIdx].factor));
-
-        Serial.print(F("Drive PWM: "));
-        Serial.println(drivePWM);
-
-        analogWrite(motorPWMPin, round(drivePWM*drivePWMscale));
-      }
-      break;
-
-    case doorBlocked:
-      // wait until a button is pressed
-      if (swTrigger == LOW) {
-        // close door only if end-stop is active
-        if (swBack == LOW) {
-          Serial.print(F("Button switch triggered - closing door\n"));
-          initDrive(forward, accelProfileLow);
-          ledMode = ledForward;
-          doorState = doorClosing;
-        } else {
-          Serial.print(F("Button switch triggered - opening door\n"));
-          initDrive(backward, accelProfileLow);
-          ledMode = ledBackward;
-          doorState = doorOpening;
-        }
-        setLeds2(white, black, 3, ledMode);
-swTrigger = HIGH;
-      }
-      break;
-
-    case doorError:
-      // wait for reset by qualified service technician
-      // TODO: make it user-resettable
-/*
-// wait until driver cools down
-// TODO: this won't work now because motorDisable() pulls the pins low
-if (motorDiagA == HIGH && motorDiagB == HIGH) {
-  motorEnable();
-  setLeds1(red, ledSolid);
-  doorState = doorBlocked;
-}
-*/
-digitalWrite(13, HIGH);
-      break;
-  }
-
-
-  ledMillis += elapsedMillis;
-  switch(ledMode) {
-    case ledSolid:
-      if (ledMillis >= ledSolidInterval) {
-        ledMillis = 0;
-        ledptr = &leds[0];
-        LED.sync();
-      }
-      break;
-
-    case ledFade: {
-      if (ledMillis >= ledFadeInterval) {
-        ledMillis = 0;
-
-        // TODO: really scale the values. this is too cheap
-        for (uint8_t i = 0; i < MAXPIX; i++) {
-          tmp_leds[i].r = max(0, (int)leds[i].r - abs(ledState.fader));
-          tmp_leds[i].g = max(0, (int)leds[i].g - abs(ledState.fader));
-          tmp_leds[i].b = max(0, (int)leds[i].b - abs(ledState.fader));
-        }
-
-        if (ledState.fader++ >= 255) {
-          ledState.fader = -254;
-        }
-
-        ledptr = &tmp_leds[0];
-        LED.sync();
-      }
-      break;
-    }
-
-    case ledBlink:
-      if (ledMillis >= ledBlinkInterval) {
-        ledMillis = 0;
-
-        if (!ledState.blink_on) {
-  //          memset(&tmp_leds, 0x00, sizeof(tmp_leds));
-          for (uint8_t i = 0; i < MAXPIX; i++) {
-            tmp_leds[i] = black;
-          }
-          ledptr = &tmp_leds[0];
-        } else {
-          ledptr = &leds[0];
-        }
-
-        ledState.blink_on = !ledState.blink_on;
-
-        LED.sync();
-      }
-      break;
-
-    case ledBackward:
-      if (ledMillis >= ledMoveInterval) {
-        ledMillis = 0;
-
-        if (ledState.ledidx >= EXTRAPIX) {
-          ledState.ledidx = 0;
-        }
-
-        // move window forward
-        ledptr = &leds[ledState.ledidx++];
-        LED.sync();
-      }
-      break;
-
-    case ledForward:
-      if (ledMillis >= ledMoveInterval) {
-        ledMillis = 0;
-
-        if (ledState.ledidx == 0) {
-          ledState.ledidx = EXTRAPIX;
-        }
-
-        // move window backwards
-        ledptr = &leds[--ledState.ledidx];
-        LED.sync();
-      }
-      break;
-  }
-}
-
-//__attribute__((always_inline))
-inline void debounce(const int swPin, bool *swVal, uint16_t *swDebounce) {
-  // similiar to what digitalRead() does, assumes that swPin has no timer output assigned
-  // this still leads to several indirect lookups per sample. direct PINx access might be faster
-  debounce(portInputRegister(digitalPinToPort(swPin)), digitalPinToBitMask(swPin), swVal, swDebounce);
-/*
-  *swDebounce = ((*swDebounce << 1) | digitalRead(swPin)) & 0x1FFF; // 13-bit debounce
-*/
-}
-
-//__attribute__((always_inline))
-inline void debounce(const volatile uint8_t *port, const uint8_t pinMask, bool *swVal, uint16_t *swDebounce) {
-  // NB: interference near multiples of 1/interval could cause spurious edges
-  *swDebounce = ((*swDebounce << 1) | ((*port & pinMask)?(1):(0))) & 0x1FFF; // 13-bit debounce
-  if (*swDebounce == 0x1000) { // edge HIGH -> 12xLOW
-    *swVal = LOW;
-  } else if (*swDebounce == 0x0FFF) { // edge LOW -> 12xHIGH
-    *swVal = HIGH;
-  }
-}
-
-// set profile pointer, reset counters, set driver inputs
-// TODO: understand & fix enum namespace fnord
-inline void initDrive(const int dir, const struct accelProfile *profile) {
-  motorDir = (enum motorDir)dir;
-
-  accelProfile = profile;
-  accelProfileIdx = 0;
-  drivePWM = accelProfile[0].startPWM;
-
-  driveMillis = driveStepMillis = 0;
-
-  switch(dir) {
-    case forward:
-      motorForward(); break;
-    case backward:
-      motorBackward(); break;
-  }
-}
-
-// functions beginning with _motor don't output to Serial, used in early interrupt version
-// TODO: either use them with interrupts or remove
-
-inline void setMotorBits(const byte bits) {
-  digitalWrite(motorPWMPin, LOW);
-  digitalWrite(motorInAPin, (bits & 0x02) ? (HIGH) : (LOW));
-  digitalWrite(motorInBPin, (bits & 0x01) ? (HIGH) : (LOW));
-}
-
-void motorDisable() {
-  // actively pull diag pins low, disables driver bridges
-  digitalWrite(motorDiagAPin, LOW);
-  pinMode(motorDiagAPin, OUTPUT);
-
-  digitalWrite(motorDiagBPin, LOW);
-  pinMode(motorDiagBPin, OUTPUT);
-
-  Serial.print(F("Motor driver disabled\n"));
-}
-
-void motorEnable() {
-  // return control to pull-ups on the BB-VNH3SP30 board
-  pinMode(motorDiagAPin, INPUT);
-  pinMode(motorDiagBPin, INPUT);
-  Serial.print(F("Motor driver enabled\n"));
-}
-
-void motorBrake() {
-  _motorBrake();
-  Serial.print(F("Brake engaged\n"));
-}
-
-void _motorBrake() {
-  setMotorBits(0x00);
-/*
-  digitalWrite(motorInAPin, LOW);
-  digitalWrite(motorInBPin, LOW);
-*/
-  digitalWrite(motorPWMPin, HIGH);
-}
-
-void motorFree() {
-  _motorFree();
-  Serial.print(F("Brake disengaged\n"));
-}
-
-void _motorFree() {
-  setMotorBits(0x00);
-/*
-  digitalWrite(motorPWMPin, LOW);
-  digitalWrite(motorInAPin, LOW);
-  digitalWrite(motorInBPin, LOW);
-*/
-}
-
-void motorForward() {
-  _motorForward();
-  Serial.print(F("Forward\n"));
-}
-
-void _motorForward() {
-  setMotorBits(0x02);
-/*
-  digitalWrite(motorPWMPin, LOW);
-  digitalWrite(motorInAPin, HIGH);
-  digitalWrite(motorInBPin, LOW);
-*/
-}
-
-void motorBackward() {
-  _motorBackward();
-  Serial.print(F("Backward\n"));
-}
-
-void _motorBackward() {
-  setMotorBits(0x01);
-/*
-  digitalWrite(motorPWMPin, LOW);
-  digitalWrite(motorInAPin, LOW);
-  digitalWrite(motorInBPin, HIGH);
-*/
-}
-
-
-// copy&pasted from http://playground.arduino.cc/Code/PwmFrequency
-
-/**
- * Divides a given PWM pin frequency by a divisor.
- *
- * The resulting frequency is equal to the base frequency divided by
- * the given divisor:
- *   - Base frequencies:
- *      o The base frequency for pins 3, 9, 10, and 11 is 31250 Hz.
- *      o The base frequency for pins 5 and 6 is 62500 Hz.
- *   - Divisors:
- *      o The divisors available on pins 5, 6, 9 and 10 are: 1, 8, 64,
- *        256, and 1024.
- *      o The divisors available on pins 3 and 11 are: 1, 8, 32, 64,
- *        128, 256, and 1024.
- *
- * PWM frequencies are tied together in pairs of pins. If one in a
- * pair is changed, the other is also changed to match:
- *   - Pins 5 and 6 are paired on timer0
- *   - Pins 9 and 10 are paired on timer1
- *   - Pins 3 and 11 are paired on timer2
- *
- * Note that this function will have side effects on anything else
- * that uses timers:
- *   - Changes on pins 3, 5, 6, or 11 may cause the delay() and
- *     millis() functions to stop working. Other timing-related
- *     functions may also be affected.
- *   - Changes on pins 9 or 10 will cause the Servo library to function
- *     incorrectly.
- *
- * Thanks to macegr of the Arduino forums for his documentation of the
- * PWM frequency divisors. His post can be viewed at:
- *   http://forum.arduino.cc/index.php?topic=16612#msg121031
- */
-void setPwmFrequency(int pin, int divisor) {
-  byte mode;
-  if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
-    switch(divisor) {
-      case 1: mode = 0x01; break;
-      case 8: mode = 0x02; break;
-      case 64: mode = 0x03; break;
-      case 256: mode = 0x04; break;
-      case 1024: mode = 0x05; break;
-      default: return;
-    }
-    if(pin == 5 || pin == 6) {
-      TCCR0B = TCCR0B & 0b11111000 | mode;
-    } else {
-      TCCR1B = TCCR1B & 0b11111000 | mode;
-    }
-  } else if(pin == 3 || pin == 11) {
-    switch(divisor) {
-      case 1: mode = 0x01; break;
-      case 8: mode = 0x02; break;
-      case 32: mode = 0x03; break;
-      case 64: mode = 0x04; break;
-      case 128: mode = 0x05; break;
-      case 256: mode = 0x06; break;
-      case 1024: mode = 0x7; break;
-      default: return;
-    }
-    TCCR2B = TCCR2B & 0b11111000 | mode;
-  }
-}
-


Added the twinkle animation to the LED staff

--- examples/led-staff/led-staff.ino
+++ examples/led-staff/led-staff.ino
@@ -55,6 +55,19 @@
     Log.Info("Button press detected");
     switch(currentAnimation) {
       case 0:
+        Log.Info("Switching to Twinkle animation");
+        looper->clearAll();
+        delete viz;
+        delete anim;
+        viz = new TwinkleVisualization(&input, STAFF_LEDS);
+        anim = new PassThroughAnimation(viz, leds);
+        looper->addInput(&input);
+        looper->addVisualization(viz);
+        looper->addAnimation(anim);
+        looper->setUpdatesPerSecond(50);
+        currentAnimation = 1;
+        break;
+      case 1:
         Log.Info("Switching to Disco animation");
         looper->clearAll();
         delete viz;
@@ -64,9 +77,9 @@
         looper->addInput(&input);
         looper->addVisualization(viz);
         looper->addAnimation(anim);
-        currentAnimation = 1;
+        currentAnimation = 2;
         break;
-      case 1:
+      case 2:
         Log.Info("Switching to Fire animation");
         looper->clearAll();
         delete viz;


Clean up.

Clean up.

--- libraries/MCP23008/examples/CosaMCP23008/CosaMCP23008.ino
+++ libraries/MCP23008/examples/CosaMCP23008/CosaMCP23008.ino
@@ -99,27 +99,28 @@
   // Toggle led and output pin(0). Measure execution time in micro-seconds
   static bool v = false;
   static const uint8_t p = 0;
+  static const size_t BUF_MAX = 16;
   uint32_t start, stop;
+  uint8_t buf[BUF_MAX];
   ledPin.toggle();

   // Fast toggle pin(0)
-  uint8_t buf[16];
-  for (uint8_t i = 0; i < sizeof(buf); i++) buf[i] = i & 1;
+  for (uint8_t i = 0; i < BUF_MAX; i++) buf[i] = i & 1;
   start = RTC::micros();
   port.write(buf, sizeof(buf));
   stop = RTC::micros();
-  trace << (stop - start) / sizeof(buf)
+  trace << (stop - start) / BUF_MAX
 	<< PSTR(": write(buf[") << sizeof(buf) << PSTR("])")
 	<< endl;
   trace.flush();

   // Toggle pin(0)
   start = RTC::micros();
-  for (uint8_t i = 0; i < sizeof(buf); i++) {
+  for (uint8_t i = 0; i < BUF_MAX; i++) {
     port.write(p, i & 1);
   }
   stop = RTC::micros();
-  trace << (stop - start) / sizeof(buf)
+  trace << (stop - start) / BUF_MAX
 	<< PSTR(": write():") << sizeof(buf) << PSTR("X")
 	<< endl;
   trace.flush();
@@ -133,14 +134,14 @@

   // Fast read pins
   start = RTC::micros();
-  port.read(buf, sizeof(buf));
+  port.read(buf, BUF_MAX);
   stop = RTC::micros();
-  trace << (stop - start) / sizeof(buf)
+  trace << (stop - start) / BUF_MAX
 	<< PSTR(": read(buf[") << sizeof(buf) << PSTR("])")
 	<< endl;
   trace.flush();

-  // Toggle pin(0)
+  // Toggle pin(0); Note the
   start = RTC::micros();
   port.write((uint8_t) p, v);
   stop = RTC::micros();


Added ROV identifying strings.

Added ROV identifying strings.

--- ROVMain/ROVMain.ino
+++ ROVMain/ROVMain.ino
@@ -10,12 +10,13 @@
  * @email: alekasdner.lidtke@gmail.com
  * @url: www.aleksanderlidtke.com
  * @since: 24 Sep 2015
- * @version: 2.1.0
+ * @version: 2.1.1
  *
  * CHANGELOG
  *  5 Sep 2015 - 1.0.0 - Alek Lidtke - released the first version.
  *  6 Sep 2015 - 2.0.0 - Alek & Artur Lidtke - derived motor class from the Module class.
  * 24 Sep 2015 - 2.1.0 - Alek Lidtke - added command handling via dummy Modules.
+ * 				 2.1.1 - Alek Lidtke - added ROV identifying strings.
  */

 // Custom includes.
@@ -26,6 +27,10 @@

 // Standard c/C++ includes
 #include <stdio.h>
+
+// ROV identifiers.
+const String ROV_MODEL = "zy3b";
+const String ROV_SW_VERSION = "2.1.1";

 /* =============================================================================
  * FUNCTION DECLARATIONS.
@@ -56,7 +61,7 @@
 	MOTOR_MIN_PULSE_WIDTH, MOTOR_ARM_PULSE_WIDTH, 3, 2);

 /* =============================================================================
- * MISC ACTUATOR DEFINITIONS.
+ * MISC ACTUATOR AND COMMAND DEFINITIONS.
  * =============================================================================
  */
 Module sendSensorReadingsModule = Module("sendSensorReadings"); // Sends sensor readings over serial.
@@ -123,7 +128,7 @@

 	//TODO: do whatever else operations we want to do at start-up.

-	Serial.println("ROV listening to commands."); //TODO: could add VERSION, ROVMODEL etc. consts somewhere so we know what ROV we're using.
+	Serial.println("ROV "+ROV_MODEL+" v. "+ROV_SW_VERSION+" listening to commands."); //TODO: could add VERSION, ROVMODEL etc. consts somewhere so we know what ROV we're using.
 }

 void loop(void)
@@ -218,7 +223,7 @@
   	// If next actuator index < 0 we have no value to read now
   	if (nextActuatorIndex >= 0)
   	{
-  		Serial.print("ROV trying to set value of actuator ");
+  		Serial.print("ROV "+ROV_MODEL+" v. "+ROV_SW_VERSION+" trying to set value of actuator ");
   		Serial.print(actuators[nextActuatorIndex]->getIdentifier());
   		Serial.print(" to ");
   		Serial.println( String(int(atof(token))) );


Brightness no longer changes in a linear manner

--- arduino/ClockFOUR_v1/LED_Display.ino
+++ arduino/ClockFOUR_v1/LED_Display.ino
@@ -32,8 +32,8 @@

 	uint8_t brightness = getBrightness();

-	strip.setBrightness(getLinearBrightness(brightness));
-	logoStrip.setBrightness(getLinearBrightness(brightness));
+	strip.setBrightness(brightness);
+	logoStrip.setBrightness(brightness);

 	PRINT_DEBUG(" Brightness: ");
 	PRINT_DEBUG(brightness);


minor changes, think timeout works as intended

--- embedded/qubo_arduino/qubo_arduino.ino
+++ embedded/qubo_arduino/qubo_arduino.ino
@@ -20,7 +20,7 @@
 #define NUM_THRUSTERS 8

 // Time(ms) arduino waits without hearing from jetson before turning off thrusters
-#define ALIVE_TIMEOUT 5000
+#define ALIVE_TIMEOUT 10000

 // Character sent to the jetson on connect and reconnect
 #define CONNECTED "C"
@@ -176,22 +176,18 @@
       if ( !prot[0] ) {
         Serial.println("B1");
       }
-
       // Handle specific commands
-      else {
-        switch(prot[0]) {
-
-        case 't': {
+      else if ( prot[0] == 't' ) {
+          Serial.println("Thrusters on");
           thrusterCmd;
         }
-        case 'd': {
+      else if ( prot[0] == 'd' ) {
+          Serial.println("Get depth");
           getDepth();
-        }
-        default:
+      }
+      else {
           Serial.println("B2");
           Serial.println(prot[0]);
-        }
-
       }

       // Reset buffer position
@@ -201,6 +197,8 @@
     }

     else {
+      Serial.print("Buffer pos ");
+      Serial.println(serialBufferPos);
       serialBufferPos++;
     }

@@ -211,12 +209,13 @@

   // Timeout checking
   else {
+
     unsigned long current_time = millis();
     // If the time wrapped around, can't just subtract them, take the difference from max and then the current_time
     if ( current_time <= alive ){
       unsigned long max_long = (unsigned long) -1;
       if ( ((max_long - alive) + current_time ) >= ALIVE_TIMEOUT ){
-        Serial.println("Timed out, thrusters off");
+        Serial.println("Overflow Timed out, thrusters off");
         thrustersOff();
         timedout = true;
       }
@@ -230,6 +229,5 @@
   }

   //here we put code that we need to run with or without the jetsons attached
-
-}
-
+}
+


DEBUG_PRINT

--- _02-mqtt-sw-temperature/_02-mqtt-sw-temperature.ino
+++ _02-mqtt-sw-temperature/_02-mqtt-sw-temperature.ino
@@ -87,10 +87,12 @@

 void wifi_connect() {
   // WIFI
-  Serial.println();
-  Serial.println();
-  Serial.print("Connecting to ");
-  Serial.println(ssid);
+  if (DEBUG_PRINT) {
+    Serial.println();
+    Serial.println();
+    Serial.print("Connecting to ");
+    Serial.println(ssid);
+  }

   WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, password);
@@ -99,41 +101,26 @@
   while (WiFi.status() != WL_CONNECTED) {
     delay(100);
     Attempt++;
-    Serial.print(".");
+    if (DEBUG_PRINT) {
+      Serial.print(".");
+    }
     if (Attempt == 200)
     {
-      Serial.println();
-      Serial.println("Could not connect to WIFI");
+      if (DEBUG_PRINT) {
+        Serial.println();
+        Serial.println("Could not connect to WIFI");
+      }
       ESP.restart();
     }
   }

-  Serial.println("");
-  Serial.println("WiFi connected");
-  Serial.println("IP address: ");
-  Serial.println(WiFi.localIP());
-
-  /*
-    timemillis = millis();
-
-    if (WiFi.status() == WL_CONNECTED) {
-      if (!client.connected()) {
-        if (client.connect((char*) clientName.c_str(), willTopic, 0, true, willMessage)) {
-          client.publish(willTopic, "1", true);
-          client.publish(hellotopic, "hello again wifi and mqtt from ESP8266 s02");
-          client.subscribe(subtopic);
-
-          Serial.println("reconnecting wifi and mqtt");
-        } else {
-          Serial.println("mqtt publish fail after wifi reconnect");
-        }
-      } else {
-        client.publish(willTopic, "1", true);
-        client.publish(hellotopic, "hello again wifi from ESP8266 s02");
-        client.subscribe(subtopic);
-      }
-    }
-  */
+  if (DEBUG_PRINT) {
+    Serial.println("");
+    Serial.println("WiFi connected");
+    Serial.println("IP address: ");
+    Serial.println(WiFi.localIP());
+  }
+
 }

 boolean reconnect()
@@ -143,10 +130,14 @@
       client.publish(willTopic, "1", true);
       client.publish(hellotopic, "hello again 1 from ESP8266 s02");
       client.subscribe(subtopic);
-      Serial.println("connected");
+      if (DEBUG_PRINT) {
+        Serial.println("connected");
+      }
     } else {
-      Serial.print("failed, rc=");
-      Serial.println(client.state());
+      if (DEBUG_PRINT) {
+        Serial.print("failed, rc=");
+        Serial.println(client.state());
+      }
     }
   }
   //timemillis = millis();
@@ -171,7 +162,7 @@
   if ( receivedpayload == "{\"LIGHT\":1}") {
     relaystatus = 1 ;
   }
-  if ( receivedpayload == "{\"LIGHT\":0}") {
+  else if ( receivedpayload == "{\"LIGHT\":0}") {
     relaystatus = 0 ;
   }

@@ -190,9 +181,11 @@
     Serial.begin(74880);
   }
   delay(20);
-  Serial.println("DHTxx test!");
-  Serial.println("ESP.getFlashChipSize() : ");
-  Serial.println(ESP.getFlashChipSize());
+  if (DEBUG_PRINT) {
+    Serial.println("DHTxx test!");
+    Serial.println("ESP.getFlashChipSize() : ");
+    Serial.println(ESP.getFlashChipSize());
+  }
   delay(20);

   startMills = millis();
@@ -228,36 +221,54 @@
         client.publish(willTopic, "1", true);
         client.publish(hellotopic, (char*) getResetInfo.c_str());
         client.subscribe(subtopic);
-        Serial.print("Sending payload: ");
-        Serial.println(getResetInfo);
+        if (DEBUG_PRINT) {
+          Serial.print("Sending payload: ");
+          Serial.println(getResetInfo);
+        }
       }
     } else {
       client.publish(willTopic, "1", true);
       client.publish(hellotopic, (char*) getResetInfo.c_str());
       client.subscribe(subtopic);
-      Serial.print("Sending payload: ");
-      Serial.println(getResetInfo);
+      if (DEBUG_PRINT) {
+        Serial.print("Sending payload: ");
+        Serial.println(getResetInfo);
+      }
     }
   }

   //
-  Serial.println("Starting UDP");
+  if (DEBUG_PRINT) {
+    Serial.println("Starting UDP");
+  }
   udp.begin(localPort);
-  Serial.print("Local port: ");
-  Serial.println(udp.localPort());
+  if (DEBUG_PRINT) {
+    Serial.print("Local port: ");
+    Serial.println(udp.localPort());
+  }
   delay(1000);
   setSyncProvider(getNtpTime);

   if (timeStatus() == timeNotSet) {
-    Serial.println("waiting for sync message");
+    if (DEBUG_PRINT) {
+      Serial.println("waiting for sync message");
+    }
   }

   attachInterrupt(13, motion_detection, RISING);
   attachInterrupt(5, run_lightcmd, CHANGE);

   sensors.begin();
-  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
-  if (!sensors.getAddress(outsideThermometer, 1)) Serial.println("Unable to find address for Device 1");
+  if (!sensors.getAddress(insideThermometer, 0)) {
+    if (DEBUG_PRINT) {
+      Serial.println("Unable to find address for Device 0");
+    }
+  }
+  if (!sensors.getAddress(outsideThermometer, 1)) {
+    if (DEBUG_PRINT) {
+      Serial.println("Unable to find address for Device 1");
+    }
+  }

   // set the resolution to 9 bit
   sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
@@ -270,7 +281,9 @@
   f = dht.readTemperature(true);

   if (isnan(h) || isnan(t) || isnan(f)) {
-    Serial.println("Failed to read from DHT sensor!");
+    if (DEBUG_PRINT) {
+      Serial.println("Failed to read from DHT sensor!");
+    }
     return;
   }

@@ -279,7 +292,9 @@
   tempCoutside = sensors.getTempC(insideThermometer);

   if ( isnan(tempCinside) || isnan(tempCoutside) ) {
-    Serial.println("Failed to read from sensor!");
+    if (DEBUG_PRINT) {
+      Serial.println("Failed to read from sensor!");
+    }
     return;
   }
 }
@@ -288,8 +303,10 @@
 {
   if (WiFi.status() == WL_CONNECTED) {
     if (!client.connected()) {
-      Serial.print("failed, rc=");
-      Serial.print(client.state());
+      if (DEBUG_PRINT) {
+        Serial.print("failed, rc=");
+        Serial.print(client.state());
+      }

       long now = millis();
       if (now - lastReconnectAttempt > 5000) {
@@ -375,19 +392,22 @@
 {
   //  if ( relaystatus != oldrelaystatus )
   //  {
-  Serial.print(" => ");
-  Serial.println("checking relay status changelight");
-  delay(10);
+  if (DEBUG_PRINT) {
+    Serial.print(" => ");
+    Serial.println("checking relay status changelight");
+  }
+  delay(30);
   digitalWrite(RELAYPIN, relaystatus);
-  delay(20);
+  delay(30);
   digitalWrite(RELAYPIN, relaystatus);
-  delay(20);
+  delay(30);
   digitalWrite(RELAYPIN, relaystatus);
-  delay(20);
+  delay(30);
   //oldrelaystatus = relaystatus ;
-  Serial.print(" => ");
-  Serial.println("changing relay status");
-
+  if (DEBUG_PRINT) {
+    Serial.print(" => ");
+    Serial.println("changing relay status");
+  }
   //sendlightstatus();
   //}
 }
@@ -400,7 +420,9 @@
   f = dht.readTemperature(true);

   if (isnan(h) || isnan(t) || isnan(f)) {
-    Serial.println("Failed to read from DHT sensor!");
+    if (DEBUG_PRINT) {
+      Serial.println("Failed to read from DHT sensor!");
+    }
   }

   float hi = dht.computeHeatIndex(f, h);
@@ -413,7 +435,9 @@
   tempCoutside = sensors.getTempC(insideThermometer);

   if ( isnan(tempCinside) || isnan(tempCoutside) ) {
-    Serial.println("Failed to read from sensor!");
+    if (DEBUG_PRINT) {
+      Serial.println("Failed to read from sensor!");
+    }
   }
 }

@@ -432,33 +456,32 @@

 void sendmqttMsg(char* topictosend, String payload)
 {
-  /*
-  if (!client.connected()) {
-    if (client.connect((char*) clientName.c_str(), willTopic, 0, true, willMessage)) {
-      client.publish(willTopic, "1", true);
-      client.publish(hellotopic, "hello again 2 from ESP8266 s02");
-      client.subscribe(subtopic);
-    }
-  }
-  */

   if (client.connected()) {
-    Serial.print("Sending payload: ");
-    Serial.print(payload);
+    if (DEBUG_PRINT) {
+      Serial.print("Sending payload: ");
+      Serial.print(payload);
+    }

     unsigned int msg_length = payload.length();

-    Serial.print(" length: ");
-    Serial.println(msg_length);
+    if (DEBUG_PRINT) {
+      Serial.print(" length: ");
+      Serial.println(msg_length);
+    }

     byte* p = (byte*)malloc(msg_length);
     memcpy(p, (char*) payload.c_str(), msg_length);

     if ( client.publish(topictosend, p, msg_length, 1)) {
-      Serial.println("Publish ok");
+      if (DEBUG_PRINT) {
+        Serial.println("Publish ok");
+      }
       free(p);
     } else {
-      Serial.println("Publish failed");
+      if (DEBUG_PRINT) {
+        Serial.println("Publish failed");
+      }
       free(p);
     }
   }
@@ -494,14 +517,18 @@
 time_t getNtpTime()
 {
   while (udp.parsePacket() > 0) ; // discard any previously received packets
-  Serial.println("Transmit NTP Request called");
+  if (DEBUG_PRINT) {
+    Serial.println("Transmit NTP Request called");
+  }
   sendNTPpacket(timeServer);
   delay(1000);
   uint32_t beginWait = millis();
   while (millis() - beginWait < 1500) {
     int size = udp.parsePacket();
     if (size >= NTP_PACKET_SIZE) {
-      Serial.println("Receive NTP Response");
+      if (DEBUG_PRINT) {
+        Serial.println("Receive NTP Response");
+      }
       udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
       unsigned long secsSince1900;
       // convert four bytes starting at location 40 to a long integer
@@ -512,15 +539,19 @@
       return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
     }
   }
-  Serial.println(millis() - beginWait);
-  Serial.println("No NTP Response :-(");
+  if (DEBUG_PRINT) {
+    Serial.println(millis() - beginWait);
+    Serial.println("No NTP Response :-(");
+  }
   return 0; // return 0 if unable to get the time
 }

 // send an NTP request to the time server at the given address
 void sendNTPpacket(IPAddress & address)
 {
-  Serial.println("Transmit NTP Request");
+  if (DEBUG_PRINT) {
+    Serial.println("Transmit NTP Request");
+  }
   // set all bytes in the buffer to 0
   memset(packetBuffer, 0, NTP_PACKET_SIZE);
   // Initialize values needed to form NTP request
@@ -539,7 +570,9 @@
   udp.beginPacket(address, 123); //NTP requests are to port 123
   udp.write(packetBuffer, NTP_PACKET_SIZE);
   udp.endPacket();
-  Serial.println("Transmit NTP Sent");
-}
-//
-//
+  if (DEBUG_PRINT) {
+    Serial.println("Transmit NTP Sent");
+  }
+}
+//
+//


Remove duplicate Arduboy.h include

Remove duplicate Arduboy.h include

--- examples/ArduBreakout/ArduBreakout.ino
+++ examples/ArduBreakout/ArduBreakout.ino
@@ -10,7 +10,6 @@
  */

 #include <Arduboy.h>
-#include "Arduboy.h"
 #include <ArduboyPlaytune.h>
 #include "breakout_bitmaps.h"


make inArgv const correct

make inArgv const correct

--- examples/BasicExample/BasicExample.ino
+++ examples/BasicExample/BasicExample.ino
@@ -84,8 +84,8 @@

 	bool
 	SerialCmdHello(
-		int		inArgC,
-		char*	inArgv[])
+		int			inArgC,
+		char const*	inArgv[])
 	{
 		Serial.printf("Hello World\n");


ledvo final tweak

ledvo final tweak

--- proj/ledvo_lounge_final/ledvo_lounge_final.ino
+++ proj/ledvo_lounge_final/ledvo_lounge_final.ino
@@ -80,7 +80,7 @@

 // For animation switching, this number needs to be hard coded unforunately
 //const uint8_t numAnimation = 11;
-const uint8_t numAnimation = 3;
+const uint8_t numAnimation = 6;
 uint8_t chaser_opt = 0; // For choosing the sub patterns on the animations that use chasers

 void setup() {
@@ -226,18 +226,21 @@
     // Select animation to run based on global counter
     if (!dj_control) {
       if (gAnimCounter == 0) {
+        fill_all();
+      }
+      else if (gAnimCounter == 1) {
         trap_solid();
       }
-      else if (gAnimCounter == 1) {
+      else if (gAnimCounter == 2) {
         saw_chaser_0(chaser_opt);
       }
-      else if (gAnimCounter == 2) {
+      else if (gAnimCounter == 3) {
         saw_chaser_1(chaser_opt);
       }
-      else if (gAnimCounter == 3) {
+      else if (gAnimCounter == 4) {
         saw_solid_0();
       }
-      else if (gAnimCounter == 4) {
+      else if (gAnimCounter == 5) {
         saw_solid_1();
       }
       /*if (gAnimCounter == 0) {


redefines led blink for common anode prototype

--- SQUARES/firmware_latest/firmware_latest.ino
+++ SQUARES/firmware_latest/firmware_latest.ino
@@ -31,6 +31,8 @@
 String payload;
 char c_payload[19];

+#define COMMON_ANODE
+
 #define FADE_TIME 2000
 #define DIR_UP 1
 #define DIR_DOWN -1
@@ -86,15 +88,15 @@
   pinMode(VIBRO_PIN, OUTPUT);

   //blink the LEDS to test they are actually working
+  digitalWrite(GREEN_LED_PIN, LOW);
+  delay(250);
+  digitalWrite(RED_LED_PIN, LOW);
+  delay(250);
+  digitalWrite(BLUE_LED_PIN, LOW);
+  delay(500);
   digitalWrite(GREEN_LED_PIN, HIGH);
-  delay(250);
   digitalWrite(RED_LED_PIN, HIGH);
-  delay(250);
   digitalWrite(BLUE_LED_PIN, HIGH);
-  delay(500);
-  digitalWrite(GREEN_LED_PIN, LOW);
-  digitalWrite(RED_LED_PIN, LOW);
-  digitalWrite(BLUE_LED_PIN, LOW);

   //Setup Bluetooth Connectivity
   //set the device name


- change PM25 app to have new APP ID - change version number to 0.7.5

--- Device_LinkItOne/LASS/LASS.ino
+++ Device_LinkItOne/LASS/LASS.ino
@@ -96,8 +96,9 @@
 #define VER_FORMAT "3"	// version number has been increased to 2 since v0.7.0
 #define FMT_OPT 0 // FMT_OPT : 0: default format with gps, 1: default format but gps is fix data, need to update GPS_FIX_INFOR
     // ( format is right, but no actual gps information because no gps device exist )
-#define VER_APP "0.7.4"
-
+#define VER_APP "0.7.5"
+
+#define APPTYPE_SYSTEM_BASE 0
 #define APPTYPE_PUBLIC_BASE 256
 #define APPTYPE_PRIVATE_BASE 32768

@@ -139,8 +140,15 @@
 //----- SENSOR CUSTOMIZATION -----
 // Sensor README:

-#define APP_ID (APPTYPE_PUBLIC_BASE+4)               // REPLACE: this is your unique application 0-255: system reserved, 256-32767: user public use, 32768-65536: private purpose
-#if APP_ID==(APPTYPE_PUBLIC_BASE+2)
+#define APP_ID (APPTYPE_SYSTEM_BASE+1)               // REPLACE: this is your unique application 0-255: system reserved, 256-32767: user public use, 32768-65536: private purpose
+#if APP_ID==(APPTYPE_SYSTEM_BASE+1)
+  #define APP_NAME "PM25" // REPLACE: this is your unique application name
+  #include <DHT_linkit.h>     // Reference: https://github.com/Seeed-Studio/Grove_Starter_Kit_For_LinkIt/tree/master/libraries/Humidity_Temperature_Sensor
+  #include <KalmanFilter.h>
+  #define DHTPIN 2
+  #define DHTTYPE DHT22   // DHT 22  (AM2302)
+  DHT_linkit dht(DHTPIN, DHTTYPE);
+#elif APP_ID==(APPTYPE_PUBLIC_BASE+2)
   #define APP_NAME "EXAMPLE_APP1" // REPLACE: this is your unique application name
 #elif APP_ID==(APPTYPE_PUBLIC_BASE+1)
   #define APP_NAME "Wuulong" // REPLACE: this is your unique application name
@@ -157,13 +165,6 @@
   KalmanFilter t_filter;    //temperature filter
   KalmanFilter p_filter;    //pressure filter
   KalmanFilter a_filter;    //altitude filter
-#elif APP_ID==(APPTYPE_PUBLIC_BASE+4)
-  #define APP_NAME "PM25" // REPLACE: this is your unique application name
-  #include <DHT_linkit.h>     // Reference: https://github.com/Seeed-Studio/Grove_Starter_Kit_For_LinkIt/tree/master/libraries/Humidity_Temperature_Sensor
-  #include <KalmanFilter.h>
-  #define DHTPIN 2
-  #define DHTTYPE DHT22   // DHT 22  (AM2302)
-  DHT_linkit dht(DHTPIN, DHTTYPE);
 #endif

 #define SENSOR_ID_RECORDID 0
@@ -171,7 +172,15 @@
 #define SENSOR_ID_BATTERYCHARGING 2 //      battery is charging: (0) not charging, (1) charging
 #define SENSOR_ID_GROUNDSPEED 3

-#if APP_ID==(APPTYPE_PUBLIC_BASE+2)
+#if APP_ID==(APPTYPE_SYSTEM_BASE+1)
+  #define SENSOR_ID_DUST 10
+  #define SENSOR_ID_TEMPERATURE 11
+  #define SENSOR_ID_HUMIDITY 12
+  #define SENSOR_ID_DUST_BLYNK 4
+  #define SENSOR_ID_TEMPERATURE_BLYNK 5
+  #define SENSOR_ID_HUMIDITY_BLYNK 6
+
+#elif APP_ID==(APPTYPE_PUBLIC_BASE+2)
   #define SENSOR_ID_DUST 10
   #define SENSOR_ID_DUST_BLYNK 4

@@ -194,13 +203,6 @@
   #define SENSOR_ID_TEMPERATURE_BLYNK 5
   #define SENSOR_ID_HUMIDITY_BLYNK 6
   #define SENSOR_ID_LIGHT_BLYNK 7
-#elif APP_ID==(APPTYPE_PUBLIC_BASE+4)
-  #define SENSOR_ID_DUST 10
-  #define SENSOR_ID_TEMPERATURE 11
-  #define SENSOR_ID_HUMIDITY 12
-  #define SENSOR_ID_DUST_BLYNK 4
-  #define SENSOR_ID_TEMPERATURE_BLYNK 5
-  #define SENSOR_ID_HUMIDITY_BLYNK 6
 #endif

 enum pinSensorConfig{
@@ -271,7 +273,7 @@
 //----- MQTT -----
 #define MQTT_PROXY_IP "gpssensor.ddns.net"  // Current LASD server
 #define DEVICE_TYPE  "LinkItONE"
-#define DEVICE_ID "Wuulong1"    // REPLACE: The device ID you like, please start from LASD. Without this prefix, maybe it will be filter out.
+#define DEVICE_ID "YOUR_DEVICE_NAME"    // REPLACE: The device ID you like, please start from LASD. Without this prefix, maybe it will be filter out.
 #define MQTT_TOPIC_PREFIX "LASS/Test"
 #define PARTNER_ID "LASS-Partner1"
 char mqttTopic[64];
@@ -405,7 +407,10 @@
   pinMode(DUST_SENSOR_PIN, INPUT);

-#if APP_ID == (APPTYPE_PUBLIC_BASE+3)
+#if APP_ID == (APPTYPE_SYSTEM_BASE+1)
+      // Grove - Temperature and Humidity Sensor Pro
+    dht.begin();
+#elif APP_ID == (APPTYPE_PUBLIC_BASE+3)
       // Grove - Temperature and Humidity Sensor Pro
     dht.begin();

@@ -424,9 +429,6 @@
     } else {
       Serial.println("HP20x_dev isn't available.");
     }
-#elif APP_ID == (APPTYPE_PUBLIC_BASE+4)
-      // Grove - Temperature and Humidity Sensor Pro
-    dht.begin();
 #endif

 }
@@ -656,7 +658,11 @@
   strcpy(sensorType[1], "1");
   strcpy(sensorType[2], "2");
   strcpy(sensorType[3], "3");
-#if APP_ID == (APPTYPE_PUBLIC_BASE+2)
+#if APP_ID == (APPTYPE_SYSTEM_BASE+1)
+  strcpy(sensorType[SENSOR_ID_DUST],"d0");
+  strcpy(sensorType[SENSOR_ID_TEMPERATURE], "t0");
+  strcpy(sensorType[SENSOR_ID_HUMIDITY],"h0");
+#elif APP_ID == (APPTYPE_PUBLIC_BASE+2)
   strcpy(sensorType[SENSOR_ID_DUST],"d0");
 #elif APP_ID == (APPTYPE_PUBLIC_BASE+1)
   strcpy(sensorType[SENSOR_ID_DUST],"d0");
@@ -667,10 +673,6 @@
   strcpy(sensorType[SENSOR_ID_TEMPERATURE], "t0");
   strcpy(sensorType[SENSOR_ID_HUMIDITY],"h0");
   strcpy(sensorType[SENSOR_ID_LIGHT], "l0");
-#elif APP_ID == (APPTYPE_PUBLIC_BASE+4)
-  strcpy(sensorType[SENSOR_ID_DUST],"d0");
-  strcpy(sensorType[SENSOR_ID_TEMPERATURE], "t0");
-  strcpy(sensorType[SENSOR_ID_HUMIDITY],"h0");
 #endif

@@ -698,7 +700,29 @@
     Serial.println(sensorValue[SENSOR_ID_GROUNDSPEED]);

     //sensor 10-19: user sensor
-#if APP_ID == (APPTYPE_PUBLIC_BASE+1)
+#if APP_ID == (APPTYPE_SYSTEM_BASE+1)
+      Serial.print("[Performence TIME-COUNT]:");
+      timecount=millis()-timecount;
+      Serial.println(timecount);
+      timecount=millis();
+      sensorValue[SENSOR_ID_DUST] = (float)pm25sensorG3();
+      Serial.print("[SENSOR-DUST]:");
+      Serial.println(sensorValue[SENSOR_ID_DUST]);
+
+      float h,t;
+      dht.readHT(&t, &h);
+      while (isnan(t) || isnan(h) || t<0 || t>80 || h<0 || h > 100){
+        Serial.println("Something wrong with DHT => retry it!");
+        delay(100);
+        dht.readHT(&t, &h);
+      }
+      sensorValue[SENSOR_ID_TEMPERATURE] = t;
+      Serial.print("SensorValue(Temperature):");
+      Serial.println(sensorValue[SENSOR_ID_TEMPERATURE]);
+      sensorValue[SENSOR_ID_HUMIDITY] = h;
+      Serial.print("SensorValue(Humidity):");
+      Serial.println(sensorValue[SENSOR_ID_HUMIDITY]);
+#elif APP_ID == (APPTYPE_PUBLIC_BASE+1)
       Serial.println("Measure dust, take 30 seconds ...");
       get_sensor_data_dust();
       Serial.print("SensorValue(dust sensor):");
@@ -745,28 +769,6 @@
       sensorValue[SENSOR_ID_LIGHT] = TSL2561.readVisibleLux();
       Serial.print("SensorValue(Light):");
       Serial.println(sensorValue[SENSOR_ID_LIGHT]);
-#elif APP_ID == (APPTYPE_PUBLIC_BASE+4)
-      Serial.print("[Performence TIME-COUNT]:");
-      timecount=millis()-timecount;
-      Serial.println(timecount);
-      timecount=millis();
-      sensorValue[SENSOR_ID_DUST] = (float)pm25sensorG3();
-      Serial.print("[SENSOR-DUST]:");
-      Serial.println(sensorValue[SENSOR_ID_DUST]);
-
-      float h,t;
-      dht.readHT(&t, &h);
-      while (isnan(t) || isnan(h) || t<0 || t>80 || h<0 || h > 100){
-        Serial.println("Something wrong with DHT => retry it!");
-        delay(100);
-        dht.readHT(&t, &h);
-      }
-      sensorValue[SENSOR_ID_TEMPERATURE] = t;
-      Serial.print("SensorValue(Temperature):");
-      Serial.println(sensorValue[SENSOR_ID_TEMPERATURE]);
-      sensorValue[SENSOR_ID_HUMIDITY] = h;
-      Serial.print("SensorValue(Humidity):");
-      Serial.println(sensorValue[SENSOR_ID_HUMIDITY]);
 #endif

 /*
@@ -829,7 +831,20 @@

-#if APP_ID==(APPTYPE_PUBLIC_BASE+1)
+#if APP_ID==(APPTYPE_SYSTEM_BASE+1)
+BLYNK_READ(SENSOR_ID_DUST_BLYNK)
+{
+  Blynk.virtualWrite(SENSOR_ID_DUST_BLYNK, sensorValue[SENSOR_ID_DUST]);
+}
+BLYNK_READ(SENSOR_ID_TEMPERATURE_BLYNK)
+{
+  Blynk.virtualWrite(SENSOR_ID_TEMPERATURE_BLYNK, sensorValue[SENSOR_ID_TEMPERATURE]);
+}
+BLYNK_READ(SENSOR_ID_BHUMIDITY_BLYNK)
+{
+  Blynk.virtualWrite(SENSOR_ID_HUMIDITY_BLYNK, sensorValue[SENSOR_ID_HUMIDITY]);
+}
+#elif APP_ID==(APPTYPE_PUBLIC_BASE+1)
 BLYNK_READ(SENSOR_ID_DUST_BLYNK)
 {
   Blynk.virtualWrite(SENSOR_ID_DUST_BLYNK, sensorValue[SENSOR_ID_DUST]);
@@ -864,19 +879,6 @@
 BLYNK_READ(SENSOR_ID_LIGHT_BLYNK)
 {
   Blynk.virtualWrite(SENSOR_ID_LIGHT_BLYNK, sensorValue[SENSOR_ID_LIGHT]);
-}
-#elif APP_ID==(APPTYPE_PUBLIC_BASE+4)
-BLYNK_READ(SENSOR_ID_DUST_BLYNK)
-{
-  Blynk.virtualWrite(SENSOR_ID_BAROMETER_BLYNK, sensorValue[SENSOR_ID_DUST]);
-}
-BLYNK_READ(SENSOR_ID_TEMPERATURE_BLYNK)
-{
-  Blynk.virtualWrite(SENSOR_ID_TEMPERATURE_BLYNK, sensorValue[SENSOR_ID_TEMPERATURE]);
-}
-BLYNK_READ(SENSOR_ID_BHUMIDITY_BLYNK)
-{
-  Blynk.virtualWrite(SENSOR_ID_HUMIDITY_BLYNK, sensorValue[SENSOR_ID_HUMIDITY]);
 }
 #endif


declare wifi mode prior to connect

declare wifi mode prior to connect

must have statement for current Arduino Framework, see also https://github.com/knolleary/pubsubclient/issues/138#issuecomment-326113915

--- examples/mqtt_esp8266/mqtt_esp8266.ino
+++ examples/mqtt_esp8266/mqtt_esp8266.ino
@@ -42,6 +42,7 @@
   Serial.print("Connecting to ");
   Serial.println(ssid);

+  WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, password);

   while (WiFi.status() != WL_CONNECTED) {


Neue IP

Neue IP

--- arduino/sensebox/sensebox.ino
+++ arduino/sensebox/sensebox.ino
@@ -40,7 +40,7 @@

 //Configure ethernet connection
-IPAddress myIp(192, 168, 137, 42);
+IPAddress myIp(192, 168, 42, 42);
 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
 char server[] = "www.opensensemap.org";
 EthernetClient client;
@@ -173,7 +173,8 @@
     client.print(sensorId);
     client.println(F(" HTTP/1.1"));
     // Send the required header parameters
-    client.println(F("Host:opensensemap.org"));
+    client.print(F("Host: "));
+    client.println(server);
     client.println(F("Content-Type: application/json"));
     client.println(F("Connection: close"));
     client.print(F("Content-Length: "));


updated testing for ultrasonic

updated testing for ultrasonic

--- arduino/main/main.ino
+++ arduino/main/main.ino
@@ -1,26 +1,26 @@

 #include "Arduino.h"
-#include "sensors/turbidity/turbidity.h"
+//#include "sensors/turbidity/turbidity.h"
 #include "sensors/ultrasonic/ultrasonic.h"
-#include "sensors/temperature/temperature.h"
-#include "sensors/dissolvedO2/dissolvedO2.h"
+//#include "sensors/temperature/temperature.h"
+//#include "sensors/dissolvedO2/dissolvedO2.h"

 void serialPrintResult();

 void setup()
 {
-  turbidity.SETUP();
+  //turbidity.SETUP();
   ultrasonic.SETUP();
   Serial.begin(9600);
-  temperature.SETUP();
+  //temperature.SETUP();

 }

 void loop()
 {
-  turbidity.TURBIDITY();
+  //turbidity.TURBIDITY();
   ultrasonic.DISTANCE();
-  temperature.TEMPERATURE();
+  //temperature.TEMPERATURE();
   delay(10);
   // insert error handling
   serialPrintResult();
@@ -31,15 +31,15 @@

 void serialPrintResult()
 {
-  Serial.print("Turbidity: ");
-  Serial.println(turbidity.turbidityVoltageOutput);
-   Serial.print("Distance: ");
-   Serial.println(ultrasonic.distanceTravelled);
-   Serial.print("Celcius: ");
-   Serial.println(temperature.cel);
-   Serial.println("Farenheit: ");
-   Serial.println(temperature.farh);
-   Serial.println(" ");
+  //Serial.print("Turbidity: ");
+  //Serial.println(turbidity.turbidityVoltageOutput);
+  Serial.print("Distance: ");
+  Serial.println(ultrasonic.distanceTravelled);
+//   Serial.print("Celcius: ");
+//   Serial.println(temperature.cel);
+//   Serial.println("Farenheit: ");
+//   Serial.println(temperature.farh);
+//   Serial.println(" ");

 }


Update code.ino

Update code.ino

--- code/code.ino
+++ code/code.ino
@@ -110,6 +110,7 @@
    calculateKinematics();
 //printAngles();
    //getMagnet();
+    //calibrateMagnetometer();
     //printMagnet();
     //Serial.println(deltaTime);
     previousTime=currentTime;


Simple (too bad yet) task example

Simple (too bad yet) task example

--- Multitasking-Ardiuno.ino
+++ Multitasking-Ardiuno.ino
@@ -1,13 +1,36 @@
+#include "Multitasking/Multitasking.h"
+
+class BlinkerTask : public TaskBase
+{
+private:
+	byte pin;
+	bool state;
+public:
+	explicit BlinkerTask(byte pin)
+		: TaskBase(), pin(pin), state()
+	{
+		pinMode(pin, OUTPUT);
+	}
+
+	virtual bool Step() override
+	{
+		delay(100);
+		digitalWrite(pin, state = !state);
+		return false;
+	}
+};
+
 void setup()
 {
+	Scheduler<16> scheduler;

-  /* add setup code here */
+	BlinkerTask blinker(13);

+	scheduler.AddTask(&blinker);
+
+	scheduler.Run();
 }

 void loop()
 {
-
-  /* add main program code here */
-
 }


Implemented background pattern driving

Implemented background pattern driving


faster pwm

faster pwm

--- pug.ino
+++ pug.ino
@@ -148,7 +148,7 @@
   pinMode(rightMotorPin1, OUTPUT);
   pinMode(rightMotorPin2, OUTPUT);

-  motorTimer.begin(_motorsLivecycle, 30);
+  motorTimer.begin(_motorsLivecycle, 10);
   ultraTimer.begin(_ultrasonLivecycle, 50000);

   // Debug led


sensV updated

sensV updated

--- sensV/src/sketch.ino
+++ sensV/src/sketch.ino
@@ -9,9 +9,11 @@
 #define activityLED 3

 // *** declare constants
-const float ref5V = 5.14;   // reference: 5.0V on measurePin == 1023.0
-const float R1 = 100000.0;  // Resistor value used for R1
-const float R2 = 10000.0;   // Resistor value used for R2
+const float ref5V = 5.14;   // reference: 5.14V on measurePin == 1023.0
+//const float R1 = 100000.0;  // Resistor value used for R1
+const float R1 = 99300.0;  // Measured resistor value used for R1
+//const float R2 = 10000.0;   // Resistor value used for R2
+const float R2 = 9870.0;   // Measured resistor value used for R2

 // (numSamples ^ 0.5) is the S/N ratio that can be achieved.
 // To get a S/N-ratio of 3 requires 9 samples. S/N=4 requires 16 samples
@@ -22,15 +24,14 @@
 const int numSamples = 16;  // number of measurements used for one result

 // *** declare calculated constants
-const float ratioRes = (R2/(R1 + R2));
-const float scaleRaw2Volts = ref5V / (ratioRes * 1023.0);
+const float ratioRes = ((R1 + R2)/R2) * 0.00001; // multiply by 1e-5 to get V

 // *** declare variables
 int sumSamples = 0;         // sum of samples
 int cntSamples = 0;         // sample counter
 float voltage = 0.0;
-unsigned long startTime;
-unsigned long elapsedTime;
+unsigned long startTime = 0;
+unsigned long elapsedTime = 0;

 void setup()
 {
@@ -47,12 +48,12 @@
   // *** Add up the pre-defined number of samples for Sample Averaging
   for (cntSamples = 0; cntSamples < numSamples; cntSamples++) {
     sumSamples += analogRead(measurePin);
-    delay(10);
+    delay(200);
   }

   // *** Determine the source voltage:
   voltage = (float)sumSamples / (float)cntSamples; // Calculate avg raw value.
-  voltage *= scaleRaw2Volts;      // Scale avg raw value to source voltage.
+  voltage = map(voltage * 10, 0, 1023, 0, ref5V * 10000) * ratioRes;

   Serial.print(voltage);
   Serial.println(" V");


Destroy old animations

Destroy old animations

--- jacket.ino
+++ jacket.ino
@@ -245,6 +245,8 @@
   if (!lastAnim) {
     lastAnim = anim;
     animTransition = 255;
+  } else {
+    delete anim;
   }

   // Start up the new animation


Ajouté détection des faces

Ajouté détection des faces

--- eqbe.ino
+++ eqbe.ino
@@ -56,6 +56,9 @@
 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; //These will be the raw data from the MPU6050.;
 #define ACCELEROMETER_ORIENTATION 4     // 0, 1, 2, 3 or 4 to set the orientation of the accerometer module
 int a_forward=0,a_sideway=0,a_vertical=0;
+enum FACES { FACE_NONE, FACE_1, FACE_2, FACE_3, FACE_4, FACE_5, FACE_6, FACES_COUNT };
+const char *faceName[FACES_COUNT] = { "None", "Face 1", "Face 2", "Face 3", "Face 4", "Face 5 (LEDs up)", "Face 6 (LEDs down)" };
+uint8_t orientation = FACE_NONE;

 void solid()
 {
@@ -418,6 +421,33 @@

   Serial.printf("f:%d s:%d v:%d\n", a_forward,a_sideway,a_vertical);

-
-}
-
+  // Detect cube orientation - Current test works with ACCELEROMETER_ORIENTATION = 4
+  orientation=FACE_NONE;
+  if (a_vertical >= 80 && abs(a_forward) <= 25 && abs(a_sideway) <= 25) {
+    // coté 1 en haut
+    orientation = FACE_1;
+  }
+  if (a_forward >= 80 && abs(a_vertical) <= 25 && abs(a_sideway) <= 25) {
+    // coté 2 en haut
+    orientation = FACE_2;
+  }
+  if (a_vertical <= -80 && abs(a_forward) <= 25 && abs(a_sideway) <= 25) {
+    // coté 3 en haut
+    orientation = FACE_3;
+  }
+  if (a_forward <= -80 && abs(a_vertical) <= 25 && abs(a_sideway) <= 25) {
+    // coté 4 en haut
+    orientation = FACE_4;
+  }
+  if (a_sideway >= 80 && abs(a_vertical) <= 25 && abs(a_forward) <= 25) {
+    // coté LEDs en haut
+    orientation = FACE_5;
+  }
+  if (a_sideway <= -80 && abs(a_vertical) <= 25 && abs(a_forward) <= 25) {
+    // coté batteries en haut
+    orientation = FACE_6;
+  }
+
+  Serial.printf("Orientation: %s\n", faceName[orientation]);
+}
+


Samll change to fix the LEDs flickering problem

--- eqbe.ino
+++ eqbe.ino
@@ -3,6 +3,7 @@

 // External Library
 #include "painlessMesh.h"
+#define FASTLED_ALLOW_INTERRUPTS 0  // To fix flickering issue https://github.com/FastLED/FastLED/issues/306
 #include "FastLED.h"
 FASTLED_USING_NAMESPACE

@@ -14,7 +15,8 @@
 #define BRIGHTNESS          30
 #define FRAMES_PER_SECOND   60 // 125 frames/sec <=> 8 milli/frame

-#define NUM_LEDS  25
+//#define NUM_LEDS  25
+#define NUM_LEDS  64

 #define LED_TYPE    WS2812B
 #define COLOR_ORDER GRB


detachのレスポンスメッセージを忘れていたのを修正.

detachのレスポンスメッセージを忘れていたのを修正.

--- arduino/GeneralIoSerial/GeneralIoSerial.ino
+++ arduino/GeneralIoSerial/GeneralIoSerial.ino
@@ -115,6 +115,7 @@
 const prog_char JSON_FORMAT_WRAP_EVENT[] PROGMEM       = "{\"event\":\"%s\",\"data\":%s}";
 const prog_char JSON_FORMAT_INTERRUPT[] PROGMEM        = "{\"msg\":\"OK\",\"num\":%d,\"count\":%d}";
 const prog_char JSON_FORMAT_ATTACH_INTERRUPT[] PROGMEM = "{\"msg\":\"OK\",\"num\":%d,\"mode\":\"%s\"}";
+const prog_char JSON_FORMAT_DETACH_INTERRUPT[] PROGMEM = "{\"msg\":\"OK\",\"num\":%d}";
 const prog_char JSON_FORMAT_IO[] PROGMEM               = "{\"msg\":\"OK\",\"port\":%d,\"val\":%d}";
 const prog_char JSON_FORMAT_READY[] PROGMEM            = "{\"msg\":\"READY\"}";

@@ -632,6 +633,7 @@
   }

   detachInterrupt(num);
+  return okDetachInterruptJson(num);
 }

 // スタックオーバーフローにより強制的にリセット
@@ -758,6 +760,16 @@
   return RESULT_MSG_PTR;
 }

+char* okDetachInterruptJson(uint8_t num){
+  char format_buf[64] = {0};
+  strcpy_P(format_buf, JSON_FORMAT_DETACH_INTERRUPT);
+
+  snprintf(result_msg_buf, ARRAYSIZE(result_msg_buf),
+      format_buf,
+      num);
+  return RESULT_MSG_PTR;
+}
+
 char* interruptJson(uint8_t num, uint32_t count){

   char format_buf[64] = {0};


Update Arduino.ino

Update Arduino.ino

--- Arduino/Arduino.ino
+++ Arduino/Arduino.ino
@@ -3,7 +3,7 @@
 #include <MideaHeatpumpIR.h>

 SoftwareSerial esp12(4, 5); //RX,TX
-IRSenderPWM irSender(3);
+IRSenderPWM irSender(8);
 HeatpumpIR *heatpumpIR = new MideaHeatpumpIR();

 char c;