Update example with setContrast().

Update example with setContrast().

--- examples/HelloWorld/HelloWorld.ino
+++ examples/HelloWorld/HelloWorld.ino
@@ -53,7 +53,7 @@
 void setup() {
   // PCD8544-compatible displays may have a different resolution...
   lcd.begin(84, 48);
-
+
   // Add the smiley to position "0" of the ASCII table...
   lcd.createChar(0, glyph);
 }
@@ -73,7 +73,11 @@
   lcd.write(' ');
   lcd.write(0);  // write the smiley

-  delay(500);
+  // Use a potentiometer to set the LCD contrast...
+  // short level = map(analogRead(A0), 0, 1023, 0, 127);
+  // lcd.setContrast(level);
+
+  delay(200);
   counter++;
 }


Seed random from A0

Seed random from A0

--- examples/RandomPlay/RandomPlay.ino
+++ examples/RandomPlay/RandomPlay.ino
@@ -60,11 +60,15 @@
       delay(3000);
     }
   }
+
+ // mitigate "pseudo random" by sampling the noise on analogue pin0 and use it as a value.
+ randomSeed(analogRead(A0));
+
 }

 void loop() {

-  //  ** NOTE: Checking for STOPPED doesn't work with the builtin memory
+  //  ** NOTE: Checking for STOPPED doesn't work with the builtin memory z
   //      because in that case the devie appears to only return PAUSED, not STOPPED
   byte stat = mp3.getStatus();
   if(stat != MP3_STATUS_PLAYING)


Update SerialTemp.ino

Update SerialTemp.ino

--- examples/SerialTemp/SerialTemp.ino
+++ examples/SerialTemp/SerialTemp.ino
@@ -4,7 +4,8 @@

  This exmaple writes the current temperarure in celsius
  and fahrenheit to the serial monitor.
- */
+
+*/

 #include <TMP36.h>


Removed bug-inducing code

Removed bug-inducing code

The upcoming read() already does this; this added call only causes an
aditional cluster increment which makes it 'crash' and not display all
sketches on low-cluster size sd-cards

--- examples/SketchList/SketchList.ino
+++ examples/SketchList/SketchList.ino
@@ -155,11 +155,6 @@
     redrawIcons = false;
     PHNDisplay8Bit::fillRect(SKETCHES_OFF_X, SKETCHES_OFF_Y, SKETCHES_FULLW, SKETCHES_FULLH, COLOR_MENU_BG);
     memset(sketch_icon_dirty, 1, sizeof(sketch_icon_dirty));
-  }
-
-  /* Pre-load the next block of file listing */
-  if (!sketches_reachedEnd) {
-    volume_cacheCurrentBlock(0);
   }

   /*


Update code

Update code

--- Get_MAC_adress/Get_MAC_adress.ino
+++ Get_MAC_adress/Get_MAC_adress.ino
@@ -11,4 +11,9 @@

 }

-void loop(){}
+void loop(){
+   Serial.println();
+   Serial.print("MAC: ");
+   Serial.println(WiFi.macAddress());
+   delay(5000);
+   }


removed trailing spaces

removed trailing spaces

--- LSM303/examples/Serial/Serial.ino
+++ LSM303/examples/Serial/Serial.ino
@@ -18,7 +18,7 @@
 (divided by 16) to be consistent with the conversion factors specified
 in the datasheets.

-Example: An LSM303DLH gives an accelerometer Z axis reading of -16144
+Example: An LSM303DLH gives an accelerometer Z axis reading of -16144
 with its default full scale setting of +/- 2 g. Dropping the lowest 4
 bits gives a 12-bit raw value of -1009. The LA_So specification in the
 LSM303DLH datasheet (page 11) states a conversion factor of 1 mg/digit
@@ -39,7 +39,7 @@
   Wire.begin();
   compass.init();
   compass.enableDefault();
-
+
   while (!Serial);
   Serial.println("         Accelerometer           Magnetometer");
   Serial.println("       X       Y       Z       X       Y       Z");
@@ -52,7 +52,7 @@
   snprintf(report, sizeof(report), "%8d%8d%8d%8d%8d%8d",
     compass.a.x, compass.a.y, compass.a.z,
     compass.m.x, compass.m.y, compass.m.z);
-  Serial.println(report);
-
+  Serial.println(report);
+
   delay(100);
 }


final oz

final oz

--- OzControlPanel/OzControlPanel.ino
+++ OzControlPanel/OzControlPanel.ino
@@ -30,13 +30,21 @@
   pixels.clear();
   motor.setSpeed(20);

-  generateColors(_currentColors, kNumberOfPixels);
-  generateColors(_targetColors, kNumberOfPixels);
+  generateColors(_currentColors);
+  generateColors(_targetColors);
+
+  delay(1000);
 }

-void generateColors(uint32_t colors[], int count)
+void generateColors(uint32_t colors[])
 {
-  for (int i = 0; i < count; i++)
+  for (int i = 0; i < 4; i++)
+  {
+    uint8_t c = 255;
+    colors[i] = pixels.Color(c, c, c);
+  }
+
+  for (int i = 4; i < kNumberOfPixels; i++)
   {
     colors[i] = pixels.Color(random(0, 16) * random(0, 16), random(0, 16) * random(0, 16), random(0, 16) * random(0, 16));
   }
@@ -51,6 +59,7 @@
 {
   rot(deg - _motorLoc);
   _motorLoc = deg;
+  Serial.println(_motorLoc);
 }

 uint32_t blendComponent(uint32_t color1, uint32_t color2, int shift, float f)
@@ -75,12 +84,14 @@
   }

   pixels.show();
-  Serial.println((uint8_t)(_currentColors[0] >> 16));
 }

 void play1()
 {
   rotTo(random(-75, 75));
+//  static bool flipped = false;
+//  rotTo(flipped ? -75 : 75);
+//  flipped = !flipped;
 }

 void play2()
@@ -91,7 +102,7 @@
     delay(3);
   }

-  generateColors(_targetColors, kNumberOfPixels);
+  generateColors(_targetColors);
 }

 void loop()
@@ -99,6 +110,7 @@
   play1();
   play2();

+  //delay(3000);
   //delay(random(400, 2000));
 }


RaceTimer: implemented time conversion and began settings menu

--- RaceTimer/RaceTimer/RaceTimer.ino
+++ RaceTimer/RaceTimer/RaceTimer.ino
@@ -2,11 +2,14 @@
 #include <Chrono.h>
 #include <LightChrono.h>

-// constants won't change. They're used here to
-// set pin numbers:
 const int laserPin = 2;     // the number of the pushbutton pin
 const int buzzerPin =  3;      // the number of the LED pin
 const int onPin = 4;     // the number of the pushbutton pin
+
+const int returnPin = 5;
+const int prevPin = 6;
+const int nextPin = 7;
+const int setPin = 8;

 Chrono chrono(Chrono::MICROS);
 unsigned long measuredTimes[10];
@@ -22,9 +25,15 @@
 void setup() {
   Serial.begin(9600);   // Test
   Serial.println("Stopwatch");
+
   pinMode(buzzerPin, OUTPUT);
   pinMode(laserPin, INPUT);
   pinMode(onPin, INPUT);
+
+  pinMode(returnPin, INPUT);
+  pinMode(prevPin, INPUT);
+  pinMode(nextPin, INPUT);
+  pinMode(setPin, INPUT);

   measurementTimeout.restart();

@@ -75,6 +84,26 @@

 }

+void settingsMenu() {
+
+  do {
+    Serial.println("Settings");
+
+    Serial.print("Number of Measurements: ");
+    Serial.print(maxMeasurements);
+    Serial.println();
+
+    if (digitalRead(nextPin)) {
+      maxMeasurements++;
+    }
+    if (digitalRead(prevPin)) {
+      maxMeasurements--;
+    }
+
+  } while (!digitalRead(returnPin));
+
+}
+
 void logAndRestart() {
     if (measurementIndex < maxMeasurements){
       measuredTimes[measurementIndex] = chrono.elapsed();
@@ -85,42 +114,20 @@
     }
  }

-
-// http://forum.arduino.cc/index.php?topic=18588.0
-// argument is time in milliseconds
 void printTime(unsigned long t_milli)
 {
    char buffer[20];
-   int days, hours, mins, secs;
-   int fractime;
-   unsigned long inttime;
+   int mins, secs ;
+   unsigned long millisecs;

-   inttime  = t_milli / 1000;
-   fractime = t_milli % 1000;
-   // inttime is the total number of number of seconds
-   // fractimeis the number of thousandths of a second
+   mins = t_milli / (1000*60);
+   millisecs = t_milli - (mins * 1000 * 60);
+
+   secs = millisecs / 1000;

-   // number of days is total number of seconds divided by 24 divided by 3600
-   days     = inttime / (24*3600);
-   inttime  = inttime % (24*3600);
+   millisecs = millisecs - (secs * 1000);

-   // Now, inttime is the remainder after subtracting the number of seconds
-   // in the number of days
-   hours    = inttime / 3600;
-   inttime  = inttime % 3600;
-
-   // Now, inttime is the remainder after subtracting the number of seconds
-   // in the number of days and hours
-   mins     = inttime / 60;
-   inttime  = inttime % 60;
-
-   // Now inttime is the number of seconds left after subtracting the number
-   // in the number of days, hours and minutes. In other words, it is the
-   // number of seconds.
-   secs = inttime;
-
-   // Don't bother to print days
-   sprintf(buffer, "%02d:%02d:%02d.%03d", hours, mins, secs, fractime);
+   sprintf(buffer, "%02d:%02d:%03d", mins, secs, millisecs);
    Serial.println(buffer);
    //lcd.print(buffer);
 }


Have code auto-detect the arduino board we are using and adjust accordingly (instead of previous manual settings)

--- CoreIR.ino
+++ CoreIR.ino
@@ -16,11 +16,16 @@
 long tx_id = 4242424;
 long tx_alt_id = 8901234;

-//if using an attiny, comment out the atmega line below otherwise leave as is.
-//#define atmega
-
-//if using a arduino pro micro, uncomment the below line
-#define micro
+//if using an attiny
+#ifdef defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny85)
+#else
+  #define atmega
+#endif
+
+//if using a arduino pro micro
+#ifdef defined(__AVR_ATmega32U4__)
+  #define micro
+#endif

 //CONFIGURATION END


tap dance now fires when another key is pressed (issue #16)

--- mods/tapDance/mod_tapDance.ino
+++ mods/tapDance/mod_tapDance.ino
@@ -25,7 +25,7 @@
 const byte modMethod(MAX_KEYS) = 3;
 const byte modMethod(PADDING) = 2;

-uint16_t modMethod(PressTimer)[modMethod(MAX_INDEX)];
+int16_t modMethod(PressTimer)[modMethod(MAX_INDEX)];
 byte modMethod(PressCount)[modMethod(MAX_INDEX)];
 boolean modMethod(KeyIsDown)[modMethod(MAX_INDEX)];

@@ -62,14 +62,11 @@
           {
             modMethod(PressTimer)[i]--;
           }
-          else
+          else if (modMethod(PressTimer)[i] == 0)
           {
+            modMethod(PressTimer)[i] = -1; // signal that the key has fired
             PressKey(modMethod(GetKeyVal)(i, modMethod(PressCount)[i] - 1), modMethod(GetKeyType)(i, modMethod(PressCount)[i] - 1));
-            if (modMethod(KeyIsDown)[i])
-            {
-              // do nothing
-            }
-            else
+            if (!modMethod(KeyIsDown)[i])
             {
               modMethod(KeyUp)(i, 19);
             }
@@ -107,6 +104,25 @@
   }
 }

+void modMethod(PrePress)(char val, byte type)
+{
+  if (IS_MASTER)
+  {
+    for (byte i = 0; i < modMethod(MAX_INDEX); i++)
+    {
+      if ((type != 19 || val != i) && modMethod(PressCount)[i] > 0)
+      {
+        modMethod(PressTimer)[i] = -1; // signal that the key has fired
+        PressKey(modMethod(GetKeyVal)(i, modMethod(PressCount)[i] - 1), modMethod(GetKeyType)(i, modMethod(PressCount)[i] - 1));
+        if (!modMethod(KeyIsDown)[i])
+        {
+          modMethod(KeyUp)(i, 19);
+        }
+      }
+    }
+  }
+}
+
 void modMethod(KeyUp)(char val, byte type)
 {
   // ran when a key is pressed up
@@ -120,13 +136,9 @@
       // sends the macro sequence with id = val
       ReleaseKey(modMethod(GetKeyVal)(val, modMethod(PressCount)[val] - 1), modMethod(GetKeyType)(val, modMethod(PressCount)[val] - 1));

-      if (modMethod(KeyIsDown)[val])
-      {
-        // do nothing
-      }
-      else
-      {
-
+      // if key has already fired
+      if (modMethod(PressTimer)[val] < 0)
+      {
         modMethod(PressCount)[val] = 0;
         modMethod(PressTimer)[val] = 0;
       }
@@ -147,8 +159,6 @@
   }
   else if (input.startsWith("uniqueksettapdance"))
   {
-    byte key, type, state;
-
     input = input.substring(input.indexOf('(')+1);
     byte id = input.substring(0, input.indexOf('(')).toInt();
     input = input.substring(input.indexOf('(')+1);


Remove excess output to Serial in car_system

The output was originally to debug the system, but is no longer required.

--- arduino/car_system/car_system.ino
+++ arduino/car_system/car_system.ino
@@ -53,7 +53,6 @@
 }

 void setup() {
-  Serial.begin(9600);
   ppad.begin(9600);

   pinMode(pinCapacitive, INPUT);
@@ -97,8 +96,6 @@

     if(ppad.available()) {
       String in = ppad.readStringUntil('\n');
-      Serial.println(in);
-
       if(in.charAt(0) == '1') {
         alertSensorEssential = true;
       }
@@ -131,8 +128,6 @@
       digitalWrite(pinGeneralLED, LOW);
     }

-    Serial.println("ALERT");
-
     delay(.2 * 1000);
   }
 }


add sample oled support to DEV example

add sample oled support to DEV example

--- examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino
+++ examples/DEV/OnDemandConfigPortal/OnDemandConfigPortal.ino
@@ -7,6 +7,49 @@
 #define TRIGGER_PIN 0
 const char* modes[] = { "NULL", "STA", "AP", "STA+AP" };

+#define OLED
+
+#include <Wire.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+#ifdef OLED
+
+#define SCREEN_WIDTH 128 // OLED display width, in pixels
+#define SCREEN_HEIGHT 32 // OLED display height, in pixels
+
+// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
+#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
+
+void init_oled(){
+  Wire.begin(SCL,SDA);  // begin(sda, scl) SWAP!
+  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
+    Serial.println(F("SSD1306 allocation failed"));
+  }
+
+  display.clearDisplay();
+  display.setTextSize(1);             // Normal 1:1 pixepl scale
+  display.setTextColor(WHITE);        // Draw white text
+  display.setCursor(0,0);             // Start at top-left corner
+  display.display();
+}
+#endif
+
+void print_oled(String str,uint8_t size){
+  #ifdef OLED
+  display.clearDisplay();
+  display.setTextSize(size);
+  display.setTextColor(WHITE);
+  display.setCursor(0,0);
+  display.println(str);
+  display.display();
+  #else
+  (void)str;
+  (void)size;
+  #endif
+}
+
 WiFiManager wm;
 bool TEST_CP  = false; // always start the configportal
 bool TEST_NET = true; // do a network test, get ntp time
@@ -20,6 +63,7 @@
 //gets called when WiFiManager enters configuration mode
 void configModeCallback (WiFiManager *myWiFiManager) {
   Serial.println("[CALLBACK] configModeCallback fired");
+  print_oled("WiFiManager Waiting\nIP: " + WiFi.softAPIP().toString() + "\nSSID: " + WiFi.softAPSSID(),1);
   // myWiFiManager->setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
   // Serial.println(WiFi.softAPIP());
   //if you used auto generated SSID, print it
@@ -44,11 +88,15 @@
 void setup() {
   // put your setup code here, to run once:
   Serial.begin(115200);
-  Serial.setDebugOutput(true);
+  // Serial.setDebugOutput(true);
   // delay(3000);
   Serial.println("\n Starting");
   // WiFi.setSleepMode(WIFI_NONE_SLEEP); // disable sleep, can improve ap stability

+  #ifdef OLED
+  init_oled();
+  #endif
+  print_oled(F("Starting..."),2);
   wm.debugPlatformInfo();

   //Local intialization. Once its business is done, there is no need to keep it around
@@ -121,8 +169,10 @@
   //here  "AutoConnectAP"
   //and goes into a blocking loop awaiting configuration

+  print_oled(F("Connecting..."),2);
   if(!wm.autoConnect("AutoConnectAP")) {
     Serial.println("failed to connect and hit timeout");
+    print_oled("Not Connected",2);
   }
   else if(TEST_CP) {
     // start configportal always
@@ -132,6 +182,7 @@
   else {
     //if you get here you have connected to the WiFi
      Serial.println("connected...yeey :)");
+      print_oled("Connected\nIP: " + WiFi.localIP().toString() + "\nSSID: " + WiFi.SSID(),1);
   }
   pinMode(TRIGGER_PIN, INPUT);
 }
@@ -151,6 +202,7 @@
     } else {
       //if you get here you have connected to the WiFi
       Serial.println("connected...yeey :)");
+      print_oled("Connected\nIP: " + WiFi.localIP().toString() + "\nSSID: " + WiFi.SSID(),1);
       getTime();
     }
   }
@@ -175,7 +227,7 @@
     if((millis() - start) > timeout){
       Serial.println("[ERROR] Failed to get NTP time.");
       return;
-    }
+    }
   }
   Serial.println("");
   struct tm timeinfo;


Fixed comments

Fixed comments

--- examples/SharpDistSensorByModel/SharpDistSensorByModel.ino
+++ examples/SharpDistSensorByModel/SharpDistSensorByModel.ino
@@ -27,9 +27,9 @@

 /*
 This example shows how to use the SharpDistSensor library to continuously
-read the sensor and display the analog value and the corrseponding distance
-in mm using a pre-defined sensor model. See the library README page for the
-list of available models and corresponding constants.
+read the sensor and display the distance in mm using a pre-defined sensor model.
+See the library README page for the list of available models and corresponding
+constants.

 For how to use different sensor model, units, range or calibration with a
 custom calibration curve, see the SharpDistSensorCustom.ino example sketch in


Changing comments from the readings

Changing comments from the readings

--- examples/UbidotsSaveMultiValues/UbidotsSaveMultiValues.ino
+++ examples/UbidotsSaveMultiValues/UbidotsSaveMultiValues.ino
@@ -34,13 +34,13 @@

 void setup() {
   Serial.begin(115200);
-  client.setDebug(false);
+  client.setDebug(true);
 }

 void loop() {
   float temperature = analogRead(A0);  // Reading analog pin A0
-  float humidity = analogRead(A1);  // Reading analog pin A0
-  float pressure = analogRead(A2);  // Reading analog pin A0
+  float humidity = analogRead(A1);  // Reading analog pin A1
+  float pressure = analogRead(A2);  // Reading analog pin A2

   client.add(VARIABLE_LABEL_1, temperature);
   client.add(VARIABLE_LABEL_2, humidity);


negate check - as we've changed the wiring

--- lib-arduino/ACNode/examples/CompressorNode/CompressorNode.ino
+++ lib-arduino/ACNode/examples/CompressorNode/CompressorNode.ino
@@ -25,7 +25,7 @@

 OptoDebounce opto1(OPTO1); // wired to the 'pressure low' switch of the compressor.

-LED aartLed = LED(AART_LED);
+LED aartLed = LED(AART_LED);
 ACNode node = ACNode(MACHINE, WIFI_MAKERSPACE_NETWORK, WIFI_MAKERSPACE_PASSWD);

 #ifdef OTA_PASSWD
@@ -161,7 +161,12 @@

   aartLed.set(state[machinestate].ledState);

-  if (opto1.state())
+  // We are inverted - i.e. over the on-off pressure switch; as there is a leak
+  // across the L which puts it at 100v when off (relative to N) or 220 when
+  // on. Which we cannot detect. So instead we detect the leak current and
+  // the 0 ohm of the siwch quelling that voltage.
+  //
+  if (opto1.state() == false)
     machinestate = RUNNING;
   else if (machinestate > POWERED)
     machinestate = POWERED;


reduce time to 3 s

reduce time to 3 s

--- collect_arduino_data/WebControlPER/WebControlPER.ino
+++ collect_arduino_data/WebControlPER/WebControlPER.ino
@@ -628,7 +628,7 @@

     writehomepage ();

-    flashLED (1, 9, 500);
+    flashLED (1, 9, 300);
     return ;
   }


removed reverse governer

removed reverse governer

--- arduino/car_control/src/main_control_nano/main_control_nano.ino
+++ arduino/car_control/src/main_control_nano/main_control_nano.ino
@@ -113,12 +113,7 @@
 //controls the acceleration/deccelration of the robot. -100 is full break to 100 full gas

 void set_throttle_position(float pos) {
-  //dont allow input past the limits, note we only limit reverse if the
-  //standing throttle position is at zero. This allows for full breaking
-  if (rpm < ROLLING_RPM){
-    pos = max(_GOVERNER_R, pos);
-  }
-
+  //dont allow input past the limits
   pos = min(_GOVERNER_F, pos);

   throttle_pos = pos;


OTA update example

OTA update example

--- src/homie-sonoff-touch.ino
+++ src/homie-sonoff-touch.ino
@@ -8,6 +8,10 @@
 const char *__FLAGGED_FW_NAME = "\xbf\x84\xe4\x13\x54" FW_NAME "\x93\x44\x6b\xa7\x75";
 const char *__FLAGGED_FW_VERSION = "\x6a\x3f\x3e\x0e\xe1" FW_VERSION "\xb0\x30\x48\xd4\x1a";
 /* End of magic sequence for Autodetectable Binary Upload */
+
+/* To use Homie built in OTA updater...
+./ota_updater.py -l 172.24.32.13 -t devices/ -i 60019485376d /home/kyleg/Projects/homie-sonoff-touch/.pioenvs/esp8285/firmware.bin
+*/

 // LED_PIN controls the LED under the wifi symbol on the front plate.
 // RELAY_PIN controls the relay, *AND* the LED under the touchpad.


Buck: Code cleanup

Buck: Code cleanup


changed comment in ESP8266_OSCExample.ino while trying to understand why the voltage reading is going above 1 for /batt

--- code/ESP8266_OSCExample/ESP8266_OSCExample/ESP8266_OSCExample.ino
+++ code/ESP8266_OSCExample/ESP8266_OSCExample/ESP8266_OSCExample.ino
@@ -24,9 +24,9 @@
 /*Voltage Measurement*/
 // Voltage divider on ADC allows for a measurement of battery voltage.
 // maybe these don't need to be preprocessor
-#define V_RES float(1./256.) //the number of steps per volt
-#define R1 float(2000000.)
-#define R2 float(330000.)
+#define V_RES float(1./256.) //the number of volts per step
+#define R1 float(200.)
+#define R2 float(33.)
 #define V_SCALE float(R2 / (R1 + R2))
 #define V_MIN float(2.6) //the undervoltage shutoff of voltage regulator
 #define V_MAX float(4.2) //the theoretical maximum voltage of LiPo


changed the /time endpoint to send millis because micros was overflowing

--- code/ESP8266_OSCExample/ESP8266_OSCExample/ESP8266_OSCExample.ino
+++ code/ESP8266_OSCExample/ESP8266_OSCExample/ESP8266_OSCExample.ino
@@ -330,7 +330,7 @@
     /*OSC Out*/
     //declare a bundle
     OSCBundle bndl;
-    bndl.add("/time").add((int32_t)micros()); //time since active :: indicates a connection
+    bndl.add("/time").add((int32_t)millis()); //time since active :: indicates a connection
     bndl.add("/ypr").add(pi2float(ypr[0])).add(pi2float(ypr[1])).add(pi2float(ypr[2])); // yaw/pitch/roll
     bndl.add("/batt").add(float((analogRead(A0) >> 2)-SCALED_V_MIN)/(SCALED_V_MAX - SCALED_V_MIN)); //battery voltage [0,1]


WIP - retrieve sysex data

WIP - retrieve sysex data

work in progress - simple sysex buffer/parser.

--- nRF51822-BLEMIDI/nRF51822-BLEMIDI.ino
+++ nRF51822-BLEMIDI/nRF51822-BLEMIDI.ino
@@ -37,7 +37,7 @@

 #define TXRX_BUF_LEN                     20
 #define RX_BUF_LEN                       100 /** Overwriting RX Buf Len since we handle fragmentation **/
-#define UART_RX_TIME                     APP_TIMER_TICKS(10, 0)
+#define UART_RX_TIME                     APP_TIMER_TICKS(20, 0)

 #define STATUS_CHECK_TIME                APP_TIMER_TICKS(20, 0)
@@ -45,7 +45,7 @@

 // Activate to debug
 // this increases delay significantly due to increased I/Os
-#define DEBUG 1
+#define DEBUG 0

 #ifdef DEBUG
 #define DEBUG_PRINT(x)     Serial.print (x)
@@ -277,7 +277,10 @@
   if ( charHandle == txCharacteristic.getHandle() )
   {
     ble.readCharacteristicValue(txCharacteristic.getHandle(), buf, &bytesRead);
-   	parseBLEtoMIDI(buf, bytesRead);
+     parseBLEtoMIDI(buf, bytesRead);
+     sprintf(debugBuf, " READ: %i", bytesRead);
+             Serial.print(debugBuf);
+             Serial.println();
   }
 }

@@ -384,7 +387,7 @@
   int i = 0; /*data index*/
   char debugBuf[123];
   char buf[20];
-  uint8_t bufMidi[128];
+  uint8_t bufMidi[220];
   byte outBuf[ 3 ]; // single midi message
   // uint8_t outBufMidi[128];
   // Remove header byte
@@ -394,7 +397,64 @@
 for (int i = 0; i < bytesRead-1; i++) {
     switch (prsState)
     {
-      case STRT:
+
+       case MIDI:
+          if (i%4 != 0)
+	  {
+            sprintf(debugBuf, "MIDI: %02X", bufMidi[i]);
+            Serial.print(debugBuf);
+           	outBuf[(i%4)] = bufMidi[i];
+          }
+          else
+	  {
+            Serial.print(" - ");
+            Midi.SendData(outBuf,2);
+            memset(outBuf, 0, sizeof(outBuf));
+          }
+          if ( i == (bytesRead-2))
+	  {
+	    prsState = STRT;
+	  }
+         break;
+
+       case RUN:
+	       if (i < 4 && i%4 != 0)
+		{
+	       		outBuf[(i%4)] = bufMidi[i];
+	          if (i%4 == 3) {  Midi.SendData(outBuf,3); };
+	       }
+	       else if (i%2 == 0)
+	       {
+	          outBuf[0] = midStat;
+	          outBuf[1] = bufMidi[i];
+	          outBuf[2] = bufMidi[i+1];
+	          Midi.SendData(outBuf,3);
+
+	       }
+	       if ( i == (bytesRead-2))
+	       {
+	          prsState = STRT;
+	       }
+
+       break;
+
+       case SYSEX:
+         if (bufMidi[i] == 0xF7) // End reached, move pointer back and overwrite timestamp with SysEx End
+         {
+           outBufMidi[outBufMidPtr] = bufMidi[i];
+           Midi.SendSysEx(outBufMidi, outBufMidPtr+1, 0);
+           prsState = STRT;
+           outBufMidPtr = 0;
+
+         }
+         else
+	 {
+           outBufMidi[outBufMidPtr] = bufMidi[i];
+           outBufMidPtr++;
+         }
+        break;
+          case STRT:
+          default:
         if (bufMidi[i+1] == 0xF0) // looking 1 byte ahead to skip timestamp
           {
             memset(&outBufMidi[0], 0, sizeof(outBufMidi)); // Empty SysEx Buffer
@@ -419,67 +479,6 @@
           }
           startStamp = bufMidi[i];
           break;
-       case MIDI:
-          if (i%4 != 0)
-					{
-            sprintf(debugBuf, " %02X", bufMidi[i]);
-            Serial.print(debugBuf);
-           	outBuf[(i%4)] = bufMidi[i];
-          }
-          else
-					{
-            Serial.print(" - ");
-            Midi.SendData(outBuf,2);
-            memset(outBuf, 0, sizeof(outBuf));
-          }
-          if ( i == (bytesRead-2))
-					{
-						prsState = STRT;
-					}
-         break;
-
-       case RUN:
-	       if (i < 4 && i%4 != 0)
-				 {
-	       		outBuf[(i%4)] = bufMidi[i];
-	          if (i%4 == 3) {  Midi.SendData(outBuf,3); };
-	       }
-	       else if (i%2 == 0)
-	       {
-	          outBuf[0] = midStat;
-	          outBuf[1] = bufMidi[i];
-	          outBuf[2] = bufMidi[i+1];
-	          Midi.SendData(outBuf,3);
-
-	       }
-	        if ( i == (bytesRead-2))
-					{
-						prsState = STRT;
-					}
-
-       break;
-
-       case SYSEX:
-         if (i == (bytesRead-2) && bufMidi[i] == 0xF7) // End reached, move pointer back and overwrite timestamp with SysEx End
-         {
-           outBufMidi[outBufMidPtr-1] = bufMidi[i];
-           Midi.SendData(outBufMidi, 3);
-           prsState = STRT;
-
-
-           Serial.print("Dumping SYSEX BLOB: ");
-           for (int i = 0; i < outBufMidPtr; i++)
-					 {
-           	 sprintf(debugBuf, " %02X", outBufMidi[i]);
-             Serial.print(debugBuf); }
-             Serial.println();
-         	 }
-         else
-				 {
-           outBufMidi[outBufMidPtr] = bufMidi[i];
-           outBufMidPtr++;
-         }
-        break;
     }

 }


Additional Code Cleanup

Additional Code Cleanup

Additional Code cleanup for readability as preparation for impending rewrite.

--- nRF51822-BLEMIDI/nRF51822-BLEMIDI.ino
+++ nRF51822-BLEMIDI/nRF51822-BLEMIDI.ino
@@ -1,4 +1,3 @@
-
 /*
  *   Copyright (c) 2014 Matthias Frick, All rights reserved.
  *
@@ -31,44 +30,26 @@
 #include <Usb.h>
 #include <usbh_midi.h>
 #define __CORE_CM0_H_GENERIC
-#define BLE_UUID_TXRX_SERVICE            0x0000 /**< The UUID of the Nordic UART Service. */
-#define BLE_UUID_TX_CHARACTERISTIC       0x0001 /**< The UUID of the TX Characteristic. */
+#define BLE_UUID_TXRX_SERVICE           0x0000 /**< The UUID of the Nordic UART Service. */
+#define BLE_UUID_TX_CHARACTERISTIC      0x0001 /**< The UUID of the TX Characteristic. */
 #define BLE_UUID_RX_CHARACTERISTIC      0x0002 /**< The UUID of the RX Characteristic. */

-#define TXRX_BUF_LEN                     100
-#define UART_RX_TIME                     APP_TIMER_TICKS(10, 0)
-
-
-#define STATUS_CHECK_TIME                APP_TIMER_TICKS(20, 0)
-
-
-// Activate to debug
-// this increases delay significantly due to increased I/Os
-#define DEBUG 1
-
-#ifdef DEBUG
-#define DEBUG_PRINT(x)     Serial.print (x)
-#define DEBUG_PRINTDEC(x)     Serial.print (x, DEC)
-#define DEBUG_PRINTHEX(x)     Serial.print (x, HEX)
-#define DEBUG_PRINTLN(x)  Serial.println (x)
-#else
-#define DEBUG_PRINT(x)
-#define DEBUG_PRINTDEC(x)
-#define DEBUG_PRINTHEX(x)
-#define DEBUG_PRINTLN(x)
-#endif
-
-
+#define TXRX_BUF_LEN                    20
+#define RX_BUF_LEN                      100 /** Overwriting RX Buf Len since we handle fragmentation **/
+#define UART_RX_TIME                    APP_TIMER_TICKS(20, 0)
+#define STATUS_CHECK_TIME               APP_TIMER_TICKS(20, 0)

 BLEDevice  ble;

-static app_timer_id_t                    m_uart_rx_id;
-static app_timer_id_t                    m_status_check_id;
-static uint8_t rx_buf[TXRX_BUF_LEN];
+static app_timer_id_t                   m_uart_rx_id;
+static app_timer_id_t                   m_status_check_id;
+static uint8_t rx_buf[RX_BUF_LEN];
 static int rx_buf_num, rx_state = 0;
 static uint8_t rx_temp_buf[20];
-
-// TXRX Service & UDIDs
+uint8_t outBufMidi[128];
+int outBufMidPtr;
+
+// TXRX Service
 static const uint8_t uart_base_uuid[] = {0x03, 0xB8, 0x0E, 0x5A, 0xED, 0xE8, 0x4B, 0x33, 0xA7, 0x51, 0x6C, 0xE3, 0x4E, 0xC4, 0xC7, 0};
 static const uint8_t uart_tx_uuid[]   = {0x77, 0x72, 0xE5, 0xDB, 0x38, 0x68, 0x41, 0x12, 0xA1, 0xA9, 0xF2, 0x66, 0x9D, 0x10, 0x6B, 0xF3};
 static const uint8_t uart_rx_uuid[]   = {0x77, 0x72, 0xE5, 0xDB, 0x38, 0x68, 0x41, 0x12, 0xA1, 0xA9, 0xF2, 0x66, 0x9D, 0x10, 0x6B, 0xF3};
@@ -77,13 +58,19 @@
 uint8_t txPayload[TXRX_BUF_LEN] = {0,};
 uint8_t rxPayload[TXRX_BUF_LEN] = {0,};

-GattCharacteristic  txCharacteristic (uart_tx_uuid, txPayload, 1, 20,
-                                     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic  txCharacteristic
+  (uart_tx_uuid, txPayload, 1, 20,
+  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE |
+  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE |
+  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY |
+  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);

 GattCharacteristic *uartChars[] = {&txCharacteristic};
-GattService         uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *));
-
-
+GattService         uartService(uart_base_uuid, uartChars,
+                                sizeof(uartChars) / sizeof(GattCharacteristic *));
+
+/* Parser States: START (uninitialized), MIDI, SYSEX, RUNNING MSG*/
+typedef enum { STRT, MIDI, SYSEX, RUN} OutParserState;

 /*******************************************************************************
  * INITIALIZE USB MIDI Variables
@@ -94,12 +81,13 @@
 uint8_t laststate;
 uint8_t rcode;
 USB_DEVICE_DESCRIPTOR buf;
+OutParserState prsState; /* Parser */

 void MIDI_poll();
-void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);

 boolean bFirst;
 boolean isConnected;
+boolean isSysex;
 uint16_t pid, vid;

@@ -110,45 +98,30 @@
 static uint8_t midiOut_buff[MAX_TX_BUFF];
 static uint8_t midiOut_buff_len = 0;

+
+
 /*******************************************************************************
 * Send MIDI data to BLE Stack
-*
-* BLE Packet is capped to 17 bytes (2 bytes prefix + 3 bytes MIDI + 3 * 4 bytes)
-*
-* Right now this is periodically called by the app_timer, to make sure the buffer clears
-* out fast enough as calling this through MIDI_poll() caused more delay.
-* TO DO: Use MIDI Structs instead of byte array
-*
 *******************************************************************************/
 void m_uart_rx_handle(void * p_context)
 {
-if(rx_buf_num > 0 && isConnected)
-{
-	 int bufInc = 0;
-
-	 // with every ticker-call to this function we take 17 bytes off the buffer and send it out to BLE
-	 if (rx_buf_num < 17)
-	 {
-	    bufInc = rx_buf_num % 17;
-	 }
-	 else
-	 {
-		 bufInc = 17;
-	 }
-	  ble.updateCharacteristicValue(txCharacteristic.getHandle(), rx_buf, bufInc);
-	  memmove(rx_buf, rx_buf+bufInc, rx_buf_num-bufInc); // probably not best practice, needs to be fixed
-	  rx_buf_num -= bufInc;
-	  rx_state = 0;
-}
-}
-
-/*******************************************************************************
-* Connection callback
-*
-*  TO DO:
-* - Probably doesnt need Serial.Read() here since we dont do any reading
-*
-/******************************************************************************/
+  if(rx_buf_num > 0 && isConnected)
+  {
+    int bufInc = 0;
+    if (rx_buf_num < 17)
+    {
+      bufInc = rx_buf_num % 17; }
+    else
+    {
+      bufInc = 17;
+    }
+    ble.updateCharacteristicValue(txCharacteristic.getHandle(), rx_buf, bufInc);
+    memmove(rx_buf, rx_buf+bufInc, rx_buf_num-bufInc); // probably not best practice, needs to be fixed
+    rx_buf_num -= bufInc;
+    rx_state = 0;
+  }
+}
+
 void uartCallBack(void)
 {
   uint32_t err_code = NRF_SUCCESS;
@@ -173,8 +146,7 @@
   Usb.Task();
   usbstate = Usb.getUsbTaskState();

-  if (usbstate != laststate)
-	{
+  if (usbstate != laststate) {
     laststate = usbstate;

     switch (usbstate) {
@@ -197,12 +169,12 @@
         E_Notify(PSTR("\r\nGetting device descriptor"), 0x80);
         rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf);

-        if (rcode)
-				{
+        if (rcode) {
           E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80);
+          // print_hex(rcode, 8);
         }
-        else
-				{
+        else {
+
           E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80);
           print_hex(buf.bLength, 8);
           E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80);
@@ -245,12 +217,11 @@

   if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
   {
-		MIDI_poll();
-  }
-
-}
-
-// Disconnect Callback
+
+    MIDI_poll();
+  }
+
+}
 void disconnectionCallback(void)
 {
   Serial.println("Disconnected! \r\n");
@@ -259,13 +230,12 @@
   ble.startAdvertising();
 }

-void connectionCallback(void)
-{
- 	isConnected = true;
- 	uint32_t err_code = NRF_SUCCESS;
+void connectionCallback(void)
+{
+  isConnected = true;
+  uint32_t err_code = NRF_SUCCESS;
   err_code = app_timer_create(&m_uart_rx_id, APP_TIMER_MODE_REPEATED, m_uart_rx_handle);
   APP_ERROR_CHECK(err_code);
-
   err_code = app_timer_start(m_uart_rx_id, STATUS_CHECK_TIME, NULL);
   APP_ERROR_CHECK(err_code);
 }
@@ -273,31 +243,32 @@

 /*******************************************************************************
 * Callback for INCOMING MIDI BLE Data
-*
-*
 *******************************************************************************/
-
 void onDataWritten(uint16_t charHandle)
 {
   uint8_t buf[TXRX_BUF_LEN];
   uint16_t bytesRead;
-	Serial.println("Something");
+  char debugBuf[23];
   if ( charHandle == txCharacteristic.getHandle() )
   {
     ble.readCharacteristicValue(txCharacteristic.getHandle(), buf, &bytesRead);
     parseBLEtoMIDI(buf, bytesRead);
+    sprintf(debugBuf, " READ: %i", bytesRead);
+    Serial.print(debugBuf);
+    Serial.println();
   }
 }

 void setup(void)
 {
+  prsState = STRT; // Assuming MIDI
   bFirst = true;
   vid = pid = 0;
   isConnected = false;
   uint32_t err_code = NRF_SUCCESS;
   uart_callback_t uart_cb;
   Serial.begin(9600);
-
+
   //Workaround for non UHS2.0 Shield
   pinMode(10, OUTPUT);
   digitalWrite(10, HIGH);
@@ -315,48 +286,46 @@
   /* setup advertising */
   ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
   ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
-  ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)"BLIDIno", sizeof("BLIDIno") - 1);
-  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
+  ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
+    (const uint8_t *)"BLIDIno", sizeof("BLIDIno") - 1);
+  ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
+    (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));

   /* 100ms; in multiples of 0.625ms. */
   ble.setAdvertisingInterval(160);

   ble.addService(uartService);
   SPI.begin();
-  //Set Dev_Name
+  //Set Device Name
   err_code = RBL_SetDevName("BLIDino");
   APP_ERROR_CHECK(err_code);

   ble.startAdvertising();
- // err_code = app_timer_create(&m_uart_rx_id, APP_TIMER_MODE_SINGLE_SHOT, m_uart_rx_handle);
-
   err_code = app_timer_create(&m_status_check_id, APP_TIMER_MODE_REPEATED, m_status_check_handle);
   APP_ERROR_CHECK(err_code);

   err_code = app_timer_start(m_status_check_id, STATUS_CHECK_TIME, NULL);
   APP_ERROR_CHECK(err_code);
-
 }

 void loop(void)
 {
   ble.waitForEvent();
 }
-

 /*******************************************************************************
  * Poll MIDI DATA from USB Port
  *******************************************************************************/
 void MIDI_poll()
 {
-
   uint8_t bufMidi[64];
   uint16_t  rcvd;
   uint8_t size;
   byte outBuf[ 3 ];
   char buf[20];

-  if (Midi.vid != vid || Midi.pid != pid) {
+  if (Midi.vid != vid || Midi.pid != pid)
+  {
     vid = Midi.vid;
     pid = Midi.pid;
   }
@@ -364,95 +333,124 @@
   do {
     if ( (size = Midi.RecvData(outBuf)) > 0 ) {
       // Send data to parser
-     parseMIDItoAppleBle(size, outBuf);
-
+      parseMIDItoAppleBle(size, outBuf);
     }
   } while (size > 0);

  uint32_t err_code = NRF_SUCCESS;
-
 }

 /*******************************************************************************
  * Convert MIDI BLE to MIDI USB
- *
- * Pleas check the experimental branch for MIDI BLE to MIDI USB
- *
  *******************************************************************************/
 void parseBLEtoMIDI(uint8_t *dataptr, uint16_t bytesRead)
 {
-  // stubbed out
-
-}
-
-
+  // stubbed out, needs rewrite
+}

 /*******************************************************************************
  * Convert MIDI Data to MIDI-BLE Packets
- *
- * TO DO:
- * - Jitter / Time Coding is not yet implemented
- * - 1 Byte between MIDI Packet is time-offset currently ignored
- * - Move this to proper MIDI Parsing (e.g. SysEx)
- *
  *******************************************************************************/
-void parseMIDItoAppleBle(int size, byte outBuf[3]) {
+void parseMIDItoAppleBle(int size, byte outBuf[3])
+{
   char time[2];
   char buf[20];
-
   unsigned long timer = 0;
   int lastPos;
   timer = millis();
-
   uint16_t blueMidiTime = 0;
   blueMidiTime = 32768 + (timer % 16383);

   uint32_t err_code = NRF_SUCCESS;
   int localBufNum = rx_buf_num;

-  if(rx_buf_num <= 100) // buffer up to 100 bytes
-  {
-      if (rx_buf_num % 17 == 0) // End of packet, start a new one
-      {
-        rx_buf[rx_buf_num] = blueMidiTime >> 8;
-        rx_buf_num++;
-        rx_buf[rx_buf_num] = 0x80;
-        rx_buf_num++;
-      }
-      else
-      {
-        rx_buf[rx_buf_num] = 0x80;
-        rx_buf_num++;
-      }
-
-      for (int i = 0; i < size; i++)
-      {
-        rx_buf[rx_buf_num] = outBuf[i];
-        rx_buf_num++;
-      }
-  }
-}
-
+  if(rx_buf_num <= 100) // arbitrary high number
+  {
+    if (rx_buf_num % 17 == 0) // End of packet, start a new one
+    {
+      rx_buf[rx_buf_num] = blueMidiTime >> 8;
+      rx_buf_num++;
+      rx_buf[rx_buf_num] = 0x80;
+      rx_buf_num++;
+    }
+    else
+    {
+      rx_buf[rx_buf_num] = 0x80;
+      rx_buf_num++;
+    }
+    for (int i = 0; i < size; i++)
+    {
+      rx_buf[rx_buf_num] = outBuf[i];
+      rx_buf_num++;
+    }
+  }
+}

 /*******************************************************************************
  * Convert USB Host debug info to Hex
- *
  *******************************************************************************/
-void print_hex(int v, int num_places) {
+void print_hex(int v, int num_places)
+{
   int mask = 0, n, num_nibbles, digit;
-
-  for (n = 1; n <= num_places; n++) {
+  for (n = 1; n <= num_places; n++)
+  {
     mask = (mask << 1) | 0x0001;
   }
   v = v & mask; // truncate v to specified number of places

   num_nibbles = num_places / 4;
-  if ((num_places % 4) != 0) {
+  if ((num_places % 4) != 0)
+  {
     ++num_nibbles;
   }
-  do {
+  do
+  {
     digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;
     DEBUG_PRINTHEX(digit);
   }
   while (--num_nibbles);
 }
+
+/* TAKEN FROM USBH_MIDI Library */
+/* https://github.com/YuuichiAkagawa/USBH_MIDI */
+/* look up a MIDI message size from spec */
+/*Return                                 */
+/*  0 : undefined message                */
+/*  0<: Vaild message size(1-3)          */
+uint8_t lookupMsgSize(uint8_t midiMsg)
+{
+    uint8_t msgSize = 0;
+    if( midiMsg < 0xf0 ) midiMsg &= 0xf0;
+    switch(midiMsg) {
+       //3 bytes messages
+        case 0xf2 : //system common message(SPP)
+        case 0x80 : //Note off
+        case 0x90 : //Note on
+        case 0xa0 : //Poly KeyPress
+        case 0xb0 : //Control Change
+        case 0xe0 : //PitchBend Change
+            msgSize = 3;
+            break;
+            //2 bytes messages
+        case 0xf1 : //system common message(MTC)
+        case 0xf3 : //system common message(SongSelect)
+        case 0xc0 : //Program Change
+        case 0xd0 : //Channel Pressure
+            msgSize = 2;
+            break;
+            //1 bytes messages
+        case 0xf8 : //system realtime message
+        case 0xf9 : //system realtime message
+        case 0xfa : //system realtime message
+        case 0xfb : //system realtime message
+        case 0xfc : //system realtime message
+        case 0xfe : //system realtime message
+        case 0xff : //system realtime message
+            msgSize = 1;
+            break;
+            //undefine messages
+        default :
+            break;
+    }
+    return msgSize;
+}


Arduino isn’t necessary anymore

Arduino isn’t necessary anymore

--- Arduino/main.ino
+++ Arduino/main.ino
@@ -1,22 +0,0 @@
-#include <SoftwareSerial.h>
-
-#define RX_PIN 10
-#define TX_PIN 11
-
-SoftwareSerial SerialFS20(RX_PIN, TX_PIN);
-
-void setup() {
-	Serial.begin(38400);
-	SerialFS20.begin(38400);
-}
-
-void serialEvent() {
-	SerialFS20.write(Serial.read());
-}
-
-void loop() {
-	int i = SerialFS20.read();
-	if(i != -1) {
-		Serial.write(i & 0xFF);
-	}
-}


stubbing out PID and calibration

stubbing out PID and calibration

--- Firmware/JBC-Soldering-Controller/JBC-Soldering-Controller.ino
+++ Firmware/JBC-Soldering-Controller/JBC-Soldering-Controller.ino
@@ -53,6 +53,14 @@
 };
 //EEMEM tells the compiler that the object resides in the EEPROM
 NVOL nvol EEMEM;
+
+//Hard-coded calibration points.  TODO: make these not hard-coded
+#define NUM_CAL_POINTS 4
+//uint16_t microvolts [NUM_CAL_POINTS] = {0,10,20,30,40,50};
+uint16_t adc_reading [NUM_CAL_POINTS] = {283,584,919,1098};
+uint16_t deg_c [NUM_CAL_POINTS] = {105,200,300,345};
+
+//x = multiMap2(raw, adc_reading, deg_c, NUM_CAL_POINTS);

 //Volatile Variables used by the interrupt handlers
 volatile int16_t adc_value=0;          //ADC value read by ADS1118
@@ -182,6 +190,8 @@
    //read back from the ADC while simultaneously changing the config to start a oneshot read of internal temp)
    fastDigitalWrite(CS, LOW);
    adc_value=SPI.transfer16(ADS1118_SINGLE_SHOT_INTERNAL_TEMPERATURE);
+   myPID.Compute();
+   //TODO: update the PWM duty
    fastDigitalWrite(CS, HIGH);
   }
   //every other interrupt will be a rising edge, we need to keep track of which is which
@@ -299,3 +309,25 @@
   Serial.println(ADS1118_INT_TEMP_C(0x3B00<<2));
   delay(5000);
   */
+
+
+  // note: the _in array should have increasing values
+//multimap2 allows for extrapolation if the input value is outside the bounds of the lookup array
+int multiMap2(int val, int* _in, int* _out, uint8_t size)
+{
+  // take care the value is within range
+  // val = constrain(val, _in[0], _in[size-1]);
+  if (val <= _in[0]) return _out[0];
+  //if (val >= _in[size-1]) return _out[size-1];  //extrapolate the value using the last 2 xy pairs.
+  //if (val >= _in[size-1]) return _out[size-1];  //extrapolate the value using the last 2 xy pairs.
+
+  // search right interval
+  uint8_t pos = 1;  // _in[0] allready tested
+  while(val > _in[pos] && pos<size-1) pos++;
+
+  // this will handle all exact "points" in the _in array
+  if (val == _in[pos]) return _out[pos];
+
+  // interpolate in the right segment for the rest
+  return (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
+}


forgot break, would have been a strange bug

--- rp6control/CommandHandling.ino
+++ rp6control/CommandHandling.ino
@@ -19,7 +19,6 @@
       parseAndSetServerIp(getParamString(sCommand));
       break;
     case MAXSPEED:
-      // check if parameter is correct
       setMaxSpeed(parameter);
     case DIRECTION:
       switch (parameter) {


Resolve the style criticisms in #9 (which addresses a file already added

--- examples/WhackAMole/WhackAMole.ino
+++ examples/WhackAMole/WhackAMole.ino
@@ -25,11 +25,11 @@
 #define ANALOG_PIN_COUNT 9
 const int analogPins[ANALOG_PIN_COUNT] = {30, 29, 28, 27, 26, 25, 24, 23, 2};

-#define RGB_Red 40
-#define RGB_Green 39
-#define RGB_Blue 38
-#define Multiplexer_PIN_COUNT 9
-const int multiplexer_pins[Multiplexer_PIN_COUNT] = {37, 36, 35, 34, 33, 32, 31, 11, 12};
+#define RGB_RED 40
+#define RGB_GREEN 39
+#define RGB_BLUE 38
+#define MULTIPLEXER_PIN_COUNT 9
+const int multiplexer_pins[MULTIPLEXER_PIN_COUNT] = {37, 36, 35, 34, 33, 32, 31, 11, 12};

 #define MAXDATALEN 255
 uint8_t header[16];
@@ -42,150 +42,148 @@

 // Set up serial for debugging, and CBL2 for communication
 void setup() {
-  Serial.begin(9600);
-  cbl = new CBL2(lineRed, lineWhite);
-  cbl->resetLines();
+	Serial.begin(9600);
+	cbl = new CBL2(lineRed, lineWhite);
+	cbl->resetLines();
 #ifdef VERBOSE
-  cbl->setVerbosity(true, &Serial);  // Comment this in for message information
+	cbl->setVerbosity(true, &Serial);  // Comment this in for message information
 #endif
-  cbl->setupCallbacks(header, data, MAXDATALEN,
-                      onGetAsCBL2, onSendAsCBL2);
+	cbl->setupCallbacks(header, data, MAXDATALEN, onGetAsCBL2, onSendAsCBL2);
 }

 // Main loop: Let CBL2 event handler do the work
 void loop() {
-  int rval;
-  rval = cbl->eventLoopTick();
-  if (rval && rval != ERR_READ_TIMEOUT) {
-    Serial.print("Failed to run eventLoopTick: code ");
-    Serial.println(rval);
-  }
-
+	int rval;
+	rval = cbl->eventLoopTick();
+	if (rval && rval != ERR_READ_TIMEOUT) {
+		Serial.print("Failed to run eventLoopTick: code ");
+		Serial.println(rval);
+	}
+
 }

 // Takes Led = LED 1-9
-void SetRgbActive(int led){
-    turnOffAllRGBLEDs();
-    digitalWrite(multiplexer_pins[led - 1], HIGH);
-
+void SetRgbActive(int led) {
+	turnOffAllRGBLEDs();
+	digitalWrite(multiplexer_pins[led - 1], HIGH);
 }

-void turnOffAllRGBLEDs(){
-    for(int i = 0; i < Multiplexer_PIN_COUNT; i++) {
-        digitalWrite(multiplexer_pins[i], LOW);
-    }
+void turnOffAllRGBLEDs() {
+	for(int i = 0; i < MULTIPLEXER_PIN_COUNT; i++) {
+		digitalWrite(multiplexer_pins[i], LOW);
+	}
 }

 int onGetAsCBL2(uint8_t type, enum Endpoint model, int datalen) {
 #ifdef VERBOSE
-  Serial.print("Got variable of type ");
-  Serial.print(type);
-  Serial.print(" from endpoint of type ");
-  Serial.println((int)model);
+	Serial.print("Got variable of type ");
+	Serial.print(type);
+	Serial.print(" from endpoint of type ");
+	Serial.println((int)model);
 #endif
-
-  if (type != 0x5D) { //VarTypes82::VarRList) ???
-    return -1;  //If you are not a list we do not want you ABORT
-  }
-  int list_len = data[0] | (data[1] << 8);
-  switch(list_len) {
-    case 1:{  //If we are a control structure
-        int value = (int)TIVar::realToFloat8x(&data[2], model);  // Get element
-        switch(value){
-            case 0:{  // Turns off all LEDS
+
+	if (type != 0x5D) { //VarTypes82::VarRList) ???
+		return -1;  //If you are not a list we do not want you ABORT
+	}
+	int list_len = data[0] | (data[1] << 8);
+	switch(list_len) {
+		case 1: {  //If we are a control structure
+			int value = (int)TIVar::realToFloat8x(&data[2], model);  // Get element
+			switch(value) {
+				case 0:{  // Turns off all LEDS
 #ifdef VERBOSE
-                Serial.println("Turning off all LEDs");
+					Serial.println("Turning off all LEDs");
 #endif
-                turnOffAllRGBLEDs();
-                return 0;
-            }
-            case 10:  // Unimplemented yet. But room to grow for single commands is here.
-            case 11:  //
-            default:
-                return -1;
-        }
-    }
-    case 4:{  // RGB Control structure
-             // {N,R,G,B} Where N is LED and RGB=Analog Values for each color
-
-        turnOffAllRGBLEDs();  //First we turn off the multiplexer
-
-        int Offset = 2;  //Start us after the size bytes
-        int NewLed = (int)TIVar::realToFloat8x(&data[Offset], model);  // Get element
-
-        Offset += TIVar::sizeOfReal(model);
-        int val_red = (int)TIVar::realToFloat8x(&data[Offset], model);
-        Offset += TIVar::sizeOfReal(model);
-        int val_green = (int)TIVar::realToFloat8x(&data[Offset], model);
-        Offset += TIVar::sizeOfReal(model);
-        int val_blue = (int)TIVar::realToFloat8x(&data[Offset], model);
-
+					turnOffAllRGBLEDs();
+					return 0;
+				}
+				case 10:  // Unimplemented yet. But room to grow for single commands is here.
+				case 11:  //
+				default:
+					return -1;
+			}
+		}
+		case 4: {  // RGB Control structure
+		           // {N,R,G,B} Where N is LED and RGB=Analog Values for each color
+			turnOffAllRGBLEDs();  //First we turn off the multiplexer
+
+			int offset = 2;  //Start us after the size bytes
+			int new_led = (int)TIVar::realToFloat8x(&data[offset], model);  // Get element
+
+			offset += TIVar::sizeOfReal(model);
+			int val_red = (int)TIVar::realToFloat8x(&data[offset], model);
+			offset += TIVar::sizeOfReal(model);
+			int val_green = (int)TIVar::realToFloat8x(&data[offset], model);
+			offset += TIVar::sizeOfReal(model);
+			int val_blue = (int)TIVar::realToFloat8x(&data[offset], model);
+
 #ifdef VERBOSE
-        Serial.print("Setting LED ");
-        Serial.print(NewLed);
-        Serial.print(" to color (");
-        Serial.print(val_red);
-        Serial.print(',');
-        Serial.print(val_green);
-        Serial.print(',');
-        Serial.print(val_blue);
-        Serial.println(")");
+			Serial.print("Setting LED ");
+			Serial.print(new_led);
+			Serial.print(" to color (");
+			Serial.print(val_red);
+			Serial.print(',');
+			Serial.print(val_green);
+			Serial.print(',');
+			Serial.print(val_blue);
+			Serial.println(")");
 #endif
-        // I don't know why this is inverted. It works.
-        analogWrite(RGB_Red, 255 - val_red);
-        analogWrite(RGB_Green, 255 - val_green);
-        analogWrite(RGB_Blue, 255 - val_blue);
-
-        SetRgbActive(NewLed);  //Turn on the new LED
-        return 0;
-    }
-    default:{  // Gotta Catch Em All!
-        return -1;
-    }
-  }
-
-  return -1;
+			// I don't know why this is inverted. It works.
+			analogWrite(RGB_RED, 255 - val_red);
+			analogWrite(RGB_GREEN, 255 - val_green);
+			analogWrite(RGB_BLUE, 255 - val_blue);
+
+			SetRgbActive(new_led);  //Turn on the new LED
+			return 0;
+		}
+		default: {  // Gotta Catch Em All!
+				return -1;
+		}
+	}
+
+	return -1;
 }

 int onSendAsCBL2(uint8_t type, enum Endpoint model, int* headerlen,
                  int* datalen, data_callback* data_callback)
 {
-  Serial.print("Got request for variable of type ");
-  Serial.print(type);
-  Serial.print(" from endpoint of type ");
-  Serial.println((int)model);
+	Serial.print("Got request for variable of type ");
+	Serial.print(type);
+	Serial.print(" from endpoint of type ");
+	Serial.println((int)model);

-  if (type != VarTypes82::VarRList)
-    return -1; //If we are not a list we do not want you ABORT
+	if (type != VarTypes82::VarRList) {
+		return -1; //If we are not a list we do not want you ABORT
+	}

-     // Compose the VAR header
-  *datalen = 2 + TIVar::sizeOfReal(model) * ANALOG_PIN_COUNT;
-  TIVar::intToSizeWord(*datalen, &header[0]);	// Two bytes for the element count, ANALOG_PIN_COUNT Reals
-                                                // This sets header[0] and header[1]
-  header[2] = 0x04;				// RealList (if you're a TI-85. Bleh.)
-  header[3] = 0x01;				// Name length
-  header[4] = 0x41;				// "A", as per "standard" See http://www.cemetech.net/forum/viewtopic.php?p=224739#224739
-  header[5] = 0x00;				// Zero terminator (remainder of header is ignored)
-  *headerlen = 11;
-
-  // Compose the body of the variable
-  data[0] = ANALOG_PIN_COUNT;
-  data[1] = 0;
-  int offset = 2;
-  for(int i = 0; i < ANALOG_PIN_COUNT; i++) {
-	long value = analogRead(analogPins[i]);
-	// Convert the value, get the length of the inserted data or -1 for failure
-	int rval = TIVar::longToReal8x(value, &data[offset], model);
-	if (rval < 0) {
-		return -1;
+	// Compose the VAR header
+	*datalen = 2 + TIVar::sizeOfReal(model) * ANALOG_PIN_COUNT;
+	TIVar::intToSizeWord(*datalen, &header[0]);	// Two bytes for the element count, ANALOG_PIN_COUNT Reals
+	                                            // This sets header[0] and header[1]
+	header[2] = 0x04;				// RealList (if you're a TI-85. Bleh.)
+	header[3] = 0x01;				// Name length
+	header[4] = 0x41;				// "A", as per "standard" See http://www.cemetech.net/forum/viewtopic.php?p=224739#224739
+	header[5] = 0x00;				// Zero terminator (remainder of header is ignored)
+	*headerlen = 11;
+
+	// Compose the body of the variable
+	data[0] = ANALOG_PIN_COUNT;
+	data[1] = 0;
+	int offset = 2;
+	for(int i = 0; i < ANALOG_PIN_COUNT; i++) {
+		long value = analogRead(analogPins[i]);
+		// Convert the value, get the length of the inserted data or -1 for failure
+		int rval = TIVar::longToReal8x(value, &data[offset], model);
+		if (rval < 0) {
+			return -1;
+		}
+		offset += rval;
 	}
-	offset += rval;
-  }
-  for(int i = 0; i < *datalen; i++) {
-    Serial.print(data[i], HEX);
-	Serial.print(" ");
-  }
-  Serial.println("]]");
+	for(int i = 0; i < *datalen; i++) {
+		Serial.print(data[i], HEX);
+		Serial.print(" ");
+	}
+	Serial.println("]]");

-  return 0;
+	return 0;
 }


Correct pllay_movie

Correct pllay_movie

Correctt the way for making Intent

--- ScriptingAccessory/firmware/play_movie/play_movie.ino
+++ ScriptingAccessory/firmware/play_movie/play_movie.ino
@@ -49,8 +49,7 @@
       Serial.println("import android,time");
       Serial.println("droid = android.Android()");
       Serial.println("droid.makeToast('Play Movie')");
-      Serial.println("droid.startActivityIntent(makeIntent('android.intent.action.VIEW', 'https://docs.google.com/file/d/0B14PZnE7DkYmck9Yc2tlcTZwTnM/edit?usp=sharing'))");
-      //Serial.println("droid.webViewShow('http://youtu.be/0p3vL0zuNYE', True)");
+      Serial.println("droid.startActivityIntent(droid.makeIntent('android.intent.action.VIEW', 'https://docs.google.com/file/d/0B14PZnE7DkYmck9Yc2tlcTZwTnM/edit?usp=sharing').result)");
       state = STATE_WRITE_DONE_FOR_CONNECT;
       break;


decreased goal area requirement

decreased goal area requirement

--- master/master.ino
+++ master/master.ino
@@ -168,7 +168,7 @@

 #define PIXY1_ADDRESS 0x54   // default i2c address

-#define MIN_BLOCK_AREA   1500
+#define MIN_BLOCK_AREA   1000

 PixyI2C pixy1(PIXY1_ADDRESS);


Corrected DST calaculation.

Corrected DST calaculation.

Old implementation set DST at USA change dates.
Now time is calculated for Europe. ( CEST )

--- routines.ino
+++ routines.ino
@@ -41,18 +41,21 @@
 }

 // IsDST(): returns true if during DST, false otherwise
-boolean isDST( int mo, int dy, int dw ) {
-  if ( mo < 3 || mo > 11 ) {
+// For CEST time!!           http://stackoverflow.com/a/22761920
+boolean isDST( int month, int day, int dow ) {
+  if ( month < 3 || month > 11 ) {
     return false;  // January, February, and December are out.
   }
-  if ( mo > 3 && mo < 11 ) {
+  if ( month > 3 && month < 11 ) {
     return true;  // April to October are in
   }
-  int previousSunday = dy - dw;
-  if ( mo == 3 ) {
-    return previousSunday >= 8;  // In March, we are DST if our previous Sunday was on or after the 8th.
+  int previousSunday = day - dow;
+  if ( month == 3 ) {
+    return previousSunday >= 25;  // In March, we are DST if our previous Sunday was on or after the 25th.
   }
-  return previousSunday <= 0; // In November we must be before the first Sunday to be DST. That means the previous Sunday must be before the 1st.
+  if (month == 10) {
+    return previousSunday < 25; // In November we must be before the first Sunday to be DST. That means the previous Sunday must be before the 25st.
+  }
 }

 void setPercentage( const byte thisChannel, const time_t secondsToday ) {


update

update

--- src/Firmware.ino
+++ src/Firmware.ino
@@ -1,11 +1,12 @@
 #include <Arduino.h>
 #include <MeStepper.h>
-#define STATES_COUNT 6
-#define COMMANDS_COUNT 6
+#define SBI(n, b) (n |= _BV(b))
+#define CBI(n, b) (n &= ~_BV(b))
+
 #define POINTS_COUNT 6
 #define PULSES_PER_MM 100
 #define CURVE_SECTION 0.5
-#define NUM_STEPS 100
+#define NUM_STEPS 20
 #define NUM_AXIS 2
 // #define DEBUG true
 enum MOTION_STATE
@@ -14,7 +15,7 @@
     MOTION_NORMAL = 1,
     MOTION_DECELETING = 2
 };
-struct PlannerPoint
+typedef struct
 {
     long err;
     double delta[NUM_AXIS];
@@ -24,13 +25,12 @@
     long targetPosition[NUM_AXIS];
     long targetCount[NUM_AXIS];
     long totalCount = 0;
-    uint8_t enterSpeed = 1;
-    uint8_t speed = 1;
-    uint8_t exitSpeed = 1;
-    uint8_t acceleration = 1;
+    uint16_t speed = 1000;
+    uint16_t exitSpeed = 1000;
+    uint16_t acceleration = 1;
     uint8_t power = 0;
-};
-struct SystemStatus
+} PlannerPoint;
+typedef struct
 {
     bool running = false;
     long currentPosition[NUM_AXIS] = {0, 0};
@@ -38,19 +38,19 @@
     long startPosition[NUM_AXIS];
     long lastPosition[NUM_AXIS] = {0, 0};
     long timerCount = 0;
-    long time = 4250;
     long defaultTime = 4250;
     long defaultAcceleration = 64;
     long defaultAccelCount = 200;
     long defaultDecelCount = 200;
-    long maxTime = 2250;
-    long minTime = 25;
+    long maxSpeed = 100;
+    long minSpeed = 100;
+    long currentSpeed = 1;
     PlannerPoint points[POINTS_COUNT];
     PlannerPoint prevPoint;
     uint8_t power = 0;
-    uint8_t defaultSpeed = 1;
-    uint8_t speed = 100;
-    uint8_t acceleration = 1;
+    uint16_t defaultSpeed = 500;
+    uint16_t speed = 100;
+    uint16_t acceleration = 100;
     uint8_t statesIndex = 0;
     uint8_t statesLength = 0;
     uint8_t plannedIndex = 0;
@@ -58,8 +58,11 @@
     uint8_t isRunningState = MOTION_ACCELETING;
     uint8_t powerPin = 10;
     String buffer = "";
-};
-SystemStatus _sys;
+} SystemStatus;
+static SystemStatus _sys;
+volatile uint8_t plannedLength = 0;
+volatile uint8_t plannedIndex = 0;
+volatile bool busy = false;
 MeStepper steppers[NUM_AXIS] = {MeStepper(SLOT_1), MeStepper(SLOT_2)};

 void setup()
@@ -73,16 +76,20 @@
         steppers[i].disableOutputs();
     }
     Serial.println("opened");
+    setPower(0);
     moveTo(0, 0);
+    for (;;)
+    {
+        if (Serial.available())
+        {
+            char c = Serial.read();
+            parseBuffer(c);
+        }
+    }
 }

 void loop()
 {
-    if (Serial.available())
-    {
-        char c = Serial.read();
-        parseBuffer(c);
-    }
 }
 void parseBuffer(char c)
 {
@@ -97,15 +104,16 @@
     }
 }

+static String vStr = "";
+static double v[8];
 void parseCommand(String cmd)
 {
     cmd.toLowerCase();
     char code = cmd.charAt(0);
     long x1, y1, x2, y2, x3, y3, x4, y4;
-    static double v[8];
-    String vStr = "";
     uint8_t vIndex = 0;
     uint8_t len = cmd.length();
+    vStr = "";
     for (int i = 1; i < len; i++)
     {
         char c = cmd.charAt(i);
@@ -226,74 +234,72 @@
     finishCommand();
 }

-void addMotion(long x, long y, uint8_t power, uint8_t speed, uint8_t acceleration)
-{
-    if (_sys.plannedLength >= POINTS_COUNT)
-    {
-        waitingPushPoint();
-    }
+void addMotion(long x, long y, uint8_t power, uint16_t speed, uint16_t acceleration)
+{
     PlannerPoint prevPoint = _sys.prevPoint;
-    PlannerPoint nextPoint;
-    nextPoint.targetPosition[0] = x;
-    nextPoint.targetPosition[1] = y;
-    nextPoint.dir[0] = prevPoint.targetPosition[0] < nextPoint.targetPosition[0];
-    nextPoint.dir[1] = prevPoint.targetPosition[1] < nextPoint.targetPosition[1];
-    nextPoint.targetCount[0] = abs(nextPoint.targetPosition[0] - prevPoint.targetPosition[0]);
-    nextPoint.targetCount[1] = abs(nextPoint.targetPosition[1] - prevPoint.targetPosition[1]);
-    nextPoint.delta[0] = (nextPoint.targetCount[0]);
-    nextPoint.delta[1] = (nextPoint.targetCount[1]);
-    nextPoint.totalCount = nextPoint.delta[0] + nextPoint.delta[1];
-    nextPoint.enterSpeed = _sys.plannedIndex > 0 ? prevPoint.exitSpeed : _sys.defaultSpeed;
-    nextPoint.speed = fmax(1, speed);
-    prevPoint.exitSpeed = fmax(1, sqrt(nextPoint.speed));
-    nextPoint.acceleration = acceleration;
-    long dist = sqrt(nextPoint.delta[0] * nextPoint.delta[0] + nextPoint.delta[1] * nextPoint.delta[1]) / 2;
-    nextPoint.accelCount = nextPoint.totalCount - min(dist, _sys.defaultAccelCount);
-    nextPoint.decelCount = min(dist, _sys.defaultDecelCount);
-    nextPoint.power = power;
-    nextPoint.err = (nextPoint.delta[0] > nextPoint.delta[1] ? nextPoint.delta[0] : -nextPoint.delta[1]) / 2;
-    _sys.points[_sys.plannedIndex] = nextPoint;
-    _sys.prevPoint = nextPoint;
-    _sys.plannedIndex++;
-    _sys.plannedLength++;
+
+    _sys.points[plannedIndex].targetPosition[0] = x;
+    _sys.points[plannedIndex].targetPosition[1] = y;
+    _sys.points[plannedIndex].dir[0] = prevPoint.targetPosition[0] < _sys.points[plannedIndex].targetPosition[0];
+    _sys.points[plannedIndex].dir[1] = prevPoint.targetPosition[1] < _sys.points[plannedIndex].targetPosition[1];
+    _sys.points[plannedIndex].targetCount[0] = abs(_sys.points[plannedIndex].targetPosition[0] - prevPoint.targetPosition[0]);
+    _sys.points[plannedIndex].targetCount[1] = abs(_sys.points[plannedIndex].targetPosition[1] - prevPoint.targetPosition[1]);
+    _sys.points[plannedIndex].delta[0] = (_sys.points[plannedIndex].targetCount[0]);
+    _sys.points[plannedIndex].delta[1] = (_sys.points[plannedIndex].targetCount[1]);
+    _sys.points[plannedIndex].totalCount = _sys.points[plannedIndex].delta[0] + _sys.points[plannedIndex].delta[1];
+    _sys.points[plannedIndex].speed = speed;
+    if (plannedIndex > 1)
+    {
+        _sys.points[plannedIndex - 1].exitSpeed = _sys.points[plannedIndex].speed;
+    }
+    _sys.points[plannedIndex].acceleration = acceleration;
+    long dist = sqrt(_sys.points[plannedIndex].delta[0] * _sys.points[plannedIndex].delta[0] + _sys.points[plannedIndex].delta[1] * _sys.points[plannedIndex].delta[1]) / 2;
+    _sys.points[plannedIndex].accelCount = _sys.points[plannedIndex].totalCount - min(dist, _sys.defaultAccelCount);
+    _sys.points[plannedIndex].decelCount = min(dist, _sys.defaultDecelCount);
+    _sys.points[plannedIndex].power = power;
+    _sys.points[plannedIndex].err = (_sys.points[plannedIndex].delta[0] > _sys.points[plannedIndex].delta[1] ? _sys.points[plannedIndex].delta[0] : -_sys.points[plannedIndex].delta[1]) / 2;
+
+    _sys.prevPoint = _sys.points[plannedIndex];
+    plannedIndex += 1;
+    plannedLength += 1;
 }
 void finishCommand()
 {
-    if (commandsLength() < POINTS_COUNT)
-    {
-        Serial.print("ok:");
-        Serial.println(commandsLength());
-    }
+    Serial.print("ok:");
+    if (commandsLength() < 1)
+    {
+        closePower();
+    }
+    Serial.println(commandsLength());
 }
 int8_t commandsLength()
 {
-    return _sys.plannedLength;
+    return plannedLength;
 }
 void setPower(uint8_t power)
 {
-    _sys.power = fmaxf(0.0, fminf(100.0, power));
-}
-void setSpeed(uint8_t speed)
-{
-    _sys.speed = fmaxf(0.0, fminf(100.0, speed));
-}
-void setAccel(uint8_t accel)
-{
-    _sys.acceleration = fmaxf(0.0, fminf(100.0, accel));
+    _sys.power = power;
+}
+void setSpeed(uint16_t speed)
+{
+    _sys.speed = speed;
+}
+void setAccel(uint16_t accel)
+{
+    _sys.acceleration = accel;
 }
 void firePower(uint8_t power)
 {
     pinMode(_sys.powerPin, OUTPUT);
-    analogWrite(_sys.powerPin, fmaxf(0.0, fminf(255.0, power)));
+    analogWrite(_sys.powerPin, power);
 }
 void openPower()
 {
-    pinMode(_sys.powerPin, OUTPUT);
-    analogWrite(_sys.powerPin, _sys.power * 2.55);
+    firePower(_sys.power);
 }
 void closePower()
 {
-    analogWrite(_sys.powerPin, 0);
+    firePower(0);
 }
 /**
  * motion control in Timer
@@ -301,27 +307,25 @@

 void shiftPlanned()
 {
-    if (_sys.plannedLength > 0)
-    {
-        for (int i = 0; i < _sys.plannedLength - 1; i++)
+    if (plannedLength > 0)
+    {
+        for (int i = 0; i < plannedLength - 1; i++)
         {
             _sys.points[i] = _sys.points[i + 1];
         }
-        _sys.plannedIndex--;
-        _sys.plannedLength--;
-    }
-    if (_sys.plannedLength <= 0)
-    {
-        finishCommand();
+        plannedIndex -= 1;
+        plannedLength -= 1;
     }
 }
 void lockTimer()
 {
-    noInterrupts();
+    cli();
+    // noInterrupts();
 }
 void unlockTimer()
 {
-    interrupts();
+    sei();
+    // interrupts();
 }
 void setRun()
 {
@@ -337,51 +341,83 @@
 }
 void motionFinish()
 {
-    if (_sys.plannedLength > 0)
-    {
-        lockTimer();
+    if (plannedLength > 0)
+    {
         shiftPlanned();
-        unlockTimer();
-        firePower(_sys.points[0].power);
-        _sys.minTime = fmax(25, 100.0 / (_sys.points[0].speed / 100.0));
-        _sys.maxTime = fmin(_sys.defaultTime, _sys.defaultTime / (_sys.points[0].exitSpeed / 50.0));
-    }
-}
-void waitingPushPoint()
-{
-    while (true)
-    {
-        if (_sys.plannedLength < POINTS_COUNT)
-        {
-            break;
-        }
-        delay(200);
+        if (plannedLength > 0)
+        {
+            firePower(_sys.points[0].power);
+            _sys.maxSpeed = _sys.points[0].speed;
+            _sys.minSpeed = fmax(10, _sys.points[0].exitSpeed);
+        }
 #ifdef DEBUG
-        String str = "waiting:";
-        str += _sys.plannedLength;
+        String str = "finish:";
+        str += plannedLength;
         Serial.println(str);
 #endif
     }
 }
+void waitingForBusy()
+{
+    for (;;)
+    {
+        int v = plannedLength;
+        if (v < POINTS_COUNT)
+        {
+            // #ifdef DEBUG
+            //             String str = "exiting:";
+            //             str += plannedLength;
+            //             Serial.println(str);
+            // #endif
+            return;
+        }
+        else
+        {
+            // for (int i = 0; i < 1000; i++)
+            // {
+            //     noInterrupts();
+            //     int v = plannedLength;
+            //     interrupts();
+            //     if (v < POINTS_COUNT)
+            //     {
+            //         break;
+            //     }
+            //     delay(1);
+            // }
+        }
+        // delay(1);
+    }
+}
 void initTimer()
 {
-    lockTimer(); // disable all interrupts
+    // lockTimer(); // disable all interrupts
+    // TCCR1A = 0;
+    // TCCR1B = 0;
+    // TCNT1 = 0;
+    cli();
     TCCR1A = 0;
     TCCR1B = 0;
     TCNT1 = 0;
-
-    OCR1A = _sys.time;      // compare match register 16MHz/256/1Hz
+    OCR1A = 2000;           // compare match register 16MHz/256/1Hz
     TCCR1B |= (1 << WGM12); // CTC mode
     TCCR1B |= (1 << CS11);
     // TCCR1B |= (1 << CS10);   // 64 prescaler
     TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
-
-    unlockTimer(); // enable all interrupts
+    sei();
+    // unlockTimer(); // enable all interrupts
 }
 int tt = 0;
 ISR(TIMER1_COMPA_vect)
 {
+    if (busy)
+    {
+        return;
+    }
+    sei();
+    busy = true;
     run();
+    busy = false;
+    cli();
 }
 void run()
 {
@@ -392,10 +428,11 @@
 }
 bool motionStep()
 {
-    if (_sys.plannedLength < 1)
+    if (plannedLength < 1)
     {
         return false;
     }
+    firePower(_sys.points[0].power);
     long distX = _sys.points[0].delta[0];
     long distY = _sys.points[0].delta[1];
     if (distX <= 0 && distY <= 0)
@@ -430,45 +467,43 @@
 }
 void nextWait()
 {
-    if (_sys.points[0].totalCount > _sys.points[0].accelCount)
-    {
-        _sys.isRunningState = MOTION_ACCELETING;
-    }
-    else if (_sys.points[0].totalCount > _sys.points[0].decelCount)
-    {
-        _sys.isRunningState = MOTION_NORMAL;
-    }
-    else
-    {
-        _sys.isRunningState = MOTION_DECELETING;
-    }
     if (tt % 2 == 0)
     {
+        if (_sys.points[0].totalCount > _sys.points[0].accelCount)
+        {
+            _sys.isRunningState = MOTION_ACCELETING;
+        }
+        else if (_sys.points[0].totalCount > _sys.points[0].decelCount)
+        {
+            _sys.isRunningState = MOTION_NORMAL;
+        }
+        else
+        {
+            _sys.isRunningState = MOTION_DECELETING;
+        }
         switch (_sys.isRunningState)
         {
         case MOTION_ACCELETING:
         {
-            if (_sys.time > _sys.minTime)
+            if (_sys.currentSpeed < _sys.maxSpeed)
             {
-                _sys.time -= _sys.defaultAcceleration;
-                if (_sys.time < _sys.minTime)
+                _sys.currentSpeed += _sys.acceleration;
+                if (_sys.currentSpeed > _sys.maxSpeed)
                 {
-                    _sys.time = _sys.minTime;
-                }
-                else
-                {
+                    _sys.currentSpeed = _sys.maxSpeed;
                 }
             }
             break;
         }
         case MOTION_DECELETING:
         {
-            if (_sys.time < _sys.maxTime)
+            if (_sys.currentSpeed > _sys.minSpeed)
             {
-                _sys.time += _sys.defaultAcceleration;
-            }
-            else
-            {
+                _sys.currentSpeed -= _sys.acceleration;
+                if (_sys.currentSpeed < _sys.minSpeed)
+                {
+                    _sys.currentSpeed = _sys.minSpeed;
+                }
             }
             break;
         }
@@ -479,7 +514,7 @@
         }
         }
         tt = 0;
-        OCR1A = _sys.time;
+        OCR1A = 1600000 / _sys.currentSpeed - 1;
     }
     tt++;
 }
@@ -489,7 +524,7 @@

 void moveTo(long x, long y)
 {
-    waitingPushPoint();
+    waitingForBusy();
 #ifdef DEBUG
     String str = "move:";
     str += x;
@@ -499,12 +534,12 @@
 #endif
     _sys.startPosition[0] = x;
     _sys.startPosition[1] = y;
-    _sys.time = _sys.defaultTime;
+    _sys.currentSpeed = _sys.defaultSpeed;
     addMotion(x, y, 0, _sys.speed, _sys.acceleration);
 }
 void lineTo(long x, long y)
 {
-    waitingPushPoint();
+    waitingForBusy();
 #ifdef DEBUG
     String str = "line:";
     str += x;
@@ -587,13 +622,13 @@
     double fx, fy;
     for (int i = 0; i < step; i++)
     {
-        float t = i / step;
-        float u = 1 - t;
+        float t = (float)i / (float)step;
+        float u = 1.0 - t;
         fx = x0 * u * u + x1 * 2 * u * t + x2 * t * t;
         fy = y0 * u * u + y1 * 2 * u * t + y2 * t * t;
-        lineTo(fx, fy);
-    }
-    lineTo(x2, y2);
+        lineTo(floorf(fx * 100) / 100, floorf(fy * 100) / 100);
+    }
+    lineTo(floorf(x2 * 100) / 100, floorf(y2 * 100) / 100);
 }

 void arc(long sx, long sy, long cx, long cy, long ex, long ey, bool ccw)


Clean up. Modified poll to happen once a second.

--- module/module.ino
+++ module/module.ino
@@ -1,12 +1,11 @@
 #include <SoftwareSerial.h>
-#include "rfid.h"
+#include "RFID.h"

 SoftwareSerial RDM880(RDM880_RX, RDM880_TX);

 const int ledPin = 13;
 const int signalPin = 4;
 const int speakerPin = 8;
-const int debounce = 25;
 const int quota = 3600;
 const int pollInterval = 1000;
 const bool reject = true;
@@ -29,7 +28,7 @@

 	// Scan for RFID tags
 	Serial.println("Scanning...");
-	while (responseFlag == false) {
+	while (!responseFlag) {
 		getSerialNumber();
 		delay(waitforSerialResponse);
 		responseFlag = getResponse(readData);
@@ -100,148 +99,6 @@
 	}
 }

-bool getResponse(unsigned char response[]) {
-	int i = 0;
-
-	while (RDM880.available()) {
-		response[i] = RDM880.read();
-		/*Serial.print(response[i], HEX);
-		Serial.print(" ");*/
-		i++;
-	}
-	//Serial.println();
-
-	// 3rd byte of response packet is the STATUS byte, 0x00 means OK
-	if (response[statusOffset] == 0x00)
-		return true;
-	else
-		return false;
-}
-/*
-	Reads time data from card and stores it in one 4 byte chunk
-
-	Param: readData - array containing all bytes read from card
-
-	Function: Time is encoded as four 1 byte chunks 0xAA 0xBB 0xCC 0xDD.
-			  existingTime is one 4 byte chuck 0x00000000
-			  This function XORs the most significant byte with each time byte,
-			  and left shifts it 1 byte size every iteration.
-			  First iteration: 0x000000AA, Second iteration: 0x0000AABB, etc.
-
-	Returns: existing time from card
-*/
-unsigned long getTime (unsigned char readData[]) {
-	int i = 0;
-	unsigned long existingTime = 0;
-
-	for (i = 0; i < numTimeBytes; i++) {
-		existingTime = (existingTime << 8) ^ readData[i + timeOffset];
-	}
-
-	return existingTime;
-
-}
-
-/*
-	Calculates the checksum of a packet to ensure data integrity.
-
-	Param: A[] 		- array containing all bytes in a packet
-		   numBytes - number of bytes in the array
-
-	Returns: checksum
-
-*/
-unsigned char checksum(unsigned char A[], int numBytes) {
-	int i = 0;
-	unsigned char BCC = A[i];
-
-	for(i = 1; i < numBytes; i++) {
-		BCC = BCC ^ A[i];
-	}
-
-	return BCC;
-}
-
-/*
-	Gets the serial number of an RFID tag.
-
-	Post: Response packet contains OK status and serial number of the tag selected
-
-*/
-void getSerialNumber(void) {
-	unsigned char A[] = { 0x00, 0x03, CMD_GET_SNR, 0x26, 0x00 };
-	unsigned char BCC = checksum( A, sizeof(A)/sizeof(A[0]) );
-	unsigned char CMD[] = { STX, 0x00, 0x03, CMD_GET_SNR, 0x26, 0x00, BCC, ETX };
-	RDM880.write( CMD, sizeof(CMD)/sizeof(CMD[0]) );
-}
-
-/*
-	Writes to the selected RFID tag.
-
-	Param: numBlocks 	- number of 16 byte blocks to be written to (max 3)
-		   startAddress - address of the first block (0 - 63)
-		   time 		- data to be written
-
-	Post: Response packet contains OK status and serial number of the tag written to.
-
-	NOTE: Block 0 contains manufacturer data.
-		  Sector trailers (multiples of 4) should also not be written to.
-		  i.e. Block 3, 7 and 11 are sector trailers that contain authentication keys.
-
-*/
-
-void writeCard(unsigned char numBlocks, unsigned char startAddress, unsigned long time) {
-	int i = 0;
-	int j = 24;
-
-	// prepare data to be written, time is in format 0xAABBCCDD
-	// timeByte is in format { 0xAA, 0xBB, 0xCC, 0xDD }
-	unsigned char timeByte[numTimeBytes];
-	for(i = 0; i < numTimeBytes; i++) {
-		timeByte[i] = (time >> j) & MSB;
-		j -= 8;
-	}
-
-	unsigned char A[] = { 0x00, 0x1A, CMD_WRITE, 0x01, numBlocks, startAddress,
-						keyA[0], keyA[1], keyA[2], keyA[3], keyA[4], keyA[5],
-						0xDD, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-						timeByte[0], timeByte[1], timeByte[2], timeByte[3] };
-	unsigned char BCC = checksum( A, sizeof(A)/sizeof(A[0]) );
-	unsigned char CMD[] = { STX, 0x00, 0x1A, CMD_WRITE, 0x01, numBlocks, startAddress,
-						keyA[0], keyA[1], keyA[2], keyA[3], keyA[4], keyA[5],
-						0xDD, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-						timeByte[0], timeByte[1], timeByte[2], timeByte[3],
-						BCC, ETX };
-
-	/*Serial.print("Attempting to write block ");
-	Serial.println(startAddress);*/
-
-	RDM880.write( CMD, sizeof(CMD)/sizeof(CMD[0]) );
-}
-
-/*
-	Reads the selected RFID tag.
-
-	Param: numBlocks	- number of 16 byte blocks to be read (max 3)
-		   startAddress - address of first block to read (0 - 63)
-
-	Post: Response packet contains serial number of selected tag and data.
-
-*/
-void readCard(unsigned char numBlocks, unsigned char startAddress) {
-	int i = 0;
-	unsigned char A[] = { 0x00, 0x0A, CMD_READ, 0x01, numBlocks, startAddress,
-						keyA[0], keyA[1], keyA[2], keyA[3], keyA[4], keyA[5] };
-	unsigned char BCC = checksum( A, sizeof(A)/sizeof(A[0]) );
-	unsigned char CMD[] = { STX, 0x00, 0x0A, CMD_READ, 0x01, numBlocks, startAddress,
-                          keyA[0], keyA[1], keyA[2], keyA[3], keyA[4], keyA[5], BCC, ETX };
-
-	Serial.println("Reading data...");
-	//Serial.println(startAddress);
-
-	RDM880.write( CMD, sizeof(CMD)/sizeof(CMD[0]) );
-
-}

 /*
 	Function that waits for a control signal to go high and counts time
@@ -253,25 +110,28 @@
 unsigned long accumulator(void) {
 	unsigned long startTime, endTime = 0;
 	int lastPolltime = millis();
+	int pollCounter = 0;
 	int signalState;
 	int previousState;

 	while (1) {
-		// poll for card
-		getSerialNumber();
-		if(!getResponse(readData)) {
-			delay(cardTimeout);
+		// poll for card every second
+		if ((millis() - lastPolltime) >= pollInterval) {
+			getSerialNumber();
 			if(!getResponse(readData)) {
-				soundFeedback(reject);
-				Serial.println("Card not detected.");
-				return 0;
+				pollCounter += 1;
+				if(pollCounter == 4) {
+					soundFeedback(reject);
+					Serial.println("Card not detected.");
+					return 0;
+				}
 			}
+			lastPolltime = millis();
 		}

 		// read signal state
 		signalState = digitalRead(signalPin);
 		delay(debounce);
-
 		// debounce check
 		if(signalState == digitalRead(signalPin)) {
 			// check for new ON signal aka rising edge
@@ -294,6 +154,5 @@
 				previousState = signalState;
 			}
 		}
-
 	}
 }


Testing LED blink on poll

Testing LED blink on poll

--- module/module.ino
+++ module/module.ino
@@ -146,7 +146,7 @@
 unsigned long accumulator(unsigned char serialNumber[], unsigned long elapsedTime) {
 	// some variables used in this scope
 	unsigned long startTime = 0;
-	unsigned long lastPollTime = 0;
+	unsigned long lastPollTime, lastBlink = 0;
 	unsigned int periodX, periodY;
 	unsigned int pollCounter = 0;
 	int signals[] = { 0, 0, 0, 0, 0 };
@@ -163,7 +163,7 @@
 			sendCommand(CMD_GET_SNR, blockID, machineID, keyA, NULL);
 			// if card is missing, increment a counter and blink LED?? too slow
 			if (!getResponse(serialNumber)) {
-				digitalWrite(ledPin, (digitalRead(ledPin) == HIGH ? LOW : HIGH));
+				//digitalWrite(ledPin, (digitalRead(ledPin) == HIGH ? LOW : HIGH));
 				pollCounter += 1;
 				// if the counter reaches a specified timeout, return
 				if (pollCounter == pollTimeout) {
@@ -250,6 +250,10 @@
 	    	digitalWrite(interlock, HIGH);
 			lastPollTime = millis();
 		}
+
+		if ( (pollCounter > 0) && (timeSince(lastBlink) > 500) ) {
+			digitalWrite(ledPin, (digitalRead(ledPin) == HIGH ? LOW : HIGH));
+		}
 	}
 }
 /*void soundFeedback(bool isReject) {


Add check for unsupported band

Add check for unsupported band

--- examples/raw-feather/raw-feather.ino
+++ examples/raw-feather/raw-feather.ino
@@ -242,6 +242,8 @@

   // default tx power for US: 21 dBm
   LMIC.txpow = 21;
+#else
+# error Unsupported LMIC regional configuration.
 #endif

   // disable RX IQ inversion


Test autoscroll

Test autoscroll

--- arduino/CommunicationArduino/CommunicationArduino.ino
+++ arduino/CommunicationArduino/CommunicationArduino.ino
@@ -9,12 +9,28 @@
   lcd.init(); // initialize the lcd
   lcd.backlight();
   lcd.print("Setup Arduino"); // Print a message to the LCD.
+
 }

 void loop()
 {
-  if (Serial.available())  {
+  /*if (Serial.available())  {
+    delay(100);
     lcd.clear();
+    lcd.autoscroll();
     lcd.print(Serial.readString());
+  }*/
+  // when characters arrive over the serial port...
+  if (Serial.available()) {
+    // wait a bit for the entire message to arrive
+    delay(100);
+    // clear the screen
+    lcd.clear();
+    lcd.autoscroll();
+    // read all the available characters
+    while (Serial.available() > 0) {
+      // display each character to the LCD
+      lcd.write(Serial.read());
+    }
   }
 }


now version 0.9

now version 0.9


Update feather_code.ino

Update feather_code.ino

--- code/feather_code.ino
+++ code/feather_code.ino
@@ -201,6 +201,7 @@
   uint8_t gndPercent = (uint8_t) ((analogRead(A2) / 33.30F) * 100);
   Serial.println(gndPercent);

+
   //Akkustand auslesen
   float measuredvbat = analogRead(VBATPIN);
   measuredvbat *= 2;    // we divided by 2, so multiply back
@@ -211,6 +212,7 @@
   Serial.println(measuredvbat);
   Serial.println(akkuPercent);

+
   //Werte ins Array schreiben
   sensordata[0] = hightempratureByte;
   sensordata[1] = lowtempratureByte;


Removed neopixel blink on data reception

--- src/arduino/Triangula_Main/Triangula_Main.ino
+++ src/arduino/Triangula_Main/Triangula_Main.ino
@@ -109,8 +109,6 @@
         pixels.show();
         break;
       case ENCODER_READ:
-        pixels.setSolidColour(80, 255, 50);
-        pixels.show();
         encoderData[0] =  (pos_c & 0xff00) >> 8;
         encoderData[1] =  pos_c & 0xff;
         encoderData[2] =  (pos_b & 0xff00) >> 8;
@@ -192,10 +190,10 @@
 // Handle pin change interrupts
 ISR (PCINT0_vect) {
   byte last_read = PINB;
-  byte c = (last_read & 48) >> 4;
+  byte a = (last_read & 48) >> 4;
   byte b = (last_read & 12) >> 2;
   // The wires are swapped over on encoder a (the pink pylon) so we need to swap things!
-  byte a = last_read & 3;
+  byte c = last_read & 3;
   pos_a -= encoderValues[a + (encoder_a << 2)];
   pos_b += encoderValues[b + (encoder_b << 2)];
   pos_c += encoderValues[c + (encoder_c << 2)];


bug fix

bug fix

--- software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
+++ software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
@@ -52,26 +52,26 @@

   // dequeue commands from textQ, then cmdQ
   // textQ will be emptied before processing anything in cmdQ
-  if (dequeueFrom(textQ))
-    dequeueFrom(cmdQ);
-}
-
-static boolean dequeueFrom(CommandQueue q) {
-  if (!q.isEmpty()) {
+  if (dequeueFrom(&textQ))
+    dequeueFrom(&cmdQ);
+}
+
+static boolean dequeueFrom(CommandQueue *q) {
+  if (!q->isEmpty()) {
     // see if we can queue the next command to the bot...  two situations where we can dequeue:
     //   1) if the next command is a movement command, and the bots motion queue isn't full
     //   2) the bot has finished whatever it was doing
     if (
-        ( q.peekAtType() <= LOGO_MOVE_CMDS && !bot.isQFull() )
+        ( q->peekAtType() <= LOGO_MOVE_CMDS && !bot.isQFull() )
         ||
-        !bot.isBusy()
+        ( !bot.isBusy() )
     ) {
         // dequeue and process next command - ultimately passing it over to the bot object for execution
-        doLogoCommand(q.dequeue());
+        doLogoCommand(q->dequeue());
     }
   }
   // return true when this queue is empty
-  return q.isEmpty();
+  return q->isEmpty();
 }

 static void handleCollision(byte collisionData)


analog pin

analog pin

--- src/main.ino
+++ src/main.ino
@@ -21,7 +21,7 @@

 // LOOP //
 void loop() {
-  int emg = analogRead(A0);
+  int emg = analogRead(A4);

   if (emg < 200) {
     allFingers(700);
@@ -29,7 +29,7 @@
     allFingers(2300);
   }
   delay(1000);
-
+}

 // FUNCTIONS //
 void allFingers(int pos) {


New lantern

New lantern

--- trike/trikebox/lantern.ino
+++ trike/trikebox/lantern.ino
@@ -1,22 +1,9 @@
 namespace Lantern {
-  const int snakesCount = 50;
+  const int snakesCount = 10;
   const int circumference = LEDS_PER_ROW;
   int numberOfSparkles = 0;
   bool increasing = true;
   uint8_t hue = 50;
-
-  int curve(int value, int difference, int maximum) {
-    if (value < maximum && increasing) {
-      value += difference;
-    } else if (value > 1) {
-      value -= difference;
-      increasing = false;
-    } else {
-      increasing = true;
-      value += difference;
-    }
-    return value;
-  }

   uint16_t snakes[snakesCount];
   int snake = 0;
@@ -28,14 +15,26 @@
   }

   void lanternPattern() {
+    numberOfSparkles = beatsin16(15, 4, N_LEDS * 0.03);
+
+    EVERY_N_MILLISECONDS(100) {
+      hue -= 1;
+    }
+
     EVERY_N_MILLISECONDS(40) {
       for (int i = 0; i < snakesCount; i++) {
         uint16_t j = snakes[i];
         if (j > 0) {
-          // Different hue for shooting stars
-          Soulmate::led_arr[j] = CHSV(hue + j / 10 + 10, 240, 255);
+          if (j > 1) {
+            Soulmate::led_arr[j-1] = CHSV(hue + j / 10 + 10, 180, 100);
+          }
+          Soulmate::led_arr[j] = CHSV(hue + j / 10 + 10, 180, 180);
+          if (j < N_LEDS - 1) {
+            Soulmate::led_arr[j+1] = CHSV(hue + j / 10 + 10, 180, 100);
+          }

-          snakes[i] += circumference+1;
+          // angle
+          snakes[i] += circumference + 1;
           if (snakes[i] >= N_LEDS) snakes[i] = 0;
         }
       }
@@ -45,9 +44,6 @@
       if (random16(N_LEDS * 0.4) < numberOfSparkles) {
         shootingStar();
       }
-    }
-
-    EVERY_N_MILLISECONDS(10) {
       fade_raw(Soulmate::led_arr, N_LEDS, 1);
     }

@@ -59,14 +55,6 @@
         }
       }
     }
-
-    EVERY_N_MILLISECONDS(200) {
-      numberOfSparkles = curve(numberOfSparkles, 4, N_LEDS * 0.03);
-    }
-
-    EVERY_N_MILLISECONDS(100) {
-      hue -= 1;
-    }
   }
 }


Fixed Number Module #48

Fixed Number Module #48

Made number module sync with count module, and added a threshold to
prevent flickering between numbers

--- Modules/Action/Number/ArduinoCodes/NumberATmega/NumberATmega.ino
+++ Modules/Action/Number/ArduinoCodes/NumberATmega/NumberATmega.ino
@@ -60,21 +60,28 @@
   pinMode(input_pin, INPUT);
 }

-int input_val;
-int number;
-// the loop function runs over and over again forever
+int input_val;      // input value from previous module
+int number;         // current number being displayed
+int change_val;     // value on last state change
+
 void loop() {
   input_val = cutAndMap(input.filteredAnalogRead(AVERAGE), 50, 975, 0, 1023);
-  int pos = cutAndMap(input_val, 0, 1023, 0, 180);

-  number = cutAndMap(input_val, 0, 1023, 0, 9);
+  // only change the number if the value is significantly different from when it was last changed
+  if (abs(change_val - input_val) > 50) {
+    number = input_val / 105;               //using 105 will map 0-1023 to 0-9
+    change_val = input_val;
+  }
+
   write_digit(number);
 }

+/* writes the specified digit to the display */
 void write_digit(int digit) {
   write_pattern(digit_patterns[digit]);
 }

+/* writes the specified anode pattern to the segments */
 void write_pattern(const bool* segments) {
   for (int i = 0; i < 7; i++) {
     if (segments[i] == true) {


Complete refactoring to handle serial exchanges differently.  This commit has a timing problem and the exposure times are way off.

--- DSLR_Controller/DSLR_Controller.ino
+++ DSLR_Controller/DSLR_Controller.ino
@@ -9,14 +9,52 @@
 time in milliseconds.

 Serial Commands to Board:
-E,n,n,nnn -- Expose camera.
-C,n,n     -- Cancel exposure.
-Q         -- Query which cameras are exposing.
+Enn,mmmmmm -- Expose camera for mmmmmm milliseconds.
+C          -- Cancel exposure.  Cancels exposure on both cameras.
+Q          -- Query which cameras are exposing.
+T          -- Query temperature and humidity from DHT22 (only works if camera not exposing)
+O          -- Query orientation (only works if camera not exposing)
 */

-// Constants for Camera Relay
-const int camera1_pin = 2;
-const int camera2_pin = 3;
+char Command[3];
+char Data[7];
+const int bSize = 20;
+char Buffer[bSize];  // Serial buffer
+int ByteCount;
+
+int camera1_pin = 2;
+int camera2_pin = 4;
+
+//Analog read pins
+const int xPin = 0;
+const int yPin = 1;
+const int zPin = 2;
+
+//The minimum and maximum values that came from
+//the accelerometer while standing still
+//You very well may need to change these
+int minVal = 265;
+int maxVal = 402;
+
+//to hold the caculated values
+double x;
+double y;
+double z;
+
+//-----------------------------------------------------------------------------
+// SerialParser
+//-----------------------------------------------------------------------------
+void SerialParser(void) {
+    ByteCount = -1;
+    ByteCount =  Serial.readBytesUntil('\n',Buffer,bSize);
+    if (ByteCount  > 0) {
+        strcpy(Command,strtok(Buffer,","));
+        strcpy(Data,strtok(NULL,","));
+    }
+    memset(Buffer, 0, sizeof(Buffer));   // Clear contents of Buffer
+    Serial.flush();
+}
+

 //-----------------------------------------------------------------------------
 // SETUP
@@ -27,7 +65,6 @@
     while (!Serial) {
     ; // wait for serial port to connect. Needed for Leonardo only
     }
-
     Serial.print("Setup Camera Relay Pins ... ");
     pinMode(camera1_pin, OUTPUT);
     pinMode(camera2_pin, OUTPUT);
@@ -36,60 +73,132 @@
     Serial.println("done!");
 }

+
 //-----------------------------------------------------------------------------
 // MAIN LOOP
 //-----------------------------------------------------------------------------
 void loop() {
-    // if there's any serial available, read it:
-    while (Serial.available() > 0) {
-        int command = Serial.parseInt();
-        // Based on the command, parse the rest of the serial string differently.
-        if (command == 69) {
-            // Expose (E=69) command
-            int camera1 = Serial.parseInt();
-            int camera2 = Serial.parseInt();
-            int exptime_ms = Serial.parseInt();
-            // look for the newline. That's the end of your
-            // sentence:
-            if (Serial.read() == '\n') {
-                // expose camera for exptime_ms milliseconds
-                Serial.print("Starting ");
-                Serial.print(exptime_ms/1000.0);
-                Serial.print(" second exposure");
-                if (camera1 >= 1) {
-                    Serial.print(" on camera1 ");
-                    digitalWrite(camera1_pin, HIGH);
-                    if (camera2 >= 1) { Serial.print("and"); }
+    boolean cam1 = false;
+    boolean cam2 = false;
+    SerialParser();
+    if (Command[0] == 'E') {
+        if (Command[1] == '1') {cam1 = true;}
+        if (Command[1] == '2') {cam2 = true;}
+        if (Command[2] == '1') {cam1 = true;}
+        if (Command[2] == '2') {cam2 = true;}
+        String exptime_ms_string = String(Data);
+        unsigned long exptime_ms = exptime_ms_string.toInt();
+        float exptime_sec = exptime_ms/1000.0;
+        Serial.print("EXP");
+        if (cam1 == true) {Serial.print("1");}
+        if (cam2 == true) {Serial.print("2");}
+        Serial.print(",");
+        Serial.print(exptime_ms);
+        Serial.println('#');
+        if (cam1 == true) {digitalWrite(camera1_pin, HIGH);}
+        if (cam2 == true) {digitalWrite(camera2_pin, HIGH);}
+        // Now go in to loop waiting for exposure time to finish
+        // If a cancel command is received, cancel exposure.
+        unsigned long total_exptime = 0;
+        unsigned long remainder = exptime_ms % 100;
+        unsigned long startTime = millis();
+        while (total_exptime < exptime_ms - remainder) {
+            delay(100);
+            total_exptime = total_exptime + 100;
+            Serial.println(total_exptime);
+            // Look for cancel or query status commands
+            SerialParser();
+            if (ByteCount > 0) {
+                if (Command[0] == 'Q') {
+                    Serial.print("EXP");
+                    if (cam1 == true) {Serial.print("1");}
+                    if (cam2 == true) {Serial.print("2");}
+                    Serial.println('#');
+                } else if (Command[0] == 'X') {
+                    cam1 = false;
+                    cam2 = false;
+                    digitalWrite(camera1_pin, LOW);
+                    digitalWrite(camera2_pin, LOW);
+                    Serial.print("EXP");
+                    if (cam1 == true) {Serial.print("1");}
+                    if (cam2 == true) {Serial.print("2");}
+                    Serial.println('X#');
+                    total_exptime = exptime_ms;
+                } else {
+                    Serial.println('?#');
                 }
-                if (camera2 >= 1) {
-                    Serial.print(" on camera2 ");
-                    digitalWrite(camera2_pin, HIGH);
-                }
-                Serial.print("... ");
-                // Now go in to loop waiting for exposure time to finish
-                // If a cancel command is received, cancel exposure.
-                int total_exptime = 0;
-                int remainder = total_exptime % 100;
-                int n_loops = (total_exptime - remainder) / 100;
-                for (int index = 0; index < n_loops; index++) {
-                    delay(100);
-                    total_exptime = total_exptime + 100;
-                    // Look for cancel command
-                }
-                delay(remainder);
-                // Set pins low (stop exposure)
-                digitalWrite(camera1_pin, LOW);
-                digitalWrite(camera2_pin, LOW);
-                Serial.println("done");
             }
         }
-        if (command == 67) {
-            // Cancel (C=67) command
-        }
-        if (command == 81) {
-            // Query (Q=81) command
-        }
+        delay(remainder);
+        total_exptime = total_exptime + remainder;
+        // Set pins low (stop exposure)
+        cam1 = false;
+        cam2 = false;
+        digitalWrite(camera1_pin, LOW);
+        digitalWrite(camera2_pin, LOW);
+        unsigned long elapsed = millis() - startTime;
+        Serial.println(elapsed);
+    } else if (Command[0] == 'Q') {
+        Serial.print("EXP");
+        Serial.println('#');
+    } else if (Command[0] == 'X') {
+        Serial.print("EXP");
+        Serial.println('#');
+    } else if (Command[0] == 'T') {
+        //
+    } else if (Command[0] == 'O') {
+        queryOrientation();
+    } else if (Command[0] != ' ') {
+        Serial.println('#');
     }
+    Command[0] = ' ';
+    Command[1] = '0';
+    Command[2] = '0';
+    Data[0] = '0';
+    Data[1] = '0';
+    Data[2] = '0';
+    Data[3] = '0';
+    Data[4] = '0';
+    Data[5] = '0';
+    Data[6] = '0';
     delay(100);
 }

+
+//-----------------------------------------------------------------------------
+// Query Temperature
+//-----------------------------------------------------------------------------
+float queryTemperature(void) {
+
+}
+
+
+//-----------------------------------------------------------------------------
+// Query Orientation
+//-----------------------------------------------------------------------------
+float queryOrientation(void) {
+  //read the analog values from the accelerometer
+  int xRead = analogRead(xPin);
+  int yRead = analogRead(yPin);
+  int zRead = analogRead(zPin);
+
+  //convert read values to degrees -90 to 90 - Needed for atan2
+  int xAng = map(xRead, minVal, maxVal, -90, 90);
+  int yAng = map(yRead, minVal, maxVal, -90, 90);
+  int zAng = map(zRead, minVal, maxVal, -90, 90);
+
+  //Caculate 360deg values like so: atan2(-yAng, -zAng)
+  //atan2 outputs the value of -π to π (radians)
+  //We are then converting the radians to degrees
+  x = RAD_TO_DEG * (atan2(-yAng, -zAng) + PI);
+  y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI);
+  z = RAD_TO_DEG * (atan2(-yAng, -xAng) + PI);
+
+  //Output the caculations
+  Serial.print("x: ");
+  Serial.print(x);
+  Serial.print(" | y: ");
+  Serial.print(y);
+  Serial.print(" | z: ");
+  Serial.println(z);
+}


correct minor typo

correct minor typo

--- OpenStage/b_nonUserSettableGlobals.ino
+++ OpenStage/b_nonUserSettableGlobals.ino
@@ -24,7 +24,7 @@
 bool locationStored[4]={0,0,0,0};

-// SPEENMAT stores the motor speed for each hat-stick value at each speed mode. These numbers
+// SPEEDMAT stores the motor speed for each hat-stick value at each speed mode. These numbers
 // are calculated once in the setup function and never change during execution. Pre-calculating
 // them is a good way of improving performance during hat-stick motions.
 float SPEEDMAT[128][4];