All basic features working.

All basic features working.

Still need to add EEPROM support and look into SD card support

--- interrupt_driven_rgb.ino
+++ interrupt_driven_rgb.ino
@@ -1,14 +1,14 @@
-// #include <avr/sleep.h>
 // #include <pitches.h>

 #include <SPI.h>
 #include <Time.h>
 // #include <EEPROM.h>
+#include <Button.h>
 #include <Ucglib.h>
 #include <TinyGPS++.h>
 #include <Streaming.h>
 #include <TimedEvent.h>
-#include <ButtonEvent.h>
+#include <LowPower_Teensy3.h>
 #include <FiniteStateMachine.h>

 #define OLED_MOSI 11
@@ -25,58 +25,59 @@

 #define arraySize(a) (sizeof(a) / sizeof(a[0]))

-const uint8_t buttonPin = 2;
+const uint8_t buttonPin = 6;
 // const uint8_t id_address = 0;
 const double threshold = 0.01;
-// unsigned long start = 0;
 double distanceTo;
 double course;
 uint8_t waypoint_index = 0;

 const double waypoint[][2] = {
-  { 36.139670, -96.004777 },
-  { 36.139777, -96.003538 },
-  { 36.140135, -96.004070 },
+  { 36.049521, -95.921004 },
+  { 36.048774, -95.921697 },
+  // { 36.140135, -96.004070 },
 };
+
+Button button = Button(buttonPin);

 // U8GLIB_SSD1351_128X128_HICOLOR oled(OLED_CS, OLED_DC, OLED_RESET);
 Ucglib_SSD1351_18x128x128_HWSPI oled(OLED_DC, OLED_CS, OLED_RESET);

+TEENSY3_LP LP = TEENSY3_LP();
+
 TinyGPSPlus gps;

-// TinyGPSCustom ack_command(gps, "PMTK001", 1);
-// TinyGPSCustom ack_response(gps, "PMTK001", 2);
-// TinyGPSCustom awake(gps, "PMTK010", 1);
+TinyGPSCustom ack_command(gps, "PMTK001", 1);
+TinyGPSCustom ack_response(gps, "PMTK001", 2);
+TinyGPSCustom awake(gps, "PMTK010", 1);

 State GetFix       = State(enterGetFix, updateGetFix, exitGetFix);
 State ReadLocation = State(enterReadLocation, updateReadLocation, exitReadLocation);
 State SleepModules = State(enterSleepModules, updateSleepModules, NULL);
 State SleepNow     = State(updateSleepNow);
 State WakeModules  = State(enterWakeModules, updateWakeModules, NULL);
-State NextWaypoint = State(enterNextWaypoint, updateNextWaypoint, NULL);
-State LastWaypoint = State(updateLastWaypoint);
+State NextWaypoint = State(enterNextWaypoint, NULL, NULL);
+State LastWaypoint = State(enterLastWaypoint, NULL, NULL);
 State GPSFailure   = State(enterGPSFailure, NULL, NULL);

 FSM stateMachine = FSM(GetFix);

-// void pictureLoop(void (draw)()) {
-//   oled.firstPage();
-//   do {
-//     draw();
-//   } while(oled.nextPage());
-// }
-
-void onDown(ButtonInformation* sender) { /* do nothing here */ }
-
-void onUp(ButtonInformation* sender) { /* do nothing here */ }
-
-void onDouble(ButtonInformation* sender) { /* do nothing here */ }
-
-void onHold(ButtonInformation* sender) {
-  if(millis() < 6000) {
-    // reset waypoint index
+void onClick(Button& button) {
+  if(stateMachine.isInState(NextWaypoint)) {
+    if(waypoint_index >= arraySize(waypoint)) {
+      stateMachine.transitionTo(LastWaypoint);
+    } else {
+      stateMachine.transitionTo(ReadLocation);
+    }
+  }
+}
+
+void onHold(Button& button) {
+  if(millis() < 6000 || stateMachine.isInState(LastWaypoint)) {
+    waypoint_index = 0;
   } else {
-    stateMachine.transitionTo(NextWaypoint);
+    if(gps.location.isValid())
+      stateMachine.transitionTo(NextWaypoint);
   }
 }

@@ -111,9 +112,6 @@
   oled.setColor(255, 255, 0);
   oled.setPrintPos(0, oled.getHeight() / 2);
   oled << F("Please wait...");
-
-  int width = oled.getStrWidth("0 satellites");
-  oled.setClipRange(0, oled.getHeight() - 12, width, 12);

   TimedEvent.start(GET_FIX_TIMER);
 }
@@ -186,36 +184,68 @@
   oled.setColor(255, 255, 0);
   oled.setPrintPos(0, oled.getHeight() / 2);
   oled << F("Please wait...");
-}
+
+  Serial3.println(F("$PMTK161,0*28")); // Sleep GPS
+}
+

 void updateSleepModules() {
+  if(ack_command.isUpdated())
+    if(strcmp(ack_command.value(), "161") + strcmp(ack_response.value(), "3") == 0)
+      stateMachine.transitionTo(SleepNow);
 }

 void updateSleepNow() {
+  oled.clearScreen();
+
+  LP.DeepSleep(GPIO_WAKE, PIN_6);
+
+  stateMachine.transitionTo(WakeModules);
 }

 void enterWakeModules() {
-  ;
+  drawTitle(F("Waking"));
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setColor(255, 255, 0);
+  oled.setPrintPos(0, oled.getHeight() / 2);
+  oled << F("Please wait...");
+
+  Serial3.println(' ');
 }

 void updateWakeModules() {
-  drawWakeModules();
+  if(awake.isUpdated()) {
+    awake.value();
+    delay(1000);
+    stateMachine.transitionTo(GetFix);
+  }
 }

 void enterNextWaypoint() {
-  ;
-}
-
-void updateNextWaypoint() {
-  drawNextWaypoint();
-}
-
-void updateLastWaypoint() {
-  drawLastWaypoint();
+  drawTitle(F("Waypoint Reached"));
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setColor(255, 255, 0);
+  oled.setPrintPos(0, oled.getHeight() / 2);
+  oled << F("Push the button to");
+  oled.setPrintPos(0, (oled.getHeight() / 2) + (oled.getFontAscent() - oled.getFontDescent()));
+  oled << F("continue.");
+
+  waypoint_index++;
+}
+
+void enterLastWaypoint() {
+  drawTitle(F("Open the Box"));
 }

 void enterGPSFailure() {
-  drawGPSFailure();
+  drawTitle(F("GPS Failure"));
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setColor(255, 255, 0);
+  oled.setPrintPos(0, oled.getHeight() / 2);
+  oled << F("No data from GPS!");
 }

 void drawReadLocation() {
@@ -242,86 +272,27 @@
   oled << datetime;

   oled.setFont(ucg_font_7x13Br);
-
-  oled.setPrintPos(0, oled.getHeight() / 2 - 20);
+  oled.setColor(0, 255, 0);
+
+  oled.setPrintPos(0, oled.getHeight() / 2);
   oled << distanceTo << F(" miles");

-  oled.setPrintPos(0, oled.getHeight() / 2 + 20);
+  oled.setPrintPos(0, (oled.getHeight() / 2) + (oled.getFontAscent() - oled.getFontDescent()));
   oled << TinyGPSPlus::cardinal(course);

   oled.setFont(ucg_font_fixed_v0r);
-
-  oled.setPrintPos(0, oled.getHeight() - (oled.getFontDescent() + 12));
+  oled.setColor(255, 255, 255);
+
+  oled.setPrintPos(0, oled.getHeight() + oled.getFontDescent());
   oled << status;

-  oled.setPrintPos(0, oled.getHeight() - (oled.getFontDescent() + 24));
-  oled << F("hdop: ") << gps.hdop.value() << F(" WP: ") << (waypoint_index + 1) << '/' << arraySize(waypoint);
-}
-
-void drawSleepModules() {
-  oled.clearScreen();
-  oled.setColor(0, 0, 255);
-  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
-
-  oled.setFont(ucg_font_7x13Br);
-
-  oled.setColor(255, 255, 255);
-  oled.setPrintPos(5, 15);
-  oled << F("Sleep Modules");
-}
-
-void drawSleepNow() {
-  ;
-}
-
-void drawWakeModules() {
-  ;
-}
-
-void drawNextWaypoint() {
-  oled.clearScreen();
-  oled.setColor(0, 0, 255);
-  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
-
-  oled.setFont(ucg_font_7x13Br);
-
-  oled.setColor(255, 255, 255);
-  oled.setPrintPos(5, 15);
-  oled << F("Next Waypoint");
-}
-
-void drawLastWaypoint() {
-  ;
-}
-
-void drawGPSFailure() {
-  oled.clearScreen();
-  oled.setColor(0, 0, 255);
-  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
-
-  oled.setFont(ucg_font_7x13Br);
-
-  oled.setColor(255, 255, 255);
-  oled.setPrintPos(5, 15);
-  oled << F("GPS Failure");
-
-  oled.setFont(ucg_font_fixed_v0r);
-
-  oled.setColor(255, 255, 0);
-  oled.setPrintPos(0, oled.getHeight() / 2);
-  oled << F("No data from GPS!");
+  oled.setPrintPos(0, oled.getHeight() + (oled.getFontDescent() + 12));
+  oled << F("hdop: ") << gps.hdop.value() << F(" WP: ") << (waypoint_index + 1) << '/' << arraySize(waypoint) << "    ";
 }

 void setup() {
-  ButtonEvent.addButton(
-    buttonPin,
-    onDown,
-    onUp,
-    onHold,
-    5000,
-    onDouble,
-    200
-  );
+  button.clickHandler(onClick);
+  button.holdHandler(onHold, 5000);

   TimedEvent.addTimer(GET_FIX_TIMER, 5000, gpsFailure);
   TimedEvent.addTimer(READ_LOCATION_TIMER, 60000, initiateSleep);
@@ -339,6 +310,6 @@
 void loop() {
   while(Serial3.available()) gps << Serial3.read();
   TimedEvent.loop();
-  ButtonEvent.loop();
+  Button.process();
   stateMachine.update();
 }


Added license text to .ino file

Added license text to .ino file

--- SmartBowlDevice/SmartBowlDevice.ino
+++ SmartBowlDevice/SmartBowlDevice.ino
@@ -1,3 +1,29 @@
+/*
+
+MIT License
+
+Copyright (c) 2017 Grzegorz Hołdys
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
 /*
  * Arduino Board Setup:
  *


CodeCleanup

CodeCleanup

--- Weight.ino
+++ Weight.ino
@@ -47,13 +47,33 @@

 #define BUTTON_PIN   0

+typedef struct {
+  int eepromAddress;
+  HX711 scale;
+  unsigned long last;
+  unsigned long lastPrint;
+  float lastValue;
+}
+Scale;
+
+typedef struct {
+  char* name;
+  unsigned int index;
+}
+MenuItem;
+
+
 // initialize the library with the numbers of the interface pins
 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //PROD
-HX711 scales[] = {HX711 (A1, A2), HX711 (A3, A4)}; //A1 = ANALOG1 = DT // A2=SCK
-int eepromAddress[WEIGHT_SENSORS] = {0,1};
-
-unsigned long last[WEIGHT_SENSORS];
-unsigned long lastPrint[WEIGHT_SENSORS];
+
+Scale scale1 = {
+  0, HX711 (A1, A2), 0, 0, 0};
+Scale scale2 = {
+  1, HX711 (A3, A4), 0, 0, 0};
+
+Scale scales[] = {
+  scale1, scale2};
+
 const String kilo = "kg";

 // KEY VARIABLES
@@ -71,7 +91,18 @@

 //MENU
 char* EMPTY = "                ";
-char* menu[] = {"Calibrate" ,"Tare", "+Beersize", "Keg Weight"};
+char* beerSizes[] = {
+  "0.33", "0.5"};
+MenuItem menu[] = {
+  {
+    "Calibrate", 0  }
+  , {
+    "Tare", 1  }
+  , {
+    "Beersize", 2  }
+  , {
+    "Keg Weight", 3  }
+};
 unsigned int lastItem = 3;
 unsigned int menuMarker = 0;

@@ -80,19 +111,19 @@

 void setup() {
   Serial.begin(BAUD_RATE);
-
+
   lcd.begin(16, 2);
   lcd.print("Starting...");
   for (int i = 0; i < WEIGHT_SENSORS; i++) {
-    lastValue[i] = 0;
-    last[i] = 0;
-    lastPrint[i] = 0;
-    scales[i].set_scale(228.f);
-    scales[i].tare();
+    scales[i].lastValue = 0;
+    scales[i].last = 0;
+    scales[i].lastPrint = 0;
+    scales[i].scale.set_scale(228.f);
+    scales[i].scale.tare();
     delay(DELAY);
     if (USE_EEPROM) { //Firstime use please use calibrate.
-      double value = EEPROM.readDouble(eepromAddress[i]);
-      scales[i].set_offset(value);
+      double value = EEPROM.readDouble(scales[i].eepromAddress);
+      scales[i].scale.set_offset(value);
     }
   }
   lcd.clear();
@@ -119,10 +150,12 @@
   unsigned long now = millis();
   if (lcd_key == btnNONE) {
     return btnNONE;
-  } else if (millisPressedKey == 0 && lcd_key != btnNONE) {
+  }
+  else if (millisPressedKey == 0 && lcd_key != btnNONE) {
     millisPressedKey = now;
     return btnNONE;
-  } else if (((millisPressedKey + 10) < now) && (debounceTime < now)) {
+  }
+  else if (((millisPressedKey + 10) < now) && (debounceTime < now)) {
     int lcd_key_confirm = read_LCD_buttons();
     debounceTime = now + 300;
     millisPressedKey = 0;
@@ -130,11 +163,13 @@
       //Serial.println(lcd_key);
       buttonPressed = 0;
       return lcd_key;
-    } else {
+    }
+    else {
       millisPressedKey = now;
       return btnNONE;
     }
-  } else {
+  }
+  else {
     return btnNONE;
   }
 }
@@ -154,10 +189,10 @@
 }

 void printToSerial(const float value, const unsigned long now, String& weightName, const int i) {
-  if ((lastPrint[i] + DEFAULT_WEIGHT_PRINT_TIME) < now || ((useFastWeight && (last[i] + DEFAULT_WEIGHT_TIME_FAST) < now))) {
+  if ((scales[i].lastPrint + DEFAULT_WEIGHT_PRINT_TIME) < now || ((useFastWeight && (scales[i].last + DEFAULT_WEIGHT_TIME_FAST) < now))) {
     Serial.print(weightName);
     Serial.println(value, 1);
-    lastPrint[i] = now;
+    scales[i].lastPrint = now;
   }
 }

@@ -182,17 +217,21 @@
   if (weight > KILO * 10 || (KILO * -10) < weight) {
     if (WEIGHT_SENSORS > 2) {
       decimals = 1;
-    } else {
+    }
+    else {
       if (weight < 0) {
         decimals = 2;
-      } else {
+      }
+      else {
         decimals = 3;
       }
     }
-  } else {
+  }
+  else {
     if (WEIGHT_SENSORS > 2) {
       decimals = 0;
-    } else {
+    }
+    else {
       decimals = 2;
     }
   }
@@ -209,7 +248,8 @@
   //lcd.clear();
   if (WEIGHT_SENSORS > 2) {
     lcd.print(weight + kilo);
-  } else {
+  }
+  else {
     if (WEIGHT_SENSORS == 1) {
       lcd.print(weightName + weight + kilo + "   ");
       lcd.setCursor(0, 1);
@@ -217,45 +257,47 @@
       char numberOfBeers[4];
       dtostrf(((value - KEG_WEIGHT) / (TAP_SIZE)), 1, 0, numberOfBeers);
       lcd.print(beers + numberOfBeers + " (0.33)");
-    } else {
+    }
+    else {
       char numberOfBeers[4];
       dtostrf(((value - KEG_WEIGHT) / (TAP_SIZE)), 1, 0, numberOfBeers);
       lcd.print(weightName + weight + kilo + " (" + numberOfBeers +")    ");
     }
   }
-
+
   delete weight;
 }

 void doWeigth() {
-   if (printGUI){
+  if (printGUI){
     return;
   }
   unsigned long now = millis();
-
-    for (int i = 0; i < WEIGHT_SENSORS; i++) {
-      if (((last[i] + DEFAULT_WEIGHT_TIME) < now) || ((useFastWeight && (last[i] + DEFAULT_WEIGHT_TIME_FAST) < now))) {
+
+  for (int i = 0; i < WEIGHT_SENSORS; i++) {
+    if (((scales[i].last + DEFAULT_WEIGHT_TIME) < now) || ((useFastWeight && (scales[i].last + DEFAULT_WEIGHT_TIME_FAST) < now))) {
       lcd.setCursor(0, 1);

       String weightName = getName(i);
-      float value = getValue(scales[i]);
-
-      if ((value > (lastValue[i] + 50)) || (value < (lastValue[i] - 50))) {
+      float value = getValue(scales[i].scale);
+
+      if ((value > (scales[i].lastValue + 50)) || (value < (scales[i].lastValue - 50))) {
         useFastWeight = 1;
-        lastValue[i] = value;
-      } else {
+        scales[i].lastValue = value;
+      }
+      else {
         useFastWeight = 0;
       }
-
+
       printToSerial(value, now, weightName, i);

       const int row = getRow(i);
       const int col = getCol(i);
       lcd.setCursor(col, row);
-
+
       printWeightOnLCD(value, weightName);

-      last[i] = millis();
+      scales[i].last = millis();
     }
   }
 }
@@ -268,7 +310,8 @@
     lcd.print(" ");
     lcd.setCursor(0, 1);
     lcd.print(">");
-  } else {
+  }
+  else {
     lcd.setCursor(0, 0);
     lcd.print(">");
     lcd.setCursor(0, 1);
@@ -277,10 +320,10 @@
 }

 void printMenuItem(char* &item) {
-   char textItem[50];
-   strcpy(textItem, item);
-   strcat(textItem, EMPTY);
-   lcd.print(textItem);
+  char textItem[50];
+  strcpy(textItem, item);
+  strcat(textItem, EMPTY);
+  lcd.print(textItem);
 }

 void printMenu() {
@@ -291,19 +334,21 @@
   printMenuMarker(up);
   if (!up) {
     lcd.setCursor(1, 0);
-    printMenuItem(menu[menuMarker]);
+    printMenuItem(menu[menuMarker].name);
     if (menuMarker < lastItem) {
       lcd.setCursor(1, 1);
-      printMenuItem(menu[menuMarker + 1]);
-    } else {
+      printMenuItem(menu[menuMarker + 1].name);
+    }
+    else {
       lcd.setCursor(1, 1);
       lcd.print(EMPTY);
     }
-  } else {
+  }
+  else {
     lcd.setCursor(1, 0);
-    printMenuItem(menu[menuMarker - 1]);
+    printMenuItem(menu[menuMarker - 1].name);
     lcd.setCursor(1, 1);
-    printMenuItem(menu[menuMarker]);
+    printMenuItem(menu[menuMarker].name);
   }
 }

@@ -312,21 +357,22 @@
   lcd.setCursor(0, 1);
   lcd.print("Tare all weights");
   for (int i = 0; i < WEIGHT_SENSORS; i++) {
-    scales[i].tare();
+    scales[i].scale.tare();
     delay(DELAY);
   }
   lcd.print("Done tare...");
-  delay(DELAY * 2);
+  delay(DELAY * 4);
 }

 void kegWeight() {
-    useKegWeight ^= 1 << 0;
-    if (useKegWeight == 0) {
-        lcd.print("Keg is not removed");
-    } else {
-        lcd.print("Keg is removed");
-    }
-    delay(DELAY * 2);
+  useKegWeight ^= 1 << 0;
+  if (useKegWeight == 0) {
+    lcd.print("Keg is not removed");
+  }
+  else {
+    lcd.print("Keg is removed");
+  }
+  delay(DELAY * 4);
 }

 void doCalibrate() {
@@ -337,34 +383,48 @@
   lcd.print("Please clear all.");
   delay(4000);
   for (int i = 0; i < WEIGHT_SENSORS; i++) {
-    scales[i].tare();
-    double sum = scales[i].read_average(10);
+    scales[i].scale.tare();
+    double sum = scales[i].scale.read_average(10);
 #if defined(DEBUG)
     Serial.print("Offset is");
     Serial.println(sum);
 #endif
-    EEPROM.writeDouble(eepromAddress[i], sum);
-
+    EEPROM.writeDouble(scales[i].eepromAddress, sum);
+
   }
 }

 void doSelect(int value) {
   switch (value) {
   case 0:
-     doCalibrate();
-     break;
+    doCalibrate();
+    break;
   case 1:
     doTare();
-  break;
-    case 3:
+    break;
+  case 3:
     kegWeight();
-  break;
+    break;
   default:
     break;
   }
   delay(DELAY);
   printGUI = 0;
   lcd.clear();
+}
+
+void doRight() {
+  if (printGUI) {}
+  else {
+    lcd.clear();
+    printGUI = 1;
+  }
+}
+
+void doSelect() {
+  if (printGUI) {
+    doSelect(menuMarker);
+  }
 }

 void doButtonAction(int btn) {
@@ -372,48 +432,43 @@
 #if defined(DEBUG)
     Serial.println(btn);
 #endif
-
-   switch (btn) {
+    switch (btn) {
     case btnRIGHT: {
-      if (printGUI) {
-
-      } else {
+        doRight();
+        break;
+      } case btnSELECT: {
+        doSelect();
+        break;
+      } case btnLEFT: {
+        if (printGUI) {
           lcd.clear();
-          printGUI = 1;
-       }
-        break;
-    }
-    case btnSELECT: {
-       if (printGUI) {
-         doSelect(menuMarker);
-       }
-        break;
-      }
-    case btnLEFT: {
-      if (printGUI) {
-         lcd.clear();
-         printGUI = 0;
-      } else {
-
-       }
-        break;
-      }
-    case btnUP: {
-       if (menuMarker == 0) {
-             menuMarker = lastItem;
-       } else {
-             menuMarker = menuMarker - 1;
-       }
-       break;
-      }
-    case btnDOWN: {
-         if (printGUI) {
-           if (menuMarker >= lastItem) {
-             menuMarker = 0;
-           } else {
-             menuMarker = menuMarker + 1;
-           }
-         }
+          printGUI = 0;
+        }
+        else {
+
+        }
+        break;
+      }
+    case btnUP:
+      {
+        if (menuMarker == 0) {
+          menuMarker = lastItem;
+        }
+        else {
+          menuMarker = menuMarker - 1;
+        }
+        break;
+      }
+    case btnDOWN:
+      {
+        if (printGUI) {
+          if (menuMarker >= lastItem) {
+            menuMarker = 0;
+          }
+          else {
+            menuMarker = menuMarker + 1;
+          }
+        }
         break;
       }
     case btnNONE:
@@ -421,12 +476,12 @@
         break;
       }
     }
-    #if defined(DEBUG)
+#if defined(DEBUG)
     Serial.print("MenuMarker:");
     Serial.println(menuMarker);
     Serial.print("useKegWeight:");
     Serial.println(useKegWeight);
-    #endif
+#endif
   }
 }

@@ -440,4 +495,3 @@

-


deleted ino

deleted ino

--- clavier.ino
+++ clavier.ino
@@ -1,87 +0,0 @@
-#ifndef _CHAIR_AFFAIR_CLAVIER
-#define _CHAIR_AFFAIR_CLAVIER
-
-#include <inttypes.h>
-#include <config.h>
-#include <Adafruit_MPR121.h>
-
-uint16_t _currtouched;
-uint16_t _lasttouched;
-uint16_t _active_flags;
-uint16_t _new_touches;
-uint16_t _new_releases;
-
-Adafruit_MPR121 _sensor_interface;
-boolean _sensor_interface_online;
-
-void clavier_begin() {
-	_active_flags = 0;
-	//	region sensors are active
-	_active_flags |= (1 << MPR_121_RGN_1);
-	_active_flags |= (1 << MPR_121_RGN_2);
-	_active_flags |= (1 << MPR_121_RGN_3);
-	_active_flags |= (1 << MPR_121_RGN_4);
-	_active_flags |= (1 << MPR_121_RGN_5);
-	_active_flags |= (1 << MPR_121_RGN_6);
-	_active_flags |= (1 << MPR_121_RGN_7);
-
-	//	global function sensors are active too
-	_active_flags |= (1 << MPR_121_RYTH);
-	_active_flags |= (1 << MPR_121_COLOR);
-	_active_flags |= (1 << MRP_121_OTHER);
-
-	_sensor_interface = Adafruit_MPR121();
-
-	Serial.println("Created instance of MPR121");
-
-	if( _sensor_interface.begin(0x5A) ) {
-		_sensor_interface_online = true;
-	}
-	else {
-		_sensor_interface_online = false;
-	}
-	Serial.println("Started MRP121");
-
-	for( int i = 0; i < 10; i++ ) {
-		digitalWrite(LED_BUILTIN,HIGH);
-		delay(100);
-		digitalWrite(LED_BUILTIN,LOW);
-		delay(75);
-	}
-}
-
-boolean clavier_sensor_online() {
-	return _sensor_interface_online;
-}
-
-void clavier_update() {
-	_currtouched = _sensor_interface.touched();
-	for( uint8_t i = 0; i<12; i++ ) {
-    	// it if *is* touched and *wasnt* touched before, alert!
-    	if( (_currtouched & _BV(i)) && !(_lasttouched & _BV(i)) ) {
-      		Serial.print(i); Serial.println(" touched");
-      		_new_touches |= _BV(i);
-    	}
-    	// if it *was* touched and now *isnt*, alert!
-    	if( !(_currtouched & _BV(i)) && (_lasttouched & _BV(i)) ) {
-      		Serial.print(i); Serial.println(" released");
-      		_new_releases |= _BV(i);
-    	}
-	}
-	_lasttouched = _currtouched;
-	Serial.print("("); Serial.print(_lasttouched,HEX); Serial.println(")");
-}
-
-uint16_t clavier_new_touches() {
-	uint16_t temp = _new_touches;
-	_new_touches = 0;
-	return temp;
-}
-
-uint16_t clavier_new_releases() {
-	uint16_t temp = _new_releases;
-	_new_releases = 0;
-	return temp;
-}
-
-#endif


Auto display off after 5 minutes

Auto display off after 5 minutes

--- pano-controller.ino
+++ pano-controller.ino
@@ -15,6 +15,9 @@
 #include "joystick.h"
 #include "remote.h"
 #include "menu.h"
+
+// inactivity time to turn display off (ms)
+#define DISPLAY_SLEEP 5*60*1000

 // Address of I2C OLED display. If screen looks scaled edit Adafruit_SSD1306.h
 // and pick SSD1306_128_64 or SSD1306_128_32 that matches display type.
@@ -276,6 +279,7 @@
  */
 void displayMenu(void){
     int event;
+    int last_event = millis();

     menu.open();
     display.clearDisplay();
@@ -285,8 +289,16 @@

     while (!running){
         event = joystick.read() | remote.read();
-        if (!event) continue;
-
+        if (!event){
+            if (millis() - last_event > DISPLAY_SLEEP){
+                display.clearDisplay();
+                display.display();
+                last_event = millis();
+            }
+            continue;
+        }
+
+        last_event = millis();
         if (HID::isEventLeft(event) || HID::isEventCancel(event)) menu.cancel();
         else if (HID::isEventRight(event) || HID::isEventOk(event)) menu.select();
         else if (HID::isEventDown(event)) menu.next();


Make motor watchdog settings independent for open and close

--- CoopAlamode/L298NDoor.ino
+++ CoopAlamode/L298NDoor.ino
@@ -33,25 +33,28 @@
 // Maximum PWM setting.  Valid values are 0 (off) to 255 (full on)
 const int MAX_PWM = 255;

-// PWM setting for low speed mode when approaching an end stop.
-// Valid values are 0 (off) to 255 (full on)
-const int LOW_SPEED_PWM_OPEN = 110;
-const int LOW_SPEED_PWM_CLOSE = 60;
-
 const int MAX_DOOR_SPEED = 0x3FFF;

-// This value controls the slope of the soft start
-const int RAMP_UP_VALUE = 32; // amount to increase speed per cycle
+// Door low speed when approaching an end stop.
+// Valid values are 0 (off) to MAX_DOOR_SPEED (full on)
+const int DOOR_LOW_SPEED_CLOSE = 60 << 6;
+const int DOOR_LOW_SPEED_OPEN = 95 << 6;
+
+
+// This value controls the slope of the soft start / stop
+const int DOOR_SPEED_RAMP = 32; // amount to change speed per cycle

 // Initial speed for the motor when reversing. If negative, motor will not be started until the ramp up has
 // brought the value above 0.
-const int INITIAL_REVERSING_MOTOR_SPEED = -1 * 128 * RAMP_UP_VALUE;
+const int INITIAL_REVERSING_MOTOR_SPEED = -4096 / DOOR_SPEED_RAMP;

 // Arbitrary value defining when to shut down the motor if it has been on for this many update cycles.
-const unsigned int DOOR_MOTOR_WATCHDOG_MAX = 2600;
+const unsigned int DOOR_MOTOR_WATCHDOG_CLOSE_MAX = 2600;
+const unsigned int DOOR_MOTOR_WATCHDOG_OPEN_MAX = 2700;

 // Arbitrary value defining when to slow motor down
-const unsigned int DOOR_MOTOR_WATCHDOG_LOW_SPEED = 1800;
+const unsigned int DOOR_MOTOR_WATCHDOG_CLOSE_LOW_SPEED = 1700;
+const unsigned int DOOR_MOTOR_WATCHDOG_OPEN_LOW_SPEED = 1900;

 // Globals

@@ -63,11 +66,21 @@
 // and atomicity
 volatile byte doorCommand = DOOR_COMMAND_NONE;

-// Door PWM setting.  A negative values indicates no motor output and are used for a motor start delay.
+// Door speed tracker. Negative values indicates no motor output and are used for a motor start delay.
+// Note this is not directly used as a PWM value but rather the PWM is derived from this.
 int doorSpeed = 0;

 // Door watchdog counter.
 unsigned int doorWatchdog = 0;
+
+// Max allowed for for door watchdog, variable as it can differ between opening and closing
+unsigned int doorWatchdogMax;
+
+// door watchdog value at which it transitions to low speed, variable as it can differ between opening and closing
+unsigned int doorWatchdogLowSpeedCutover;
+
+// door speed setting for low speed, variable as it can differ between opening and closing
+int doorLowSpeed;

 /**
@@ -183,6 +196,9 @@
   }

   doorWatchdog = 0;
+  doorWatchdogMax = DOOR_MOTOR_WATCHDOG_OPEN_MAX;
+  doorWatchdogLowSpeedCutover = DOOR_MOTOR_WATCHDOG_OPEN_LOW_SPEED;
+  doorLowSpeed = DOOR_LOW_SPEED_OPEN;
   doorState = DOOR_STATE_OPENING;
 }

@@ -213,17 +229,20 @@
   }

   doorWatchdog = 0;
+  doorWatchdogMax = DOOR_MOTOR_WATCHDOG_CLOSE_MAX;
+  doorWatchdogLowSpeedCutover = DOOR_MOTOR_WATCHDOG_CLOSE_LOW_SPEED;
+  doorLowSpeed = DOOR_LOW_SPEED_CLOSE;
   doorState = DOOR_STATE_CLOSING;
 }

 /**
- * Updates the speed of the motor.  The PWM field will be incremented by RAMP_UP_VALUE
+ * Updates the speed of the motor.  The PWM field will be incremented by DOOR_SPEED_RAMP
  * each time this method is called until the MAX_PWM is reached.  If the door is no longer opening
  * or closing, no speed change will occur. If the speed is negative, no speed change will occur.
  *
  * In order to not bang into the limit switches, after a pre-determined amount of time, the motor
- * speed will be lowered to
+ * speed will be ramped down to a low speed value appropriate for the door direction.
  *
  * Finally, this method increments and checks a watchdog counter in case the limit switches
  * are never tripped.  If the motor runs for too long, it is stopped and the door state becomes
@@ -236,8 +255,10 @@
     return;
   }

+  int pwm;
+
   doorWatchdog++;
-  if (doorWatchdog > DOOR_MOTOR_WATCHDOG_MAX) {
+  if (doorWatchdog > doorWatchdogMax) {
     digitalWrite(PWM_PIN, LOW);
     digitalWrite(OPENING_PIN, LOW);
     digitalWrite(CLOSING_PIN, LOW);
@@ -245,33 +266,32 @@
     doorState = DOOR_STATE_UNKNOWN;
     interrupts();
     return;
-  }
-  else if (doorWatchdog == DOOR_MOTOR_WATCHDOG_LOW_SPEED) {
-    if (doorState == DOOR_STATE_OPENING) {
-      analogWrite(PWM_PIN, LOW_SPEED_PWM_OPEN);
-    }
-    else {
-      analogWrite(PWM_PIN, LOW_SPEED_PWM_CLOSE);
+  }
+
+  if (doorWatchdog >= doorWatchdogLowSpeedCutover) {
+    if (doorSpeed > doorLowSpeed) {
+      doorSpeed -= DOOR_SPEED_RAMP;
+      if (doorSpeed < doorLowSpeed) {
+        doorSpeed = doorLowSpeed;
+      }
+      pwm = (doorSpeed >> 6) & 0xFF;
+      analogWrite(PWM_PIN, pwm);
     }
     interrupts();
     return;
   }
-  else if (doorWatchdog > DOOR_MOTOR_WATCHDOG_LOW_SPEED) {
-    interrupts();
-    return;
-  }

   if (doorSpeed >= MAX_DOOR_SPEED) {
     interrupts();
     return;
   }

-  doorSpeed += RAMP_UP_VALUE;
+  doorSpeed += DOOR_SPEED_RAMP;
   if (doorSpeed >= MAX_DOOR_SPEED) {
     doorSpeed = MAX_DOOR_SPEED;
   }

-  int pwm = (doorSpeed >> 6) & 0xFF;
+  pwm = (doorSpeed >> 6) & 0xFF;

   if (doorSpeed > 0) {
     analogWrite(PWM_PIN, pwm);


testing control via uart. speed direction and steps are done. 	modified:   mcu_main/mcu_main.ino

--- mcu_main/mcu_main.ino
+++ mcu_main/mcu_main.ino
@@ -28,22 +28,55 @@
   pinMode(C, OUTPUT);
   pinMode(D, OUTPUT);

-  pinMode(indicator, HIGH);
+  pinMode(indicator, HIGH);
+
+  Serial.begin(9600);
 }

 void loop()
 {
-
+  String cmd;
+  while (Serial.available())
+  {
+    delay(3);  //delay to allow buffer to fill
+    if (Serial.available() > 0)
+    {
+      char c = Serial.read();  //gets one byte from serial buffer
+      cmd += c; //makes the string readString
+    }
+  }
+
+  if(cmd.length() > 0)
+  {
+    Serial.println(cmd); //see what was received
+  }
+
+
+
+  if(cmd.length() > 3)
+  {
+//    State state;
+//    state.spd     =  cmd[1];
+//    state.steps   =  cmd[2]<<8  +  cmd[3];
+//    state.running =  true;
+//    state.cw      =  cmd[0]  &  0x01;
+
   State state;
-  state.spd = 500;
-  state.steps = 150;
+  state.spd = cmd[1];
+  state.steps = cmd[2];
   state.running = true;
   state.cw = true;

-  half(&state);
+    wave(&state);
+  }
+
+  if(cmd.length() > 0)
+  {
+    Serial.println(cmd); //see what was received
+  }
+
+

-
-  while(true);
 }

 //!  @brief :  wave stepping


Modified RampTest; Expanded Instrument structure; Added servo comments.

--- Elcano_C2_DriveByWire.ino
+++ Elcano_C2_DriveByWire.ino
@@ -93,16 +93,30 @@
 const int Straight = 191;
 const int HalfRight = 223;
 const int HardRight = 255;
-/*  Servo range is 50 mm for brake, 100 mm for steering.
-    Servo is fully retracted on a pulse width of 2 ms;
+/*  Elcano Servo range is 50 mm for brake, 100 mm for steering.
+
+    Elcano servo has a hardware controller that moves to a
+    particular position based on a PWM signal from Arduino.
+    Wikispeed servo is the same, except that controller box has
+    buttons for extend, retract, or moving to three preset positions.
+
+    Elcano servo is fully retracted on a pulse width of 2 ms;
     fully extended at 1 ms and centered at 1.5 ms.
     There is a deadband of 8 us.
     At 12v, servo operating speed is 56mm/s with no load or
     35 mm/s at maximum load.
-
     The Arduino PWM signal is at 490 Hz or 2.04 ms.
     0 is always off; 255 always on. One step is 7.92 us.

+    Either servo has five wires, with observed bahavior of:
+    White: 0V
+    Yellow: 5V
+    Blue: 0-5V depending on position of servo.
+    Black: 12V while servo extends; 0V at rest or retracting.
+    Red:   12V while retracting; 0V at rest or extending.
+    The reading on the Blue line has hysteresis when Elcano sends a PWM signal;
+    there appear to be different (PWM, position) pairs when retracting or extending.
+    Motor speed is probably controlled by the current on the red or black line.
 */

   const int Motor = 0;
@@ -116,12 +130,14 @@
      int StickMoved;  // bool
      int Joystick;   // position of stick
      int LastCommand;  // last commanded
+     int MinPosition;
+     int MaxPosition;
      int Feedback;   // actual position
      int EnablePin;
      int SignalPin;
      int FeedbackPin;
      int CurrentPin;
-     int CloseEnough;  // in counts; Try for 0-4095
+     int CloseEnough;  // in counts; Try for 0-1023
      int Stuck;        // max number of time steps for not getting to position
      int StepSize;     // controls how quickly the servo moves. 2"/sec servo max
      int QuiescentCurrent;  // Nominally 120 counts
@@ -131,25 +147,34 @@
      // The ACS758 has sensitivity of 60 mA/V
      int move(int desired_position)
      {
-         int Position = desired_position;
-         Feedback = analogRead(FeedbackPin);
-         if (desired_position < 0)
-           desired_position = 0;
-         if (desired_position > 4095)
-           desired_position = 4095;
-         if ((desired_position - Feedback) > StepSize)
-           Position = max (4095, Feedback + StepSize);
-         if ((desired_position - Feedback) < StepSize)
-           Position = min(0, Feedback - StepSize);
-         analogWrite(SignalPin, Position);
+         int Position = desired_position;    // 0 to 1023
+         Feedback = analogRead(FeedbackPin);  // 0 to 1023
+         if (desired_position > Feedback)
+         {
+            Position = min(desired_position, Feedback + StepSize);
+            Position = min (Position, 1023);
+         }
+         else
+         {
+            Position = max(desired_position,  Feedback - StepSize);
+            Position = max(0, Position);
+         }
+         int PWMPosition = 127 + Position/8;
+         analogWrite(SignalPin, PWMPosition);  // 0 to 255
+         Serial.print(desired_position); Serial.print(", ");
+         Serial.print(Feedback); Serial.print(", ");
+         Serial.print(Position); Serial.print(", ");
+         Serial.println(PWMPosition);
         return Position;
      }
      void home(int desired_position)
      {
+       return;
        int feedback_after, Position;
        int no_move_count = 0;
        do
        {
+         Serial.print("Home ");
          Position = move (desired_position);
          delay(STEP_SIZE_ms);
          feedback_after = analogRead(FeedbackPin);
@@ -223,25 +248,32 @@
         Instrument[Motor].SignalPin = TractionMotor;
         Instrument[Motor].FeedbackPin = FeedbackMotor;
         Instrument[Motor].CurrentPin = Current36V;
-        Instrument[Motor].StepSize = 20; // max from range of 4095.
+        Instrument[Motor].StepSize = 20; // max from range of 1023.
         Instrument[Motor].CloseEnough = 1000;  // no feedback
         Instrument[Motor].Stuck = 3;
+        Instrument[Motor].MinPosition = 85;  // anolog read range is 0 to 1023
+        Instrument[Motor].MaxPosition = 800;
+

         Instrument[Steering].EnablePin = EnableSteer;
         Instrument[Steering].SignalPin = Steer;
         Instrument[Steering].FeedbackPin = FeedbackSteer;
         Instrument[Steering].CurrentPin = CurrentSteer;
         Instrument[Steering].StepSize = 20;
-        Instrument[Motor].CloseEnough = 1;
-        Instrument[Motor].Stuck = 3;
+        Instrument[Steering].CloseEnough = 1;
+        Instrument[Steering].Stuck = 3;
+        Instrument[Steering].MinPosition = 85;  // anolog read range is 0 to 1023
+        Instrument[Steering].MaxPosition = 800;

         Instrument[Brakes].EnablePin = EnableBrake;
         Instrument[Brakes].SignalPin = DiskBrake;
         Instrument[Brakes].FeedbackPin = FeedbackBrake;
         Instrument[Brakes].CurrentPin = CurrentBrake;
-        Instrument[Brakes].StepSize = 20;
-        Instrument[Motor].CloseEnough = 1;
-        Instrument[Motor].Stuck = 3;
+        Instrument[Brakes].StepSize = 50;
+        Instrument[Brakes].CloseEnough = 1;
+        Instrument[Brakes].Stuck = 3;
+        Instrument[Brakes].MinPosition = 85;  // anolog read range is 0 to 1023
+        Instrument[Brakes].MaxPosition = 800;

         Instrument[Motor].Feedback =
           analogRead(Instrument[Motor].FeedbackPin);
@@ -420,17 +452,17 @@
  // make loop faster
  // limit servo motion during loop to step size
   unsigned long fred = millis();
-  Serial.print(fred - TimeNow);
-  Serial.print(",");
+//  Serial.print(fred - TimeNow);
+//  Serial.print(",");
   do  //  Delay so that loop is not faster than 10 Hz.
   {
     EndTime = millis();
   } while (EndTime < NextLoopTime_ms);
-  Serial.print(EndTime - fred);
-  Serial.print(",");
-  Serial.print(NextLoopTime_ms);
-  Serial.print(",");
-  Serial.println(OutsideTime);
+//  Serial.print(EndTime - fred);
+//  Serial.print(",");
+//  Serial.print(NextLoopTime_ms);
+//  Serial.print(",");
+//  Serial.println(OutsideTime);

 }
@@ -835,16 +867,28 @@
 void RampTest()
 {
   static int Position[] ={ 0, 0, 0};
-    for (int i = 0; i< 3; i++)
-    {
-       if( digitalRead(Instrument[i].EnablePin) == HIGH)
-       {
-           if (abs(Instrument[i].move(Position[i]) - Position[i]) < Instrument[i].CloseEnough)
-             Position[i] = Position[i]? 0: 4095;
-          Serial.print(i); Serial.print(", ");
-          Serial.print(Position[i]); Serial.print(", ");
-
-       }
+  const int i = Brakes;
+    for (int j = 80; j <800; j += 20) /*Instrument[i].MinPosition; j<= Instrument[i].MaxPosition;
+    j += Instrument[i].StepSize) */
+    {
+        Serial.print("Move up ");
+        Instrument[i].move(j);
+
+//       if( digitalRead(Instrument[i].EnablePin) == HIGH)
+//       {
+//           if (abs(Instrument[i].move(Position[i]) - Position[i]) < Instrument[i].CloseEnough)
+//           {
+//             if (Position[i] = Position[i]? 0: 1023;
+//           }
+//       }
+        delay(500);
+    }
+    for (int j = Instrument[i].MaxPosition; j>= Instrument[i].MinPosition;
+    j -= 20)
+    {
+         Serial.print("Move down ");
+        Instrument[i].move(j);
+        delay(500);
     }

 }


enable servo

enable servo

--- arduino/arduino.ino
+++ arduino/arduino.ino
@@ -14,7 +14,7 @@
 void setup()
 {
   Serial.begin(38400);
-//  myservo.attach(servoPin);
+  myservo.attach(servoPin);

   lcd.begin(16, 2);


actually start the flasher

actually start the flasher

--- arduino/due/due.ino
+++ arduino/due/due.ino
@@ -71,6 +71,7 @@
   //Pin structs take care of themselves, unless you need special modes outside arduino's libraries.
   greenirq.attach(true);//we don't build in attach() to the constructor as in many cases the isr needs stuff that isn't initialized until setup() is run.
   redirq.attach(true);
+  flashLamp.retrigger();//have to manually fire it off once, after that it toggles in its own.
 }

 char indicator='-';


can temporarily change current enable threshold

--- short-circuit-limiter/short-circuit-limiter.ino
+++ short-circuit-limiter/short-circuit-limiter.ino
@@ -3,7 +3,7 @@
 #include <DallasTemperature.h>
 #include "CTSensor.h"

-#define CURRENT_ENABLE_THRESHOLD 0.2
+#define DEFAULT_CURRENT_ENABLE_THRESHOLD 0.2
 #define CURRENT_MCB_CUT 16

 #define TEMP_MAX 85
@@ -41,7 +41,7 @@
 #define NUM_CT_SAMPLES 275

 //Delay between LCD Print to avoid slowing down data collection
-#define INTERVAL_PRINT 500
+#define INTERVAL_PRINT 300

 #define BACKLIGHT_BLINK_RATE 200

@@ -56,9 +56,8 @@
 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
 OneWire oneWire(PIN_TEMP);

-// Pass our oneWire reference to Dallas Temperature.
+// Pass our oneWire reference to Dallas Temperature.
 DallasTemperature dallasTemp(&oneWire);
-

 U8G2_UC1701_MINI12864_F_4W_SW_SPI u8g2(U8G2_R2, 21, 20, 19, 22);
 CTSensor clamp(PIN_CT, CT_CALIBRATION_VALUE);
@@ -69,7 +68,20 @@

 bool isBacklightAlwaysOn = false;

+float currentEnableThreshold;
+
+float getEnableThresholdFromEEProm(){
+  return DEFAULT_CURRENT_ENABLE_THRESHOLD;
+}
+
+void changeEnableThreshold(float newThreshold){
+  currentEnableThreshold = newThreshold;
+}
+
+
 void setup() {
+
+  currentEnableThreshold = getEnableThresholdFromEEProm();

   pinMode(PIN_LED, OUTPUT);
   pinMode(PIN_BUZZER, OUTPUT);
@@ -95,56 +107,57 @@
     if(isMiddleButtonPressed()){
       break;
     }
-
+
     getCurrentMeasurement();

     unsigned long currentTime = millis();
     static unsigned long lastDisplayTime = 0;
-
+
     if((currentTime - lastDisplayTime) >= INTERVAL_PRINT){

       lastDisplayTime = currentTime;
-
+
       unsigned long timeLeft = INITIAL_SETTLE_TIME - timeElapsedSinceStart;
       unsigned int timeLeftSeconds = timeLeft / 1000;
-
+      updateCurrentThresholdForCertainModes();
+
       u8g2.clearBuffer();
-
+
       u8g2.setFont(u8g2_font_6x10_tr);
       u8g2.drawStr(0,10, "Short Circuit Limiter\n");
       u8g2.drawStr(0,21, "Starting in: ");
-
+
       u8g2.setFont(u8g2_font_9x18_tr);
       char secondsBuffer[10];
       sprintf(secondsBuffer, "%ds", timeLeftSeconds);
-
+
       u8g2.drawStr(80, 22, secondsBuffer);
       u8g2.setFont(u8g2_font_5x8_tr);
-
+
       char valueBuff[10];
       char valueBuff2[10];
       char fullBuff[30];
-
+
       float temperature = getTemperature();
       dtostrf(temperature, 3, 1, valueBuff);
       sprintf(fullBuff,"Curr Temp: %sC", valueBuff);
       u8g2.drawStr(0,31, fullBuff);
-
+
       dtostrf(TEMP_WARN, 2, 0, valueBuff);
       dtostrf(TEMP_MAX, 2, 0, valueBuff2);
       sprintf(fullBuff,"Temp Warn/Max : %s/%s C", valueBuff, valueBuff2);
       u8g2.drawStr(0,39, fullBuff);
-
-      dtostrf(CURRENT_ENABLE_THRESHOLD, 4, 2, valueBuff);
+
+      dtostrf(currentEnableThreshold, 4, 2, valueBuff);
       sprintf(fullBuff,"Enable thres: %sA", valueBuff);
-      u8g2.drawStr(0,47, fullBuff);
-
+      u8g2.drawStr(0,47, fullBuff);
+
       dtostrf(CURRENT_MCB_CUT, 4, 1, valueBuff);
       sprintf(fullBuff,"Trip thres: %sA", valueBuff);
       u8g2.drawStr(0,55, fullBuff);
-
+
       u8g2.drawStr(0,63, "Designer: Yeo Kheng Meng");
-
+
       u8g2.sendBuffer();
     }
   }
@@ -156,7 +169,7 @@
 }

 double getCurrentMeasurement(){
-
+
   for(int sampleIndex = 0; sampleIndex < NUM_CT_SAMPLES; sampleIndex++){
     clamp.doIncrementalMeasurement();
   }
@@ -170,7 +183,7 @@
 void loop() {

   double currentValue = getCurrentMeasurement();
-
+
   if(currentValue >= CURRENT_MCB_CUT){
     nextState = enterMCBTrippedMode(currentValue);
   }
@@ -216,7 +229,7 @@

     char valueBuff[10];
     char fullBuff[30];
-
+
     dtostrf(mcbTrippedCurrent, 4, 1, valueBuff);
     sprintf(fullBuff,"Tripped: %sA", valueBuff);
     u8g2.drawStr(0,50, fullBuff);
@@ -225,10 +238,10 @@
     dtostrf(CURRENT_MCB_CUT, 4, 1, valueBuff);
     sprintf(fullBuff,"Trip threshold: %sA", valueBuff);
     u8g2.drawStr(0,63, fullBuff);
-
+
     u8g2.sendBuffer();

-  } else if(currentState == STATE_TEMP_MAX){
+  } else if(currentState == STATE_TEMP_MAX){
     if((currentTime - lastDisplayTime) >= INTERVAL_PRINT){

       lastDisplayTime = currentTime;
@@ -237,10 +250,10 @@
       u8g2.clearBuffer();
       u8g2.setFont(u8g2_font_9x18_tr);
       u8g2.drawStr(0,10, "Overheated!!!");
-
+
       char valueBuff[10];
       char fullBuff[30];
-
+
       u8g2.setFont(u8g2_font_7x13_tr);
       dtostrf(temperature, 3, 1, valueBuff);
       sprintf(fullBuff,"Curr Temp: %sC", valueBuff);
@@ -253,14 +266,14 @@

       dtostrf(TEMP_WARN, 3, 1, valueBuff);
       sprintf(fullBuff,"Temp Warn: %sC", valueBuff);
-      u8g2.drawStr(0,60, fullBuff);
-
+      u8g2.drawStr(0,60, fullBuff);
+
       u8g2.sendBuffer();

-
-    }
-
+
+    }
+
   } else {

     static double runningTotal = 0;
@@ -268,14 +281,14 @@

     runningTotal += currentValue;
     samplesTaken++;
-
+
     //We don't want to keep printing to screen as it is slow so we just do a running average
-    if((currentTime - lastDisplayTime) >= INTERVAL_PRINT){
+    if((currentTime - lastDisplayTime) >= INTERVAL_PRINT){
       lastDisplayTime = currentTime;

       float temperature = getTemperature();
       double average = runningTotal / samplesTaken;
-
+
       runningTotal = 0;
       samplesTaken = 0;

@@ -294,7 +307,7 @@
           u8g2.drawStr(0,10, "Limiter: Bypassed");
           break;
         case STATE_MCB_TRIPPED:
-          //Fallthrough
+          //Fallthrough
         default:
           Serial.println("LCD Printing shouldn't come to this mode!");
           break;
@@ -304,7 +317,7 @@

        char valueBuff[10];
        char fullBuff[30];
-
+
        dtostrf(currentValue, 4, 2, valueBuff);
        sprintf(fullBuff,"Current  : %sA", valueBuff);
        u8g2.drawStr(0,33, fullBuff);
@@ -320,7 +333,7 @@
        }

        u8g2.setFont(u8g2_font_5x8_tr);
-       dtostrf(CURRENT_ENABLE_THRESHOLD, 4, 2, valueBuff);
+       dtostrf(currentEnableThreshold, 4, 2, valueBuff);
        sprintf(fullBuff,"Enable Current: %sA", valueBuff);
        u8g2.drawStr(0,63, fullBuff);

@@ -329,7 +342,7 @@

     }
   }
-
+
 }

 STATE enterMCBTrippedMode(double currentValue){
@@ -353,7 +366,7 @@
     digitalWrite(PIN_BUZZER, HIGH);
   }

-  //This is to sound the buzzer and blink the Backlight for BACKLIGHT_BLINK_RATE duration
+  //This is to sound the buzzer and blink the Backlight for BACKLIGHT_BLINK_RATE duration
   if(initialWarningTriggered){

     static bool displayBacklightCurrentlyOn = false;
@@ -370,16 +383,16 @@
       initialWarningTriggered = false;
       digitalWrite(PIN_BUZZER, LOW);
       changeDisplayBacklight(true);
-
-    }
-
+
+    }
+
   }

   if(isMiddleButtonPressed()){
     return STATE_WINDOW_BEFORE;
   }

-  return STATE_MCB_TRIPPED;
+  return STATE_MCB_TRIPPED;
 }

 STATE enterWindowBeforeMode(double currentValue){
@@ -393,26 +406,27 @@
     if(currentState != STATE_WINDOW_WITHIN){
       shortBeepXTimesNoDelay(2);
     }
-
+
     currentState = STATE_WINDOW_BEFORE;
     Serial.println("Window Before");
   }

   updateDisplayBackLightSettingsForCertainModes();
-
-  if(currentValue >= CURRENT_ENABLE_THRESHOLD){
+  updateCurrentThresholdForCertainModes();
+
+  if(currentValue >= currentEnableThreshold){
     return STATE_WINDOW_WITHIN;
   }

   return STATE_WINDOW_BEFORE;
-
+
 }

 STATE enterWindowWithinMode(double currentValue){
   unsigned long currentTime = millis();

   static unsigned long enableWindowTime = 0;
-
+
   if(currentState != STATE_WINDOW_WITHIN){
     currentState = STATE_WINDOW_WITHIN;
     enableWindowTime = currentTime;
@@ -420,15 +434,16 @@
   }

   updateDisplayBackLightSettingsForCertainModes();
-
-  if(currentValue < CURRENT_ENABLE_THRESHOLD){
+  updateCurrentThresholdForCertainModes();
+
+  if(currentValue < currentEnableThreshold){
     return STATE_WINDOW_BEFORE;
   } else if((currentTime - enableWindowTime) >= DELAY_BEFORE_LIMITER_RELAY_ENABLE){
     //Exit window if no overcurrent is detected in this time
     return STATE_WINDOW_EXITED;
   } else {
     return STATE_WINDOW_WITHIN;
-  }
+  }
 }

 STATE enterWindowExitedMode(double currentValue){
@@ -441,22 +456,23 @@
   }

   passFullCurrentThrough(true);
-
-  if(currentValue < CURRENT_ENABLE_THRESHOLD){
+  updateCurrentThresholdForCertainModes();
+
+  if(currentValue < currentEnableThreshold){
     return STATE_WINDOW_BEFORE;
   } else {
     return STATE_WINDOW_EXITED;
-  }
+  }

 }

 STATE enterTempMaxMode(){
   if(currentState != STATE_TEMP_MAX){
     currentState = STATE_TEMP_MAX;
-
+
     changeMCBRelayState(false);
     passFullCurrentThrough(false);
-
+
     changeDisplayBacklight(true);
     shortBeepXTimesNoDelay(10);
     Serial.println("Enter Max Temp mode");
@@ -466,17 +482,32 @@

   //We remain in this mode until the temperature drops below TEMP_WARN to prevent oscillating into this mode and out
   if(temperature >= TEMP_WARN){
-    return STATE_TEMP_MAX;
-  } else {
-    return STATE_WINDOW_BEFORE;
+    return STATE_TEMP_MAX;
+  } else {
+    return STATE_WINDOW_BEFORE;
   }
 }

 void updateDisplayBackLightSettingsForCertainModes(){
   if(isMiddleButtonPressed()){
-    isBacklightAlwaysOn = !isBacklightAlwaysOn;
-    changeDisplayBacklight(isBacklightAlwaysOn);
-  }
+    isBacklightAlwaysOn = !isBacklightAlwaysOn;
+    changeDisplayBacklight(isBacklightAlwaysOn);
+  }
+}
+
+void updateCurrentThresholdForCertainModes(){
+  float newThreshold = currentEnableThreshold;
+
+  if(isTopButtonPressed()){
+    changeEnableThreshold(currentEnableThreshold += 0.01);
+  }
+
+  if(isBottomButtonPressed()){
+    changeEnableThreshold(currentEnableThreshold -= 0.01);
+  }
+
+
+
 }

@@ -519,29 +550,50 @@
   return temperature;
 }

+bool isTopButtonPressed(){
+  int upPressed = digitalRead(PIN_BUTTON_UP);
+
+  if(upPressed == LOW){
+    return buttonDebounceComplete();
+  } else {
+    return false;
+  }
+}
+
 bool isMiddleButtonPressed(){
-
   int enterPressed = digitalRead(PIN_BUTTON_ENTER);

   if(enterPressed == LOW){
-
-    static unsigned long lastPressedTime = 0;
-    unsigned long currentTime = millis();
-
-    if((currentTime - lastPressedTime) > BUTTON_DEBOUNCE){
-      lastPressedTime = currentTime;
-      return true;
-    } else {
-      return false;
-    }
-
+    return buttonDebounceComplete();
   } else {
     return false;
   }
 }

+bool isBottomButtonPressed(){
+  int downPressed = digitalRead(PIN_BUTTON_DOWN);
+
+  if(downPressed == LOW){
+    return buttonDebounceComplete();
+  } else {
+    return false;
+  }
+}
+
+bool buttonDebounceComplete(){
+  static unsigned long lastPressedTime = 0;
+  unsigned long currentTime = millis();
+
+  if((currentTime - lastPressedTime) > BUTTON_DEBOUNCE){
+    lastPressedTime = currentTime;
+    return true;
+  } else {
+    return false;
+  }
+}
+
 void shortBeepXTimesNoDelay(int times){
-  beepsLeft = times;
+  beepsLeft = times;
 }

 //We don't use delay from beeps to avoid holding up the controller
@@ -562,7 +614,7 @@
           beepCurrentlyOn = false;
           beepsLeft--;
       }
-
+
     } else {

       if((currentTime - beepChangedTime) > BUZZER_BEEP_OFF_TIME){
@@ -572,7 +624,7 @@
       }
     }
   }
-
+
 }

 //Returns true if temperature threshold has been reached
@@ -581,7 +633,7 @@
   if(temperature >= TEMP_MAX){
     nextState = STATE_TEMP_MAX;
     return true;
-
+
   } else if(temperature >= TEMP_WARN){
     static unsigned long lastTempAlert = 0;

@@ -589,13 +641,12 @@

     if((currentTime - lastTempAlert) > TEMP_WARNING_RATE){
       lastTempAlert = currentTime;
-      shortBeepXTimesNoDelay(5);
+      shortBeepXTimesNoDelay(5);
     }

     return true;
-
+
   }

   return false;
 }
-


Tested on pool table for x-rail

Tested on pool table for x-rail

~ x-rail functionality works consistently with end-stops, user-buttons, and serial-line movement request
~ next is to test y-rail with x-rail on pool table

--- src/microController/microController.ino
+++ src/microController/microController.ino
@@ -1,7 +1,3 @@
-// Include  ////////////////////////////////////////////////////////////////////////////////
-
-#include <EEPROM.h>
-
 // Define  ////////////////////////////////////////////////////////////////////////////////

 #define X1_STEP_PIN          54 //X1->X
@@ -31,12 +27,12 @@
 #define RMIN_PIN             27 //r sensor 1
 #define RMAX_PIN             29 //r sensor 2

-#define USERBUTTON1_PIN      20
-#define USERBUTTON2_PIN      21
-
-#define UPPERBOUND_X         10000 //Number of steps for full range of motion in X, need test empirically
+#define USERBUTTON1_PIN      20 //move button
+#define USERBUTTON2_PIN      21 //user control button
+
+#define UPPERBOUND_X         10000 //Number of steps for full range of motion in X, tested, somehow exactly 10000
 #define UPPERBOUND_Y         10000 //Number of steps for full range of motion in Y, need test empirically
-#define UPPERBOUND_R         197 //Number of steps for full rotation in R, need test empirically
+#define UPPERBOUND_R         197   //Number of steps for full rotation in R, need test empirically
 #define UPPERBOUND_E         3     //Number of power settings for take shot, probably 3

 #define MICRODELAY           800
@@ -59,7 +55,10 @@
 int yDir; //Direction Y should move
 int rDir; //Direction R should move

+bool moveControl = false; //Used in move button funcitonality
 bool userControl = false; //Enable or disable user turn
+bool sensorsEnabled = false; //Enable or disable sensors
+

 // Setup  /////////////////////////////////////////////////////////////////////////////////

@@ -94,11 +93,8 @@
   pinMode(YMAX_PIN, INPUT);
   pinMode(RMIN_PIN, INPUT);
   pinMode(RMAX_PIN, INPUT);
-
   pinMode(USERBUTTON1_PIN, INPUT);
-  attachInterrupt(digitalPinToInterrupt(USERBUTTON1_PIN), UserButton1, FALLING);
   pinMode(USERBUTTON2_PIN, INPUT);
-  attachInterrupt(digitalPinToInterrupt(USERBUTTON2_PIN), UserButton2, FALLING);

   InitializeRoutine();

@@ -110,10 +106,10 @@
 {

   AllowUserTurn();
-  PoseForPicture();
-  if(userControl == false) RequestPCInstruction();
-  if(userControl == false) MoveXYR();
-  if(userControl == false) TakeShot();
+  if(!userControl) PoseForPicture();
+  if(!userControl) RequestPCInstruction();
+  if(!userControl) MoveXYR();
+  if(!userControl) TakeShot();

 }

@@ -123,11 +119,11 @@
 {

   requestedX = 0;
-  requestedY = 0;
-  requestedR = -1;
+  //requestedY = 0;
+  //requestedR = -1;
   currentX = UPPERBOUND_X - 1;
-  currentY = UPPERBOUND_Y - 1;
-  currentR = UPPERBOUND_R - 1;
+  //currentY = UPPERBOUND_Y - 1;
+  //currentR = UPPERBOUND_R - 1;
   MoveXYR();

 }
@@ -139,8 +135,8 @@
   char aChar;
   int val;
   int count = 1000;
-
-  memset(&readline[0], 0, sizeof(readline));
+
+  while(Serial.available()) char getData = Serial.read(); //Clear buffer

   do {
     count++;
@@ -148,15 +144,17 @@
     {
       Serial.println("55");
       count = 0;
-    }
-    delay(10);
-  } while(Serial.available() <= 0); //Will loop forever until confirmation from PC
+    }
+    delay(10);
+    if(digitalRead(USERBUTTON2_PIN) == 0) UserButton2();
+  } while(Serial.available() <= 0 && !userControl); //Will loop forever until confirmation from PC

   count = 0;

   do {
     delay(10);
-  } while(Serial.available() <= 0); //Will loop forever until shot information from PC
+    if(digitalRead(USERBUTTON2_PIN) == 0) UserButton2();
+  } while(Serial.available() <= 0 && !userControl); //Will loop forever until shot information from PC

   do {
     aChar = Serial.read();
@@ -199,7 +197,7 @@
   else xDir = -1;

   digitalWrite(X1_DIR_PIN, xDir > 0);
-  digitalWrite(X2_DIR_PIN, xDir > 0);
+  digitalWrite(X2_DIR_PIN, xDir < 0);

   if (requestedY > currentY)  yDir = 1;
   else  yDir = -1;
@@ -221,41 +219,52 @@

   while(requestedX-currentX != 0 || requestedY-currentY != 0 || requestedR-currentR != 0)
   {
-
-    if(xDir == -1 && digitalRead(XMIN_PIN) == 0) //XMIN endstop hit
-    {
-      currentX = 0;
-      xDir = 1;
-      digitalWrite(X1_DIR_PIN, HIGH);
-      digitalWrite(X2_DIR_PIN, HIGH);
-    }
-
-    if(xDir == 1 && digitalRead(XMAX_PIN) == 0) //XMAX endstop hit
-    {
-      currentX = UPPERBOUND_X - 1;
-      xDir = -1;
-      digitalWrite(X1_DIR_PIN, LOW);
-      digitalWrite(X2_DIR_PIN, LOW);
-    }
-
-    if(yDir == -1 && digitalRead(YMIN_PIN) == 0) //YMIN endstop hit
-    {
-      currentY = 0;
-      yDir = 1;
-      digitalWrite(Y_DIR_PIN, HIGH);
-    }
-
-    if(yDir == 1 && digitalRead(YMAX_PIN) == 0) //YMAX endstop hit
-    {
-      currentY = UPPERBOUND_Y - 1;
-      yDir = -1;
-      digitalWrite(Y_DIR_PIN, LOW);
-    }
-
-    if(digitalRead(RMIN_PIN) == 0 && digitalRead(RMAX_PIN) == 0) //R reference point hit
-    {
-      currentR = 0;
-      if(requestedR == -1) requestedR = 0;
+      if(digitalRead(USERBUTTON1_PIN) == 0) UserButton1();
+      if(digitalRead(USERBUTTON2_PIN) == 0) UserButton2();
+
+      if(xDir == -1 && digitalRead(XMIN_PIN) == 0) //XMIN endstop hit
+      {
+        currentX = 0;
+        xDir = 1;
+        digitalWrite(X1_DIR_PIN, HIGH);
+        digitalWrite(X2_DIR_PIN, LOW);
+        delay(500);
+      }
+
+      if(xDir == 1 && digitalRead(XMAX_PIN) == 0) //XMAX endstop hit
+      {
+        currentX = UPPERBOUND_X - 1;
+        xDir = -1;
+        digitalWrite(X1_DIR_PIN, LOW);
+        digitalWrite(X2_DIR_PIN, HIGH);
+        delay(500);
+      }
+
+    if(sensorsEnabled)
+    {
+
+      if(yDir == -1 && digitalRead(YMIN_PIN) == 0) //YMIN endstop hit
+      {
+        currentY = 0;
+        yDir = 1;
+        digitalWrite(Y_DIR_PIN, HIGH);
+      }
+
+      if(yDir == 1 && digitalRead(YMAX_PIN) == 0) //YMAX endstop hit
+      {
+        currentY = UPPERBOUND_Y - 1;
+        yDir = -1;
+        digitalWrite(Y_DIR_PIN, LOW);
+      }
+
+      if(digitalRead(RMIN_PIN) == 0 || digitalRead(RMAX_PIN) == 0) //R reference point hit
+      {
+        currentR = 0;
+        if(requestedR == -1)
+        {
+          requestedR = 0;
+        }
+      }
     }

     if(requestedX-currentX != 0)
@@ -317,6 +326,8 @@
   {
     MoveXYR();
     delay(10);
+    if(digitalRead(USERBUTTON1_PIN) == 0) UserButton1();
+    if(digitalRead(USERBUTTON2_PIN) == 0) UserButton2();
   }

 }
@@ -332,19 +343,39 @@

 void UserButton1() //Tell machine to move out of the way
 {
-
   if (userControl)
   {
-    if(requestedX == currentX && requestedX != 0) requestedX = 0; //Move to 0
-    else if(requestedX == 0) requestedX =  UPPERBOUND_X - 1; //Move to upperboundX - 1
-    else requestedX = currentX; //Stop moving
+    delay(250);
+    if(requestedX != currentX) requestedX = currentX; //Stop Moving
+    else
+    {
+      if(moveControl == false && requestedX != 0) //Move to 0
+      {
+        requestedX = 0;
+        moveControl = true;
+      }
+      else if(moveControl == true && requestedX != UPPERBOUND_X - 1)  //Move to UPPERBOUND_X
+      {
+        requestedX =  UPPERBOUND_X - 1;
+        moveControl = false;
+      }
+      else if(moveControl == false && requestedX == 0) //At 0, move to UPPERBOUND_X instead
+      {
+        requestedX = UPPERBOUND_X - 1;
+      }
+      else if(moveControl == true && requestedX == UPPERBOUND_X - 1) //At UPPERBOUND_X, move to 0 instead
+      {
+        requestedX =  0;
+      }
+    }
   }

 }

 void UserButton2() //Give/relinquish user control
 {
-
+
+  delay(250);
   userControl = !userControl;
   requestedX = currentX;
   requestedY = currentY;


Radio init

Radio init

--- pitch_notes/pitch_notes.ino
+++ pitch_notes/pitch_notes.ino
@@ -22,11 +22,37 @@
 #define SCALE 32

 #include <FHT.h> // include the library
-
-const int NUM_SPELLS = 2;
-int *spell_length;
-int **spell_sequence;
-char **spell_name;
+#include <chibi.h>
+#include <Wire.h>
+#include <stdint.h>
+
+//// globals radio
+//
+  int hgmPin = 22;
+  int ledPin = 18;
+  int vbatPin = 31;
+  int vsolPin = 29;
+  int led_state = 1;
+
+  #define ADCREFVOLTAGE 3.3
+  #define NODE_ID 300
+//
+
+//// globals spells
+//
+  const int NUM_SPELLS = 2;
+  int *spell_length;
+  int **spell_sequence;
+  char **spell_name;
+  int sound_buffer[FHT_N];
+  int current_note=0;
+  int note_duration=0;
+  int cur_sequence[10];
+  int seq_index=0;
+  int pin13_state=LOW;
+  int pin12_state=LOW;
+//
+

 int note_letter_to_int(char note)
 {
@@ -95,6 +121,7 @@
 void setup() {
   Serial.begin(115200); // use the serial port
   Serial.println("starting");
+
  // ADC configuration
  // set prescale to 16
  sbi(ADCSRA,ADPS2) ;
@@ -106,8 +133,7 @@

- // Spells initialization
-
+ //// Spells initialization
  spell_length = new int[NUM_SPELLS];
  spell_sequence = new int*[NUM_SPELLS];
  spell_name = new char*[NUM_SPELLS];
@@ -120,10 +146,26 @@

  make_spell(0, "Red Led", "CDEC");
  make_spell(1, "Green Led", "FGFG");
+
+
+  //// Initialize radio
+  // set up high gain mode pin
+  pinMode(hgmPin, OUTPUT);
+  digitalWrite(hgmPin, LOW);
+  // set up battery monitoring
+  pinMode(vbatPin, INPUT);
+  // set up LED
+  pinMode(ledPin, OUTPUT);
+  digitalWrite(ledPin, LOW);
+  // Initialize the chibi command line and set the speed to 57600 bps
+  chibiCmdInit(115200);
+  // Initialize the chibi wireless stack
+  chibiInit();
+  // high gain mode
+  digitalWrite(hgmPin, HIGH);
+
  Serial.println("setup done");
 }
-
-int sound_buffer[FHT_N];

 void detect_note(float& note, float& volume)
 {
@@ -184,12 +226,6 @@
 }

-int current_note=0;
-int note_duration=0;
-int cur_sequence[10];
-int seq_index=0;
-int pin13_state=LOW;
-int pin12_state=LOW;

 void loop() {
     int note;
@@ -277,6 +313,11 @@
            else
              pin13_state=LOW;
            digitalWrite(13, pin13_state);
+           char sbuf[100];
+           sprintf(sbuf, "SPELL:%s", spell_name[spell]);
+           Serial.println(sbuf);
+           chibiTx(BROADCAST_ADDR, (unsigned char*)(&sbuf), strlen(sbuf)+1);
+           free(sbuf);
           }
           if(spell==1)
           {


Added french accent to welcome message

Added french accent to welcome message

--- controle_par_mannette/controle_par_mannette.ino
+++ controle_par_mannette/controle_par_mannette.ino
@@ -15,7 +15,7 @@
 //
 /////////////////////////////////////////////////////////////

-#define DEBOGGAGE 1
+#define DEBOGGAGE 0

 // Numéro de pin des sorties vers les moteurs
 const int moteur_avant   =  9;


Update rotaryEncoder.ino

Update rotaryEncoder.ino

--- RotaryEncoder/rotaryEncoder/rotaryEncoder.ino
+++ RotaryEncoder/rotaryEncoder/rotaryEncoder.ino
@@ -6,7 +6,7 @@
 const int PinDT=3;                    // Used for reading DT signal
 const int PinSW=8;                    // Used for the push button switch

-volatile long     virtualPosition  =0;  // without STATIC it does not count correctly!!!
+volatile long     virtualPosition  =0;  // must be volatile to work with the isr

 void isr0 ()  {
   detachInterrupt(0);


remove IR activates led blinking

remove IR activates led blinking

--- client/client.ino
+++ client/client.ino
@@ -39,11 +39,12 @@
 char deviceId[3] = "00";
 char XBeeInString[50];

-unsigned int ledStateInterval = 500;
+
 boolean eighty_twenty = false;

 unsigned int blinkFast = 200;
 unsigned int blinkSlow = 200;
+unsigned int ledStateInterval = blinkFast;
 unsigned long randomDelay = 0;
 unsigned long start_time;
 unsigned long end_time;
@@ -110,10 +111,7 @@
     DEBUG_PRINTLN(results.value);
     sendBackDeviceID();
     irrecv.resume();
-
-    //client starts blinking
-    statePending = true;
-    ledStateInterval = 800;
+

   }
   else if (XBee.available()) {
@@ -122,6 +120,8 @@
     printXBeePacket(p);

     DEBUG_TAGGING("id: ", p.id);
+    DEBUG_TAGGING("func: ", p.func);
+    DEBUG_TAGGING("var: ", p.var);
     DEBUG_TAGGING("data: ", p.data);

     if ( strcmp(p.id, "FF") == 0 ) {


catch rising voltage for interrupts, works well with new rotary switch circuit

--- super_freq/super_freq.ino
+++ super_freq/super_freq.ino
@@ -31,11 +31,11 @@

     // setup interrupt 0 (digital pin 2) to detect changed palette
     // rotary switch position
-    attachInterrupt(0, palette_switch_changed, LOW);
+    attachInterrupt(0, palette_switch_changed, RISING);

     // setup interrupt 1 (digital pin 3) to detect changed pattern
     // rotary switch position
-    attachInterrupt(1, pattern_switch_changed, LOW);
+    attachInterrupt(1, pattern_switch_changed, RISING);

     pinMode(pattern_button_pin, INPUT);
     pinMode(white_out_button_pin, INPUT);
@@ -87,10 +87,6 @@
     }

     if (palette_switch_flag) {
-        // disable palette rotary switch interrupt
-        // while we determine switch values
-        detachInterrupt(0);
-
         input_A1 = read_analog_pin(A1);
         new_palette_choice = determine_switch_selection(input_A1);
         changeColorPalette();
@@ -101,23 +97,18 @@
         }

         palette_switch_flag = false;
-
-        // re-enable palette switch interrupt
-        attachInterrupt(0, palette_switch_changed, LOW);
     }

     if (pattern_switch_flag) {
-        // disable pattern rotary switch interrupt
-        // while we determine switch values
-        detachInterrupt(1);
-
         input_A2 = read_analog_pin(A2);
         pattern_choice = determine_switch_selection(input_A2) - 1;

+        if (DEBUG) {
+            Serial.print("Analog value: ");
+            Serial.println(input_A2);
+        }
+
         pattern_switch_flag = false;
-
-        // re-enable pattern switch interrupt
-        attachInterrupt(1, pattern_switch_changed, LOW);
     }

     // read pattern engage input pin here


Using delayAtLeast instead of Timer1, verified working

--- Flameduino/Flameduino.ino
+++ Flameduino/Flameduino.ino
@@ -35,17 +35,17 @@
 // -------------------------
 //        Settings
 // -------------------------
-const bool debug = true;       //true = write to serial monitor, false = bypass
-const int serialOutLoops = 000; //Number of loops that should execute before a serial write
+const bool debug = false;       //true = write to serial monitor, false = bypass
+const int serialOutLoops = 300; //Number of loops that should execute before a serial write
 //Ignition Settings
 const int dwell = 2500;         //Ignition coil charging dwell in microseconds (2.5ms = 2500us)
-const long periodMax = 2000000; //Maximum period between ignitions, in microseconds (min frequency)
+const long periodMax = 1000000; //Maximum period between ignitions, in microseconds (min frequency)
 const long periodMin = 5000;    //Minimum period between ignitions, in microseconds (max frequency)
 const int periodCorrection = 0; //Variance to period due to loop code execution time (milliseconds)
-const float linearity = 2.5;    //1.0 = linear, 0.5 = more resolution in the high end, 2.0 = more resolution in the low end (exponential)
+const float linearity = 3.0;    //1.0 = linear, 0.5 = more resolution in the high end, 2.0 = more resolution in the low end (exponential)
 const bool triggerHigh = true;  //true = HIGH to fire, false = LOW to fire
 //Multifire Settings
-const bool multiFire = false;    //true = fire [firingCount] times per period, false = fire once per period
+const bool multiFire = true;    //true = fire [firingCount] times per period, false = fire once per period
 const int multiCount = 3;       //Numeber of sparks to fire per event
 const int multiDelay = 2000;    //Delay between multifires in microseconds (2ms = 2000us)
 //Tachometer Settings
@@ -58,7 +58,6 @@
 // -------------------------
 volatile bool active = false;
 byte ignitionMode = OFF;
-volatile bool updateTimer = true;
 volatile unsigned long tachPrevious = 0;
 volatile unsigned long tachCurrent = 0;
 unsigned long tachDuration0 = 0;
@@ -92,8 +91,6 @@
   attachInterrupt(TACH_PIN - 2, ISR_TACH, RISING);
   attachInterrupt(ACTIVATION_PIN - 2, ISR_ACTIVE, CHANGE);

-  initializeTimer1();
-
   if (debug)
   {
     Serial.begin(9600);
@@ -122,62 +119,7 @@
   else if (!active && ignitionMode != OFF)
     disableCoil();

-  //Fire Ignition
-  switch(ignitionMode)
-  {
-    case FIRE:
-      dischargeCoil();
-      if (multiFire) remainingCount = multiCount - 1;
-      updateTimer = true;
-      break;
-    case MULTIFIRE:
-      dischargeCoil();
-      remainingCount--;
-      updateTimer = true;
-      break;
-  }
-
-  if (updateTimer == true)
-  {
-    stopTimer1();
-    updateTimer = false;
-    timerCount++;
-
-    if (debug && loopsSinceSerialWrite >= serialOutLoops)
-    {
-      Serial.print("Timer Reached - ");
-      Serial.print(timerCount);
-      Serial.print(", ");
-    }
-
-    ignitionMode = nextMode(ignitionMode);
-
-    //Set the delay period (Head of Mode)
-    switch(ignitionMode)
-    {
-      case OFF:
-        dischargeCoil();
-        break;
-      case DWELL:
-        //Charging Coil
-        chargeCoil();
-        startTimer1(dwell);
-        break;
-      case MF_WAIT:
-        //Waiting (MultiFire)
-        startTimer1(multiDelay);
-        break;
-      case MF_DWELL:
-        //Charging Coil
-        chargeCoil();
-        startTimer1(dwell);
-        break;
-      case WAIT:
-        //Waiting (Frequency)
-        startTimer1(period);
-        break;
-    }
-  }
+  completeIgnitionCycle();

   if (debug && loopsSinceSerialWrite >= serialOutLoops)
   {
@@ -197,122 +139,51 @@
 }

 // -------------------------
-//          Methods
-// -------------------------
-bool isActive()
-{
-  return digitalRead(ACTIVATION_PIN) == activeState;
-}
-
-long getPeriod()
-{
-  int frequency = analogRead(FREQUENCY_PIN);
-
-  float percentage = frequency / 1023.0;
-
-  if (debug && loopsSinceSerialWrite >= serialOutLoops)
-  {
-    Serial.print("Frequency: ");
-    Serial.print(frequency);
-    Serial.print("(");
-    Serial.print(percentage * 100);
-    Serial.print("%), ");
-  }
-
-  return periodMin + (periodMax - periodMin) * pow(percentage, linearity) + periodCorrection;
-}
-
-unsigned int getRPM()
-{
-  noInterrupts();
-  unsigned long current = tachCurrent;
-  unsigned long previous = tachPrevious;
-  interrupts();
-
-  if (isStale())
-  {
-    tachDuration0 = 0;
-    tachDuration1 = 0;
-    tachDuration2 = 0;
-    return 0;
-  }
-
-  unsigned long duration;
-  if (current >= previous)
-  {
-    duration = current - previous + tachTrim;
-  }
-  else
-  {
-    //Handle Rollover
-    duration = 0xFFFFFFFFu - previous + current + tachTrim;
-  }
-
-  //Shift the values
-  tachDuration2 = tachDuration1;
-  tachDuration1 = tachDuration0;
-  tachDuration0 = duration;
-
-  if (false && debug && loopsSinceSerialWrite >= serialOutLoops)
-  {
-    Serial.print("t0: ");
-    Serial.print(tachDuration0);
-    Serial.print(", t1: ");
-    Serial.print(tachDuration1);
-    Serial.print(", t2: ");
-    Serial.print(tachDuration2);
-    Serial.print(", ");
-  }
-
-  if (tachDuration0 <= 0 || tachDuration1 <= 0 || tachDuration2 <= 0)
-    return 0;
-
-  //Calculate Weighted Average duration
-  unsigned long average = (3*tachDuration0 + 2*tachDuration1 + 1*tachDuration2)/6;
-
-  //Convert to RPM
-  return 60.0 * 1000000 / average;
-}
-
-bool isStale()
-{
-  return (micros() - tachCurrent) > tachStale;
-}
-
-void enableCoil()
-{
-  //Enable Coil Firing
-  ignitionMode = DWELL;
-  updateTimer = true;
-}
-
-void disableCoil()
-{
-  //Disable Coil Firing
-  ignitionMode = OFF;
-  updateTimer = true;
-}
-
-void chargeCoil()
-{
-  digitalWrite(EXTERNAL_LED_PIN, HIGH);
-  digitalWrite(INTERNAL_LED_PIN, HIGH);
-
-  if (triggerHigh)
-    digitalWrite(IGNITION_PIN, HIGH);
-  else
-    digitalWrite(IGNITION_PIN, LOW);
-}
-
-void dischargeCoil()
-{
-  if (triggerHigh)
-    digitalWrite(IGNITION_PIN, LOW);
-  else
-    digitalWrite(IGNITION_PIN, HIGH);
+//      Ignition Cycle
+// -------------------------
+bool completeIgnitionCycle()
+{
+  for (;;)
+  {
+    //Run a Complete Ignition Cycle
+    switch(ignitionMode)
+    {
+      case OFF:
+        dischargeCoil();
+        break;
+      case DWELL:
+        //Charging Coil
+        chargeCoil();
+        delayAtLeast(dwell);
+        break;
+      case FIRE:
+        dischargeCoil();
+        if (multiFire) remainingCount = multiCount - 1;
+        break;
+      case MF_WAIT:
+        //Waiting (MultiFire)
+        delayAtLeast(multiDelay);
+        break;
+      case MF_DWELL:
+        //Charging Coil
+        chargeCoil();
+        delayAtLeast(dwell);
+        break;
+      case MULTIFIRE:
+        dischargeCoil();
+        remainingCount--;
+        break;
+      case WAIT:
+        //Waiting (Frequency)
+        delayAtLeast(period);
+        break;
+    }

-  digitalWrite(EXTERNAL_LED_PIN, LOW);
-  digitalWrite(INTERNAL_LED_PIN, LOW);
+    ignitionMode = nextMode(ignitionMode);
+
+    if (ignitionMode == WAIT) return true;
+    else if (!active || ignitionMode == OFF) return false;
+  }
 }

 byte nextMode(byte mode)
@@ -341,12 +212,129 @@
   }
 }

+// -------------------------
+//          Methods
+// -------------------------
+bool isActive()
+{
+  return digitalRead(ACTIVATION_PIN) == activeState;
+}
+
+long getPeriod()
+{
+  int frequency = analogRead(FREQUENCY_PIN);
+
+  float percentage = frequency / 1023.0;
+
+  if (debug && loopsSinceSerialWrite >= serialOutLoops)
+  {
+    Serial.print("Frequency: ");
+    Serial.print(frequency);
+    Serial.print("(");
+    Serial.print(percentage * 100);
+    Serial.print("%), ");
+  }
+
+  return periodMin + (periodMax - periodMin) * pow(percentage, linearity) + periodCorrection;
+}
+
+unsigned int getRPM()
+{
+  noInterrupts();
+  unsigned long current = tachCurrent;
+  unsigned long previous = tachPrevious;
+  interrupts();
+
+  if (isStale())
+  {
+    tachDuration0 = 0;
+    tachDuration1 = 0;
+    tachDuration2 = 0;
+    return 0;
+  }
+
+  unsigned long duration;
+  if (current >= previous)
+  {
+    duration = current - previous + tachTrim;
+  }
+  else
+  {
+    //Handle Rollover
+    duration = 0xFFFFFFFFu - previous + current + tachTrim;
+  }
+
+  //Shift the values
+  tachDuration2 = tachDuration1;
+  tachDuration1 = tachDuration0;
+  tachDuration0 = duration;
+
+  if (false && debug && loopsSinceSerialWrite >= serialOutLoops)
+  {
+    Serial.print("t0: ");
+    Serial.print(tachDuration0);
+    Serial.print(", t1: ");
+    Serial.print(tachDuration1);
+    Serial.print(", t2: ");
+    Serial.print(tachDuration2);
+    Serial.print(", ");
+  }
+
+  if (tachDuration0 <= 0 || tachDuration1 <= 0 || tachDuration2 <= 0)
+    return 0;
+
+  //Calculate Weighted Average duration
+  unsigned long average = (3*tachDuration0 + 2*tachDuration1 + 1*tachDuration2)/6;
+
+  //Convert to RPM
+  return 60.0 * 1000000 / average;
+}
+
+bool isStale()
+{
+  return (micros() - tachCurrent) > tachStale;
+}
+
+void enableCoil()
+{
+  //Enable Coil Firing
+  ignitionMode = DWELL;
+}
+
+void disableCoil()
+{
+  //Disable Coil Firing
+  ignitionMode = OFF;
+}
+
+void chargeCoil()
+{
+  digitalWrite(EXTERNAL_LED_PIN, HIGH);
+  digitalWrite(INTERNAL_LED_PIN, HIGH);
+
+  if (triggerHigh)
+    digitalWrite(IGNITION_PIN, HIGH);
+  else
+    digitalWrite(IGNITION_PIN, LOW);
+}
+
+void dischargeCoil()
+{
+  if (triggerHigh)
+    digitalWrite(IGNITION_PIN, LOW);
+  else
+    digitalWrite(IGNITION_PIN, HIGH);
+
+  digitalWrite(EXTERNAL_LED_PIN, LOW);
+  digitalWrite(INTERNAL_LED_PIN, LOW);
+}
+
 void fireMultiple()
 {
   fireCoil();
   for(int i = 1; i < multiCount; i++)
   {
-    delayMicroseconds(multiDelay);
+    delayAtLeast(multiDelay);
     fireCoil();
   }
 }
@@ -354,7 +342,7 @@
 void fireCoil()
 {
   chargeCoil();
-  delayMicroseconds(dwell);
+  delayAtLeast(dwell);
   dischargeCoil();
 }

@@ -374,105 +362,24 @@
   active = isActive();
 }

-void ISR_IGNITION()
-{
-  //Interrupt has fired
-  updateTimer = true;
-}
-
-//Attach ISR to Timer1 Overflow
-ISR(TIMER1_OVF_vect)
-{
-  ISR_IGNITION();
-}
-
 // -------------------------
 // Generic Utility Functions
 // -------------------------
-void delayFixed(long milliseconds)
-{
-  if (milliseconds <= 0)
+void delayFixed(unsigned long milliseconds)
+{
+  if (milliseconds = 0)
     return;
   else if (milliseconds < 16)
-    delayMicroseconds(milliseconds * 1000);
+    delayAtLeast(milliseconds * 1000);
   else
     delay(milliseconds);
 }

-void initializeTimer1()
-{
-  noInterrupts();
-  //Set Mode: Phase and Frequency correct PWM (stops the timer)
-  TCCR1A = 0;                 //Set Mode (bit 1A)
-  TCCR1B = bit(WGM13);        //Set Mode (bit 1B)
-  TIMSK1 = bit(TOIE1);        //Enable Overflow ISR
-  interrupts();
-}
-
-void startTimer1(unsigned long microseconds)
-{
-  char clockSelectBits;
-  short pwmPeriod;
-
-  //Calculate clock select bits
-  const unsigned long cycles = (F_CPU / 2000000) * microseconds;
-  if (cycles < TIMER1_RESOLUTION)
-  {
-    //No Prescaling
-    clockSelectBits = bit(CS10);
-    pwmPeriod = cycles;
-  }
-  else if (cycles < TIMER1_RESOLUTION * 8)
-  {
-    //Prescale by /8
-    clockSelectBits = bit(CS11);
-    pwmPeriod = cycles / 8;
-  }
-  else if (cycles < TIMER1_RESOLUTION * 64)
-  {
-    //Prescale by /64
-    clockSelectBits = bit(CS11) | bit(CS10);
-    pwmPeriod = cycles / 64;
-  }
-  else if (cycles < TIMER1_RESOLUTION * 256)
-  {
-    //Prescale by /256
-    clockSelectBits = bit(CS12);
-    pwmPeriod = cycles / 256;
-  }
-  else if (cycles < TIMER1_RESOLUTION * 1024)
-  {
-    //Prescale by /1024
-    clockSelectBits = bit(CS12) | bit(CS10);
-    pwmPeriod = cycles / 1024;
-  }
-  else
-  {
-    //Out of bounds, use maximum prescaler
-    clockSelectBits = bit(CS12) | bit(CS10);
-    pwmPeriod = TIMER1_RESOLUTION - 1;
-  }
-
-  noInterrupts();
-  TCNT1 = 1;                             //Resets the counter
-  ICR1 = pwmPeriod;                      //Sets the Period
-  //Set Mode: Phase and Frequency correct PWM (Starts the timer)
-  TCCR1A = 0;                            //Set Mode (bit 1A)
-  TCCR1B = bit(WGM13) | clockSelectBits; //Set Mode (bit 1B)
-  //unsigned int tcnt1;
-  //do {  // Nothing -- wait until timer moved on from zero - otherwise get a phantom interrupt
-  //  tcnt1 = TCNT1;
-  //} while (tcnt1==0);
-  interrupts();
-}
-
-void stopTimer1()
-{
-  noInterrupts();
-  //Set Mode: Phase and Frequency correct PWM (stops the timer)
-  TCCR1A = 0;                 //Set Mode (bit 1A)
-  TCCR1B = bit(WGM13);        //Set Mode (bit 1B)
-  interrupts();
+void delayAtLeast(unsigned long microseconds)
+{
+  unsigned long target = micros() + microseconds;
+  while (micros() < target)
+    ;
 }

 long readInternalTemp()


activate new classes, deactivate DallasTemperatureClass

--- firmware/Nanpy/Nanpy.ino
+++ firmware/Nanpy/Nanpy.ino
@@ -40,17 +40,17 @@
     REGISTER_CLASS(ArduinoClass);               // 0.8 k
     REGISTER_CLASS(LiquidCrystalClass);         // 2.3 k
     REGISTER_CLASS(OneWireClass);               // 1.7 k
-    REGISTER_CLASS(DallasTemperatureClass);     // 6.1 k
+//    REGISTER_CLASS(DallasTemperatureClass);     // 6.1 k
     REGISTER_CLASS(StepperClass);               // 0.8 k
     REGISTER_CLASS(ServoClass);                 // 2.5 k
     REGISTER_CLASS(ToneClass);                  // 2.2 k
     REGISTER_CLASS(CapacitiveSensorClass);      // 2.2 k

     // new classes
-    //REGISTER_CLASS(DefineClass);                // 0.6 k
-    //REGISTER_CLASS(ArduinoCoreClass);           // 0.7 k
-    //REGISTER_CLASS(WatchdogClass);              // 0.2 k
-    //REGISTER_CLASS(RegisterClass);              // 1.5 k
+    REGISTER_CLASS(DefineClass);                // 0.6 k
+    REGISTER_CLASS(ArduinoCoreClass);           // 0.7 k
+    REGISTER_CLASS(WatchdogClass);              // 0.2 k
+    REGISTER_CLASS(RegisterClass);              // 1.5 k

     ComChannel::connect();
 }


Code update ...

Code update ...

--- i2c_cmd_slave_attiny85/i2c_cmd_slave_attiny85.ino
+++ i2c_cmd_slave_attiny85/i2c_cmd_slave_attiny85.ino
@@ -167,7 +167,7 @@
 				byte acknowledge[2] = { 0 };
 				acknowledge[0] = opCodeAck;

-        command[1] = command[1] & 0xEF; // ERROR INJECTED IN SOME OPERANDS RECEIVED TO TEST CRC - REMOVE FOR PRODUCTION !!!
+        command[1] = command[1] & 0xEF; // ERROR INJECTED IN SOME OPERANDS RECEIVED TO TEST CRC - REMOVE THIS LINE FOR PRODUCTION !!!

         acknowledge[1] = CalculateCRC(command, 3);
 				digitalWrite(LED_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)


Another typo

Another typo

--- src/WiFiSensor/deepsleep.ino
+++ src/WiFiSensor/deepsleep.ino
@@ -64,7 +64,7 @@
 	  }

 	  if(mqttfailcount >= 30 ){
-		  Serial.println("Giving up MQTT connection"" );
+		  Serial.println("Giving up MQTT connection" );
 		  mqtttimeout = true;
 	  }


minor changes

minor changes


Delete Increasing_Difficulty.ino

Delete Increasing_Difficulty.ino

--- Increasing_Difficulty/Increasing_Difficulty.ino
+++ Increasing_Difficulty/Increasing_Difficulty.ino
@@ -1,115 +0,0 @@
-#include <LiquidCrystal.h>
-
-int ledPin = 6;
-const int buttonPin = 7;
-
-LiquidCrystal lcd(53, 51, 47, 43, 39, 35);
-
-static int count = 0;
-int buttonState = 0;
-int preButtonState = 0;
-
-unsigned long minutes = 60000;
-
-void setup() {
-lcd.clear();
-Serial.begin(9600);
-lcd.begin(16, 2);
-
-pinMode(ledPin, OUTPUT);
-pinMode(buttonPin, INPUT);
-
-lcd.setCursor(0, 0);
- lcd.print("Dance! xwyz!Lv.1");
- delay(1000);
-  lcd.setCursor(6, 1);
- lcd.print("3!");
- delay(1000);
-   lcd.setCursor(6, 1);
- lcd.print("2!");
-  delay(1000);
-   lcd.setCursor(6, 1);
- lcd.print("1!");
-  delay(1000);
-   lcd.setCursor(6, 1);
- lcd.print("Go!");
-  delay(1000);
-  lcd.clear();
-}
-
-
-void loop() {
-  if(millis() < minutes * 1) {
-lcd.setCursor(0, 0);
- lcd.print("Dance! xwyz!");
-  delay(1000);
-
-digitalWrite(ledPin, HIGH);
-
-unsigned long time = millis ();
-
-while( millis()-time < 500) {
-
-  buttonState = digitalRead(buttonPin);
-  if (buttonState != preButtonState ){
-    if (buttonState == LOW){
-      count = count + 1;
-    }
-  } preButtonState = buttonState;
-} digitalWrite(ledPin, LOW);
-  delay(10);
- }
- else {
-  if (count < 30) {
-    lcd.setCursor(0, 0);
- lcd.print("Your Score is:");
-  lcd.setCursor(6, 1);
- lcd.print(count);
-  }
-  else {
-    lcd.setCursor(0, 0);
- lcd.print("Dance! xwyz!Lv.2");
- delay(1000);
-  lcd.setCursor(6, 1);
- lcd.print("3!");
- delay(1000);
-   lcd.setCursor(6, 1);
- lcd.print("2!");
-  delay(1000);
-   lcd.setCursor(6, 1);
- lcd.print("1!");
-  delay(1000);
-   lcd.setCursor(6, 1);
- lcd.print("Go!");
-  delay(1000);
-  lcd.clear();
-
-  void loop(){
-  if(millis() < minutes * 1) {
-lcd.setCursor(0, 0);
- lcd.print("Dance! xwyz!");
-  delay(1000);
-
-digitalWrite(ledPin, HIGH);
-
-unsigned long time = millis ();
-
-while( millis()-time < 300) {
-
-  buttonState = digitalRead(buttonPin);
-  if (buttonState != preButtonState ){
-    if (buttonState == LOW){
-      count = count + 1;
-    }
-  } preButtonState = buttonState;
-} digitalWrite(ledPin, LOW);
-  delay(10);
- } else {
-   lcd.setCursor(0, 0);
- lcd.print("Your Score is:");
-  lcd.setCursor(6, 1);
- lcd.print(count);
- }
-  }
- }
-  }


Update comment.

Update comment.

--- examples/Nucleo/CosaNucleoBlink/CosaNucleoBlink.ino
+++ examples/Nucleo/CosaNucleoBlink/CosaNucleoBlink.ino
@@ -23,7 +23,8 @@
  * @section Description
  * Demonstration of Cosa Nucleo Threads; Blink LED with thread
  * delay and use an additional thread to control the LED blink
- * frequency.
+ * frequency. The main thread will power down while waiting for
+ * Watchdog ticks (ATtiny, LED on 2 mA, LED off >10 uA @ 3.7V).
  *
  * This file is part of the Arduino Che Cosa project.
  */


.More

.More

--- examples/extras/SitBit_Debounce/SitBit_Debounce.ino
+++ examples/extras/SitBit_Debounce/SitBit_Debounce.ino
@@ -10,7 +10,7 @@
 // Define the pin that represents the tilt switch
 const int tiltSwitch = 6;
 int stepCount = 0;
-int stepsLabel = 0;
+int stepsLabelId = 0;

 // Define constants for debounce
 const int min_on_time = 5;
@@ -40,7 +40,7 @@
   Serial.println("Press");
   stepCount++;
   if (SimbleeForMobile.updatable) {
-      SimbleeForMobile.updateValue(stepsLabel, stepCount);
+      SimbleeForMobile.updateValue(stepsLabelId, stepCount);
   }
 }

@@ -99,8 +99,6 @@

-
-
 void loop() {
   updateSwitchState();

@@ -112,12 +110,15 @@

 void ui()
 {
-  Serial.println("UI");
   SimbleeForMobile.beginScreen(WHITE);
+
+  // Place a Logo on the screen
+  SimbleeForMobile.drawText(110, 180, "Steps", BLACK, 40);
+
+  // Place an updateable label on the screen
+  stepsLabelId = SimbleeForMobile.drawText(150, 220, stepCount, BLACK, 40);

-  SimbleeForMobile.drawText(60, 90, "Steps");
-
-  stepsLabel = SimbleeForMobile.drawText(60, 310, stepCount);
+  SimbleeForMobile.endScreen();

   SimbleeForMobile.endScreen();
 }


Removed RF24 Library

Removed RF24 Library

Couldn't get them to work reliably.
Will change to BLE modules

--- Caravan_Thermostat_TX/Caravan_Thermostat_TX.ino
+++ Caravan_Thermostat_TX/Caravan_Thermostat_TX.ino
@@ -13,7 +13,6 @@
 #include <TimeLib.h>
 #include <DS1307RTC.h> // RTC Library
 #include <IRremote.h> // IR Library
-#include <RF24.h>

 // Define the pins.

@@ -33,10 +32,8 @@
 dht DHT;
 IRrecv irrecv(IRPIN);
 decode_results results;
-//RF24 radio(7,8);

 // Define Global Variables
-bool radioNumber = 0; //Master is 0, Slave is 1

 char PreviousTemperature[4];
 char PreviousHumidity[4];


VGA lcd sketch now is able to emulate all ssd1306 graphics directly in UART console

--- tools/vga_lcd/vga_lcd.ino
+++ tools/vga_lcd/vga_lcd.ino
@@ -4,13 +4,19 @@

 #define DEBUG

+void uart_send_byte(uint8_t c);
+
 extern uint16_t ssd1306_color;
+
+///////////////////////////////// VGA INTERFACE ///////////////////////////////////
+
 static uint8_t s_vga_command = 0xFF;
 static uint8_t s_cursor_x = 0;
 static uint8_t s_cursor_y = 0;
 static uint8_t s_column = 0;
 static uint8_t s_column_end = 0;
 static uint8_t s_page = 0;
+
 static uint8_t s_vga_buffer[64*40/2] = {0};

 void vga_interface_init()
@@ -20,13 +26,14 @@

 void vga_interface_stop()
 {
+    s_vga_command = 0xFF;
 }

 void vga_interface_close()
 {
 }

-void vga_put_pixel(uint8_t x, uint8_t y, uint8_t color)
+void vga_put_pixel4(uint8_t x, uint8_t y, uint8_t color)
 {
     uint8_t mask;
     if (x&1)
@@ -43,7 +50,7 @@
     s_vga_buffer[addr] |= color;
 }

-void vga_interface_send_byte(uint8_t data)
+void vga_interface_send_byte4(uint8_t data)
 {
     if (s_vga_command == 0xFF)
     {
@@ -53,7 +60,7 @@
     if (s_vga_command == 0x40)
     {
         uint8_t color = ((data & 0x80) >> 5) | ((data & 0x10) >> 3) | ((data & 0x02)>>1);
-        vga_put_pixel(s_cursor_x, s_cursor_y, color);
+        vga_put_pixel4(s_cursor_x, s_cursor_y, color);
         if (s_page == 0xFF)
         {
             s_cursor_x++;
@@ -74,14 +81,48 @@
         }
         return;
     }
+    if (!s_vga_command)
+    {
+        s_vga_command = data;
+    }
     // command mode
 }

+void vga_interface_send_byte1(uint8_t data)
+{
+    if (s_vga_command == 0xFF)
+    {
+        s_vga_command = data;
+        return;
+    }
+    if (s_vga_command == 0x40)
+    {
+        uint8_t mask = (0x1 << (s_cursor_x & 0x7));
+        uint16_t addr = (s_cursor_x + s_cursor_y*ssd1306_lcd.width)/8;
+        for(uint8_t i=8; i>0; i++)
+        {
+            if (data & 0x01)
+            {
+                s_vga_buffer[addr] |= mask;
+            }
+            else
+            {
+                s_vga_buffer[addr] &= ~mask;
+            }
+            data>>=1;
+            addr+=ssd1306_lcd.width/8;
+        }
+        s_cursor_x++;
+        return;
+    }
+    // command mode
+}
+
 void vga_interface_send_bytes(const uint8_t *buffer, uint16_t len)
 {
     while (len--)
     {
-        vga_interface_send_byte(*buffer);
+        ssd1306_intf.send(*buffer);
         buffer++;
     }
 }
@@ -91,10 +132,12 @@
     ssd1306_intf.spi = 0;
     ssd1306_intf.start = vga_interface_init;
     ssd1306_intf.stop = vga_interface_stop;
-    ssd1306_intf.send = vga_interface_send_byte;
+    ssd1306_intf.send = vga_interface_send_byte4;
     ssd1306_intf.send_buffer = vga_interface_send_bytes;
     ssd1306_intf.close = vga_interface_close;
 }
+
+/////////////////////////////// VGA LCD //////////////////////////////////

 void vga_set_block1(lcduint_t x, lcduint_t y, lcduint_t w)
 {
@@ -183,6 +226,71 @@
     ssd1306_lcd.set_mode = vga_set_mode;
 }

+/////////////////////////// UART /////////////////////////////////
+
+#define BAUD 115200
+#include <util/setbaud.h>
+#define UART_BUFFER_RX  32  // :( Still need large buffer to process USART RX bytes
+static uint8_t uart_get_ptr = 0;
+volatile static uint8_t uart_put_ptr = 0;
+volatile static uint8_t uart_buf[UART_BUFFER_RX];
+
+ISR(USART_RX_vect, ISR_BLOCK)
+{
+//    if (bit_is_clear(UCSR0A, FE0)) // Do not perform error checks for now
+//    {
+        uart_buf[uart_put_ptr] = UDR0;
+        uart_put_ptr = (uart_put_ptr+1) & (UART_BUFFER_RX - 1);
+//    }
+//    else
+//    {
+//        volatile unsigned char data __attribute__((unused)) = UDR0;
+//    }
+}
+
+void uart_init()
+{
+    UBRR0H = UBRRH_VALUE;
+    UBRR0L = UBRRL_VALUE;
+
+#if USE_2X
+    UCSR0A |= _BV(U2X0);
+#else
+    UCSR0A &= ~(_BV(U2X0));
+#endif
+
+    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
+    UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0);
+}
+
+void uart_send_byte(uint8_t c)
+{
+    loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
+    UDR0 = c;
+}
+
+uint8_t uart_byte_available(void)
+{
+    return uart_put_ptr != uart_get_ptr;
+}
+
+static inline uint8_t uart_byte_available_direct(void)
+{
+    return bit_is_set(UCSR0A, RXC0);
+}
+
+uint8_t uart_read_byte(void)
+{
+    uint8_t data = uart_buf[uart_get_ptr];
+    uart_get_ptr = (uart_get_ptr + 1) & (UART_BUFFER_RX - 1);
+    return data;
+}
+
+static inline uint8_t uart_read_byte_direct(void)
+{
+    return UDR0;
+}
+
 #ifdef DEBUG
 void debug_print_vga_buffer()
 {
@@ -191,18 +299,110 @@
         for(int x = 0; x < ssd1306_lcd.width; x++)
         {
             uint8_t color = (s_vga_buffer[(y*ssd1306_lcd.width + x)/2] >> ((x&1)<<2)) & 0x0F;
-            if (color) Serial.print("##");
-            else       Serial.print("  ");
-        }
-        Serial.println();
-    }
-    Serial.println();
+            if (color)
+            {
+                uart_send_byte('#');
+                uart_send_byte('#');
+            }
+            else
+            {
+                uart_send_byte(' ');
+                uart_send_byte(' ');
+            }
+        }
+        uart_send_byte('\r');
+        uart_send_byte('\n');
+    }
+    uart_send_byte('\r');
+    uart_send_byte('\n');
 }
 #endif

-NanoEngine8 engine;
-
-bool drawAll()
+enum
+{
+    UART_CMD_NONE      = 0x00, // Module is waiting for any input on UART
+    UART_CMD_PROXY     = 0x01, // Module proxies all bytes to vga library interface
+    UART_CMD_LISTEN    = 0x02, // Module waits for command over UART
+    UART_CMD_ESCAPE    = 0x7D, // Escape symbol, next needs to be modified via ^0x20
+    UART_CMD_FRAME_END = 0x7E, // Stop communication
+};
+
+/** Warning. May hold cpu while waiting for byte after 0x7D */
+void vga_uart_on_receive(uint8_t data)
+{
+    static uint8_t s_uart_command = UART_CMD_NONE;
+    static uint8_t s_uart_arg = 0;
+    for(;;)
+    {
+        if (data == UART_CMD_FRAME_END)
+        {
+            if (s_uart_command != UART_CMD_NONE)
+            {
+                s_uart_command = UART_CMD_NONE;
+                #ifdef DEBUG
+                    debug_print_vga_buffer();
+                #endif
+            }
+            return;
+        }
+        if (data == UART_CMD_ESCAPE)
+        {
+            while (!uart_byte_available());
+            data = uart_read_byte() ^ 0x20;
+        }
+        break;
+    }
+    if (s_uart_command == UART_CMD_NONE)
+    {
+        if ((data == 0x40) || (data == 0x00))
+        {
+            // Proxy standard LCD controller commands vga interface
+            ssd1306_intf.send(data);
+            s_uart_command = UART_CMD_PROXY;
+            return;
+        }
+        s_uart_command = data;
+        s_uart_arg = 0;
+    }
+    if (s_uart_command == UART_CMD_PROXY)
+    {
+        ssd1306_intf.send(data);
+        return;
+    }
+    // command mode
+    if (s_uart_command == UART_CMD_LISTEN)
+    {
+        s_uart_command = data;
+        s_uart_arg = 0;
+    }
+    if (s_uart_command == 'C')
+    {
+        ssd1306_clearScreen();
+        ssd1306_setCursor(0,0);
+        s_uart_command = UART_CMD_LISTEN;
+    }
+    if (s_uart_command == 'T')
+    {
+        if (s_uart_arg) ssd1306_write(data);
+    }
+    if (s_uart_command == 'M')
+    {
+        if (s_uart_arg)
+        {
+            if (data >= '0') data -= '0';
+            ssd1306_setMode(data);
+            s_uart_command = UART_CMD_LISTEN;
+        }
+    }
+    s_uart_arg++;
+}
+
+
+/////////////////////////////// MAIN /////////////////////////////////////
+
+//NanoEngine8 engine;
+
+/*bool drawAll()
 {
     engine.canvas.clear();
     engine.canvas.setMode(CANVAS_MODE_TRANSPARENT);
@@ -213,24 +413,27 @@
     engine.canvas.setColor(RGB_COLOR8(255,0,0));
     engine.canvas.printFixed(16, 15, "This is example");
     return true;
-}
+}*/

 void setup()
 {
     init_vga_interface();
     init_vga_lcd();
     #ifdef DEBUG
-        Serial.begin(115200);
+        uart_init();
+//        Serial.begin(115200);
     #endif

     ssd1306_setFixedFont(ssd1306xled_font6x8);
     ssd1306_clearScreen();
-    ssd1306_printFixed(1,8,"Hello",STYLE_BOLD);
-
-    engine.begin();
+    ssd1306_printFixed(10,8,"SSD1306",STYLE_BOLD);
+    ssd1306_printFixed(24,16,"by",STYLE_BOLD);
+    ssd1306_printFixed(4,24,"Alexey D.",STYLE_BOLD);
+
+/*    engine.begin();
     engine.drawCallback( drawAll );
     engine.refresh();
-    engine.display();
+    engine.display(); */

     #ifdef DEBUG
         debug_print_vga_buffer();
@@ -239,4 +442,9 @@

 void loop()
 {
-}
+    while (uart_byte_available())
+    {
+        uint8_t data = uart_read_byte();
+        vga_uart_on_receive(data);
+    }
+}


Added 1.6.10 support

Added 1.6.10 support

--- src/Deutsch/NOKO/NOKO.ino
+++ src/Deutsch/NOKO/NOKO.ino
@@ -5,7 +5,7 @@
  * The main loop controls the timing events and gets interrupted by the taste()-funtion.
  * Otherwise NOKO falls asleep with powerdowndelay() for 120ms. This saves a lot of power.
  *
- * Flash-Usage: 29.308 (1.6.10 | AVR Core 1.6.12 | Linux x86_64, Windows 10 | Compiler Options)
+ * Flash-Usage: 28.308 (1.6.10 | AVR Core 1.6.12 | Linux x86_64, Windows 10 | Compiler Options)
  *
  * Optional:
  * Compiler Options:   -funsafe-math-optimizations -mcall-prologues -maccumulate-args