added xbee stuff

added xbee stuff

--- master/master.ino
+++ master/master.ino
@@ -36,6 +36,39 @@
 bool ledState = true;
 uint32_t ledBlinkTime = 500;

+/**********************************************************/
+/*				        playMode  				     	  */
+/**********************************************************/
+#define OFFENSE 0
+#define DEFENSE 1
+#define UNDECIDED 2
+
+uint8_t playMode = UNDECIDED;
+
+bool powerOn = true;
+
+/**********************************************************/
+/*				        wireless   						  */
+/**********************************************************/
+#define XBEE_START 255
+#define XBEE Serial3
+#define XBEE_TIMEOUT 200000 // xbee timeout in ms
+
+uint8_t rx_len;
+uint8_t rx_packet[6];
+uint8_t rx_i;
+uint8_t prev_c;
+
+elapsedMillis rx_elapsed;
+bool xbeeConnected = false;
+
+uint8_t otherRobot_playMode;
+uint8_t otherRobot_tsopStrength;
+int16_t otherRobot_tsopAngle;
+uint8_t otherRobot_lineLocation;
+bool otherRobot_powerOn;
+
+uint8_t tx_i;

 /**********************************************************/
 /*					      tft   						  */
@@ -184,6 +217,72 @@
 int laserSig = 0;

 bool ballInZone = false;
+
+void resetOtherRobotData(){
+	otherRobot_playMode = DEFENSE;
+	otherRobot_tsopStrength = 0;
+	otherRobot_tsopAngle = 0;
+	otherRobot_lineLocation = LINELOCATION::UNKNOWN;
+	otherRobot_powerOn = false;
+}
+
+void rx(){
+	otherRobot_playMode = rx_packet[0];
+	otherRobot_tsopStrength = rx_packet[1];
+	otherRobot_tsopAngle  = (rx_packet[2] << 8) | rx_packet[3];
+	otherRobot_lineLocation = rx_packet[4];
+	otherRobot_powerOn = rx_packet[5];
+	Serial.print("received\t");
+	Serial.print(otherRobot_playMode); Serial.print('\t');
+	Serial.print(otherRobot_tsopStrength); Serial.print('\t');
+	Serial.print(otherRobot_tsopAngle); Serial.print('\t');
+	Serial.print(otherRobot_lineLocation); Serial.print('\t');
+	Serial.println(otherRobot_powerOn);
+}
+
+void tx(){
+	switch(tx_i){
+		case 0: XBEE.write(XBEE_START); XBEE.write(XBEE_START); break;
+		case 1: XBEE.write(playMode); break;
+		case 2: XBEE.write(tsopStrength); break;
+		case 3: XBEE.write(highByte(tsopAngle)); break;
+		case 4: XBEE.write(lowByte(tsopAngle)); break;
+		case 5: XBEE.write(linelocation); break;
+		case 6: XBEE.write(powerOn); break;
+	}
+	tx_i++;
+	if (tx_i == 7) tx_i = 0;
+}
+
+void xbeeTryTxRx(){
+	tx();
+
+	rx_len = XBEE.available();
+	if(rx_len){
+		for(uint8_t i = 0; i < rx_len; i++){
+			uint8_t c = XBEE.read();
+			if(c == XBEE_START && prev_c == XBEE_START){
+				rx_i = 0;
+			}
+			else if(rx_i <= 5){
+				rx_packet[rx_i] = c;
+				rx_i++;
+			}
+			if(rx_i == 6){
+				rx();
+				rx_elapsed = 0;
+				xbeeConnected = true;
+				rx_i = 7;
+			}
+			prev_c = c;
+		}
+	}
+
+	if(rx_elapsed >= 50){
+		xbeeConnected = false;
+		resetOtherRobotData();
+	}
+}

 inline void ledBlink(){
 	// led blinking
@@ -714,6 +813,7 @@

 extern "C" int main(void){
 	Serial.begin(115200);
+	XBEE.begin(9600);

 	// begin i2c at 400kHz
 	Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
@@ -803,6 +903,10 @@

 				break;
 		}
+		/* xbee */
+		xbeeTryTxRx();
+		/* end xbee */
+
 		/* orientation/imu */
 		getSlave1Data();
 		/* end orientation/imu */


Updated string function under quota check

--- module/module.ino
+++ module/module.ino
@@ -77,7 +77,7 @@
 		// Check if the user has not reached the 60 min quota, skip if staff member
 		else if ( (existingTime >= quota) && (isStaff == 0x00) ) {
 			//soundFeedback(isReject);
-			Serial.print(messages.quotaMet);
+			getStringFromMem(quotaMet);
 		}
 		// User passed all checks and is able to use the machine
 		// --------------------------------------------------------------------


Testing on small laser

Testing on small laser

--- module/module.ino
+++ module/module.ino
@@ -154,8 +154,9 @@
 	// some variables used in this scope
 	unsigned long startTime = 0;
 	unsigned int periodX, periodY;
-	unsigned int i, pulseCount, pollCounter = 0;
+	unsigned int pulseCount, pollCounter = 0;
 	int signals[] = { 0, 0, 0 };
+  int i = 0;

 	// Only here temporarily for debugging
 	if (debug) {
@@ -195,6 +196,8 @@
 		periodX = pulseIn(driverX, HIGH);
 		periodY = pulseIn(driverY, HIGH);

+    signals[i] = inRange(periodX, periodY);
+
 		// Only here temporarily for debugging
 		if (debug) {
 			Serial.print("PeriodX: "); Serial.print(periodX);
@@ -206,7 +209,7 @@
 		}

 		// if periodX and periodY IS a valid pair
-		if ( inRange(periodX, periodY) ) {
+		if ( signals[i] == 1 ) {
 			// a job is detected when we get 3 valid signals in a row
 			// begin stopwatch
 			if (checkHistory(signals) == flag.detectedJobStart) {
@@ -218,7 +221,7 @@
 			}
 		}
 		// if periodX and periodY IS NOT a valid pair
-		if ( !inRange(periodX, periodY) ) {
+		if ( signals[i] == 0 ) {
 			// check if enough negative signals have been detected
 			// calculate elapsed time
 			if (checkHistory(signals) == flag.detectedJobEnd) {
@@ -236,13 +239,12 @@
 			}
 		}

-		// record the previous state
-		signals[i] = inRange(periodX, periodY);
-		i++;
-
-		if (i == sampleSize) {
+		if (i == sampleSize - 1) {
 			i = 0;
 		}
+    else {
+      i += 1;
+    }
 		delay(pollInterval);
 	}
 }
@@ -292,11 +294,9 @@
 	unsigned int sum = periodX + periodY;

 	if (0 < sum && sum <= maximumValue) {
-		delay(debounce);
 		return 1;
 	}
 	else {
-		delay(debounce);
 		return 0;
 	}
 }


Changed default mode

Changed default mode

--- mojoEngineSim.ino
+++ mojoEngineSim.ino
@@ -52,9 +52,9 @@
 // Mode settings - These could easily be 4 jumpers connected to spare pins, checked at startup to determin mode

 boolean managedThrottle = true;     // Managed mode looks after the digipot if fitted for volume, and adds some mass to the engine
-boolean potThrottle = false;         // A pot connected to A1, 0-1023 sets speed
+boolean potThrottle = true;         // A pot connected to A1, 0-1023 sets speed
 boolean pwmThrottle = false;        // Takes a standard servo signal on pin 2 (UNO)
-boolean spiThrottle = true;        // SPI mode, is an SPI slave, expects 1-255 for throttle position, with 0 being engine off
+boolean spiThrottle = false;        // SPI mode, is an SPI slave, expects 1-255 for throttle position, with 0 being engine off


New pins on the Teensy2

New pins on the Teensy2

These pins are more convenient for soldering on
the Teensy2.

--- shofanduino2/shofanduino2.ino
+++ shofanduino2/shofanduino2.ino
@@ -13,11 +13,11 @@

 #include <DHT22.h> // see above for URLs

-#define DHT22_PIN 6
+#define DHT22_PIN 23

 // consts for controlling relays
-const int K1 = 11;
-const int K2 = 12;
+const int K1 = 5;
+const int K2 = 6;
 const int milliseconds_switch_delay = 100;
 const int NormallyConnected = HIGH;
 const int NormallyOpen = LOW;


Delete Application.ino

Delete Application.ino

--- examples/Application.ino
+++ examples/Application.ino
@@ -1 +0,0 @@
-test


Change default channel name

Change default channel name

--- examples/Basic/Basic.ino
+++ examples/Basic/Basic.ino
@@ -62,10 +62,10 @@
     // be done once.
     //
     // NOTE: Please ensure you've created a channel called "Helium
-    // Cloud MQTT" called in the Helium Dashboard.
+    // MQTT" called in the Helium Dashboard.
     int8_t result;
     Serial.print("Creating Channel - ");
-    status = channel.begin("Helium Cloud MQTT", &result);
+    status = channel.begin("Helium MQTT", &result);
     // Print status and result
     report_status_result(status, result);
 }


add ability to move text around in music demo

- makes it a little bit more of a hardware test demo
- A/B inverts and uninverts the screen

--- examples/Tunes/Tunes.ino
+++ examples/Tunes/Tunes.ino
@@ -162,10 +162,9 @@
 {
   arduboy.start();
   arduboy.setTextSize(4);
-  arduboy.setCursor(0,0);
-  arduboy.print("Music\nDemo");
-  arduboy.display();
 }
+
+int x = 0, y = 0;

 void loop ()
 {
@@ -173,6 +172,27 @@
   if (!(arduboy.nextFrame()))
     return;

+  if (arduboy.pressed(UP_BUTTON)) {
+    y-=1;
+  } else if (arduboy.pressed(DOWN_BUTTON)) {
+    y+=1;
+  } else if (arduboy.pressed(LEFT_BUTTON)) {
+    x-=1;
+  } else if (arduboy.pressed(RIGHT_BUTTON)) {
+    x+=1;
+  }
+
+  if (arduboy.pressed(A_BUTTON)) {
+    arduboy.invert(true);
+  } else if (arduboy.pressed(B_BUTTON)) {
+    arduboy.invert(false);
+  }
+
+  arduboy.setCursor(x,y);
+  arduboy.print("Music\nDemo");
+  arduboy.display();
+
+
   // play the tune if we aren't already
   if (!arduboy.tunes.playing())
     arduboy.tunes.playScore(score);


save state to EEPROM added

save state to EEPROM added

--- nodemcu-rgbstrip.ino
+++ nodemcu-rgbstrip.ino
@@ -4,12 +4,14 @@
 #include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson
 #include <PubSubClient.h>
 #include <strings.h>
+#include <EEPROM.h>

 #include "DomoticzRGBDimmer.h"

 /*
  * TODO: PWM value storage
- *   - store the values into EEPROM before OFF state
+ *   [x] store the values into EEPROM before OFF state
+ *   []  restore the saved values from the EEPROM when entering ON state
 */

 /* Program states and the current state */
@@ -35,6 +37,8 @@
 #define PWM_FREQ 100
 #define CONFNAME "/wificreds.conf"

+#define EE_STATUS_BASE  0
+
 #define SLEDS_OFF { digitalWrite(D6, false); digitalWrite(D7, false); digitalWrite(D8, false); }
 #define CAPTIVE_ON { digitalWrite(D6, false); digitalWrite(D7, false); digitalWrite(D8, true); }  // Blue LED
 #define BOOT_ON { digitalWrite(D6, true); digitalWrite(D7, true); digitalWrite(D8, false); }      // Yellow LED
@@ -47,7 +51,7 @@
 #define MQTT_CLEN 80 // channel string length
 #define MQTT_ULEN 20 // username length
 #define MQTT_PLEN 20 // password length
-#define MQTT_FLEN 20 // friendly name length
+#define MQTT_FLEN 20 // friendly name length

 #define DEBUG 1

@@ -110,6 +114,9 @@

   Serial.begin(115200);

+  // EEPROM init
+  EEPROM.begin(512);
+
   // PWM outputs
   pinMode(D2, OUTPUT);  /* RED */
   pinMode(D4, OUTPUT);  /* GREEN */
@@ -131,8 +138,10 @@
   /* remove saved config and restart if the flash button is pushed */
   attachInterrupt(digitalPinToInterrupt(D3), deleteWifiConfig, CHANGE);

+#ifdef DEBUG
   Serial.print(F("Flash chip size: "));
   Serial.println(ESP.getFlashChipRealSize());
+#endif

   /* Try to load config */
   if (SPIFFS.begin()) {
@@ -147,8 +156,10 @@
         configFile.readBytes(buf.get(), size);
         DynamicJsonBuffer jsonBuffer;
         JsonObject& json = jsonBuffer.parseObject(buf.get());
+#ifdef DEBUG
         json.printTo(Serial);
         Serial.println("");
+#endif
         if (json.success()) {
           stassid = String((const char*)json["sta_ssid"]);
           stapass = String((const char*)json["sta_pass"]);
@@ -268,9 +279,9 @@

     int fragPercent = 0;

+    DomoticzRGBDimmer dimmerParams = parseDomoticzRGBDimmer((const char*)payload);
+#ifdef DEBUG
     Serial.println(F("Payload target is this device. Processing payload..."));
-    DomoticzRGBDimmer dimmerParams = parseDomoticzRGBDimmer((const char*)payload);
-
     Serial.println(F("Setting PWM levels to: "));
     Serial.print(F("  R:     "));
     Serial.println(dimmerParams.Color_r);
@@ -282,12 +293,26 @@
     Serial.println(dimmerParams.Level);
     Serial.print(F("  Value: "));
     Serial.println(dimmerParams.nvalue);
+#endif
+
     setOutput(dimmerParams.Color_r, dimmerParams.Color_g, dimmerParams.Color_b, (!dimmerParams.nvalue)?0:dimmerParams.Level);
+
+#ifdef DEBUG
     Serial.println(F("Releasing resources..."));
+#endif
+
     freeDomoticzRGBDimmer(&dimmerParams);
+
+#ifdef DEBUG
     Serial.print(F("Resources released. Fragmentation [%]: "));
+#endif
+
     fragPercent = ESP.getHeapFragmentation();
+
+#ifdef DEBUG
     Serial.println(fragPercent);
+#endif
+
     if (fragPercent > 80) {
       Serial.println(F("Fragmentation is too high! Rebooting..."));
       ESP.reset();
@@ -297,6 +322,27 @@

 void saveStateToEeprom(int r, int g, int b, int level)
 {
+  bool changed = false;
+
+  if ( EEPROM.read(EE_STATUS_BASE) != (unsigned char)r ) {
+    EEPROM.write(EE_STATUS_BASE, (unsigned char)r);
+    changed = true;
+  }
+  if ( EEPROM.read(EE_STATUS_BASE+1) != (unsigned char)g ) {
+    EEPROM.write(EE_STATUS_BASE+1, (unsigned char)g);
+    changed = true;
+  }
+  if ( EEPROM.read(EE_STATUS_BASE+2) != (unsigned char)b ) {
+    EEPROM.write(EE_STATUS_BASE+2, (unsigned char)b);
+    changed = true;
+  }
+  if ( EEPROM.read(EE_STATUS_BASE+3) != (unsigned char)level ) {
+    EEPROM.write(EE_STATUS_BASE+3, (unsigned char)level);
+    changed = true;
+  }
+  if (changed) {
+    EEPROM.commit();
+  }
   return;
 }


Update rx5808-pro-diversity.ino

Update rx5808-pro-diversity.ino

Added new band with frequencies 5362 MHz 5399 MHz 5436 MHz 5473 MHz 5510 MHz 5547 MHz 5584 MHz and 5621 MHz.


using getMessage and isChecksumCorrect

using getMessage and isChecksumCorrect

--- test_parser/test_parser.ino
+++ test_parser/test_parser.ino
@@ -30,7 +30,9 @@
     msg_len = parser.parse(Serial1.read());
   }

-  if (msg_len > 0)
+  if (msg_len > 0) {
     parser.debugMessage();
+    if (parser.isChecksumCorrect()) Serial.print("getMessage: " + parser.getMessage() + "\n");
+  }
 }


stable binary hero

stable binary hero

stable version of map moving and having to catch  the right button at
time, have variable so that can change reaction time as level up, but
haven't set up level upping. Now need to create more maps and count
level and level up and change reaction times as level up.  And later on,
also have a menu at end to choose to play again if you want to.

--- game_one/game_one.ino
+++ game_one/game_one.ino
@@ -12,7 +12,8 @@
 const int led_pin = 13;
 const int touch_pin = 4;
 const int buzz_pin = 8;
-const char blank_writer[16] = "               ";
+const char blank_writer[17] = "                ";
+int rxn_time = 30;//time to react, decreases as levels go up

 int button_state = 0;
 int touch_state = 0;
@@ -30,6 +31,9 @@
 int val1 = 0;
 int user0 = 0;
 int user1 = 0;
+boolean good = false;
+int loop_count = 0;
+boolean start_delay = true;

 boolean correct_press();//checks to see if the user pressed the correct buttons
 void map_display();//const unsigned int& map0, const unsigned int& map1, unsigned int& p0, unsigned int& p1);
@@ -56,7 +60,7 @@
     lcd.print(blank_writer);
     delay(200);
     map_display();
-    delay(500);
+    delay(30);
 }

 //map display function
@@ -67,20 +71,6 @@
   //setting val0 and val1
   val0 = map_0[ptr0];
   val1 = map_1[ptr1];
-  /*lcd.setCursor(0,0);
-  lcd.print("val0:");
-  lcd.print(val0);
-  lcd.setCursor(0,1);
-  lcd.print("val1:");
-  lcd.print(val1);
-  delay(700);
-  lcd.setCursor(0,0);
-  lcd.print("usr0:");
-  lcd.print(user0);
-  lcd.setCursor(0,1);
-  lcd.print("usr1:");
-  lcd.print(user1);
-  delay(700);*/
   //displaying map
   for(;i<16;++i)
   {
@@ -100,63 +90,55 @@

 boolean correct_press()
 {
-  /*lcd.setCursor(0,0);
-  lcd.print(user0);
-  lcd.setCursor(0,1);
-  lcd.print(user1);
-  delay(700);
-   if(user0==val0 && user1==val1)
-   {
-     tone(buzz_pin, 1500, 400);
-     lcd.setCursor(0,0);
-     lcd.print("CORRECT");
-     delay(900);
-   }
-   else{
-     //tone(buzz_pin, 2000, 300);
-     //tone(buzz_pin, 400, 400);
-     lcd.setCursor(0,0);
-     lcd.print("~~~~~~");
-     lcd.setCursor(0,1);
-     lcd.print("~~~~~~");
-     delay(900);
-   }*/
-   delay(80);
+//   delay(80);
    return (user0==val0 && user1==val1);
 }

 void loop()
 {
+  if(start_delay)
+  {
+    delay(400);
+    tone(buzz_pin, 1900, 200);
+    delay(400);
+    tone(buzz_pin, 1900, 200);
+    delay(400);
+    tone(buzz_pin, 1900, 200);
+    delay(400);
+    tone(buzz_pin, 3000, 200);
+  }
+  ++loop_count;
   button_state = digitalRead(button_pin);
   touch_state = digitalRead(touch_pin);
-//  lcd.setCursor(0,0);
-//  lcd.print(touch_state);
-//  lcd.setCursor(0,1);
-//  lcd.print(button_state);
-//  delay(100);
-//  tone(buzz_pin, 900, 40);
   if(button_state == HIGH)
   {
     user1 = 1;
-    /*tone(buzz_pin, 900, 200);
-    lcd.setCursor(0,1);
-    lcd.print("HIHIHIHI");*/
   }
   else
     user1 = 0;
   if(touch_state == HIGH)
   {
     user0 = 1;
-    /*tone(buzz_pin, 1800, 40);
-    lcd.setCursor(0,0);
-    lcd.print("00000");*/
   }
   else
     user0 = 0;
+//  lcd.setCursor(0,0);
+//  lcd.print("user0:");
+//  lcd.print(user0);
+//  lcd.setCursor(0,1);
+//  lcd.print("user1:");
+//  lcd.print(user1);
+//  delay(100);
+  if(start_delay)
+  {
+    delay(300);
+    start_delay = false;
+  }
   if(correct_press())
   {
-    ++ptr0;
-    ++ptr1;
+    //++ptr0;
+    //++ptr1;
+    good = true;
   }
   if(ptr0<ptr_max)
   {
@@ -170,10 +152,30 @@
     lcd.print(blank_writer);
     lcd.print(blank_writer);
     lcd.setCursor(0,0);
-    lcd.print("DONE! GAME OVER");
+    lcd.print("DONE! YOU WON!!");
     lcd.setCursor(0,1);
     lcd.print(blank_writer);
     while(true){}
+  }
+  if(loop_count>=rxn_time && !good)//lost
+  {
+    lcd.setCursor(0,0);
+    lcd.print(blank_writer);
+    lcd.setCursor(0,1);
+    lcd.print(blank_writer);
+    lcd.setCursor(0,0);
+    lcd.print("GAME OVER");
+    //lcd.print(ptr0); //used to figure out which index it failed at
+    lcd.setCursor(0,1);
+    lcd.print("TRY AGAIN");
+    while(true){}
+  }
+  else if(loop_count>=rxn_time && good)//continue
+  {
+    ++ptr0;
+    ++ptr1;
+    loop_count = 0;
+    good = false;
   }
   delay(10);
 }


Fix point controller to add more servos. 13 now

--- examples/servo_point_controler/servo_point_controler.ino
+++ examples/servo_point_controler/servo_point_controler.ino
@@ -24,52 +24,68 @@
 #include <EEPROM.h> //required by the library
 #include <VarSpeedServo.h>

-//uncomment this line to see debug messages
+/* uncomment this line to see debug messages */
 //#define DEBUGNODE

-//Module definitions
-#define NUM_SERVOS 8      //number of servos
-//first 2 are to indicate which servo is on. 2 bytes to indicate to togle. 2 for start and end angle
+/* Module definitions */
+
+#define NUM_SERVOS 13      //number of servos
+
+/* first 2 are to indicate which servo is on. 2 bytes to indicate to togle. 2 for start and end angle */
+
 #define VAR_PER_SERVO 6  //variables per servo
 #define SPEED 50        //servo speed
 #define SERVO_START 15        //servo start angle.start at 15 to avoid jitter
 #define SERVO_END 180        //servo end angle

-//CBUS definitions
-#define GREEN_LED 8                  //merg green led port
-#define YELLOW_LED 7                 //merg yellow led port
+/* CBUS definitions */
+#define GREEN_LED A0                  //merg green led port
+#define YELLOW_LED 0                 //merg yellow led port
 #define PUSH_BUTTON 9                //std merg push button

-//Node definition
-//number o node variables
-#define NODE_VARS 2
-//var1 = Servo speed
-//var2 = flags
-//flag1 (2 first bits) action to take on starting. see setupServos
-//flag2 (bit 3), indicate to maintain the servo attached after moving. default is 0 = detached
+/*
+ * Node definition
+ * number o node variables
+ */
+
+#define NODE_VARS 2
+
+/*
+* var1 = Servo speed
+* var2 = flags
+* flag1 (2 first bits) action to take on starting. see setupServos
+* flag2 (bit 3), indicate to maintain the servo attached after moving. default is 0 = detached
+*/
+
 #define SERVO_SPEED_VAR  1
 #define SERVO_FLAGS_VAR  2

 #define NODE_EVENTS 30              //max number of events
 #define EVENTS_VARS VAR_PER_SERVO   //number of variables per event
 #define DEVICE_NUMBERS NUM_SERVOS   //number of device numbers. each servo can be a device
-//the indexes start at 1 not at 0
+
+/*
+ * the indexes start at 1 not at 0
+ */
+
 #define ACTIVE_SERVO_VAR 1          //2 bytes for that
 #define TOGLE_SERVO_VAR  3          //2 bytes for that
 #define START_ANGLE_VAR  5          //var index for the start angle
 #define END_ANGLE_VAR    6          //var index for the end angle

-//create the merg object
+/* create the merg object */
 MergCBUS cbus=MergCBUS(NODE_VARS,NODE_EVENTS,EVENTS_VARS,DEVICE_NUMBERS);

-//servo controler
+/* servo controler */
 VarSpeedServo servos[NUM_SERVOS];

-//pins where the servos are attached
-//pins 9,10 and 15 don't work for many servos. servo library limitation
-byte servopins[]={1,2,3,4,5,6,7,8};//,19,20,21,22,23,24,25,26,27,28,29,30};
+ /*
+ * pins where the servos are attached
+ * pins 9,10 and 15 don't work for many servos. servo library limitation
+ */
+byte servopins[]={2,3,4,5,6,7,8,1,A1,A2,A3,A4,A5};//,19,20,21,22,23,24,25,26,27,28,29,30};
 byte active_servo[2]; //store the active servo event var
 byte togle_servo[2]; //store the togle servo event var
 boolean attach_servo = false;
@@ -78,7 +94,7 @@

 void setup(){

-  //create the servos object
+  /* create the servos object */
   initializeFlags();
   setupServos();

@@ -89,7 +105,7 @@
   Serial.end();
   #endif

-  //Configuration data for the node
+  /* Configuration data for the node */
   cbus.getNodeId()->setNodeName("MODSERV",7);  //node name
   cbus.getNodeId()->setModuleId(56);            //module number
   cbus.getNodeId()->setManufacturerId(0xA5);    //merg code
@@ -100,7 +116,7 @@
   cbus.setStdNN(999); //standard node number

   if (digitalRead(PUSH_BUTTON)==LOW){
-   // Serial.println("Setup new memory");
+    //Serial.println("Setup new memory");
     cbus.setUpNewMemory();
     cbus.setSlimMode();
     cbus.saveNodeFlags();
@@ -109,8 +125,7 @@
   cbus.setPushButton(PUSH_BUTTON);//set the push button ports
   cbus.setUserHandlerFunction(&myUserFunc);//function that implements the node logic
   cbus.initCanBus(10);  //initiate the transport layer. pin=53, rate=125Kbps,10 tries,200 millis between each try
-
-  //Serial.println("Setup finished");
+
 }

 void loop (){
@@ -126,9 +141,9 @@
   }
 }

-//user defined function. contains the module logic.called every time run() is called.
+/* user defined function. contains the module logic.called every time run() is called.*/
 void myUserFunc(Message *msg,MergCBUS *mcbus){
-  //getting standard on/off events
+  /* getting standard on/off events */

   boolean onEvent;
   unsigned int converted_speed;
@@ -139,20 +154,18 @@
      initializeFlags();
      onEvent=mcbus->isAccOn();
      getServosArray(msg,mcbus);
-    // Serial.println("event match");
+
      servo_start=mcbus->getEventVar(msg,START_ANGLE_VAR);
      servo_end=mcbus->getEventVar(msg,END_ANGLE_VAR);
-     //Serial.println(servo_start);
-     //Serial.println(servo_end);
-      //get the events var and control the servos
+
+      /* get the events var and control the servos */
       for (uint8_t i=0;i<NUM_SERVOS;i++){
-        if (isServoActive(i)){
-          //Serial.print("S ");
-          //Serial.println(i);
+        if (isServoActive(i)){
           moveServo(onEvent,i,servo_start,servo_end);
+          delay(200);
         }
       }
-      //set time to detach the servos. detach after 2 seconds
+      /* set time to detach the servos. detach after 2 seconds */
       detachservos_time=millis() + 2000;
   }
 }
@@ -176,21 +189,23 @@
         lastPos = servo_start;
       }
     }
-    //write last pos to eprom
-   //variables start with number 1
+    /*
+     * write last pos to eprom
+     * variables start with number 1
+     */
     cbus.setInternalNodeVariable(servoidx+1,lastPos);

     servos[servoidx].write(lastPos,SPEED);
-    //servos already attached
+    /* servos already attached */
     //if (!attach_servo){
-	servos[servoidx].attach(servopins[servoidx]);
+	  servos[servoidx].attach(servopins[servoidx]);
     //}
     servos[servoidx].write(lastPos,SPEED);

 }

-//create the objects for each servo
+/* create the objects for each servo */
 void setupServos(){

   for (uint8_t i=0;i<NUM_SERVOS;i++){
@@ -209,9 +224,10 @@
       case 3://move to last position
           moveServoToLastPosition(i);
       break;
-    }
-  }
-  delay(1000);
+    }
+    delay(100);
+  }
+
   detachServos();
 }

@@ -234,16 +250,16 @@
     }
 }

-//is the servo to be activated or not
+/* is the servo to be activated or not */
 boolean isServoActive(uint8_t index){
   return checkBit(active_servo,index);
 }
-//is the servo by index to togle or not
+/* is the servo by index to togle or not */
 boolean isServoToTogle(uint8_t index){
   return checkBit(togle_servo,index);
 }

-//check the if a bit is set or not
+/* check the if a bit is set or not */
 boolean checkBit(byte *array,uint8_t index){
   byte a,i;
   if (index<8){
@@ -262,7 +278,7 @@
      return false;
   }
 }
-//get the events vars for activate servos and to togle the servos:invert behaviour on on/off events
+/* get the events vars for activate servos and to togle the servos:invert behaviour on on/off events */
 void getServosArray(Message *msg,MergCBUS *mcbus){
   active_servo[0]=mcbus->getEventVar(msg,ACTIVE_SERVO_VAR);
   active_servo[1]=mcbus->getEventVar(msg,ACTIVE_SERVO_VAR + 1);
@@ -270,7 +286,7 @@
   togle_servo[1]=mcbus->getEventVar(msg,TOGLE_SERVO_VAR + 1);
 }

-//the the flags var and initialize them
+/* the the flags var and initialize them */
 void initializeFlags(){
     byte flag = cbus.getNodeVar(SERVO_FLAGS_VAR);
     start_action = flag && 0x03; //first 2 bits


Remove warning and ideas

Remove warning and ideas

--- src/homie-sonoff-touch.ino
+++ src/homie-sonoff-touch.ino
@@ -1,15 +1,3 @@
-/* WARNING: untested */
-
-/* Some functional ideas
-  Single, double and triple tap.
-  Single and double tap and hold
-  Single tap = regular on/off
-  Single hold = dim up
-  Double tap = Unknown
-  Double tap and hold = dim down
-  Triple tap = toggle state of onboard relay
-*/
-
 #include <ClickButton.h>
 #include <Homie.h>


optimize

optimize

--- src/nest.ino
+++ src/nest.ino
@@ -40,10 +40,6 @@
   Ethernet.begin(mac);
 }

-const char nestId[] PROGMEM = "nestId:";
-const uint8_t offset PROGMEM =48;
-const uint8_t skydome_port=5506;
-const char skydome[] PROGMEM = "api.skydome.io";
 void loop() {
   uint8_t data[2] PROGMEM;
   if (manager.available()) {
@@ -51,20 +47,20 @@
     uint8_t from;

     if (manager.recvfromAck(data, &len, &from)) {
-      char message[] PROGMEM = {from + offset,':', data[0] + offset,':', data[1] + offset,'\0'};
-      sendMessage(nestId,message);
+     char message[] PROGMEM = {from + 48,':', data[0] + 48,':', data[1] + 48,'\0'};
+
+      sendMessage(message);
     }
   }
 }

-void sendMessage(const char *nestId, char *message) {
-  int success = udp.beginPacket(skydome, skydome_port);
-
+void sendMessage(char *message) {
+  int success = udp.beginPacket("api.skydome.io", 5506);
   Serial.print(F("beginPacket: "));
   Serial.println(success ? F("success") : F("failed"));

-  success = udp.write(nestId);
+  success = udp.write("NestId:");
   success = udp.write(message);

   Serial.print(F("bytes written: "));


erase default speed

erase default speed

--- examples/GPRS_IncomingCall/GPRS_IncomingCall.ino
+++ examples/GPRS_IncomingCall/GPRS_IncomingCall.ino
@@ -7,7 +7,7 @@

 // создаём объект класса GPRS и передаём ему скорость 9600 бод
 // с помощью него будем давать команды GPRS шилду
-GPRS gprs(9600);
+GPRS gprs();

 void setup()
 {


+ Just updated the pins for the ultrasound sensor.

--- ClydeClock/ProxySens.ino
+++ ClydeClock/ProxySens.ino
@@ -1,5 +1,6 @@
 // Now that's the code related to the HC-SR04 sensor.
 // connection notes:
+// Has to be connected to digital pins (NOT A...)
 // Gnd -> GND
 // Echo -> 4
 // Trig -> 12
@@ -7,8 +8,8 @@

 #ifdef ENABLE_PROXYSENS

-uint8_t proxy_sens_trig = A1;  // the pin to which the HC-SR04 trigger pin has been attached.
-uint8_t proxy_sens_echo = A0;  // the pin to which the HC-SR04 echo pin has been attached.
+uint8_t proxy_sens_trig = 12;  // the pin to which the HC-SR04 trigger pin has been attached.
+uint8_t proxy_sens_echo = 4;  // the pin to which the HC-SR04 echo pin has been attached.
 int proxy_sens_basal_dist = 0;  // the basal, initial distance measured by the sensor.
 uint32_t proxy_sens_last_action_triggered = 0;  // keep track of the last triggered action.
 //int PROXY_SENS_THRESH = 1;      // the threshold value, if we get closer by PROXY_SENS_THRESH cm we trigger an action.


Added switch condicionals form Master.

Added switch condicionals form Master.

--- scadacar_sketch/scadacar_sketch.ino
+++ scadacar_sketch/scadacar_sketch.ino
@@ -3,6 +3,7 @@
  Developed by: Ruy García
  Created: July 22, 2014
  By: Ruy García
+ Javascript: parseInt( ( "41 0C 0F A0".substring(6) ).replace(" ",""),16 );
  */

 #include <TinyGPS++.h>
@@ -86,7 +87,7 @@
 void loop()
 {
   readGPS();
-
+  /*
   send_OBD_cmd("ATZ");      //send to OBD ATZ, reset
   delay(1000);
   send_OBD_cmd("ATSP0");    //send ATSP0, protocol auto
@@ -97,6 +98,9 @@
   send_OBD_cmd("0140");     //send 0140, retrieve available pid's 40-??
   delay(1000);
   send_OBD_cmd(PID_RPM);    //send 010C1, RPM cmd
+  */
+  delay(1000);
+  readMaster();
   delay(1000);
 }

@@ -108,15 +112,16 @@
   bt.println(message);
 }

-void readMessage()
+void readMaster()
 {
   if (bt.available() > 0) {
     String msg; //string to store entire command line
     while (bt.available()) {
       msg += bt.read();
-      Serial.print(msg);
-      delay(50);
     }
+    Serial.println(msg);
+    delay(50);
+    checkIncommingCmd( msg.toInt() );
   }
   bt.flush();
 }
@@ -128,9 +133,11 @@
     delay(1000); // wait 1 sec to give time enough for the serial to receive all the stream
     while (obd.available()) {
       msg += obd.read();
-      Serial.print(msg);
-      delay(50);
     }
+    Serial.println(msg);
+    delay(50);
+  } else {
+    sendMessage("No data from OBD2.");
   }
   obd.flush();
 }
@@ -144,11 +151,12 @@
       displayInfo();
     }
   }
+  ss.flush();

   if (millis() > 5000 && gps.charsProcessed() < 10)
   {
     Serial.println(F("No GPS detected: check wiring."));
-    while(true);
+    //while(true);
   }
 }

@@ -187,3 +195,24 @@
   obd.println(obd_cmd);
   readOBD();
 }
+
+void checkIncommingCmd(int cmd)
+{
+  switch (cmd) {
+    case 0:
+      send_OBD_cmd(PID_RPM);
+      break;
+    case 1:
+      send_OBD_cmd(PID_SPEED);
+      break;
+    case 2:
+      send_OBD_cmd(PID_FUEL_LEVEL);
+      break;
+    case 3:
+      send_OBD_cmd(PID_DISTANCE);
+      break;
+    case 4:
+      send_OBD_cmd(PID_THROTTLE);
+      break;
+  }
+}


COH-80: WIP

COH-80: WIP

--- COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
+++ COHEAT2015/20160316-COHEAT-M1/COHEAT-M1/COHEAT-M1.ino
@@ -334,6 +334,7 @@
 #if defined(ENABLE_OTSECUREFRAME_ENCODING_SUPPORT)
 #ifdef ALLOW_CC1_SUPPORT_RELAY
 // Support for secure TX side using FHT8V ID plus 0x80 padding from relay.
+// (High bits of trailing bytes should be high for traffic from node whose ID is in header.)
 // ID is of length OTV0P2BASE::OpenTRV_Node_ID_Bytes.
 static bool getTXID(uint8_t *const id)
   {


Goggles example deleted, moved to guide instead

--- examples/goggles/goggles.ino
+++ examples/goggles/goggles.ino
@@ -1,246 +0,0 @@
-/*
-NeoPixel Ring goggles sketch -- for steampunk, rave or Burning Man fashion!
-Welding or costume goggles using 50mm round lenses can be outfitted with
-a pair of Adafruit NeoPixel Rings: http://www.adafruit.com/product/1463
-
-Please exercise common sense.  These goggles emit a LOT of stray light and
-should NOT BE WORN ON YOUR EYES.  They're for fashion and costuming only,
-for display on a hat or on your forehead.
-
-Draws a spinning rainbow on both eyepieces.  Not a Mac beachball, honest.
-"Eyes" glance around and blink at random.
-
-For 'reflected' colors (rainbows rotate in opposite directions, while eyes
-look in same direction), connect the output of the first ring to the input
-of the second.  Or you can connect the inputs of both rings to the same
-Arduino pin if that's easier -- the rainbows will both twirl in the same
-direction in that case.
-
-By default, pixel #0 (the first LED) on both rings should be at the TOP of
-the goggles.  Looking at the BACK of the board, pixel #0 is immediately
-clockwise from the OUT connection.  If a different pixel is at the top,
-that's OK, the code can compensate (TOP_LED_FIRST and TOP_LED_SECOND below).
-
-IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
-pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
-and minimize distance between Arduino and first pixel.  Avoid connecting
-on a live circuit...if you must, connect GND first.
-*/
-
-#include <Adafruit_NeoPixel.h>
-#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
-  #include <avr/power.h>
-#endif
-
-#define PIN            0
-
-#define TOP_LED_FIRST  0 // Change these if the first pixel is not
-#define TOP_LED_SECOND 0 // at the top of the first and/or second ring.
-
-#define EFFECT         RAINBOW // Choose a visual effect from the names below
-
-#define RAINBOW        0
-#define ECTO           1
-
-Adafruit_NeoPixel pixels = Adafruit_NeoPixel(32, PIN, NEO_GRB + NEO_KHZ800);
-
-const int8_t PROGMEM
-  yCoord[] = { // Vertical coordinate of each pixel.  First pixel is at top.
-    127,117,90,49,0,-49,-90,-117,-127,-117,-90,-49,0,49,90,117 },
-  sine[] = { // Brightness table for ecto effect
-    0, 28, 96, 164, 192, 164, 96, 28, 0, 28, 96, 164, 192, 164, 96, 28 };
-
-// Eyelid vertical coordinates.  Eyes shut slightly below center.
-#define upperLidTop     130
-#define upperLidBottom  -45
-#define lowerLidTop     -40
-#define lowerLidBottom -130
-
-// Gamma correction improves appearance of midrange colors
-const uint8_t PROGMEM gamma8[] = {
-      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-      0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,
-      1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-      3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  5,  6,  6,  6,  6,  7,
-      7,  7,  8,  8,  8,  9,  9,  9, 10, 10, 10, 11, 11, 11, 12, 12,
-     13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
-     20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29,
-     30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
-     42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-     58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75,
-     76, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96,
-     97, 99,100,102,103,105,106,108,109,111,112,114,115,117,119,120,
-    122,124,125,127,129,130,132,134,136,137,139,141,143,145,146,148,
-    150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,
-    182,184,186,188,191,193,195,197,199,202,204,206,209,211,213,215,
-    218,220,223,225,227,230,232,235,237,240,242,245,247,250,252,255
-};
-
-uint32_t
-  iColor[16][3];      // Background colors for eyes
-int16_t
-  hue          =   0; // Initial hue around perimeter (0-1535)
-uint8_t
-  iBrightness[16],    // Brightness map -- eye colors get scaled by these
-  brightness   = 220, // Global brightness (0-255)
-  blinkFrames  =   5, // Speed of current blink
-  blinkCounter =  30, // Countdown to end of next blink
-  eyePos       = 192, // Current 'resting' eye (pupil) position
-  newEyePos    = 192, // Next eye position when in motion
-  gazeCounter  =  75, // Countdown to next eye movement
-  gazeFrames   =  50; // Duration of eye movement (smaller = faster)
-int8_t
-  eyeMotion    =   0; // Distance from prior to new position
-
-
-void setup() {
-#ifdef __AVR_ATtiny85__ // Trinket, Gemma, etc.
-  if(F_CPU == 16000000) clock_prescale_set(clock_div_1);
-  // Seed random number generator from an unused analog input:
-  randomSeed(analogRead(2));
-#else
-  randomSeed(analogRead(A0));
-#endif
-
-  pixels.begin();
-}
-
-void loop() {
-  uint8_t i, r, g, b, a, c, inner, outer, ep;
-  int     y1, y2, y3, y4, h;
-  int8_t  y;
-
-  // Draw eye background colors
-
-#if EFFECT == RAINBOW
-
-  // This renders a glotating rainbow...a WAY overdone LED effect but
-  // does show the color gamut nicely.
-
-  for(h=hue, i=0; i<16; i++, h += 96) {
-    a = h;
-    switch((h >> 8) % 6) {
-     case 0: iColor[i][0] = 255; iColor[i][1] =   a; iColor[i][2] =   0; break;
-     case 1: iColor[i][0] =  ~a; iColor[i][1] = 255; iColor[i][2] =   0; break;
-     case 2: iColor[i][0] =   0; iColor[i][1] = 255; iColor[i][2] =   a; break;
-     case 3: iColor[i][0] =   0; iColor[i][1] =  ~a; iColor[i][2] = 255; break;
-     case 4: iColor[i][0] =   a; iColor[i][1] =   0; iColor[i][2] = 255; break;
-     case 5: iColor[i][0] = 255; iColor[i][1] =   0; iColor[i][2] =  ~a; break;
-    }
-  }
-  hue += 7;
-  if(hue >= 1536) hue -= 1536;
-
-#elif EFFECT == ECTO
-
-  // A steampunk aesthetic might fare better with this more subdued effect.
-  // Etherial green glow with just a little animation for visual spice.
-
-  a = (hue >> 4) & 15;
-  c =  hue       & 15;
-  for(i=0; i<16; i++) {
-    b = (a + 1) & 15;
-    iColor[i][1] = 255; // Predominantly green
-    iColor[i][0] = (pgm_read_byte(&sine[a]) * (16 - c) +
-                    pgm_read_byte(&sine[b]) *       c  ) >> 4;
-    iColor[i][2] = iColor[i][0] >> 1;
-    a = b;
-  }
-  hue -= 3;
-
-#endif
-
-  // Render current blink (if any) into brightness map
-  if(blinkCounter <= blinkFrames * 2) { // In mid-blink?
-    if(blinkCounter > blinkFrames) {    // Eye closing
-      outer = blinkFrames * 2 - blinkCounter;
-      inner = outer + 1;
-    } else {                            // Eye opening
-      inner = blinkCounter;
-      outer = inner - 1;
-    }
-    y1 = upperLidTop    - (upperLidTop - upperLidBottom) * outer / blinkFrames;
-    y2 = upperLidTop    - (upperLidTop - upperLidBottom) * inner / blinkFrames;
-    y3 = lowerLidBottom + (lowerLidTop - lowerLidBottom) * inner / blinkFrames;
-    y4 = lowerLidBottom + (lowerLidTop - lowerLidBottom) * outer / blinkFrames;
-    for(i=0; i<16; i++) {
-      y = pgm_read_byte(&yCoord[i]);
-      if(y > y1) {        // Above top lid
-        iBrightness[i] = 0;
-      } else if(y > y2) { // Blur edge of top lid in motion
-        iBrightness[i] = brightness * (y1 - y) / (y1 - y2);
-      } else if(y > y3) { // In eye
-        iBrightness[i] = brightness;
-      } else if(y > y4) { // Blur edge of bottom lid in motion
-        iBrightness[i] = brightness * (y - y4) / (y3 - y4);
-      } else {            // Below bottom lid
-        iBrightness[i] = 0;
-      }
-    }
-  } else { // Not in blink -- set all 'on'
-    memset(iBrightness, brightness, sizeof(iBrightness));
-  }
-
-  if(--blinkCounter == 0) { // Init next blink?
-    blinkFrames  = random(4, 8);
-    blinkCounter = blinkFrames * 2 + random(5, 180);
-  }
-
-  // Calculate current eye movement, possibly init next one
-  if(--gazeCounter <= gazeFrames) { // Is pupil in motion?
-    ep = newEyePos - eyeMotion * gazeCounter / gazeFrames; // Current pos.
-    if(gazeCounter == 0) {                   // Last frame?
-      eyePos      = newEyePos;               // Current position = new pos
-      newEyePos   = random(16) * 16;         // New pos. (always pixel center)
-      eyeMotion   = newEyePos - eyePos;      // Distance to move
-      gazeFrames  = random(10, 20);          // Duration of movement
-      gazeCounter = random(gazeFrames, 130); // Count to END of next movement
-    }
-  } else ep = eyePos; // Not moving -- fixed gaze
-
-  // Draw pupil -- 2 pixels wide, but sup-pixel positioning may span 3.
-  a = ep >> 4;         // First candidate
-  b = (a + 1)  & 0x0F; // 1 pixel CCW of a
-  c = (a + 2)  & 0x0F; // 2 pixels CCW of a
-  i = ep & 0x0F;       // Fraction of 'c' covered (0-15)
-  iBrightness[a] = (iBrightness[a] *       i ) >> 4;
-  iBrightness[b] = 0;
-  iBrightness[c] = (iBrightness[c] * (16 - i)) >> 4;
-
-  // Merge iColor with iBrightness, issue to NeoPixels
-  for(i=0; i<16; i++) {
-    a = iBrightness[i] + 1;
-    // First eye
-    r = iColor[i][0];            // Initial background RGB color
-    g = iColor[i][1];
-    b = iColor[i][2];
-    if(a) {
-      r = (r * a) >> 8;          // Scale by brightness map
-      g = (g * a) >> 8;
-      b = (b * a) >> 8;
-    }
-    pixels.setPixelColor(((i + TOP_LED_FIRST) & 15),
-      pgm_read_byte(&gamma8[r]), // Gamma correct and set pixel
-      pgm_read_byte(&gamma8[g]),
-      pgm_read_byte(&gamma8[b]));
-
-    // Second eye uses the same colors, but reflected horizontally.
-    // The same brightness map is used, but not reflected (same left/right)
-    r = iColor[15 - i][0];
-    g = iColor[15 - i][1];
-    b = iColor[15 - i][2];
-    if(a) {
-      r = (r * a) >> 8;
-      g = (g * a) >> 8;
-      b = (b * a) >> 8;
-    }
-    pixels.setPixelColor(16 + ((i + TOP_LED_SECOND) & 15),
-      pgm_read_byte(&gamma8[r]),
-      pgm_read_byte(&gamma8[g]),
-      pgm_read_byte(&gamma8[b]));
-  }
-  pixels.show();
-
-  delay(15);
-}
-


Dynamic VU bar coloring

Dynamic VU bar coloring

--- ArduinoAudioSpectrumAnalyzer.ino
+++ ArduinoAudioSpectrumAnalyzer.ino
@@ -200,7 +200,9 @@
 	if (peakLevelXpos < barWidth)
 		peakLevelXpos = barWidth;

-	tft.fillRect(0, vuYpos, barWidth, vuHeight, RGB_to_565(0, 255, 30));
+	const uint16_t vuBarColor = rms < 512 ? RGB_to_565(rms / 2, 255, 30) : RGB_to_565(255, (rms - 512) / 2, 30);
+
+	tft.fillRect(0, vuYpos, barWidth, vuHeight, vuBarColor);
 	tft.fillRect(barWidth + 1, vuYpos, ScreenWidth - vuTextWidth - barWidth, vuHeight, RGB_to_565(0, 0, 0));
 	tft.drawFastVLine(peakLevelXpos, vuYpos, vuHeight, RGB_to_565(255, 0, 30));


Update master.ino

Update master.ino

--- Modules/i2c_test/i2c_string/master.ino
+++ Modules/i2c_test/i2c_string/master.ino
@@ -1,7 +1,11 @@
-// Tested on UNO
-
-// Based on Wire Master Reader
-// by Nicholas Zambetti <http://www.zambetti.com>
+/* Tested on the Arduion UNO
+ * Connect SDA/SDL/3.3V/GND to Attiny85 running slave code
+ * Open Serial port to see results
+ * Don't forget to match up your slave device ID below
+ *
+ * based on Wire Master Reader
+ * by Nicholas Zambetti <http://www.zambetti.com>
+*/

 #include <Wire.h>

@@ -11,7 +15,7 @@
 }

 void loop() {
-  Wire.requestFrom(10, 2);    // request x bytes from slave device #y
+  Wire.requestFrom(10, 32);    // request 32 bytes from slave device #10

   while (Wire.available()) { // slave may send less than requested
     char c = Wire.read(); // receive a byte as character


Delete LDRyLED_web.ino

Delete LDRyLED_web.ino

in dir parte_II

--- parte_I/LDRyLED_web.ino
+++ parte_I/LDRyLED_web.ino
@@ -1,131 +0,0 @@
-#include <SPI.h>  //Importamos librería comunicación SPI
-#include <Ethernet.h>  //Importamos librería Ethernet
-
-byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };//Ponemos la dirección MAC de la Ethernet Shield que está con una etiqueta debajo la placa
-IPAddress ip(192,168,1,100); //Asingamos la IP al Arduino
-EthernetServer server(80); //Creamos un servidor Web con el puerto 80 que es el puerto HTTP por defecto
-
-int led=3; //Pin del led
-String estado="OFF"; //Estado del Led inicialmente "OFF"
-
-int LDR = 0;
-float photocell = 0;
-
-
-void setup()
-{
-  Serial.begin(9600);
-
-  // Inicializamos la comunicación Ethernet y el servidor
-  Ethernet.begin(mac, ip);
-  server.begin();
-  Serial.print("server is at ");
-  Serial.println(Ethernet.localIP());
-
-  pinMode(led,OUTPUT);
-  pinMode(LDR, INPUT);
-
-}
-
-void loop()
-{
-  EthernetClient client = server.available(); //Creamos un cliente Web
-  //Cuando detecte un cliente a través de una petición HTTP
-  if (client) {
-    Serial.println("new client");
-    boolean currentLineIsBlank = true; //Una petición HTTP acaba con una línea en blanco
-    String cadena=""; //Creamos una cadena de caracteres vacía
-    while (client.connected()) {
-      if (client.available()) {
-        char c = client.read();//Leemos la petición HTTP carácter por carácter
-        Serial.write(c);//Visualizamos la petición HTTP por el Monitor Serial
-        cadena.concat(c);//Unimos el String 'cadena' con la petición HTTP (c). De esta manera convertimos la petición HTTP a un String
-
-         //Ya que hemos convertido la petición HTTP a una cadena de caracteres, ahora podremos buscar partes del texto.
-         int posicion=cadena.indexOf("LED="); //Guardamos la posición de la instancia "LED=" a la variable 'posicion'
-
-          if(cadena.substring(posicion)=="LED=ON")//Si a la posición 'posicion' hay "LED=ON"
-          {
-            digitalWrite(led,HIGH);
-            estado="ON";
-          }
-          if(cadena.substring(posicion)=="LED=OFF")//Si a la posición 'posicion' hay "LED=OFF"
-          {
-            digitalWrite(led,LOW);
-            estado="OFF";
-          }
-
-        //Cuando reciba una línea en blanco, quiere decir que la petición HTTP ha acabado y el servidor Web está listo para enviar una respuesta
-        if (c == '\n' && currentLineIsBlank) {
-
-            // Enviamos al cliente una respuesta HTTP
-            client.println("HTTP/1.1 200 OK");
-            client.println("Content-Type: text/html");
-            client.println();
-
-
-            //Página web en formato HTML
-            client.println("");
-            client.println("");
-            client.println("");
-            client.println("");
-            // auto reload webpage every 4 second
-            client.println("<META HTTP-EQUIV=REFRESH CONTENT=4 URL=>");
-
-            client.println("
Arduino + Ethernet Shield

LED y LDR controlado por Servidor Web con Arduino

");
-            client.println("
");
-
-            //LDR WEB
-            photocell = analogRead(LDR);
-            client.print("

Valor Sensor Luz = ");
-            client.println(photocell, 2);
-            client.println("

");
-
-
-            if (photocell > 10) {
-              client.println("

Hay Luz!

");
-              }
-              else if (photocell == 0){
-                client.println("

No hay Luz

");
-                  }
-                else {
-                        client.println("

Hay poca Luz.

");
-              }
-
-            //Creamos los botones. Para enviar parametres a través de HTML se utiliza el metodo URL encode. Los parámetros se envian a través del símbolo '?'
-
-            client.print("
CONTROL DEL LED
");
-
-            if (estado == "ON") {
-              client.println("
ENCENDIDO
");
-              }
-              else if (estado == "OFF"){
-                client.println("
APAGADO
");
-                  }
-
-
-            client.println("<button onClick=location.href='./?LED=ON\' style='margin:auto;background-color: #84B1FF;color: snow;padding: 10px;border: 1px solid #3F7CFF;width:65px;'>");
-            client.println("ON");
-            client.println("</button>");
-            client.println("<button onClick=location.href='./?LED=OFF\' style='margin:auto;background-color: #84B1FF;color: snow;padding: 10px;border: 1px solid #3F7CFF;width:65px;'>");
-            client.println("OFF");
-            client.println("</button>");
-            client.println("

");
-            client.println("
");
-            client.println("");
-            client.println("");
-            break;
-        }
-        if (c == '\n') {
-          currentLineIsBlank = true;
-        }
-        else if (c != '\r') {
-          currentLineIsBlank = false;
-        }
-      }
-    }
-    //Dar tiempo al navegador para recibir los datos
-    delay(1);
-    client.stop();// Cierra la conexión
-  }
-}


Update teensytransfertool.ino

Update teensytransfertool.ino


Entirely untested lift of watchdog and timeout code from https://github.com/enc-X/sonoff-homie

--- src/homie-sonoff-touch.ino
+++ src/homie-sonoff-touch.ino
@@ -29,12 +29,81 @@
 // Milliseconds to wait per cycle for a held command.
 const int waitInterval = 100;

+// EEPROM structure
+struct EEpromDataStruct {
+  int keepAliveTimeOut; // 0 - disabled, keepalive time - seconds
+  bool initialState;  // Initial state (just after boot - homie independet)
+  int watchDogTimeOut; // 0 - disabled, watchdog time limit - seconds
+};
+
+EEpromDataStruct EEpromData;
+
 // Associate the PIN_BUTTON GPIO with the ClickButton library
 ClickButton button1(PIN_BUTTON, LOW, CLICKBTN_PULLUP);

 // Register our two HomieNode instances
 HomieNode relayNode("relay", "relay");
 HomieNode buttonNode("button", "button");
+HomieNode keepAliveNode("keepalive", "keepalive");
+HomieNode watchDogNode("watchdog", "Watchdog mode");
+
+/*
+ * Recevied tick message for watchdog
+ */
+bool watchdogTickHandler(const HomieRange& range, const String& value)
+{
+  if (value == "0")
+  {
+    watchDogCounterStart = 0;
+  } else {
+    watchDogCounterStart = millis();
+  }
+  return true;
+}
+/*
+ * Received watchdog timeout value
+ */
+bool watchdogTimeOutHandler(const HomieRange& range, const String& value)
+{
+  int oldValue = EEpromData.watchDogTimeOut;
+  if (value.toInt() > 15)
+  {
+    EEpromData.watchDogTimeOut = value.toInt();
+  }
+  if (value=="0")
+  {
+    EEpromData.watchDogTimeOut = 0;
+  }
+
+  if (oldValue!=EEpromData.watchDogTimeOut)
+  {
+    String outMsg = String(EEpromData.watchDogTimeOut);
+    watchDogNode.setProperty("timeOut").send(outMsg);
+    EEPROM.put(0, EEpromData);
+    EEPROM.commit();
+  }
+}
+/*
+ * Initial mode handler
+ */
+bool relayInitModeHandler(HomieRange range, String value)
+{
+  int oldValue = EEpromData.initialState;
+  if (value.toInt() == 1 or value=="ON")
+  {
+    relayNode.setProperty("relayInitMode").send("1");
+    EEpromData.initialState=1;
+  } else {
+    relayNode.setProperty("relayInitMode").send( "0");
+    EEpromData.initialState=0;
+  }
+  if (oldValue!=EEpromData.initialState)
+  {
+    EEPROM.put(0, EEpromData);
+    EEPROM.commit();
+  }
+  return true;
+}

 bool RelayHandler(const HomieRange& range, const String& value) {
   /*
@@ -138,8 +207,17 @@
 }

 void setup() {
+  EEPROM.begin(sizeof(EEpromData));
+  EEPROM.get(0,EEpromData);
   pinMode(PIN_RELAY, OUTPUT);
-  digitalWrite(PIN_RELAY, LOW);
+  //digitalWrite(PIN_RELAY, LOW);
+  if (EEpromData.initialState)
+  {
+    digitalWrite(PIN_RELAY,1);
+  } else {
+    digitalWrite(PIN_RELAY,0);
+    EEpromData.initialState=0;
+  }

   // Setup button timers (all in milliseconds / ms)
   // (These are default if not set, but changeable for convenience)
@@ -151,8 +229,17 @@
   Homie.setLedPin(PIN_LED, HIGH); // Status LED
   // This is a full reset, and will wipe the config
   Homie.setResetTrigger(PIN_BUTTON, LOW, 30000);
+  Homie.setSetupFunction(setupHandler);
   Homie.setLoopFunction(loopHandler);
   relayNode.advertise("relayState").settable(RelayHandler);
+  relayNode.advertise("relayTimer").settable(relayTimerHandler);
+  relayNode.advertise("relayInitMode").settable(relayInitModeHandler);
+  watchDogNode.advertise("tick").settable(watchdogTickHandler);
+  watchDogNode.advertise("timeOut").settable(watchdogTimeOutHandler);
+  keepAliveNode.advertise("tick").settable(keepAliveTickHandler);
+  keepAliveNode.advertise("timeOut").settable(keepAliveTimeOutHandler);
+
+  Homie.onEvent(onHomieEvent);
   Homie.setup();
 }


adding multi-tap support

adding multi-tap support

--- firmware/beer/beersensor.ino
+++ firmware/beer/beersensor.ino
@@ -17,103 +17,121 @@
 #define EEPROM_ADDR_PULSE_COUNT 1
 #define EEPROM_ADDR_MAX_PULSE_COUNT 2
 #define EEPROM_ADDR_PERCENT_FULL 3
-#define PIXEL_PIN D2
 #define PIXEL_TYPE WS2812B
 #define PIXEL_COUNT 14

-Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
-
 int ledPin = D7;

-int pin0 = A0;
-int pin1 = D1;
-int pin2 = A2;
-int pin3 = D3;
-int pin4 = A4;
-int pin5 = D5;
-int pin6 = D6;
-
-int pin0Value = 0;
-int pin1Value = 0;
-int pin2Value = 0;
-int pin3Value = 0;
-int pin4Value = 0;
-int pin5Value = 0;
-int pin6Value = 0;
-
-int instantPulseCount = 0;
-int previousPulseCount = 0;
-bool flowing = false;
-int pulseCount = 200;
-int maxPulseCount = 200; //bogus init value //real value for chad's fridge left tap: 45 pulses / qt = 900 pulses for a 5 gal keg
-int percentFull = 100;
+int flowTapPin0 = D6;
+int flowTapPin1 = D5;
+int flowTap2Pin = D4;
+
+int ledTapPin0 = D3;
+int ledTapPin1 = D2;
+int ledTapPin2 = D1;
+
+Adafruit_NeoPixel stripT0 = Adafruit_NeoPixel(PIXEL_COUNT, ledTapPin0, PIXEL_TYPE);
+Adafruit_NeoPixel stripT1 = Adafruit_NeoPixel(PIXEL_COUNT, ledTapPin1, PIXEL_TYPE);
+Adafruit_NeoPixel stripT2 = Adafruit_NeoPixel(PIXEL_COUNT, ledTapPin2, PIXEL_TYPE);
+
+int flowTapPin0Value = 0;
+int flowTapPin1Value = 0;
+int flowTapPin2Value = 0;
+
+//tap 0 values
+int instantPulseCountT0 = 0;
+int previousPulseCountT0 = 0;
+bool flowingT0 = false;
+int pulseCountT0 = 200;
+int maxPulseCountT0 = 200; //calibration value
+
+//tap 1 values
+int instantPulseCountT1 = 0;
+int previousPulseCountT1 = 0;
+bool flowingT1 = false;
+int pulseCountT1 = 200;
+int maxPulseCountT1 = 200; //calibration value
+
+//tap 3 values
+int instantPulseCountT2 = 0;
+int previousPulseCountT2 = 0;
+bool flowingT2 = false;
+int pulseCountT2 = 200;
+int maxPulseCountT2 = 200; //calibration value
+
+int percentFullT0 = 100;
+int percentFullT1 = 100;
+int percentFullT2 = 100;
+
 int currentSecond = 1;
 int previousSecond = 0;
 int animationStep = 0;
 String *strArr = new String[20];

-const char* pin0Name = "pin0Value";
-const char* pin1Name = "pin1Value";
-const char* pin2Name = "pin2Value";
-const char* pin3Name = "pin3Value";
-const char* pin4Name = "pin4Value";
-const char* pin5Name = "pin5Value";
-const char* pin6Name = "pin6Value";
+const char* flowTapPin0Name = "flowTapPin0Val";
+const char* flowTapPin1Name = "flowTapPin1Val";
+const char* flowTapPin2Name = "flowTapPin2Val";

 int handlePost(String command);

 void setup()
 {
   Serial.begin(9600);
-  strip.begin();
-  strip.setPixelColor(0, strip.Color(0,0,255));
-  strip.show();
-
-  //get persistent values
-//   pulseCount = EEPROM.read(EEPROM_ADDR_PULSE_COUNT);
-//   maxPulseCount = EEPROM.read(EEPROM_ADDR_MAX_PULSE_COUNT);
-//   percentFull = EEPROM.read(EEPROM_ADDR_PERCENT_FULL);
+  stripT0.begin();
+  stripT1.begin();
+  stripT2.begin();
+  //set strips pixel 0 to red until setup is done
+  stripT0.setPixelColor(0, strip.Color(255,0,0));
+  stripT1.setPixelColor(0, strip.Color(255,0,0));
+  stripT2.setPixelColor(0, strip.Color(255,0,0));
+  stripT0.show();
+  stripT1.show();
+  stripT2.show();

   //pin modes
-  pinMode(pin0, INPUT_PULLDOWN);
-  pinMode(pin1, INPUT_PULLDOWN);
-  pinMode(pin2, INPUT_PULLDOWN);
-  pinMode(pin3, INPUT_PULLDOWN);
-  pinMode(pin4, INPUT_PULLDOWN);
-  pinMode(pin5, INPUT_PULLDOWN);
-  pinMode(pin6, INPUT_PULLDOWN);
-
+  pinMode(flowTapPin0, INPUT_PULLDOWN);
+  pinMode(flowTapPin1, INPUT_PULLDOWN);
+  pinMode(flowTapPin2, INPUT_PULLDOWN);
+
   pinMode(ledPin, OUTPUT);

   //read any values set in the EEPROM
-  maxPulseCount = EEPROM.read(EEPROM_ADDR_MAX_PULSE_COUNT);
-  pulseCount = EEPROM.read(EEPROM_ADDR_PULSE_COUNT);
-  percentFull = EEPROM.read(EEPROM_ADDR_PERCENT_FULL);
-
-  //cloud variables
-//   Spark.variable(pin0Name, &pin0Value, INT);
-//   Spark.variable(pin1Name, &pin1Value, INT);
-//   Spark.variable(pin2Name, &pin2Value, INT);
-//   Spark.variable(pin3Name, &pin3Value, INT);
-//   Spark.variable(pin4Name, &pin4Value, INT);
-//   Spark.variable(pin5Name, &pin5Value, INT);
-  Spark.variable(pin6Name, &pin6Value, INT);
+  // maxPulseCount = EEPROM.read(EEPROM_ADDR_MAX_PULSE_COUNT);
+  // pulseCount = EEPROM.read(EEPROM_ADDR_PULSE_COUNT);
+  // percentFull = EEPROM.read(EEPROM_ADDR_PERCENT_FULL);

   //https://api.particle.io/v1/devices/<device_id>/<variable_name>?access_token=<access_token>
-  Spark.variable("maxPCount", &maxPulseCount, INT);
-  Spark.variable("instPCount", &instantPulseCount, INT);
-  Spark.variable("pulseCount", &pulseCount, INT);
-  Spark.variable("percentFull", &percentFull, INT);
+  Spark.variable("maxPCountTap0", &maxPulseCountT0, INT);
+  Spark.variable("instPCountTap0", &instantPulseCountT0, INT);
+  Spark.variable("pulseCountTap0", &pulseCountT0, INT);
+  Spark.variable("percentFullTap0", &percentFullT0, INT);
+
+  Spark.variable("maxPCountTap1", &maxPulseCountT1, INT);
+  Spark.variable("instPCountTap1", &instantPulseCountT1, INT);
+  Spark.variable("pulseCountTap1", &pulseCountT1, INT);
+  Spark.variable("percentFullTap1", &percentFullT1, INT);
+
+  Spark.variable("maxPCountTap2", &maxPulseCountT2, INT);
+  Spark.variable("instPCountTap2", &instantPulseCountT2, INT);
+  Spark.variable("pulseCountTap2", &pulseCountT2, INT);
+  Spark.variable("percentFullTap2", &percentFullT2, INT);

   //cloud functions - handle a cloud POST(data)
   //curl https://api.particle.io/v1/devices/<device_id>/post \
   // -d access_token=<access_token> \
   // -d "args=<command>,<data0>,<dataN>"
   Spark.function("post", handlePost);
-  strip.setPixelColor(0, strip.Color(255,0,255));
-  strip.show();
-}
-
+
+  //set pixel 0 to green when setup is done
+  stripT0.setPixelColor(0, strip.Color(0,255,0));
+  stripT1.setPixelColor(0, strip.Color(0,255,0));
+  stripT2.setPixelColor(0, strip.Color(0,255,0));
+  stripT0.show();
+  stripT1.show();
+  stripT2.show();
+}
+
+//TODO: make this work for 3 taps
 int handlePost(String postData)
 {
   String* args = stringSplit(postData, ',');
@@ -136,46 +154,68 @@

 void loop()
 {
-//   pinVal(pin0, &pin0Value, pin0Name);
-//   pinVal(pin1, &pin1Value, pin1Name);
-//   pinVal(pin3, &pin3Value, pin3Name);
-//   pinVal(pin4, &pin4Value, pin4Name);
-//   pinVal(pin5, &pin5Value, pin5Name);
-  pinVal(pin6, &pin6Value, pin6Name);
-
-  float percent = (float)pulseCount / (float)maxPulseCount;
-  percentFull = (int)(percent * 100.0f);
-  if(percentFull > 100)
-    percentFull = 100;
-  EEPROM.update(EEPROM_ADDR_PERCENT_FULL, percentFull);
-
-  if(flowing)
-  {
-    animateTap();
+  pinVal(flowTapPin0, &flowTapPin0Value, flowTapPin0Name);
+  pinVal(flowTapPin1, &flowTapPin1Value, flowTapPin1Name);
+  pinVal(flowTapPin2, &flowTapPin2Value, flowTapPin2Name);
+
+  float percent = (float)pulseCountT0 / (float)maxPulseCountT0;
+  percentFullT0 = (int)(percent * 100.0f);
+  if(percentFullT0 > 100)
+    percentFullT0 = 100;
+  // EEPROM.update(EEPROM_ADDR_PERCENT_FULL, percentFull);
+
+  if(flowingT0)
+  {
+    animateTap(stripT0);
   }
   else
   {
-    if(pulseCount > maxPulseCount)
-      pulseCount = maxPulseCount;
-    EEPROM.update(EEPROM_ADDR_PULSE_COUNT, pulseCount);
-    recalculateTapColor();
+    if(pulseCountT0 > maxPulseCountT0)
+      pulseCountT0 = maxPulseCountT0;
+    // EEPROM.update(EEPROM_ADDR_PULSE_COUNT, pulseCount);
+    recalculateTapColor(stripT0);
+  }
+
+  if(flowingT1)
+  {
+    animateTap(stripT1);
+  }
+  else
+  {
+    if(pulseCountT1 > maxPulseCountT1)
+      pulseCountT1 = maxPulseCountT1;
+    // EEPROM.update(EEPROM_ADDR_PULSE_COUNT, pulseCount);
+    recalculateTapColor(stripT1);
+  }
+
+  if(flowingT2)
+  {
+    animateTap(stripT2);
+  }
+  else
+  {
+    if(pulseCountT0 > maxPulseCountT2)
+      pulseCountT0 = maxPulseCountT2;
+    // EEPROM.update(EEPROM_ADDR_PULSE_COUNT, pulseCount);
+    recalculateTapColor(stripT2);
   }
 }

 int resetPulseCount()
 {
-  pulseCount = maxPulseCount;
-  EEPROM.update(EEPROM_ADDR_PULSE_COUNT, pulseCount);
+  // pulseCount = maxPulseCount;
+  // EEPROM.update(EEPROM_ADDR_PULSE_COUNT, pulseCount);
   return 1;
 }

 int setCalibration(int val)
 {
-  maxPulseCount = val;
-  EEPROM.update(EEPROM_ADDR_MAX_PULSE_COUNT, maxPulseCount);
-}
-
-void pinVal(int pin, int* pinValue, String pinName)
+  // maxPulseCount = val;
+  // EEPROM.update(EEPROM_ADDR_MAX_PULSE_COUNT, maxPulseCount);
+}
+
+void pinVal(int pin, int* pinValue, String pinName, int* pulseCount,
+            int* previousPulseCount, int* instantPulseCount, bool* flowing)
 {
   if(digitalRead(pin) == HIGH)
   {
@@ -201,12 +241,6 @@
   currentSecond = Time.second();
   if(currentSecond != previousSecond)
   {
-      Serial.println("pinVal Next second");
-      Serial.println(previousPulseCount);
-      Serial.println(pulseCount);
-      Serial.println(flowing);
-      Serial.println("-------------");
-      // setPixels(instantPulseCount);
       instantPulseCount = 0;
       if(previousPulseCount != pulseCount)
         flowing = true;
@@ -214,10 +248,6 @@
         flowing = false;
       previousPulseCount = pulseCount;
       previousSecond = currentSecond;
-      Serial.println(previousPulseCount);
-      Serial.println(pulseCount);
-      Serial.println(flowing);
-      Serial.println("================");
   }
 }


Do not use delay() in interrupts

Do not use delay() in interrupts

Since delay() itself is made on interrupts, the use of it
is not recommended (or necessary).
delayMicroseconds() has a fine resolution of 0..16k us,
which is way less that what we need.
After all, delaying in interrupts may be not such a great idea.

--- bb/bb.ino
+++ bb/bb.ino
@@ -6,10 +6,10 @@
 #include "bb.h"
 #include "music.h"

+#define DEBUG
+
 Servo pan, tilt;
 Servo left, right;
-
-// TODO: use map() and constrain(TILT)

 /*
  * BotBoarduino PINs
@@ -39,6 +39,12 @@
 #define PIN_ANALOG_I2C_SDA      4 // i2c enabled by jumper
 #define PIN_ANALOG_I2C_SCL      5 // i2c enabled by jumper

+#ifdef DEBUG
+#  define Log Serial.println
+#else
+#  define Log(...)
+#endif
+
 // TODO: read these from Arduino Nano (protocol = ?)
 unsigned long encoder_left_front = 0, encoder_left_back = 0,
               encoder_right_front = 0, encoder_right_back = 0;
@@ -53,33 +59,13 @@
 uint16_t status = 0;

 #define BUSY(module, ifnotready) { \
-  if (!(status & (MODULE_ ## module))) { \
+  if (!(status & (1 << MODULE_ ## module))) { \
+    Log("Module " #module " received a command but is not ready."); \
     { ifnotready; } \
   } \
   (status = status & ~(MODULE_ ## module)); \
 }
 #define READY(module) (status |= (1 << MODULE_ ## module))
-
-// Motor state can only be changed at STEP per DELAY max speed
-#define APPROACH_STEP 45
-#define APPROACH_DELAY 200
-
-// Max time for Servo to reach new position (worst case, 180 degree turn)
-#define MAX_SERVO_ROTATE_TIME 200
-
-void approach(Servo *servo, byte value) {
-  int16_t delta = ((int16_t)servo->read()) - value;
-  while (abs(delta) > APPROACH_STEP) {
-    if (delta > 0) {
-      delta -= APPROACH_STEP;
-    } else {
-      delta += APPROACH_STEP;
-    }
-    servo->write(delta + value);
-    delay(APPROACH_DELAY);
-  }
-  servo->write(value);
-}

 void attachMotor(boolean attach) {
   if (attach) {
@@ -120,6 +106,10 @@
   Wire.onReceive(i2cReceive);
   READY(BOARD);

+#ifdef DEBUG
+  Serial.begin(9600);
+#endif
+
   environment_sensor.begin();
   // not: READY(ENVIRONMENT_SENSOR);
   // (do not make it ready until the first measurement)
@@ -197,25 +187,21 @@
     case REGISTER(PAN):
       BUSY(PAN, return);
       pan.write(value8);
-      delay(MAX_SERVO_ROTATE_TIME);
       READY(PAN);
       break;
     case REGISTER(TILT):
-      if (value8 <= MAX_TILT) {
-        BUSY(TILT, return);
-        tilt.write(value8);
-        delay(MAX_SERVO_ROTATE_TIME);
-        READY(TILT);
-      }
+      BUSY(TILT, return);
+      tilt.write(constrain(value8, 0, MAX_TILT));
+      READY(TILT);
       break;
     case REGISTER(MOTOR) + MOTOR_LEFT:
       BUSY(MOTOR, return);
-      approach(&left, value8);
+      left.write(value8);
       READY(MOTOR);
       break;
     case REGISTER(MOTOR) + MOTOR_RIGHT:
-      BUSY(MOTOR, return);
-      approach(&right, value8);
+      BUSY(MOTOR, return)
+      right.write(value8);
       READY(MOTOR);
       break;
     case REGISTER(MOTOR) + MOTOR_ENCODER_LEFT_FRONT:
@@ -233,10 +219,10 @@
     Wire.write((byte *)(&status), sizeof(status));
     break;
   case REGISTER(BOARD) + BOARD_BATTERY:
-    // V = analog / 56.88
-    // Range = 10.6 .. 12.6
+    // centiV = analog * 1.7581
+    // Range = 10.6V .. 12.6V
     value = analogRead(PIN_ANALOG_BATTERY);
-    Wire.write((byte)(((float)value / 56.88 - 10.6) * 50));
+    Wire.write((byte)(value * 1.7581 / 2));
     break;
   case REGISTER(LIGHT_SENSOR):
     value = analogRead(PIN_ANALOG_LIGHT_SENSOR);


Update timer_interrupt_dual_comp_registers.ino

--- interrupts/timer_interrupt_dual_comp_registers.ino
+++ interrupts/timer_interrupt_dual_comp_registers.ino
@@ -23,30 +23,37 @@
 */

 void setup() {
-  pinMode(13, OUTPUT);
-  setupTimer();
+  pinMode(13, OUTPUT); // enable the LED pin as output
+  setupTimer(); // abstract timer setup
 }

-ISR(TIMER1_COMPA_vect) {
-  digitalWrite(13, HIGH);
+ISR(TIMER1_COMPA_vect) { // ISR for Timer 1 Output Compare Register A (OCR1A)
+  digitalWrite(13, HIGH); // turn on the LED
 }

-ISR(TIMER1_COMPB_vect) {
-  digitalWrite(13, LOW);
-  TCNT1 = 0; //
+ISR(TIMER1_COMPB_vect) { // ISR for Timer 1 Output Compare Register B (OCR1B)
+  digitalWrite(13, LOW); // turn off the LED
+  TCNT1 = 0; // must manually reset the Timer Counter to zero as CTC mode is disabled
 }

-void loop() {}
+void loop() {} // leave blank

 void setupTimer() {
-  noInterrupts();
-  TCCR1A = 0;
-  TCCR1B = 0;
-  OCR1A = 15625;
-  OCR1B = 15625 * 2;
+  noInterrupts(); // turn off interrupts
+
+  TCCR1A = 0; // reset the Timer/Counter Control Register A for Timer 1
+  TCCR1B = 0; // reset the Timer/Counter Control Register B for Timer 1
+
+  // enable 1/256 prescaling
   TCCR1B |= (1 << CS10);
   TCCR1B |= (1 << CS12);
+
+  // enable COMPA and COMPB ISRs
   TIMSK1 |= (1 << OCIE1A);
   TIMSK1 |= (1 << OCIE1B);
-  interrupts();
+
+  OCR1A = 15625; // set time delay for the COMPA ISR to 1 s
+  OCR1B = 15625 * 2; // set time delay for the COMPB ISR to 2s
+
+  interrupts(); // turn on interrupts
 }


Fix pin mappings and fix a race condition when duty_cycle ~== mains cycle

--- arduino-light-dimmer-ble/arduino-light-dimmer-ble.ino
+++ arduino-light-dimmer-ble/arduino-light-dimmer-ble.ino
@@ -9,10 +9,10 @@
 #define LED2 11

 #define PIN_ZCROSS 3
-#define SSR1_PIN A0
-#define SSR2_PIN A1
-#define SSR3_PIN A2
-#define SSR4_PIN A3
+#define SSR1_PIN A3
+#define SSR2_PIN A0
+#define SSR3_PIN A1
+#define SSR4_PIN A2
 #define INITIAL_SMOOTHING_US 2000

 // Maps a brigthness value [0-31] to a duty-cycle value in the range
@@ -35,6 +35,15 @@
     op_type_t op : 1;
   };
 };
+
+
+volatile uint8_t g_zerocross_isr_flag;
+volatile uint32_t g_zerocross_time;
+uint32_t g_now;
+uint16_t g_num_cycles;
+uint8_t g_led2_state;
+uint8_t g_mins_since_last_remote_command;
+

 template<unsigned int PIN>
 class DimmerChannel {
@@ -51,7 +60,9 @@
       duty_cycle_smoothing_rate_us_ = INITIAL_SMOOTHING_US;
     }

-    void on_zero_cross(const uint32_t& last_zerocross_time) {
+    void on_zero_cross() {
+      digitalWrite(PIN, LOW);
+
       // Perform smoothing adjustement to converge towards the
       // |target_duty_cycle_us| set-point.
       if (current_duty_cycle_us_ > target_duty_cycle_us_) {
@@ -63,7 +74,7 @@
       }

       // Calculate the absolute time for the next SSR trigger.
-      next_trigger_time_ = last_zerocross_time + current_duty_cycle_us_;
+      next_trigger_time_ = g_now + current_duty_cycle_us_;
     }

     void store_brightness_in_eeprom() {
@@ -76,17 +87,13 @@
       EEPROM.update(PIN, brightness_);
     }

-    void trigger_ssr_if_time(const uint32_t& now) {
-      if (now >= next_trigger_time_) {
+    void trigger_ssr_if_time() {
+      if (g_now >= next_trigger_time_) {
         digitalWrite(PIN, HIGH);
         next_trigger_time_ = -1;
       }
     }

-    inline void reset_ssr() {
-      digitalWrite(PIN, LOW);
-    }
-
     inline uint8_t brightness() const {
        return brightness_;
     }
@@ -101,7 +108,7 @@
     }

     void set_duty_cycle_smoothing_rate(uint8_t value) {
-      duty_cycle_smoothing_rate_us_ = ((uint16_t) (value + 1)) << 2ul;
+      duty_cycle_smoothing_rate_us_ = ((uint16_t) (value + 1)) << 2;
     }

   private:
@@ -121,12 +128,6 @@
     uint8_t brightness_;
 };

-volatile uint32_t last_zerocross_isr_time;
-volatile uint8_t zerocross_isr_flag;
-uint16_t num_cycles;
-uint8_t led2_state;
-uint8_t mins_since_last_remote_command;
-
 DimmerChannel<SSR1_PIN> ch1;
 DimmerChannel<SSR2_PIN> ch2;
 DimmerChannel<SSR3_PIN> ch3;
@@ -148,64 +149,63 @@
   ch3.initialize();
   ch4.initialize();

-  mins_since_last_remote_command = 0;
+  g_mins_since_last_remote_command = 0;
   Serial.begin(9600);
   initialize_hm10_beacon();

-  zerocross_isr_flag = 0;
-  last_zerocross_isr_time = 0;
+  g_zerocross_isr_flag = 0;
+  g_now = micros();
   attachInterrupt(digitalPinToInterrupt(PIN_ZCROSS), isr_zerocross, RISING);
 }

 void loop()
 {
-  if (zerocross_isr_flag) {
-    zerocross_isr_flag = 0;
-    const uint32_t zerocross_time = last_zerocross_isr_time;
-    ch1.on_zero_cross(zerocross_time);
-    ch2.on_zero_cross(zerocross_time);
-    ch3.on_zero_cross(zerocross_time);
-    ch4.on_zero_cross(zerocross_time);
-
-    ++num_cycles;
-    digitalWrite(LED1, (num_cycles & 0x10) ? HIGH : LOW);
-    if (num_cycles == 600)  {  // Every ~1 minute
-      ++mins_since_last_remote_command;
-      if (mins_since_last_remote_command >= 240) {  // Every ~4 hours.
-        ch1.set_duty_cycle_smoothing_rate(1);
-        ch1.set_brightness(0);
-        ch2.set_duty_cycle_smoothing_rate(1);
-        ch2.set_brightness(0);
-        ch3.set_duty_cycle_smoothing_rate(1);
-        ch3.set_brightness(0);
-        ch4.set_duty_cycle_smoothing_rate(1);
-        ch4.set_brightness(0);
-      }
+  if (g_zerocross_isr_flag) {
+    g_now = g_zerocross_time;
+    g_zerocross_isr_flag = 0;
+    ch1.on_zero_cross();
+    ch2.on_zero_cross();
+    ch3.on_zero_cross();
+    ch4.on_zero_cross();
+
+    ++g_num_cycles;
+    digitalWrite(LED1, (g_num_cycles & 0x10) ? HIGH : LOW);
+    if (g_num_cycles == 6000)  {  // Every ~10 mins
+      ++g_mins_since_last_remote_command;
+      if (g_mins_since_last_remote_command >= 24)  // Every ~4 hours.
+        turn_all_off_smoothly();
       ch1.store_brightness_in_eeprom();
       ch2.store_brightness_in_eeprom();
       ch3.store_brightness_in_eeprom();
       ch4.store_brightness_in_eeprom();
-      num_cycles = 0;
-    } else if ((num_cycles & 63) == 32) {  // Every ~3.2 seconds.
+      g_num_cycles = 0;
+    } else if ((g_num_cycles & 63) == 32) {  // Every ~3.2 seconds.
       hm10_beacon_send_current_brightness();
     }
   }

-  uint32_t now = micros();
-  ch1.trigger_ssr_if_time(now);
-  ch2.trigger_ssr_if_time(now);
-  ch3.trigger_ssr_if_time(now);
-  ch4.trigger_ssr_if_time(now);
+  g_now = micros();
+  ch1.trigger_ssr_if_time();
+  ch2.trigger_ssr_if_time();
+  ch3.trigger_ssr_if_time();
+  ch4.trigger_ssr_if_time();
   hm10_beacon_receive();
 }

 void isr_zerocross() {
-  ch1.reset_ssr();
-  ch2.reset_ssr();
-  ch3.reset_ssr();
-  ch4.reset_ssr();
-  last_zerocross_isr_time = micros();
-  zerocross_isr_flag = 1;
+  g_zerocross_time = micros();
+  g_zerocross_isr_flag = 1;
+}
+
+void turn_all_off_smoothly() {
+  ch1.set_duty_cycle_smoothing_rate(1);
+  ch1.set_brightness(0);
+  ch2.set_duty_cycle_smoothing_rate(1);
+  ch2.set_brightness(0);
+  ch3.set_duty_cycle_smoothing_rate(1);
+  ch3.set_brightness(0);
+  ch4.set_duty_cycle_smoothing_rate(1);
+  ch4.set_brightness(0);
 }

 void initialize_hm10_beacon() {
@@ -223,7 +223,6 @@
   }
 }

-
 bool initialize_hm10_attempt() {
   Serial.setTimeout(2000);

@@ -274,7 +273,7 @@
       case 2: ch3.set_brightness(cmd.value); break;
       case 3: ch4.set_brightness(cmd.value); break;
     }
-  } else /* cmd.op == SET_SMOOTHING */ {
+  } else { /* cmd.op == SET_SMOOTHING */
     switch (cmd.channel) {
       case 0: ch1.set_duty_cycle_smoothing_rate(cmd.value); break;
       case 1: ch2.set_duty_cycle_smoothing_rate(cmd.value); break;
@@ -282,9 +281,9 @@
       case 3: ch4.set_duty_cycle_smoothing_rate(cmd.value); break;
     }
   }
-  led2_state = led2_state ? LOW : HIGH;
-  digitalWrite(LED2, led2_state);
-  mins_since_last_remote_command = 0;
+  g_led2_state = g_led2_state ? LOW : HIGH;
+  digitalWrite(LED2, g_led2_state);
+  g_mins_since_last_remote_command = 0;
 }

 void hm10_beacon_send_current_brightness() {


Add mode change functionality

Add mode change functionality

--- midicontroller.ino
+++ midicontroller.ino
@@ -171,31 +171,34 @@

   updateButtons();

-  changeBank();
-
-  changeMode();
+  boolean modeChange = changeMode();
+
+  if (!modeChange) {
+    changeBank();
+  }

   updateLeds();

 }

-boolean bothBanksDownLastState = false;
-
-void changeMode() {
-  /*if (bankDownDown && bankUpDown) {
-    if (!previousBothBanksDown) {
-      initMode = 1 - initMode;
-      previousBothBanksDown = true;
-      if (initMode) {
-        Serial.println("Init mode");
-      } else {
-        Serial.println("Normal mode");
-      }
+boolean bothBanksDown = false;
+
+boolean changeMode() {
+  if (bankDownButton.isPressed() && bankUpButton.isPressed()) {
+    bothBanksDown = true;
+  } else if (bothBanksDown && ((bankDownButton.isJustReleased() && !bankUpButton.isPressed()) || (bankUpButton.isJustReleased() && !bankDownButton.isPressed()))) {
+    bothBanksDown = false;
+    initMode = 1 - initMode;
+    if (initMode) {
+      Serial.println("Init mode");
     } else {
-      previousBothBanksDown = false;
-    }
-    }*/
-
+      Serial.println("Normal mode");
+    }
+    return true;
+  } else if (bothBanksDown) {
+    return true;
+  }
+  return false;
 }

 void changeBank() {


-Added "Access-Control-Allow-Origin" header to all web traffic.

--- webservertask.ino
+++ webservertask.ino
@@ -697,7 +697,8 @@
     request->send( 404 );
   });

-  //start the web server
+  DefaultHeaders::Instance().addHeader( "Access-Control-Allow-Origin", "*" );
+
   server.begin();
   Serial.println("HTTP server setup done.");


adding warmwhite to rgb_led

adding warmwhite to rgb_led

no idea if the lights can physically make this color, but it should work if they can

--- RGB_LED/ioBridge_Iota_to_Arduino.ino
+++ RGB_LED/ioBridge_Iota_to_Arduino.ino
@@ -121,7 +121,13 @@
         analogWrite( GREEN, 165 );
         analogWrite( BLUE, 0 );
     }
-    else if (String(stringIn) == "white" || String(stringIn) == "warmwhite")
+    else if (String(stringIn) == "warmwhite")
+    {
+        analogWrite( RED, 255 );
+        analogWrite( GREEN, 223 );
+        analogWrite( BLUE, 223 );
+    }
+    else if (String(stringIn) == "white")
     {
         analogWrite( RED, 255 );
         analogWrite( GREEN, 255 );


update communication

update communication

--- Arduino/MainRobot/Remote.ino
+++ Arduino/MainRobot/Remote.ino
@@ -8,12 +8,13 @@
 const char MOVE_BACK    = 'b'; // move backwards
 const char MOVE_LEFT    = 'l'; // move left
 const char MOVE_RIGHT   = 'r'; // move right
+const char PIVOT_CW     = 'c'; // rotate 90 degrees CW
 const char PIVOT_CCW    = 'C'; // rotate 90 degrees CCW
-const char PIVOT_CW     = 'c'; // rotate 90 degrees CW
+const char PIVOT_CW_45  = 'q'; // rotate 45 degrees CW
 const char PIVOT_CCW_45 = 'Q'; // rotate 45 degrees CCW
-const char PIVOT_CW_45  = 'q'; // rotate 45 degrees CW
+const char PIVOT_CW_135 = 'j'; // rotate 135 degrees CW
 const char PIVOT_CCW_135= 'J'; // rotate 135 degrees CCW
-const char PIVOT_CW_135 = 'j'; // rotate 135 degrees CW
+const char TURNAROUND   = 't'; // rotate 180 degrees (default CW)
 const char PIVOT        = 'p'; // rotation angle (minus rotates CCW)
 const char GRAB_ONE_TUBE= 'g'; // grab only one tube
 const char GRAB_TWO_TUBE= 'G'; // grab the second tube


Fixed include of VLCD after refactoring. Update size statistics.


Removing MEO programs during debugging.

Removing MEO programs during debugging.

--- examples/TiconXmas2012/TiconXmas2012.ino
+++ examples/TiconXmas2012/TiconXmas2012.ino
@@ -15,7 +15,6 @@
 #include <ProgramRunner.h>
 #include <StockPrograms.h>
 #include <PlusPrograms.h>
-#include <MEOPrograms.h>

 // Arduino with Like A G35 shield (https://github.com/sowbug/like-a-g35).
 // First string on pin 8. Second on 9. My roofline isn't quite long enough
@@ -24,11 +23,10 @@
 G35String lights_2(9, 41);

 const int PROGRAM_COUNT = StockProgramGroup::ProgramCount +
-  PlusProgramGroup::ProgramCount + MEOProgramGroup::ProgramCount;
+  PlusProgramGroup::ProgramCount;

 StockProgramGroup stock_programs;
 PlusProgramGroup plus_programs;
-MEOProgramGroup meo_programs;
 G35StringGroup string_group;

 LightProgram* CreateProgram(uint8_t program_index) {
@@ -43,11 +41,6 @@
     return plus_programs.CreateProgram(string_group, program_index);
   }
   program_index -= PlusProgramGroup::ProgramCount;
-
-  if (program_index < MEOProgramGroup::ProgramCount) {
-    return meo_programs.CreateProgram(string_group, program_index);
-  }
-  program_index -= MEOProgramGroup::ProgramCount;

   return NULL;
 }


Turnstile sample fixed

Turnstile sample fixed

--- examples/cie-Turnstile/cie-Turnstile.ino
+++ examples/cie-Turnstile/cie-Turnstile.ino
@@ -30,6 +30,10 @@
 #define PN532_MOSI (3)
 #define PN532_SS   (4)
 #define PN532_MISO (5)
+
+#define SERVO      (9)
+#define GREEN_LED  (10)
+#define RED_LED    (11)

 // I2C is not supported in this release
 //#define PN532_IRQ   (2)


local bettery monitoring

local bettery monitoring

--- transmitter/Monitor/Monitor.ino
+++ transmitter/Monitor/Monitor.ino
@@ -30,9 +30,42 @@

 unsigned long comms_last = 0;
 unsigned long display_last = 0;
+unsigned long vcc_last = 0;
+int vcc = 0;
+
+void batterySetup()
+{
+  // Read 1.1V reference against AVcc
+  // set the reference to Vcc and the measurement to the internal 1.1V reference
+  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
+  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
+    ADMUX = _BV(MUX5) | _BV(MUX0);
+  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
+    ADMUX = _BV(MUX3) | _BV(MUX2);
+  #else
+    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
+  #endif
+}
+
+long batteryVcc() {
+
+  ADCSRA |= _BV(ADSC); // Start conversion
+  while (bit_is_set(ADCSRA,ADSC)); // measuring
+
+  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
+  uint8_t high = ADCH; // unlocks both
+
+  long result = (high<<8) | low;
+
+  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
+  return result; // Vcc in millivolts
+}
+

 void setup()
 {
+  batterySetup();
   Serial.begin(115200);
   u8g.setRot180();
   memset(&monitor, 0, sizeof(monitor_t));
@@ -73,11 +106,7 @@
       switch (ack_payload.key) {
         case 255:
           monitor.pps = ack_payload.val;
-          break;
-        case 253:
-          monitor.vcc_tx = ack_payload.val;
-          break;
-
+          break;
         case 0:
           monitor.vcc_rx = ack_payload.val;
           break;
@@ -94,6 +123,7 @@
           monitor.roll = ack_payload.val;
           break;
       }
+      monitor.vcc_tx = vcc;

     } else {
       ack_flag = 0;
@@ -101,7 +131,12 @@

   }

-
+  // Read the battery level
+  if (now - vcc_last > 1000) {
+    vcc = batteryVcc();
+  }
+
+  // Change the display if there is no serial data from the transmitter
   if (now - comms_last > 250) {
     memset(&monitor, 0, sizeof(monitor_t));
   }
@@ -109,7 +144,7 @@
   if (now - display_last > 50) {
     displayUpdate();
   }
-
+
 }

 void displayUpdate()


Commented out checkPosition()

Commented out checkPosition()

--- AL5D/al5d.ino
+++ AL5D/al5d.ino
@@ -192,7 +192,7 @@
 {
    int ret_val = 0;

-   checkPosition();
+   //checkPosition();
    //if ( ( ret_val = checkPosition() ) != 0 ) return ret_val;

    DEBUG("moveArm("); DEBUG(basPulse); DEBUG(","); DEBUG(shlPulse); DEBUG(","); DEBUG(elbPulse); DEBUG(","); DEBUG(wriPulse); DEBUGln(")");


Dew Point

Dew Point

--- weather_station/dashboard/arduino/weather_station_02.ino
+++ weather_station/dashboard/arduino/weather_station_02.ino
@@ -38,12 +38,19 @@
   // Read temperature as Celsius
   float c = dht.readTemperature();

+  // Read temperature as Celsius
+  float k = c + 273.15;
+
   // Read temperature as Fahrenheit
   float f = dht.readTemperature(true);

   // Compute heat index
   // Must send in temp in Fahrenheit!
   float hi = dht.computeHeatIndex(f, h);
+
+  // How cold? (temperature and humidity with Arduino)
+  // http://wodieskodie.com/how-cold-temperature-and-humidity-with-arduino/
+  float dp = dewPoint(c, h);

   if (client) {
     // read the command
@@ -59,6 +66,11 @@
       client.print(c);
       //client.print(" degrees C");
      }
+     if (request == "tempk") {
+      //client.print("
Current Temperature: ");
+      client.print(k);
+      //client.print(" degrees K");
+     }
      if (request == "hum") {
       //client.print("
Current Humidity: ");
       client.print(h);
@@ -66,6 +78,10 @@
      if (request == "hi") {
       //client.print("
Heat Index: ");
       client.print(hi);
+     }
+     if (request == "dp") {
+      //client.print("
Dew Point: ");
+      client.print(dp);
      }
      if (request == "light") {
       //client.print("
Light: ");
@@ -85,4 +101,24 @@
     client.stop();
   }
   delay(50);
+}
+
+// ****************
+// Declare User-written Functions
+// ****************
+
+// dewPoint function NOAA
+// reference: http://wahiduddin.net/calc/density_algorithms.htm
+double dewPoint(double celsius, double humidity) {
+
+  double A0= 373.15/(273.15 + celsius);
+  double SUM = -7.90298 * (A0-1);
+  SUM += 5.02808 * log10(A0);
+  SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
+  SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
+  SUM += log10(1013.246);
+  double VP = pow(10, SUM-3) * humidity;
+  double T = log(VP/0.61078); // temp var
+
+  return (241.88 * T) / (17.558-T);
 }


Update TWI scanner tool; repeat scanning of devices on bus.

--- examples/Tools/CosaTWIscanner/CosaTWIscanner.ino
+++ examples/Tools/CosaTWIscanner/CosaTWIscanner.ino
@@ -24,6 +24,7 @@

 #include "Cosa/Types.h"
 #include "Cosa/TWI.hh"
+#include "Cosa/Watchdog.hh"
 #include "Cosa/IOStream.hh"
 #include "Cosa/IOStream/Driver/UART.hh"

@@ -106,12 +107,18 @@
   return (NULL);
 }

+IOStream cout(&uart);
+
 void setup()
 {
   // Bind the UART to en output stream for print out
-  IOStream cout(&uart);
   uart.begin(9600);
+  Watchdog::begin();
   cout << PSTR("CosaTWIscanner: started") << endl;
+}
+
+void loop()
+{
   // Iterate through all bus addresses
   for (uint8_t addr = 3; addr < 128; addr++) {
     // Attempt to read from the device
@@ -129,5 +136,6 @@
     if (name != NULL) cout << ':' << name;
     cout << endl;
   }
+  cout << endl;
+  SLEEP(5);
 }
-


Program now prints system's drift in degrees every 100 milliseconds.

--- software/Arduino/ServoController/ServoController.ino
+++ software/Arduino/ServoController/ServoController.ino
@@ -17,6 +17,7 @@
 int i = 0;
 int j = 0;
 float runningSum = 0;
+float oldAverage;
 bool int_flag = false;

 void setup() {
@@ -29,6 +30,8 @@
     entries[i] = readGyro();
     runningSum += entries[i];
   } // fill up the rolling average
+
+  oldAverage = getAverage();

   xy.attach(3); // pro mini pwm pin
   xy.write(0); // Start at a well-defined value
@@ -43,7 +46,9 @@
     runningSum -= entries[j % 10];
     entries[j % 10] = readGyro();
     runningSum += entries[j % 10];
-    Serial.println(getAverage(), 2);
+    float newAverage = getAverage();
+    Serial.println(newAverage - oldAverage, 2); // Print drift in 100 ms
+    oldAverage = newAverage;
     j++;
     int_flag = false;
   }
@@ -68,9 +73,13 @@
     Serial.println(" GND     | GND");
     Serial.println(" A4      | SDA");
     Serial.println(" A5      | SCL");
-    while (1) {
+    while (!imu.begin()) {
+      Serial.println(" [ FAILED ] ");
       blinkLED();
+      Serial.print("Connecting...");
+      delay(1000);
     }
+    Serial.println("[ SUCCESS ] ");
   }
   Serial.println(" [ DONE ] ");


Adapted to new size value

Adapted to new size value

--- examples/led_fuel_gauge/led_fuel_gauge.ino
+++ examples/led_fuel_gauge/led_fuel_gauge.ino
@@ -12,7 +12,7 @@
 void setup() {

   cmp.begin( A0, 50 )
-    .threshold( threshold_list, sizeof( threshold_list ) / sizeof( threshold_list[0] ), true )
+    .threshold( threshold_list, sizeof( threshold_list ), true )
     .onChange( true, step, Atm_step::EVT_STEP )
     .onChange( false, step, Atm_step::EVT_BACK );


Correctedd checksum

Correctedd checksum

--- apollo/apolloClient/apolloClient.ino
+++ apollo/apolloClient/apolloClient.ino
@@ -159,15 +159,12 @@
       Serial.print(F("Prepended Value = "));

       int prependedSize = twoBytes();
-      byte checkSum1 = client.read();
-      byte checkSum2 = client.read();
+      unsigned int checksum = twoBytes();

       Serial.print(prependedSize);
       Serial.println(F(" bytes"));
-      Serial.print(F("Prepended Sum1 = "));
-      Serial.println(checkSum1);
-      Serial.print(F("Prepended Sum2 = "));
-      Serial.println(checkSum2);
+      Serial.print(F("Prepended checksum = "));
+      Serial.println(checksum);
       Serial.print(F("Data: "));
       int i = 0;
       byte sum1 = 0;
@@ -193,17 +190,18 @@
           i++;
         }
       }
-      Serial.println();
-      Serial.print("Sum1 = ");
-      Serial.print(sum1);
-      Serial.print("; Sum2 = ");
-      Serial.println(sum2);
+      unsigned int computedChecksum = sum1 << 8;
+      computedChecksum |= sum2;
+
+      Serial.println();
+      Serial.print("Computed Checksum = ");
+      Serial.print(computedChecksum);

       file.close();
       Serial.println();
       Serial.print(i);
       Serial.println(F(" Bytes Received."));
-      if (prependedSize <= 0 || prependedSize != i || checkSum1 != sum1 || checkSum2 != sum2) {
+      if (prependedSize <= 0 || prependedSize != i || checksum != computedChecksum) {
         Serial.println(F("ERROR RECEIVING FIRMWARE!"));
       }
       else {


v2.6.0 - update example 18 - use more compile directives

--- examples/Scheduler_example18_StatusRequest_LTS_WDT_Timeout/Scheduler_example18_StatusRequest_LTS_WDT_Timeout.ino
+++ examples/Scheduler_example18_StatusRequest_LTS_WDT_Timeout/Scheduler_example18_StatusRequest_LTS_WDT_Timeout.ino
@@ -1,22 +1,22 @@
-/**
- *  This is example 5 rewritten with Timeout, LTS and WDT functioanlity:
- *  - 1 second timeout is set for the main calculation task
- *  - LTS is used to address individual array elements for each sensor sinlce the callback code is shared
- *  - WDT is used to set the Task ID and use that as an index for array of distances (alternative to LTS)
- *
- *  Original description:
- *  ====================
- *    This test emulates querying 3 sensors once every 10 seconds, each could respond with a different delay
- *    (ultrasonic sensors for instance) and printing a min value of the three when all three have reported their values.
- *    The overall timeout of 1 second is setup as well.
- *    An error message needs to be printed if a timeout occurred instead of a value.
- *
- *    Example5:
- *     Sketch uses 6066 bytes (18%) of program storage space. Maximum is 32256 bytes.
- *     Global variables use 1039 bytes (50%) of dynamic memory, leaving 1009 bytes for local variables. Maximum is 2048 bytes.
- *    Example 18:
- *     Sketch uses 5142 bytes (15%) of program storage space. Maximum is 32256 bytes.
- *     Global variables use 878 bytes (42%) of dynamic memory, leaving 1170 bytes for local variables. Maximum is 2048 bytes.
+/**
+    This is example 5 rewritten with Timeout, LTS and WDT functioanlity:
+    - 1 second timeout is set for the main calculation task
+    - LTS is used to address individual array elements for each sensor sinlce the callback code is shared
+    - WDT is used to set the Task ID and use that as an index for array of distances (alternative to LTS)
+
+    Original description:
+    ====================
+      This test emulates querying 3 sensors once every 10 seconds, each could respond with a different delay
+      (ultrasonic sensors for instance) and printing a min value of the three when all three have reported their values.
+      The overall timeout of 1 second is setup as well.
+      An error message needs to be printed if a timeout occurred instead of a value.
+
+      Example5:
+       Sketch uses 6066 bytes (18%) of program storage space. Maximum is 32256 bytes.
+       Global variables use 1039 bytes (50%) of dynamic memory, leaving 1009 bytes for local variables. Maximum is 2048 bytes.
+      Example 18:
+       Sketch uses 5142 bytes (15%) of program storage space. Maximum is 32256 bytes.
+       Global variables use 878 bytes (42%) of dynamic memory, leaving 1170 bytes for local variables. Maximum is 2048 bytes.
 */

 // #define _TASK_TIMECRITICAL      // Enable monitoring scheduling overruns
@@ -24,10 +24,10 @@
 #define _TASK_STATUS_REQUEST    // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
 #define _TASK_WDT_IDS           // Compile with support for wdt control points and task ids
 #define _TASK_LTS_POINTER       // Compile with support for local task storage pointer
-// #define _TASK_PRIORITY          // Support for layered scheduling priority
+#define _TASK_PRIORITY          // Support for layered scheduling priority
 // #define _TASK_MICRO_RES         // Support for microsecond resolution
 // #define _TASK_STD_FUNCTION      // Support for std::function (ESP8266 and ESP32 ONLY)
-// #define _TASK_DEBUG             // Make all methods and variables public for debug purposes
+#define _TASK_DEBUG             // Make all methods and variables public for debug purposes
 #define _TASK_INLINE       // Make all methods "inline" - needed to support some multi-tab, multi-file implementations
 #define _TASK_TIMEOUT           // Support for overall task timeout

@@ -35,7 +35,7 @@

 StatusRequest measure;

-Scheduler ts;
+Scheduler ts, hts;

 // Callback methods prototypes
 void CycleCallback();
@@ -49,13 +49,14 @@
 Task tSensor2(0, TASK_ONCE, &SCallback, &ts, false, &SEnable); // task ID = 2
 Task tSensor3(0, TASK_ONCE, &SCallback, &ts, false, &SEnable); // task ID = 3

-Task tCycle(10000, TASK_FOREVER, &CycleCallback, &ts);
-Task tCalculate(TASK_IMMEDIATE , TASK_ONCE, &CalcCallback, &ts, false, &CalcEnable, &CalcDisable);
+Task tCycle(10000, TASK_FOREVER, &CycleCallback, &hts);
+Task tCalculate(TASK_IMMEDIATE , TASK_ONCE, &CalcCallback, &hts, false, &CalcEnable, &CalcDisable);

 #define NO_OF_SENSORS 3
-long distance, d[NO_OF_SENSORS+1], d_lts[NO_OF_SENSORS]; // d[] will be populated via task ID used as array indexes, d_lts will be addressed via LTS pointers
+long distance, d[NO_OF_SENSORS + 1], d_lts[NO_OF_SENSORS]; // d[] will be populated via task ID used as array indexes, d_lts will be addressed via LTS pointers

 void CycleCallback() {
+  Serial.println();
   Serial.print(millis()); Serial.print(":\t");
   Serial.println("CycleCallback: Initiating measurement cycle every 10 seconds");

@@ -80,7 +81,7 @@
   if (tCalculate.timedOut()) {
     measure.signalComplete(-1);  // signal error
     Serial.print(millis()); Serial.print(":\t");
-    Serial.println("MeasureCallback: Timeout!");
+    Serial.println("MeasureCallback: ***** Timeout *****");
     //    tSensor1.disable();
     //    tSensor2.disable();
     //    tSensor3.disable();
@@ -133,11 +134,11 @@
   Serial.print("SCallback: TaskID=");
   Serial.println(i);
   Serial.print("Emulating measurement. d=");
-
+
   d[i] = random(501); // pick a value from 0 to 500 "centimeters" simulating a measurement
   int *pd = (int*) t.getLtsPointer();
   *pd = d[i];
-
+
   measure.signal();

   Serial.print(d[i]);
@@ -152,14 +153,15 @@

   Serial.begin(115200);
   Serial.println("TaskScheduler StatusRequest Sensor Emulation Test. Complex Test.");
-  randomSeed(analogRead(A1) + millis());
+  randomSeed(analogRead(A0) + millis());

   tSensor1.setLtsPointer(&d_lts[0]);
   tSensor2.setLtsPointer(&d_lts[1]);
   tSensor3.setLtsPointer(&d_lts[2]);

+  ts.setHighPriorityScheduler(&hts);
+
   tCalculate.setTimeout(1 * TASK_SECOND);
-
   tCycle.enable();
 }


#36 prevent setting up panos wider than 360 or taller than 180.

--- pano-controller.ino
+++ pano-controller.ino
@@ -234,8 +234,12 @@
             horiz_rpm = horiz_rpm * abs(pos_x) / joystick.range;
             pos_x = pos_x / abs(pos_x);
         }
-        if (pos_x && horiz && pano.horiz_home_offset + pos_x < 0){
-            pos_x = -pano.horiz_home_offset;
+        if (pos_x && horiz){
+            if (pos_x < -pano.horiz_home_offset){
+                pos_x = -pano.horiz_home_offset;
+            } else if (abs(pos_x + pano.horiz_home_offset) + camera.getHorizFOV() > 360){
+                pos_x = 360 - camera.getHorizFOV() - pano.horiz_home_offset;
+            }
         }

         pos_y = joystick.getPositionY();
@@ -249,8 +253,12 @@
             vert_rpm = vert_rpm * abs(pos_y) / joystick.range;
             pos_y = pos_y / abs(pos_y);
         }
-        if (pos_y && vert && -pano.vert_home_offset - pos_y < 0){
-            pos_y = -pano.vert_home_offset;
+        if (pos_y && vert){
+            if (pos_y > -pano.vert_home_offset){
+                pos_y = -pano.vert_home_offset;
+            } else if (-(pos_y + pano.vert_home_offset) + camera.getVertFOV() > 180){
+                pos_y = -(180 - camera.getVertFOV() + pano.vert_home_offset);
+            }
         }

         if (vert && !pos_x && !pos_y){


#22 Add a 2s delay before starting pano to allow for standing back.

--- pano-controller.ino
+++ pano-controller.ino
@@ -55,9 +55,6 @@

 void setup() {
     Serial.begin(38400);
-    // temporary turn on EN on both motors
-    pinMode(4, OUTPUT); digitalWrite(4, LOW);
-    pinMode(7, OUTPUT); digitalWrite(7, LOW);

     horiz_motor.setMicrostep(32);
     vert_motor.setMicrostep(32);
@@ -253,6 +250,7 @@

     button_clicked = false;
     while (joystick.getButtonState()) delay(20);
+    delay(2000); // don't start moving while button is being pressed
     pano.start();
     attachInterrupt(digitalPinToInterrupt(JOYSTICK_SW), button_click, FALLING);


Change all duration variables to unsigned longs

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

--- src/sketch.ino
+++ src/sketch.ino
@@ -61,9 +61,9 @@
 char newDuration[rDurlength];
 char newSustainDuration[rDurlength];
 int halfTurns;
-unsigned int Duration;
-unsigned int midDuration;
-unsigned int sustainDuration;
+unsigned long Duration;
+unsigned long midDuration;
+unsigned long sustainDuration;
 float startPitch;
 float midPitch;
 float endPitch;
@@ -169,7 +169,7 @@
     findsensor(max(maxPulse, endpulse));
 }

-int timedturn(int halfturns, int duration, bool dir) {
+int timedturn(int halfturns, unsigned long duration, bool dir) {
     int fullspeedsteps = (halfTurnSteps * halfturns) - (accelSteps * 2);
     unsigned long pulse = ((duration * 1000L) - (maxPulse * accelSteps)) /
                           (accelSteps + fullspeedsteps);
@@ -197,7 +197,7 @@
     return pulse;
 }

-long _durationgliss(int duration, float startpitch, float endpitch,
+long _durationgliss(unsigned long duration, float startpitch, float endpitch,
         int sustainstart, int sustainend, bool dir, bool recentre) {
     int startsustainpulse = pitchToPulse(startpitch + glissAdd - 1);
     int startpulse = pitchToPulse(startpitch + glissAdd);
@@ -238,11 +238,11 @@
     return glissTime;
 }

-void durationturn(int duration, float pitch, bool dir, bool recentre) {
+void durationturn(unsigned long duration, float pitch, bool dir, bool recentre) {
     _durationgliss(duration, pitch, pitch, 0, 0, dir, recentre);
 }

-long durationgliss(int duration, float startpitch, float endpitch,
+long durationgliss(unsigned long duration, float startpitch, float endpitch,
         bool dir, bool recentre, int sustain) {
     return _durationgliss(duration, startpitch, endpitch, sustain, sustain, dir, recentre);
 }
@@ -501,8 +501,8 @@
             for (byte d=0; d<rDurlength; d++) {
                 newDuration[d] = serialIncoming[++i];
             }
-            midDuration = Duration; // midDuration is previous duration
-            Duration = atoi(newDuration);
+            midDuration = Duration; // midDuration is previous Duration
+            Duration = atol(newDuration);
         } else if (data == rReset) {
             defaults();
         } else if (data == rDoubleGliss) {
@@ -514,7 +514,7 @@
             for (byte d=0; d<rDurlength; d++) {
                 newSustainDuration[d] = serialIncoming[++i];
             }
-            sustainDuration = atoi(newSustainDuration);
+            sustainDuration = atol(newSustainDuration);
         } else if (data < 21) {
         } else if (data < 40) {
             halfTurns = data - 20;