Set up serial interface

Set up serial interface

Signed-off-by: Mark Knoop <f1b5a91d4d6ad523f2610114591c007e75d15084@markknoop.com>

--- src/sketch.ino
+++ src/sketch.ino
@@ -20,13 +20,38 @@
  * communication commands
  *************************
  */
+#define sReady          6
+#define rEOM            0
 #define rQuery          2
-#define rAccelturn      3
-#define rGlissturn      4
-#define sReady          6
-
-byte serialIncoming   = 0;
+#define rTurn           3
+#define rGliss          4
+#define rTimedTurn      5
+#define rDurationTurn   6
+#define rDurationGliss  7
+#define rForwards       8
+#define rBackwards      9
+#define rRecentre      10
+#define rNoRecentre    11
+#define rSetDuration   12
+#define rDurlength      5
+#define rLength        12
+/*
+ * ranges:
+    13-20  tests
+    21-39  set halfturns
+    40-112 set startpitch
+   120-192 set endpitch
+ */
+
+char serialIncoming[rLength];
+char newDuration[rDurlength];
 int halfTurns         = 1;
+unsigned int duration = 500;
+float startPitch      = 72;
+float endPitch        = 36;
+boolean dir           = true;
+boolean recentre      = true;
+boolean newData       = false;

 void setup() {
     pinMode(LED_BUILTIN, OUTPUT);
@@ -36,7 +61,8 @@
     digitalWrite(dirPin, HIGH);
     Serial.begin(9600);
     findsensor(maxPulse);
-    Serial.write(sReady);
+    //Serial.write(sReady);
+    Serial.println("arduino ready");
 }

 int pitchToPulse(float pitch) {
@@ -47,7 +73,7 @@
 }

 float pitchbyteToMidi(byte pitch) {
-    return (pitch / 2) + 36;
+    return (pitch / 2.0) + 36;
 }

 void flashled() {
@@ -220,7 +246,7 @@
         Serial.println(millis() - starttime);
     } else if (style == 2) {
         // random timed turn
-        int halfturns = random(1, 10);
+        int halfturns = random(1, 4);
         int duration = random(300, 5000);
         Serial.print("halfturns ");
         Serial.print(halfturns, DEC);
@@ -274,39 +300,97 @@
             durationturn(dur, i, i % 2, false);
             Serial.println(millis() - starttime);
         }
+    } else if (style == 6) {
+        // show settings
+        Serial.print("halfturns ");
+        Serial.print(halfTurns, DEC);
+        Serial.print(", duration ");
+        Serial.println(duration, DEC);
+        Serial.print("startpitch ");
+        Serial.print(startPitch, DEC);
+        Serial.print(", endpitch ");
+        Serial.println(endPitch, DEC);
+        Serial.print("direction ");
+        Serial.print(dir, BIN);
+        Serial.print(", recentre ");
+        Serial.println(recentre, BIN);
+    } else {
+        // show test styles
+        Serial.println("13: 0x0d: turn");
+        Serial.println("14: 0x0e: gliss");
+        Serial.println("15: 0x0f: timedturn");
+        Serial.println("16: 0x10: durationturn");
+        Serial.println("17: 0x11: durationgliss");
+        Serial.println("18: 0x12: scale");
+        Serial.println("19: 0x13: show settings");
     }
     delay(333);
 }

+void processdata() {
+    for (byte i=0; i<rLength; i++) {
+        if (serialIncoming[i] == rEOM) {
+            newData = false;
+            return;
+        } else if (serialIncoming[i] == rQuery) {
+            findsensor(maxPulse);
+            //Serial.write(sReady);
+            Serial.println("arduino ready");
+            flashled();
+        } else if (serialIncoming[i] == rTurn) {
+            turn(halfTurns, startPitch, dir);
+        } else if (serialIncoming[i] == rGliss) {
+            gliss(halfTurns, startPitch, endPitch, dir);
+        } else if (serialIncoming[i] == rTimedTurn) {
+            timedturn(duration, halfTurns, dir);
+        } else if (serialIncoming[i] == rDurationTurn) {
+            durationturn(duration, startPitch, dir, recentre);
+        } else if (serialIncoming[i] == rDurationGliss) {
+            durationgliss(duration, startPitch, endPitch, dir, recentre);
+        } else if (serialIncoming[i] == rForwards) {
+            dir = true;
+        } else if (serialIncoming[i] == rBackwards) {
+            dir = false;
+        } else if (serialIncoming[i] == rRecentre) {
+            recentre = true;
+        } else if (serialIncoming[i] == rNoRecentre) {
+            recentre = false;
+        } else if (serialIncoming[i] == rSetDuration) {
+            for (byte d=0; d<rDurlength; d++) {
+                newDuration[d] = serialIncoming[++i];
+            }
+            duration = atoi(newDuration);
+        } else if (serialIncoming[i] < 21) {
+            test(serialIncoming[i] - 13);
+        } else if (serialIncoming[i] < 40) {
+            halfTurns = serialIncoming[i] - 20;
+        } else if (serialIncoming[i] < 112) {
+            startPitch = pitchbyteToMidi(serialIncoming[i] - 40);
+        } else if (serialIncoming[i] < 120) {
+            true;
+        } else if (serialIncoming[i] < 192) {
+            endPitch = pitchbyteToMidi(serialIncoming[i] - 120);
+        }
+    }
+}
+
+void receivedata() {
+    static byte idx = 0;
+    char rc;
+    if (Serial.available() > 0) {
+        rc = Serial.read();
+        serialIncoming[idx] = rc;
+        if (rc != rEOM) {
+            idx++;
+            if (idx >= rLength) idx = rLength - 1;
+        } else {
+            idx = 0;
+            newData = true;
+        }
+    }
+}
+
 void loop() {
-    test(4);
-    /*
-    if (Serial.available()) {
-        serialIncoming = Serial.read();
-
-        if (serialIncoming == rQuery) {
-            findsensor(slowestPulse);
-            Serial.write(sReady);
-            flashled();
-        } else if (serialIncoming == rAccelturn) {
-            accelturn(halfTurns, minPulse, maxPulse, accelSteps);
-        } else if (serialIncoming == rGlissturn) {
-            glissturn(halfTurns, startPulse, endPulse, maxPulse, accelSteps);
-        } else if (serialIncoming < 11) {
-            flashled();
-        } else if (serialIncoming < 21) {
-            halfTurns = serialIncoming - 10;
-        } else if (serialIncoming < 41) {
-            minPulse = map(serialIncoming, 21, 40, fastestPulse, fastestStart);
-        } else if (serialIncoming < 61) {
-            maxPulse = map(serialIncoming, 41, 60, fastestStart, slowestPulse);
-        } else if (serialIncoming < 81) {
-            startPulse = map(serialIncoming, 61, 80, fastestPulse, slowestPulse);
-        } else if (serialIncoming < 101) {
-            endPulse = map(serialIncoming, 81, 100, fastestPulse, slowestPulse);
-        } else if (serialIncoming < 121) {
-            accelSteps = map(serialIncoming, 101, 120, halfTurnSteps/4, halfTurnSteps/2);
-        }
-    }
-    */
-}
+    receivedata();
+    if (newData) processdata();
+}


Update Magnetmeter.

Update Magnetmeter.

--- examples/read9axis/read9axis.ino
+++ examples/read9axis/read9axis.ino
@@ -4,6 +4,7 @@
 FaBo9Axis fabo9axis;

 void setup() {
+  Serial.begin(9600);
   // デバイス初期化
   Serial.println("Checking I2C device...");
   if (fabo9axis.searchDevice()) {
@@ -26,5 +27,29 @@
   fabo9axis.readMagnetXYZ(&mx, &my, &mz);
   temp = fabo9axis.readTemperature();

+  Serial.print("ax: ");
+  Serial.print(ax);
+  Serial.print(" ay: ");
+  Serial.print(ay);
+  Serial.print(" az: ");
+  Serial.println(az);
+
+  Serial.print("gx: ");
+  Serial.print(gx);
+  Serial.print(" gy: ");
+  Serial.print(gy);
+  Serial.print(" gz: ");
+  Serial.println(az);
+
+  Serial.print("mx: ");
+  Serial.print(mx);
+  Serial.print(" my: ");
+  Serial.print(my);
+  Serial.print(" mz: ");
+  Serial.println(mz);
+
+  Serial.print("temp: ");
+  Serial.println(temp);
+
   delay(1000);
 }


Trying to get debug output w/out using Arduino IDE.

--- xy.ino
+++ xy.ino
@@ -1,5 +1,33 @@
 // Compile and run with:
 // arduino --upload --board arduino:avr:uno --port /dev/ttyACM0 xy.ino
+
+/* Configure tty to read output from Serial.print():
+
+   stty -F /dev/ttyACM0 cs8 115200 -cstopb ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts
+
+   stty -F /dev/ttyACM0
+      cs8                       // Set character size to 8 bits
+      115200                    // Baud rate, matching Serial.begin(n)
+      -cstopb                   // Use only only 1 stop bit per characters
+      ignbrk                    // Ignore break characters
+      -brkint                   // NOT Breaks cause interrupt signal
+      -icrnl                    // NOT Translate CR to NL
+      -imaxbel                  // NOT beep and do not flush a full input buffer on a characters -- does this mean it
+                                //     WILL flush the buffer?
+      -opost                    // NOT postprocess output
+      -onlcr                    // NOT translate NL to CRNL (LF?)
+      -isig                     // NOT enable interrupt, quit, suspect special characters
+      -icanon                   // NOT enable erase, kill, werase, rprnt special characters
+      -iexten                   // NOT enable non-POSIX special characters
+      -echo                     // NOT echo input characters
+      -echoe                    // NOT echo erase characters as backspace-space-backspace
+      -echok                    // NOT echo a newline after a kill characters
+      -echoctl                  // NOT echo control characters in hat notation ('^c')
+      -echoke                   // NOT kill all line by obeying the echoctl and echok settings
+      noflsh                    // Disable flushing after interrupt and quit special characters
+      -ixon                     // Enable XON/XOFF flow control
+      -crtscts                  // Enable RTS/CTS handshaking
+ */

 #include "Adafruit_WS2801.h"
 #include "SPI.h" // Comment out this line if using Trinket or Gemma
@@ -104,13 +132,23 @@
    unsigned long desiredDuration = 3600UL * 1000UL; // total desired run time, milliseconds
    // desiredDuration = 120UL * 1000UL;

+//   Serial.begin( 115200);
+//   Serial.println( "setup()");
+//   Serial.print( "desiredDuration = ");
+//   Serial.println( desiredDuration);
+
    strip.begin();
    // clearStrip();
    strip.show();
    setupRotatingColorAxes();

    while (millis() < desiredDuration)
+   {
+//      Serial.print( "millis() = ");
+//      Serial.println( millis());
       rotatingColorAxes();
+   }
+

    clearStrip();
 }
@@ -387,6 +425,9 @@

    for (run = 0; run < 6; run++)
    {
+//      Serial.print( "run ");
+//      Serial.println( run);
+
       struct runParamTuple rp = runParams[run];
       for (y = 0; y < GRID_SIZE_Y; y++)
          for (x = 0; x < GRID_SIZE_X; x++)


Small fixes

Small fixes

--- src/Full_decoder/Full_decoder.ino
+++ src/Full_decoder/Full_decoder.ino
@@ -79,7 +79,7 @@

 void configureSlot(uint8_t slot) {
   uint8_t pin_config;
-  uint16_t pin, address, pos1, pos2, speed, fbslot1, fbslot2;
+  uint16_t pin, address, pos1, pos2, speed, fbslot1, fbslot2, powerpin;

     pin_config = eeprom_read_byte((uint8_t*)&(_CV.pin_conf[slot]));
     pin   = eeprom_read_word((uint16_t*)&(_CV.conf[slot].servo.arduinopin));
@@ -92,7 +92,7 @@
         speed = eeprom_read_word((uint16_t*)&(_CV.conf[slot].servo.speed));
         fbslot1  = eeprom_read_word((uint16_t*)&(_CV.conf[slot].servo.fbslot1));
         fbslot2  = eeprom_read_word((uint16_t*)&(_CV.conf[slot].servo.fbslot2));
-        powerpin = eeprom_read_word((uint16_t*)&(_CV.conf[i].servo.pwrslot)) && 0xFF;
+        powerpin = eeprom_read_word((uint16_t*)&(_CV.conf[slot].servo.pwrslot)) && 0xFF;
         confpins[slot] = new ServoSwitch(slot, pin, address, pos1, pos2, speed, powerpin, fbslot1, fbslot2);
         confpins[slot]->restore_state(eeprom_read_word((uint16_t*)&(_CV.conf[slot].servo.state)));
         break;
@@ -100,7 +100,7 @@
         confpins[slot] = new InputPin(slot, pin, address);
         break;
       case 3: // Output
-        pin_config = ((eeprom_read_word((uint16_t*)&(_CV.conf[i].output.options)) & 0x01) == 0x01);
+        pin_config = ((eeprom_read_word((uint16_t*)&(_CV.conf[slot].output.options)) & 0x01) == 0x01);
         confpins[slot] = new OutputPin(slot, pin, address, pin_config);
         break;
       default:


Refactor display logic

Refactor display logic

--- moros/moros.ino
+++ moros/moros.ino
@@ -92,7 +92,41 @@
   }
 };

+void init_display(player *p) {
+  p->tft.begin();
+  p->tft.background(0,0,0);
+  p->tft.stroke(255,255,255);
+  p->tft.fill(0,0,0);
+  p->tft.setTextSize(DISPLAY_FONT_SIZE);
+}

+void update_timer(player *p) {
+  p->time_remaining_ms -= (millis() - p->last_update_ms);
+  p->last_update_ms = millis();
+}
+
+void incrementally_update_text(player *p, const char *text) {
+  for(unsigned int i = 0; i < strlen(text); i++) {
+    p->tft.text(text, 0, 20);
+    if(text[i] != p->display_time[i]) {
+
+      // draw a rect
+      p->tft.stroke(0,0,0);
+      p->tft.rect(CHAR_WIDTH_PX * i , 20, CHAR_WIDTH_PX, CHAR_HEIGHT_PX);
+      //p->tft.background(0,0,0);
+      char next_char[2] = {text[i], '\0' };
+      p->tft.stroke(255,255,255);
+      p->tft.text(next_char, CHAR_WIDTH_PX * i, 20);
+    }
+  }
+  strncpy(p->display_time, text, sizeof(p->display_time));
+}
+
+void update_display(player *p) {
+  static char timea[12];
+  ltoa(p->time_remaining_ms/100, timea, 10);
+  incrementally_update_text(p, timea);
+}

 // does the SPI library allow selecting of which SS to issue the command on?

@@ -100,17 +134,9 @@
   Serial.begin(115200);
   Serial.println("Initializing...");

-  char timea[12];
   for(unsigned int i = 0; i < sizeof(players) / sizeof(players[0]); i++) {
-    players[i].tft.begin();
-    players[i].tft.background(0,0,0);
-    players[i].tft.stroke(255,255,255);
-    players[i].tft.fill(0,0,0);
-    players[i].tft.setTextSize(DISPLAY_FONT_SIZE);
-//    Serial.println(players[i].tft.width());
-    ltoa(players[i].time_remaining_ms/100, timea, 10);
-    strncpy(players[i].display_time, timea, 12);
-    players[i].tft.text(timea, 0, 20);
+    init_display(&players[i]);
+    update_display(&players[i]);
     attachInterrupt(players[i].interrupt_number, players[i].handle_button_press, RISING);
   }

@@ -122,37 +148,22 @@

 int loop_count = 0;
 void loop() {
-  char timea[12];
   if (loop_count == 0) {
     Serial.println("in loop");
     loop_count++;
   }
  // Serial.println(button_pressed);
+
   if (active_player != NONE) {
     if (players[active_player].time_remaining_ms <= 0) {
       active_player = NONE;
       button_pressed = NONE;
       return;
     }
-    players[active_player].time_remaining_ms -= (millis() - players[active_player].last_update_ms);
-    players[active_player].last_update_ms = millis();
-    long display_time = players[active_player].time_remaining_ms/100;
+    update_timer(&players[active_player]);
+    update_display(&players[active_player]);
+  }

-    ltoa(display_time, timea, 10);
-    for(unsigned int i = 0; i < strlen(players[active_player].display_time); i++) {
-      if(timea[i] != players[active_player].display_time[i]) {
-
-        // draw a rect
-        players[active_player].tft.stroke(0,0,0);
-        players[active_player].tft.rect(CHAR_WIDTH_PX * i , 20, CHAR_WIDTH_PX, CHAR_HEIGHT_PX);
-        //players[active_player].tft.background(0,0,0);
-        char timeb[2] = {timea[i], '\0' };
-        players[active_player].tft.stroke(255,255,255);
-        players[active_player].tft.text(timeb, CHAR_WIDTH_PX * i, 20);
-      }
-    }
-    strncpy(players[active_player].display_time, timea, sizeof(players[active_player].display_time));
-  }
   if ((active_player == NONE || button_pressed == active_player) && button_pressed != NONE)   {
     Serial.print("pre button_pressed: ");
     Serial.println(button_pressed);


Adjust reset button timeouts

Adjust reset button timeouts

--- moros/moros.ino
+++ moros/moros.ino
@@ -225,9 +225,9 @@

 class Controller {
 protected:
-  const unsigned long mode_button_reset_ms = 3000;
-  const unsigned long mode_button_settime_ms = 5000;
-  const unsigned long mode_button_poweroff_ms = 7000;
+  const unsigned long mode_button_reset_ms = 1000;
+  const unsigned long mode_button_settime_ms = 3000;
+  const unsigned long mode_button_poweroff_ms = 5000;
   enum { INIT, PRE_GAME, IN_PROGRESS, PAUSED, SET_TIME, SET_TIME_CLOCK_1, SET_TIME_CLOCK_2 } game_state;
 public:
   Player *players[NUM_PLAYERS];


TowerIR Minis are programmed

TowerIR Minis are programmed

--- src/TowerFloodIR/TowerFloodIR.ino
+++ src/TowerFloodIR/TowerFloodIR.ino
@@ -1,4 +1,6 @@
-// Compile for Arduino Pro/Pro Mini 5V 16Mhz with ATMega 328
+// Compile for Arduino Pro/Pro Mini 5V 16Mhz with ATMega 328.
+// During compilation, hold down RESET on the mini, and release when "Uploading..."
+// The pinout for the Minis with the rectangular RESET button are flipped, so the programmer will face away from you.

 // need to strike RobotIRRemote directory in Arduino IDE libraries folder.  Name collision!
 #include <IRremote.h> // IR connected to pin 3


Adjustment to lightness.  Truncated all black and all white values, for greater variety.  Add white/black checkboard at end to show full white.

--- xy.ino
+++ xy.ino
@@ -243,14 +243,16 @@

    int ledBrightness[GRID_SIZE_X]; // RGB intensity
    float dLedBrightness = 1.0 / (GRID_SIZE_X - 1);
+   float dLightness = 1.0 / (GRID_SIZE_X + 1); // Will drop lightness = 0 (black) and 1 (white), since that results in
+                                               // an entire row/column being all the same (fully off or fully on).
    float lightness[GRID_SIZE_X]; // HSL
    float saturation[GRID_SIZE_X]; // HSL

-   ledBrightness[0] = 0;
+   ledBrightness[0]               = 0;
    ledBrightness[GRID_SIZE_X - 1] = 255;

-   saturation[0] = lightness[0] = 0;
-   saturation[GRID_SIZE_X - 1] = lightness[GRID_SIZE_X - 1] = 1;
+   saturation[0]                  = 0;
+   saturation[GRID_SIZE_X - 1]    = 1;

    float v;

@@ -261,9 +263,16 @@
       v = i * dLedBrightness;   // Linear
       saturation[i] = v;
       v = pow( v, exponent);    // Non-linear
+      ledBrightness[i] = v * 256; // Don't need to constrain; won't get close to 255.
+   }
+
+   for (i = 0; i < GRID_SIZE_X; i++)
+   {
+      v = (i + 1) * dLightness; // See dLightness.
+      v = pow( v, 3.45);
       lightness[i] = v;
-      ledBrightness[i] = v * 256; // Don't need to constrain; won't get close to 255.
-   }
+   }
+

    // // Debug:
    // for (i = 0; i < GRID_SIZE_X; i++)
@@ -380,7 +389,16 @@
       strip.show();
       delay( run < 3 ? 5000 : 20000); // Delay longer for HSL part of run
    }
-
+
+   // Since we skipped "black" and "white", show a checkerboard of those.
+
+   clearStrip();
+   c = Color( 255, 255, 255);
+   for (i = 0; i < 25; i += 2)
+      strip.setPixelColor( i, c);
+   strip.show();
+   delay( 5000);
+
    // for (run = 0; run < 3; run++)
    // {
    //    for (y = 0; y < 5; y++)


Review by Maarten

Review by Maarten

--- arduino/mRPM/mRPM.ino
+++ arduino/mRPM/mRPM.ino
@@ -1,5 +1,6 @@
 // RPM measurement tool for Jan Ridders
-//     2017 july 10 by Maarten Pennings
+//     2017 July 16 by Maarten Pennings  v2  Removed 'String', fixed spelling errors, fixed error in hz100, added but_init(), added #defines
+//     2017 July 10 by Maarten Pennings  v1  Created
 // Hardware used:
 //   - RobotDyn NodeMCU V3 ESP8266 32M flash USB-serial CH340G
 //     https://www.aliexpress.com/item/NodeMCU-WIFI-module-integration-of-ESP8266-extra-memory-32M-flash-USB-serial-CH340G/32739832131.html?
@@ -21,30 +22,30 @@

 MAX7219_Dot_Matrix dsp(DSP_COUNT,DSP_CS,DSP_DIN,DSP_CLK);

-// Send commands to the matrix display (clear all leds, sets brightness)
+// Send commands to the matrix display (clear all LEDs, sets brightness)
 void dsp_init(void) {
   dsp.begin();
   dsp.setIntensity(8);
 }

-// Puts 'msg' (flush right) on the display (msg should be max 4 chars, rest is truncated)
-void dsp_set(String msg) {
-  int offset = (msg.length()-DSP_COUNT)*8-1;
-  dsp.sendSmooth(msg.c_str(),offset);
+// Puts 'msg' (flush right) on the display ('msg' should be max 4 chars, rest is truncated)
+void dsp_set(char * msg) {
+  int offset = (strlen(msg)-DSP_COUNT)*8 - 1; // The -1 shifts one column - looks better
+  dsp.sendSmooth(msg,offset);
 }

 // Sensor
 // ============================================================

-// Each time the sensor detects the marker on the rotating wheel, a pulse is generated.
+// Each time the sensor detects the marker on the rotating wheel a pulse is generated.
 // The pulse fires an interrupt, causing sen_isr() to be called.
-// The isr looks at the system clock - micros() - to determine the time stamp (sen_time) of the pulse.
+// The ISR looks at the system clock - micros() - to determine the time stamp (sen_time) of the pulse.
 // Two consecutive pulses allow the computation of their difference (delta).
-// Note: the term 'delta' refers to a time in micro seconds for one full retation.
+// Note: the term 'delta' refers to a time in micro seconds for one full rotation.

 // In reality there are some problems to solve
-//  - We need at least two pulses for a delta, so the first pulse must be largly ignored.
+//  - We need at least two pulses for a delta, so the first pulse must be largely ignored.
 //  - There are spurious pulses ("spikes"), probably caused when seeing the "rough" edges of the marker.
 //    It seems that the edges at the start of the marker as well as at the end of the marker cause spikes
 //  - A moving average (sen_movav1) is maintained to detect spikes (window size is SEN_SIZE1).
@@ -58,32 +59,32 @@
 //#define SEN_TRACE(...)      // nothing

 #define SEN_PIN        D6          // D0 pin of line tracking sensor connected to this pin of ESP8266 (VCC on VIN, GND on GND)
-#define SEN_IDLE       2000000     // If there is no pulse within 2 000 000 us (2 seconds), assume no rotation
-#define SEN_COUNT      4           // Number of pulses to wait after a restart before reporting measurements
+#define SEN_IDLE       2000000     // If there is no pulse within 2 000 000 us (2 seconds), assume rotation stopped
+#define SEN_COUNT      4           // Number of pulses to wait after a restart, before reporting measurements
 #define SEN_SIZE1      8           // Window size for first moving average (sen_movav1) - this is used to filter out spikes
 #define SEN_STEP       2           // Any measured delta smaller than the moving average (sen_movav1) divided by SEN_STEP is ignored
-#define SEN_SIZE2      16          // Window size for first moving average (sen_movav1) - this is used to filter out spikes
-volatile unsigned long sen_time;   // Timestamp of the last pulse fromn the sensor
+#define SEN_SIZE2      16          // Window size for second moving average (sen_movav2) - this is to smooth output (not too fast changes)
+volatile unsigned long sen_time;   // Time stamp of the last pulse from the sensor
 unsigned long          sen_count1; // Number of samples (delta's) in sen_movav1
 unsigned long          sen_movav1; // The moving average of all measured delta's
 unsigned long          sen_count2; // Number of samples (delta's) in sen_movav2
 volatile unsigned long sen_movav2; // The moving average of all accepted delta's

-// Prepare pin SEN_PIN for generating interrupts
+// Prepare sensor (setup pin, enable interrupt, initialize signal processing)
 void sen_init(void) {
   sen_time = micros()-SEN_IDLE; // Pretend not sensor was idle for SEN_IDLE
   pinMode(SEN_PIN, INPUT);
   attachInterrupt(digitalPinToInterrupt(SEN_PIN), sen_isr, RISING); // ensures sen_isr() is called when a pulse is detected on pin SEN
 }

-// The interrupts serivice routine called for every pulse
+// The interrupts service routine called for every pulse (registered in sen_init)
 void sen_isr(void) {
-  // Record stamp of the incoming pulse, and compute diff with previous pulse
+  // Record stamp of the incoming pulse, and compute differences with previous pulse
   unsigned long now= micros();
   unsigned long delta= now - sen_time;
   sen_time= now;
-  // Check if this is the first pulse after a long time; if so, bail out (for a delta we need two pulses).
+  // Check if this is the first pulse after a long time (a "restart"); if so, bail out (for a delta we need two pulses).
   if( delta >= SEN_IDLE ) {
     // Restating; clear the moving averages
     sen_count1= 0;
@@ -92,7 +93,7 @@
     SEN_TRACE("isr: %12lu %12lu start\n",delta,sen_movav1);
     return;
   }
-  // Compute the moving average (approximation) of all delta's (but reset moving average after a restart)
+  // Maintain (approximation of) the moving average of all delta's (but initialize moving average after a restart)
   sen_movav1= (sen_count1==0) ? delta : (sen_movav1*SEN_SIZE1 + delta - sen_movav1)/SEN_SIZE1;
   // Bail out if restarting
   if( sen_count1<SEN_COUNT ) {
@@ -105,26 +106,26 @@
     SEN_TRACE("isr: %12lu %12lu spike\n",delta,sen_movav1);
     return;
   }
-  // Compute the moving average (approximation) of all delta's (but reset moving average after a restart)
+  // Compute the (approximation of) the moving average of all accepted delta's (but initialize moving average after a restart)
   sen_movav2= (sen_count2==0) ? delta : (sen_movav2*SEN_SIZE2 + delta - sen_movav2)/SEN_SIZE2;
   SEN_TRACE("isr: %12lu %12lu av=%lu\n",delta,sen_movav1,sen_movav2);
-  // Step counter (when warpping, skip 0)
+  // Step counter (when wrapping, skip 0)
   sen_count2++;
   if( sen_count2==0 ) sen_count2++;
 }

-// Returns the duration of one rotation in us.
-// Returns 0 when there is no rotation (detected the last SEN_IDLE us).
+// Returns the duration of one rotation in us (smoothed).
+// Returns 0 when there is no rotation (detected no rotation during the last SEN_IDLE us).
 unsigned long sen_get(void) {
   unsigned long delta;
   noInterrupts();
-    // Get the moving average of the delta's from the isr
+    // Get the moving average of the delta's from the ISR
     delta= sen_movav2;
     // Check if the last pulse was too old, flag
     if( micros()- sen_time >= SEN_IDLE ) {
       if( sen_count1>0 ) { SEN_TRACE("isr: end\n"); sen_count1=0; } // sen_count1 is misused to only trace 'end' once
-      sen_time = micros()-SEN_IDLE; // Reset sen_time (needed to prevent wrap-around artefacts)
-      delta=0;
+      sen_time = micros()-SEN_IDLE; // Reset sen_time (needed to prevent wrap-around artifacts)
+      delta= 0;
     }
   interrupts();
   return delta;
@@ -139,22 +140,26 @@
 int but_oldstate;
 int but_curstate;

+// Initialize the button hardware (pin) and software module
 void but_init(void) {
   pinMode(BUT_PIN, INPUT);
   but_scan();
   but_scan();
 }

+// Checks the status of the pins; to be called periodically
 void but_scan(void) {
   int but_newstate= digitalRead(BUT_PIN)==0;
   but_oldstate = but_curstate;
   but_curstate = but_newstate;
 }

+// Returns current state of the button (1=is-down, 0=is-up)
 int but_isdown(void) {
   return but_curstate;
 }

+// Returns the current state with respect to the previous state - transition  (1=went-down, 0=is-down/is-up/went-up)
 int but_wentdown(void) {
   return (but_curstate ^ but_oldstate) & but_curstate;
 }
@@ -164,14 +169,14 @@
 // ============================================================

 // Helper function that formats an integer to a string.
-// It puts an dot at position dotpos.
+// It puts an dot at position 'dotpos'.
 // Note that the font is patched (to have digits with a leading decimal point)
 char * tostr(int val,int dotpos) {
-  static char buf[]="xxxx";
+  static char buf[]="xxxx"; // local buffer - only works for single threaded - ok here
   for(int i=0; i<4; i++ ) {
     int digit=val%10;
     buf[3-i]=digit+'0';
-    if( i==dotpos && i!=0 ) buf[3-i]=digit+'\x10'; // Font is patched to have 0. 1. etc at 0x10 and up
+    if( i==dotpos && i!=0 ) buf[3-i]=digit+'\x10'; // Font is patched to have '0.', '1.' etc at 0x10 and up
     val=val/10;
   }
   // Erase trailing 0s
@@ -190,19 +195,20 @@

 // Shows the current delta on the display (using current units)
 void show_delta( unsigned long delta, int units ) {
-  if( delta==0 ) {
-    switch( units ) { // Font is patched to have -. at 0x1A
+  if( delta==0 ) { // No delta available, show dashes
+    switch( units ) { // Font is patched to have '-.' at 0x1A
       case 0: dsp_set("-"); break;
       case 1: dsp_set("\x1A-"); break;
       case 2: dsp_set("\x1A--"); break;
     }
-  } else {
+  } else { // delta is rotation time in us
+    // Compute derived values - the additions below are for rounding
     int rpm= (60*1000*1000+delta/2)/delta;  // units: rotations per minute
-    int ms10= (delta+50)/100;               // units: 1/10 microseconds
-    int hz100= (100*1000*1000+delta)/delta; // units: 1/100 herz
+    int ms10= (delta+50)/100;               // units: 1/10 milliseconds
+    int hz100= (100*1000*1000+delta/2)/delta; // units: 1/100 hertz
     switch( units ) {
-      case 0: dsp_set(tostr(rpm,0)); break;
-      case 1: dsp_set(tostr(ms10,1)); break;
+      case 0: dsp_set(tostr(rpm  ,0)); break;
+      case 1: dsp_set(tostr(ms10 ,1)); break;
       case 2: dsp_set(tostr(hz100,2)); break;
     }
   }
@@ -212,23 +218,27 @@
 // Arduino entry points
 // ============================================================

-#define TOGGLE 1000    // Time (in ms) between displaying units and delta (when not rotating)
-int units;             // With the 'flash' buttons, the units can be chosen. This variable hold the current mode.
-int olddelta;          // Last valid measurement
-unsigned long oldtime; // Last time the display was refreshed (when not rotating)
+#define BAUD       115200  // Baud rate for serial connection
+#define INTRO_MS   3000    // Time (in ms) for the intro message
+#define REFRESH_MS 100     // Time (in ms) between display and button refreshes
+#define TOGGLE_MS  1000    // Time (in ms) between displaying units and delta (when not rotating)
+int units;                 // With the 'flash' button, the units can be chosen. This variable holds the current mode
+int olddelta;              // Last valid measurement
+unsigned long oldtime;     // Last time the display was refreshed (when not rotating)

 void setup() {
-  // Init serial port (over USB), matrix and sensor
-  Serial.begin(115200);
+  // Initialize serial port (over USB), matrix, sensor en button
+  Serial.begin(BAUD);
   dsp_init();
   sen_init();
-  // Init program variables
+  but_init();
+  // Initialize program variables
   units= 0; // 0=rpm, 1=ms, 2=Hz
   olddelta= 0;
   // Welcome messages
   Serial.printf("\n\nWelcome at mRPM\n");
   dsp_set("mRPM");
-  delay(3000);
+  delay(INTRO_MS);
 }

 void loop(){
@@ -242,8 +252,8 @@
   if( delta==0 ) {
     // Not rotating: toggle display between units and last known delta
     unsigned long now = millis();
-    if( now-oldtime<1*TOGGLE ) show_units(units);
-    else if( now-oldtime<2*TOGGLE ) show_delta(olddelta,units);
+    if( now-oldtime<1*TOGGLE_MS ) show_units(units);
+    else if( now-oldtime<2*TOGGLE_MS ) show_delta(olddelta,units);
     else oldtime= now;
   } else {
     // Rotating: show current delta
@@ -252,7 +262,7 @@
     oldtime= millis();
   }
   // Display and buttons are refreshed every 100ms
-  delay(100);
+  delay(REFRESH_MS);
 }


output sample and seperate by ':'

output sample and seperate by ':'

--- arduino-raw-tx/arduino-raw-tx.ino
+++ arduino-raw-tx/arduino-raw-tx.ino
@@ -27,11 +27,10 @@

 	raw = accel.readRaw();

-	Serial.print("RAW:  ");
 	Serial.print(raw.XAxis);
-	Serial.print("\t");
+	Serial.print(":");
 	Serial.print(raw.YAxis);
-	Serial.print("\t");
+	Serial.print(":");
 	Serial.println(raw.ZAxis);

 	delay(10);


send sensible pixel data

send sensible pixel data

--- arduino/led_matrix/led_matrix.ino
+++ arduino/led_matrix/led_matrix.ino
@@ -19,9 +19,9 @@
 }

 void loop() {
-  for (y = 0; y < NUM_LEDS; y++) {
-    for (x = 0; x < NUM_LEDS; x++) {
-      while (Serial.available() < NUM_LEDS * 3);
+  for (y = 0; y < HEIGHT; y++) {
+    for (x = 0; x < WIDTH; x++) {
+      while (Serial.available() < 3);
       b = Serial.read();
       g = Serial.read();
       r = Serial.read();