SetTime: dropped old crap. Actually receive NTP messages from the network and display time!

--- SetTime/SetTime.ino
+++ SetTime/SetTime.ino
@@ -1,124 +1,166 @@
+// time routines extracted from: http://www.jbox.dk/sanos/source/lib/time.c.html
+// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+//    notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice, this list of conditions and the following disclaimer in the
+//    documentation and/or other materials provided with the distribution.
+// 3. Neither the name of the project nor the names of its contributors
+//    may be used to endorse or promote products derived from this software
+//    without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+
+// from http://embeddedgurus.com/barr-code/2009/09/binary-literals-in-c/
+#define HEX__(n) 0x##n##LU
+#define B8__(x) ((x&0x0000000FLU)?1:0) \
++((x&0x000000F0LU)?2:0) \
++((x&0x00000F00LU)?4:0) \
++((x&0x0000F000LU)?8:0) \
++((x&0x000F0000LU)?16:0) \
++((x&0x00F00000LU)?32:0) \
++((x&0x0F000000LU)?64:0) \
++((x&0xF0000000LU)?128:0)
+
+// User-visible Macros
+#define B8(d) ((uint8_t)B8__(HEX__(d)))
+
+/* Time manipulation code */
+
+struct tm {
+  int tm_year;
+  int tm_yday;
+  int tm_mon;
+  int tm_mday;
+  int tm_wday;
+  int tm_hour;
+  int tm_min;
+  int tm_sec;
+};
+
+#define EPOCH_YR                1970
+#define SECS_DAY                (24L * 60L * 60L)
+#define LEAPYEAR(year)          (!((year) % 4) && (((year) % 100) || !((year) % 400)))
+#define YEARSIZE(year)          (LEAPYEAR(year) ? 366 : 365)
+#define FIRSTSUNDAY(timp)       (((timp)->tm_yday - (timp)->tm_wday + 420) % 7)
+#define FIRSTDAYOF(timp)        (((timp)->tm_wday - (timp)->tm_yday + 420) % 7)
+
+#define TIME_MAX                2147483647L
+
+#define TZ_OFFSET (3600 * 3)
+
+int _daylight = 0;                  // Non-zero if daylight savings time is used
+long _dstbias = 0;                  // Offset for Daylight Saving Time
+long _timezone = 0;                 // Difference in seconds between GMT and local time
+char *_tzname[2] = {"GMT", "GMT"};  // Standard/daylight savings time zone names
+
+const int yearDays[2][12] = {
+  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+struct tm *gmtime_r(const uint32_t time, struct tm *tmbuf) {
+  unsigned long dayclock, dayno;
+  int year = EPOCH_YR;
+
+  dayclock = (unsigned long) time % SECS_DAY;
+  dayno = (unsigned long) time / SECS_DAY;
+
+  tmbuf->tm_sec = dayclock % 60;
+  tmbuf->tm_min = (dayclock % 3600) / 60;
+  tmbuf->tm_hour = dayclock / 3600;
+  tmbuf->tm_wday = (dayno + 4) % 7; // Day 0 was a thursday
+  while (dayno >= (unsigned long) YEARSIZE(year)) {
+    dayno -= YEARSIZE(year);
+    year++;
+  }
+  tmbuf->tm_year = year;
+  tmbuf->tm_yday = dayno;
+  tmbuf->tm_mon = 0;
+  while (dayno >= (unsigned long) yearDays[LEAPYEAR(year)][tmbuf->tm_mon]) {
+    dayno -= yearDays[LEAPYEAR(year)][tmbuf->tm_mon];
+    tmbuf->tm_mon++;
+  }
+  tmbuf->tm_mday = dayno + 1;
+  return tmbuf;
+}
+
+/* End of time manipulation code */
+
+/* Networking code */
+#include "etherShield.h"
+#include "ETHER_28J60.h"
+
+#define TRANSMIT_TIMESTAMP_P 40
+#define NTP_PACKET_SIZE 48
+
+static uint8_t mac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
+static uint8_t ip[4] = {192,168,11,60};
+static uint16_t port = 80;
+
+static const int bufferSize = 200;
+static uint8_t buf[bufferSize];
+
+extern EtherShield es;
+
+static const int ntpPort = 123;
+
+ETHER_28J60 ethernet;
+
+/* End of networking code */
+
 int out = 2;
 int in = 3;
 int debug = 4;

-const unsigned sequenceSize = 200;
-unsigned char sequence[sequenceSize + 1];
-int sequenceAt = 0; // for reading sequences
-int sequenceAtBit = 0;
-int prevSequenceSize = 0;
-
-int inBinarySequence = 0;
-
+/* Bit sequence sending declarations */
+
+//uint8_t setHHMM[] = { 32, 117, 103, 0, 248, 7, 128, 126, 1, 143, 254, 192, 255 };
+uint8_t setHHMM[] = { 4, 174, 230, 0, 31, 224, 1, 126, 128, 241, 127, 3, 255 };
+
+uint8_t bitsOfDigit[10] = {
+  B8(00000001),
+  B8(01001111),
+  B8(00010010),
+  B8(00000110),
+  B8(01001100),
+  B8(00100100),
+  B8(00100000),
+  B8(00001111),
+  B8(00000000),
+  B8(00000100)
+};
+
+volatile uint8_t* sequence;
+
+/* End of bit sequence sending declarations */
+
+/* Timer interrupt code */
 volatile int writeBitsLeft = 0;
 volatile int writeCurBit = 0;
 volatile int writeCurByte = 0;
-
-unsigned char initsequence[] = {
-#if 0
-0,0,1,0,0,0,0,0,0,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,1,0,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,0,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,0,1,0,0,0,0,1,1,1,0,0,0,0,1,1,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,1,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,1,1,1,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,1,1,1,1,0,2,
-0,1,1,0,0,0,0,0,0,2,
-
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,1,1,1,1,1,0,2,
-0,1,1,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,1,0,0,0,0,2,
-0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,0,1,0,1,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,2,
-0,0,0,0,0,0,0,0,1,1,1,1,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,0,0,1,0,1,0,1,1,1,0,0,1,0,1,1,0,1,0,1,1,1,1,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,1,0,1,0,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,2,
-
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,1,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,
-0,0,1,0,1,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,2,
-//0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,2,
-  0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,2,
-
-0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,2,
-0,1,0,0,0,0,0,0,0,2,
-#endif
-
-#if 0
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,2,;
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,2,
-
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,1,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-
-// the following makes 01:59 appear on the screen:
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,1,0,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,1,0,0,0,0,0,1,0,0,1,1,1,1,0,0,0,2,
-0,1,1,0,0,0,0,0,0,
-
-1,1,1,0,0,1,0,0,1,1,1,0,1,1,1,
-0,1,1,1,1,1,1,1,1,1,1,1,1,
-0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,1,
-0,0,1,0,0,0,0,0,0,2,
-0,0,0,0,0,0,0,0,0,2,
-
-0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,1,0,1,1,1,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,0,1,0,0,1,1,1,1,1,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,1,0,1,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,1,0,0,1,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,0,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,1,1,1,0,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1,0,2,
-0,1,0,0,0,1,1,0,1,1,1,1,0,1,0,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1,0,2,
-0,0,0,0,0,1,1,0,2,
-0,0,1,1,0,1,0,0,0,1,1,1,1,1,0,1,1,1,1,0,1,0,0,1,1,1,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,1,0,0,1,1,1,1,1,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,0,1,1,1,0,1,1,1,1,0,2,
-0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,0,0,1,0,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,0,1,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,1,0,0,0,0,0,0,1,0,1,1,1,1,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,0,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,0,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,0,0,0,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,1,0,0,1,1,0,0,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,1,0,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,2,
-0,0,1,0,0,0,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,2,
-#endif
-
-3};
-
-#if 0
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,1,0,1,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,
-0,0,1,0,1,0,0,0,0,1,1,1,0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,2,
-
-0,1,1,0,0,0,0,0,0,2,
-0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,2,
-0,1,0,0,0,0,0,0,0,2, ;
-
-
-#endif

 static const int prescaler = 1;
 static const double systemHz = 16000000;
 static const double bitLength = 52.0 / 1000000.0;
 static const unsigned int finetuning = 50; // fine-tuned with an oscilloscope
 static const unsigned int timerPreload = 65536 - systemHz / prescaler / (1 / bitLength) + finetuning;
-//static const unsigned int = 0;

 void setupTimer()
 {
@@ -159,6 +201,8 @@
 #endif
 }

+/* End of timer interrupt code */
+
 // the loop routine runs over and over again forever:
 void setup() {
   pinMode(out, OUTPUT);
@@ -166,148 +210,100 @@
   pinMode(in, INPUT);
   digitalWrite(out, HIGH);
   digitalWrite(debug, HIGH);
+  ethernet.setup(mac, ip, port);
   Serial.begin(9600);
-  Serial.print("Start. timerPreload=");
-  Serial.println(timerPreload);
+  Serial.println("Start.");
   setupTimer();
 }

-void sendSequence(const unsigned char* seq)
-{
-  Serial.println("Sending sequence");
-  static unsigned long time = micros();
-  for (int c = 0; seq[c] != 3; ++c) {
-    if (seq[c] == 2) {
-      digitalWrite(out, HIGH);
-      digitalWrite(debug, HIGH);
-      delayMicroseconds(52 * 12);
-      time = micros();
-    } else {
-      digitalWrite(out, seq[c]);
-      digitalWrite(debug, seq[c]);
-      time += 52;
-      unsigned int delta = time - micros();
-      delayMicroseconds(delta);
-    }
-  }
-  digitalWrite(out, HIGH);
-  digitalWrite(debug, HIGH);
-  Serial.println("Done sending sequence");
-}
-
 // sends stuff from sequence, sequenceAtBit/sequenceAtByte
-void sendBinarySequenceHw()
+void sendBits(uint8_t* ptr, int bits)
 {
   noInterrupts();
-  writeBitsLeft = sequenceAt * 8 + sequenceAtBit;
+  writeBitsLeft = bits;
   writeCurBit = 0;
   writeCurByte = 0;
+  sequence = ptr;
   interrupts();

   while (writeBitsLeft > 0) {
     // wait for writing to go through
   }
-  Serial.println(".");
-}
-
-void doit() {
-  sendSequence(initsequence);
-}
-
-void baseLoop() {
-  if (Serial.available()) {
-    char ch = Serial.read();
-    switch (ch) {
-      case 'i': {
-        doit();
-      } break;
-      case '0': {
-        if (sequenceAt < sequenceSize) {
-          sequence[sequenceAt++] = 0;
-        } else {
-          Serial.println("Sequence is too long");
-        }
-      } break;
-      case '1': {
-        if (sequenceAt < sequenceSize) {
-          sequence[sequenceAt++] = 1;
-        } else {
-          Serial.println("Sequence is too long");
-        }
-      } break;
-      case 'b': {
-        sequenceAt = 0;
-        sequenceAtBit = 0;
-        inBinarySequence = true;
-      } break;
-      case ';': {
-        if (!prevSequenceSize || sequenceAt > 0) {
-          sequence[sequenceAt++] = 3;
-        } else {
-          sequenceAt = prevSequenceSize;
-        }
-        Serial.println(sequenceAt);
-        for (int c = 0; c < sequenceAt; ++c) {
-          Serial.print((int) sequence[c]);
-        }
-        Serial.println();
-        sendSequence(sequence);
-        prevSequenceSize = sequenceAt;
-        sequenceAt = 0;
-      } break;
+
+  writeCurByte = 0;
+  writeCurBit = 0;
+
+  for (int c = 0; c < bits; ++c) {
+    int value = ((sequence[writeCurByte] >> writeCurBit) & 1) ? HIGH : LOW;
+    Serial.print(value ? "1" : "0");
+    if (++writeCurBit == 8) {
+      writeCurBit = 0;
+      ++writeCurByte;
     }
   }
-}
-
-void advanceBit() {
-  if (++sequenceAtBit == 8) {
-    ++sequenceAt;
-    sequenceAtBit = 0;
-  }
-  if (sequenceAt == sequenceSize) {
-    inBinarySequence = false;
-  }
-}
-
-void binarySequenceLoop() {
-  if (Serial.available()) {
-    char ch = Serial.read();
-    switch (ch) {
-      case '1': {
-        sequence[sequenceAt] |= (1 << sequenceAtBit);
-        advanceBit();
-      } break;
-      case '0': {
-        sequence[sequenceAt] &= ~(1 << sequenceAtBit);
-        advanceBit();
-      } break;
-      case ';': {
-#if 0
-        Serial.print("Sending binary ");
-        Serial.print(sequenceAt * 8);
-        Serial.print("+");
-        Serial.print(sequenceAtBit);
-        Serial.println(" bits");
-#endif
-        //sendBinarySequence(sequence, sequenceAt * 8 + sequenceAtBit);
-        sendBinarySequenceHw();
-        inBinarySequence = false;
-      } break;
-      default:
-        Serial.println("!");
-        inBinarySequence = false;
+  Serial.println();
+}
+
+void insertByte(uint8_t* dst, int dstBit, uint8_t data)
+{
+  for (int bitN = 7; bitN >= 0; --bitN) {
+    *dst = *dst & ~(1 << dstBit) | ((!!(data & (1 << bitN))) << dstBit);
+    if (++dstBit == 8) {
+      ++dst;
+      dstBit = 0;
     }
   }
 }

+inline uint8_t digit(int n, bool dot)
+{
+  return bitsOfDigit[n] << 1 | (dot ? 0 : 1);
+}
+
+void sendHHMM(int hh, int mm)
+{
+  int h1 = hh / 10;
+  int h2 = hh % 10;
+  int m1 = mm / 10;
+  int m2 = mm % 10;
+  insertByte(setHHMM + 3, 1, digit(h1, 0));
+  insertByte(setHHMM + 4, 6, digit(h2, 0));
+  insertByte(setHHMM + 6, 2, digit(m1, 0));
+  insertByte(setHHMM + 8, 0, digit(m2, 0));
+  sendBits(setHHMM, sizeof(setHHMM) * 8);
+}
+
 void loop() {
-  if (inBinarySequence) {
-    binarySequenceLoop();
-    if (!inBinarySequence) {
-      sequenceAt = 0;
-      prevSequenceSize = 0;
+  static bool flag = true;
+  if (flag) {
+    sendHHMM(99, 99);
+    flag = false;
+  }
+  uint16_t length = es.ES_enc28j60PacketReceive(bufferSize, buf);
+  if (length && length >= 42 /* IP packet min length */ && length <= UDP_DATA_P + NTP_PACKET_SIZE) {
+    if (es.ES_eth_type_is_arp_and_my_ip(buf, length)) {
+      es.ES_make_arp_answer_from_request(buf);
+    } else if (es.ES_eth_type_is_ip_and_my_ip(buf, length) &&
+               buf[IP_PROTO_P]==IP_PROTO_ICMP_V &&
+               buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V) {
+      es.ES_make_echo_reply_from_request(buf, length);
+    } else if (buf[IP_PROTO_P] == IP_PROTO_UDP_V && buf[UDP_DST_PORT_L_P] == ntpPort && length == UDP_DATA_P + NTP_PACKET_SIZE) {
+      // NOTE: requires disabling the pass-only-arp-broadcast filter from enc28j60
+      Serial.println("Received ntp packet");
+      uint32_t a = buf[UDP_DATA_P + TRANSMIT_TIMESTAMP_P + 0];
+      uint32_t b = buf[UDP_DATA_P + TRANSMIT_TIMESTAMP_P + 1];
+      uint32_t c = buf[UDP_DATA_P + TRANSMIT_TIMESTAMP_P + 2];
+      uint32_t d = buf[UDP_DATA_P + TRANSMIT_TIMESTAMP_P + 3];
+      uint32_t t = ((a << 24) | (b << 16) | (c << 8) | d) - 2208988800ul + TZ_OFFSET;
+      struct tm tm;
+      gmtime_r(t, &tm);
+      Serial.println(tm.tm_mday);
+      Serial.println(tm.tm_mon + 1);
+      Serial.println(tm.tm_year);
+      Serial.println(tm.tm_hour);
+      Serial.println(tm.tm_min);
+      Serial.println(tm.tm_sec);
+      sendHHMM(tm.tm_hour, tm.tm_min);
     }
-  } else {
-    baseLoop();
-  }
-}
+  }
+}


Update BH1750FVI_Simple.ino

Update BH1750FVI_Simple.ino

--- examples/BH1750FVI_Simple/BH1750FVI_Simple.ino
+++ examples/BH1750FVI_Simple/BH1750FVI_Simple.ino
@@ -1,36 +1,260 @@
-/*
-  This is a simple example to test the BH1750 Light sensor
-
-  Connect the sensor to a NodeMCU ESP8266:
-  VCC  <-> 3V3 [grey]
-  GND  <-> Gnd [purple]
-  SDA  <-> D2  [green]
-  SCL  <-> D1  [blue]
-  ADDR <-> RX  [yellow]
- */
-
+
+
+// Includes: Wifi, MQTT, JSON
+#include<ESP8266WiFi.h>
+#include <PubSubClient.h>
+#include <ArduinoJson.h>
+
+// Includes: Sensors
 #include <Wire.h>
+#include "DHT.h"
 #include <BH1750FVI.h>

-// Settings
+// Defines: Wifi and MQTT
+#define mqtt_server "192.168.1.8"
+
+// Defines: Sensors
+#define DHTPIN 2  //D4
+#define DHTTYPE DHT11
+
+
+// Declarations: Wifi and MQTT
+char* ssid     = " xx ";
+const char* password = " xx ";
+WiFiClient espClient;
+PubSubClient client(espClient);
+
+// Declarations: JSON
+StaticJsonDocument<1024> jsonDoc;
+
+typedef struct keyAndValue_ {
+//   char key[100];
+//   char value[100];
+   String key;
+   String value;
+} keyAndValue_t;
+
+
+// Declarations: Sensors
+DHT DHT_dht(DHTPIN, DHTTYPE);
 uint8_t ADDRESSPIN = 13;
 BH1750FVI::eDeviceAddress_t DEVICEADDRESS = BH1750FVI::k_DevAddress_H;
 BH1750FVI::eDeviceMode_t DEVICEMODE = BH1750FVI::k_DevModeContHighRes;
-
-// Create the Lightsensor instance
 BH1750FVI LightSensor(ADDRESSPIN, DEVICEADDRESS, DEVICEMODE);

-void setup()
-{
+
+
+void setup() {
   Serial.begin(115200);
-  LightSensor.begin();
-  Serial.println("Running...");
-}
-
-void loop()
-{
+  Serial.println("");
+  Serial.println("Starting connecting WiFi.");
+  delay(1000);
+  yield();
+  WiFi.begin(ssid, password);
+  yield();
+  while (WiFi.status() != WL_CONNECTED) {
+    yield();
+    delay(500);
+    Serial.print(".");
+  }
+  Serial.println("WiFi connected");
+  Serial.println("IP address: ");
+  Serial.println(WiFi.localIP());
+
+  client.setServer(mqtt_server, 1883);
+  client.setCallback(callback);
+
+  // setup sensors
+  DHT_dht.begin();
+  LightSensor.begin();
+}
+
+void reconnect() {
+  // Loop until we're reconnected
+  while (!client.connected()) {
+    Serial.print("Attempting MQTT connection...");
+    // Attempt to connect
+    if (client.connect("sensorstation")) {
+      Serial.println("connected");
+      client.subscribe("sensorstation/command");
+    } else {
+      Serial.print("failed, rc=");
+      Serial.print(client.state());
+      Serial.println(" try again in 5 seconds");
+      // Wait 5 seconds before retrying
+      delay(5000);
+    }
+  }
+}
+
+void callback(char* topic, byte* payload, unsigned int length)
+{
+  Serial.println(" callback");
+}
+
+void loop() {
+  if (!client.connected()) {
+    reconnect();
+  }
+  client.loop();
+  delay(5000);
+  //MeasureDHT();
+  //MeasureFakeSensor(); //word deels overschreven door de volgende, return value van jsondoc maken en aan publish voeren?
+  MeasureBH1750FVI();  //en de dubbele komt niet aan bij nodered...
+  PublishValues();
+}
+
+void PublishValues() {
+  char buffer[1024];
+  serializeJson(jsonDoc, buffer);
+  Serial.println(buffer);
+  client.publish("sensorstation/json", buffer);
+  Serial.println("Published");
+}
+
+// DHT
+void MeasureDHTorg()
+{
+  /*
+    DHTPIN 2  //D4
+  */
+
+  float DHT_temp = 0;
+  float DHT_hum = 0;
+  float DHT_heatindex = 0;
+  char tempString[8];
+
+  DHT_temp = DHT_dht.readTemperature();
+  DHT_hum = DHT_dht.readHumidity();
+  DHT_heatindex = DHT_dht.computeHeatIndex(DHT_temp, DHT_hum, false);
+  //if (isnan(DHT_temp) || isnan(DHT_hum) || isnan(DHT_heatindex)) {
+  //  Serial.println("Failed to read from DHT sensor!");
+  //  return;
+  //}
+
+//todo, create root above sensor (buiten deze dht.
+  //add values to json
+  jsonDoc["sensor"] = "dht11";
+  jsonDoc["sensornumber"] = 1;
+  jsonDoc["data"]["temperature"] = dtostrf(DHT_temp, 5, 2, tempString);
+  jsonDoc["data"]["humidity"] = dtostrf(DHT_hum, 5, 2, tempString);
+  //jsonDoc["data"]["heatindex"] = dtostrf(DHT_heatindex, 5, 2, tempString);
+  //jsonDoc["data"]["heatindex"] = "1234";
+  Serial.print("DHT_temp     : "); Serial.print(DHT_temp); Serial.println(" C");
+  Serial.print("DHT_hum      : "); Serial.print(DHT_hum); Serial.println(" %");
+  Serial.print("DHT_heatindex: "); Serial.print(DHT_heatindex); Serial.println(" *C");
+  Serial.println("");
+}
+
+void AddData(String Sensor, uint8_t SensorNumber, keyAndValue_t SensorData[], uint8_t Count)
+{
+  /*
+  JsonObject measurement = jsonDoc.createNestedObject("measurement");
+  measurement["sensor"] = Sensor;
+  measurement["sensornumber"] = SensorNumber;
+
+  JsonObject measurement_data = measurement.createNestedObject("data");
+  //measurement_data["temperature"] = "24.10";
+  //measurement_data["humidity"] = "57.00";
+  for (int x = 0; x <= 1; x++) {
+    //for (int x = 0; x <= sizeof(SensorData)/sizeof(SensorData[0]); x++) {
+    measurement_data[SensorData[x].key] = SensorData[x].value;
+  }*/
+
+  jsonDoc["measurement"]["sensor"] = Sensor;
+  jsonDoc["measurement"]["sensornumber"] = SensorNumber;
+  for (int x = 0; x < Count; x++) {
+    jsonDoc["measurement"]["data"][String(SensorData[x].key)] = SensorData[x].value;
+  }
+
+  Serial.println("AddData:");
+  for (int x = 0; x < Count; x++) {
+    Serial.print(SensorData[x].key);
+    Serial.println(SensorData[x].value);
+  }
+  Serial.println("-------");
+}
+
+void AddDataold(String Sensor, uint8_t SensorNumber, String DataName, String DataValue)
+{
+  String Name(DataName);
+  jsonDoc["measurement"]["sensor"] = Sensor;
+  jsonDoc["measurement"]["sensornumber"] = SensorNumber;
+  jsonDoc["measurement"]["data"][Name] = DataValue;
+}
+
+// DHT
+void MeasureDHT()
+{
+  /*
+    DHTPIN 2  //D4
+  */
+
+  float DHT_temp = 0;
+  float DHT_hum = 0;
+  float DHT_heatindex = 0;
+  char tempString[8];
+
+  DHT_temp = DHT_dht.readTemperature();
+  DHT_hum = DHT_dht.readHumidity();
+  DHT_heatindex = DHT_dht.computeHeatIndex(DHT_temp, DHT_hum, false);
+  //if (isnan(DHT_temp) || isnan(DHT_hum) || isnan(DHT_heatindex)) {
+  //  Serial.println("Failed to read from DHT sensor!");
+  //  return;
+  //}
+
+//todo, create root above sensor (buiten deze dht.
+  //add values to json
+  jsonDoc["sensor"] = "dht11";
+  jsonDoc["sensornumber"] = 1;
+  jsonDoc["data"]["temperature"] = dtostrf(DHT_temp, 5, 2, tempString);
+  jsonDoc["data"]["humidity"] = dtostrf(DHT_hum, 5, 2, tempString);
+  //jsonDoc["data"]["heatindex"] = dtostrf(DHT_heatindex, 5, 2, tempString);
+  //jsonDoc["data"]["heatindex"] = "1234";
+  Serial.print("DHT_temp     : "); Serial.print(DHT_temp); Serial.println(" C");
+  Serial.print("DHT_hum      : "); Serial.print(DHT_hum); Serial.println(" %");
+  Serial.print("DHT_heatindex: "); Serial.print(DHT_heatindex); Serial.println(" *C");
+  Serial.println("");
+}
+
+void MeasureBH1750FVI()
+{
+  /*
+    VCC  <-> 3V3 [grey]
+    GND  <-> Gnd [purple]
+    SDA  <-> D2  [green]
+    SCL  <-> D1  [blue]
+    ADDR <-> RX  [yellow]
+  */
+
   uint16_t lux = LightSensor.GetLightIntensity();
   Serial.print("Light: ");
   Serial.println(lux);
-  delay(250);
-}
+
+  keyAndValue_t SensorData[] = {
+    {"lux", String(lux)}
+  };
+
+  // Serial.println("SensorData:");
+  // for (int x = 0; x < sizeof(SensorData)/sizeof(SensorData[0]); x++) {
+  //   Serial.print(SensorData[x].key);
+  //   Serial.println(SensorData[x].value);
+  // }
+  //uint8_t Count = (sizeof(SensorData)/sizeof(SensorData[0]));    <---- werkt voor geen kloot
+  AddData("BH1750VI", 1, SensorData, 1);
+}
+
+// FakeSensor
+void MeasureFakeSensor()
+{
+  float FakeValA = 10.123;
+  float FakeValB = 20.123;
+
+  keyAndValue_t SensorData[] = {
+    {"FakeValA", String(FakeValA, 2)},
+    {"FakeValB", String(FakeValB, 3)}
+  };
+
+  //uint8_t Count = (sizeof(SensorData)/sizeof(SensorData[0]));
+  AddData("FakeSensor", 1, SensorData, 2);
+}


add flash warning

add flash warning

--- examples/ParamsChildClass/ParamsChildClass.ino
+++ examples/ParamsChildClass/ParamsChildClass.ino
@@ -64,6 +64,8 @@
         delay(1000);
     }

+    // warning for example only, this will initialize empty memory into your vars
+    // always init flash memory or add some checksum bits
     EEPROM.begin( 512 );
     EEPROM.get(0, sett);
     Serial.println("Settings loaded");


Remove from whitespace

Remove from whitespace

--- src/HC_NodeMcuCode.ino
+++ src/HC_NodeMcuCode.ino
@@ -497,14 +497,9 @@
     case s_idle:
       // State is currently: idle. Neather cooling or heating.
       if (checkHeatRequired(dht.readTemperature(), targetHeaterTemperature, targetHeaterTemperatureHyst, false))
-      {
         stateMachine = s_HeaterStart;    // Heat required, start.
-      }
       else if (checkCoolRequired(dht.readTemperature(), targetCoolerTemperature, targetCoolerTemperatureHyst, false))
-      {
         stateMachine = s_CoolerStart;    // Cooling required, start.
-      }
-
       break;

     case s_HeaterStart:
@@ -520,10 +515,7 @@
       // This inhibits the cooler turning on.
       // Check if we need to stop, by checking if heat is still required.
       if (!checkHeatRequired(dht.readTemperature(), targetHeaterTemperature, targetHeaterTemperatureHyst, true))
-      {
-        // Heat no longer required, stop.
-        stateMachine = s_HeaterStop;
-      }
+        stateMachine = s_HeaterStop; // Heat no longer required, stop.
       break;

     case s_HeaterStop:
@@ -548,10 +540,7 @@
       // This inhibits the heater turning on.
       // Check if we need to stop, by checking if cooling is still required.
       if (!checkCoolRequired(dht.readTemperature(), targetCoolerTemperature, targetCoolerTemperatureHyst, true))
-      {
-        // Cooling no longer required, stop.
-        stateMachine = s_CoolerStop;
-      }
+        stateMachine = s_CoolerStop; // Cooling no longer required, stop.
       break;

     case s_CoolerStop:
@@ -562,11 +551,7 @@
       // Set state mahcine to idle on the next loop
       stateMachine = s_idle;
       break;
-
-  }
-}
-
-
+  }}

 void setup() {
   // Initialize pins


Added Finnish summer/winter time support

Used to have hardcoded Finnish summertime

--- SetTime/SetTime.ino
+++ SetTime/SetTime.ino
@@ -54,6 +54,14 @@
   int tm_sec;
 };

+#define SUNDAY 0
+#define MONDAY 1
+#define TUESDAY 2
+#define WEDNESDAY 3
+#define THURSDAY 4
+#define FRIDAY 5
+#define SATURDAY 6
+
 #define EPOCH_YR                1970
 #define SECS_DAY                (24L * 60L * 60L)
 #define LEAPYEAR(year)          (!((year) % 4) && (((year) % 100) || !((year) % 400)))
@@ -99,6 +107,51 @@
   }
   tmbuf->tm_mday = dayno + 1;
   return tmbuf;
+}
+
+int countsOfWeekdayBeforeNextMonth(struct tm* tm, int wday)
+{
+  int count = 0;
+  int curMday = tm->tm_mday;
+  int curWday = tm->tm_wday;
+  while (curMday <= yearDays[LEAPYEAR(tm->tm_year)][tm->tm_mon]) {
+    if (curWday == wday) {
+      ++count;
+    }
+    ++curMday;
+    ++curWday;
+    if (curWday == 7) {
+      curWday = 0;
+    }
+  }
+  return count;
+}
+
+bool afterOrAtLastSunday(struct tm* tm)
+{
+  return
+    (tm->tm_wday == 0 && countsOfWeekdayBeforeNextMonth(tm, SUNDAY) == 1) ||
+    (countsOfWeekdayBeforeNextMonth(tm, SUNDAY) == 0);
+}
+
+int tzOffset(struct tm* tm)
+{
+  bool isSummerTime =
+    (tm->tm_mon > 2 ||
+     (tm->tm_mon == 2 && /* maaliskuu, tm_mon alkaa nollasta */
+      afterOrAtLastSunday(tm)
+     )
+    ) && (
+     tm->tm_mon < 9 ||
+     (tm->tm_mon == 9 && /* lokakuu, tm_mon alkaa nollasta */
+      !afterOrAtLastSunday(tm)
+     )
+    );
+  if (isSummerTime) {
+    return 3600 * 3;
+  } else {
+    return 3600 * 2;
+  }
 }

 /* End of time manipulation code */
@@ -304,16 +357,26 @@
       uint32_t now = curTime;
       interrupts();
       if (now != prevTime) {
+        prevTime = now;
         struct tm tm;
-        gmtime_r(now + TZ_OFFSET, &tm);
+        gmtime_r(now, &tm);
+        int offset = tzOffset(&tm);
+        gmtime_r(now + offset, &tm);
         sendHHMM(tm.tm_hour, tm.tm_min, B8(0110000));
+        Serial.print(tm.tm_year);
+        Serial.print("-");
+        Serial.print(tm.tm_mon + 1);
+        Serial.print("-");
+        Serial.print(tm.tm_mday);
+        Serial.print(" ");
+        Serial.print(tm.tm_wday);
+        Serial.print(" ");
         Serial.print(tm.tm_hour);
         Serial.print(":");
         Serial.print(tm.tm_min);
         Serial.print(":");
         Serial.print(tm.tm_sec);
         Serial.println();
-        prevTime = now;
       }
     }
   }


Change the trigger frequency to 9Hz.

Change the trigger frequency to 9Hz.

--- Trigger/Trigger.ino
+++ Trigger/Trigger.ino
@@ -1,6 +1,6 @@

 //
-// Generate a signal to trigger camera and lightning
+// Generate a 9Hz signal to trigger camera and lightning
 //

 // Setup
@@ -10,8 +10,7 @@
 int button_state;
 int last_button_state = LOW;
 int high_duration = 10;
-int low_duration = 190; // 5Hz
-//int low_duration = 101; // 9Hz
+int low_duration = 101;

 // Arduino setup
 void setup() {


ChangeBC127Baudrate: start with hardware reset, and interactive baudrate changing ability

--- examples/07-Bluetooth/ChangeBC127Baudrate/ChangeBC127Baudrate.ino
+++ examples/07-Bluetooth/ChangeBC127Baudrate/ChangeBC127Baudrate.ino
@@ -20,122 +20,104 @@

 #include <Arduino.h>
 #include <Tympan_Library.h>
-BLE        ble(&Serial1);

 // USER PARAMETERS
 const int TARGET_BAUDRATE = 115200;    //try 115200 (fast!) or 9600 (factory original)
-const int FIRMWARE_VERSION = 7;        // what Melody firmware we are dealing with
-const bool USE_HARDWARE_RESET = true;  //try to use the BC127 GPIO Pins to force a factory reset

-const int pin_PIO0 = 5; //RevD = 56, RevE = 5   // Pin # for connection to BC127 PIO0 pin
-const int pin_RST = 9;  //RevD = 34, RevE = 9   // Pin # for connection to BC127 RST pin
+// Automatically choose which Tympan and which firmware (you can override!)
+#ifdef KINETISK  //this is set by the Arduino IDE when you choose Teensy 3.6
+  //REV D...does not work reliably with RevD.  I don't know why
+  Tympan myTympan(TympanRev::D);      //sets all the control pins correctly
+  const int FIRMWARE_VERSION = 5;     // what Melody firmware we are dealing with
+#else
+  //REV E
+  Tympan myTympan(TympanRev::E);       //sets all the control pins correctly
+  const int FIRMWARE_VERSION = 7;      // what Melody firmware we are dealing with
+#endif

+//define the pins that are used for the hardware reset
+const int pin_PIO0 = myTympan.getTympanPins().BT_PIO0;   //RevD = 56, RevE = 5   // Pin # for connection to BC127 PIO0 pin
+const int pin_RST = myTympan.getTympanPins().BT_nReset;  //RevD = 34, RevE = 9   // Pin # for connection to BC127 RST pin
+const int pin_VREGEN = myTympan.getTympanPins().BT_REGEN;
+
+const int baudrate_factory = 9600;       // here is the factory default

 // //////////////////////////////////////////// Helper functions

-const int baudrate_factory = 9600;       // here is the factory default
-const int baudrate1 = baudrate_factory;  //here is one possible starting baudrate for the BLE module
-const int baudrate2 = 115200;            //here is the other possible starting baudrate for the BLE module
-int cur_baudrate;  // this is the baudrate that we've set Serial1 to be
+
 void setSerial1BaudRate(int new_baud) {
-  Serial1.flush();
-  Serial1.end();
-  delay(500);
-  Serial1.begin(new_baud);
-  delay(500);
-  cur_baudrate = new_baud;
+  Serial1.flush();  Serial1.end();   Serial1.begin(new_baud);
 }
-

 //This function attempts to hold PIO 0 high and then reseting via the reset pin.
 //See Melody Guide for v7 "Restoring the Default Configuration".
 void hardwareReset() {
-  //Set the reset pin.  "Normal" is high impedance with an external pull-up.  Let's
-  //set our default to high-impedance ("INPUT") with also an internal pullup, then
-  //transition to low-impedance (ie, "OUTPUT") set high
-  pinMode(pin_RST, INPUT);
-  digitalWrite(pin_RST, HIGH);
-  pinMode(pin_RST, OUTPUT);
-  digitalWrite(pin_RST, HIGH);

-  //now set the PIO0 pin.  Normal is PIO0
-  pinMode(pin_PIO0,OUTPUT);
-  digitalWrite(pin_PIO0, LOW);
+  //Serial.println("HardwareReset: RST Pin = " + String(pin_RST) + ", PIO0 Pin = " + String(pin_PIO0));
+
+  pinMode(pin_PIO0,OUTPUT);    //prepare the PIO0 pin
+  digitalWrite(pin_PIO0,HIGH); //normally low.  Swtich high

-  //stall for a tiny bit (for no good reason)
-  delay(50);
+  pinMode(pin_RST,OUTPUT);    //prepare the reset pin
+  digitalWrite(pin_RST,LOW);  //pull low to reset
+  delay(20);                  //hold low for at least 5 msec
+  digitalWrite(pin_RST,HIGH); //pull high to start the boot

-  //Now we follow the instructions in the Melody User Guide
-  //
-  // The default configuration can be restored using either of the following equivalent
-  // methods:
-  //   * Maintain PIO 0 high (press the VOL UP button on a BC127-DISKIT) while
-  //     resetting the module
-  //   * Use RESTORE
-  digitalWrite(pin_PIO0,HIGH);
-  delay(5); //let it setting
-
-  //And, from the Datasheet, reset if low for more than 5msec
-  digitalWrite(pin_RST,LOW);  //pull the pin low to start reset timer
-  delay(10);                  //resets if low for more than 5 msec
-  digitalWrite(pin_RST,LOW);  //return to normal
+  //wait for boot to proceed far enough before changing anything
+  delay(400);                 //V7: works with 200 but not 175.  V5: works with 350 but not 300

-  //did it reset?  It should report its ID info to the Serial
+  digitalWrite(pin_PIO0,LOW); //pull PIO0 back down low
+  pinMode(pin_PIO0,INPUT);    //go high-impedance to make irrelevant

-  //return to normal
-  delay(10);
-  digitalWrite(pin_PIO0,LOW); //return to normal
 }

-int hardwareResetWithChecking(void) {
-  Serial.println("setup(): Attempting a hardware reset...");
-
-  //if successfull, we'll end up in the factory baudrate.  So, let's switch
-  //so that we can get its boot-up message
-  setSerial1BaudRate(baudrate_factory);
-
-  //do the hardware reset
-  hardwareReset();
-
-  //check for the boot message
-  delay(500);
-  echoIncomingBTSerial();
-  Serial.println("Did you see the boot-up info from the BC127??");
-
-  //check BT status (another way to confirm that we have the right speed
-  ret_val = checkStatusBLE();
-  if (ret_val != BC127::SUCCESS) {
-    Serial.println("setup(): Hardware reset FAILED to restore factory baudrate.");
-    return -1; //fail
-  } else {
-    Serial.println("setup(): Hardware reset SUCCESSS in restoring factory baudrate.");
-  }
-  return 0; //assume success
-}
-
-//If the baudrate to the BLE modue matches that baudrate that the BLE module expects,
-//we should be able to ask its status and get a valid reply.  So, we don't get a valid
-//reply, the baudrate of Serial1 probably does not match.
-int checkStatusBLE(void) {
-  int ret_val = ble.status(true);
-  Serial.println("checkStatusBLE: reply code to status = " + String(ret_val));
-  if (ret_val != BC127::SUCCESS) {
-    Serial.println("checkStatusBLE: status() returned error: " + String(ret_val));
+void changeBaudRateBC127(int target_rate, int firmware_ver) {
+  //Serial.println("setup: Firmware V" + String(firmware_ver) + ": Change baudrate on the BC127 to "  + String(target_rate) + "...");
+  if (firmware_ver > 5)  {
+    //On version 7.3, the baud rate shift is instant.
+    Serial1.print("SET UART_CONFIG=");Serial1.print(target_rate);Serial1.print(" OFF 0");Serial1.print('\r');
+  } else  {
+    //On version 5, the baud rate shift is instant.
+    Serial1.print("SET BAUD=");Serial1.print(target_rate);Serial1.print('\r');
   }
-  return ret_val;
 }

 // Echo what's coming in on USB Serial out to Bluetooth Serial
 void echoIncomingUSBSerial(void) {
-  while (Serial.available()) Serial1.write(Serial.read());
+    while (Serial.available())
+    {
+      char c = Serial.read();
+      if (c == '|') {
+          Serial.println("Switching Serial1 to 115200...");
+          setSerial1BaudRate(115200);
+      } else if (c =='\\') {
+          Serial.println("Switching Serial1 to 9600...");
+          setSerial1BaudRate(9600);
+      } else if (c == ']') {
+          Serial.println("Hardware reset...");
+          hardwareReset();
+      } else {
+          Serial1.write(c); //send to Bluetooth
+      }
+    }
 }

 // Echo what's coming in on Bluetooth Serial out to USB Serial
 void echoIncomingBTSerial(void) {
+  static char prev_char;
   while (Serial1.available()) {
-    char c = Serial1.read();
-    if (c == '\r') c = '\n'; //translate carriage return to newline
-    Serial.write(c);
+    char orig_c = Serial1.read();
+    char c = orig_c;
+    if ((c == '\n') && (prev_char == '\r')) {
+      //don't send
+    } else if ((c == '\r') && (prev_char == '\n')) {
+      //don't send
+    } else {
+      //send the character (perhaps modified)
+      if (c == '\r') c = '\n'; //translate carriage return to newline
+      Serial.write(c);
+    }
+    prev_char = orig_c;
   }
 }

@@ -143,61 +125,70 @@
 // ///////////////////////////////////////////////////  Arduino setup() and loop()

 void setup() {
-  //Serial.begin(115200);  //on Teensy (and Tympan), you don't need to do this.

-  //tell the BLE class what firmware we think that is actually on the BC127
-  ble.set_BC127_firmware_ver(FIRMWARE_VERSION);
+  //////////////////////////////////////////////// Factory reset to known baud rate (9600)

-  //Start Serial1 to the BT module
-  Serial.println("setup(): Starting Serial1 at " + String(baudrate1));
-  setSerial1BaudRate(baudrate1);
+  Serial.println("setup(): Setting Teensy Serial1 at " + String(baudrate_factory));
+  setSerial1BaudRate(baudrate_factory);

-  //check on ble module...
-  int ret_val = checkStatusBLE();
-  if (ret_val != BC127::SUCCESS) {
+  //clear out buffers
+  //while (Serial.available()) Serial.read();
+  //while (Serial1.available()) Serial1.read();

-    //try a different baud rate
-    Serial.println("setup(): Trying again but at " + String(baudrate2));
-    setSerial1BaudRate(baudrate2);
-    cur_baudrate = baudrate2;
+  //Force a hardware reset...which should drop baudrate to factory setting
+  Serial.println("setup(): hardware reset...");
+  hardwareReset();
+  delay(2000);            //delay of 1250 seems to work for V5 but 1000 occasionally fails.  1250 failed once.
+  echoIncomingBTSerial(); //should get Melody ID text (end with READY or OK)
+  Serial.println();

-    //check on ble module again...
-    ret_val = checkStatusBLE();
-    if (ret_val == BC127::SUCCESS) {
+  ///////////////////////////////////////////////// Change baud rate on the BC127

-      // we were successful at the new baud rate, so stick with it!
-      Serial.println("Success! The module was at " + String(baudrate2));
+  //Switch the baudrate on the BC127
+  Serial.print("setup(): commanding BC127 to change baud rate to "); Serial.println(TARGET_BAUDRATE);
+  changeBaudRateBC127(TARGET_BAUDRATE, FIRMWARE_VERSION);
+
+  //Switch Teensy serial to the matching speed
+  setSerial1BaudRate(TARGET_BAUDRATE);
+  Serial.println("setup(): switching Teensy Serial1 to new baud rate " + String(TARGET_BAUDRATE));

-    } else {
-      //Failed.  So, return Serial1 to original baud rate
-      Serial.println("Returning to Serial1 to original baud rate...this whole thing probably will not work");
-      setSerial1BaudRate(baudrate1);
-      cur_baudrate = baudrate1;
-    }
+  //Listen for response to the change in baud rate (or, at least, clear out the serial
+  delay(500);              //500 seems to work on V5
+  echoIncomingBTSerial();  //clear out the serial
+
+  //send carriage return to induce "ERROR" message to clear out the serial link both ways
+  Serial.println("setup(): issuing Carriage Return to clear serial...should return ERROR...");
+  Serial1.print('\r');  //should cause response of "ERROR"
+  delay(100);  echoIncomingBTSerial();  //should get error
+
+  //send WRITE to save the baud rate and send another writes just to clear up the Serial link
+  Serial.println("setup(): issuing WRITE command to save the new rate");
+  Serial1.print("WRITE");Serial1.print('\r');
+  delay(200);  echoIncomingBTSerial();  //should get OK
+
+  //Serial.println("setup(): issuing second WRITE command to save the new rate to ensure we're good");
+  //Serial1.print("WRITE");Serial1.print('\r');
+  //delay(200);  echoIncomingBTSerial();  //should get OK
+
+  ///////////////////////////////////////////////// Check to make sure that we're good
+
+  Serial.println("setup(): Asking baud rate of BC127...");
+  if (FIRMWARE_VERSION > 6) {
+    Serial1.print("GET UART_CONFIG");Serial1.print('\r');
+  } else {
+    Serial1.print("GET BAUD");Serial1.print('\r');
   }
+  delay(200); echoIncomingBTSerial();  //should give the value of the new baud rate

-  //try forcing a hardware reset
-  if (USE_HARDWARE_RESET) hardwareResetWithChecking();
-
-  //switch to desired baudrate
-  if (cur_baudrate != TARGET_BAUDRATE) {
-    //let's try commanding the BC127 to the new baud rate anyway
-    Serial.println("Change baudrate on the BC127 to "  + String(TARGET_BAUDRATE) + "...");
-    char cmdBuffer[100];
-    if (FIRMWARE_VERSION > 5)  {
-      sprintf(cmdBuffer, "SET UART_CONFIG=%u OFF 0\rWRITE\rRESTORE\r", TARGET_BAUDRATE);  //restore? or do we want reset?
-    } else  {
-      sprintf(cmdBuffer, "SET BAUD=%u\rWRITE\rRESTORE\r", TARGET_BAUDRATE);  //restore?  or do we want reset?
-    }
-    Serial1.write(cmdBuffer);  delay(500);
-    echoIncomingBTSerial();
-
-    Serial.println("Switching Serial1 to new baud rate..." + String(TARGET_BAUDRATE));
-    setSerial1BaudRate(TARGET_BAUDRATE);
-    cur_baudrate = TARGET_BAUDRATE;
-  }
-
-  Serial.println("Begin echoing commands with BC127.  Try BC127 commands like STATUS or VERSION...(carriage return!)");
+  Serial.println();
+  Serial.println("We are done!  Now echoing commands with the BC127...");
+  Serial.println();
+  Serial.println("To change BC127 baud rate: for V5, send: SET BAUD=115200   for V7: send: SET UART_CONFIG=115200 OFF 0");
+  Serial.println("To change Tympan baud rate, send '|' for 115200 or send '\\' for 9600");
+  Serial.println("To force a hardware reset of the BC127, send ']'");
+  Serial.println();
+  Serial.println("Try BC127 commands like STATUS or VERSION or ADVERTISING ON...(with carriage return!)");
+  Serial.println();
 }

 void loop() {


Controller doesn't start with Analog on(Hopefully)

Unless the game forces it to be always Analog on in DualShock 2 mode or Semi-Analog mode.

--- ps2_controller/ps2_controller.ino
+++ ps2_controller/ps2_controller.ino
@@ -166,9 +166,33 @@

 void setup() {

+  int powerRelayDelay = 133;
+  int powerRelayCounter = 3;
   pinMode(relayPin, OUTPUT);
-  delay(0.5); // Wait 0.5 second before turning off controller
-  digitalWrite(relayPin, LOW);
+  pinMode(buttonAnalog, OUTPUT);
+  digitalWrite(buttonAnalog, HIGH);
+  for (int relayCounter = 0; relayCounter < powerRelayCounter; relayCounter++)
+  {
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, LOW);
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, HIGH);
+  }
+  for (int relayCounter = 0; relayCounter < powerRelayCounter; relayCounter++)
+  {
+    delay(powerRelayDelay);
+    digitalWrite(relayPin, HIGH);
+    delay(powerRelayDelay);
+    digitalWrite(relayPin, LOW);
+  }
+  for (int relayCounter = 0; relayCounter < powerRelayCounter; relayCounter++)
+  {
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, LOW);
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, HIGH);
+  }
+  digitalWrite(buttonAnalog, HIGH);

   serial_rx_buffer_toggle_controller_pwr[0] = 0x17;
   serial_rx_buffer_toggle_controller_pwr[1] = 0x00;
@@ -494,8 +518,29 @@
   changeAutoResetControllerData();
   //Serial.println("END OF SETUP");
   //  And we are ready to go
-  delay(0.5); // Wait 0.5 second before turning on controller
-  digitalWrite(relayPin, HIGH);
+  digitalWrite(buttonAnalog, HIGH);
+  for (int relayCounter = 0; relayCounter < powerRelayCounter; relayCounter++)
+  {
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, LOW);
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, HIGH);
+  }
+  for (int relayCounter = 0; relayCounter < powerRelayCounter; relayCounter++)
+  {
+    delay(powerRelayDelay);
+    digitalWrite(relayPin, LOW);
+    delay(powerRelayDelay);
+    digitalWrite(relayPin, HIGH);
+  }
+  for (int relayCounter = 0; relayCounter < powerRelayCounter; relayCounter++)
+  {
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, LOW);
+    delay(powerRelayDelay);
+    digitalWrite(buttonAnalog, HIGH);
+  }
+  digitalWrite(buttonAnalog, HIGH);
 }

 void loop() {


Version 1.5 24th January 2017

Version 1.5 24th January 2017

* Adds support for strings, allowing you to write programs that prompt the user for input, or manipulate strings.

* Includes the string functions subseq for extracting a substring from a string, string= for comparing strings, length for finding the length of a string, and stringp for testing for strings.

--- ulisp.ino
+++ ulisp.ino
@@ -1,5 +1,5 @@
-/* uLisp Version 1.4 - www.ulisp.com
-   David Johnson-Davies - www.technoblogy.com - 18th October 2016
+/* uLisp Version 1.5 - www.ulisp.com
+   David Johnson-Davies - www.technoblogy.com - 24th January 2017

    Licensed under the MIT license: https://opensource.org/licenses/MIT
 */
@@ -29,6 +29,7 @@
 #define pop(y)             ((y) = cdr(y))

 #define numberp(x)         ((x)->type == NUMBER)
+#define stringp(x)         ((x)->type == STRING)
 #define streamp(x)         ((x)->type == STREAM)
 #define listp(x)           ((x) == NULL || (x)->type >= PAIR || (x)->type == ZERO)
 #define consp(x)           (((x)->type >= PAIR || (x)->type == ZERO) && (x) != NULL)
@@ -49,20 +50,20 @@
 const int EEPROMsize = E2END;

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

 enum function { SYMBOLS, NIL, TEE, LAMBDA, LET, LETSTAR, CLOSURE, SPECIAL_FORMS, QUOTE, DEFUN, DEFVAR,
 SETQ, LOOP, PUSH, POP, INCF, DECF, SETF, DOLIST, DOTIMES, FORMILLIS, WITHI2C, WITHSPI, TAIL_FORMS, PROGN,
-RETURN, IF, COND, WHEN, UNLESS, AND, OR, FUNCTIONS, NOT, NULLFN, CONS, ATOM, LISTP, CONSP, NUMBERP,
-STREAMP, EQ, CAR, FIRST, CDR, REST, CAAR, CADR, SECOND, CDAR, CDDR, CAAAR, CAADR, CADAR, CADDR, THIRD,
-CDAAR, CDADR, CDDAR, CDDDR, LENGTH, LIST, REVERSE, NTH, ASSOC, MEMBER, APPLY, FUNCALL, APPEND, MAPC,
-MAPCAR, ADD, SUBTRACT, MULTIPLY, DIVIDE, MOD, ONEPLUS, ONEMINUS, ABS, RANDOM, MAX, MIN, NUMEQ, LESS,
-LESSEQ, GREATER, GREATEREQ, NOTEQ, PLUSP, MINUSP, ZEROP, ODDP, EVENP, LOGAND, LOGIOR, LOGXOR, LOGNOT,
-ASH, LOGBITP, READ, EVAL, GLOBALS, LOCALS, MAKUNBOUND, BREAK, PRINT, PRINC, WRITEBYTE, READBYTE,
-RESTARTI2C, GC, ROOM, SAVEIMAGE, LOADIMAGE, CLS, PINMODE, DIGITALREAD, DIGITALWRITE, ANALOGREAD,
-ANALOGWRITE, DELAY, MILLIS, NOTE, EDIT, ENDFUNCTIONS };
+RETURN, IF, COND, WHEN, UNLESS, AND, OR, FUNCTIONS, NOT, NULLFN, CONS, ATOM, LISTP, CONSP, NUMBERP,
+STREAMP, EQ, CAR, FIRST, CDR, REST, CAAR, CADR, SECOND, CDAR, CDDR, CAAAR, CAADR, CADAR, CADDR, THIRD,
+CDAAR, CDADR, CDDAR, CDDDR, LENGTH, LIST, REVERSE, NTH, ASSOC, MEMBER, APPLY, FUNCALL, APPEND, MAPC,
+MAPCAR, ADD, SUBTRACT, MULTIPLY, DIVIDE, MOD, ONEPLUS, ONEMINUS, ABS, RANDOM, MAX, MIN, NUMEQ, LESS,
+LESSEQ, GREATER, GREATEREQ, NOTEQ, PLUSP, MINUSP, ZEROP, ODDP, EVENP, STRINGP, STRINGEQ, SUBSEQ, LOGAND,
+LOGIOR, LOGXOR, LOGNOT, ASH, LOGBITP, READ, EVAL, GLOBALS, LOCALS, MAKUNBOUND, BREAK, PRINT, PRINC,
+WRITEBYTE, READBYTE, RESTARTI2C, GC, ROOM, SAVEIMAGE, LOADIMAGE, CLS, PINMODE, DIGITALREAD, DIGITALWRITE,
+ANALOGREAD, ANALOGWRITE, DELAY, MILLIS, NOTE, EDIT, ENDFUNCTIONS };

 // Typedefs

@@ -109,6 +110,7 @@
 char LastPrint = 0;
 volatile char Escape = 0;
 char ExitEditor = 0;
+char PrintReadably = 1;

 // Forward references
 object *tee;
@@ -135,7 +137,7 @@
   }
 }

-object *myalloc() {
+object *myalloc () {
   if (freespace == 0) error(F("No room"));
   object *temp = freelist;
   freelist = cdr(freelist);
@@ -143,7 +145,8 @@
   return temp;
 }

-void myfree (object *obj) {
+inline void myfree (object *obj) {
+  car(obj) = NULL;
   cdr(obj) = freelist;
   freelist = obj;
   freespace++;
@@ -152,28 +155,28 @@
 // Make each type of object

 object *number (int n) {
-  object *ptr = (object *) myalloc ();
+  object *ptr = myalloc();
   ptr->type = NUMBER;
   ptr->integer = n;
   return ptr;
 }

 object *cons (object *arg1, object *arg2) {
-  object *ptr = (object *) myalloc ();
+  object *ptr = myalloc();
   ptr->car = arg1;
   ptr->cdr = arg2;
   return ptr;
 }

 object *symbol (unsigned int name) {
-  object *ptr = (object *) myalloc ();
+  object *ptr = myalloc();
   ptr->type = SYMBOL;
   ptr->name = name;
   return ptr;
 }

 object *stream (unsigned char streamtype, unsigned char address) {
-  object *ptr = (object *) myalloc ();
+  object *ptr = myalloc();
   ptr->type = STREAM;
   ptr->integer = streamtype<<8 | address;
   return ptr;
@@ -184,10 +187,9 @@
 void markobject (object *obj) {
   MARK:
   if (obj == NULL) return;
-
+  if (marked(obj)) return;
+
   object* arg = car(obj);
-  if (marked(obj)) return;
-
   int type = obj->type;
   mark(obj);

@@ -196,6 +198,15 @@
     obj = cdr(obj);
     goto MARK;
   }
+
+  if (type == STRING) {
+    obj = cdr(obj);
+    while (obj != NULL) {
+      arg = car(obj);
+      mark(obj);
+      obj = arg;
+    }
+  }
 }

 void sweep () {
@@ -203,12 +214,7 @@
   freespace = 0;
   for (int i=workspacesize-1; i>=0; i--) {
     object *obj = &workspace[i];
-    if (!marked(obj)) {
-      car(obj) = NULL;
-      cdr(obj) = freelist;
-      freelist = obj;
-      freespace++;
-    } else unmark(obj);
+    if (!marked(obj)) myfree(obj); else unmark(obj);
   }
 }

@@ -447,6 +453,30 @@
     length++;
   }
   return length;
+}
+
+inline int stringlength (object *form) {
+  int length = 0;
+  form = cdr(form);
+  while (form != NULL) {
+    int chars = form->integer;
+    if (chars & 0xFF) length++;
+    if (chars & 0xFF00) length++;
+    form = car(form);
+  }
+  return length;
+}
+
+char character (object *string, int n) {
+  object *arg = cdr(string);
+  for (int i=0; i<(n>>1); i++) {
+    if (arg == NULL) error(F("'subseq' index out of range"));
+    arg = car(arg);
+  }
+  char ch;
+  if (n&1) ch = (arg->integer) & 0xFF; else ch = (arg->integer)>>8 & 0xFF;
+  if (ch == 0) error(F("'subseq' index out of range"));
+  return ch;
 }

 object *apply (object *function, object *args, object **env) {
@@ -985,9 +1015,10 @@

 object *fn_length (object *args, object *env) {
   (void) env;
-  object *list = first(args);
-  if (!listp(list)) error(F("'length' argument is not a list"));
-  return number(listlength(list));
+  object *arg = first(args);
+  if (listp(arg)) return number(listlength(arg));
+  if (!stringp(arg)) error(F("'length' argument is not a list or string"));
+  return number(stringlength(arg));
 }

 object *fn_list (object *args, object *env) {
@@ -1089,8 +1120,11 @@
   object *list1 = second(args);
   object *result = list1;
   if (!listp(list1)) error(F("'mapc' second argument is not a list"));
-  object *list2 = third(args);
-  if (!listp(list2)) error(F("'mapc' third argument is not a list"));
+  object *list2 = cddr(args);
+  if (list2 != NULL) {
+    list2 = car(list2);
+    if (!listp(list2)) error(F("'mapc' third argument is not a list"));
+  }
   if (list2 != NULL) {
     while (list1 != NULL && list2 != NULL) {
       apply(function, cons(car(list1),cons(car(list2),NULL)), &env);
@@ -1110,8 +1144,11 @@
   object *function = first(args);
   object *list1 = second(args);
   if (!listp(list1)) error(F("'mapcar' second argument is not a list"));
-  object *list2 = third(args);
-  if (!listp(list2)) error(F("'mapcar' third argument is not a list"));
+  object *list2 = cddr(args);
+  if (list2 != NULL) {
+    list2 = car(list2);
+    if (!listp(list2)) error(F("'mapcar' third argument is not a list"));
+  }
   object *head = NULL;
   object *tail = NULL;
   if (list2 != NULL) {
@@ -1402,6 +1439,62 @@
   else return nil;
 }

+// Strings
+
+object *fn_stringp (object *args, object *env) {
+  (void) env;
+  object *arg1 = first(args);
+  return stringp(arg1) ? tee : nil;
+}
+
+object *fn_stringeq (object *args, object *env) {
+  (void) env;
+  object *arg1 = first(args);
+  if (!stringp(arg1)) error(F("'string=' first argument is not a string"));
+  object *arg2 = second(args);
+  if (!stringp(arg2)) error(F("'string=' second argument is not a string"));
+  arg1 = cdr(arg1);
+  arg2 = cdr(arg2);
+  while ((arg1 != NULL) || (arg2 != NULL)) {
+    if ((arg1 == NULL) || (arg2 == NULL) || (arg1->integer != arg2->integer)) return nil;
+    arg1 = car(arg1);
+    arg2 = car(arg2);
+  }
+  return tee;
+}
+
+object *fn_subseq (object *args, object *env) {
+  (void) env;
+  object *arg = first(args);
+  if (!stringp(arg)) error(F("'subseq' first argument is not a string"));
+  int start = integer(second(args));
+  int end;
+  args = cddr(args);
+  if (args != NULL) end = integer(car(args)); else end = stringlength(arg);
+  object *result = myalloc();
+  result->type = STRING;
+  object *head = NULL;
+  object *tail = NULL;
+  int chars = 0;
+  for (int i=start; i<end; i++) {
+    char ch = character(arg, i);
+    if (chars == 0) {
+      chars = ch<<8;
+      object *cell = myalloc();
+      if (head == NULL) head = cell; else tail->car = cell;
+      cell->car = NULL;
+      cell->integer = chars;
+      tail = cell;
+    } else {
+      chars = chars | ch;
+      tail->integer = chars;
+      chars = 0;
+    }
+  }
+  result->cdr = head;
+  return result;
+}
+
 // Bitwise operators

 object *fn_logand (object *args, object *env) {
@@ -1528,7 +1621,10 @@
 object *fn_princ (object *args, object *env) {
   (void) env;
   object *obj = first(args);
+  char temp = PrintReadably;
+  PrintReadably = 0;
   printobject(obj);
+  PrintReadably = temp;
   return obj;
 }

@@ -1683,7 +1779,7 @@
   return number(temp);
 }

-const uint8_t scale[] PROGMEM = { 239,225,213,201,190,179,169,159,150,142,134,127};
+const uint8_t scale[] PROGMEM = {239,226,213,201,190,179,169,160,151,142,134,127};

 object *fn_note (object *args, object *env) {
   (void) env;
@@ -1702,7 +1798,7 @@
     if (cddr(args) != NULL) prescaler = integer(third(args));
     prescaler = 9 - prescaler - note/12;
     if (prescaler<3 || prescaler>6) error(F("'note' octave out of range"));
-    OCR2A = pgm_read_byte(&scale[note%12]);
+    OCR2A = pgm_read_byte(&scale[note%12]) - 1;
     TCCR2B = 0<<WGM22 | prescaler<<CS20;
   } else TCCR2B = 0<<WGM22 | 0<<CS20;

@@ -1721,7 +1817,7 @@
     if (cddr(args) != NULL) prescaler = integer(third(args));
     prescaler = 9 - prescaler - note/12;
     if (prescaler<3 || prescaler>6) error(F("'note' octave out of range"));
-    OCR2A = pgm_read_byte(&scale[note%12]);
+    OCR2A = pgm_read_byte(&scale[note%12]) - 1;
     TCCR2B = 0<<WGM22 | prescaler<<CS20;
   } else TCCR2B = 0<<WGM22 | 0<<CS20;

@@ -1740,7 +1836,7 @@
     if (cddr(args) != NULL) prescaler = integer(third(args));
     prescaler = 9 - prescaler - note/12;
     if (prescaler<3 || prescaler>6) error(F("'note' octave out of range"));
-    OCR2A = pgm_read_byte(&scale[note%12]);
+    OCR2A = pgm_read_byte(&scale[note%12]) - 1;
     TCCR2B = 0<<WGM22 | prescaler<<CS20;
   } else TCCR2B = 0<<WGM22 | 0<<CS20;
   #endif
@@ -1873,37 +1969,40 @@
 const char string90[] PROGMEM = "zerop";
 const char string91[] PROGMEM = "oddp";
 const char string92[] PROGMEM = "evenp";
-const char string93[] PROGMEM = "logand";
-const char string94[] PROGMEM = "logior";
-const char string95[] PROGMEM = "logxor";
-const char string96[] PROGMEM = "lognot";
-const char string97[] PROGMEM = "ash";
-const char string98[] PROGMEM = "logbitp";
-const char string99[] PROGMEM = "read";
-const char string100[] PROGMEM = "eval";
-const char string101[] PROGMEM = "globals";
-const char string102[] PROGMEM = "locals";
-const char string103[] PROGMEM = "makunbound";
-const char string104[] PROGMEM = "break";
-const char string105[] PROGMEM = "print";
-const char string106[] PROGMEM = "princ";
-const char string107[] PROGMEM = "write-byte";
-const char string108[] PROGMEM = "read-byte";
-const char string109[] PROGMEM = "restart-i2c";
-const char string110[] PROGMEM = "gc";
-const char string111[] PROGMEM = "room";
-const char string112[] PROGMEM = "save-image";
-const char string113[] PROGMEM = "load-image";
-const char string114[] PROGMEM = "cls";
-const char string115[] PROGMEM = "pinmode";
-const char string116[] PROGMEM = "digitalread";
-const char string117[] PROGMEM = "digitalwrite";
-const char string118[] PROGMEM = "analogread";
-const char string119[] PROGMEM = "analogwrite";
-const char string120[] PROGMEM = "delay";
-const char string121[] PROGMEM = "millis";
-const char string122[] PROGMEM = "note";
-const char string123[] PROGMEM = "edit";
+const char string93[] PROGMEM = "stringp";
+const char string94[] PROGMEM = "string=";
+const char string95[] PROGMEM = "subseq";
+const char string96[] PROGMEM = "logand";
+const char string97[] PROGMEM = "logior";
+const char string98[] PROGMEM = "logxor";
+const char string99[] PROGMEM = "lognot";
+const char string100[] PROGMEM = "ash";
+const char string101[] PROGMEM = "logbitp";
+const char string102[] PROGMEM = "read";
+const char string103[] PROGMEM = "eval";
+const char string104[] PROGMEM = "globals";
+const char string105[] PROGMEM = "locals";
+const char string106[] PROGMEM = "makunbound";
+const char string107[] PROGMEM = "break";
+const char string108[] PROGMEM = "print";
+const char string109[] PROGMEM = "princ";
+const char string110[] PROGMEM = "write-byte";
+const char string111[] PROGMEM = "read-byte";
+const char string112[] PROGMEM = "restart-i2c";
+const char string113[] PROGMEM = "gc";
+const char string114[] PROGMEM = "room";
+const char string115[] PROGMEM = "save-image";
+const char string116[] PROGMEM = "load-image";
+const char string117[] PROGMEM = "cls";
+const char string118[] PROGMEM = "pinmode";
+const char string119[] PROGMEM = "digitalread";
+const char string120[] PROGMEM = "digitalwrite";
+const char string121[] PROGMEM = "analogread";
+const char string122[] PROGMEM = "analogwrite";
+const char string123[] PROGMEM = "delay";
+const char string124[] PROGMEM = "millis";
+const char string125[] PROGMEM = "note";
+const char string126[] PROGMEM = "edit";

 const tbl_entry_t lookup_table[] PROGMEM = {
   { string0, NULL, NIL, NIL },
@@ -1999,37 +2098,40 @@
   { string90, fn_zerop, 1, 1 },
   { string91, fn_oddp, 1, 1 },
   { string92, fn_evenp, 1, 1 },
-  { string93, fn_logand, 0, 127 },
-  { string94, fn_logior, 0, 127 },
-  { string95, fn_logxor, 0, 127 },
-  { string96, fn_lognot, 1, 1 },
-  { string97, fn_ash, 2, 2 },
-  { string98, fn_logbitp, 2, 2 },
-  { string99, fn_read, 0, 0 },
-  { string100, fn_eval, 1, 1 },
-  { string101, fn_globals, 0, 0 },
-  { string102, fn_locals, 0, 0 },
-  { string103, fn_makunbound, 1, 1 },
-  { string104, fn_break, 0, 0 },
-  { string105, fn_print, 1, 1 },
-  { string106, fn_princ, 1, 1 },
-  { string107, fn_writebyte, 1, 2 },
-  { string108, fn_readbyte, 0, 2 },
-  { string109, fn_restarti2c, 1, 2 },
-  { string110, fn_gc, 0, 0 },
-  { string111, fn_room, 0, 0 },
-  { string112, fn_saveimage, 0, 1 },
-  { string113, fn_loadimage, 0, 0 },
-  { string114, fn_cls, 0, 0 },
-  { string115, fn_pinmode, 2, 2 },
-  { string116, fn_digitalread, 1, 1 },
-  { string117, fn_digitalwrite, 2, 2 },
-  { string118, fn_analogread, 1, 1 },
-  { string119, fn_analogwrite, 2, 2 },
-  { string120, fn_delay, 1, 1 },
-  { string121, fn_millis, 0, 0 },
-  { string122, fn_note, 0, 3 },
-  { string123, fn_edit, 1, 1 },
+  { string93, fn_stringp, 1, 1 },
+  { string94, fn_stringeq, 2, 2 },
+  { string95, fn_subseq, 2, 3 },
+  { string96, fn_logand, 0, 127 },
+  { string97, fn_logior, 0, 127 },
+  { string98, fn_logxor, 0, 127 },
+  { string99, fn_lognot, 1, 1 },
+  { string100, fn_ash, 2, 2 },
+  { string101, fn_logbitp, 2, 2 },
+  { string102, fn_read, 0, 0 },
+  { string103, fn_eval, 1, 1 },
+  { string104, fn_globals, 0, 0 },
+  { string105, fn_locals, 0, 0 },
+  { string106, fn_makunbound, 1, 1 },
+  { string107, fn_break, 0, 0 },
+  { string108, fn_print, 1, 1 },
+  { string109, fn_princ, 1, 1 },
+  { string110, fn_writebyte, 1, 2 },
+  { string111, fn_readbyte, 0, 2 },
+  { string112, fn_restarti2c, 1, 2 },
+  { string113, fn_gc, 0, 0 },
+  { string114, fn_room, 0, 0 },
+  { string115, fn_saveimage, 0, 1 },
+  { string116, fn_loadimage, 0, 0 },
+  { string117, fn_cls, 0, 0 },
+  { string118, fn_pinmode, 2, 2 },
+  { string119, fn_digitalread, 1, 1 },
+  { string120, fn_digitalwrite, 2, 2 },
+  { string121, fn_analogread, 1, 1 },
+  { string122, fn_analogwrite, 2, 2 },
+  { string123, fn_delay, 1, 1 },
+  { string124, fn_millis, 0, 0 },
+  { string125, fn_note, 0, 3 },
+  { string126, fn_edit, 1, 1 },
 };

 // Table lookup functions
@@ -2075,7 +2177,7 @@

   if (form == NULL) return nil;

-  if (form->type == NUMBER) return form;
+  if ((form->type == NUMBER) || (form->type == STRING)) return form;

   if (form->type == SYMBOL) {
     unsigned int name = form->name;
@@ -2210,10 +2312,10 @@

 void pint (int i) {
   int lead = 0;
+  if (i<0) pchar('-');
   for (int d=10000; d>0; d=d/10) {
-    if (i<0) { pchar('-');i = -i;}
     int j = i/d;
-    if (j!=0 || lead || d==1) { pchar(j+'0'); lead=1;}
+    if (j!=0 || lead || d==1) { pchar(abs(j)+'0'); lead=1;}
     i = i - j*d;
   }
 }
@@ -2228,7 +2330,7 @@

 void printobject(object *form){
   #if defined(debug2)
-  pchar('[');pint((int)form);pchar(']');
+  pchar('['); pint((int)form); pchar(']');
   #endif
   if (form == NULL) pfstring(F("nil"));
   else if (listp(form) && issymbol(car(form), CLOSURE)) pfstring(F("<closure>"));
@@ -2250,6 +2352,17 @@
     pint(integer(form));
   } else if (form->type == SYMBOL) {
     pstring(name(form));
+  } else if (form->type == STRING) {
+    if (PrintReadably) pchar('"');
+    form = cdr(form);
+    while (form != NULL) {
+      int chars = form->integer;
+      char ch = chars>>8 & 0xFF;
+      if (ch) pchar(ch);
+      pchar(chars & 0xFF);
+      form = car(form);
+    }
+    if (PrintReadably) pchar('"');
   } else if (form->type == STREAM) {
     pfstring(F("<"));
     if ((form->integer)>>8 == SPISTREAM) pfstring(F("spi"));
@@ -2290,6 +2403,34 @@
   if (ch == '\'') return (object *)QUO;
   if (ch == '.') return (object *)DOT;

+  // Parse string
+  if (ch == '"') {
+    object *obj = myalloc();
+    obj->type = STRING;
+    ch = gchar();
+    object *head = NULL;
+    object *tail = NULL;
+    int chars = 0;
+    while (ch != '"') {
+      if (ch == '\\') ch = gchar();
+      if (chars == 0) {
+        chars = ch<<8;
+        object *cell = myalloc();
+        if (head == NULL) head = cell; else tail->car = cell;
+        cell->car = NULL;
+        cell->integer = chars;
+        tail = cell;
+      } else {
+        chars = chars | ch;
+        tail->integer = chars;
+        chars = 0;
+      }
+      ch = gchar();
+    }
+    obj->cdr = head;
+    return obj;
+  }
+
   // Parse variable or number
   int index = 0, base = 10, sign = 1;
   unsigned int result = 0;
@@ -2378,7 +2519,7 @@
   initworkspace();
   initenv();
   _end = 0xA5;      // Canary to check stack
-  pfstring(F("uLisp 1.4")); pln();
+  pfstring(F("uLisp 1.5")); pln();
 }

 // Read/Evaluate/Print loop


Delete IoT_temp_demo_v1.ino

Delete IoT_temp_demo_v1.ino

--- IoT_temp_demo_v1.ino
+++ IoT_temp_demo_v1.ino
@@ -1,443 +0,0 @@
-/*  IoT Demo
- *
- *  INTRO:
- *  I have created this IoT demonstration as a portfolio piece.  In this case
- *  streaming temperature data from a sensor to a webpage via a cloud service.
- *  I am able to run the device off a battery pack and connect it to my mobile
- *  phone hotspot.  By putting my finger on the temperature sensor I can
- *  show the temperature changing on the device screen and it upating on
- *  the web page. A nice touch is to get the people you are demo'ing it to to
- *  open the web page on their own phones/devices.  Typically the web page
- *  updates within 1-2 seconds dependent on the phone connection.
- *
- *  The point of the demo isn't to make an accurate temp sensor, it's to
- *  demonstrate connecting an IoT device securely (encrypted ) to a cloud
- *  service for subscribers to consume.
- *
- *  Importantly this demo is very low cost, as cheap as AU$25 for components
- *  and Google Firebase has a free pricing tier.  Also because of how Firebase
- *  works you do not need to actually host the web client (HTML page) on a
- *  server.  You could get away with just running the page straight off your pc.
- *  In fact if you don't connect the device to wifi it just runs as a
- *  temperature sensor.
- *
- *  I have put LOTS of comments here to help people understand what
- *  is going on and some of limitations of the hardware.  Unfortunately the
- *  ESP8266 on Arduino is an ongoing work in progress and I've already had to
- *  rewrite the demo once due to library updates breaking the code base.  I can
- *  only guarantee that this demo worked as of the date I uploaded it to GitHub.
- *
- *  DESCRIPTION:
- *  This is an IoT device using a BMP180 temp sensor on an ESP8266 12e
- *  (nodeMCU v1.0) micro controller.  The device connects to Google Firebase
- *  using the REST API to post sensor readings. Web clients can then access the
- *  temp data through the Firebase API.   For the demo I have a one page HMTL
- *  site using the Firebase Javascript API to receive dynamic callbacks as new
- *  data is posted.  The demo utilises the ESP8266's ability to connect via
- *  HTTPS which is required to talk to the Firebase cloud service.
- *
- *  The device uses the following components:
- *   - ESP8266 12e (nodeMCU 1.0)
- *   - ST7735 display (SPI)
- *   - BMP180 temperature sensor (I2C)
- *
- *  To run the full demo you will also need:
- *   - A Google Firebase account to create an application on and generate a
- *     secret key.  You must fill in the database name, and database secret in
- *     the demo.
- *   - WiFi for device to connect to (I have used both WiFi routers and mobile
- *     phone hotspots with no problems).  You must fill in the SSID and
- *     password of the wifi to connect to.
- *
- *  NOTE:
- *   - You can run the device just as a temperature sensor without connecting
- *     it to Wifi or Firebase :)
- *   - I'm using the BMP180 temp sensor uncalibrated and am getting temp
- *     readings which are way off, however it's fine for demos.  If you want
- *     accurate temp readings you'll have some work to do, probably including
- *     changing the sensor.
- *   - All communications with Firebase have to be secure meaning you have to
- *     use HTTPS (SSL/TLS).
- *   - The ESP8266 can only handle small payloads over HTTPS because of limited
- *     memory.  You may run into problems/stability issues trying to send
- *     larger data packets.  This is the reason the display shows message
- *     payload size (the demo sends around 40 bytes).
- *   - Since I am using the UART pins (D9 => Rx & D10 => Tx) for driving the
- *     screen you can't print any debug info to the Arduino IDE serial monitor.
- *     You could fix this by using other free pins (like D3/D4) instead.
- *     I did it this way simply to keep the wiring on my breadboard cleaner.
- *   - The Firebase onChange query only fires callback events when the data has
- *     changed.  So if sensor readings you just posted are exactly the same as
- *     the last post the client won't receive an update event.  If you want
- *     the client to receive an update everytime a post is made then add
- *     another field with a timestamp/unique value to the JSON object.
- *   - Depending on who made your ST7735 display you will probably have
- *     different pin names/layout than mine (a no-name display from China).
- *     You will have to work out this out for yourself when wiring it up.
- *     This wikipedia page lists some of the different names used for SPI
- *     pins which might help you:
- *     https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
- *
- *  ESP8266:
- *  I have the demo running on Arduino 1.6.8 and it uses this esp8266 arduino
- *  library: https://github.com/esp8266/Arduino
- *
- *  which you link in by adding this board manager link in Arduino IDE
- *  preferences (check the GitHub page above for the latest version):
- *  http://arduino.esp8266.com/stable/package_esp8266com_index.json
- *
- *  DISPLAY:
- *  Your ST7735 display will probably differ to mine (no-name & off eBay) so
- *  you will have to find out which pin does what in order to wire it up.
- *  Also you may have to change the parameter when initialising it depending
- *  on whether its a green, red, or black tab display.  Originally I couldn't
- *  get it running using software SPI in the Adafruit_ST7735 library so I had
- *  to use the hardware SPI call.  This means that the following pins are
- *  set: d5 for SCLK, d7 for MOSI, d6 for MISO, and d8 for CS.  You can set the
- *  other pins to any free pin available if you want.  The following table
- *  shows the pins on my ST7735 display (yours may differ), their SPI role, and
- *  the ESP8266 pin they connect to:
- *
- *  ST7735    SPI       esp8266 (h/w SPI)
- *  -------+--------+---------------------
- *  cs     |  CS    |   d8  => GPIO 15 (CS)
- *  sck    |  SCLK  |   d5  => GPIO 14 (SCLK)
- *  sda    |  MOSI  |   d7  => GPIO 13 (MOSI)
- *  a0     |  DC    |   d9  => GPIO 3       <= can change this to any free pin
- *  reset  |  RST   |   d10 => GPIO 1       <= can change this to any free pin
- *  -      |  MISO  |   d6  => GPIO 12 (MISO)
- *
- *  NOTE!! Even though we don't use MISO (d6) you cannot use this pin for
- *  anything else, you must keep it free.  Due to the way the Arduino library
- *  works it is possible to map CS to any free pin.  However since d8 is
- *  already set to CS you can't use it for anything else either so you would
- *  effectively end up wasting a pin.
- *
- *  SENSOR:
- *  The BMP180 temperature sensor uses I2C and I have used the following pins
- *  but they can be changed to any free pins available.
- *
- *  BMP180   ESP8266
- *  -------+-------------
- *  SDA    | d1 => GPIO 5      <= can change this to any free pin
- *  SCL    | d2 => GPIO 4      <= can change this to any free pin
- *
- *  FIREBASE-ARDUINO:
- *  The demo uses the Firebase-Arduino library off GitHub which handles the
- *  connection and comms with Firebase.  This demo is only possible because
- *  of this library so make sure to thank the authors for their great work!
- *
- *  https://github.com/googlesamples/firebase-arduino
- *
- *
- *  FIREBASE:
- *  I'm not even going to try to give you instructions on setting up Firebase
- *  just follow the online references and tutorials.  Make sure you are using
- *  the latest version which is Firebase v3 (https://firebase.google.com/) and
- *  make sure any tutorials or reference doco you are reading aren't for v2.
- *  The basic steps are:
- *
- *  1) Register as a Google developer
- *  2) Sign up for Firebase (v3) and select the free tier (no charge)
- *  3) Create an application (doesn't matter what you call it)
- *  4) Generate a secret for the application
- *  5) Paste the app name (<yourAppName>.firebaseio.com) and secret into the
- *     code below.
- *
- *  You do not need to create any database rules (although that is always
- *  recommended for security).  You do not need to create anything in the
- *  database (fields, etc) due to the way Firebase works.  If the fields don't
- *  already exist they will be created when the data is posted, if they do they
- *  will be overwritten.  Once you get the demo going you can watch the data
- *  being updated in real time throught the Firebase console.
- *
- *  The data structure in Firebase roughly looks like this. Remember if you
- *  change this structure or the field names you're going to have to reflect
- *  those changes in the HTML page as well or it won't find the data. Since
- *  it's stored as JSON adding extra fields doesn't break anything and the
- *  HTML page will just ignore them until you update the code.
- *
- *  /(root)
- *      /BMP180
- *         /temp: "99.9"
- *         /alt: "99"
- *         /hpa: "99"
- *
- *
- *  CHANGE LOG:
- *  28Oct16 [sxh] - fixed code base, nolonger uses older ST7735 lib,
- *     implemented new version of Firebase Arduino (v3 compliant?).
- *     Can now start without wifi and handles wifi drop outs/ins.
- */
-#include <Wire.h>            // I2C interface
-#include <SPI.h>             // SPI interface
-#include <ESP8266WiFi.h>     // Arduino wifi library for ESP8266
-#include <SFE_BMP180.h>      // BMP180 temp sensor
-#include <FirebaseArduino.h> // ESP8266 lib to make Firebase API calls over SSL
-#include <Adafruit_GFX.h>    // Graphics library
-#include <Adafruit_ST7735.h> // ST7735 display
-
-#include <Fonts/FreeSans9pt7b.h>
-#include <Fonts/FreeSans12pt7b.h>
-#include <Fonts/FreeSans18pt7b.h>
-
-SFE_BMP180 pressure;
-#define ALTITUDE   30.0 // current Altitude in meters
-#define READ_DELAY 1000 // delay (mS) before taking and posting next sensor reading
-
-/*** ST7735 setup ***/
-#define eCS    15    // d8  => GPIO 15 (CS/SS)
-#define eDC     3    // d9  => GPIO 3
-#define eMOSI  13    // d7  => GPIO 13 (MOSI)
-#define eSCLK  14    // d5  => GPIO 14 (SCLK)
-#define eRST    1    // d10 => GPIO 1
-Adafruit_ST7735 tft = Adafruit_ST7735(eCS, eDC, eRST);   // uses hardware SPI
-
-/*** User defined params for WiFI and FireBase App ***/
-#define WIFI_SSID       "??????"  // WiFi SSID (name)
-#define WIFI_PW         "??????"  // Wifi password
-#define FIREBASE_APP    "??????"  // Firebase app address, example "<yourAppName>.firebaseio.com"
-#define FIREBASE_SECRET "??????"  // Secret your generated for your FireBase app, example "ABcd1eF23gHIjKlMNOpqR456St7UVWXyZAB89cDE"
-
-char MAC_char[18];
-
-void setup()
-{
-  Wire.begin(5,4); // I2C for temp sensor
-
-  // Initialise ST7735 display
-  tft.initR(INITR_BLACKTAB);   // initialize ST7735S chip, black tab
-  tft.setRotation(0);  // set screen orientation
-  tft.fillScreen(ST7735_BLACK);
-  tft.setTextColor(ST7735_YELLOW);
-  tft.setCursor(0, 0);
-  tft.setTextSize(2);
-  tft.println("IoT Demo");
-  tft.setTextSize(1);
-  tft.println("v1.0");
-  tft.setTextColor(ST7735_WHITE);
-  tft.println();
-  tft.println("ST7735 Init..OK");
-  tft.print("BMP180 init..");
-
-  // Initialize the sensor
-  if (pressure.begin())
-    tft.println("OK");
-  else
-  {
-    tft.setTextColor(ST7735_RED);
-    tft.println("FAILED");
-    while(1); // Pause forever.
-  }
-
-  // connect to wifi.
-  tft.print("SSID: ");
-  tft.println(WIFI_SSID);
-  tft.print("Connecting");
-  WiFi.begin(WIFI_SSID, WIFI_PW);
-  int x = 0;
-  while (WiFi.status() != WL_CONNECTED)
-  {
-    tft.print(".");
-    delay(500);
-    if(x++>20)  // timeout
-       break;
-  }
-
-  if(WiFi.status() == WL_CONNECTED)
-  {
-    tft.println("OK");
-    tft.println(WiFi.localIP());
-
-    uint8_t MAC_array[6];
-    WiFi.macAddress(MAC_array);
-    for (int i = 0; i < sizeof(MAC_array); ++i){
-      sprintf(MAC_char,"%s%02x:",MAC_char,MAC_array[i]);
-    }
-    tft.println("MAC ");
-    tft.println(MAC_char);
-  }
-  else
-    tft.println("TIMEOUT");
-
-  Firebase.begin(FIREBASE_APP, FIREBASE_SECRET);   // Initialise Firebase object
-  delay(3000);
-
-  // set up main screen
-  tft.fillScreen(ST7735_BLACK);
-  tft.setCursor(40, 0);
-  tft.setTextColor(ST7735_WHITE);
-  tft.print("IoT DEMO");
-  tft.setTextColor(ST7735_YELLOW);
-  drawTemp(0);
-  drawPressure(0.0);
-  drawAltitude(0.0);
-
-  // ssid details (bottom screen)
-  tft.setTextColor(ST7735_WHITE);
-  tft.drawLine(0, tft.height()-12, tft.width()-1, tft.height()-12, ST7735_WHITE);   // drawLine(x,y,x1,y1,colour)
-  tft.setCursor(5,tft.height()-8);
-  tft.setTextSize(1);
-  tft.print("SSID: ");
-  drawSSID();
-  tft.setTextColor(ST7735_YELLOW);
-}
-
-void loop()
-{
-  char status;
-  double T,P,p0,a;
-
-  status = pressure.startTemperature();
-  if (status != 0)
-  {
-    // Wait for the measurement to complete:
-    delay(status);
-    status = pressure.getTemperature(T);
-    if (status != 0)
-    {
-      drawTemp(T);  //display temp on screen
-
-      // Start a pressure measurement:
-      status = pressure.startPressure(3);
-      if (status != 0)
-      {
-        delay(status);  // wait for measurement to complete
-        status = pressure.getPressure(P,T);
-        if (status != 0)
-        {
-          drawPressure(P); // display pressure on screen
-          p0 = pressure.sealevel(P,ALTITUDE);
-          a = pressure.altitude(P,p0);
-          drawAltitude(a); // display altitude on screen
-          clearStatus();
-          drawSSID();
-          if (WiFi.status() ==  WL_CONNECTED) // push readings to Firebase
-          {
-            StaticJsonBuffer<200> jsonBuffer;
-            JsonObject& data = jsonBuffer.createObject();
-            data["temp"] = String(T,1);
-            data["alt"]  = String(a,0);
-            data["hpa"]  = String(P,0);
-
-            Firebase.set("/BMP180", JsonVariant(data));
-            drawPayload(data.measureLength(), Firebase.failed());
-          }
-        }
-      }
-    }
-  }
-
-  delay(READ_DELAY);  // Delay before starting next reading
-}
-
-/**
- * Display the temperature reading on screen
- */
-void drawTemp(double dTemp)
-{
-  int y_pos = 16;
-
-  tft.setTextSize(1);
-  tft.setCursor(8,y_pos);
-  tft.print("Temp:");
-  tft.fillRoundRect( 5, y_pos+10, 118, 34, 3, ST7735_RED); //fillRoundRect(x, y, x length, y length, radius, colour)
-  tft.setCursor(10,y_pos+32);
-  tft.setTextSize(1);
-  tft.setFont(&FreeSans18pt7b);
-  tft.print(dTemp,1);
-  tft.setFont();   //reset to classic font
-  tft.setFont(&FreeSans9pt7b);
-  tft.setTextSize(1);
-  tft.setCursor(78,y_pos+26);
-  tft.print(" o");
-  tft.setFont(&FreeSans12pt7b);
-  tft.setTextSize(1);
-  tft.setCursor(93,y_pos+33);
-  tft.print("C");
-  tft.setFont();   //reset to classic font
-}
-
-/**
- * Display the pressure reading on screen
- */
-void drawPressure(double dPressure)
-{
-  int y_pos = 68;
-
-  tft.setTextSize(1);
-  tft.setCursor(8,y_pos);
-  tft.print("Pressure:");
-  tft.fillRoundRect( 5, y_pos+10, 118, 20, 3, ST7735_RED); //fillRoundRect(x, y, x length, y length, radius, colour)
-  tft.setCursor(10,y_pos+20);
-  tft.setTextSize(1);
-  tft.setFont(&FreeSans9pt7b);
-  tft.print(dPressure,0);
-  tft.print(" hPa");
-  tft.setFont();
-}
-
-/**
- *  Display the altitude reading on screen
- */
-void drawAltitude(double dAltitude)
-{
-  int y_pos = 106;
-
-  tft.setTextSize(1);
-  tft.setCursor(8,y_pos);
-  tft.print("Altitude:");
-  tft.fillRoundRect( 5, y_pos+10, 118, 20, 3, ST7735_RED);
-  tft.setCursor(10,y_pos+19);
-  tft.setTextSize(1);
-  tft.setFont(&FreeSans9pt7b);
-  tft.print(dAltitude,0);
-  tft.print("m");
-  tft.setFont();
-}
-
-/**
- *  Display the Wifi SSID (name) on screen.  Make it green if
- *  we have a connection, red if no connection
- */
-void drawSSID()
-{
-  if(WiFi.status() == WL_CONNECTED)
-    tft.setTextColor(ST7735_GREEN);
-  else
-    tft.setTextColor(ST7735_RED);
-
-  tft.setCursor(36, 152);
-  tft.print(WIFI_SSID);
-  tft.setTextColor(ST7735_YELLOW);
-}
-
-/**
- * Display message payload (size of data we are sending)
- * in bytes.  Give it a green background if post to
- * Firebase was successful, red if post failed.
- */
-void drawPayload(int nPayload, bool bFail)
-{
-  tft.setTextColor(ST7735_BLACK);
-  if(bFail)
-  {
-    tft.fillRect(100, 150 , 27, 9, ST7735_RED);
-  }
-  else
-  {
-    tft.fillRect(100, 150 , 27, 9, ST7735_GREEN);
-  }
-  tft.setCursor(105, 151);
-  tft.print(nPayload);
-  tft.setTextColor(ST7735_YELLOW);
-}
-
-/**
- * Clear status info at the bottom of the display
- * (SSID and payload info)
- */
-void clearStatus()
-{
-  tft.fillRect(35, 150 , 93, 9, ST7735_BLACK); // fillRect(x, y, x length, y length, colour)
-}


debugged averaging algorithm

debugged averaging algorithm

--- BitReceiver_withCMDCode_MotorDriving/BitReceiver_withCMDCode_MotorDriving.ino
+++ BitReceiver_withCMDCode_MotorDriving/BitReceiver_withCMDCode_MotorDriving.ino
@@ -17,15 +17,16 @@
 String theMessage = "";
 char theChar = 0;

-int xBuffer[4];
-int yBuffer[4];
+int xBuffer[5];
+int yBuffer[5];
 int bufferVal = 0;
 int xDir;
 int yDir;
+int buttonVal;

 void setup(void)
 {
-  Serial.begin(115200);
+  //Serial.begin(115200);
   radio.begin();
   radio.openReadingPipe(1,pipe);
   radio.startListening();
@@ -50,8 +51,9 @@
       radio.read(msg, 1);
       theChar = msg[0];
     }
-  if(bufferVal <= 4)
-  {
+
+   if (bufferVal <= 4)
+   {
     int delimiter = theMessage.indexOf(',');

@@ -60,30 +62,39 @@
     char charBuf[length];

     theMessage.substring(0,delimiter).toCharArray(charBuf,length);
-    int buttonVal = atof(charBuf);
+    buttonVal = atof(charBuf);

     theMessage.substring(delimiter+1, delimiter2).toCharArray(charBuf,length);
-    xBuffer[bufferVal] = atof(charBuf);
+    xBuffer[bufferVal] = (int)atof(charBuf);
+    //Serial.print(xBuffer[bufferVal]); Serial.print('\t');
+

     theMessage.substring(delimiter2+1, theMessage.length()).toCharArray(charBuf,length);
-    yBuffer[bufferVal] = atof(charBuf);
-    bufferVal = bufferVal + 1;
-  }
+    yBuffer[bufferVal] = (int)atof(charBuf);
+    if (xBuffer[bufferVal] <= 1023 && xBuffer[bufferVal] >= 0 && yBuffer[bufferVal] <= 1023 && yBuffer[bufferVal] >= 0)
+    {
+      bufferVal = bufferVal + 1;
+    }
+   }
   else
   {
     bufferVal = 0;
     xDir = (xBuffer[0] + xBuffer[1] + xBuffer[2] + xBuffer[3] + xBuffer[4])/5;
+    //Serial.print(xDir); Serial.print('\t');
     yDir = (yBuffer[0] + yBuffer[1] + yBuffer[2] + yBuffer[3] + yBuffer[4])/5;
-  }
     if (xDir <= 1023 && yDir <= 1023)
     {
       xDir = map(xDir, 0, 1023, -255, 255);
+      //Serial.println(xDir);
       yDir = map(yDir, 0, 1023, -255, 255);
     }
+  }

+

-    if(xDir > 10)
+
+    if(xDir > 50)
     {
       analogWrite(l1_motor, xDir);
       analogWrite(l2_motor, 0);
@@ -91,7 +102,7 @@
       analogWrite(r1_motor, xDir);
       analogWrite(r2_motor, 0);
     }
-    else if(xDir < -10)
+    else if(xDir < -50)
     {
       analogWrite(l2_motor, abs(xDir));
       analogWrite(l1_motor, abs(0));
@@ -109,15 +120,15 @@
       analogWrite(r2_motor, abs(0));
     }

-    //Serial.println(theMessage);
-    Serial.print(buttonVal); Serial.print('\t');
-    Serial.print(xDir); Serial.print('\t');
-    Serial.println(yDir);
+//    //Serial.println(theMessage);
+//    Serial.print(buttonVal); Serial.print('\t');
+//    Serial.print(xDir); Serial.print('\t');
+//    Serial.println(yDir);

     theMessage = "";

   }
-  delay(10);
+  //delay(1);
 }


important tweaks

important tweaks

--- examples/RF12/otRelay/otRelay.ino
+++ examples/RF12/otRelay/otRelay.ino
@@ -30,7 +30,7 @@

     byte payload [3];
     payload[0] = id;
-    payload[1] = history[id].value;
+    payload[1] = history[id].value;       // litle-endian
     payload[2] = history[id].value >> 8;

     while (!rf12_canSend())
@@ -41,11 +41,11 @@

 static void sendIfChanged () {
   byte id = hex2bin(lastChars+3);
-  word newval = hex2bin(lastChars+5) + (hex2bin(lastChars+7) << 8);
+  word newval = (hex2bin(lastChars+5) << 8) + hex2bin(lastChars+7);

+  history[id].resends = RESEND_COUNT;
   if (newval != history[id].value) {
     history[id].value = newval;
-    history[id].resends = RESEND_COUNT;
     sendId(id);
   }
 }


Examples: WDRC_8BandFIR_full switched to use myTympan.serviceLEDs

--- examples/05-FullSystems/WDRC_8BandFIR_full/WDRC_8BandFIR_full.ino
+++ examples/05-FullSystems/WDRC_8BandFIR_full/WDRC_8BandFIR_full.ino
@@ -168,8 +168,8 @@
   //service the SD recording
   serviceSD();

-  //service the LEDs
-  serviceLEDs(millis());
+  //service the LEDs...blink slow normally, blink fast if recording
+  myTympan.serviceLEDs(millis(),audioSDWriter.getState() == AudioSDWriter::STATE::RECORDING);

   //service the potentiometer...if enough time has passed
   if (USE_VOLUME_KNOB) servicePotentiometer(millis());
@@ -187,43 +187,6 @@

 // ///////////////// Servicing routines
-
-void serviceLEDs(unsigned long curTime_millis) {
-  static unsigned long lastUpdate_millis = 0;
-  if (lastUpdate_millis > curTime_millis) { lastUpdate_millis = 0; } //account for possible wrap-around
-  unsigned long dT_millis = curTime_millis - lastUpdate_millis;
-
-  if (audioSDWriter.getState() == AudioSDWriter::STATE::UNPREPARED) {
-    if (dT_millis > 1000) {  //slow toggle
-      toggleLEDs(true,true); //blink both
-      lastUpdate_millis = curTime_millis;
-    }
-  } else if (audioSDWriter.getState() == AudioSDWriter::STATE::RECORDING) {
-    if (dT_millis > 50) {  //fast toggle
-      toggleLEDs(true,true); //blink both
-      lastUpdate_millis = curTime_millis;
-    }
-  } else {
-    if (dT_millis > 1000) {  //slow toggle
-      toggleLEDs(true,true); //blink both
-      lastUpdate_millis = curTime_millis;
-    }
-  }
-}
-
-void toggleLEDs(const bool &useAmber, const bool &useRed) {
-  static bool LED = false;
-  LED = !LED;
-  if (LED) {
-    if (useAmber) myTympan.setAmberLED(true);
-    if (useRed) myTympan.setRedLED(false);
-  } else {
-    if (useAmber) myTympan.setAmberLED(false);
-    if (useRed) myTympan.setRedLED(true);
-  }
-  if (!useAmber) myTympan.setAmberLED(false);
-  if (!useRed) myTympan.setRedLED(false);
-}

 #define PRINT_OVERRUN_WARNING 1   //set to 1 to print a warning that the there's been a hiccup in the writing to the SD.


main: display dht22 readings.

main: display dht22 readings.

--- src/main.ino
+++ src/main.ino
@@ -2,6 +2,8 @@
 #include "Sds011.h"
 #include "Pcd8544.h"
 #include "Expander.h"
+#include "Dht.h"
+#include "DHT.h"

 #ifdef ESP8266
 #include <Wire.h>
@@ -32,6 +34,8 @@
 pcd8544::Pcd8544 display(A3, A2, A1, A0, 13);
 #endif

+dht::Dht dht22(14);
+
 static bool set_press;

 String val_to_str(uint16_t v)
@@ -50,7 +54,7 @@
     return r;
 }

-void display_data(uint16_t pm25, uint16_t pm10)
+void display_data(uint16_t pm25, uint16_t pm10, uint16_t t, uint16_t h)
 {
     display.clear();
     display.setCursor(0, 0);
@@ -67,6 +71,15 @@
     display.print(val_to_str((10*pm25/PM25_NORM)*10).c_str());
     display.setCursor(8*7, 2);
     display.print(val_to_str((10*pm10/PM10_NORM)*10).c_str());
+
+    display.setCursor(0, 4);
+    display.print("t:  ");
+    display.print(val_to_str(t).c_str());
+    display.print("C");
+    display.setCursor(0, 5);
+    display.print("h:  ");
+    display.print(val_to_str(h).c_str());
+    display.print("%");
 }

 void setup()
@@ -81,6 +94,7 @@
     Serial.begin(9600);

     display.begin();
+    dht22.begin();

 #ifdef ESP8266

@@ -171,8 +185,11 @@
     ok = sensor.query_data_auto(&pm25, &pm10, SAMPLES);
     sensor.set_sleep(true);

+    uint16_t t = dht22.get_temperature();
+    uint16_t h = dht22.get_humidity();
+
     if (ok) {
-        display_data(pm25, pm10);
+        display_data(pm25, pm10, t, h);
     } else {
         display.clear();
         display.setCursor(0, 0);


Updated radioData on Mega to uint8

Updated radioData on Mega to uint8

--- Sketch1/mega2560.ino
+++ Sketch1/mega2560.ino
@@ -54,8 +54,8 @@
 float motor[2] = { 100,0 }; // new,old
 int dmotor = 0;
 struct radioData {
-	unsigned int servo[3];
-	unsigned int motor;
+	uint8_t servo[3];
+	uint8_t motor;
 }radioData;

 // Declare DualShock 4 Data


Bump volume up to 0.8; add back profiling for now

--- roto.ino
+++ roto.ino
@@ -40,15 +40,19 @@
     antialias.setLowpass(0, 6000, 0.707);

     audioShield.enable();
-    audioShield.volume(0.6);
+    audioShield.volume(0.8);

     usbMIDI.begin();
     usbMIDI.setHandleNoteOn(handleNoteOn);
     usbMIDI.setHandleNoteOff(handleNoteOff);
 }

+int count = 0;
 void loop() {
     usbMIDI.read();
+    if ((count++ % 500000) == 0) {
+        usage();
+    }
 }

 int note2key(byte note) {


Prevent possible endless while loop

Prevent possible endless while loop

--- VendingMachineRFID.ino
+++ VendingMachineRFID.ino
@@ -81,7 +81,9 @@
     while(Serial.available()){Serial.read();delay(5);}
     // Request and read data from other party
     Serial.write(command);
-    while(Serial.read() != 'C'){}; // Wait till other side transmits a C (is this the best solution?)
+    while(!Serial.available()); // Wait till other side transmits a C
+    if(Serial.read() != 'C')
+      return;
     number = rfid_raw_read();
     if(recieve_error == 0){ // Recieved correctly, return value
       return number;