removed obsolete code blocks; added PMW settings again

--- Esp8266/Esp8266.ino
+++ Esp8266/Esp8266.ino
@@ -1,5 +1,4 @@
 #include <ESP8266mDNS.h>        // https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266mDNS/src/ESP8266mDNS.h
-#include <ESP8266WiFiMulti.h>   // https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h
 #include <StreamString.h>       // https://github.com/esp8266/Arduino/blob/master/cores/esp8266/StreamString.h

 #include <Esp8266Utils.h>       // https://github.com/hunsalz/esp8266utils
@@ -22,16 +21,11 @@
   // setup hardware components
   _motorA.begin(MOTOR_A_PWM, MOTOR_A_DIR);
   _motorB.begin(MOTOR_B_PWM, MOTOR_B_DIR);
-  //esp8266utils::setPWMRange(PWM_RANGE);
+  // setup PWM range once
+  _motorA.setPWMRange(PWM_RANGE);

   // WiFi AP setup
   esp8266utils::setupWiFiAp(WIFI_AP_SSID, WIFI_AP_PSK);
-
-//  // WiFi station setup
-//  ESP8266WiFiMulti wifiMulti;
-//  wifiMulti.addAP(WIFI_SSID_1, WIFI_PSK_1);
-//  wifiMulti.addAP(WIFI_SSID_2, WIFI_PSK_2);
-//  esp8266utils::setupWiFiSta(wifiMulti);

   // MDNS setup
   const char* hostname = "esp8266";
@@ -83,15 +77,6 @@
     request->send(response);
     delete payload;
   });
-//  webService.on("/sta", HTTP_GET, [](AsyncWebServerRequest* request) {
-//
-//    AsyncResponseStream *response = request->beginResponseStream("application/json");
-//    StreamString* payload = new StreamString();
-//    size_t size = esp8266utils::serializeWiFiSta(*payload);
-//    response->print(*payload);
-//    request->send(response);
-//    delete payload;
-//  });
   webService.on("/esp", HTTP_GET, [](AsyncWebServerRequest* request) {

     AsyncResponseStream *response = request->beginResponseStream("application/json");


Update Keypad.ino

Update Keypad.ino

--- ComboKeypad/Keypad.ino
+++ ComboKeypad/Keypad.ino
@@ -94,7 +94,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 for(int a = 0; a < numOfCombos; a++){
   if(input[a] != combination[a] && count == numOfCombos){
-    digitalWrite(wrongLight, 1);   //Lights up the "Red" button
+    digitalWrite(wrongLight, 1);   //Lights up the "red" button
      Serial.println("Wrong");   //Prints that the combination is wrong
       delay(100);   //Safety delay
        reset();   //Runs the reset function


Added some code to sum analog and digital values to outpins connected to it input pins.

--- ServerSketch/ServerSketch.ino
+++ ServerSketch/ServerSketch.ino
@@ -702,7 +702,10 @@
     memset(g_aPins[i].connections, '\0', sizeof(g_aPins[i].connections));
     for(int j=0; j<TOTAL_NUM_OF_PINS; j++)
     {
-      g_aPins[i].connections[j] = false;
+      if( i == j ) // Pins are always connected to themselves
+        g_aPins[i].connections[j] = true;
+      else
+        g_aPins[i].connections[j] = false;
     }
   }

@@ -763,33 +766,80 @@

 void updateBoardState()
 {
+  // Update input pins first
   for(int i=0; i<TOTAL_NUM_OF_PINS; i++)
   {
-    if( g_aPins[i].is_input )
-    {
-      if( g_aPins[i].is_analog )
+    if( g_aPins[i].is_input ) // Process input pins
+    {
+      if( g_aPins[i].is_analog ) // Process analog pins
       {
         g_aPins[i].value = analogRead(i)/float(ANALOG_IN_MAX_VALUE);
       }
-      else
+      else // Process digital pins
       {
         g_aPins[i].value = digitalRead(i);
       }
     }
-    else
-    {
-      if( g_aPins[i].is_analog )
+  }
+
+  // Update outputs pins
+  for(int i=0; i<TOTAL_NUM_OF_PINS; i++)
+  {
+    if( !g_aPins[i].is_input ) // Process output pins
+    {
+       //Serial.println("HERE");
+//       Serial.print("Is Analog: ");Serial.println(g_aPins[i].is_analog);
+      if( g_aPins[i].is_analog ) // Process analog pins
       {
-        analogWrite(i, int(g_aPins[i].value*ANALOG_OUT_MAX_VALUE) );
+        //analogWrite(i, int(g_aPins[i].value*ANALOG_OUT_MAX_VALUE) );
+  //      Serial.print("Analog Pin "); Serial.print(i); Serial.print(": ");Serial.println(getTotalPinAnalogValue(i));
+        analogWrite(i, getTotalPinAnalogValue(i)*ANALOG_OUT_MAX_VALUE );
       }
-      else
+      else // Process digital pins
       {
-        digitalWrite(i, int(g_aPins[i].value) );
+        //digitalWrite(i, int(g_aPins[i].value) );
+  //      Serial.print("Digital Pin "); Serial.print(i); Serial.print(": ");Serial.println(getTotalPinDigitalValue(i));
+        digitalWrite(i, getTotalPinDigitalValue(i) );
       }
     }
   }
 }

+float getTotalPinAnalogValue(int _iPinNum)
+{
+  float fPinValSum = 0;
+
+  for(int i=0; i<TOTAL_NUM_OF_PINS; i++)
+  {
+    // Checking what pins are connected to iPinNum
+    if(g_aPins[_iPinNum].connections[i])
+    {
+      fPinValSum += g_aPins[i].value;
+      Serial.print(i); Serial.print(" --> "); Serial.println(_iPinNum);
+      Serial.print("Value: "); Serial.println(fPinValSum);
+    }
+  }
+
+  if(fPinValSum > 1.0)
+    fPinValSum = 1.0;
+
+  return fPinValSum;
+}
+
+int getTotalPinDigitalValue(int _iPinNum)
+{
+  for(int i=0; i<TOTAL_NUM_OF_PINS; i++)
+  {
+    // Checking what pins are connected to iPinNum
+    if(g_aPins[_iPinNum].connections[i])
+    {
+      if(g_aPins[i].value == 1.0)
+        return 1.0;
+    }
+  }
+
+  return 0.0;
+}

 // Get the board state and return a JSON object
 aJsonObject* getJsonBoardState()
@@ -1094,8 +1144,8 @@
       // Print pin value after assigment
 //            Serial.println("Pin Data: ");
       //      char sPinState[128];
-  //    snprintf(sPinState, sizeof(sPinState), "%s,%i,%i,%f", g_aPins[i].label, g_aPins[i].is_analog, g_aPins[i].is_input, g_aPins[i].value);
-  //    Serial.println(sPinState);
+   //   snprintf(sPinState, sizeof(sPinState), "%s,%i,%i,%f", g_aPins[i].label, g_aPins[i].is_analog, g_aPins[i].is_input, g_aPins[i].value);
+    //  Serial.println(sPinState);

     }
   }
@@ -1194,7 +1244,12 @@
 int g_ToggleFlag = 0;
 char g_acPin3_On[] = "{\"status\":\"OK\",\"pins\":{ \"13\":{\"label\":\"Pin 13\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"1\"}, \"2\":{\"label\":\"Pin 2\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"1\"}, \"4\":{\"label\":\"Pin 4\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"1\"}, \"7\":{\"label\":\"Pin 7\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"1\"}, \"8\":{\"label\":\"Pin 8\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"1\"}, \"12\":{\"label\":\"Pin 12\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"1\"}, \"3\":{\"label\":\"Pin 3\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.9\"}, \"5\":{\"label\":\"Pin 5\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.9\"}, \"6\":{\"label\":\"Pin 6\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.9\"}, \"9\":{\"label\":\"Pin 9\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.9\"}, \"10\":{\"label\":\"Pin 10\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.9\"}, \"11\":{\"label\":\"Pin 11\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.9\"}   }}";
 char g_acPin3_Off[] = "{\"status\":\"OK\",\"pins\":{ \"13\":{\"label\":\"Pin 13\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"0\"}, \"2\":{\"label\":\"Pin 2\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"0\"}, \"4\":{\"label\":\"Pin 4\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"0\"}, \"7\":{\"label\":\"Pin 7\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"0\"}, \"8\":{\"label\":\"Pin 8\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"0\"}, \"12\":{\"label\":\"Pin 12\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"0\"}, \"3\":{\"label\":\"Pin 3\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.1\"}, \"5\":{\"label\":\"Pin 5\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.1\"}, \"6\":{\"label\":\"Pin 6\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.1\"}, \"9\":{\"label\":\"Pin 9\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.1\"}, \"10\":{\"label\":\"Pin 10\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.1\"}, \"11\":{\"label\":\"Pin 11\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.1\"}   }}";
-char g_acConnA0_TO_3[] = "{\"status\":\"OK\",\"connections\":[{\"source\":\"14\",\"target\":\"3\"},{\"source\":\"15\",\"target\":\"5\"}]}";
+//char g_acConnA0_TO_3[] = "{\"status\":\"OK\",\"connections\":[{\"source\":\"14\",\"target\":\"3\"},{\"source\":\"15\",\"target\":\"5\"}]}";
+
+char g_acPin13_On_3_Analog[] = "{\"status\":\"OK\",\"pins\":{ \"13\":{\"label\":\"Pin 13\",\"is_analog\":\"false\",\"is_input\":\"false\",\"value\":\"1\"}, \"3\":{\"label\":\"Pin 3\",\"is_analog\":\"true\",\"is_input\":\"false\",\"value\":\"0.0\"}  }}";
+char g_acConnA0_TO_3[] = "{\"status\":\"OK\",\"connections\":[{\"source\":\"14\",\"target\":\"3\"}]}";
+int g_iDebugState = 0;
+

 void loop()
 {
@@ -1209,20 +1264,44 @@

     ///////////////////////////////////////
     // Test receiving message
-    /*
+
     if(g_ToggleFlag)
       snprintf(g_acMessage,sizeof(g_acMessage),g_acPin3_On);
     else
       snprintf(g_acMessage,sizeof(g_acMessage),g_acPin3_Off);

     g_ToggleFlag = ~g_ToggleFlag;
-      */
-
+
+    processMessage(g_acMessage);
+    updateBoardState();
+
+
+    ///////////////////////////////////////
+    /*
     // Connect/Disconnect
-    snprintf(g_acMessage,sizeof(g_acMessage),g_acConnA0_TO_3);
-
-    processMessage(g_acMessage);
+    switch(g_iDebugState)
+    {
+      case 0:
+        snprintf(g_acMessage,sizeof(g_acMessage),g_acPin13_On_3_Analog);
+        processMessage(g_acMessage);
+        g_iDebugState = 1;
+        Serial.println("HERE 0");
+      break;
+
+      case 1:
+        snprintf(g_acMessage,sizeof(g_acMessage),g_acConnA0_TO_3);
+        processMessage(g_acMessage);
+        g_iDebugState = 2;
+         Serial.println("HERE 1");
+      break;
+
+      default:
+
+      break;
+    }
+
     updateBoardState();
+    */
     ///////////////////////////////////////

     //////////////////////////////////////////


Finished initial command set

Finished initial command set

--- DigitalVFO.ino
+++ DigitalVFO.ino
@@ -169,6 +169,10 @@
 char CommandBuffer[MAX_COMMAND_LEN+1];
 int CommandIndex = 0;

+// buffer to assemble frequency as a string
+const int FreqBufferLen = 16;
+char FreqBuffer[FreqBufferLen];
+
 //##############################################################################
 // The VFO state variables and typedefs
 //
@@ -339,6 +343,70 @@
 }

 //----------------------------------------
+// Function to convert an unsigned long into a string.
+//     buf      address of buffer for byte results
+//     bufsize  the size of the buffer
+//     value    the unsigned long value to convert to a string
+// The buffer 'buf' is assumed long enough and is '\0' terminated.
+// Return address of first char in the string.
+//----------------------------------------
+
+char * ulong2str(char *buf, int bufsize, ULONG value)
+{
+  char *ptr = buf + bufsize - 1;    // rightmost char in 'buf'
+
+  while (value)
+  {
+    int rem = value % 10;
+
+    value = value / 10;
+    *ptr-- = rem + '0';
+  }
+
+  return ++ptr;
+}
+
+//----------------------------------------
+// Function to convert an array of byte digit values into an unsigned long.
+//     buf  address of buffer of byte digits, terminated with '\n'
+// Returns the unsigned long value.
+//----------------------------------------
+
+ULONG buff2ulong(char *buf)
+{
+  ULONG result = 0;
+
+  while (*buf)
+  {
+    result *= 10;
+    result += *buf;
+    ++buf;
+  }
+
+  return result;
+}
+
+//----------------------------------------
+// Function to convert a string into an unsigned long.
+//     str  start of string of digits, terminated with '\0'
+// Returns the unsigned long value.
+//----------------------------------------
+
+ULONG str2ulong(char *str)
+{
+  ULONG result = 0;
+
+  while (*str)
+  {
+    result *= 10;
+    result += *str - '0';
+    ++str;
+  }
+
+  return result;
+}
+
+//----------------------------------------
 // Convert a numeric mode to a display string.
 //----------------------------------------

@@ -366,6 +434,248 @@
   }
 }

+//----------------------------------------
+// Display the VFO mode on the screen..
+//----------------------------------------
+
+void vfo_display_mode(void)
+{
+// FIXME: if we display something else on bottom row change this code!
+
+  // clear row 1 and write new mode string
+  lcd.setCursor(0, 1);
+  lcd.write(BlankRow);
+  lcd.setCursor(0, 1);
+  lcd.write(mode2display(VfoMode));
+}
+
+
+//##############################################################################
+// External command routines.
+//
+// External commands are:
+//     MSO;         set VFO mode to 'online'
+//     MSS;         set VFO mode to 'standby'
+//     MG;          get VFO mode
+//     FSnnnnnnnn;  set frequency to 'nnnnnnnn'
+//     FG;          get frequency
+//     CSn;         set cursor to index 'n'
+//     CG;          get cursor index
+//     DS+n;        increment frequency digit by 'n'
+//     DS-n;        decrement frequency digit by 'n'
+//##############################################################################
+
+//----------------------------------------
+// Mode commands:
+//     MSO;
+//     MSS;
+//     MG;
+//----------------------------------------
+const char * xcmd_mode(char *cmd)
+{
+  switch (cmd[1])
+  {
+    case 'G':
+      // return VFO status
+      if (strlen(cmd) != 3)
+        return "ERROR";
+      if (VfoMode == vfo_Standby)
+        return "STANDBY";
+      if (VfoMode == vfo_Online)
+        return "ONLINE";
+      break;
+    case 'S':
+      if (strlen(cmd) != 4)
+        return "ERROR";
+      switch (cmd[2])
+      {
+        case 'O':
+          // set ONLINE mode
+          VfoMode = vfo_Online;
+          vfo_display_mode();
+          return "OK";
+        case 'S':
+          // set 'standby' mode
+          VfoMode = vfo_Standby;
+          vfo_display_mode();
+          return "OK";
+      }
+      break;
+  }
+
+  return "ERROR";
+}
+
+//----------------------------------------
+// Mode commands:
+//     FSnnnnnnnn;  set frequency to 'nnnnnnnn'
+//     FG;          get frequency
+//----------------------------------------
+
+const char * xcmd_freq(char *cmd)
+{
+  switch (cmd[1])
+  {
+    case 'G':
+      // return VFO frequency
+      if (strlen(cmd) == 3)
+      {
+        FreqBuffer[FreqBufferLen-1] = '\0';
+        return ulong2str(FreqBuffer, FreqBufferLen-2, VfoFrequency);
+      }
+      break;
+    case 'S':
+      if (strlen(cmd) <= 11)
+      {
+        char *freq_ptr = cmd + 2;
+
+        while (*freq_ptr != ';')
+        {
+          char ch = *freq_ptr++;
+
+          if (ch < '0' || ch > '9')
+          {
+            return "ERROR";
+          }
+        }
+        *freq_ptr = '\0';    // remove terminating ';'
+        VfoFrequency = str2ulong(cmd+2);
+        display_sel_value(VfoFrequency, VfoSelectDigit, NumFreqChars,
+                          NumCols - NumFreqChars - 2, 0);
+        return "OK";
+      }
+  }
+
+  return "ERROR";
+}
+
+//----------------------------------------
+// Cursor commands:
+//     CSn;  set cursor index to 'n'
+//     CG;   get cursor index
+//----------------------------------------
+
+const char * xcmd_cursor(char *cmd)
+{
+  switch (cmd[1])
+  {
+    case 'G':
+      // return cursor index
+      if (strlen(cmd) == 3)
+      {
+        FreqBuffer[0] = VfoSelectDigit + '0';
+        FreqBuffer[1] = '\0';
+        return FreqBuffer;
+      }
+      break;
+    case 'S':
+      if (strlen(cmd) == 4)
+      {
+        char *result_ptr = cmd + 2;
+
+        int new_index = *result_ptr - '0';
+        if (new_index <= 7)
+        {
+          VfoSelectDigit = new_index;
+          display_sel_value(VfoFrequency, VfoSelectDigit,
+                            NumFreqChars, NumCols - NumFreqChars - 2, 0);
+          return "OK";
+        }
+      }
+      break;
+  }
+
+  return "ERROR";
+}
+
+//----------------------------------------
+// Digit commands:
+//     DS+n;        increment frequency digit by 'n'
+//     DS-n;        decrement frequency digit by 'n'
+//----------------------------------------
+
+const char * xcmd_digit(char *cmd)
+{
+  switch (cmd[1])
+  {
+    case 'S':
+      if (strlen(cmd) == 5)
+      {
+        char sign = *(cmd + 2);
+
+        if (sign == '+' || sign == '-')
+        {
+          int inc = *(cmd + 3) - '0';
+
+          if (inc >= 0 && inc <= 9)
+          {
+            if (sign == '+')
+            {
+              while (inc--)
+              {
+                VfoFrequency += offset2bump[VfoSelectDigit];
+              }
+              if (VfoFrequency > MaxFreq)
+                VfoFrequency = MaxFreq;
+              display_sel_value(VfoFrequency, VfoSelectDigit,
+                                NumFreqChars, NumCols - NumFreqChars - 2, 0);
+            }
+            else
+            {
+              while (inc--)
+              {
+                VfoFrequency -= offset2bump[VfoSelectDigit];
+              }
+              if (VfoFrequency < MinFreq)
+                VfoFrequency = MinFreq;
+              display_sel_value(VfoFrequency, VfoSelectDigit,
+                                NumFreqChars, NumCols - NumFreqChars - 2, 0);
+            }
+            return "OK";
+          }
+        }
+      }
+      break;
+  }
+
+  return "ERROR";
+}
+
+//----------------------------------------
+// Process an external command.
+//     cmd     address of command string buffer
+//     index   index of last char in string buffer
+// 'cmd' is '\0' terminated.
+// Returns the command response string.
+//----------------------------------------
+const char * do_external_cmd(char *cmd, int index)
+{
+  char end_char = cmd[index];
+
+  // ensure everything is uppercase
+  str2upper(cmd);
+
+  // if command too long it's illegal
+  if (end_char != COMMAND_END_CHAR)
+  {
+    return (char *) "ERROR";
+  }
+
+  // process the command
+  switch (cmd[0])
+  {
+    case 'M':
+      return xcmd_mode(cmd);
+    case 'F':
+      return xcmd_freq(cmd);
+    case 'C':
+      return xcmd_cursor(cmd);
+    case 'D':
+      return xcmd_digit(cmd);
+  }
+
+  return (char *) "ERROR";
+}

 //##############################################################################
 // Code to handle the DigitalVFO menus.
@@ -2180,12 +2490,8 @@
     dds_online();
   }

-  // clear row 1 and write new mode string
-  lcd.setCursor(0, 1);
-  lcd.write(BlankRow);
-  lcd.setCursor(0, 1);
-  lcd.write(mode2display(VfoMode));
-// FIXME: if we display something else on bottom row change this code!
+  // update display
+  vfo_display_mode();
 }

 //----------------------------------------
@@ -2235,30 +2541,6 @@
 //----------------------------------------
 // Standard Arduino loop() function.
 //----------------------------------------
-
-char * do_external_cmd(char *cmd, int index)
-{
-  char end_char = cmd[index];
-  static char message[128];
-
-  // ensure everything is uppercase
-  str2upper(cmd);
-
-  // if command too long it's illegal
-  if (end_char != COMMAND_END_CHAR)
-  {
-    strcpy(message, "Ignored illegal command: '");
-    strcat(message, cmd);
-    strcat(message, "'");
-    return message;
-  }
-
-  // process the command
-  strcpy(message, "Would execute '");
-  strcat(message, cmd);
-  strcat(message, "'  command");
-  return message;
-}

 void loop(void)
 {
@@ -2275,7 +2557,7 @@
     if (ch == COMMAND_END_CHAR)   // if end of command, execute it
     {
       CommandBuffer[CommandIndex] = '\0';
-      Serial.printf(F("%s\n"), do_external_cmd(CommandBuffer, CommandIndex-1));
+      Serial.printf(F("%s;\n"), do_external_cmd(CommandBuffer, CommandIndex-1));
       CommandIndex = 0;
     }
   }


Clean up widgets sample

Clean up widgets sample

--- widgets.ino
+++ widgets.ino
@@ -2,14 +2,13 @@
 #include <SPI.h>
 #include <GD2.h>

-static uint16_t value = 15000;
-static char message[41];
+static uint16_t value = 15000;      // every widget is hooked to this value
+static char message[41];            // 40 character text entry field
 static uint16_t options = OPT_FLAT;
 static byte prevkey;

 void setup()
 {
-  Serial.begin(1000000); // JCB
   memset(message, 7, 40);
   GD.begin();
 }
@@ -100,12 +99,5 @@
   GD.BlendFunc(SRC_ALPHA, ZERO);
   GD.cmd_text(149, 146, 18, 0, message);

-  // GD.cmd_button(240 - 100, 136 - 40, 200, 80, 31, 0, "1 UP");
-
-  /*
-  GD.cmd_text(240, 136, 26, OPT_CENTER, "Hello world");
-  GD.cmd_scrollbar(30, 136, 420, 30, 0, 25333, 10000, 65535);
-  GD.cmd_button(240 - 100, 136 - 40, 200, 80, 31, 0, "1 UP");
-  */
   GD.swap();
 }


Progress bar done.

Progress bar done.

--- wip/wip.ino
+++ wip/wip.ino
@@ -12,7 +12,7 @@
 }

 void loop() {
-
+  progressbar(leds, NUM_LEDS, 0, 5, 50, 60);
 }

 void runner(CRGB *leds, int numOfLeds, int red, int green, int blue, int ms) {
@@ -27,4 +27,46 @@
         leds[i].setRGB(0, 0, 0);
         FastLED.show();
     }
+
+    for(i = (numOfLeds - 1); i > 0; i--) {
+
+        leds[i].setRGB(red, green, blue);
+        FastLED.show();
+        delay(ms);
+        leds[i].setRGB(0, 0, 0);
+        FastLED.show();
+    }
 }
+
+void progressbar(CRGB *leds, int numOfLeds, int red, int green, int blue, int ms) {
+
+    int i;
+
+    for(i = 0; i < numOfLeds; i++) {
+
+      leds[i].setRGB(red, green, blue);
+      FastLED.show();
+      delay(ms);
+    }
+
+    for(i = 0; i < numOfLeds; i++) {
+
+      leds[i].setRGB(0, 0, 0);
+      FastLED.show();
+      delay(ms);
+    }
+
+    for(i = numOfLeds; i >= 0; i--) {
+
+      leds[i].setRGB(red, green, blue);
+      FastLED.show();
+      delay(ms);
+    }
+
+    for(i = numOfLeds; i >= 0; i--) {
+
+      leds[i].setRGB(0, 0, 0);
+      FastLED.show();
+      delay(ms);
+    }
+}


speed test

speed test

--- Pianist/Pianist.ino
+++ Pianist/Pianist.ino
@@ -5,6 +5,11 @@
 #define M1 4
 #define E2 6
 #define M2 7
+
+#define DATASIZE 500
+
+int bigdata[DATASIZE];
+//int bigtime[DATASIZE];

 // Calibration sensor
 #define ST 8
@@ -17,9 +22,14 @@

 char buf [20];

-signed int motorSpeed = 0;
-long pos = 0;
-long oldPos = 0;
+int initPos = 0;
+int curPos = 0;
+int stopPos = 0;
+
+long initTime;
+long curTime;
+long nxtTime;
+

 Encoder myEncoder(ENC1, ENC2);
@@ -45,20 +55,67 @@
   Calibrate();
   Serial.println("Done.");

-  pos = 0;
+  GoTo(1000);
+  delay(500);
+  GoTo(1000);
+  delay(500);
+  GoTo(1000);
+  delay(500);
+  GoTo(1000);
+  delay(1000);
+
+  initPos = myEncoder.read();
+  stopPos = initPos + 7000;
+  Serial.println(initPos);
+  delay(500);
+
+  int idx = 0;
+  SetMotorSpeed(250);
+  unsigned int isRunning = 1;
+
+  initTime = micros();

   while(true)
   {
-    GoTo(1000);
-    delay(500);
-    pos = myEncoder.read();
-    Serial.println(pos);
-
-    GoTo(8000);
-    delay(500);
-    pos = myEncoder.read();
-    Serial.println(pos);
+    curTime = micros();
+    curPos = myEncoder.read();
+
+    if (isRunning && (curPos > stopPos))
+    {
+        SetMotorSpeed(0);
+        isRunning = 0;
+    }
+    int deltaX = curPos - initPos;
+    int deltaT = (curTime - initTime) / 100;
+    bigdata[idx] = isRunning << 15 | deltaX;
+//    bigtime[idx] = deltaT;
+
+    idx++;
+    if (idx >= DATASIZE)
+    {
+      break;
+    }
+
+    nxtTime = curTime + 1000;
+
+    while (micros() < nxtTime)
+    {
+      ;
+    }
   }
+
+  Serial.println("Finished");
+
+  for (int i = 0; i < DATASIZE; i++)
+  {
+    isRunning = (bigdata[i] & 0x8000) ? 1 : 0;
+    sprintf(buf, "%d\t%d\t%d", i, isRunning, (bigdata[i] & 0x7FFF)),
+    Serial.println(buf);
+  }
+
+  Serial.println("Done");
+
+  while(true);
 }

 void GoTo(long pos)


- focus group test: ignore double-clicks on the buttons when opening

--- GeheimTuer.ino
+++ GeheimTuer.ino
@@ -228,6 +228,9 @@
 const unsigned long debounceInterval = 2; // shift inputs into debounce register every debounceInterval ms
 unsigned long debounceMillis = 0;

+const unsigned long debounceIgnoreInterval = 100; // ignore buttons for debounceIgnoreInterval*debounceInterval ms
+unsigned long debounceIgnore = 0;
+
 // TODO: use structured profiles
 unsigned long ledMillis = 0;
 const unsigned long ledSolidInterval = 250; // constantly update LED stripe in solid mode
@@ -396,7 +399,12 @@
   if (debounceMillis >= debounceInterval) {
     debounceMillis = 0;

-    debounce(switchTrigger, &swTrigger, &swTriggerDeglitch, &swTriggerDebounce);
+    if (!debounceIgnore) {
+      debounce(switchTrigger, &swTrigger, &swTriggerDeglitch, &swTriggerDebounce);
+    } else {
+      debounceIgnore--;
+    }
+
     debounce(switchFront, &swFront, &swFrontDeglitch, &swFrontDebounce);
     debounce(switchBack, &swBack, &swBackDeglitch, &swBackDebounce);
     debounce(pirPin, &pirTrigger, &pirDeglitch, &pirDebounce);
@@ -468,6 +476,7 @@
         if (swTrigger == LOW) {
           debug(currentMillis, F("Button switch triggered - opening door\r\n"));
           initDrive(backward, accelProfileHigh);
+          debounceIgnore = debounceIgnoreInterval;
           swTrigger = HIGH; // re-arm swTrigger
         } else {
           // maybe someone tried to pull the door open


Corrected left-right; no joystick

Corrected left-right; no joystick

--- Elcano_C2_In_Out/Elcano_C2_In_Out.ino
+++ Elcano_C2_In_Out/Elcano_C2_In_Out.ino
@@ -13,11 +13,9 @@
 #define FALSE 0
 #endif

-#ifdef MEGA
+
 #include <IO_PCB.h>
-#else
-#include <IO_2009.h>
-#endif
+

   const int ManualStop = 0;
   const int CruiseStop = 1;
@@ -42,11 +40,18 @@
 const int FullBrake = 225;  // start with a conservative value; could go as high as 255;
 const int MinimumBrake = 155; // start with a conservative value; could go as low as 127;

-const int HardLeft = 159; // start with a conservative value; could go as low as 127;
-const int HalfLeft = 159;
+const int HardLeft = 223; // was 159; // start with a conservative value; could go as high as 255;
+const int HalfLeft = 223; // was 159;
 const int Straight = 191;
-const int HalfRight = 223;
-const int HardRight = 223; // start with a conservative value; could go as high as  255;
+const int HalfRight = 159; // was 223;
+const int HardRight = 159; // was 223; // start with a conservative value; could go as low as 127;
+const int StraightFB = 501;
+const int HalfRightFB = 303;
+const int HalfLeftFB = 760;
+/* There is hysteresis on steering.
+  E.g. Move to the left until PWM 223, getting FB of 760.
+  If moves to the right are then commanded, feedback will not change until PWM of about 217.
+*/
 /*  Elcano Servo range is 50 mm for brake, 100 mm for steering.

     Elcano servo has a hardware controller that moves to a
@@ -165,7 +170,6 @@
         pinMode(CruiseThrottle, INPUT);
         pinMode(CruiseBrake, INPUT);
         pinMode(CruiseSteer, INPUT);
-#ifdef MEGA
         pinMode(Current36V, INPUT);
         pinMode(CurrentBrake, INPUT);
         pinMode(CurrentSteer, INPUT);
@@ -177,12 +181,19 @@
         pinMode(LED7, OUTPUT);
         pinMode(LED8, OUTPUT);
         Serial.begin(9600);
-#endif
+
         initialize();

         CalibrateBrakes();

-//        CalibrateSteering();
+       CalibrateSteering(HardRight,3);
+       CalibrateSteering(HardLeft,3);
+       delay(10000);
+       CalibrateSteering(HardRight,1);
+       CalibrateSteering(HardLeft,1);
+       delay(10000);
+       CalibrateSteering(HardRight,10);
+
 }

 /*---------------------------------------------------------------------------------------*/
@@ -229,30 +240,9 @@
        delay(900);   // hold each brake position 1 second.
      }
 }
-/*---------------------------------------------------------------------------------------*/
-void CalibrateSteering()
-{
-  // This routine establishes the correct values for HardLeft, HardRight, Straight, etc.
-  // Verify that the values for left are those that turn the vehicle to the let.
-  // It allows us to establish the constants to map the feedback to the commanded position.
-
-  // PWM signal is only effective from 127 to 255.
-  // Some of the extreme values produce no motion in an unattached servo.
-  // When the servo is atached to the steering link, pushing too hard can draw too much power and blow a fuse.
-
-  // Perform this test first with an unattached servo.
-  // Repeat with an attached servo.
-
- // It would be a good idea to put an ammeter on the steering servo to verify that excess current is not being drawn;
- // In case current gets too high, abort by unplugging the servo.
-  // Use the serial monitor, and save the results for analysis.
-
-  // Mechanically position the steering link so that servo motion half-way between extremes is straight ahead.
-
+void moveSteer(int i)
+{
        int feedbacks[5];
-       Serial.println("Calibrate steering");
-       for (int i = HardLeft; i < HardRight; i += 10)
-     {
        analogWrite(Steer, i);
 //       int current =  analogRead(CurrentBrake);
        delay(95);  // allow tiime for steer to respond
@@ -270,8 +260,49 @@
        Serial.print(i); Serial.print(", ");
 //       Serial.print(current); Serial.print(", ");
        Serial.println(feedback);
-       delay(900);   // hold each brake position 1 second.
-     }
+       delay(900);   // hold each steer position 1 second.
+
+}
+/*---------------------------------------------------------------------------------------*/
+void CalibrateSteering(int SteerPosition, int delta)
+{
+  // This routine establishes the correct values for HardLeft, HardRight, Straight, etc.
+  // Verify that the values for left are those that turn the vehicle to the let.
+  // It allows us to establish the constants to map the feedback to the commanded position.
+
+  // PWM signal is only effective from 127 to 255.
+  // Some of the extreme values produce no motion in an unattached servo.
+  // When the servo is atached to the steering link, pushing too hard can draw too much power and blow a fuse.
+
+  // Perform this test first with an unattached servo.
+  // Repeat with an attached servo.
+
+ // It would be a good idea to put an ammeter on the steering servo to verify that excess current is not being drawn;
+ // In case current gets too high, abort by unplugging the servo.
+  // Use the serial monitor, and save the results for analysis.
+
+  // Mechanically position the steering link so that servo motion half-way between extremes is straight ahead.
+
+       delta = abs(delta);
+       int i;
+       Serial.println("Calibrate steering");
+       if (SteerPosition >= Straight)
+       {
+         for (i = Straight; i <= SteerPosition; i += delta)
+             moveSteer(i);
+         for (i = SteerPosition; i >= Straight; i -= delta)
+             moveSteer(i);
+       }
+       else
+      {
+         for (i = Straight; i >= SteerPosition; i -= delta)
+             moveSteer(i);
+         for (i = SteerPosition; i <= Straight; i += delta)
+             moveSteer(i);
+
+       }
+      moveSteer(Straight);
+
 }
 int compareint (const void * a, const void * b)
 {
@@ -319,7 +350,7 @@
         Instrument[Steering].CloseEnough = 1;
         Instrument[Steering].Stuck = 3;
         Instrument[Steering].MinPosition = 85;  // anolog read range is 0 to 1023
-        Instrument[Steering].MaxPosition = 800;
+        Instrument[Steering].MaxPosition = 900;

         Instrument[Brakes].EnablePin = EnableBrake;
         Instrument[Brakes].SignalPin = DiskBrake;
@@ -396,16 +427,19 @@
   unsigned long NextLoopTime_ms = TimeNow + STEP_SIZE_ms;
   static unsigned long EndTime = 0;
   static unsigned long OutsideTime;
+  int center;
+
+  return;

   OutsideTime = EndTime - TimeNow;
   Instrument[Motor].Enabled = digitalRead(EnableThrottle);
   Instrument[Brakes].Enabled = digitalRead(EnableBrake);
   Instrument[Steering].Enabled = digitalRead(EnableSteer);
-#ifdef TEST_MODE
-    ServoData();
+
+   // ServoData();

-#else  // not TEST_MODE
-#endif  // TEST_MODE
+
+
  // TODO: Check out loop speed;
  // make loop faster
  // limit servo motion during loop to step size


summary editing

summary editing

--- KillSwitchduino/KillSwitchduino.ino
+++ KillSwitchduino/KillSwitchduino.ino
@@ -13,6 +13,8 @@
  * a) RX signal calibrating procedure
  * b) Engine stopping if no RX signal
  * c) RX battery chemistry type select(LiPO, LiFE) for correct battery protecting
+ * d) reset to Defaults
+ * e) exit to normal mode
  */


Removing some String(F("asdf")) because the 1.0.X compiler doesn't like it.

Since the raspberryPi only have a 1.0.x version of the arduino ide it
cannot compile with String(F("asdf")) .

--- LightController/LightController.ino
+++ LightController/LightController.ino
@@ -320,11 +320,11 @@
     char* command  = root["command"];
     Serial.print(F("Got command: "));
     Serial.println(command);
-    if (String(F("0")).equalsIgnoreCase(command)) {
+    if (String("0").equalsIgnoreCase(command)) {
       processCommand(root["lightData"]);
-    } else if (String(F("1")).equalsIgnoreCase(command)) {
+    } else if (String("1").equalsIgnoreCase(command)) {
       processArrayOfCommands(root);
-    } else if (String(F("2")).equalsIgnoreCase(command)) {
+    } else if (String("2").equalsIgnoreCase(command)) {
       allOffFade(root["delay"]);
     } else {
       Serial.print(F("Unknown Command: "));


holy jeezus it compiles on AVR

holy jeezus it compiles on AVR

vectors are done :)

--- Software/Fiduino/Fiduino.ino
+++ Software/Fiduino/Fiduino.ino
@@ -1,9 +1,8 @@
-#include <stdlib.h>
-
+#include "newVector.h"

 void setup() {
   pinMode(13,OUTPUT);
-
+  Vector<int> vect;
 }

 void loop() {


code for readout and sending LDR data added, not yet tested

--- TreibBoje1.ino
+++ TreibBoje1.ino
@@ -14,12 +14,17 @@
 #define READ_SENSORS
 // send the data via 433MHZ Tx
 #define SEND_DATA
+// read photo resistor (LDR)
+#define USE_LDR

 #ifdef DEBUG
  // http://arduiniana.org/libraries/streaming/
  // has to be included BEFORE Flash
  #include <Streaming.h>
  #include <Flash.h>
+
+ // UART baud rate
+ #define UART_BAUD_RATE  9600
 #endif // DEBUG

 #ifdef SEND_DATA
@@ -45,14 +50,16 @@
 #include <DallasTemperature.h>

 #ifdef SEND_DATA
-
-#define TX_PIN     10
+ #define TX_PIN     10
+
 RCSwitch theSender = RCSwitch();

 #endif // SEND_DATA

-// UART baud rate
-#define UART_BAUD_RATE  9600
+#ifdef USE_LDR
+ // define a pin for Photo resistor (ADC input!)
+ #define LDR_PIN     0
+#endif // USE_LDR

 // Data wire is plugged into port 2 on the Arduino
 #define ONE_WIRE_BUS 2
@@ -141,6 +148,15 @@
     }
   }
 #endif // SCAN_SENSORS
+
+#ifdef USE_LDR
+  //           PhotoR     10K
+  // +5    o---/\/\/--.--/\/\/---o GND
+  //                  |
+  // Pin 0 o----------+
+  //
+  pinMode( LDR_PIN, INPUT );
+#endif // USE_LDR
 }

 int getRawTemperature(float temp,int precision=12) {
@@ -175,6 +191,7 @@
 //
 #ifdef SEND_DATA
  #define SEND_SYNC(_x) theSender.send((_x & 0x1ff) | 0x0e00, 12)
+ #define SEND_LDR(_x) theSender.send((_x & 0x1ff), 12)
  #define SEND_T1(_x) theSender.send((_x & 0x1ff) | (0x0100 << 1), 12)
  #define SEND_T2(_x) theSender.send((_x & 0x1ff) | (0x0200 << 1), 12)
  #define SEND_T3(_x) theSender.send((_x & 0x1ff) | (0x0300 << 1), 12)
@@ -182,6 +199,7 @@
  #define SEND_T5(_x) theSender.send((_x & 0x1ff) | (0x0500 << 1), 12)
 #else
  #define SEND_SYNC(_x) {}
+ #define SEND_LDR(_x) {}
  #define SEND_T1(_x) {}
  #define SEND_T2(_x) {}
  #define SEND_T3(_x) {}
@@ -263,6 +281,18 @@
   } // if ( getDeviceCount() > 0 )
 #endif // READ_SENSORS

+#ifdef USE_LDR
+  // divide the resulting value:
+  // - with a 10k resistor divide the value by 2
+  // - for 100k resistor divide by 4.
+  // - this is a 10bit (0..1023) ADC
+  int ldr_value = analogRead(LDR_PIN)/4;
+#ifdef DEBUG
+  Serial << "LDR: " << ldr_value << endl;
+#endif // DEBUG
+  SEND_LDR(ldr_value);
+#endif // USE_LDR
+
   SEND_SYNC(2);
 }


Improving base-line measurements.

Improving base-line measurements.

--- examples/Benchmarks/CosaBenchmarkRTC/CosaBenchmarkRTC.ino
+++ examples/Benchmarks/CosaBenchmarkRTC/CosaBenchmarkRTC.ino
@@ -58,18 +58,19 @@
   // Measure baseline
   RTC::begin();
   start = RTC::micros();
+  uint32_t us = RTC::micros();
   stop = RTC::micros();
   INFO("RTC::micros(): %ul", stop - start);
-
+
   start = RTC::micros();
   uint32_t ms = RTC::millis();
   stop = RTC::micros();
   INFO("RTC::millis(): %ul", stop - start);

   start = RTC::micros();
-  DELAY(1);
+  DELAY(10);
   stop = RTC::micros();
-  INFO("DELAY(1): %ul", stop - start);
+  INFO("DELAY(10): %ul", stop - start);

   // Measure and validate micro-second level
   err = 0;


Clean up HTML & Styling

Clean up HTML & Styling

--- sketches/WHID_and_Cactus_micro_rev2_sketches/ESP_Sketch/ESP_Sketch.ino
+++ sketches/WHID_and_Cactus_micro_rev2_sketches/ESP_Sketch/ESP_Sketch.ino
@@ -32,6 +32,9 @@
 File fsUploadFile;
 String webString;

+const String HTML_CSS_STYLING = "";
+const String HTML_BACK_TO_INDEX = "<- BACK TO INDEX

";
+
 void handleFileUpload()
 {
   if(server.uri() != "/upload") return;
@@ -53,13 +56,13 @@
 }

 void ListPayloads(){
-  String FileList = "<- BACK TO INDEX

<h style=\"color: #00ff00;\">Choose Payload:</h>

";
+  String FileList = HTML_CSS_STYLING + HTML_BACK_TO_INDEX + "<h>Choose Payload:</h>

";
   Dir dir = SPIFFS.openDir("/payloads");
   while (dir.next()) {
     String FileName = dir.fileName();
     File f = dir.openFile("r");
     FileList += " ";
-    FileList += ""+FileName+""+"
";
+    FileList += ""+FileName+""+"
";
   }
   server.send(200, "text/html", FileList);
 }
@@ -81,20 +84,20 @@
   }

   server.on("/", [](){
-    server.send(200, "text/html", "<img class=\'moveimage\' src=\'data:image/png;base64,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\' />
WHID Injector

WiFi HID Injector for Fun & Profit

-----------------------------------------------
Upload Payload
-
Choose Payload
-
Format File System
-----------------------------------------------
");
+    server.send(200, "text/html", HTML_CSS_STYLING + "<img class=\'moveimage\' src=\'data:image/png;base64,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\' />
WHID Injector

WiFi HID Injector for Fun & Profit

-----------------------------------------------
Upload Payload

Choose Payload

Format File System
-----------------------------------------------
");
   });

   server.on("/format", [](){
-    server.send(200, "text/html", "
This will reformat the SPIFFS File System.

You will delete all Payloads! Are you sure?

YES - NO");
+    server.send(200, "text/html", HTML_CSS_STYLING + HTML_BACK_TO_INDEX + "
This will reformat the SPIFFS File System.

You will delete all Payloads! Are you sure?

YES - NO");
   });

   server.on("/format/yes", [](){
-    server.send(200, "text/html", "<- BACK TO INDEX

Formatting file system: This may take up to 90 seconds
");
+    server.send(200, "text/html", HTML_CSS_STYLING + HTML_BACK_TO_INDEX + "
Formatting file system: This may take up to 90 seconds
");
     SPIFFS.format();
   });

   server.on("/uploadpayload", []() {
-    server.send(200, "text/html", "<- BACK TO INDEX

Upload Payload:

<form method='POST' action='/upload' enctype='multipart/form-data'><input type='file' name='upload'><input type='submit' value='Upload'></form>");
+    server.send(200, "text/html", HTML_CSS_STYLING + HTML_BACK_TO_INDEX + "
Upload Payload:

<form method='POST' action='/upload' enctype='multipart/form-data'><input type='file' name='upload'><input type='submit' value='Upload'></form>");
   });

   server.on("/listpayloads", ListPayloads);
@@ -102,7 +105,7 @@
   server.onFileUpload(handleFileUpload);

   server.on("/upload", HTTP_POST, []() {
-    server.send(200, "text/html", "<- BACK TO INDEX

Upload Successful!

List Payloads");
+    server.send(200, "text/html", HTML_CSS_STYLING + HTML_BACK_TO_INDEX + "
Upload Successful!

List Payloads");
   });

   server.on("/showpayload", [](){
@@ -112,14 +115,14 @@
     File f = SPIFFS.open(payload, "r");
     String webString = f.readString();
     f.close();
-    server.send(200, "text/html", "<- BACK TO INDEX

<button>Run Payload</button>

"+payload+"\n-----\n"+webString+"

");
+    server.send(200, "text/html", HTML_CSS_STYLING + HTML_BACK_TO_INDEX + "<button>Run Payload</button>

"+payload+"\n-----\n"+webString+"

");
     webString="";
   });

   server.on("/dopayload", [](){
     String dopayload;
     dopayload += server.arg(0);
-    server.send(200, "text/html", "<- BACK TO INDEX

Running payload: "+dopayload+"

This may take a while to complete...
");
+    server.send(200, "text/html", HTML_CSS_STYLING + HTML_BACK_TO_INDEX + "

Running payload: "+dopayload+"

This may take a while to complete...
");
     File f = SPIFFS.open(dopayload, "r");
     while(f.available()) {
       String line = f.readStringUntil('\n');


Version 1.5a 2nd March 2017

Version 1.5a 2nd March 2017

Fixes a problem affecting save-image/load-image.

--- ulisp.ino
+++ ulisp.ino
@@ -1,5 +1,5 @@
-/* uLisp Version 1.5 - www.ulisp.com
-   David Johnson-Davies - www.technoblogy.com - 24th January 2017
+/* uLisp Version 1.5a - www.ulisp.com
+   David Johnson-Davies - www.technoblogy.com - 2nd March 2017

    Licensed under the MIT license: https://opensource.org/licenses/MIT
 */
@@ -50,7 +50,7 @@
 const int EEPROMsize = E2END;

 const int buflen = 17;  // Length of longest symbol + 1
-enum type {ZERO, SYMBOL, NUMBER, STRING, STREAM, PAIR };  // PAIR must be last
+enum type {ZERO, SYMBOL, NUMBER, STREAM, STRING, PAIR };  // STRING and PAIR must be last
 enum token { UNUSED, BRA, KET, QUO, DOT };
 enum stream { SERIALSTREAM, I2CSTREAM, SPISTREAM };

@@ -241,7 +241,7 @@
   unsigned int eval;
   unsigned int datasize;
   unsigned int globalenv;
-  unsigned int tee;
+  unsigned int gcstack;
   char data[];
 } struct_image;

@@ -251,7 +251,7 @@
   for (int i=0; i<workspacesize; i++) {
     object *obj = &workspace[i];
     int type = (obj->type) & 0x7FFF;
-    if (marked(obj) && type >= PAIR) {
+    if (marked(obj) && (type >= STRING || type==ZERO)) {
       if (car(obj) == (object *)((unsigned int)from | 0x8000))
         car(obj) = (object *)((unsigned int)to | 0x8000);
       if (cdr(obj) == from) cdr(obj) = to;
@@ -275,7 +275,6 @@
       movepointer(obj, firstfree);
       if (GlobalEnv == obj) GlobalEnv = firstfree;
       if (GCStack == obj) GCStack = firstfree;
-      if (tee == obj) tee = firstfree;
       if (*arg == obj) *arg = firstfree;
       while (marked(firstfree)) firstfree++;
     }
@@ -296,7 +295,7 @@
   eeprom_write_word(&image.datasize, imagesize);
   eeprom_write_word(&image.eval, (unsigned int)arg);
   eeprom_write_word(&image.globalenv, (unsigned int)GlobalEnv);
-  eeprom_write_word(&image.tee, (unsigned int)tee);
+  eeprom_write_word(&image.gcstack, (unsigned int)GCStack);
   eeprom_write_block(workspace, image.data, imagesize*4);
   return imagesize+2;
 }
@@ -305,7 +304,7 @@
   unsigned int imagesize = eeprom_read_word(&image.datasize);
   if (imagesize == 0 || imagesize == 0xFFFF) error(F("No saved image"));
   GlobalEnv = (object *)eeprom_read_word(&image.globalenv);
-  tee = (object *)eeprom_read_word(&image.tee) ;
+  GCStack = (object *)eeprom_read_word(&image.gcstack);
   eeprom_read_block(workspace, image.data, imagesize*4);
   gc(NULL, NULL);
   return imagesize+2;
@@ -2519,7 +2518,7 @@
   initworkspace();
   initenv();
   _end = 0xA5;      // Canary to check stack
-  pfstring(F("uLisp 1.5")); pln();
+  pfstring(F("uLisp 1.5a")); pln();
 }

 // Read/Evaluate/Print loop


Update ArduCAM_Mini_LowPowerMode.ino

Update ArduCAM_Mini_LowPowerMode.ino

--- ArduCAM/examples/mini/ArduCAM_Mini_LowPowerMode/ArduCAM_Mini_LowPowerMode.ino
+++ ArduCAM/examples/mini/ArduCAM_Mini_LowPowerMode/ArduCAM_Mini_LowPowerMode.ino
@@ -39,7 +39,7 @@
   Wire.begin();
   Serial.begin(921600);
 #endif
-Serial.println(F("ACK CMD ArduCAM Start!"));
+Serial.println(F("ACK CMD ArduCAM Start! END"));
 // set the SPI_CS as an output:
 pinMode(SPI_CS, OUTPUT);
 // initialize SPI:
@@ -49,10 +49,10 @@
   myCAM.write_reg(ARDUCHIP_TEST1, 0x55);
   temp = myCAM.read_reg(ARDUCHIP_TEST1);
   if (temp != 0x55){
-    Serial.println(F("ACK CMD SPI interface Error!"));
+    Serial.println(F("ACK CMD SPI interface Error! END"));
     delay(1000);continue;
   }else{
-    Serial.println(F("ACK CMD SPI interface OK."));break;
+    Serial.println(F("ACK CMD SPI interface OK. END"));break;
   }
 }
 #if defined (OV2640_MINI_2MP)
@@ -62,11 +62,11 @@
     myCAM.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
     myCAM.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
     if ((vid != 0x26 ) && (( pid != 0x41 ) || ( pid != 0x42 ))){
-      Serial.println(F("ACK CMD Can't find OV2640 module!"));
+      Serial.println(F("ACK CMD Can't find OV2640 module! END"));
       delay(1000);continue;
     }
     else{
-      Serial.println(F("ACK CMD OV2640 detected."));break;
+      Serial.println(F("ACK CMD OV2640 detected. END"));break;
     }
   }
 #elif defined (OV3640_MINI_3MP)
@@ -75,10 +75,10 @@
     myCAM.rdSensorReg16_8(OV3640_CHIPID_HIGH, &vid);
     myCAM.rdSensorReg16_8(OV3640_CHIPID_LOW, &pid);
     if ((vid != 0x36) || (pid != 0x4C)){
-      Serial.println(F("Can't find OV3640 module!"));
+      Serial.println(F("ACK CMD Can't find OV3640 module! END"));
       delay(1000);continue;
     }else{
-      Serial.println(F("OV3640 detected."));break;
+      Serial.println(F("ACK CMD OV3640 detected. END"));break;
     }
  }
 #else
@@ -88,11 +88,11 @@
     myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid);
     myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid);
     if((vid != 0x56) || (pid != 0x42)){
-      Serial.println(F("ACK CMD Can't find OV5642 module!"));
+      Serial.println(F("ACK CMD Can't find OV5642 module! END"));
       delay(1000);continue;
     }
     else{
-     Serial.println(F("ACK CMD OV5642 detected."));break;
+     Serial.println(F("ACK CMD OV5642 detected. END"));break;
     }
   }
 #endif
@@ -125,13 +125,13 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_160x120);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_160x120"));
+    Serial.println(F("ACK CMD switch to OV2640_160x120 END"));
  #elif defined (OV3640_MINI_3MP)
     myCAM.OV3640_set_JPEG_size(OV3640_176x144);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_160x120"));
+    Serial.println(F("ACK CMD switch to OV2640_160x120 END"));
   #else
     myCAM.OV5642_set_JPEG_size(OV5642_320x240);delay(1000);
-    Serial.println(F("ACK CMD switch to OV5642_320x240"));
+    Serial.println(F("ACK CMD switch to OV5642_320x240 END"));
   #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -140,13 +140,13 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_176x144);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_176x144"));
+    Serial.println(F("ACK CMD switch to OV2640_176x144 END"));
   #elif defined (OV3640_MINI_3MP)
       myCAM.OV3640_set_JPEG_size(OV3640_320x240);delay(1000);
-      Serial.println(F("ACK CMD switch to OV3640_320x240"));
+      Serial.println(F("ACK CMD switch to OV3640_320x240 END"));
   #else
     myCAM.OV5642_set_JPEG_size(OV5642_640x480);delay(1000);
-    Serial.println(F("ACK CMD switch to OV5642_640x480"));
+    Serial.println(F("ACK CMD switch to OV5642_640x480 END"));
   #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -156,13 +156,13 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_320x240);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_320x240"));
+    Serial.println(F("ACK CMD switch to OV2640_320x240 END"));
   #elif defined (OV3640_MINI_3MP)
       myCAM.OV3640_set_JPEG_size(OV3640_352x288);delay(1000);
-      Serial.println(F("ACK CMD switch to OV3640_352x288"));
+      Serial.println(F("ACK CMD switch to OV3640_352x288 END"));
   #else
     myCAM.OV5642_set_JPEG_size(OV5642_1024x768);delay(1000);
-    Serial.println(F("ACK CMD switch to OV5642_1024x768"));
+    Serial.println(F("ACK CMD switch to OV5642_1024x768 END"));
   #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -172,13 +172,13 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_352x288);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_352x288"));
+    Serial.println(F("ACK CMD switch to OV2640_352x288 END"));
   #elif defined (OV3640_MINI_3MP)
       myCAM.OV3640_set_JPEG_size(OV3640_640x480);delay(1000);
-      Serial.println(F("ACK CMD switch to OV3640_640x480"));
+      Serial.println(F("ACK CMD switch to OV3640_640x480 END"));
   #else
     myCAM.OV5642_set_JPEG_size(OV5642_1280x960);delay(1000);
-    Serial.println(F("ACK CMD switch to OV5642_1280x960"));
+    Serial.println(F("ACK CMD switch to OV5642_1280x960 END"));
   #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -188,13 +188,13 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_640x480);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_640x480"));
+    Serial.println(F("ACK CMD switch to OV2640_640x480 END"));
  #elif defined (OV3640_MINI_3MP)
       myCAM.OV3640_set_JPEG_size(OV3640_800x600);delay(1000);
-      Serial.println(F("ACK CMD switch to OV3640_800x600"));
+      Serial.println(F("ACK CMD switch to OV3640_800x600 END"));
   #else
     myCAM.OV5642_set_JPEG_size(OV5642_1600x1200);delay(1000);
-    Serial.println(F("ACK CMD switch to OV5642_1600x1200"));
+    Serial.println(F("ACK CMD switch to OV5642_1600x1200 END"));
   #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -203,13 +203,13 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_800x600);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_800x600"));
+    Serial.println(F("ACK CMD switch to OV2640_800x600 END"));
  #elif defined (OV3640_MINI_3MP)
       myCAM.OV3640_set_JPEG_size(OV3640_1024x768);delay(1000);
-      Serial.println(F("ACK CMD switch to OV3640_1024x768"));
+      Serial.println(F("ACK CMD switch to OV3640_1024x768 END"));
   #else
     myCAM.OV5642_set_JPEG_size(OV5642_2048x1536);delay(1000);
-    Serial.println(F("ACK CMD switch to OV5642_2048x1536"));
+    Serial.println(F("ACK CMD switch to OV5642_2048x1536 END"));
   #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -219,13 +219,13 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_1024x768);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_1024x768"));
+    Serial.println(F("ACK CMD switch to OV2640_1024x768 END"));
  #elif defined (OV3640_MINI_3MP)
     myCAM.OV3640_set_JPEG_size(OV3640_1280x960);delay(1000);
-    Serial.println(F("ACK CMD switch to OV3640_1280x960"));
+    Serial.println(F("ACK CMD switch to OV3640_1280x960 END"));
   #else
     myCAM.OV5642_set_JPEG_size(OV5642_2592x1944);delay(1000);
-    Serial.println(F("ACK CMD switch to OV5642_2592x1944"));
+    Serial.println(F("ACK CMD switch to OV5642_2592x1944 END"));
   #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -234,10 +234,10 @@
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   #if defined (OV2640_MINI_2MP)
     myCAM.OV2640_set_JPEG_size(OV2640_1280x1024);delay(1000);
-    Serial.println(F("ACK CMD switch to OV2640_1280x1024"));
+    Serial.println(F("ACK CMD switch to OV2640_1280x1024 END"));
   #else
     myCAM.OV3640_set_JPEG_size(OV3640_1600x1200);delay(1000);
-    Serial.println(F("ACK CMD switch to OV3640_1600x1200"));
+    Serial.println(F("ACK CMD switch to OV3640_1600x1200 END"));
    #endif
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
@@ -248,14 +248,14 @@
      Serial.println(F("ACK CMD switch to OV2640_1600x1200"));
    #else
      myCAM.OV3640_set_JPEG_size(OV3640_2048x1536);delay(1000);
-     Serial.println(F("ACK CMD switch to OV3640_2048x1536"));
+     Serial.println(F("ACK CMD switch to OV3640_2048x1536 END"));
    #endif
    myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   break;
   case 0x10:
   temp = 0xff;
   start_capture = 1;
-  Serial.println(F("ACK CMD CAM start single shot."));
+  Serial.println(F("ACK CMD CAM start single shot. END"));
   myCAM.clear_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
   delay(800);
   break;
@@ -273,9 +273,9 @@
 if(myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK))
 {
   myCAM.set_bit(ARDUCHIP_GPIO,GPIO_PWDN_MASK);
-  Serial.println(F("ACK CMD CAM Capture Done."));
+  Serial.println(F("ACK CMD CAM Capture Done. END"));delay(50);
   temp = 0;
-  Serial.println(F("ACK IMG"));
+  Serial.println(F("ACK IMG  END"));
   while( (temp != 0xD9) | (temp_last != 0xFF) )
   {
     temp_last = temp;


Improve MCP23008 example sketch; allow configuration of I2C frequency.

1. Measurements for 100 and 444 KHz.

--- libraries/MCP23008/examples/CosaMCP23008/CosaMCP23008.ino
+++ libraries/MCP23008/examples/CosaMCP23008/CosaMCP23008.ino
@@ -17,12 +17,12 @@
  *
  * @section Description
  * Cosa MCP23008 Remote 8-bit I/O expander driver example. Includes
- * benchmarking of read/write of port and pins;
- *  1. read pin, 472 us
- *  2. read pin (cached address), 236 us
- *  3. write pin, 340 us
- *  4. pulse pin, 676 us
- *  5. pulse pin (sequence), 226 us
+ * benchmarking of read/write of port and pins (100/444 KHz);
+ *  1. read pin, 472(164) us
+ *  2. read pin (cached address), 236(84) us
+ *  3. write pin, 340(120) us
+ *  4. pulse pin (dual write), 676(234) us
+ *  5. pulse pin (write sequence), 226(66) us
  *
  * @section Circuit
  * @code
@@ -52,6 +52,9 @@
 #include "Cosa/IOStream/Driver/UART.hh"
 #include "Cosa/Memory.h"

+// Use TWI at max frequency (444 KHz @ 16 MHz)
+#define USE_MAX_FREQ
+
 // MCP23008 Remote 8-bit I/O expander with sub-address(0x0)
 MCP23008 port(0);

@@ -74,6 +77,11 @@
   // Start the watchdog ticks and RTC
   Watchdog::begin();
   RTC::begin();
+
+#if defined(USE_MAX_FREQ)
+  // Set max frequency
+  twi.set_freq(TWI::MAX_FREQ);
+#endif

   // Start the MCP23008 device driver
   port.begin();


Update delay time for arduino button read

--- arduino_code/arduino_code.ino
+++ arduino_code/arduino_code.ino
@@ -13,6 +13,9 @@

   if (buttonState == HIGH) {
     Serial.println(randNum);
+    while(buttonState) {
+      buttonState = digitalRead(buttonPin);
+    }
   }
-  delay(500);
+  delay(50);
 }


Updated pachubeClientStirng to fix  posting interval bug

--- libraries/Ethernet/examples/PachubeClientString/PachubeClientString.ino
+++ libraries/Ethernet/examples/PachubeClientString/PachubeClientString.ino
@@ -47,7 +47,7 @@

 long lastConnectionTime = 0;        // last time you connected to the server, in milliseconds
 boolean lastConnected = false;      // state of the connection last time through the main loop
-const int postingInterval = 10000;  //delay between updates to Pachube.com
+const unsigned long postingInterval = 10000;  //delay between updates to Pachube.com

 void setup() {
   // start serial port:


Update Arduino trigger points

Update Arduino trigger points

--- sous_vide_arduino/sous_vide_arduino.ino
+++ sous_vide_arduino/sous_vide_arduino.ino
@@ -50,11 +50,11 @@
         Bean.setLed(0, 255, 0);

         // Turn heater on or off based on current temperature
-        if (currentTempF <= targetTempF + 1) {
-            // Turn on heater when currentTempF is less than 2 degrees above targetTempF
+        if (currentTempF < targetTempF) {
+            // Turn on heater when currentTempF is less than targetTempF
             heating = 1;
         } else {
-            // Turn off heater when currentTempF is 2+ degrees above targetTempF
+            // Turn off heater when currentTempF is equal to or greater than targetTempF
             heating = 0;
         }


Stop browsers from requesting favicon.ico. Make stop cards work more solid. Increased logging when creating a folder

--- RfidShelf/RfidShelf.ino
+++ RfidShelf/RfidShelf.ino
@@ -216,10 +216,18 @@
       lastCardUid[i] = mfrc522.uid.uidByte[i];
     }

-    if (switchFolder(readFolder)) {
+
+
+    if(readFolder[1] == '\0') {
+      Serial.println(F("Stopping playback"));
       stopMp3();
       yield();
-      playMp3();
+    } else {
+      if (switchFolder(readFolder)) {
+        stopMp3();
+        yield();
+        playMp3();
+      }
     }
   }

@@ -418,7 +426,7 @@
       "function writeRfid(url){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { location.reload(); }}; xhr.open('POST', url); var formData = new FormData(); formData.append('write', 1); xhr.send(formData);}"
       "function mkdir() { var folder = document.getElementById('folder'); if(folder != ''){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { location.reload(); }}; xhr.open('POST', '/'); var formData = new FormData(); formData.append('folder', folder.value); xhr.send(formData);}}"
       "function ota() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === 4) { document.write('Please wait and do NOT turn of the power!'); location.reload(); }}; xhr.open('POST', '/'); var formData = new FormData(); formData.append('ota', 1); xhr.send(formData);}"
-      "</script>"));
+      "</script><link rel=\"icon\" href=\"data:;base64,iVBORw0KGgo=\">"));

   String output;
   if (path == "/") {
@@ -584,7 +592,9 @@
     return;
   } else if (server.method() == HTTP_POST) {
     if (server.hasArg("folder")) {
-      Serial.println(F("Creating folder"));
+      Serial.print(F("Creating folder"));
+      Serial.print(F(" "));
+      Serial.println(server.arg("folder"));
       SD.mkdir((char *)server.arg("folder").c_str());
       returnOK();
       return;


Don't forget to assign the action for each of the placeholder entries

--- RoverMain/RoverMain.ino
+++ RoverMain/RoverMain.ino
@@ -183,6 +183,7 @@
 		for (int recno = 0; recno < 16; recno++) {
 			actionScore.score = 128; // set it in the middle for +- adjustment
 			actionScore.id = (byte) recno;
+			actionScore.action = (byte)recno;
 			switch (recno) {
 				case B0000:
 				case B0011:


Suppress LED's code to simplify this example

--- bottleopener/bottleopener.ino
+++ bottleopener/bottleopener.ino
@@ -7,18 +7,12 @@
 ShiftrConnector shiftrConnector;

 #define PIN_BUTTON    7
-#define PIN_LED_KO    12
-#define PIN_LED_OK    13

 //Global counter for this bottle opener
 int counter = 0;

 void setup() {
-  pinMode(PIN_LED_KO, OUTPUT);
-  pinMode(PIN_LED_OK, OUTPUT);
   pinMode(PIN_BUTTON, INPUT);
-
-  _setKO();

   //setup the bridge and serial
   Bridge.begin(); //Yun Bridge
@@ -31,7 +25,6 @@

   //Everything seems to be ok, let's start !
   Serial.println("Bottle Opener Up !!!");
-  _setOK();
 }

 /**
@@ -104,19 +97,3 @@
   lastButtonState = reading;
   return retVal;
 }
-
-/**
-   Lightup the blue led
-*/
-void _setOK() {
-  digitalWrite(PIN_LED_KO, LOW);
-  digitalWrite(PIN_LED_OK, HIGH);
-}
-
-/**
-   Light up the red led
-*/
-void _setKO() {
-  digitalWrite(PIN_LED_OK, LOW);
-  digitalWrite(PIN_LED_KO, HIGH);
-}


Fixed: comment

Fixed: comment

--- attwlight_sensor/attwlight_sensor.ino
+++ attwlight_sensor/attwlight_sensor.ino
@@ -131,7 +131,7 @@
 {
   GIMSK = _BV(PCIE); // Включить Pin Change прерывания
   if (SLEEP_PERIOD == WDTO_INFINITE || payload.light != LIGHT_FUZZY)
-    PCMSK |= _BV(LIGHT_PIN); // PCINT3; включить если нет проблем с освещением и есть шанс проснуться
+    PCMSK |= _BV(LIGHT_PIN); // PCINT3; включить если нет проблем с освещением или иначе нет шансов проснуться
   ADCSRA &= ~_BV(ADEN); // отключить ADC; уменьшает энергопотребление

   if (SLEEP_PERIOD != WDTO_INFINITE) {


add single stepping

add single stepping

--- src/monitor-firmware.ino
+++ src/monitor-firmware.ino
@@ -32,6 +32,7 @@

 // Should we cycle the processor?
 bool cycle_request;
+bool skip_to_next_sync;

 DebouncedSwitch mode_switch(BTN_MODE);
 DebouncedSwitch select_switch(BTN_SELECT);
@@ -125,6 +126,9 @@
         Serial.println(halt_request ? "on" : "off");
     } else if(cmd_buf[0] == 'c') {
         cycle_request = true;
+    } else if(cmd_buf[0] == 's') {
+        cycle_request = true;
+        skip_to_next_sync = true;
     } else {
         Serial.println("unknown cmd");
         printHelp();
@@ -174,6 +178,7 @@
     // Processor is in running state
     halt_request = false;
     cycle_request = false;
+    skip_to_next_sync = false;

     // OK, all done, just wait for display test to time out
     while(millis() - dt_shown_at < DPY_TST_DURATION) {
@@ -227,17 +232,23 @@
         // Processor running, show running dots
         int point = (millis() >> 7) % 6;
         for(int digit=0; digit<6; ++digit) {
-            setMX7219Reg(MX7219_DIGIT_0 + digit, (point == (5-digit)) ? 0x80 : 0x00);
+            setMX7219Reg(MX7219_DIGIT_0 + digit,
+                    (point == (5-digit)) ? 0x80 : 0x00);
         }
     } else {
         // step only makes sense if processor halted
-        if(cycle_request) {
+        if(cycle_request || (skip_to_next_sync && !(status_bits & SB_SYNC))) {
             // Pulse step pin
             digitalWrite(STEP, HIGH);
             digitalWrite(STEP, LOW);

-            // Reset cycle request
-            cycle_request = false;
+            // If we are skipping rather than cycling, reset skip
+            if(!cycle_request) {
+                skip_to_next_sync = false;
+            } else {
+                // Reset cycle request
+                cycle_request = false;
+            }
         }

         // Update address bus


Added all 5 channels PWM setup.

Added all 5 channels PWM setup.

--- aquacontrol32.ino
+++ aquacontrol32.ino
@@ -151,16 +151,19 @@

   //WiFi.printDiag( Serial );

-  // Setup timer and attach timer to a led pin
-  ledcActualFrequency = ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_NUMBER_OF_BIT);
+  for ( byte thisChannel = 0; thisChannel < NUMBER_OF_CHANNELS; thisChannel++ )
+  {
+    // Setup timers and attach timer to a led pin
+    ledcActualFrequency = ledcSetup(thisChannel, LEDC_BASE_FREQ, LEDC_NUMBER_OF_BIT);
+    Serial.print( "\nChannel: " ); Serial.println( thisChannel + 1 );
+    Serial.print( "PWM frequency requested: " ); Serial.print( LEDC_BASE_FREQ / 1000.0 ); Serial.println( "kHz." );
+    Serial.print( "PWM frequency actual:    " ); Serial.print( ledcActualFrequency / 1000.0 ); Serial.println( "kHz." );
+    Serial.print( "PWM depth:               " ); Serial.print( LEDC_NUMBER_OF_BIT ); Serial.print( "bit - "); Serial.print( (int)LEDC_PWM_DEPTH ); Serial.println( " steps." );

-  Serial.print( "PWM frequency requested: " ); Serial.print( LEDC_BASE_FREQ / 1000.0 ); Serial.println( "kHz." );
-  Serial.print( "PWM frequency actual:    " ); Serial.print( ledcActualFrequency / 1000.0 ); Serial.println( "kHz." );
-  Serial.print( "PWM depth:               " ); Serial.print( LEDC_NUMBER_OF_BIT ); Serial.print( "bit - "); Serial.print( (int)LEDC_PWM_DEPTH ); Serial.println( " steps." );
+    ledcAttachPin(LED_PIN, LEDC_CHANNEL_0);

-  ledcAttachPin(LED_PIN, LEDC_CHANNEL_0);
+  }
 }
-

 void loop()
 {


format

format

--- computer_box/computer_box.ino
+++ computer_box/computer_box.ino
@@ -56,15 +56,15 @@
   //           4,1   # Turn fan on
   //          13,0   # Turn led off
   while(Serial.available() > 0){
-      int pin_num = Serial.parseInt();
-      int pin_status = Serial.parseInt();
+    int pin_num = Serial.parseInt();
+    int pin_status = Serial.parseInt();

-      switch(pin_num){
-        case fan_pin:
-        case LED_BUILTIN:
-          digitalWrite(pin_num, pin_status);
-          break;
-      }
+    switch(pin_num){
+      case fan_pin:
+      case LED_BUILTIN:
+      digitalWrite(pin_num, pin_status);
+      break;
+    }
   }

   Serial.print("{");


Added all neccesary pins

Added all neccesary pins

Next is to add the tones to the pins

--- arduino_Piano_Gen_3.ino
+++ arduino_Piano_Gen_3.ino
@@ -12,6 +12,9 @@
  int tonepin = 13;  // PWM0 output = 9, PWM1 output = 10

  // these are the "piano keys" - they are just input pins
+ #define D3 3
+ #define D4 4
+ #define D5 5
  #define D6 6
  #define D7 7
  #define D8 8
@@ -21,6 +24,9 @@

  void setup() {
    // setup internal pullups on "piano keys" (pins D2 through D6)
+   pinMode(D3, INPUT);
+   pinMode(D4, INPUT);
+   pinMode(D5, INPUT);
    pinMode(D6, INPUT);
    pinMode(D7, INPUT);
    pinMode(D8, INPUT);
@@ -28,6 +34,9 @@
    pinMode(D10, INPUT);
    pinMode(D11, INPUT);

+   digitalWrite(D3, HIGH);
+   digitalWrite(D4, HIGH);
+   digitalWrite(D5, HIGH);
    digitalWrite(D6, HIGH);
    digitalWrite(D7, HIGH);
    digitalWrite(D8, HIGH);


Return status JSON when switching animation mode via REST API.

--- Arduino/McLighting/McLighting.ino
+++ Arduino/McLighting/McLighting.ino
@@ -341,6 +341,7 @@
   server.on("/set_mode", []() {
     getArgs();
     mode = SET_MODE;
+    getStatusJSON();
   });

   server.begin();


stepper experiments

stepper experiments

--- arduino/vaz2103mon/vaz2103mon.ino
+++ arduino/vaz2103mon/vaz2103mon.ino
@@ -3,6 +3,15 @@

   This code is in the public domain.
  */
+
+// driving cd-rom stepper, based on
+// http://electronics-diy.com/driving-cdrom-stepper-motor-with-arduino.php
+
+int coila1 = 2;
+int coila2 = 4;
+int coilb1 = 7;
+int coilb2 = 8;
+int mdelay = 50;

 void setup() {
   // initialize the digital pin as an output.
@@ -15,12 +24,51 @@
   pinMode(9, OUTPUT);
   pinMode(10, OUTPUT);
   pinMode(11, OUTPUT);
+  pinMode(coila1, OUTPUT);
+  pinMode(coila2, OUTPUT);
+  pinMode(coilb1, OUTPUT);
+  pinMode(coilb2, OUTPUT);
+
   //init serial
   Serial.begin(9600);
 }

 void loop() {

+
+// stepper experiments. Commented out for now
+//for (int i=0; i <= 255; i++){
+
+//digitalWrite(coila1, HIGH);
+//digitalWrite(coila2, LOW);
+//digitalWrite(coilb1, LOW);
+//digitalWrite(coilb2, LOW);
+//delay(mdelay);
+
+//digitalWrite(coila1, LOW);
+//digitalWrite(coila2, LOW);
+//digitalWrite(coilb1, HIGH);
+//digitalWrite(coilb2, LOW);
+//delay(mdelay);
+
+//digitalWrite(coila1, LOW);
+//digitalWrite(coila2, HIGH);
+//digitalWrite(coilb1, LOW);
+//digitalWrite(coilb2, LOW);
+//delay(mdelay);
+
+//digitalWrite(coila1, LOW);
+//digitalWrite(coila2, LOW);
+//digitalWrite(coilb1, LOW);
+//digitalWrite(coilb2, HIGH);
+//delay(mdelay);
+//}
+
+//digitalWrite(coila1, LOW);
+//digitalWrite(coila2, LOW);
+//digitalWrite(coilb1, LOW);
+//digitalWrite(coilb2, LOW);
+
 // some info on PWM here: http://www.uchobby.com/index.php/2008/02/12/arduino-analog-gauge/
 // need to add resistors
  if (Serial.available() > 0) {
@@ -30,6 +78,7 @@
     int cpu = Serial.parseInt();
     int ram = Serial.parseInt();
     int net = Serial.parseInt();
+
     if (Serial.read() == '\n') {

       if (cpu >= 0) {


Pretty up the debug output for rtc update event.

--- Arduino/coopController/coopController.ino
+++ Arduino/coopController/coopController.ino
@@ -263,17 +263,31 @@
       lastRTCSync = millis();
       if (Debugging) {
         DateTime now = RTC.now();
+        char dateStr[10];
+        char timeStr[8];
+        sprintf(dateStr, "%02d/%02d/%04d", now.month(), now.day(), now.year());
+        int hr = now.hour();
+        boolean ampm = false;
+        if (hr > 12) {
+          hr = hr - 12;
+          ampm = true;
+        }
+        else if (hr == 12) {
+          ampm = true;
+        }
+        else if (hr == 0) {
+          hr = 12;
+        }
+        sprintf(timeStr, "%02d:%02d:%02d", hr, now.minute(), now.second());
         debugger.println("RTC Updated:");
-        debugger.print(now.month(), DEC);
-        debugger.print("/");
-        debugger.print(now.day(), DEC);
-        debugger.print("/");
-        debugger.println(now.year(), DEC);
-        debugger.print(now.hour(), DEC);
-        debugger.print(":");
-        debugger.print(now.minute(), DEC);
-        debugger.print(":");
-        debugger.println(now.second(), DEC);
+        debugger.println(dateStr);
+        debugger.print(timeStr);
+        if (ampm) {
+          debugger.println("pm");
+        }
+        else {
+          debugger.println("am");
+        }
       }
     }
   }


Amended voice freq

Amended voice freq

--- SimonTheSkeleton.ino
+++ SimonTheSkeleton.ino
@@ -26,8 +26,10 @@
 PlainFFT FFT = PlainFFT(); /* Create FFT object */
 /*
  These values can be changed in order to evaluate the functions
- NOTE: human voice operates in 80Hz - 1kHz range
+ NOTE: human voice operates in 80Hz - 10kHz range
  */
+
+ // TODO: up sample rate to match all human voices
 const uint16_t samples = 64;
 double signalFrequency = 1000;
 double samplingFrequency = 5000;
@@ -98,12 +100,13 @@
   FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */
   //PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
   //double x = FFT.MajorPeak(vReal, samples, samplingFrequency);
+
+  //TODO: extract power in system...
   double x;
-  //extract power in system...

   Serial.println(x, 6);

-  //Output to servo
+  //TODO: Output to servo
   myservo.write(x);

   //log finished time & sleep for remaining of sampling time


Setting added TeensyDebug fields. (#41)

Setting added TeensyDebug fields. (#41)

--- Arduino/victoria_teensy_ros_node/victoria_teensy_ros_node.ino
+++ Arduino/victoria_teensy_ros_node/victoria_teensy_ros_node.ino
@@ -232,8 +232,8 @@
   ros_raw_odom_msg.child_frame_id = ros_odom_child_frame_id;
   last_cmd_vel_time = current_time;
   last_encoder_read_time = current_time;
-  encoder_left_pos = 0.0;
-  encoder_right_pos = 0.0;
+  encoder_left_pos = 0;
+  encoder_right_pos = 0;
   motor_left_speed = 0.0;
   motor_right_speed = 0.0;
   reference_wl = 0.0;
@@ -536,6 +536,13 @@
   teensy_debug_msg.motor_speed_left = motor_left_speed;
   teensy_debug_msg.motor_speed_right = motor_right_speed;
   teensy_debug_msg.last_cmd_vel_time = last_cmd_vel_time;
+  teensy_debug_msg.encoder_left = encoder_left_pos;
+  teensy_debug_msg.encoder_right = encoder_right_pos;
+  teensy_debug_msg.last_encoder_read_time = last_encoder_read_time;
+  teensy_debug_msg.w_left = getAngularVelocityFromSamples(samples_wl);
+  teensy_debug_msg.w_right = getAngularVelocityFromSamples(samples_wr);
+  teensy_debug_msg.bumper_left = analogRead(BUMPER_LEFT_PIN);
+  teensy_debug_msg.bumper_right = analogRead(BUMPER_RIGHT_PIN);
   ros_teensy_debug_pub.publish(&teensy_debug_msg);
 }


Ausgabe in Prozent

Ausgabe in Prozent

--- temt6000test1.ino
+++ temt6000test1.ino
@@ -18,6 +18,7 @@
   float voltage = (3.3/4096*analogRead(A1));
   float strom = (voltage/10020);
   float lichtstrom = (strom*2*1000000);
+  lichtstrom = lichtstrom / 6.5852;     //In Prozent 658,52 (Maximalwert) / 100
  Serial.print(lichtstrom,2);

 Serial.print("\n");


mid way fixing bug in I2C device status reporting

--- examples/Habitat_Temps/Habitat_Temps.ino
+++ examples/Habitat_Temps/Habitat_Temps.ino
@@ -36,7 +36,7 @@
  */
  byte DEBUG = 3;

-uint16_t dtime = 1000;  // delay in loop
+uint16_t dtime = 5000;  // delay in loop

 uint8_t config_value;

@@ -148,9 +148,9 @@
   // Wait here for 10 seconds to see if we will use Serial Monitor, so output is not lost
   while((!Serial) && (millis()<10000));    // wait until serial monitor is open or timeout, which seems to fall through

-  Serial.printf("\r\nPCA9548A and TMP275 Test Code at 0x%.2X\r\n", PCA9548A_70.base_get());
-
-    Serial.printf("Build %s - %s\r\n%s\r\n", __DATE__, __TIME__, __FILE__);
+  Serial.printf("\r\nHabitat Temp Monitor at MUX address 0x%.2X\r\n", PCA9548A_70.base_get());
+
+  Serial.printf("Build %s - %s\r\n%s\r\n", __DATE__, __TIME__, __FILE__);

 #if defined(__MKL26Z64__)
   Serial.println( "CPU is T_LC");
@@ -279,7 +279,6 @@
   {
     text_ptr = (PCA9548A_70.status_text[PCA9548A_70.error.error_val]);
     Serial.printf("mux0 control write failed with return of 0x%.2X: %s\r\n", PCA9548A_70.error.error_val, text_ptr);
-    text_ptr = (PCA9548A_70.status_text[PCA9548A_70.error.error_val]);
     delay(dtime/2); // don't blast repeat failures too quickly
   }
   else
@@ -291,11 +290,11 @@
   // ------------------------------
   // Init Mux0Temp7 Sensors
   stat = Mux0Temp7.init(TMP275_CFG_RES12);
-  if (SUCCESS != stat) Serial.printf(" Mux0Temp7 init failed with return of 0x%.2X: %s\r\n", Mux0Temp7.error.error_val);
+  if (SUCCESS != stat) Serial.printf(" Mux0Temp7 init failed with return of 0x%.2X: %s\r\n", Mux0Temp7.error.error_val, Mux0Temp7.status_text[Mux0Temp7.error.error_val]);

   // leave the pointer set to read temperature
   stat = Mux0Temp7.pointer_write(TMP275_TEMP_REG_PTR);
-  if (SUCCESS != stat) Serial.printf(" Mux0Temp7 ptr write failed with return of 0x%.2X: %s\r\n", Mux0Temp7.error.error_val);
+  if (SUCCESS != stat) Serial.printf(" Mux0Temp7 ptr write failed with return of 0x%.2X: %s\r\n", Mux0Temp7.error.error_val, Mux0Temp7.status_text[Mux0Temp7.error.error_val]);

   // Read Temp on Mux0Temp7
   rawtemp=0;


removed optional statusword CAN communication


Fix UNO Bug withoutLib_SS

Fix UNO Bug withoutLib_SS

--- examples/withoutLib_SS/withoutLib_SS.ino
+++ examples/withoutLib_SS/withoutLib_SS.ino
@@ -21,6 +21,7 @@
   while (!Serial);
   // set the data rate for the SoftwareSerial port
   mySerial.begin(600);
+  delay(100); //Avoid Arduino UNO Bug
 }

 void loop(){


Working on updating displays

Working on updating displays

--- Arduino_HVAC_Controller/Networked_HVAC_Controller/Networked_HVAC_Controller.ino
+++ Arduino_HVAC_Controller/Networked_HVAC_Controller/Networked_HVAC_Controller.ino
@@ -174,31 +174,33 @@
     lcd.setBacklight(ON);
   }

-  lcd.setCursor(0, 0);                  // Starting postion of character printing
+

   uint8_t buttons = lcd.readButtons();  // Constantly check to see if something has been put on the bus

-  // --------------Handle updating Temp Change Display---------------------
-  if (get_temp()) {                      // Constantly check to see if the temperature has changed, and update appropriately
+  // --------------Handle updating Temp and Time change display---------------------
+  if ((millis() - timeDelay) > 10000) {    // Update every 10 seconds
+    lcd.setCursor(0, 0);                  // Starting postion of character printing
     lcd.clear();
     lcd.print("Current Temp: ");
+    get_temp();
     lcd.print(currentTemp);
-  }
-
-  if ((millis() - timeDelay) > 10000) {
+
     hoursSeconds = get_time();
+    lcd.setCursor(5, 1);
+    // print the hour and minute:
+    lcd.print((hoursSeconds  % 86400L) / 3600); // print the hour (86400 equals secs per day)
+    lcd.print(':');
+    if ( ((hoursSeconds % 3600) / 60) < 10 ) {
+        // In the first 10 minutes of each hour, we'll want a leading '0'
+        lcd.print('0');
+    }
+    lcd.print((hoursSeconds  % 3600) / 60); // print the minute (3600 equals secs per minute)
+
     timeDelay = millis();
   }

-  lcd.setCursor(5, 1);
-  // print the hour and minute:
-  lcd.print((hoursSeconds  % 86400L) / 3600); // print the hour (86400 equals secs per day)
-  lcd.print(':');
-  if ( ((hoursSeconds % 3600) / 60) < 10 ) {
-    // In the first 10 minutes of each hour, we'll want a leading '0'
-    lcd.print('0');
-  }
-  lcd.print((hoursSeconds  % 3600) / 60); // print the minute (3600 equals secs per minute)
+

   // --------------Handle Button Presses---------------------
   if (buttons) {