tinkering with delays to try and improve latency

--- ardesp/waterelf/waterelf.ino
+++ ardesp/waterelf/waterelf.ino
@@ -96,20 +96,13 @@
 void loop() {
   dnsServer.processNextRequest();
   server.handleClient();
-  dnsServer.processNextRequest();
-  server.handleClient();
-  dnsServer.processNextRequest();
-  server.handleClient();
-  dnsServer.processNextRequest();
-  server.handleClient();
-  dnsServer.processNextRequest();
-  server.handleClient();
+  delay(5000);

   int m = monitorCursor;
   updateSensorData(monitorData);
   Serial.print("monitorData[monitorCursor].celsius:" );
   Serial.println(monitorData[m].celsius);
-  delay(10000);
+  delay(5000);
 }

 /////////////////////////////////////////////////////////////////////////////
@@ -136,7 +129,7 @@
   String toSend = pageTop;
   toSend += ": Sensor Data";
   toSend += pageTop2;
-  int m = monitorCursor;
+  int m = monitorCursor - 1;
   const int DATA_ENTRIES = 30;
   int n = m - DATA_ENTRIES;
   toSend += "<pre>\n";


reinstated fill-based cycling; upped cycle times; now doing 30 mins with 18 min max fill time

--- ardesp/waterelf/waterelf.ino
+++ ardesp/waterelf/waterelf.ino
@@ -210,10 +210,10 @@
   // in beds with overflows can be 0; else will be cycle time minus fill time
   long startTime = -1;          // when to start cycling (after boot)
   bool gotOverflow = false;     // does the growbed have an overflow?
-  int fillLevel = 10;           // cms below the level sensor: drain point
+  int fillLevel = 7;            // cms below the level sensor: drain point
   bool filling = false;         // true when closed / on
   long lastFlip = -1;           // millis at last state change
-  int floodMins = 6; // TODO 10;
+  int floodMins = 18;

   Valve() { number = counter++; }
   void stateChange(bool newState) { // turn on or off
@@ -246,7 +246,11 @@
     int t = millis();
     dbg(valveDBG, "t = "); dbg(valveDBG, t);
     dbg(valveDBG, "; filling = "); dln(valveDBG, filling);
-    if(filling && ( lastFlip + (floodMins * 60 * 1000) ) <= t) { // flood over
+    if(filling &&
+        (
+          ( lastFlip + (floodMins * 60 * 1000) ) <= t  || full(now)
+        )
+      ) { // flood over
       dbg(valveDBG, "t = "); dln(valveDBG, t);
       dbg(valveDBG, "lastFlip = "); dln(valveDBG, lastFlip);
       dbg(valveDBG, "floodMins = "); dln(valveDBG, floodMins);
@@ -257,41 +261,18 @@
       on();
       startTime += (cycleMins * 60 * 1000);
       dbg(valveDBG, "startTime = "); dln(valveDBG, startTime);
-    }
-    /* old version using level sensors:
-    else if(filling && full(now)) {           // we're full
-      off();
     }
-    */
-  }
-int averageLevel1 = 22; // TODO
-int averageLevel2 = 22;
-int averageLevel3 = 22;
+  }
   bool full(monitor_t *now) {
     int l = -1;
-    int al = -1; // TODO
     switch(number) {
       case 1: l = now->waterLevel1; break;
       case 2: l = now->waterLevel2; break;
       case 3: l = now->waterLevel3; break;
     }
-    dbg(valveDBG, "now->waterLevel = "); dln(valveDBG, l);
-    dbg(valveDBG, "waterLevel1 = "); dbg(valveDBG, now->waterLevel1);
-    dbg(valveDBG, "; waterLevel2 = "); dbg(valveDBG, now->waterLevel2);
-    dbg(valveDBG, "; waterLevel3 = "); dln(valveDBG, now->waterLevel3);
-
-if(l < 9) return false; // TODO
-switch(number) {
-  case 1: al = (averageLevel1 + l) / 2; averageLevel1 = al;
-  break;
-  case 2: al = (averageLevel2 + l) / 2; averageLevel2 = al;
-  break;
-  case 3: al = (averageLevel3 + l) / 2; averageLevel3 = al;
-  break;
-}
-dbg(valveDBG, "average level = "); dln(valveDBG, al);
-
-    return ( al <= fillLevel );
+    dbg(valveDBG, "full? l = "); dln(valveDBG, l);
+
+    return ( l <= fillLevel );
   }
 };
 int Valve::counter = 1;         // definition (the above only declares)
@@ -299,7 +280,7 @@
 class FlowController { // the set of valves and their config ////////////////
   public:
   int numValves = 3;         // WARNING! call init if resetting!
-  int cycleMins = 18; // TODO// how long is a flood/drain cycle?
+  int cycleMins = 30;        // how long is a flood/drain cycle?
   int maxSimultDrainers = 1; // how many beds can drain simultaneously?
   int minBedsWet = 1;        // min beds that are full or filling
   int maxBedsWet = 2;        // max beds that are full or filling
@@ -942,6 +923,7 @@
   duration = pulseIn(echoPin, HIGH, TIMEOUT);   // wait for response

   (*waterLevel) = (duration/2) / 29.1;
+  delay(35);                                    // anti-interference measure

   dbg(monitorDBG, "Water Level: ");
   dbg(monitorDBG, *waterLevel);


addition of a condition to avoid issues with TX

--- examples/Simple/Simple.ino
+++ examples/Simple/Simple.ino
@@ -18,7 +18,9 @@
 #include "Maxbotix.h"

 Maxbotix rangeSensorPW(8, Maxbotix::PW, Maxbotix::LV);
-Maxbotix rangeSensorTX(6, Maxbotix::TX, Maxbotix::LV);
+#ifdef MAXBOTIX_WITH_SOFTWARE_SERIAL
+  Maxbotix rangeSensorTX(6, Maxbotix::TX, Maxbotix::LV);
+#endif
 Maxbotix rangeSensorAD(A0, Maxbotix::AN, Maxbotix::LV);

 void setup()
@@ -39,7 +41,7 @@
   Serial.print("cm - ");
   Serial.print(millis() - start);
   Serial.println("ms");
-
+#ifdef MAXBOTIX_WITH_SOFTWARE_SERIAL
   // TX
   start = millis();
   Serial.print("TX: ");
@@ -47,7 +49,7 @@
   Serial.print("cm - ");
   Serial.print(millis() - start);
   Serial.println("ms");
-
+#endif
   // AD
   start = millis();
   Serial.print("AD: ");


Add sendData func and diagonalLines test pattern

--- arduino/fillbrick.ino
+++ arduino/fillbrick.ino
@@ -1,27 +1,45 @@
 //Pin connected to ST_CP of 74HC595
-const int latchPin = 12;
+const int LATCHPIN = 12;
 //Pin connected to SH_CP of 74HC595
-const int clockPin = 11;
-////Pin connected to DS of 74HC595
-const int dataPin = 13;
+const int CLOCKPIN = 11;
+// Pin connected to DS of 74HC595
+const int DATAPIN = 13;
+// Number of pins
+const int BOARDHEIGHT = 5;
+// Delay
+const int DELAY = 200;
+
+void sendData(byte data) {
+  // 001010
+  for (int i = 0; i < boardHeight; i++) {
+    digitalWrite(LATCHPIN, LOW);
+    // shift out the bits:
+    digitalWrite(DATAPIN, data[i]);
+    //take the latch pin high so the LEDs will light up:
+    digitalWrite(LATCHPIN, HIGH);
+    Serial.print(bitRead(data, i));
+  }
+  //digitalWrite(0);
+  Serial.print(0);
+  Serial.println();
+}
+
+void diagonalLines() {
+  // count from 1 (0x00001) to 32 (0x10000)
+  // note: the furthest right pin is disconnected; drop the right most digit in binary
+  for (byte a = 1; a< 32;a*=2) {
+    sendData(a);
+    delay(DELAY);
+  }
+}

 void setup() {
-  pinMode(latchPin, OUTPUT);
-  pinMode(clockPin, OUTPUT);
-  pinMode(dataPin, OUTPUT);
+  pinMode(LATCHPIN, OUTPUT);
+  pinMode(CLOCKPIN, OUTPUT);
+  pinMode(DATAPIN, OUTPUT);
+  Serial.begin(9600);
 }

 void loop() {
-  // count from 2 (0x00001) to 32 (0x10000)
-  // note: the furthest right pin is disconnected; drop the right most digit in binary
-  for (int a = 2 ; a< 32;a*=2) {
-    digitalWrite(latchPin, LOW);
-    // shift out the bits:
-    shiftOut(dataPin, clockPin, MSBFIRST, data[a]);
-    //take the latch pin high so the LEDs will light up:
-    digitalWrite(latchPin, HIGH);
-    // pause before next value:
-    delay(500);
-  }
+  diagonalLines()
 }
-


Fixed typo in bdbridge.ino

Fixed typo in bdbridge.ino

--- bdbridge/bdbridge.ino
+++ bdbridge/bdbridge.ino
@@ -13,7 +13,7 @@
 #define GEND0 4
 #define GEND1 5
 #define GEND2 6
-#defibe GEND3 7
+#define GEND3 7
 #define GENTL 8
 #define GENTR 9
 #define GENTH 3


Delete ArincShieldAutoTest.ino

Delete ArincShieldAutoTest.ino

--- ArincShieldAutoTest.ino
+++ ArincShieldAutoTest.ino
@@ -1,223 +0,0 @@
-//
-// Arinc Shield Test.ino
-//   V1.01 (15/03/2017) : ACLK divider is a parameter, to cope with both units:
-//   - 12MHz (prototypes) or
-//   - 16MHz (serial production)
-//
-
-#include <SPI.h>
-
-// pin numbers
-#define SS     10  // SPI Slave Select
-#define OE      9  // Output Enable of voltage translator (TXB0104)
-#define MR      8  // HI-3593 Master Reset
-#define TxEmpty 7  // HI-3593 Transmitter Empty
-#define DIn0    5  // Discrete input #0 (0V / open)
-#define DIn1    6  // Discrete input #1 (0V / open)
-#define DOut    4  // Discrete output (0V / Open)
-#define AIn0    A5 // Analog input #0 (0V .. 5V)
-#define AIn1    A4 // Analog input #1 (0V .. 5V)
-#define AIn2    A3 // Analog input #2 (0V .. 5V)
-#define AIn3    A2 // Analog input #3 (0V .. 5V)
-#define R1Int   3  // HI-3593 Receiver #1 interrupt
-#define R2Int   2  // HI-3593 Receiver #2 interrupt
-#define RTOut   1  // RS422 Tx Out
-#define RRIn    0  // RS422 Rx In
-
-// clock divider (page 9, table 2)
-   // for prototypes (Arduino USB 12MHz oscillator is used)
-//#define ClkDiv 0x0C
-   // for serial production (dedicated 16MHz oscillator on the shield)
-#define ClkDiv 0x10
-
-SPISettings HI3593SpiSettings(
-  // for arduino, SPI clock will be @16MHz/2 = 8MHz (the nearest from 10MHz)
-  10000000, // page 1, features: "10MHz SPI"
-  MSBFIRST, // page 14, fig 5
-  SPI_MODE0 // page 14, fig 5
-);
-
-// interrupt service routine for digital input #3 (RINT1)
-bool RINT1Trigd;
-void isr1() {
-  RINT1Trigd = true;
-}
-
-// interrupt service routine for digital input #2 (RINT2)
-bool RINT2Trigd;
-void isr2() {
-  RINT2Trigd = true;
-}
-
-void setup() {
-  // open serial port for debug
-  Serial.begin(9600);
-  Serial.println(F("\t>> Arinc 429 shield test program V1.01 <<\n"));
-
-  // in/out pins configuration
-  pinMode(SS,     OUTPUT);
-  pinMode(OE,     OUTPUT);
-  pinMode(MR,     OUTPUT);
-  pinMode(TxEmpty, INPUT);
-  pinMode(DIn1,    INPUT);
-  pinMode(DIn0,    INPUT);
-  pinMode(DOut,   OUTPUT);
-  pinMode(R1Int,   INPUT);
-  pinMode(R2Int,   INPUT);
-  pinMode(RTOut,  OUTPUT);
-  pinMode(RRIn,    INPUT);
-
-  // default states on outputs
-  digitalWrite(SS,    HIGH);
-  digitalWrite(OE,    HIGH);
-  digitalWrite(RTOut, HIGH);
-
-  // reset HI-3593
-  digitalWrite(MR, HIGH); delay(1); digitalWrite(MR,  LOW);
-
-  // initialize SPI
-  SPI.begin();
-  SPI.beginTransaction(HI3593SpiSettings);
-
-  // -------------------------------------------------------------------------
-  // Test MR (master reset) signal to HI-3593
-  // -------------------------------------------------------------------------
-  // write a register (the ACLK division register)
-  digitalWrite(SS, LOW); SPI.transfer(0x38); SPI.transfer(ClkDiv); digitalWrite(SS, HIGH);
-  // read back the register
-  digitalWrite(SS, LOW); SPI.transfer(0xd4); unsigned char readback = SPI.transfer(0); digitalWrite(SS, HIGH);
-  bool shieldPres = readback==ClkDiv;
-  // reset HI-3593
-  digitalWrite(MR, HIGH); delay(1); digitalWrite(MR,  LOW);
-  // read back again the register (default value of ACLK division register after reset is 0x00)
-  digitalWrite(SS, LOW); SPI.transfer(0xd4); readback = SPI.transfer(0); digitalWrite(SS, HIGH);
-  if (readback != ClkDiv && shieldPres) Serial.println(F("Test of Master Reset is:\t\tPASSED"));
-  else Serial.println(F("Master Reset didn't have the expected effect :("));
-  Serial.println();
-
-  // -------------------------------------------------------------------------
-  // Proper initialization after master reset
-  // -------------------------------------------------------------------------
-  // set the HI-3593 ACLK division register to accomodate the right clock frequency
-  digitalWrite(SS, LOW);
-  SPI.transfer(0x38); // Set ACLK division register (HI-3593 data sheet, page 6)
-  SPI.transfer(ClkDiv); // page 9, table 2
-  digitalWrite(SS, HIGH);
-
-  // set the HI-3593 TX control register
-  digitalWrite(SS, LOW);
-  SPI.transfer(0x08); // write transmit control register, page 4)
-  SPI.transfer(0x20); // bit 5 (TMODE): send ARINC words without enable command (page 5)
-  digitalWrite(SS, HIGH);
-
-  // -------------------------------------------------------------------------
-  // Test SPI communication with HI-3593 (reads back the TX control register)
-  // -------------------------------------------------------------------------
-  // read transmit control register
-  digitalWrite(SS, LOW); SPI.transfer(0x84); unsigned char tcr = SPI.transfer(0); digitalWrite(SS, HIGH);
-  if (tcr==0x20) Serial.println(F("Test of SPI from/to HI-3593 is:\t\tPASSED"));
-  else {
-    Serial.print(F("Incorrect read back of a HI-3593 register. Should read 0x20, obtained: 0x"));
-    Serial.println(tcr, HEX);
-  }
-  Serial.println();
-
-  // -------------------------------------------------------------------------
-  // Test ARINC transmit and receive (requires to loopback TX to both RX)
-  // -------------------------------------------------------------------------
-  // emission of an ARINC word
-  union {long int w; unsigned char b[4];} ArincWord;
-  ArincWord.w = 0x40302010;
-  digitalWrite(SS, LOW); SPI.transfer(0x0C); for (int i=0; i<4; i++) SPI.transfer(ArincWord.b[i]); digitalWrite(SS, HIGH);
-  // waits fot complete transmission
-  delay(1);
-  // reads RX channel #1
-  digitalWrite(SS, LOW); SPI.transfer(0xA0); for (int i=0; i<4; i++) ArincWord.b[i] = SPI.transfer(0); digitalWrite(SS, HIGH);
-  if (ArincWord.w == 0x40302010) Serial.println(F("Test of ARINC TX loop back to RX1 is:\tPASSED"));
-  else {
-    Serial.print(F("Incorrect loop back of A429 TX on RX1. Should read 0x40302010, obtained: 0x"));
-    Serial.println(ArincWord.w, HEX);
-  }
-  // reads RX channel #2
-  ArincWord.w = 0;
-  digitalWrite(SS, LOW); SPI.transfer(0xC0); for (int i=0; i<4; i++) ArincWord.b[i] = SPI.transfer(0); digitalWrite(SS, HIGH);
-  if (ArincWord.w == 0x40302010) Serial.println(F("Test of ARINC TX loop back to RX2 is:\tPASSED"));
-  else {
-    Serial.print(F("Incorrect loop back of A429 TX on RX2. Should read 0x40302010, obtained: 0x"));
-    Serial.println(ArincWord.w, HEX);
-  }
-  Serial.println();
-
-  // -------------------------------------------------------------------------
-  // Test ARINC receive interrupts RINT1 & RINT2 (loopback TX to both RX)
-  // -------------------------------------------------------------------------
-  // configure interrupts
-  attachInterrupt(digitalPinToInterrupt(3), isr1, RISING);
-  attachInterrupt(digitalPinToInterrupt(2), isr2, RISING);
-  RINT1Trigd = false; RINT2Trigd = false;
-  // emission of an ARINC word
-  ArincWord.w = 0x40302010;
-  digitalWrite(SS, LOW); SPI.transfer(0x0C); for (int i=0; i<4; i++) SPI.transfer(ArincWord.b[i]); digitalWrite(SS, HIGH);
-  // waits for complete transmission
-  delay(1);
-  if (RINT1Trigd) Serial.println(F("Test of RINT1 interrupt is:\t\tPASSED"));
-  else Serial.println(F("RINT1 didn't trigger :("));
-  if (RINT2Trigd) Serial.println(F("Test of RINT2 interrupt is:\t\tPASSED"));
-  else Serial.println(F("RINT2 didn't trigger :("));
-  detachInterrupt(digitalPinToInterrupt(3));
-  detachInterrupt(digitalPinToInterrupt(2));
-  Serial.println();
-
-  // -------------------------------------------------------------------------
-  // Test ARINC "transmit empty" (TEMPTY) signal
-  // -------------------------------------------------------------------------
-  // emission of several ARINC words
-  ArincWord.w = 0x40302010;
-  for (int j=0; j<12; j++)
-    {digitalWrite(SS, LOW); SPI.transfer(0x0C); for (int i=0; i<4; i++) SPI.transfer(ArincWord.b[i]); digitalWrite(SS, HIGH);}
-  int c=0;
-  int InitialTxEmpty = digitalRead(TxEmpty);
-  while (!digitalRead(TxEmpty) && c<1000) c++;
-  int FinalTxEmpty = digitalRead(TxEmpty);
-  if (InitialTxEmpty==0 && FinalTxEmpty==1) Serial.println(F("Test of TEMPTY is:\t\t\tPASSED"));
-  else Serial.println(F("TEMPTY didn't evolve as exptected (check ACLK devider) :("));
-  Serial.println();
-
-  // ---------------------------------------------------------------------------
-  // Test DOUT, DIN1 & DIN2 0v/open discrete ; and AIN0 .. AIN3 analog signals
-  // DOUT is to be looped back to DIN1, DIN2 and AIN0 .. AIN3
-  // ---------------------------------------------------------------------------
-  digitalWrite(DOut, LOW);
-  char id0 = digitalRead(DIn0); char id1 = digitalRead(DIn1);
-  int  ia0 = analogRead(AIn0);  int  ia1 = analogRead(AIn1);
-  int  ia2 = analogRead(AIn2);  int  ia3 = analogRead(AIn3);
-  digitalWrite(DOut, HIGH);
-  char fd0 = digitalRead(DIn0); char fd1 = digitalRead(DIn1);
-  int  fa0 = analogRead(AIn0);  int  fa1 = analogRead(AIn1);
-  int  fa2 = analogRead(AIn2);  int  fa3 = analogRead(AIn3);
-  if (id0==1 && fd0==0)   Serial.println(F("Test of loop back of DOUT to DIN0 is:\tPASSED"));
-  else                    Serial.println(F("Incorrect loop back of DOUT to DIN0 :("));
-  if (id1==1 && fd1==0)   Serial.println(F("Test of loop back of DOUT to DIN1 is:\tPASSED"));
-  else                    Serial.println(F("Incorrect loop back of DOUT to DIN1 :("));
-  if (ia0>923 && fa0<100) Serial.println(F("Test of loop back of DOUT to AIN0 is:\tPASSED"));
-  else                    Serial.println(F("Incorrect loop back of DOUT to AIN0 :("));
-  if (ia1>923 && fa1<100) Serial.println(F("Test of loop back of DOUT to AIN1 is:\tPASSED"));
-  else                    Serial.println(F("Incorrect loop back of DOUT to AIN1 :("));
-  if (ia2>923 && fa2<100) Serial.println(F("Test of loop back of DOUT to AIN2 is:\tPASSED"));
-  else                    Serial.println(F("Incorrect loop back of DOUT to AIN2 :("));
-  if (ia3>923 && fa3<100) Serial.println(F("Test of loop back of DOUT to AIN3 is:\tPASSED"));
-  else                    Serial.println(F("Incorrect loop back of DOUT to AIN3 :("));
-  Serial.println();
-
-  Serial.println(F("\t\tThat's all folks !"));
-
-}
-
-void loop() {
-  // repeatedly emit an ARINC word (this permits to analyze the signal with an oscilloscope)
-  union {long int w; unsigned char b[4];} ArincWord;
-  ArincWord.w = 0x40302010;
-  digitalWrite(SS, LOW); SPI.transfer(0x0C); for (int i=0; i<4; i++) SPI.transfer(ArincWord.b[i]); digitalWrite(SS, HIGH);
-  // waits 1ms to ensure FIFO is flushed
-  delay(1);
-}


Use pollWaiting() to save power, but check serial just after start.

--- JnGeneral/JnGeneral.ino
+++ JnGeneral/JnGeneral.ino
@@ -430,18 +430,27 @@
 //    scheduler.timer(MEASURE, 0);    // start the measurement loop going
 }

+static int readSerial = 0;
+
 void loop () {
-    while (Serial.available())
-    {
-        handleInput(Serial.read());
-        serialFlush();
-    }
-//    delay(1000);
-//    Serial.print(".");
-//    serialFlush();
-    // pollWaiting goes to lowpower mode
-    // It also wakes up on interrupts (like serial)
-//    switch (scheduler.pollWaiting()) {
+    // pollWaiting goes to low-power mode but also disables the serial port.
+    // So we listen to the serial port for the first minute after boot.  If
+    // we don't receive something in that time assume noone is there and
+    // stop monitoring.
+    int event;
+    if( readSerial || millis() < 60000 ) {
+        while (Serial.available())
+        {
+            readSerial = 1;
+            handleInput(Serial.read());
+            serialFlush();
+        }
+
+        event = scheduler.poll();
+    } else {
+        event = scheduler.pollWaiting();
+    }
+    switch (event) {
 #if 0
         case MEASURE:
             // reschedule these measurements periodically
@@ -460,5 +469,5 @@
             doReport();
             break;
 #endif
-//    }
-}
+    }
+}


アナログリファレンスもテーブルで保持するようにした.

アナログリファレンスもテーブルで保持するようにした.

--- arduino/GeneralIoSerial/GeneralIoSerial.ino
+++ arduino/GeneralIoSerial/GeneralIoSerial.ino
@@ -2,18 +2,6 @@

 char read_buf[128];
 int buf_index = 0;
-
-const char* AI_REF_TBL[] = {
-  "DEFAULT",
-  "INTERNAL",
-  "EXTERNAL"
-};
-
-const uint8_t AI_REF_VAL_TBL[] = {
-  DEFAULT,
-  INTERNAL,
-  EXTERNAL
-};

 // 各々のコマンドに対して処理を行う関数の型
 typedef String (*TASK_FUNC_PTR)(String str);
@@ -35,6 +23,13 @@
   {"INPUT", INPUT},
   {"OUTPUT", OUTPUT},
   {"INPUT_PULLUP", INPUT_PULLUP}
+};
+
+// AI Reference電圧の名前と値を保持するテーブル.
+const struct STR_UINT8_PEAR AI_REF_TBL[] = {
+  {"DEFAULT", DEFAULT},
+  {"INTERNAL", INTERNAL},
+  {"EXTERNAL", EXTERNAL}
 };

 // prefixとタスク関数のテーブルを使ってキメる.
@@ -282,9 +277,9 @@
  */
 String aiRefSwitchTask(String ref){
   for(int i = 0; i < ARRAYSIZE(AI_REF_TBL); i++){
-    if(ref.endsWith(AI_REF_TBL[i])){
-      analogReference(AI_REF_VAL_TBL[i]);
-      return switchTypeReturnJson("OK", AI_REF_TBL[i]);
+    if(ref.endsWith(AI_REF_TBL[i].key)){
+      analogReference(AI_REF_TBL[i].value);
+      return switchTypeReturnJson("OK", AI_REF_TBL[i].key);
     }
   }
   ref.replace("?type=", "");


Uses int type to fix a bug.

Uses int type to fix a bug.

--- Arduino/Arduino.ino
+++ Arduino/Arduino.ino
@@ -55,7 +55,9 @@
 void loop()
 {
     if (XBee.available()) {
-      if (0xDE != XBee.read()) {
+      int c = XBee.read();
+      if (0xDE != c) {
+        Serial.print("received: "); Serial.println(c, HEX);
         return;
       }
     } else {


Arduino Side | Complete refactor of send/receive methods. Added a global delay at the end of each loop iteration. Any other delay should be a multiple or submultiple of that one

--- Arduino/Arduino.ino
+++ Arduino/Arduino.ino
@@ -3,8 +3,10 @@
 #include <stdio.h>
 #include <adk.h>
 #include "DualMC33926MotorShield.h"
-#define BUFFSIZE   128
+#define BUFFSIZE   255
 #define MAX_POWER  400
+#define DELAY 50
+

 // Start Accessory Descriptor. It's how Arduino identifies itself in Android.
 char accessoryName[] = "UDOO Mobile Tank";
@@ -19,14 +21,17 @@
 USBHost Usb;
 ADK adk(&Usb, manufacturer, model, accessoryName, versionNumber, url, serialNumber);
 // End ADK configuration
-
+bool DEBUG_MODE = true;
 int randomint;
 int last_send = 0;
-uint8_t buffer[BUFFSIZE];
-char bufNew[BUFFSIZE];
-char charBuf[2000];
+uint8_t inBuffer[BUFFSIZE];
+uint8_t outBuffer[BUFFSIZE];
+char inStringBuffer[BUFFSIZE];
+char outStringBuffer[BUFFSIZE];
 uint32_t bytesRead = 0;

+char charBuf[255];
+char bufNew[255];
 DualMC33926MotorShield tank;

 void setup() {
@@ -37,8 +42,14 @@
 }

 void loop() {
-  Serial.println("Looping");
-  readingFromADK();
+  Serial.print(".");
+  Usb.Task();
+  // Starting listening when ADK is available
+  if (adk.isReady()) {
+    readFromADK();
+    sendingToADK();
+  }
+
 }

 void stopEngine() {
@@ -46,25 +57,23 @@
   tank.setM2Speed(0);
 }

-void readingFromADK() {
-  Usb.Task();
-  // Starting listening when ADK is available
-  if (adk.isReady()) {
-    adk.read(&bytesRead, BUFFSIZE, buffer);
-    if (bytesRead > 0) {
-      for (int i = 0; i < bytesRead; i++) {
-        if (buffer[i] >= 48 && buffer[i] <= 47)
-          Serial.print(buffer[i] - 48);
-        else
-          Serial.print((char)buffer[i]);
-        Serial.print("-");
-        //eepCommandInterpreter(extractMovement(), extractSpeed());
-        //eepCommandInterpreter(extractMovement(), extractSpeed());
-      }	Serial.print("RECEIVED FROM USB: ");
-      Serial.println(*(uint32_t*)buffer);
+char* readFromADK() {
+  adk.read(&bytesRead, BUFFSIZE, inBuffer);
+  if (bytesRead > 0) {
+    memset(inStringBuffer, 0, BUFFSIZE);
+    memcpy(inStringBuffer, inBuffer, bytesRead);
+    if (DEBUG_MODE) {
+      Serial.print("\nReceiving | ");
+      Serial.print(inStringBuffer);
+      Serial.print(" | ");
+      Serial.print(strlen(inStringBuffer));
+      Serial.println(" bytes incoming");
     }
-  } sendingToADK();
+    delay(DELAY/10);
+    return inStringBuffer;
+  }return {0}; // 0 is the command for NOP
 }
+

 void sendingToADK() {
   int time = millis();
@@ -85,16 +94,22 @@
     for (int i = 0; i < s.length(); i++) {
       bufNew[i] = s.charAt(i);
     }
+    memset(outStringBuffer, 0, BUFFSIZE);
+    sprintf(outStringBuffer, "%d,%d,%d", randomint, randomint - 1000, randomint + 1000);
+    memcpy(outBuffer, outStringBuffer, BUFFSIZE);
+    adk.write(strlen(outStringBuffer), (uint8_t*)outBuffer);
+      if (DEBUG_MODE) {
+    Serial.print("Sending | ");
+    Serial.print(outStringBuffer);
+    Serial.print(" | ");
+    Serial.print(strlen(outStringBuffer));
+    Serial.println(" bytes outgoing");
+  }
   }

-  writeToAdk(charBuf);
-  delay(100);
+
+  //writeToAdk(charBuf);
+  delay(DELAY);
 }

-void writeToAdk(char textToSend[]) {
-  Serial.print(textToSend);
-  Serial.print(" ");
-  Serial.print(strlen(textToSend));
-  Serial.println(" bytes in partenza");
-  adk.write(strlen(textToSend), (uint8_t*)textToSend);
-}
+


fix bit garden bug

fix bit garden bug

--- super_freq/super_freq.ino
+++ super_freq/super_freq.ino
@@ -555,6 +555,25 @@
     // turn on one light at a time w/ current color
     // until all are lit

+    // Check if the current strip_color is "off" to
+    // avoid an infinite loop...we can turn "on" all
+    // the LEDs to the current color if there is no
+    // current color!
+    //
+    // However, it's a bit weird! (pun intended)
+    // The strip_color value has each color component
+    // 7-bit value stored as 8 bits with the high bit
+    // set to 1, BUT if you read a particular LED
+    // using getPixelColor that high bit is set to 0
+    //
+    // So, if we check our strip_color to determine if
+    // the current color is "off" we would have to do
+    // some bit shifting and bit masking. Instead,
+    // we just read the first LED instead.
+    if (strip.getPixelColor(0) <= 0) {
+        return;
+    }
+
     while (button2State == HIGH) {

         // turn off all LEDs
@@ -562,6 +581,7 @@
             strip.setPixelColor(i, strip.Color(0, 0, 0));
         }

+        // keep looping while bitgarden_grew is false
         while (!bitgarden_grew) {
             // chose a random LED
             bitgarden_led = rand()%strip.numPixels();


added special setup mode for setting the number of LEDs

--- super_freq/super_freq.ino
+++ super_freq/super_freq.ino
@@ -35,9 +35,17 @@
 byte max_brightness = 127;  // LED intensity max is 127
 byte brightness;  // where LED brightness is stored (based on dB level)

-// Pins (can be any valid output pins)
-byte dataPin  = 2;
-byte clockPin = 3;
+// Pins
+byte dataPin  = 2;  // any pin
+byte clockPin = 3;  // any pin
+byte button1Pin = 7;  // any pin
+byte button2Pin = 8;  // any pin
+
+int button1State = 0;
+int button2State = 0;
+
+boolean set_LED_count_mode = false;
+boolean increment_LED_count = false;

 // First parameter is the number of LEDs in the strand.  The LED strips
 // are 32 LEDs per meter but you can extend or cut the strip.  Next two
@@ -120,6 +128,17 @@
     if (DEBUG) {
         Serial.begin(9600);
     }
+
+    pinMode(button1Pin, INPUT);
+    pinMode(button2Pin, INPUT);
+
+    // check for button press to enter LED count set mode
+    button1State = digitalRead(button1Pin);
+
+    if (button1State == HIGH) {
+        set_LED_count_mode = true;
+    }
+
     TIMSK0 = 0;           // turn off timer0 for lower jitter
     ADCSRA = 0xe5;        // set the adc to free running mode
     ADMUX = 0x40;         // use adc0
@@ -209,9 +228,67 @@
     strip.show();
 }

+void setLEDcount() {
+    button2State = digitalRead(button2Pin);
+    nLEDs = 1;
+    strip.updateLength(nLEDs);
+    strip_color = strip.Color(127, 127, 127);
+    for (int i=0; i < strip.numPixels(); i++) {
+        strip.setPixelColor(i, strip_color);
+    }
+    strip.show();
+
+    // button 1 may still be pressed since the code gets here very fast
+    // if button 1 is pressed, wait will the user releases it
+    while (button1State == HIGH) {
+        // do nothing, we need to wait until user releases the button
+        button1State = digitalRead(button1Pin);
+    }
+
+    // button 2 is used to exit the LED count set mode
+    while (button2State == LOW) {
+        button1State = digitalRead(button1Pin);
+        button2State = digitalRead(button2Pin);
+        increment_LED_count = false;
+
+        if (button1State == HIGH) {
+            increment_LED_count = true;
+        }
+
+        while (button1State == HIGH) {
+            // do nothing, we need to wait until user releases the button
+            button1State = digitalRead(button1Pin);
+        }
+
+        if (increment_LED_count) {
+            Serial.println("Button pressed!");
+            nLEDs++;
+            strip.updateLength(nLEDs);
+            strip_color = strip.Color(127, 127, 127);
+            for (int i=0; i < strip.numPixels(); i++) {
+                strip.setPixelColor(i, strip_color);
+            }
+            strip.show();
+        }
+    }
+
+    // button 2 was pressed, save LED count to EEPROM
+    set_LED_count_mode = false;
+}
+
 void loop() {
+    // check for LED count mode
+    if (set_LED_count_mode == true) {
+        if (DEBUG) {
+            Serial.println("Entered LED set mode");
+        }
+        setLEDcount();
+        return;
+    }
+
     // read color palette input pin here
     // this line reserved for color palette pin
+    button1State = digitalRead(button1Pin);

     // check if palette changed
     // Note: this equality will be changed when color palette chooser


Rework button press detection.

Rework button press detection.

--- Aufgabe3/Aufgabe3.ino
+++ Aufgabe3/Aufgabe3.ino
@@ -9,28 +9,24 @@

 bool __attribute__((OS_buttonPress)) buttonPress(bool button) {
   bool press = 0;
-  asm volatile ("    CPI   %[btn], 1   \n\t"
-                "    BREQ AButton      \n\t"
-                "DButton:              \n\t"
-                "    IN   r16, %[ping] \n\t"
-                "    ANDI r16, 0x20    \n\t"
-                "    JMP  CMP          \n\t"
-                "AButton:              \n\t"
-                "    IN   r16, %[pinf] \n\t"
-                "    ANDI r16, 0x18    \n\t"
-                "CMP:                  \n\t"
-                "    CPI  r16, 0x0     \n\t"
-                "    BRNE PRESSED      \n\t"
-                "    LDI  %[result], 0 \n\t"
-                "    JMP  END          \n\t"
-                "PRESSED:              \n\t"
-                "    LDI  %[result], 1 \n\t"
-                "END:                  \n\t"
-                "                      \n\t"
-
-                : [result]"=r" (press)
-                : [ping] "I" (_SFR_IO_ADDR(PING)), [pinf] "I" (_SFR_IO_ADDR(PINF)), [btn] "w" (button)
-                : "r16");
+
+  if (button == 0) {
+    press = (PING & 0x20);
+
+    if (press) {
+      delay(200);
+      press = (PING & 0x20);
+    }
+  }
+  else {
+    press = (PINF & 0x18);
+
+    if (press) {
+      delay(200);
+      press = (PINF & 0x18);
+    }
+  }
+
   return press;
 }


Fixed the bug. We were not initializing the HW to a known state before using the file to set the board.

--- BackEnd/BackEnd.ino
+++ BackEnd/BackEnd.ino
@@ -469,6 +469,10 @@
 //------------------------------------------------------------
 void initBoardStateFromFile(char* _sFullFilePath) {

+  // Initialize the HW to a known state
+  initBoardState();
+
+  // Read HW state in from the file
 //  Serial.println("Init from board file");
   // Open File
   FILE *fp;
@@ -855,10 +859,19 @@
   {
     if( !g_aPins[i].is_input ) // Process output pins
     {
-      if( g_aPins[i].is_analog ) // Process analog pins
+      if( g_aPins[i].is_analog ) // Process analog pins
         analogWrite(i, getTotalPinValue(i)*ANALOG_OUT_MAX_VALUE );
       else // Process digital pins
         digitalWrite(i, getTotalPinValue(i) );
+
+      /*
+      if(i==13)
+      {
+        Serial.print("Value:");
+        Serial.println(getTotalPinValue(i));
+      }
+      */
+
     }
   }

@@ -1769,14 +1782,16 @@
     {
     case UP:
 //      g_iNewCode = 0;
-      initBoardStateFromFile(BOARD_CONFIG_FILE_FULL_PATH);
+//      initBoardStateFromFile(BOARD_CONFIG_FILE_FULL_PATH);
        //      g_iWriteToFile=0;
+       digitalWrite(13, HIGH );
       break;

     case DOWN:

+           digitalWrite(13, LOW );
       // Serial.println("Writing board state to file");
-        writeBoardStateToFile(BOARD_CONFIG_FILE_FULL_PATH);
+//        writeBoardStateToFile(BOARD_CONFIG_FILE_FULL_PATH);
       // g_iWriteToFile=1;

 //        system("shutdown -r now");


Update iGPS.ino

Update iGPS.ino

增加SD卡操作

--- iGPS.ino
+++ iGPS.ino
@@ -6,6 +6,8 @@

 #include "LCD4884.h"

+#include <SD.h>
+
 #define GPRMC "$GPRMC" // 推荐最小定位信息
 #define GPVTG "$GPVTG" // 地面速度信息
 #define GPGGA "$GPGGA" // 获取海拔高度
@@ -22,6 +24,14 @@

 // SoftwareSerial 缓冲
 //#define _SS_MAX_RX_BUFF 128
+
+//SD card attached to SPI bus as follows:
+//#define SD_MOSI 11
+//#define SD_MISO 12
+//#define SD_CLK 13
+#define SD_CS 4
+
+File sdFile;

 boolean LIGHT_STATUS = 0;

@@ -73,6 +83,16 @@

   lcd.init();
   lcd.clear();
+
+  if (!SD.begin(SD_CS)) {
+//    Serial.println("initialization failed!");
+    return;
+  }
+//  Serial.println("initialization done.");
+
+  // open the file. note that only one file can be open at a time,
+  // so you have to close this one before opening another.
+
 }

 void loop(){
@@ -110,8 +130,9 @@
 boolean readGPS() {
     String sub = readLine();
     if(sub.length()) {
-      Serial.println(sub);
-      Serial.println("-------------------------------------------");
+      sdFile = SD.open("gps.txt", FILE_WRITE);
+      sdFile.println(sub);
+      sdFile.close();
       int split = sub.indexOf(',');
       String field = sub.substring(0,split);
       if(field.equals(GPRMC)) {


v.0.1.0 first version mounted on the box

--- Sequencer/Sequencer.ino
+++ Sequencer/Sequencer.ino
@@ -1,5 +1,5 @@
 /*
-KidModular - SEQUENCER
+KidModular - SEQUENCER - V.0.1.0
 by Tiago Angelo (aka p1nho)

 Built with:
@@ -28,15 +28,20 @@
 #define DEBUG 1

 // Sequencer
-#define MAXSTEPS 8
+#define MAXSTEPS 6
 #define RADIUS 140 // gemetric shapes radius
 #define STEPRADIUS 8 // step circle radius
 // Controls
-#define BPMPIN 8
-#define NSTEPSPIN 9
-#define ENCL 2 // encoder Left
-#define ENCR 3 // encoder Right
-#define ENCB 4 // encoder button
+#define BPMPIN 7 // bpm pot
+#define NSTEPSPIN 6 // num steps pot
+                    // pitch pots from A0 to A5
+#define ENCL 8 // encoder Left
+#define ENCR 9 // encoder Right
+#define ENCB 12 // encoder button
+// Control Voltage
+#define GATEPIN 11
+#define PITCHPIN 10
+                // led pins from 2 to 7
 /************************************ CLASS OBJECTS *********************************************************/
 // Encoder
 Encoder encoder(ENCL, ENCR);
@@ -53,7 +58,7 @@
 uint8_t curStep = 0;
 uint8_t stepEdit = 0, pStepEdit = 0;
 uint8_t pitch[MAXSTEPS];
-uint8_t dur[] = {50, 50, 50, 50, 50, 50, 50, 50};
+uint8_t dur[] = {50, 50, 50, 50, 50, 50};
 uint8_t pDur = 50;
 // Encoder
 byte button, _button;
@@ -63,16 +68,14 @@
   if(DEBUG) Serial.begin(9600);

   // set pins
-  for (int i = 5; i < 12; i++){
-    // LEDS pins 5~11
+  for (int i = 2; i < 8; i++){
+    // LEDS pins 2~7
     pinMode(i, OUTPUT);
     digitalWrite(i, HIGH); // turn off
   }
-  pinMode(44, OUTPUT); // LED 8 - pin44 ??
-  digitalWrite(44, HIGH); // turn off
-  pinMode(12, OUTPUT); // PITCH CV OUT pin12
-  pinMode(13, OUTPUT); // GATE CV OUT pin13
-  pinMode(4, INPUT_PULLUP); // Encoder button
+  pinMode(PITCHPIN, OUTPUT); // PITCH CV OUT pin12
+  pinMode(GATEPIN, OUTPUT); // GATE CV OUT pin13
+  pinMode(ENCB, INPUT_PULLUP); // Encoder button
   // Init LCD
   screen.init();

@@ -88,7 +91,7 @@
 void loop(void){
   noInterrupts();
   // print stuff here
-    if(DEBUG) Serial.println(dur[1]);
+    if(DEBUG) Serial.println(numSteps);
   interrupts();

   delayMicroseconds(6000); // latency = 8ms (remember 0.75ms is equivalent to 1ms)
@@ -121,38 +124,50 @@
   }
   // Gate CV output
   if(playhead < stepTime * dur[curStep] / 100.f){
-    PORTB |= _BV(PB7); // pin13 HIGH
+//    PORTB |= _BV(PB7); // pin13 HIGH
     switch(curStep){
       case 0:
+         PORTE &= ~_BV(PE4); // pin2 LOW (common anode, so it's a ON)
+      break;
+      case 1:
+         PORTE &= ~_BV(PE5); // pin3 LOW (common anode, so it's a ON)
+      break;
+      case 2:
+         PORTG &= ~_BV(PG5); // pin4 LOW (common anode, so it's a ON)
+      break;
+      case 3:
          PORTE &= ~_BV(PE3); // pin5 LOW (common anode, so it's a ON)
       break;
-      case 1:
+      case 4:
          PORTH &= ~_BV(PH3); // pin6 LOW (common anode, so it's a ON)
-      break;
-      case 2:
+      break;
+      case 5:
          PORTH &= ~_BV(PH4); // pin7 LOW (common anode, so it's a ON)
-      break;
-      case 3:
-         PORTH &= ~_BV(PH5); // pin8 LOW (common anode, so it's a ON)
       break;
       default:
       break;
     }
   }
   else{
-    PORTB &= ~_BV(PB7); // pin13 LOW
+//    PORTB &= ~_BV(PB7); // pin13 LOW
     switch(curStep){
       case 0:
+         PORTE |= _BV(PE4); // pin2 LOW (common anode, so it's a ON)
+      break;
+      case 1:
+         PORTE |= _BV(PE5); // pin3 LOW (common anode, so it's a ON)
+      break;
+      case 2:
+         PORTG |= _BV(PG5); // pin4 LOW (common anode, so it's a ON)
+      break;
+      case 3:
          PORTE |= _BV(PE3); // pin5 LOW (common anode, so it's a ON)
       break;
-      case 1:
+      case 4:
          PORTH |= _BV(PH3); // pin6 LOW (common anode, so it's a ON)
-      break;
-      case 2:
+      break;
+      case 5:
          PORTH |= _BV(PH4); // pin7 LOW (common anode, so it's a ON)
-      break;
-      case 3:
-         PORTH |= _BV(PH5); // pin8 LOW (common anode, so it's a ON)
       break;
       default:
       break;
@@ -163,9 +178,9 @@
 /************************************** UPDATE CONTROLS *****************************************************/
 void updateControls(){
   // Potentiometers
-  bpm = (analogRead(BPMPIN) >> 1) + 30; // from 40 to 167 bpm
+  bpm = (analogRead(BPMPIN) >> 1) + 30; // from 30 to 541 bpm
   stepTime = 60000.f / bpm;
-  numSteps = (analogRead(NSTEPSPIN) >> 7) + 1; // from 1 to 8 steps
+  numSteps = (analogRead(NSTEPSPIN) / 171) + 1; // from 1 to 6 steps
   for(int i = 0; i < 8; i++){
     pitch[i] = analogRead(i) >> 3; // from 0 to 127
   }


Update TeensyLogicAnalyzer.ino

Update TeensyLogicAnalyzer.ino

--- TeensyLogicAnalyzer.ino
+++ TeensyLogicAnalyzer.ino
@@ -1,5 +1,5 @@
 /* Teensy Logic Analyzer
- * Copyright (c) 2018 LAtimes2
+ * Copyright (c) 2020 LAtimes2
  *
  * The MIT License (MIT)
  *
@@ -38,64 +38,6 @@
 //   Serial : interface to SUMP user interface
 //   Serial1/2/3 : debug info (if turned on)

-//
-//  User Configuration settings
-//
-
-#define HARDWARE_CONFIGURATION 0   // if 1, it will use the SPI input(s) instead of Port D
-#define CREATE_TEST_FREQUENCIES 0  // if 1, it will output frequencies on pins 5/6/0/21 (channels 4-7) and pin 3
-
-//
-// Pin definitions (info only - do not change)
-//
-
-#if HARDWARE_CONFIGURATION
-
-#define CHAN0 1   // or 26 (3.1) / 5 (LC)
-#define CHAN1 8   // or 12
-
-#else
-
-#define CHAN0 2
-#define CHAN1 14
-#define CHAN2 7
-#define CHAN3 8
-#define CHAN4 6
-#define CHAN5 20
-#define CHAN6 21
-#define CHAN7 5
-
-#endif
-
-#define LED_PIN 13
-
-#define TIMING_PIN_0 15
-#define TIMING_PIN_1 16
-#define TIMING_PIN_2 17
-#define TIMING_PIN_3 18
-#define TIMING_PIN_4 19
-#define TIMING_PIN_5 22
-
-//////////////////////////////////////
-// End of settings
-//////////////////////////////////////
-
-#include <stdint.h>
-#include "types.h"
-
-#define VERSION "4.1"
-
-//#define TIMING_DISCRETES   // if uncommented, set pins 0 and 1 for timing
-//#define TIMING_DISCRETES_2 // if uncommented, more timing detail
-
-// Debug serial port. To turn on, comment out next 2 lines and uncomment desired line
-#define NO_DEBUG
-#define DEBUG_SERIAL(x) 0   // no debug output
-//#define DEBUG_SERIAL(x) Serial.x  // debug output to USB Serial (conflicts with GUI)
-//#define DEBUG_SERIAL(x) Serial1.x // debug output to Serial1
-//#define DEBUG_SERIAL(x) Serial2.x // debug output to Serial2
-//#define DEBUG_SERIAL(x) Serial3.x // debug output to Serial3
-
 // define the various types of Teensy's

 // Teensy 3.0
@@ -113,7 +55,86 @@
 // Teensy 3.6
 #elif defined(__MK66FX1M0__)
   #define Teensy_3_6 1
-#endif
+// Teensy 4.0
+#elif defined(__IMXRT1062__)
+  #define Teensy_4_0 1
+#endif
+
+//
+//  User Configuration settings
+//
+
+#define HARDWARE_CONFIGURATION 0   // if 1, it will use the SPI input(s) instead of Port D
+#define CREATE_TEST_FREQUENCIES 0  // if 1, it will output frequencies on pins 5/6/0/21 (channels 4-7) and pin 3
+
+//
+// Pin definitions (info only - do not change)
+//
+
+#if HARDWARE_CONFIGURATION
+
+#define CHAN0 1   // or 26 (3.1) / 5 (LC)
+#define CHAN1 8   // or 12
+
+#else
+
+  #if Teensy_4_0
+
+#define CHAN0 10
+#define CHAN1 12
+#define CHAN2 11
+
+  #else
+
+#define CHAN0 2
+#define CHAN1 14
+#define CHAN2 7
+#define CHAN3 8
+#define CHAN4 6
+#define CHAN5 20
+#define CHAN6 21
+#define CHAN7 5
+
+  #endif
+
+#endif
+
+#define LED_PIN 13
+
+#define TIMING_PIN_0 15
+#define TIMING_PIN_1 16
+#define TIMING_PIN_2 17
+#define TIMING_PIN_3 18
+#define TIMING_PIN_4 19
+#define TIMING_PIN_5 22
+
+//////////////////////////////////////
+// End of settings
+//////////////////////////////////////
+
+#include <stdint.h>
+#include "types.h"
+
+#if Teensy_4_0
+// beta release
+#define VERSION "4.1 beta"
+
+#else
+
+#define VERSION "4.1"
+
+#endif
+
+//#define TIMING_DISCRETES   // if uncommented, set pins 0 and 1 for timing
+//#define TIMING_DISCRETES_2 // if uncommented, more timing detail
+
+// Debug serial port. To turn on, comment out next 2 lines and uncomment desired line
+#define NO_DEBUG
+#define DEBUG_SERIAL(x) 0   // no debug output
+//#define DEBUG_SERIAL(x) Serial.x  // debug output to USB Serial (conflicts with GUI)
+//#define DEBUG_SERIAL(x) Serial1.x // debug output to Serial1
+//#define DEBUG_SERIAL(x) Serial2.x // debug output to Serial2
+//#define DEBUG_SERIAL(x) Serial3.x // debug output to Serial3

 // Program requires about 1k bytes for local variables. The buffer sizes
 // below have been set to be as large as possible while leaving 1k.
@@ -164,6 +185,11 @@
    // 246k buffer size
    #define LA_SAMPLE_SIZE 246 * 1024

+#elif Teensy_4_0
+
+   // 460k buffer size
+   #define LA_SAMPLE_SIZE 460 * 1024
+
 #else

    // 4k buffer size
@@ -171,8 +197,13 @@

 #endif

-// use Port D for sampling
-#define PORT_DATA_INPUT_REGISTER  GPIOD_PDIR
+#if Teensy_4_0
+   // use Port 7 for sampling
+   #define PORT_DATA_INPUT_REGISTER  GPIO7_PSR
+#else
+   // use Port D for sampling
+   #define PORT_DATA_INPUT_REGISTER  GPIOD_PDIR
+#endif

 // PIT timer registers
 #define TIMER_CONTROL_REGISTER    PIT_TCTRL0
@@ -225,6 +256,16 @@
   STRATEGY_ASM_8_CLOCKS,
 } sumpStrategy = STRATEGY_NORMAL;

+#if Teensy_4_0
+
+int F_BUS = F_BUS_ACTUAL;
+
+// cpu clock cycles between samples
+uint32_t cpuClockCycles;
+uint32_t previousSampleTime;
+
+#endif
+
 int currentFBUS = F_BUS;
 uint32_t sumpRunning = 0;

@@ -285,11 +326,13 @@
   pinMode(CHAN0, INPUT);
   pinMode(CHAN1, INPUT);
   pinMode(CHAN2, INPUT);
+#if not Teensy_4_0
   pinMode(CHAN3, INPUT);
   pinMode(CHAN4, INPUT);
   pinMode(CHAN5, INPUT);
   pinMode(CHAN6, INPUT);
   pinMode(CHAN7, INPUT);
+#endif

 #endif

@@ -307,6 +350,7 @@

 #endif

+  blinkled();
   blinkled();

   setupTestFrequencies (F_BUS);
@@ -520,7 +564,17 @@
           Serial.write("Teensy48");
         #endif
       } else {
-        Serial.write("Teensy");
+        #if Teensy_4_0
+           if (F_CPU == 600000000) {
+              Serial.write("Teensy40_600");
+           } else if (F_CPU == 816000000) {
+              Serial.write("Teensy40_816");
+           } else {
+              Serial.write("Teensy");
+           }
+        #else
+           Serial.write("Teensy");
+        #endif
       }
       Serial.write(0x00);
       // firmware version string
@@ -700,6 +754,7 @@
       // by setting device.dividerClockspeed = F_BUS, divisor is exactly equal to value to put in timer
       sumpSetup.busClockDivisor = divisor;

+#if not Teensy_4_0
       sumpSetup.clockFrequency = F_BUS / (divisor + 1);

       if (F_CPU >= 144000000) {
@@ -720,6 +775,10 @@

         setupTestFrequencies (currentFBUS);
       }
+#else
+      // Teensy 4 does not use F_BUS for logic analyzer, so config file sets it to F_CPU
+      sumpSetup.clockFrequency = F_CPU_ACTUAL / (divisor + 1);
+#endif

       #if HARDWARE_CONFIGURATION
       if (F_CPU > 150000000) {
@@ -730,6 +789,9 @@

       sumpSetup.cpuClockTicks = F_CPU / sumpSetup.clockFrequency;

+#if Teensy_4_0
+      cpuClockCycles = sumpSetup.cpuClockTicks;
+#endif
       break;

     case SUMP_CAPTURE_COUNT:
@@ -808,25 +870,31 @@

 #else

+#if Teensy_4_0
+  // GPIO read seems to take 8 clock cycles
+  if (sumpSetup.cpuClockTicks <= 8)
+#else
   if (sumpSetup.cpuClockTicks <= 3)
+#endif
   {
     sumpStrategy = STRATEGY_ASM_3_CLOCKS;
     sumpSetup.numberOfChannels = 8;
   }
 #if Teensy_LC
   else if (sumpSetup.cpuClockTicks <= 6)
+#else
+  else if (sumpSetup.cpuClockTicks <= 5)
+#endif
   {
     sumpStrategy = STRATEGY_ASM_5_6_CLOCKS;
     sumpSetup.numberOfChannels = 8;
   }
-#else
-  else if (sumpSetup.cpuClockTicks <= 5)
-  {
-    sumpStrategy = STRATEGY_ASM_5_6_CLOCKS;
-    sumpSetup.numberOfChannels = 8;
-  }
-#endif
+#if Teensy_4_0
+  // GPIO read seems to take 8 clock cycles
+  else if (sumpSetup.cpuClockTicks <= 11)
+#else
   else if (sumpSetup.cpuClockTicks <= 8)
+#endif
   {
     sumpStrategy = STRATEGY_ASM_8_CLOCKS;
     sumpSetup.numberOfChannels = 8;
@@ -836,7 +904,11 @@
     // if RLE selected, 8 channels, and more than 48 clock ticks
     if (sumpSetup.rleSelected &&
         sumpSetup.numberOfChannels >= 8 &&
+#if Teensy_4_0
+        sumpSetup.cpuClockTicks > 24)
+#else
         sumpSetup.cpuClockTicks > 48)
+#endif
     {
       sumpSetup.rleUsed = true;
       sumpStrategy = STRATEGY_NORMAL_RLE;
@@ -850,7 +922,11 @@
     }
     else
     {
+#if Teensy_4_0
+      if (sumpSetup.cpuClockTicks > 11)
+#else
       if (sumpSetup.cpuClockTicks > 48)
+#endif
       {
         sumpStrategy = STRATEGY_NORMAL;
       }
@@ -915,7 +991,11 @@
   }

   // if assembly language
+#if Teensy_4_0
+  if (sumpSetup.cpuClockTicks <= 11)
+#else
   if (sumpSetup.cpuClockTicks <= 8)
+#endif
   {
     // assembly only does 1 sample per byte
     sumpSetup.numberOfChannels = 8;
@@ -1027,7 +1107,7 @@
 #endif
   else if (sumpStrategy == STRATEGY_ASM_3_CLOCKS)
   {
-#if Teensy_3_6
+#if Teensy_3_6 || Teensy_4_0
     // need to call once to load the code in the cache so it
     // can meet the speed requirement
     sumpSetupVariableStruct dummySetup = sumpSetup;
@@ -1035,6 +1115,7 @@
     dummySetup.samplesToSend = 1024;
     recordDataAsm3Clocks(dummySetup, dynamic);
 #endif
+
     recordDataAsm3Clocks(sumpSetup, dynamic);
   }
   else if (sumpStrategy == STRATEGY_ASM_8_CLOCKS)
@@ -1071,12 +1152,21 @@
   SUMPreset();
 }

-
 inline void waitForTimeout (void)
 {
-  #ifdef TIMING_DISCRETES
+  #ifdef TIMING_DISCRETES
     digitalWriteFast (TIMING_PIN_0, HIGH);
   #endif
+
+#if Teensy_4_0
+
+  // TODO: this handles rollover but takes extra cpu cycles
+  //  while (ARM_DWT_CYCCNT - previousSampleTime < cpuClockCycles) ; // wait
+  while (ARM_DWT_CYCCNT < cpuClockCycles + previousSampleTime) ; // wait
+
+  previousSampleTime += cpuClockCycles;
+
+#else

   // for speed, to reduce jitter
   if (TIMER_FLAG_REGISTER)
@@ -1099,6 +1189,7 @@
     waitEnd:
     clearTimerFlag ();
   }
+#endif

   #ifdef TIMING_DISCRETES
     digitalWriteFast (TIMING_PIN_0, LOW);
@@ -1173,6 +1264,11 @@

 void startTimer (uint32_t busTicks)
 {
+#if Teensy_4_0
+
+  previousSampleTime = ARM_DWT_CYCCNT;
+
+#else
   // Enable PIT clock
   SIM_SCGC6 |= SIM_SCGC6_PIT;

@@ -1187,5 +1283,6 @@

   // Enable timer
   TIMER_CONTROL_REGISTER |= PIT_TCTRL_TEN;
-}
-
+#endif
+}
+


installed all 8 stepper motors

installed all 8 stepper motors

--- loom.ino
+++ loom.ino
@@ -13,7 +13,7 @@
     - 1 foot pedal (MPJA 18150 or equiv.)
     - 1 Teensy 3.5 microprocessor, with 512KB flash, 192KB RAM, 4KB EEPROM, and 40 I/O pins

-   The software allow you to graphically configure the treadle tie-ups and the treadle sequence,
+   The software allows you to graphically configure the treadle tie-ups and the treadle sequence,
    and then weave by throwing the shuttle and just pushing the single foot pedeal to get the
    next configuration of the shafts.  The warping, though, must still be done manually!


add new sensor

add new sensor

--- main.ino
+++ main.ino
@@ -86,6 +86,9 @@
     //set up IR sensor
     shortIR_RF.init(shortIR_RF_in);
     shortIR_LF.init(shortIR_LF_in);
+
+    shortIR_R.init(shortIR_R_in);
+    shortIR_L.init(shortIR_L_in);
     //longIR_F.init(longIR_F_in);
     delay(10);
 }


add interrupt auto fix

add interrupt auto fix

--- main.ino
+++ main.ino
@@ -4,24 +4,30 @@
 #include "HMC5883L.h"  // Digital Compass
 #include "Speed.h"     // Set Speed
 #include "Cornering.h" // Turning
+#include "avr/io.h"    // hmm
+#include "avr/interrupt.h" //

-#define urPWM_F 2
-#define urTRIG_F 3
+#define urPWM_F 15
+#define urTRIG_F 14

-#define urPWM_L 4
-#define urTRIG_L 5
+#define urPWM_L 1
+#define urTRIG_L 0

-#define urPWM_R 6
-#define urTRIG_R 7
+#define urPWM_R 13
+#define urTRIG_R 11

-#define motor_L A0
-#define motor_R A1
+#define motor_L 3  // encoder
+#define motor_R 5  // encoder

 /**********************/
-#define shortIR_LF_in A2
-#define shortIR_LR_in A3
-#define longIR_F_in A4
+#define shortIR_LF_in A4
+#define shortIR_LR_in A5
+//#define longIR_F_in A4
 /**********************/
+#define RisingEdgePerGrid 400 // need testing
+#define RisingEdgePerTurn 400 // need testing
+
+
 URM37 u_F, u_L, u_R;
 SharpA02 longIR_F;
 SharpA21 shortIR_LF, shortIR_LR;
@@ -32,7 +38,18 @@

 void setPinsMode() {
     //analog pins no need
+    //so IR sensor no need
     //digital pins are set in URM37.h
+    //
+    //TODO ===> set moto sensor in
+    pinMode(motor_R, INPUT);
+    pinMode(motor_L, INPUT);
+}
+
+void waitForCommand() {
+    while (!Serial.available() || Serial.read() != 'S') {
+    }
+    delay(10);
 }

 void setup() {
@@ -55,13 +72,47 @@
     //set up IR sensor
     shortIR_LR.init(shortIR_LR_in);
     shortIR_LF.init(shortIR_LF_in);
-    longIR_F.init(longIR_F_in);
+    //longIR_F.init(longIR_F_in);
     delay(10);
-    while (!Serial.available() || Serial.read() != 'S') {
-        delay(10);
-    }
 }

 void loop() {
+    waitForCommand();
+    exploration();
+    waitForCommand();
+    //memoryLane();
+    bridesheadRevisited();
+}

+void setTimerInterrupt() {
+  cli();          // disable global interrupts
+  // Timer/Counter Control Registers
+  TCCR1A = 0;     // set entire TCCR1A register to 0
+  TCCR1B = 0;     // same for TCCR1B
+
+  // set compare match register to desired timer count:
+  OCR1A = 1562;   // scale = 1024, OCR1A = (xxx / 64 / 1024)
+
+  // turn on CTC mode:
+  TCCR1B |= (1 << WGM12);
+  // Set CS10 and CS12 bits for 1024 prescaler:
+  TCCR1B |= (1 << CS10);
+  TCCR1B |= (1 << CS12);
+
+  //  enable timer compare interrupt:
+  //  Timer/Counter Interrupt Mask Register
+  //  Compare A&B interrupts
+  TIMSK1 |= (1 << OCIE1A);
+  sei();          // enable global interrupts
+}
+void detachTimerInterrupt() {
+  cli();
+  TIMSK1 = 0; // disable
+  sei();
+}
+ISR(TIMER1_COMPA_vect) {
+  if (speedMode == 0)
+    md.setM1Speed((200 + leftCompensate) * neg);
+  else
+    md.setM1Speed((350 + leftCompensate) * neg);
 }


Добавлена сигнализация при неправильном пароле. Начата работа с секундомером

--- main.ino
+++ main.ino
@@ -11,7 +11,7 @@
 // #define FIRST_LOADING
 // #define DEBUG
 // #define ENGINEERING_MODE
-#define TIKTOK 4
+// #define TIKTOK 4

 #define set_bit(m,b)	((m) |= (b))
 #define unset_bit(m,b)	((m) &= ~(b))
@@ -22,7 +22,7 @@

 LiquidCrystal_I2C lcd(0x27,16,2); // Инициализация дисплея (адрес, количество символов, количество строк)

-#define VERSION "0.5(r)"
+#define VERSION "0.87(b)"

 static byte	bat_icon[8] = {
 	B01110,
@@ -64,6 +64,7 @@
 #define NEON_ON_DOWNTIME	(1 << 3)	// Плавное свечение нижней подсветки в простое
 #define ALARM_STATE			(1 << 4)	// Для того, чтобы даже после сброса сигнализация не выключилась
 #define ALARM_WRITED		(1 << 5)	// Было ли записано значение о сигнализации в EEPROM
+#define ALARM_WITHOUT_DOCK	(1 << 6)	// Сигналтзация при отключения от велосипеда

 struct sys_conf {
 	byte	password[6],		// Пароль, для отключения сигнала
@@ -76,7 +77,7 @@
 			system_byte,		// Байт взявший в себя функцию нескольких болевкских переменных
 			lux_light_on,		// При какой яркости включать фару
 			lux_backlight_on,	// При какой яркости включать подсветку экрана
-			bright_headlight;		// Яркость фары
+			bright_headlight;	// Яркость фары

 	float	distance,
 			max_speed,
@@ -117,6 +118,10 @@
 #define BATTERY_ICON		0
 #define SIGNAL_ICON			1
 #define LOCK_ICON			2
+#define ZERO_SPEED_DEL		2		// * 500 = секунд - время обнуления скорости
+#define SPEED_DEF			3.0		// На сколько должна упасть скорость, чтобы загорелся красный сигнал
+#define WAIT_INPUT_DELAY	5000	// Время, за которое должен быть осуществлён ввод иначе сигнализация
+#define BIP_ALARM_DELAY		250		// Задержка для смены тона сигнала при сигнализации

 /*Для определения заряда батарей*/
 #define TYPVBG				1.1
@@ -134,7 +139,16 @@
 #define SIGNAL_RIGHT_ON		(1 << 4)
 #define EMERGENCY_SIGNAL	(1 << 5)
 #define SECOND_ITERATION	(1 << 6)
-#define BIP_SIGNAL			(1 << 7)
+
+/*bits road_signals*/
+#define BIP_SIGNAL			(1 << 0)
+#define RED_STOP_SIGNAL		(1 << 1)
+
+/*bits security_byte*/
+#define DEEP_SLEEP			(1 << 0)
+#define WAIT_INPUT			(1 << 1)
+#define BIP_FIRST_STAGE		(1 << 1)
+

 unsigned long	lastturn;	// Время последнего обращения

@@ -142,14 +156,23 @@
 			distance		= 0.0;	// Расстояние

 byte		system_mode		= 0,
-			deep_sleep		= false;
+			security_byte	= 0,
+			stopwatch_hour	= 0,
+			stopwatch_min	= 0,
+			stopwatch_sec	= 0;
+
+bool		stopwatch_run	= false;
+
+unsigned int	sys_wait_delay	= 0;

 /*system_mode*/
-#define SPEED_MODE			0
-#define ALARM_MODE			1
-#define MENU_MODE			2
-#define SETTING_MODE		3
-#define SLEEP_MODE			4
+#define SPEED_MODE		0
+#define ALARM_MODE		1
+#define MENU_MODE		2
+#define SETTING_MODE	3
+#define SLEEP_MODE		4
+#define STOPWATCH_MODE	5
+#define WARNING_MODE	6

 sys_conf		btc_config; // Конфигурация системы

@@ -158,10 +181,15 @@
 	Serial.begin(9600);
 	#endif

+	#if !defined(FIRST_LOADING)
+	ReadSysConfEEPROM(&btc_config, 0);
+	#endif
+
 	pinMode(EXT_ALARM, OUTPUT);
 	digitalWrite(EXT_ALARM, HIGH);

 	pinMode(DISPLAY_LIGHT, OUTPUT);		// Подключение подсветки экрана
+	pinMode(LOWER_LIGHT, OUTPUT);

 	lcd.begin();
 	lcd.print("Loading system...");
@@ -169,13 +197,14 @@
 	lcd.print("Version: ");
 	lcd.print(VERSION);

-	for (byte	i	= 0; i < 255; i++, delay(8), analogWrite(DISPLAY_LIGHT, i));
-
+	if (!bit_seted(btc_config.system_byte, ALARM_STATE))
+		for (byte	i	= 0; i < 255; i++, delay(8), analogWrite(DISPLAY_LIGHT, i), analogWrite(LOWER_LIGHT, i));
+
+	digitalWrite(LOWER_LIGHT, LOW);

 	/*Инициализация цифровых выводов*/
 	pinMode(BIP, OUTPUT);
 	pinMode(HEADLIGHT, OUTPUT);
-	pinMode(LOWER_LIGHT, OUTPUT);
 	pinMode(VIBRO_SENSOR, OUTPUT);
 	pinMode(LATCH_PIN, OUTPUT);
 	pinMode(RED_BACK_LIGHT, OUTPUT);
@@ -210,8 +239,6 @@
 	calibration();
 	input_password();
 	WriteSysConfEEPROM(btc_config, 0);
-	#else
-	ReadSysConfEEPROM(&btc_config, 0);
 	#endif

 	#ifdef DEBUG
@@ -282,7 +309,11 @@

 	registerWrite(0);

-	system_mode	= SPEED_MODE;
+	if (bit_seted(btc_config.system_byte, ALARM_STATE))
+		system_mode	= ALARM_MODE;
+	else
+		system_mode	= SPEED_MODE;
+
 }

 void loop() {
@@ -290,7 +321,8 @@
 		case SPEED_MODE:	road_mode();
 							break;

-		case ALARM_MODE:	break;
+		case ALARM_MODE:	alarm();
+							break;

 		case MENU_MODE:		menu();
 							break;
@@ -300,6 +332,9 @@

 		case SLEEP_MODE:	system_sleep();
 							break;
+
+		case STOPWATCH_MODE:	stopwatch();
+								break;
 	}
 }

@@ -308,38 +343,94 @@
 }

 void speed_sense() {	// Подсчёт скорости
-	system_mode	= SPEED_MODE;
-
-	if ((millis() - lastturn) > 80) { // Защита от случайных измерений (основано на том, что велосипед не будет ехать быстрее 120 кмч)
-		speed_now	= btc_config.wheel_length / ((float)(millis() - lastturn) / 1000) * 3.6;	// Расчет скорости, км/ч
-		lastturn	= millis();	// Запомнить время последнего оборота
-		distance	= distance + btc_config.wheel_length / 1000;	// Прибавляем длину колеса к дистанции при каждом обороте
+	if ((system_mode != ALARM_MODE) && (system_mode != SLEEP_MODE) && (system_mode != STOPWATCH_MODE)) {
+		system_mode	= SPEED_MODE;
+
+		if ((millis() - lastturn) > 80) { // Защита от случайных измерений (основано на том, что велосипед не будет ехать быстрее 120 кмч)
+			speed_now	= btc_config.wheel_length / ((float)(millis() - lastturn) / 1000) * 3.6;	// Расчет скорости, км/ч
+			lastturn	= millis();	// Запомнить время последнего оборота
+			distance	= distance + btc_config.wheel_length / 1000;	// Прибавляем длину колеса к дистанции при каждом обороте
+		}
 	}
 }

 bool sys_watch() {
-	if ((system_mode != SLEEP_MODE) && (bit_seted(btc_config.system_byte, AUTO_HEADLIGHT)) && (analog_to_byte(analogRead(LIGHT_SENSOR)) > btc_config.lux_light_on)) {	// Следилка за фарой
+	if ((system_mode != ALARM_MODE) && (system_mode != SLEEP_MODE) && (bit_seted(btc_config.system_byte, AUTO_HEADLIGHT)) && (analog_to_byte(analogRead(LIGHT_SENSOR)) > btc_config.lux_light_on)) {	// Следилка за фарой
 		digitalWrite(HEADLIGHT, LOW);
-	} else if (system_mode != SLEEP_MODE) {
+		digitalWrite(RED_BACK_LIGHT, LOW);
+	} else if ((system_mode != ALARM_MODE) && (system_mode != SLEEP_MODE)) {
+		analogWrite(RED_BACK_LIGHT, btc_config.bright_headlight);
 		analogWrite(HEADLIGHT, btc_config.bright_headlight);
 	}

-	if ((system_mode != SLEEP_MODE) && (bit_seted(btc_config.system_byte, AUTO_BACKLIGHT)) && (analog_to_byte(analogRead(LIGHT_SENSOR)) > btc_config.lux_backlight_on)) {	// Следилка за подсветкой экрана
+	if ((system_mode != ALARM_MODE) && (system_mode != SLEEP_MODE) && (bit_seted(btc_config.system_byte, AUTO_BACKLIGHT)) && (analog_to_byte(analogRead(LIGHT_SENSOR)) > btc_config.lux_backlight_on)) {	// Следилка за подсветкой экрана
 		digitalWrite(DISPLAY_LIGHT, LOW);
-	} else if (system_mode != SLEEP_MODE) {
+	} else if ((system_mode != ALARM_MODE) && (system_mode != SLEEP_MODE)) {
 		digitalWrite(DISPLAY_LIGHT, HIGH);
 	}

-	if ((system_mode != SLEEP_MODE) && (system_mode != SLEEP_MODE) && (bit_seted(btc_config.system_byte, AUTO_BACKLIGHT) == false) && (digitalRead(DISPLAY_LIGHT) == LOW)) {	// Чтобы при выключенной автоподсветке включилась посветка экрана
+	if ((system_mode != ALARM_MODE) && (system_mode != SLEEP_MODE) && (bit_seted(btc_config.system_byte, AUTO_BACKLIGHT) == false) && (digitalRead(DISPLAY_LIGHT) == LOW)) {	// Чтобы при выключенной автоподсветке включилась посветка экрана
 		digitalWrite(DISPLAY_LIGHT, HIGH);
 	}

-	if ((deep_sleep) && (system_mode == SPEED_MODE)) {
+	if ((bit_seted(security_byte, DEEP_SLEEP)) && (system_mode == SPEED_MODE)) {
 		return false;
 	}

-	if ((deep_sleep) && (analog_to_byte(analogRead(ACTION_BUTTON)) > (btc_config.button_ok_signal + 2)) && (analog_to_byte(analogRead(ACTION_BUTTON)) < (btc_config.button_ok_signal - 2))) {
+	if ((bit_seted(security_byte, DEEP_SLEEP)) && (analogRead(ACTION_BUTTON) > 5)) {
 		return false;
+	}
+
+	if ((system_mode == ALARM_MODE) && (!bit_seted(btc_config.system_byte, ALARM_WRITED))) {
+		digitalWrite(VIBRO_SENSOR, LOW);
+		sys_wait_delay	= 0;
+		set_bit(btc_config.system_byte, ALARM_WRITED);
+		WriteSysConfEEPROM(btc_config, 0);
+		delay(100);
+	}
+
+	if ((system_mode != ALARM_MODE) && (bit_seted(security_byte, WAIT_INPUT))) {	// Если был включён ввод пароля для выхода из сна
+		if (sys_wait_delay < WAIT_INPUT_DELAY) {
+			sys_wait_delay++;
+			delay(1);
+		} else {
+			unset_bit(security_byte, WAIT_INPUT);
+			system_mode	= ALARM_MODE;
+			set_bit(btc_config.system_byte, ALARM_STATE);
+			return false;
+		}
+	}
+
+	if (system_mode == ALARM_MODE) {
+		if (sys_wait_delay < BIP_ALARM_DELAY) {
+			sys_wait_delay++;
+		}
+
+		if (sys_wait_delay >= BIP_ALARM_DELAY) {
+			if (bit_seted(security_byte, BIP_FIRST_STAGE)) {
+				unset_bit(security_byte, BIP_FIRST_STAGE);
+				tone(BIP, 1000);
+				digitalWrite(EXT_ALARM, HIGH);
+				registerWrite(0);
+				digitalWrite(HEADLIGHT, LOW);
+				digitalWrite(RED_BACK_LIGHT, HIGH);
+				digitalWrite(LOWER_LIGHT, LOW);
+				digitalWrite(DISPLAY_LIGHT, HIGH);
+			} else {
+				set_bit(security_byte, BIP_FIRST_STAGE);
+				tone(BIP, 2000);
+				digitalWrite(EXT_ALARM, LOW);
+				registerWrite(255);
+				digitalWrite(HEADLIGHT, HIGH);
+				digitalWrite(RED_BACK_LIGHT, LOW);
+				digitalWrite(LOWER_LIGHT, HIGH);
+				digitalWrite(DISPLAY_LIGHT, LOW);
+			}
+
+			sys_wait_delay	= 0;
+		}
+
+		delay(1);
 	}

 	return true;
@@ -412,7 +503,8 @@
 	}

 	while ((wait_keys) && (analogRead(ACTION_BUTTON) > 5) && (delay_time < SWITCH_NEXT)) {	// Ожидание зажатия
-		delay(1);
+		if (system_mode == ALARM_MODE) sys_watch();	// При сигнализации sys_watch выдаёт задержку в 1 (и для того, чтобы сигнал пищалки не замедлялся)
+		else delay(1);
 		delay_time++;
 	}

@@ -464,7 +556,8 @@
 			case 1:	system_mode	= SPEED_MODE;
 					break;

-			case 2:	break;
+			case 2:	system_mode	= STOPWATCH_MODE;
+					break;

 			case 3:	lcd.clear();
 					lcd.print("Internal: ");
@@ -496,12 +589,14 @@
 		"Light settings",
 		"Time setting",
 		"Wheel length",
+		"Alarm dock",
 		"About system",
+		"Reset results",
 		"Back"
 	};

 	while ((system_mode	== SETTING_MODE) && (sys_watch())) {
-		switch (display_list(setting_array, 7)) {
+		switch (display_list(setting_array, 9)) {
 			case 0: if (digitalRead(LOWER_LIGHT) == HIGH) {
 						digitalWrite(LOWER_LIGHT, LOW);
 					} else {
@@ -537,7 +632,16 @@
 					changes	= true;
 					break;

-			case 5: about();
+			case 5:	count = input_int_number("Alarm if no dock", 0, 1, bit_seted(btc_config.system_byte, ALARM_WITHOUT_DOCK));
+					if (count != bit_seted(btc_config.system_byte, ALARM_WITHOUT_DOCK)) {
+						if (count) set_bit(btc_config.system_byte, ALARM_WITHOUT_DOCK);
+						else unset_bit(btc_config.system_byte, ALARM_WITHOUT_DOCK);
+
+						changes	= true;
+					}
+					break;
+
+			case 6: about();
 					break;

 			default:	system_mode	= MENU_MODE;
@@ -558,6 +662,7 @@

 	bool	key_pressed_ok	= true;

+	// while (system_mode	!= SPEED_MODE) {
 	while (true) {
 		if (key_pressed_ok) {
 			if (selected == on_display) {
@@ -753,6 +858,8 @@
 bool read_password() {
 	bool	wrong = false;

+	byte	key_now;
+
 	lcd.clear();			// Очистка экрана
 	lcd.print("Current password");

@@ -760,8 +867,15 @@
 	lcd.print("Password: ");

 	for (byte i = 0; i < 6; i++) {
-		if (btc_config.password[i]	!= key_pressed(true)) {
+		key_now	= key_pressed(true);
+
+		if (btc_config.password[i]	!= key_now) {
 			wrong = true;
+		}
+
+		if (key_now == 0) {
+			return false;
+			break;
 		}

 		lcd.print("*");
@@ -771,13 +885,17 @@

 	if (wrong) {
 		lcd.print("Incorrect!");
-		delay(2000);
+		delay_w(2000);
 		return	false;
 	} else {
-		lcd.print("Pass!");
-		delay(2000);
+		if (system_mode != ALARM_MODE) {
+			lcd.print("Pass!");
+			delay(2000);
+		}
+
 		return	true;
 	}
+

 	return false;
 }
@@ -807,12 +925,16 @@
 }

 void road_mode() {	// Режим спидометра
-	float	speed_old		= 0.1;
-
-	byte	turn_signals	= 0,
-			baterry_percent	= 0;
+	float	speed_old			= 0.1;
+
+	byte	turn_signals		= 0,
+			baterry_percent		= 0,
+			road_signals		= 0,
+			zero_speed_delay	= 0;

 	int		road_delay;
+
+	registerWrite(0);

 	lcd.clear();
 	lcd.print("km/h: ");
@@ -828,15 +950,37 @@
 	#endif

 	while (system_mode == SPEED_MODE) {
+
+		if ((speed_old == speed_now) && (zero_speed_delay >= ZERO_SPEED_DEL)) {	// Обнуление скорости, если какое-то время скорость не меняется
+			speed_now	= 0.0;
+			speed_old	= 0.0;
+			lcd.setCursor(5, 0);
+			lcd.print("0.0   ");
+		}
+
 		if (speed_old > speed_now) {
 			lcd.setCursor(5, 0);
-			lcd.print("		");
+			lcd.print("      ");
+		}
+
+		if ((bit_seted(btc_config.system_byte, RED_SPEED)) && (speed_old > speed_now) && ((speed_old - speed_now) >= SPEED_DEF)) {	// При сбросе скорости загорается красный
+			digitalWrite(RED_BACK_LIGHT, HIGH);
+			set_bit(road_signals, RED_STOP_SIGNAL);
+		}
+
+		if ((bit_seted(road_signals, RED_STOP_SIGNAL)) && (speed_now > speed_old)) {
+			unset_bit(road_signals, RED_STOP_SIGNAL);
+			if (bit_seted(btc_config.system_byte, AUTO_HEADLIGHT) && (analog_to_byte(analogRead(LIGHT_SENSOR)) > btc_config.lux_light_on))
+				analogWrite(RED_BACK_LIGHT, btc_config.bright_headlight);
+			else
+				digitalWrite(RED_BACK_LIGHT, LOW);
 		}

 		if (speed_old != speed_now) {
 			lcd.setCursor(5, 0);
 			lcd.print(speed_now);
 			speed_old	= speed_now;
+			zero_speed_delay	= 0;
 		}

 		/*TIME START*/
@@ -906,18 +1050,22 @@

 		}

-		for (road_delay	= 0; road_delay < 500; road_delay++) {
+		for (road_delay	= 0; road_delay < 250; road_delay++) {

 			switch(key_pressed(false)) {
 				case BUT_OK:		system_mode	= MENU_MODE;
 									break;

 				case BUT_UP:		if (bit_seted(turn_signals, TURN_SIGNAL_RIGHT)) {
-										turn_signals	= 0;
-										registerWrite(0);
+										unset_bit(turn_signals, TURN_SIGNAL_ON);
+										unset_bit(turn_signals, TURN_SIGNAL_RIGHT);
+										unset_bit(turn_signals, SIGNAL_RIGHT_ON);
+
+										registerWrite(RIGHT_TURN_LIGHT, 0);
 										lcd.setCursor(10, 1);
 										lcd.print("  ");
 									}
+
 									if (!bit_seted(turn_signals, TURN_SIGNAL_ON)) {
 										set_bit(turn_signals, TURN_SIGNAL_ON);
 										set_bit(turn_signals, TURN_SIGNAL_LEFT);
@@ -929,8 +1077,11 @@
 									break;

 				case BUT_DOWN:		if (bit_seted(turn_signals, TURN_SIGNAL_LEFT)) {
-										turn_signals	= 0;
-										registerWrite(0);
+										unset_bit(turn_signals, TURN_SIGNAL_ON);
+										unset_bit(turn_signals, TURN_SIGNAL_LEFT);
+										unset_bit(turn_signals, SIGNAL_LEFT_ON);
+
+										registerWrite(LEFT_TURN_LIGHT, 0);
 										lcd.setCursor(8, 1);
 										lcd.print("   ");
 									}
@@ -944,8 +1095,8 @@
 									}
 									break;

-				case BUT_SIGNAL:	tone(BIP, 2000, 250);
-									set_bit(turn_signals, BIP_SIGNAL);
+				case BUT_SIGNAL:	tone(BIP, 2000);
+									set_bit(road_signals, BIP_SIGNAL);
 									lcd.setCursor(9, 1);
 									lcd.write(SIGNAL_ICON);
 									break;
@@ -956,14 +1107,15 @@
 									lcd.setCursor(8, 1);
 									lcd.print("   ");
 								}
+
+								if (bit_seted(road_signals, BIP_SIGNAL)) {
+									lcd.setCursor(9, 1);
+									lcd.print(" ");
+									noTone(BIP);
+								}
 								break;
 			}
 			delay(1);
-		}
-
-		if (bit_seted(turn_signals, BIP_SIGNAL)) {
-			lcd.setCursor(9, 1);
-			lcd.print(" ");
 		}

 		if (bit_seted(turn_signals, TURN_SIGNAL_ON)) {
@@ -973,9 +1125,14 @@
 				set_bit(turn_signals, SECOND_ITERATION);
 			}
 		}
-	}
-
+
+		if (speed_now > 0.0)
+			zero_speed_delay++;	// Для обнуления скорости
+	}
+
+	noTone(BIP);
 	registerWrite(0);
+
 	while ((analogRead(ACTION_BUTTON) > 5) && (sys_watch()));	// Ожидание отжатия кнопки
 }

@@ -1369,19 +1526,21 @@
 }

 void delay_w(int delay_num) {
-	for (int	delay_count	= 0; ((delay_count < delay_num) && (sys_watch())); delay_count++, delay(1));
+	if (system_mode == ALARM_MODE)
+		for (int	delay_count	= 0; ((delay_count < delay_num) && (sys_watch())); delay_count++);
+	else
+		for (int	delay_count	= 0; ((delay_count < delay_num) && (sys_watch())); delay_count++, delay(1));
 }

 void system_sleep() {
-	byte	count;
+	sys_watch();

 	registerWrite(0);
-	digitalWrite(HEADLIGHT, LOW);
-	digitalWrite(DISPLAY_LIGHT, LOW);
-	digitalWrite(LOWER_LIGHT, LOW);
-	digitalWrite(RED_BACK_LIGHT, LOW);
-
-	deep_sleep	= true;
+	for (byte	i = 0; i != 13; digitalWrite(i, LOW), i++);
+
+	security_byte	= 0;
+
+	set_bit(security_byte, DEEP_SLEEP);

 	while (true) {
 		while ((sys_watch()) && (system_mode == SLEEP_MODE)) {
@@ -1417,18 +1576,26 @@
 		}

 		if (system_mode == SLEEP_MODE) {
-			deep_sleep	= false; // Выход из глубокого сна, чтобы можно было хоть что-нибудь ввести
+			unset_bit(security_byte, DEEP_SLEEP);	// Выход из глубокого сна, чтобы можно было хоть что-нибудь ввести
+			set_bit(security_byte, WAIT_INPUT);
+
+			sys_wait_delay	= 0;

 			while ((sys_watch()) && (analogRead(ACTION_BUTTON) > 5));

-			for (count	= 0; ((count < 3) && (!read_password())); count++);
-
-			if (count >= 3) {
+
+			if (!read_password()) {
 				set_bit(btc_config.system_byte, ALARM_STATE);
 				system_mode	= ALARM_MODE;
 				break;
 			} else {
-				break;
+				tone(BIP, 3000, 200);
+				delay(250);
+				tone(BIP, 3000, 200);
+
+				unset_bit(security_byte, WAIT_INPUT);
+				sys_wait_delay	= 0;
+				break;
 			}
 		}
 	}
@@ -1436,5 +1603,117 @@
 	if (system_mode	!= ALARM_MODE)
 		system_mode	= SPEED_MODE;

-	deep_sleep	= false;
+	security_byte	= 0;
+}
+
+void stopwatch() {
+	if (!stopwatch_run) {
+		stopwatch_hour	= 0;
+		stopwatch_min	= 0;
+		stopwatch_sec	= 0;
+
+		char stopwatch_menu[][15] = {
+			"Start",
+			"Back"
+		};
+
+		if (display_list(stopwatch_menu, 2) == 0) {
+			stopwatch_run	= true;
+			stopwatch_hour	= hour();
+			stopwatch_min	= minute();
+			stopwatch_sec	= second();
+		}
+	}
+
+	if (stopwatch_run) {
+		while ((system_mode == STOPWATCH_MODE) && (sys_watch())) {
+			char stopwatch_menu[][15] = {
+				"Stop",
+				"Speedometr",
+				"Back"
+			};
+
+			bool	pause	= false;
+
+			unsigned int	start_stopwatch_time = (unsigned int)((stopwatch_hour * 3600) + (stopwatch_min * 60) + stopwatch_sec),
+							now_stopwatch_time = 0;
+
+			float	now_hour_stopwatch,
+					now_min_stopwatch,
+					now_sec_stopwatch;
+
+			lcd.clear();
+			lcd.print("00:00:00");
+
+			while (key_pressed(false) != BUT_OK) {
+				now_stopwatch_time	= ((hour() * 3600.0) + (minute() * 60.0) + second()) - start_stopwatch_time;
+				now_hour_stopwatch	= (now_stopwatch_time / 3600.0);
+				now_min_stopwatch	= (now_hour_stopwatch - (byte)now_hour_stopwatch) * 60.0;
+				now_sec_stopwatch	= (now_min_stopwatch - (byte)now_min_stopwatch) * 60.0;
+
+				lcd.setCursor(0, 0);
+
+				if (now_hour_stopwatch < 10) {
+					lcd.print("0");
+				}
+
+				lcd.print((byte)now_hour_stopwatch);
+				lcd.setCursor(3, 0);
+
+				if (now_min_stopwatch < 10) {
+					lcd.print("0");
+				}
+
+				lcd.print((byte)now_min_stopwatch);
+				lcd.setCursor(6, 0);
+
+				if (now_sec_stopwatch < 10) {
+					lcd.print("0");
+				}
+
+				lcd.print((byte)now_sec_stopwatch);
+				delay_w(1000);
+			}
+
+			while (analogRead(ACTION_BUTTON) > 5);
+
+			switch (display_list(stopwatch_menu, 3)) {
+				case 0:	stopwatch_run	= false;
+						break;
+
+				case 1:	system_mode	= SPEED_MODE;
+
+				default:	break;
+			}
+		}
+	}
+}
+
+void alarm() {
+	lcd.clear();
+	while (!read_password());
+
+	noTone(BIP);
+	lcd.clear();
+	lcd.print("Unlocking...");
+
+	digitalWrite(LOWER_LIGHT, LOW);
+	digitalWrite(HEADLIGHT, LOW);
+	digitalWrite(RED_BACK_LIGHT, LOW);
+	registerWrite(0);
+
+	unset_bit(btc_config.system_byte, ALARM_STATE);
+	unset_bit(btc_config.system_byte, ALARM_WRITED);
+	digitalWrite(EXT_ALARM, HIGH);
+
+	sys_wait_delay	= 0;
+	security_byte	= 0;
+	system_mode		= SPEED_MODE;
+
+	WriteSysConfEEPROM(btc_config, 0);
+
+	delay(500);
+	tone(BIP, 3000, 200);
+	delay(250);
+	tone(BIP, 3000, 200);
 }


Capture: adjusted finetuning

Capture: adjusted finetuning

--- Capture/Capture.ino
+++ Capture/Capture.ino
@@ -5,7 +5,7 @@
 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 finetuning = 47; // fine-tuned with an oscilloscope
 static const unsigned int timerPreload = 65536 - systemHz / prescaler / (1 / bitLength) + finetuning;
 static const unsigned int timerPreload2 = 65536 - systemHz / prescaler / (1 / (bitLength / 2)) + finetuning;


Probationary Xtal sanity check

Probationary Xtal sanity check

--- V0p2_Main/V0p2_Main.ino
+++ V0p2_Main/V0p2_Main.ino
@@ -384,6 +384,42 @@
       }
     }
 //  posPOST(2, F("slow RTC clock OK"));
+#if 1 // Probationary Xtal sanity check
+  // Test low frequency oscillator vs main clock oscillator.
+  // Tests clock frequency with 15 ms nap in between for up to 30 cycles and panics if not within bounds.
+  // As of 2016-02-16, all working REV7s give count >= 120 and that fail to program via bootloader give count <= 119
+  // REV10 gives 119-120 (only one tested though)
+  {
+    static const uint8_t optimalLFClock = 122; // might be optimal...
+    static const uint8_t errorLFClock = 4; // max drift from allowed value
+    uint8_t count = 0;
+    for(uint8_t i = 0; ; i++) {
+      ::OTV0P2BASE::nap(WDTO_15MS);
+      ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      // wait for edge on xtal counter
+      // start counting cycles
+      // on next edge, stop
+          const uint8_t t0 = TCNT2;
+          while(t0 == TCNT2) {}
+          const uint8_t t01 = TCNT0;
+          const uint8_t t1 = TCNT2;
+          while(t1 == TCNT2) {}
+          const uint8_t t02 = TCNT0;
+          count = t02-t01;
+      }
+      // Check end conditions
+      if((count < optimalLFClock+errorLFClock) & (count > optimalLFClock-errorLFClock)) break;
+      if(i > 30) panic();
+    }
+    // optionally print value to debug
+#if 0 && defined(DEBUG)
+    DEBUG_SERIAL_PRINT_FLASHSTRING("Xtal cntr check: ");
+    DEBUG_SERIAL_PRINT(count);
+    DEBUG_SERIAL_PRINTLN();
+#endif
+  }
+#endif // Probationary Xtal sanity check
+
 #else
   DEBUG_SERIAL_PRINTLN_FLASHSTRING("(No xtal.)");
 #endif


finished hacking together fixes for the lib

--- WatSat_arduino_code.ino
+++ WatSat_arduino_code.ino
@@ -112,6 +112,7 @@

 void readall(){
   // SOLDERING NOTE: MAKE SURE TO LINE UP OUTPUTS!!
+  // can fix this by giving a board another var that describes it's input pin
   for (int i=0; i<(NUM_BOARDS/2); i++){
     master[i] = boards[i].readData(in0);
     master[i+1] = boards[i+1].readData(in1);


update the other chip

update the other chip

--- init.ino
+++ init.ino
@@ -86,7 +86,7 @@
 void queue_sys_threads() {
 	// device processes
 	thread_handler.queue(new MSGEQ7::UpdaterProcess(device_manager.getDevice<MSGEQ7>(0)));
-	//thread_handler.queue(new MSGEQ7::UpdaterProcess(device_manager.getDevice<MSGEQ7>(1)));
+	thread_handler.queue(new MSGEQ7::UpdaterProcess(device_manager.getDevice<MSGEQ7>(1)));

 	// system processes
 	//thread_handler.queue();


Discard wrong offline message

Discard wrong offline message

--- sketch_yunba/sketch_yunba.ino
+++ sketch_yunba/sketch_yunba.ino
@@ -20,6 +20,8 @@
 char g_username[24];
 char g_password[16];
 bool g_need_report = true;
+
+unsigned long g_connected_ms = 0;

 EthernetClient *g_net_client;
 MQTTClient *g_mqtt_client;
@@ -204,6 +206,11 @@
   bytes[length] = 0;
   Serial.println(bytes);

+  if (millis() - g_connected_ms < 5000) { // discard wrong offline message...
+    Serial.println("ds");
+    return;
+  }
+
   JsonObject& root = jsonBuffer.parseObject(bytes);
   if (!root.success()) {
     Serial.println("js");
@@ -272,6 +279,8 @@

 //  g_mqtt_client->subscribe(g_topic);
   g_mqtt_client->publish(",yali", g_devid); // set alias
+
+  g_connected_ms = millis();
 }

 void setup() {


Beta 1

Beta 1

--- ESPmeteo/src/pass.ino
+++ ESPmeteo/src/pass.ino
@@ -1,10 +1,10 @@
 void passWifi(char* &ssid,char* &wifipass)
 {
-  ssid = "TIM-18232399";
-  wifipass = "ObXtYwlWaqnXIJjqs2NbF6qP";
+  ssid = "******";
+  wifipass = "******";

 }
 void passWeb(String &webpass)
 {
-  webpass     = "admin";
+  webpass     = "******";
 }


fona: #define FONA_RX 5

fona: #define FONA_RX 5

--- FONAtest/FONAtest.ino
+++ FONAtest/FONAtest.ino
@@ -29,7 +29,8 @@
 */
 #include "Adafruit_FONA.h"

-#define FONA_RX 2
+//#define FONA_RX 2
+#define FONA_RX 5
 #define FONA_TX 3
 #define FONA_RST 4


Clean up serial messages in reconnect()

Clean up serial messages in reconnect()

--- GarHAge/GarHAge.ino
+++ GarHAge/GarHAge.ino
@@ -76,7 +76,7 @@
   delay(10);
   Serial.println();
   Serial.print("Connecting to ");
-  Serial.println(ssid);
+  Serial.print(ssid);

   WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, password);
@@ -90,9 +90,7 @@
     Serial.print(".");
   }

-  Serial.println("");
-  Serial.println("WiFi connected");
-  Serial.print("IP address: ");
+  Serial.print(" WiFi connected - IP address: ");
   Serial.println(WiFi.localIP());
 }


Fix MXChip sensor example

Fix MXChip sensor example

--- examples/arduino-mxchip-sensors/src/SensorStatus.ino
+++ examples/arduino-mxchip-sensors/src/SensorStatus.ino
@@ -3,7 +3,7 @@
 #include "IoT_DevKit_HW.h"
 #include "SystemVersion.h"
 #include "SystemTickCounter.h"
-#include "telemetry.h"
+#include "Telemetry.h"

 #define NUMSENSORS 5 // 5 sensors to display


clean up claw code

clean up claw code

--- dfrdb/dfrdb.ino
+++ dfrdb/dfrdb.ino
@@ -1,17 +1,27 @@
-/*
+/******************************************************************************
 dfrdb
 DFRobot Romeo Drive Bot
 Robot for MakerFaire Kansas City Arch Reactor booth
+drives just the claw - user Sabertooth for motor shield
+
+Pin connections:
+AIL:  (hold pin 0 for this use)
+ELE:  (hold pin 1 for this use)
+THR: 3
+RUD: 2
+power receiver off A5 since digital pins at 7.2V for servos

 Read RC signal pulse width by using interrupt then control servos of
-SparkFun robot arm (https://www.sparkfun.com/products/11524 and  https://www.sparkfun.com/products/11674 )
+SparkFun robot arm (https://www.sparkfun.com/products/11524 and
+https://www.sparkfun.com/products/11674 )

 DFRobot Romeo v2 controller board
 http://www.dfrobot.com/wiki/index.php/Romeo_V2-All_in_one_Controller_(R3)_(SKU:DFR0225)

-Board has pin config like Leonardo - plan to take advantage of fact that Leonardo has 4 hardware
-interrupts for my 4 controller signals; see http://www.arduino.cc/en/Reference/AttachInterrupt
+Board has pin config like Leonardo - plan to take advantage of fact that
+Leonardo has 4 hardware interrupts for my 4 controller signals;
+see http://www.arduino.cc/en/Reference/AttachInterrupt

 Helpful resources:
@@ -20,38 +30,56 @@
 http://rcarduino.blogspot.com/2012/01/how-to-read-rc-receiver-with.html
 https://beyondszine.wordpress.com/2013/10/31/part-ii-all-pin-interrupt-method-for-rc-in-arduino/

+Using HobbyKing Turnigy 5X 5 channel mini transmitter and receiver
+https://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idProduct=43854
+Right joystick for steering/speed, Left for claw (fwd/back for arm position,
+side to side to open/close claw)

-*/
+Will assume full range of signal (1000 - 2000), simplifies programming
+Extreme values outside range only occur with extremes of trim, which
+should be a rare outlier - will avoid the overhead of a constrain() operation

+******************************************************************************/
+
+/********************
+*** DECLARATIONS ****
+********************/
 #include <Servo.h>

 Servo wrist;
 Servo claw;

-const int WristInterrupt = 3; // interrupt 0 is on pin 3 for wrist (throttle on receiver)
-const int ClawInterrupt = 2;
-// interrupt 1 is on pin 2 for claw (rudder on receiver)
+const int WristInterruptPin = 3; // interrupt 0 is on pin 3 for wrist
+const int WristInterrupt = 0;
+const int ClawInterruptPin = 2;
+const int ClawInterrupt = 1;
 const int WristPin = 12;
 const int ClawPin = 13;

-volatile unsigned long wristPW = 0;   // volatile since will be in interrupt function
+volatile unsigned long wristPW = 0;   // volatile since will be in interrupt
+                                      // function
 volatile unsigned long clawPW = 0;
 volatile unsigned long wristTimer = 0;
 volatile unsigned long clawTimer = 0;
-volatile boolean flag = false;
+volatile boolean wristFlag = false;
+volatile boolean clawFlag = false;
 unsigned long wristPulse = 0;
 unsigned long clawPulse = 0;

 int clawAngle = 85;
-int clawMinDeadspaceLimit = 1400; // threshold for closing claw; want dead zone in center
-int clawMaxDeadspaceLimit = 1600; // threshold for opening claw
-const int minClawAngle = 35;      // limit travel to protect servo
+int ClawRDZ = 1450; // threshold for closing claw - right limit of dead zone
+int ClawLDZ = 1550; // threshold for opening claw
+const int minClawAngle = 5;      // limit travel to protect servo
 const int maxClawAngle = 135;

+/********************
+====== BODY =========
+********************/
+
 void setup() {
-  attachInterrupt(0, readWristInterrupt, CHANGE);  // pin 3 on Romeo  __ signal for wrist
-  attachInterrupt(1, readClawInterrupt, CHANGE);   // pin 2            __ signal for claw
+  attachInterrupt(WristInterrupt, readWristInterruptPin, CHANGE);
+  attachInterrupt(ClawInterrupt, readClawInterruptPin, CHANGE);
   wrist.attach(WristPin);
   claw.attach(ClawPin);
   wrist.write(90); // starting position
@@ -59,22 +87,30 @@
 } // end setup()

 void loop() {
-  // use flag to see if there is actually a new signal; may need to use more specific flags in future
-  if (flag){
-    noInterrupts(); // pause interrupts so pw signals are read faithfully and not changed part way during assignment
+  // use flag to see if there is actually a new signal
+  if (wristFlag){
+    noInterrupts(); // pause interrupts so pw signals are read faithfully
+                    // and not changed part way during assignment
     wristPulse = wristPW;
-    clawPulse = clawPW;
-    flag = false;
-    interrupts();   // there is a safer way to do this by saving and resorting settings register, but since I'm not using libraries should be OK
+    wristFlag = false;
+    interrupts();   // there is a safer way to do this by saving and restoring
+                    // settings register, but since I'm not using extensive
+                    // libraries should be OK

     wrist.writeMicroseconds(wristPulse);
-
-    // for claw want to open/close base on stick, but then hold position; so increment/decrement depending on position
+  }
+  if (clawFlag){
+    noInterrupts();
+    clawPulse = clawPW;
+    clawFlag = false;
+    interrupts();
+    // for claw want to open/close base on stick, but then hold position;
+    // so increment/decrement depending on position
     // and then keep that value if joystick centered
-    if (clawPulse < clawMinDeadspaceLimit){
+    if (clawPulse < ClawRDZ){
       clawAngle -= 1;
     }
-    else if (clawPulse > clawMaxDeadspaceLimit){
+    else if (clawPulse > ClawLDZ){
       clawAngle +=1;
     }
     clawAngle = constrain(clawAngle, minClawAngle, maxClawAngle);
@@ -82,26 +118,29 @@
   }
 } // end loop()

-void readWristInterrupt() {
-  // interrupt occurs on CHANGE - need to determine if now high (start of pulse) or low (end of pulse
-  if(digitalRead(WristInterrupt) == HIGH){
+/********************
+----- FUNCTIONS -----
+********************/
+
+void readWristInterruptPin() {
+  // interrupt occurs on CHANGE - need to determine if now high
+  // (start of pulse) or low (end of pulse
+  if(digitalRead(WristInterruptPin) == HIGH){
     wristTimer = micros();  // get time stamp for initiation of pulse
   }
   else{
     // pin must now be low - end of pulse; calculate pulse width
     wristPW = micros() - wristTimer;
-    flag = true;
+    wristFlag = true;
   }
-} // end readWristInterrupt()
+} // end readWristInterruptPin()

-void readClawInterrupt() {
-  // interrupt occurs on CHANGE - need to determine if now high (start of pulse) or low (end of pulse
-  if(digitalRead(ClawInterrupt) == HIGH){
-    clawTimer = micros();  // get time stamp for initiation of pulse
+void readClawInterruptPin()        // works just like wrist interrupt
+  if(digitalRead(ClawInterruptPin) == HIGH){
+    clawTimer = micros();
   }
-  else{
-    // pin must now be low - end of pulse; calculate pulse width
+  else{
     clawPW = micros() - clawTimer;
-    flag = true;
+    clawFlag = true;
   }
-} // end readClawInterrupt()
+} // end readClawInterruptPin()


Fixing ascii->petscii table for BASIC.

Fixing ascii->petscii table for BASIC.

git-svn-id: d8bfcd070c2c81762cca1b3912331324182919ba@17095 0d6f1817-ed0e-0410-87c9-987e46238f29


Sending SMS on initialization of weather station: lcd reporting adjusted


Loader: Fix bit numbers (comments only)

Loader: Fix bit numbers (comments only)

--- Loader/Loader.ino
+++ Loader/Loader.ino
@@ -8,8 +8,8 @@
 // Uno     Name   OUT bit            CD4021     74HC595 (U39)
 // ------- ------ -------- --------- ---------- ----------------
 // Pin 13  PORTB5 None     SER_DATA  11 SER INP 14 SER
-// Pin 12  PORTB4 6 vSync  SER_LATCH  0 PAR/SER None
-// Pin 11  PORTB3 7 hSync  SER_PULSE 10 CLOCK   11 SRCLK 12 RCLK
+// Pin 12  PORTB4 7 vSync  SER_LATCH  0 PAR/SER None
+// Pin 11  PORTB3 6 hSync  SER_PULSE 10 CLOCK   11 SRCLK 12 RCLK

 #define buttonDown  4
 #define buttonStart 16


Bugfix #1

Bugfix #1

faster ISR fuction

--- Arduino/DigitalFotografieHacks/ch04/LightBarrier/LightBarrier.ino
+++ Arduino/DigitalFotografieHacks/ch04/LightBarrier/LightBarrier.ino
@@ -10,13 +10,15 @@
 #define irLedPin 13
 #define irRcvPin 12

+int ledState = 0;
 /// --------------------------
 /// Custom ISR Timer Routine
 /// --------------------------
 void timerIsr()
 {
     // Toggle LED
-    digitalWrite( irLedPin, digitalRead( irLedPin ) ^ 1 );
+    digitalWrite( irLedPin, ledState);
+    ledState ^= 1;
 }

 void setup() {
@@ -37,4 +39,4 @@
     interrupts();
     delay(200);
   }
-}
+}


Smaller Variables

Smaller Variables

--- ComboKeypad/Keypad.ino
+++ ComboKeypad/Keypad.ino
@@ -18,7 +18,7 @@
 int input[numOfCombos]; //Saves what the user has clicked
 //
 const short int del = 10000;   //Timer(10s), if user inputs a number
-///////////////////////////and not inputs another within 10 seconds program will reset
+                               //and not inputs another within 10 seconds program will reset
 unsigned long time;
 short int buttonsRead[numOfButtons];   //Stores the "digitalRead()" of buttons[]
 const short int buttonStream = 2;   //Electricity for the buttons, didnt really know how to name this one so buttonStream it is
@@ -26,7 +26,7 @@
 const short int wrongLight = 8;   //Incorrect combo PIN, "Red" Light
 ///
 //Function prototyping
-void pressButton(int num, int digRead);
+void pressButton(short int num, short int digRead);
 void reset();
 void debug();
 //Function prototyping
@@ -113,7 +113,7 @@
 //////////////////////////////////////////////////////

 //Function pressButton, If user presses a Button
-void pressButton(int num, int digRead){
+void pressButton(short int num, short int digRead){
   if (digRead == 1 && doonce != true) { // If I hit a Button
    time = millis();   //Starts the 10 second timer
     input[count] = num + 1; // sends the number 1 into the array at the "count number"


Resolve version code merge conflict

Resolve version code merge conflict

--- wled00/wled00.ino
+++ wled00/wled00.ino
@@ -39,8 +39,8 @@
 #include "src/dependencies/e131/E131.h"

 //version in format yymmddb (b = daily build)
-#define VERSION 1808311
-char versionString[] = "0.7.1";
+#define VERSION 1809084
+char versionString[] = "0.8.0-a";

 //AP and OTA default passwords (change them!)
 char apPass[65] = "wled1234";


Cleaned up main test file a bit

Cleaned up main test file a bit

--- SDTest/SDTest.ino
+++ SDTest/SDTest.ino
@@ -1,20 +1,5 @@
 /*
-  SD card read/write
-
- This example shows how to read and write data to and from an SD card file
- The circuit:
- * SD card attached to SPI bus as follows:
- ** MOSI - pin 11
- ** MISO - pin 12
- ** CLK - pin 13
- ** CS - pin 4
-
- created   Nov 2010
- by David A. Mellis
- modified 9 Apr 2012
- by Tom Igoe
-
- This example code is in the public domain.
+Testing for RRD functionality and timeserver syncing

  */

@@ -26,17 +11,13 @@
 File myFile;
 File myFile1;
 File myFile2;
+
 RRDSD archiveRRD;//
 RRDSD archiveRRD2;
-
 RRDSD myRRD;//

-char timestampchar[19];
 char dataBuffer[3];
 char timestampBuffer[19];
-
-
-

 int average(int intArray[], int length)
 {
@@ -68,98 +49,24 @@
     return;
   }
   Serial.println(F("initialization done."));
-
-  //archiveRRD.resetFile();
-  //myRRD.resetFile();
-  //SD.remove("testArch.txt");
-  //SD.remove("testRRD.txt");
-
-  //archiveRRD.resetFile();
+
   archiveRRD2 = RRDSD("testArc2.txt",4,12,22,2);
   archiveRRD = RRDSD("testArch.txt",2,4,22,2,&archiveRRD2,&average);
   myRRD = RRDSD("testRRD.txt",1,2,22,2,&archiveRRD,&average);
+
+  // Remove these lines to not clear the file on reset
   myRRD.resetFile();
   archiveRRD.resetFile();
   archiveRRD2.resetFile();
-
-  //Serial.println(myRRD.getLength());
-  //Serial.println(myRRD.getArchiveLength());

-  //archiveRRD.log("50");
-  /*
-  myRRD.log("80");
-  myRRD.log("75");
-  myRRD.log("60");
-  myRRD.log("90");
-  myRRD.log("20");
-  //myRRD.log("90");
-  */
-
-
-
-
-
-//  // open the file. note that only one file can be open at a time,
-//  // so you have to close this one before opening another.
-//  myFile = SD.open("test.txt", FILE_WRITE);
-//
-//  // if the file opened okay, write to it:
-//  if (myFile) {
-//    myFile.seek(0);
-//    Serial.print("Position: ");
-//    Serial.println(myFile.position());
-//
-//    Serial.print("Writing to test.txt...");
-//
-//    myFile.println("testing 1, 2, 3");
-//	// close the file:
-//
-//    Serial.println("done.");
-//    Serial.print("Position: ");
-//    Serial.println(myFile.position());
-//    myFile.close();
-//  } else {
-//    // if the file didn't open, print an error:
-//    Serial.println("error opening test.txt");
-//  }
-//
-//  // re-open the file for reading:
-//  myFile = SD.open("test.txt");
-//  if (myFile) {
-//    Serial.println("test.txt:");
-//
-//    // read from the file until there's nothing else in it:
-//    while (myFile.available()) {
-//    	Serial.write(myFile.read());
-//    }
-//    // close the file:
-//    myFile.close();
-//  } else {
-//  	// if the file didn't open, print an error:
-//    Serial.println("error opening test.txt");
-//  }
 }

 void loop()
 {
-
-//  String timestamp=String(hour());
-//  timestamp+=":";
-//  timestamp+=String(minute());
-//  timestamp+=":";
-//  timestamp+=String(second());
-//  timestamp+=",";
-//  timestamp+=String(day());
-//  timestamp+="/";
-//  timestamp+=String(month());
-//  timestamp+="/";
-//  timestamp+=String(year());
-//  char timestampchar[timestamp.length()+1];
-//  timestamp.toCharArray(timestampchar, timestamp.length()+1);
-   getTimestamp(&timestampchar[0]);
-  Serial.println(timestampchar);
+  getTimestamp(&timestampBuffer[0]);
+  Serial.println(timestampBuffer);
   //Serial.print(F("freeMemory()="));Serial.println(freeMemory());
-    boolean archive = myRRD.log("50",&timestampchar[0], &dataBuffer[0], &timestampBuffer[0]);
+    boolean archive = myRRD.log("50",&timestampBuffer[0], &dataBuffer[0], &timestampBuffer[0]);
   if (archive){
     //Serial.print(F("freeMemory()="));Serial.println(freeMemory());
     //Serial.print(F("databuffer: ")); Serial.println(dataBuffer);
@@ -170,9 +77,7 @@
    archiveRRD2.log(&dataBuffer[0],&timestampBuffer[0]);
   }
   }
-
-  //delete[] dataBuffer;
-  //delete[] timestampBuffer;
+

   Serial.print(F("freeMemory()="));Serial.println(freeMemory());

@@ -194,8 +99,6 @@
   }
   else Serial.println("failed");

-
-
   myFile = SD.open("testRRD.txt");
   if(myFile){
     while (myFile.available()) {
@@ -204,10 +107,9 @@
     myFile.close();
   }
   else Serial.println("failed");
+
+  // delay for readability in Serial
   delay(3000);
-
-
-
 }

 void getTimestamp(char *timestamp){
@@ -238,14 +140,12 @@
    timestamp[12]='0';
  }
   sprintf(timestamp+15, "%d", year(t));
-
-
+
  timestamp[2]=':';
  timestamp[5]=':';
  timestamp[8]=',';
  timestamp[11]='/';
- timestamp[14]='/';
-
+ timestamp[14]='/';
 }


Removed unnecessary condition. Reformatted to ClangFormat.

--- src/_web.ino
+++ src/_web.ino
@@ -168,7 +168,8 @@
       const char *hostname = settings[KEY_HOSTNAME];
       if (os_strcmp(cfg.hostname, hostname) != 0) {
         os_strcpy(cfg.hostname, hostname);
-        cfg.mqtt_ha_is_discovered = false; // Re-register the device via MQTT HASS Autodiscovery
+        cfg.mqtt_ha_is_discovered =
+            false; // Re-register the device via MQTT HASS Autodiscovery
         needRestart = true;
       }
     }
@@ -212,7 +213,8 @@
       if (os_strcmp(cfg.mqtt_state_topic, mqtt_state_topic) != 0) {
         os_strcpy(cfg.mqtt_state_topic, mqtt_state_topic);
         mqtt_changed = true;
-        cfg.mqtt_ha_is_discovered = false; // Re-register the device via MQTT HASS Autodiscovery
+        cfg.mqtt_ha_is_discovered =
+            false; // Re-register the device via MQTT HASS Autodiscovery
       }
     }

@@ -221,7 +223,8 @@
       if (os_strcmp(cfg.mqtt_command_topic, mqtt_command_topic) != 0) {
         os_strcpy(cfg.mqtt_command_topic, mqtt_command_topic);
         mqtt_changed = true;
-        cfg.mqtt_ha_is_discovered = false; // Re-register the device via MQTT HASS Autodiscovery
+        cfg.mqtt_ha_is_discovered =
+            false; // Re-register the device via MQTT HASS Autodiscovery
       }
     }

@@ -230,7 +233,8 @@
       if (os_strcmp(cfg.mqtt_lwt_topic, mqtt_lwt_topic) != 0) {
         os_strcpy(cfg.mqtt_lwt_topic, mqtt_lwt_topic);
         mqtt_changed = true;
-        cfg.mqtt_ha_is_discovered = false; // Re-register the device via MQTT HASS Autodiscovery
+        cfg.mqtt_ha_is_discovered =
+            false; // Re-register the device via MQTT HASS Autodiscovery
       }
     }

@@ -292,9 +296,7 @@
       uint8_t powerup_mode = (os_strlen(settings[KEY_POWERUP_MODE]) > 0)
                                  ? settings[KEY_POWERUP_MODE]
                                  : POWERUP_MODE;
-      if (cfg.powerup_mode != powerup_mode) {
-        cfg.powerup_mode = powerup_mode;
-      }
+      cfg.powerup_mode = powerup_mode;
     }

     // Reconnect to the MQTT broker due to new settings
@@ -320,8 +322,9 @@
   }

   if (root.containsKey(KEY_COLOR)) {
-    AiLight->setColor(root[KEY_COLOR][KEY_COLOR_R], root[KEY_COLOR][KEY_COLOR_G],
-                     root[KEY_COLOR][KEY_COLOR_B]);
+    AiLight->setColor(root[KEY_COLOR][KEY_COLOR_R],
+                      root[KEY_COLOR][KEY_COLOR_G],
+                      root[KEY_COLOR][KEY_COLOR_B]);
   }

   if (root.containsKey(KEY_WHITE)) {
@@ -412,11 +415,15 @@
     AsyncWebServerResponse *response =
         request->beginResponse_P(200, HTTP_MIMETYPE_HTML, html_gz, html_gz_len);

-    response->addHeader(HTTP_HEADER_CONTENT_ENCODING, HTTP_HEADER_CONTENT_ENCODING_VALUE);
+    response->addHeader(HTTP_HEADER_CONTENT_ENCODING,
+                        HTTP_HEADER_CONTENT_ENCODING_VALUE);
     response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
-    response->addHeader(HTTP_HEADER_XSS_PROTECTION, HTTP_HEADER_XSS_PROTECTION_VALUE);
-    response->addHeader(HTTP_HEADER_CONTENT_TYPE_OPTIONS, HTTP_HEADER_CONTENT_TYPE_OPTIONS_VALUE);
-    response->addHeader(HTTP_HEADER_FRAME_OPTIONS, HTTP_HEADER_FRAME_OPTIONS_VALUE);
+    response->addHeader(HTTP_HEADER_XSS_PROTECTION,
+                        HTTP_HEADER_XSS_PROTECTION_VALUE);
+    response->addHeader(HTTP_HEADER_CONTENT_TYPE_OPTIONS,
+                        HTTP_HEADER_CONTENT_TYPE_OPTIONS_VALUE);
+    response->addHeader(HTTP_HEADER_FRAME_OPTIONS,
+                        HTTP_HEADER_FRAME_OPTIONS_VALUE);

     request->send(response);
   });
@@ -478,66 +485,66 @@
   if (cfg.api) {

     // 'Light' API Endpoint
-    server->on(HTTP_APIROUTE_LIGHT, HTTP_GET,
-               [](AsyncWebServerRequest *request) {
-                 // Check for appropriate HTTP method
-                 if (request->method() != HTTP_GET) {
-                   AsyncWebServerResponse *response =
-                       request->beginResponse(405, HTTP_MIMETYPE_JSON);
-                   response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
-                   response->addHeader(HTTP_HEADER_ALLOW, HTTP_HEADER_ALLOW_GET_PATCH);
-                   request->send(response);
-
-                   return;
-                 }
-
-                 if (!authorizeAPI(request)) {
-                   return;
-                 }
-
-                 // Send response
-                 DynamicJsonBuffer jsonBuffer;
-                 JsonObject &root = jsonBuffer.createObject();
-                 createStateJSON(root);
-
-                 char buffer[root.measureLength() + 1];
-                 root.printTo(buffer, sizeof(buffer));
-
-                 AsyncWebServerResponse *response =
-                     request->beginResponse(200, HTTP_MIMETYPE_JSON, buffer);
-                 response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
-                 request->send(response);
-               });
+    server->on(
+        HTTP_APIROUTE_LIGHT, HTTP_GET, [](AsyncWebServerRequest *request) {
+          // Check for appropriate HTTP method
+          if (request->method() != HTTP_GET) {
+            AsyncWebServerResponse *response =
+                request->beginResponse(405, HTTP_MIMETYPE_JSON);
+            response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
+            response->addHeader(HTTP_HEADER_ALLOW, HTTP_HEADER_ALLOW_GET_PATCH);
+            request->send(response);
+
+            return;
+          }
+
+          if (!authorizeAPI(request)) {
+            return;
+          }
+
+          // Send response
+          DynamicJsonBuffer jsonBuffer;
+          JsonObject &root = jsonBuffer.createObject();
+          createStateJSON(root);
+
+          char buffer[root.measureLength() + 1];
+          root.printTo(buffer, sizeof(buffer));
+
+          AsyncWebServerResponse *response =
+              request->beginResponse(200, HTTP_MIMETYPE_JSON, buffer);
+          response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
+          request->send(response);
+        });

     // 'About' API Endpoint
-    server->on(HTTP_APIROUTE_ABOUT, HTTP_ANY,
-               [](AsyncWebServerRequest *request) {
-                 // Only allow HTTP_GET method
-                 if (request->method() != HTTP_GET) {
-                   AsyncWebServerResponse *response =
-                       request->beginResponse(405, HTTP_MIMETYPE_JSON);
-                   response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
-                   response->addHeader(HTTP_HEADER_ALLOW, HTTP_HEADER_ALLOW_GET);
-                   request->send(response);
-
-                   return;
-                 }
-
-                 if (!authorizeAPI(request)) {
-                   return;
-                 }
-
-                 DynamicJsonBuffer jsonBuffer;
-                 JsonObject &root = jsonBuffer.createObject();
-                 createAboutJSON(root);
-
-                 AsyncResponseStream *response =
-                     request->beginResponseStream(HTTP_MIMETYPE_JSON);
-                 response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
-                 root.printTo(*response);
-
-                 request->send(response);
-               });
+    server->on(
+        HTTP_APIROUTE_ABOUT, HTTP_ANY, [](AsyncWebServerRequest *request) {
+          // Only allow HTTP_GET method
+          if (request->method() != HTTP_GET) {
+            AsyncWebServerResponse *response =
+                request->beginResponse(405, HTTP_MIMETYPE_JSON);
+            response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
+            response->addHeader(HTTP_HEADER_ALLOW, HTTP_HEADER_ALLOW_GET);
+            request->send(response);
+
+            return;
+          }
+
+          if (!authorizeAPI(request)) {
+            return;
+          }
+
+          DynamicJsonBuffer jsonBuffer;
+          JsonObject &root = jsonBuffer.createObject();
+          createAboutJSON(root);
+
+          AsyncResponseStream *response =
+              request->beginResponseStream(HTTP_MIMETYPE_JSON);
+          response->addHeader(HTTP_HEADER_SERVER, SERVER_SIGNATURE);
+          root.printTo(*response);
+
+          request->send(response);
+        });
   }

   // Handle unknown URI