diff --git a/Arduino/Makefile b/Arduino/Makefile
index a1f4a20b5bfb796689a71bfd5977c36a4db194d8..5a15097fe19f3d5af5457400dc2d672e0ba7e849 100644
--- a/Arduino/Makefile
+++ b/Arduino/Makefile
@@ -1,9 +1,4 @@
-#NO_CORE=	1
-#MCU=		m328p
-#F_CPU=		16000000
-#VARIANT=	standard
 TARGET=		PowerSensor
-BOARD_TAG=	uno
-#ARDUINO_PORT=	/dev/ttyACM0
-ARDUINO_PORT=	/dev/ttyUSB0
+BOARD_TAG=	leonardo
+ARDUINO_PORT=	/dev/ttyACM0
 include /usr/share/arduino/Arduino.mk
diff --git a/Arduino/PowerSensor.ino b/Arduino/PowerSensor.ino
index b0385ee013976e8d6a2f9dab8976d9ec73d3f6f4..8908824ed058aa24e17f1e4b298723522cbe65a1 100644
--- a/Arduino/PowerSensor.ino
+++ b/Arduino/PowerSensor.ino
@@ -32,79 +32,75 @@ struct EEPROM
   struct Sensor {
     double volt;
     double type;
-    int16_t nullLevels;
+    double nullLevel;
   } sensors[MAX_SENSORS];
 } eeprom __attribute__((section(".eeprom")));
 
-int64_t accumulated_values[MAX_SENSORS];
-int16_t levels[MAX_SENSORS];
-long    previous_time;
-double  weights[MAX_SENSORS];
-int16_t nullLevels[MAX_SENSORS];
-bool    inUse[MAX_SENSORS];
+struct Sensor
+{
+  bool     inUse;
+  uint16_t count;
+  int32_t  total;
+  double   weight;
+  double   nullLevel;
 
+  double power() const { return weight * total / count - nullLevel; }
 
-int64_t total_accumulated_value()
-{
-  int64_t sum = 0;
+} sensors[MAX_SENSORS];
 
-  for (uint8_t sensor = 0; sensor < MAX_SENSORS; sensor ++)
-    if (inUse[sensor])
-      sum += weights[sensor] * accumulated_values[sensor];
 
-  return sum;
-}
+bool streamValues = false;
 
 
-inline uint8_t next_sensor(uint8_t current_sensor)
+inline uint8_t nextSensor(uint8_t currentSensor)
 {
   do
-    if (++ current_sensor == MAX_SENSORS)
-      current_sensor = 0;
-  while (!inUse[current_sensor]);
+    if (++ currentSensor == MAX_SENSORS)
+      currentSensor = 0;
+  while (!sensors[currentSensor].inUse);
+
+  return currentSensor;
+}
 
-  return current_sensor;
+
+inline void setADMUX(uint8_t sensor)
+{
+#if defined __AVR_ATmega32U4__
+  ADMUX = _BV(REFS0) | ((sensor <= 2 ? 6 : 4) - sensor);
+#else
+  ADMUX = _BV(REFS0) | (sensor + 1); // ADC0 reads the LCD buttons; skip it
+#endif
 }
 
 
 ISR(ADC_vect)
 {
-  static uint8_t current_sensor = 0;
+  static uint8_t currentSensor = 0;
 
   uint8_t low = ADCL, high = ADCH; // read in this order
-  levels[current_sensor] = (high << 8) | low;
 
   // start next ADC ASAP.
-  uint8_t previous_sensor = current_sensor;
-  current_sensor = next_sensor(current_sensor);
+  uint8_t previousSensor = currentSensor;
+  currentSensor = nextSensor(currentSensor);
 
-  ADMUX = _BV(REFS0) | (current_sensor + 1); // ADC0 reads the LCD buttons; skip it
+  setADMUX(currentSensor);
   ADCSRA |= _BV(ADSC); // start ADC conversion
 
-  // handle measured value
-
-  if (current_sensor <= previous_sensor) {
-    // we had one round of all sensors.  now handle them in one go
-    long measured_time = micros();
-    long time_difference = measured_time - previous_time;
-    previous_time = measured_time;
+  int16_t level = (high << 8) | low;
+  sensors[previousSensor].total += level - 512;
+  sensors[previousSensor].count ++;
 
-    for (uint8_t sensor = 0; sensor < MAX_SENSORS; sensor ++)
-      // compiler will generate 16x16 bit multiply producing 32-bit result
-      accumulated_values[sensor] += (long) (int) time_difference * (levels[sensor] - nullLevels[sensor]);
-  }
-}
+  if (streamValues) {
+    Serial.write((previousSensor << 5) | (level >> 5));
+    Serial.write(0xE0 | (level & 0x1F));
 
+#if defined __AVR_ATmega32U4__
+    Serial.flush();
+#endif
 
-void readState()
-{
-  noInterrupts();
-
-  int32_t total = total_accumulated_value() >> 16;
-  Serial.write((const uint8_t *) &total, sizeof total);
-  Serial.write((const uint8_t *) &previous_time, sizeof previous_time);
-
-  interrupts();
+    //for (int i = 2; i < 16; i ++)
+      //Serial.write(0);
+  }
 }
 
 
@@ -114,9 +110,9 @@ void configureFromEEPROM()
   eeprom_read_block(&copy, &eeprom, sizeof copy);
 
   for (unsigned i = 0; i < MAX_SENSORS; i ++) {
-    inUse[i] = copy.sensors[i].volt != 0;
-    weights[i] = inUse[i] ? copy.sensors[i].volt * 2.5 / copy.sensors[i].type : 0;
-    nullLevels[i] = copy.sensors[i].nullLevels;
+    sensors[i].inUse = copy.sensors[i].volt != 0;
+    sensors[i].weight = sensors[i].inUse ? (2.5 / 512) * (copy.sensors[i].volt / copy.sensors[i].type) : 0;
+    sensors[i].nullLevel = copy.sensors[i].nullLevel;
   }
 }
 
@@ -131,7 +127,10 @@ void readConfig()
 
 void writeConfig()
 {
+#if !defined __AVR_ATmega32U4__
   Serial.begin(115200); // serial comm from host to Arduino seems less reliable --> reduce baud rate
+#endif
+
   EEPROM copy;
 
   for (unsigned i = 0; i < sizeof copy; i ++) {
@@ -141,31 +140,32 @@ void writeConfig()
     ((uint8_t *) &copy)[i] = Serial.read();
   }
 
-  Serial.begin(2000000); // probably only neecssary on Leonardo, that does not automatically reset after creating a new connection
+#if !defined __AVR_ATmega32U4__
+  Serial.begin(2000000);
+#endif
+
   eeprom_update_block(&copy, &eeprom, sizeof copy);
   configureFromEEPROM();
 }
 
 
-void readLevels()
-{
-  Serial.write((const uint8_t *) levels, sizeof levels);
-}
-
-
 void serialEventRun()
 {
   switch (Serial.read()) {
-    case 'l': readLevels();
+    case 'r': readConfig();
 	      break;
 
-    case 'r': readConfig();
+    case 'w': writeConfig();
 	      break;
 
-    case 's': readState();
+    case 'S': streamValues = true;
 	      break;
 
-    case 'w': writeConfig();
+    case 'T': streamValues = false;
+	      break;
+
+    case 'X': streamValues = false;
+	      Serial.write((const uint8_t []) { 0xFF, 0xE0 }, 2);
 	      break;
   }
 }
@@ -182,7 +182,7 @@ void setup()
 
   Serial.begin(2000000);
 
-  ADMUX   = _BV(REFS0) + 1;
+  setADMUX(0);
   ADCSRA |= _BV(ADIE); // enable ADC interrupts
   ADCSRA |= _BV(ADSC); // start ADC conversion
 }
@@ -190,51 +190,52 @@ void setup()
 
 void loop()
 {
-  static unsigned long previous_print_time;
-  static int64_t previous_value_of_next_sensor, previous_value_total;
-  static uint8_t count, current_sensor = next_sensor(MAX_SENSORS - 1), current_line;
-
-  noInterrupts();
+  static unsigned long previousPrintTime;
+  static uint8_t count, currentSensor = nextSensor(MAX_SENSORS - 1), currentLine;
 
-  unsigned long current_time = micros(), time_difference = current_time - previous_print_time;
+  uint16_t currentTime = millis(), timeDifference = currentTime - previousPrintTime;
 
-  if (time_difference > 333333) {
+  if (timeDifference > 333) {
     double power;
 
-    if (current_line == 0) {
+    if (currentLine == 0) {
       // print top line; rotate among the used sensors
-      int64_t total = weights[current_sensor] * accumulated_values[current_sensor];
-
-      if ((++ count & 7) == 0)
-	current_sensor = next_sensor(current_sensor);
-
-      power = (double) (total - previous_value_of_next_sensor) / (512 * time_difference);
-      previous_value_of_next_sensor = weights[current_sensor] * accumulated_values[current_sensor];
 
+      noInterrupts();
+      power = sensors[currentSensor].power();
       interrupts();
 
+      if ((++ count & 7) == 0)
+	currentSensor = nextSensor(currentSensor);
+
       if ((count & 7) == 1) {
 	lcd.setCursor(7, 0);
-	lcd.print((char) ('0' + current_sensor));
+	lcd.print((char) ('0' + currentSensor));
       }
-    } else { // current_line == 1
+    } else { // currentLine == 1
       // print bottom line; the sum of all sensors
-      int64_t total = total_accumulated_value();
+      power = 0;
+
+      noInterrupts();
+
+      for (uint8_t sensor = 0; sensor < MAX_SENSORS; sensor ++) {
+	if (sensors[sensor].inUse) {
+	  power += sensors[sensor].power();
+	  sensors[sensor].total = 0;
+	  sensors[sensor].count = 0;
+	}
+      }
 
       interrupts();
 
-      power = (double) (total - previous_value_total) / (512 * time_difference);
-      previous_value_total = total;
-      previous_print_time = current_time;
+      previousPrintTime = currentTime;
     }
 
     char buffer[16];
     dtostrf(power, 6, 1, buffer);
-    lcd.setCursor(9, current_line);
+    lcd.setCursor(9, currentLine);
     lcd.print(buffer);
 
-    current_line ^= 1;
+    currentLine ^= 1;
   }
-
-  interrupts();
 }
diff --git a/Semaphore.h b/Semaphore.h
new file mode 100644
index 0000000000000000000000000000000000000000..adb1a3d9645258c18cb84fb1c2ee2a55947c42b5
--- /dev/null
+++ b/Semaphore.h
@@ -0,0 +1,46 @@
+#if !defined SEMAPHORE_H
+#define SEMAPHORE_H
+
+#include <condition_variable>
+#include <mutex>
+
+
+namespace PowerSensor {
+
+
+class Semaphore
+{
+  public:
+    Semaphore(unsigned initialLevel = 0)
+    :
+      level(initialLevel)
+    {
+    }
+
+    void up(unsigned count = 1)
+    {
+      std::unique_lock<std::mutex> lock(mutex);
+      level += count;
+
+      if (count == 1)
+	cv.notify_one();
+      else
+	cv.notify_all();
+    }
+    
+    void down(unsigned count = 1)
+    {
+      std::unique_lock<std::mutex> lock(mutex);
+      cv.wait(lock, [this, count] { return level >= count; });
+      level -= count;
+    }
+
+  private:
+    std::mutex		    mutex;
+    std::condition_variable cv;
+    unsigned		    level;
+};
+
+}
+
+#endif