Buzzer eingebaut

Buzzer eingebaut

--- BrewDuino.ino
+++ BrewDuino.ino
@@ -38,9 +38,9 @@
 //Fehler festlegen
 #define ERROR_NO_THERMOMETER 1

-int errors = 0;
-
-//Display einrichten
+int errors = 0, lastErrors = 0;
+
+//Display einrichten
 //Old LCD5110 lcd(8, 9, 10, 11, 12);
 LCD5110 lcd(PIN_LCD_SCLK, PIN_LCD_MOSI, PIN_LCD_DC, PIN_LCD_RST, PIN_LCD_SCE);
 extern uint8_t SmallFont[];
@@ -56,7 +56,7 @@

 //Main FSM und States definieren
 State stateMenu = State(enterMenu, menu, leaveMenu);
-State stateError = State(error);
+State stateError = State(enterError, error, NULL);
 State stateMaischen = State(enterMaischen, maischen, leaveMaischen);
 State stateKochen = State(enterKochen, kochen, leaveKochen);
 State stateHeizen = State(enterHeizen, heizen, leaveHeizen);
@@ -69,33 +69,33 @@
 State stateEnterAnzahlRasten = State(forceFirstDisplay, enterAnzahlRasten, NULL);
 State stateDefineRast = State(forceFirstDisplay, defineRast, NULL);
 State stateEnterAbmaischTemp = State(forceFirstDisplay, enterAbmaischTemp, NULL);
-State stateReachEinmaischTemp = State(prepareReachEinmaischTemp,reachEinmaischTemp,NULL);
+State stateReachEinmaischTemp = State(prepareReachEinmaischTemp, reachEinmaischTemp, NULL);
 State stateEinmaischen = State(einmaischen);
 State stateReachRastTemp = State(reachRastTemp);
-State stateWaitRastDauer = State(prepareRastDauer,waitRastDauer,NULL);
-State stateReachAbmaischTemp = State(NULL,reachAbmaischTemp,NULL);
+State stateWaitRastDauer = State(prepareRastDauer, waitRastDauer, NULL);
+State stateReachAbmaischTemp = State(NULL, reachAbmaischTemp, NULL);
 FSM fsmMaischen = FSM(stateEnterEinmaischTemp);

 //Kochen FSM und States definieren
 State stateEnterKochzeit = State(forceFirstDisplay, enterKochzeit, NULL);
 State stateEnterAnzahlHopfengaben = State(forceFirstDisplay, enterAnzahlHopfengaben, NULL);
 State stateDefineHopfengaben = State(forceFirstDisplay, defineHopfengaben, NULL);
-State stateDoKochen = State(enterDoKochen,doKochen, NULL);
+State stateDoKochen = State(enterDoKochen, doKochen, NULL);
 FSM fsmKochen = FSM(stateEnterKochzeit);

 //Timer FSM und States definieren
-State stateEnterTimerTime = State(forceFirstDisplay,enterTimerTime,NULL);
-State stateDoTimer = State(prepareDoTimer,doTimer,NULL);
+State stateEnterTimerTime = State(forceFirstDisplay, enterTimerTime, NULL);
+State stateDoTimer = State(prepareDoTimer, doTimer, NULL);
 FSM fsmTimer = FSM(stateEnterTimerTime);

 //Variablen initialisieren

 int selectedMenuEntry = 0, menuOffset = 0;
 //char* menuEntrys[] = {"Maischen","Kochen","Heizen","Timer","Einstell."};
-char* menuEntrys[] = {"Maischen","Kochen","Heizen","Timer"};
-float lastTemps[TMP_SMOOTH]={0,0,0,0,0};
+char* menuEntrys[] = {"Maischen", "Kochen", "Heizen", "Timer"};
+float lastTemps[TMP_SMOOTH] = {0, 0, 0, 0, 0};
 float tempTotal = 0;
-int temp, lastTemp, sollTemp, lastHeatCheckTemp, tmpIndex=0;
+int temp, lastTemp, sollTemp, lastHeatCheckTemp, tmpIndex = 0;

 unsigned long lastRest = -1;
 unsigned long dauer = 0;
@@ -107,7 +107,7 @@
 bool isHeating;

 void setup()   {
-  //LCD Setup
+  //LCD Setup
   lcd.InitLCD();
   lcd.clrScr();
   lcd.setFont(SmallFont);
@@ -115,115 +115,130 @@
   printRow(PROG_NAME" "PROG_VERSION, LEFT, 16);
   printRow(COPYRIGHT, LEFT, 32);
   printRow(COPYRIGHT2, RIGHT, 40);
-
-  #if SERIAL != N
-    Serial.begin(9600);
-  #endif
-
+
+#if SERIAL != N
+  Serial.begin(9600);
+#endif
+
   pinMode(PIN_BG_LIGHT, OUTPUT);
   pinMode(PIN_HEATER, OUTPUT);
-  digitalWrite(PIN_BG_LIGHT, HIGH);
+  digitalWrite(PIN_BG_LIGHT, LOW);
   digitalWrite(PIN_HEATER, HIGH);
-
+
   //Encoder und Interrupt Setup
   encoder = new ClickEncoder(PIN_ROTARY_1, PIN_ROTARY_2, PIN_ROTARY_BUTTON, 4);
   encoder->setAccelerationEnabled(false);
   Timer1.initialize(1000);
-  Timer1.attachInterrupt(timerIsr);
-
+  Timer1.attachInterrupt(timerIsr);
+
   //Temperaturen und Heizung initialisieren
   setSollTemp(MIN_TEMP);
   isHeating = false;
-
-  //Temperatursensor initialisieren
+
+ initThermometer();
+
+  checkForErrors();
+  delay(2000);
+  if (errors > 0) {
+    fsmMain.immediateTransitionTo(stateError);
+    alarm();
+  } else {
+    fsmMain.immediateTransitionTo(stateMenu);
+  }
+}
+
+void loop() {
+  fsmMain.update();
+
+  ClickEncoder::Button b = encoder->getButton();
+  if (b != ClickEncoder::Open) {
+    if ( b == ClickEncoder::Held ) {
+      fsmMain.transitionTo(stateMenu);
+    }
+  }
+
+  readTemperature(false);
+  checkHeatingStatus(false);
+  addTemperature(false);
+
+  if (alertMillis != 0)
+    doAlert();
+}
+
+void initThermometer(){
   sensors.begin();
   sensors.getAddress(thermometer, 0);
   // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
   sensors.setResolution(thermometer, 9);
   //Init Temp array
-  for(int i = 0; i < NUMITEMS(menuEntrys); i++)
+  for (int i = 0; i < TMP_SMOOTH; i++)
     readTemperature(true);
-  //---------------------------------------------------------------
-  checkForErrors();
-  delay(2000);
-  if(errors > 0)
-    fsmMain.immediateTransitionTo(stateError);
-}
-
-void loop() {
-  fsmMain.update();
-
-  ClickEncoder::Button b = encoder->getButton();
-  if (b != ClickEncoder::Open) {
-    if( b == ClickEncoder::Held ){
-      fsmMain.transitionTo(stateMenu);
-    }
-  }
-
-  readTemperature(false);
-  checkHeatingStatus(false);
-  addTemperature(false);
-
-  if(alertMillis != 0)
-    doAlert();
-}
-
-void enterMenu(){
+}
+
+void enterMenu() {
   encoder->setAccelerationEnabled(false);
   //selectedMenuEntry = 0;
   //menuOffset = 0;
   setSollTemp(MIN_TEMP);
   checkHeatingStatus(true);
-  clrScr(true,false);
+  clrScr(true, false);
   printRow(PROG_NAME" "PROG_VERSION, CENTER, 0);
   forceFirstDisplay();
 }

-void leaveMenu(){
+void leaveMenu() {
   encoder->setAccelerationEnabled(true);
 }

-void enterMaischen(){
+void enterError() {
+  setSollTemp(MIN_TEMP);
+  checkHeatingStatus(true);
+  clrScr(true, true);
+  printRow("--Fehler--", CENTER, 0);
+  forceFirstDisplay();
+}
+
+void enterMaischen() {
   encoder->setAccelerationEnabled(true);
   fsmMaischen.immediateTransitionTo(stateEnterEinmaischTemp);
-  clrScr(true,false);
-  printRow("--Maischen--",CENTER,0);
-}
-
-void leaveMaischen(){
-  setSollTemp(MIN_TEMP);
-}
-
-void enterKochen(){
+  clrScr(true, false);
+  printRow("--Maischen--", CENTER, 0);
+}
+
+void leaveMaischen() {
+  setSollTemp(MIN_TEMP);
+}
+
+void enterKochen() {
   encoder->setAccelerationEnabled(true);
   setSollTemp(100);
   checkHeatingStatus(true);
   fsmKochen.immediateTransitionTo(stateEnterKochzeit);
-  clrScr(true,false);
-  printRow("--Kochen--",CENTER,0);
-}
-
-void leaveKochen(){
-  setSollTemp(MIN_TEMP);
-}
-
-void enterHeizen(){
+  clrScr(true, false);
+  printRow("--Kochen--", CENTER, 0);
+}
+
+void leaveKochen() {
+  setSollTemp(MIN_TEMP);
+}
+
+void enterHeizen() {
   encoder->setAccelerationEnabled(true);
   setSollTemp(temp);
-  clrScr(true,false);
-  printRow("--Heizen--",CENTER,0);
+  clrScr(true, false);
+  printRow("--Heizen--", CENTER, 0);
   forceFirstDisplay();
 }

-void leaveHeizen(){
-  setSollTemp(MIN_TEMP);
-}
-
-void enterTimer(){
+void leaveHeizen() {
+  setSollTemp(MIN_TEMP);
+}
+
+void enterTimer() {
   encoder->setAccelerationEnabled(true);
   fsmTimer.immediateTransitionTo(stateEnterTimerTime);
-  clrScr(true,false);
-  printRow("--Timer--",CENTER,0);
+  clrScr(true, false);
+  printRow("--Timer--", CENTER, 0);
 }

 /*void enterSettings(){
@@ -232,143 +247,153 @@

 void menu() {
   encoderValue = encoder->getValue();
-
-  if(encoderValue != 0 || first){
+
+  if (encoderValue != 0 || first) {
     first = false;
-    if(encoderValue > 0)
-      for(int i = 0; i < encoderValue; i++)
+    if (encoderValue > 0)
+      for (int i = 0; i < encoderValue; i++)
         menuUp();
-    if(encoderValue < 0)
-      for(int i = encoderValue; i < 0; i++)
+    if (encoderValue < 0)
+      for (int i = encoderValue; i < 0; i++)
         menuDown();
-
-    if(selectedMenuEntry == 0+menuOffset)
+
+    clrScr(false, false);
+    if (selectedMenuEntry == 0 + menuOffset)
       printRow("=>", 10, 16);
-    lcd.print(menuEntrys[0+menuOffset], 25,16);
-    if(selectedMenuEntry == 1+menuOffset)
+    lcd.print(menuEntrys[0 + menuOffset], 25, 16);
+    if (selectedMenuEntry == 1 + menuOffset)
       printRow("=>", 10, 24);
-    lcd.print(menuEntrys[1+menuOffset], 25,24);
-  }
-
-  if(buttonClicked()){
-    if(selectedMenuEntry == 0)
+    lcd.print(menuEntrys[1 + menuOffset], 25, 24);
+  }
+
+  if (buttonClicked()) {
+    if (selectedMenuEntry == 0)
       fsmMain.transitionTo(stateMaischen);
-    if(selectedMenuEntry == 1)
+    if (selectedMenuEntry == 1)
       fsmMain.transitionTo(stateKochen);
-    if(selectedMenuEntry == 2)
+    if (selectedMenuEntry == 2)
       fsmMain.transitionTo(stateHeizen);
-    if(selectedMenuEntry == 3)
+    if (selectedMenuEntry == 3)
       fsmMain.transitionTo(stateTimer);
     //if(selectedMenuEntry == 4)
-      //fsmMain.transitionTo(stateSettings);
-      //alarm();
-  }
+    //fsmMain.transitionTo(stateSettings);
+    //alarm();
+  }
 }

 void menuUp() {
-	selectedMenuEntry -= 1;
-	if(selectedMenuEntry < 0)
-		selectedMenuEntry = 0;
-	if(selectedMenuEntry < menuOffset)
-		menuOffset--;
-}
-
+  selectedMenuEntry -= 1;
+  if (selectedMenuEntry < 0)
+    selectedMenuEntry = 0;
+  if (selectedMenuEntry < menuOffset)
+    menuOffset--;
+}
+
 void menuDown() {
-	selectedMenuEntry += 1;
-	if(selectedMenuEntry > NUMITEMS(menuEntrys)-1)
-		selectedMenuEntry = NUMITEMS(menuEntrys)-1;
-	if(selectedMenuEntry > menuOffset+1)
-		menuOffset += 1;
-}
-
-void error(){
-  //Fehler anzeigen
-}
-
-void maischen(){
+  selectedMenuEntry += 1;
+  if (selectedMenuEntry > NUMITEMS(menuEntrys) - 1)
+    selectedMenuEntry = NUMITEMS(menuEntrys) - 1;
+  if (selectedMenuEntry > menuOffset + 1)
+    menuOffset += 1;
+}
+
+void error() {
+  if(lastErrors != errors || first){
+
+    lastErrors = errors;
+
+    if(errors >= ERROR_NO_THERMOMETER){
+      errors -= ERROR_NO_THERMOMETER;
+      lcd.print("Kein Therm.", 0, 16);
+    }
+
+  }
+}
+
+void maischen() {
   fsmMaischen.update();
 }

-void kochen(){
+void kochen() {
   fsmKochen.update();
 }

-void heizen(){
+void heizen() {
   doHeizen();
 }

-void timer(){
+void timer() {
   fsmTimer.update();
 }
 /*void settings(){
   fsmSettings.update();
 }*/

-void readTemperature(bool force){
+void readTemperature(bool force) {
   //Gelesen wir nur alle 2,5 sec.
-  if(millis()-lastTempMillis > 2500 || force){
+  if (millis() - lastTempMillis > 2500 || force) {
     lastTempMillis = millis();
-
+
     //Aktuelle Temperatur lesen.
-    sensors.requestTemperatures();
-
+    sensors.requestTemperatures();
+
     //Letzte Temperatur dieser Position aus Summe nehmen
     tempTotal -= lastTemps[tmpIndex];
     //Neue Temperatur dieser Position schreiben
     lastTemps[tmpIndex] = sensors.getTempC(thermometer);
     //Neue Temperatur dieser Position zur Summe hinzunehmen und Position erhöhen
     tempTotal += lastTemps[tmpIndex++];
-
+
     //Durchschnitt errechnen
     temp = tempTotal / TMP_SMOOTH;
-
+
     //Ggf. Position korrigieren
-    if(tmpIndex >= TMP_SMOOTH)
+    if (tmpIndex >= TMP_SMOOTH)
       tmpIndex = 0;
   }
 }

-void setSollTemp(int t){
+void setSollTemp(int t) {
   sollTemp = t;
   checkHeatingStatus(true);
 }

-void checkHeatingStatus(bool force){
-  if(temp != lastHeatCheckTemp || force){
+void checkHeatingStatus(bool force) {
+  if (temp != lastHeatCheckTemp || force) {
     lastHeatCheckTemp = temp;
     //Ein oder ausschalten des Heizelementes.
     //Evtl. schaltfrequent sicherstellen
-
+
     //-127 heißt kein Thermometer
-    if(temp != -127){
-      if(isHeating){
-        if(temp >= sollTemp + TEMP_OFFSET)
+    if (temp != -127) {
+      if (isHeating) {
+        if (temp >= sollTemp + TEMP_OFFSET)
           turnOffHeating();
       } else {
-         if(temp <= sollTemp - TEMP_OFFSET)
+        if (temp <= sollTemp - TEMP_OFFSET)
           turnOnHeating();
       }
     }
   }
 }

-void turnOffHeating(){
+void turnOffHeating() {
   //Toggle Relais
   isHeating = false;
-  digitalWrite(PIN_HEATER,HIGH);
+  digitalWrite(PIN_HEATER, HIGH);
   addTemperature(true);
 }

-void turnOnHeating(){
+void turnOnHeating() {
   //Toggle Relais
   isHeating = true;
-  digitalWrite(PIN_HEATER,LOW);
+  digitalWrite(PIN_HEATER, LOW);
   addTemperature(true);
 }

 void addTemperature(boolean force) {
   //Wenn die aktuelle Temperatur nciht der angezeigten entspricht, aktualisieren.
-  if(temp != lastTemp || force){
+  if (temp != lastTemp || force) {
     lastTemp = temp;
     lcd.clrRow(5);
     String s = (isHeating ? "H " : "");
@@ -376,83 +401,83 @@
     s += temp;
     s += "~ C";
     char buf[14];
-    s.toCharArray(buf,14);
+    s.toCharArray(buf, 14);
     printRow(buf, RIGHT, 40);
   }
 }

-void clrScr(bool clearFirst, bool clearLast){
-  if(clearFirst && clearLast){
+void clrScr(bool clearFirst, bool clearLast) {
+  if (clearFirst && clearLast) {
     lcd.clrScr();
     return;
   }
-  if(clearFirst){
+  if (clearFirst) {
     lcd.clrRow(0);
   }
   lcd.clrRow(1);
   lcd.clrRow(2);
   lcd.clrRow(3);
   lcd.clrRow(4);
-  if(clearLast){
+  if (clearLast) {
     lcd.clrRow(5);
   }
 }

-void printRow(char* text, int pos, int row){
-  if(row > 5)
+void printRow(char* text, int pos, int row) {
+  if (row > 5)
     row = row / 8;
   lcd.clrRow(row);
-  lcd.print(text, pos, row*8);
+  lcd.print(text, pos, row * 8);
 }

 void timerIsr() {
   encoder->service();
 }

-void forceFirstDisplay(){
+void forceFirstDisplay() {
   first = true;
 }

-void alarm(){
+void alarm() {
   alertMillis = millis();
 }

-void doAlert(){
-  unsigned long dur = millis()-alertMillis;
-
-  if((dur/250)%2==0){
+void doAlert() {
+  unsigned long dur = millis() - alertMillis;
+
+  if ((dur / 250) % 2 == 0) {
     tone(PIN_BUZZER, 262, 250);
   } else {
     noTone(PIN_BUZZER);
   }
-  if((dur/500)%2==0){
-    digitalWrite(PIN_BG_LIGHT,LOW);
+  if ((dur / 500) % 2 == 0) {
+    digitalWrite(PIN_BG_LIGHT, LOW);
   } else {
-    digitalWrite(PIN_BG_LIGHT,HIGH);
-  }
-
+    digitalWrite(PIN_BG_LIGHT, HIGH);
+  }
+
   //Nach spät. 10 sec. den Alarm Abbrechen
-  if(dur >= 10000){
+  if (dur >= 10000) {
     cancelAlarm();
   }
 }

-void cancelAlarm(){
+void cancelAlarm() {
   alertMillis = 0;
   noTone(PIN_BUZZER);
-  digitalWrite(PIN_BG_LIGHT,HIGH);
-}
-
-bool buttonClicked(){
+  digitalWrite(PIN_BG_LIGHT, LOW);
+}
+
+bool buttonClicked() {
   ClickEncoder::Button b = encoder->getButton();
   if (b != ClickEncoder::Open && b == ClickEncoder::Clicked )
     return true;
   return false;
 }

-void checkForErrors(){
-  if(temp = -127){
+void checkForErrors() {
+  if (-128 < temp && -126 > temp) {
     //Kein Thermometer
     errors += ERROR_NO_THERMOMETER;
-  }
-}
+  }
+}


Wifi conf v2

Wifi conf v2

--- EspOdom/EspOdom.ino
+++ EspOdom/EspOdom.ino
@@ -45,7 +45,7 @@

 // WiFi configuration. Replace *** by your data//
 const char* ssid = "***";
-const char* password = "***";
+const char* password = "**";
 // Set the rosserial socket server IP address
 IPAddress server(192,168,1,***);
 // Set the rosserial socket server port


Debugging volts calibrate save problem

Debugging volts calibrate save problem

--- DigitalVFO.ino
+++ DigitalVFO.ino
@@ -1595,13 +1595,11 @@
   EEPROM.put(EepromDClickTime, ReDClickTime);
   EEPROM.put(EepromVoltsCalibrate, VoltsCalibrate);

-#if 0
   Serial.printf(F("save_to_eeprom: VfoClockOffset=%ld\n"), VfoClockOffset);
   Serial.printf(F("save_to_eeprom: VoltsCalibrate=%ld\n"), VoltsCalibrate);
   Serial.printf(F("save_to_eeprom: EepromVfoClockOffset=%d\n"), EepromVfoClockOffset);
   Serial.printf(F("save_to_eeprom: EepromVoltsCalibrate=%d\n"), EepromVoltsCalibrate);
   Serial.printf(F("save_to_eeprom: EepromSaveFreqBase=%d\n"), EepromSaveFreqBase);
-#endif
 }

 //----------------------------------------
@@ -1620,13 +1618,11 @@
   EEPROM.get(EepromDClickTime, ReDClickTime);
   EEPROM.put(EepromVoltsCalibrate, VoltsCalibrate);

-#if 0
   Serial.printf(F("restore_from_eeprom: VfoClockOffset=%ld\n"), VfoClockOffset);
   Serial.printf(F("restore_from_eeprom: VoltsCalibrate=%ld\n"), VoltsCalibrate);
   Serial.printf(F("restore_from_eeprom: EepromVfoClockOffset=%d\n"), EepromVfoClockOffset);
   Serial.printf(F("restore_from_eeprom: EepromVoltsCalibrate=%d\n"), EepromVoltsCalibrate);
   Serial.printf(F("restore_from_eeprom: EepromSaveFreqBase=%d\n"), EepromSaveFreqBase);
-#endif
 }

 //----------------------------------------
@@ -1841,51 +1837,6 @@
 // Main VFO code
 //##############################################################################

-#ifdef JUNK
-const int EepromFreq = NEXT_FREE;
-#define NEXT_FREE   (EepromFreq + sizeof(Frequency))
-
-// address for int 'selected digit'
-const int EepromSelDigit = NEXT_FREE;
-#define NEXT_FREE   (EepromSelDigit + sizeof(SelOffset))
-
-// address for 'VfoClockOffset' calibration
-const int EepromVfoClockOffset = NEXT_FREE;
-#define NEXT_FREE   (EepromVfoClockOffset + sizeof(VfoClockOffset))
-
-// address for byte 'contrast'
-const int EepromContrast = NEXT_FREE;
-#define NEXT_FREE   (EepromContrast + sizeof(LcdContrast))
-
-// address for byte 'brightness'
-const int EepromBrightness = NEXT_FREE;
-#define NEXT_FREE   (EepromBrightness + sizeof(LcdBrightness))
-
-// address for int 'hold click time'
-const int EepromHoldClickTime = NEXT_FREE;
-#define NEXT_FREE   (EepromHoldClickTime + sizeof(ReHoldClickTime))
-
-// address for int 'double click time'
-const int EepromDClickTime = NEXT_FREE;
-#define NEXT_FREE   (EepromDClickTime + sizeof(ReDClickTime))
-
-// address for float 'voltage calibrate'
-const int EepromVoltsCalibrate = NEXT_FREE;
-#define NEXT_FREE   (EepromVoltsCalibrate + sizeof(VoltsCalibrate))
-
-// number of frequency save slots in EEPROM
-const int NumSaveSlots = 10;
-
-const int EepromSaveFreqBase = NEXT_FREE;
-#define NEXT_FREE   (EepromSaveFreqBase + NumSaveSlots * sizeof(Frequency))
-
-//also save the offset for each frequency
-const int EepromSaveOffsetBase = NEXT_FREE;
-#define NEXT_FREE   (EepromSaveOffsetBase + NumSaveSlots * sizeof(SelOffset);
-
-// additional EEPROM saved items go here
-#endif
-
 //----------------------------------------
 // The standard Arduino setup() function.
 // Called once on powerup.
@@ -1908,9 +1859,6 @@
   // set brightness/contrast pin state
   pinMode(mc_Brightness, OUTPUT);
   pinMode(mc_Contrast, OUTPUT);
-
-  // force a full EEPROM write, debug
-//  initialize_eeprom();

   // get state back from EEPROM, set display brightness/contrast
   restore_from_eeprom();
@@ -2826,7 +2774,7 @@
           break;
       }

-      // show hold time value in row 1
+      // show voltage calibrate value
       display_sel_offset(VoltsCalibrate, seldig, 5, 10, 1);
     }
   }
@@ -3019,6 +2967,7 @@
   {
     char ch = Serial.read();

+    // ignore newlines
     if (ch == '\n')
       continue;

@@ -3100,6 +3049,8 @@
 // Overwrite everything in the EEPROM.
 //----------------------------------------

+#if 0
+
 void initialize_eeprom()
 {
   EEPROM.put(EepromFreq, DefaultFrequency);
@@ -3120,6 +3071,8 @@
   }
 }

+#endif
+
 //----------------------------------------
 // Standard Arduino loop() function.
 //----------------------------------------
@@ -3139,13 +3092,9 @@
   display_sel_value(VfoFrequency, VfoSelectDigit, NumFreqChars, NumCols - NumFreqChars - 2, 0);
   display_battery();

-#if (DEBUG & DEBUG_FREQ)
-    Serial.printf(F("Main loop: VfoFrequency=%ld\n"), VfoFrequency);
-#endif
-
   // if online, update DDS-60 and write changes to EEPROM
   if (VfoMode == vfo_Online)
   {
-    save_to_eeprom();
-  }
-}
+    save_to_eeprom();   // only writes if value(s) different
+  }
+}


Fixed bug setting brightness

Fixed bug setting brightness

--- DigitalVFO.ino
+++ DigitalVFO.ino
@@ -157,9 +157,10 @@
 byte batt80[8]    = {0x0e,0x1f,0x11,0x1f,0x1f,0x1f,0x1f,0x1f};
 byte batt100[8]   = {0x0e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f};
 byte battover[8]  = {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f};
+byte battnone[8]  = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

 // array of references to the 8 'battery symbol' characters
-byte *batt_syms[] = {battunder, batt00, batt20, batt40, batt60, batt80, batt100, battover};
+byte *batt_syms[] = {battunder, batt00, batt20, batt40, batt60, batt80, batt100, battover, battnone};

 //-----
 // Events and the event queue.
@@ -197,12 +198,17 @@
 //-----

 // milliseconds delay between measuring battery voltage
+//const int VoltageDelay = 1000;
 const int VoltageDelay = 30000;

 // stuff for the calibrate action
 const int MinClockOffset = -32000;
 const int MaxClockOffset = +32000;
 const int MaxOffsetDigits = 5;
+
+// battery voltage limits
+const float MaxVoltage = 8.2;   // battery voltage for "100% full"
+const float MinVoltage = 6.4;   // battery voltage for "0% full"

 // macro to get number of elements in an array
 #define ALEN(a)    (sizeof(a)/sizeof((a)[0]))
@@ -2533,6 +2539,7 @@
           break;
         case vfo_HoldClick:
           LcdBrightness = old_brightness;
+          analogWrite(mc_Brightness, LcdBrightness);
           event_flush();
           return;
         default:
@@ -2991,13 +2998,10 @@
 // Standard Arduino loop() function.
 //----------------------------------------

-const float MaxVoltage = 8.2;   // battery voltage for "100% full"
-const float MinVoltage = 6.4;   // battery voltage for "0% full"
-
 void loop(void)
 {
 #if INC_BATTERY
-  // measure voltage every second
+  // measure voltage every whenever
   // we will get a value of 1023 for 3.3 volts
   static UINT last_volts_time = -VoltageDelay;    // millis() value last time we measured
   ULONG now = millis();
@@ -3009,19 +3013,30 @@
     UINT measured = analogRead(mc_BattVolts);
     MeasuredVoltage = ((3.3 * measured) / 1023) * (32.0/10.0);

+#if (DEBUG & DEBUG_BATT)
+      Serial.printf(F("raw volts=%d\n"), measured);
+#endif
+
     // figure out which battery symbol to use
     if (MeasuredVoltage < MinVoltage)
+    {
         BatterySymbol = battunder;
+        if (MeasuredVoltage < 1.0)
+        {
+          BatterySymbol = battnone;
+        }
+    }
     else if (MeasuredVoltage > MaxVoltage)
         BatterySymbol = battover;
     else
     {
       int percent = (int) ((MeasuredVoltage - MinVoltage) / (MaxVoltage - MinVoltage) * 100.0);
       int batt_bucket = (int) (percent/20);
+      BatterySymbol = batt_syms[batt_bucket + 2];
 #if (DEBUG & DEBUG_BATT)
-      Serial.printf(F("volts=%f, percent=%d, batt_bucket=%d\n"), MeasuredVoltage, percent, batt_bucket);
-#endif
-      BatterySymbol = batt_syms[batt_bucket + 2];
+      Serial.printf(F("actual volts=%f, percent=%d, batt_bucket=%d\n"),
+                      MeasuredVoltage, percent, batt_bucket);
+#endif
     }
     display_battery();
   }


Successful GPS advertised over Bluetooth

Can see the lat/lon numbers changing on my phone bluetooth scanner as I walk around.

--- ESP32/beacon_gps_update/beacon_gps_update.ino
+++ ESP32/beacon_gps_update/beacon_gps_update.ino
@@ -96,22 +96,30 @@
 void gps_setup(){
   Serial2.begin(9600);   //Do not change, must match factory setting.
 }
-
+
+void
+gps_debug_passthrough()
+{
+    while (Serial2.available())         // If anything comes in Serial2 (pins 16-Rx & 17-Tx)
+      {Serial.write(Serial2.read());};  // read it and send it out Serial (USB)
+    Serial.println();
+    Serial.println();
+}
+
 void
 gps_read_into( beacon_data_t * beaconData)
 {
-    //Serial.print(".");
-    if(Serial2.available())
+    //gps_debug_passthrough(); return;
+
+    while(Serial2.available())
     {
-    //Serial.print(":");
       int c = Serial2.read();
       if (gps.encode(c)) // do we have a valid gps data that we can encode
       {
-          //Serial.print(",");
-          gps.get_position(&lat,&lon); // get latitude and longitude
-          Serial.printf("Position - lat: %ld lon: %ld \n", lat, lon);
-
-          //gps.get_position( &beaconData->fields.gpsLatitute, &beaconData->fields.gpsLongitude );
+          //gps.get_position(&lat,&lon); // get latitude and longitude
+          gps.get_position( &beaconData->fields.gpsLatitute, &beaconData->fields.gpsLongitude );
+          Serial.printf("Position - lat: %ld lon: %ld \n", beaconData->fields.gpsLatitute, beaconData->fields.gpsLongitude);
+

           // returns speed in 100ths of a knot
@@ -229,7 +237,7 @@

 void
 setup() {
-    Serial.begin(9600);
+    Serial.begin(115200);
     Serial.setDebugOutput(true);
     pinMode(LED_BUILTIN, OUTPUT);
     Serial.print("ESP32 SDK: ");
@@ -243,10 +251,11 @@
 void
 loop() {
     gps_read_into( &myBeaconData );
-    //if(esp_ble_gap_config_adv_data(&advertisement_config))
-    //{   log_e("gap_config_adv_data failed");
-    //    exit(1);
-    //}
+
+    if(esp_ble_gap_config_adv_data(&advertisement_config))
+    {   log_e("gap_config_adv_data failed");
+        exit(1);
+    }
     delay(500); digitalWrite(LED_BUILTIN, HIGH);
     delay(500); digitalWrite(LED_BUILTIN, LOW);


WIP: Try to playback values from serial

WIP: Try to playback values from serial

--- HHI_switches_gripper/HHI_switches_gripper.ino
+++ HHI_switches_gripper/HHI_switches_gripper.ino
@@ -11,6 +11,7 @@

 int reading[10];
 int finalReading;
+String readString;
 int StimPin = 3; // TENS Digital 3
 int GripPin = 2; //Digital Out that controls Servo Motor Gripper Hand
 int MAX = 0;
@@ -20,6 +21,7 @@
 int aQ1 = 11;
 int aQ2 = 13;
 int aQ3 = 8;
+char lastChar = ' ';

 const int UpdateTime = 200; // (number of milliseconds between updating servo position -- if too low you will burn motor out)
 unsigned long OldTime = 0;
@@ -38,17 +40,23 @@
 }

 void loop(){
-    // take ten readings in ~0.02 seconds
-    for(int i = 0; i < 10; i++){
-        reading[i] = analogRead(A0) * multiplier;
-        delay(2);
+    // Read value to apply from serial
+    // Read until newline
+    delay(10);  //delay to allow buffer to fill
+    while (Serial.available()) {
+        if (Serial.available() >0) {
+            char c = Serial.read();  //gets one byte from serial buffer
+            if (c == '\n') {
+                break;
+            }
+            readString += c; //makes the string readString
+        }
     }
+    // Parse the value read from serial to int
+    finalReading = readString.toInt();

-    // average the ten readings
-    for(int i = 0; i < 10; i++){
-        finalReading += reading[i];
-    }
-    finalReading /= 10;
+    // Reset the string read for next iteration in the loop
+    readString = "";

     // write all LEDs low and stim pin low
     for(int j = 0; j < NUM_LED; j++){
@@ -77,5 +85,6 @@
         OldTime = millis();
         old_degrees = new_degrees;
     }
+
 }


The latest and the greatest test firmware.

What works:
 * Emergency brake system
 * Steering wheel control, centering and backlash calibration (needs investigation as regadring to degree to step conversion)
 * Horn, lights, parking and key

What's left:
 * Line sensor
 * Obstacle sensor

--- testFw/testFw.ino
+++ testFw/testFw.ino
@@ -3,13 +3,7 @@
 #include "brake.h"
 #include "line_follower.h"
 #include "steering.h"
-
-void setup() {
-	pinsInit();
-	controlAllOff();
-	Serial.begin(115200);
-	steeringInit();
-}
+#include "Bounce2.h"

 void testAllOutputs() {
 	magnetEngage();
@@ -116,15 +110,138 @@
 	}
 }

+
+//int angle[] ={9000, -9000};
+int i = 0;
+uint32_t lastMoveTs = 0;
+
+void testHBridge() {
+	setDirection(DIRECTION_OUT);
+	actuatorEnable();
+
+	lastMoveTs = millis();
+	while(millis() - lastMoveTs < 4000) {
+		Serial.println(analogRead(HBRIDGE_CURRENT_ANALOG));
+	}
+
+	setDirection(DIRECTION_OUT);
+	actuatorDisable();
+
+	delay(4000);
+
+	setDirection(DIRECTION_IN);
+	actuatorEnable();
+
+	lastMoveTs = millis();
+	while(millis() - lastMoveTs < 4000) {
+		Serial.println(analogRead(HBRIDGE_CURRENT_ANALOG));
+	}
+
+	actuatorDisable();
+	delay(4000);
+
+}
+
+Bounce button = Bounce();
+
+uint16_t maxCurrent = 0;
+
+void setup() {
+	pinsInit();
+
+	button.attach(GAZ_SPEED3);
+	button.interval(100);
+
+	controlAllOff();
+	Serial.begin(115200);
+
+	keyOn();
+	controlTakeover();
+	delay(5000);
+	hornOn();
+	delay(50);
+	hornOff();
+
+	// lightsOn();
+	// mirgalkeOn();
+	// auxOn();
+	// delay(1000);
+	// auxOff();
+	// lightsOff();
+	// mirgalkeOff();
+
+	parkingOff();
+	directionForwardOn();
+	setSpeed(SPEED0);
+	gasEnable();
+	delay(1000);
+	steeringInit();
+	delay(5000);
+
+	// steeringDisable();
+}
+
 int angle = 900;

+int dir = DIRECTION_OUT;
+
+
+
 void loop() {
+
+//	Serial.println(getWheelPosition());
+	uint16_t curr = analogRead(HBRIDGE_CURRENT_ANALOG);
+	Serial.println(curr);
+
+	if(curr > maxCurrent) {
+		maxCurrent = curr;
+	}
+
+	if(button.fell()) {
+		// hornOn();
+		// delay(50);
+		// hornOff();
+
+
+		if(DIRECTION_OUT == dir) {
+			dir = DIRECTION_IN;
+			brakeEmergencyRelease();
+		} else {
+			dir = DIRECTION_OUT;
+			magnetDisengage();
+		}
+
+	}
+
+
 	if(steeringIsMoveDone()) {
+		angle = angle * -1;
 		steeringSetAngle(angle);
-		angle = -angle;
-	}
-//	testAllOutputs();
-//  serialTest();
-//	delay(1000);
+		delay(1000);
+	}
+
+	// directionForwardOn();
+	// delay(1000);
+	// setSpeed(SPEED1);
+	// parkingOff();
+	// gasEnable();
+	// delay(15000);
+	// setSpeed(SPEED0);
+	// delay(15000);
+	// directionBackwardOn();
+	// setSpeed(SPEED1);
+	// delay(15000);
+	// setSpeed(SPEED0);
+	// parkingOn();
+	// delay(15000);
+
+	// gasDisable();
+	// delay(2000);
+
+	// parkingOff();
+	// delay(1000);
+	// parkingOn();
+
 	steeringRun();
+	button.update();
 }


New firmware version number for AutoUpdate


implementado função da fotocélula, liberação e corte

--- EMP-B-Due.ino
+++ EMP-B-Due.ino
@@ -36,6 +36,7 @@
 const byte sensor_painel = 34;   // Sensor de Segurança da Porta do Painel
 const byte sensor_maquina = 36;  // Sensor de Segurança da Porta da Máquina
 const byte sensor_mandibula = 2; // Sensor de Segurança de Fechamento da Mandíbula
+const byte fotocelula = 6; // Sensor da Fotocélula de Corte
 const byte pot_solda_vertical = A0; // Potenciômetro da Solda Vertical
 const byte pot_solda_horizontal = A1; // Potenciômetro da Solda Vertical
 const byte pot_solda_datador = A2; // Potenciômetro da Solda Vertical
@@ -161,6 +162,7 @@
   // SENSORES
   pinMode(sensor_reset, BOTAO); // Mudar para Sensor após os testes.
   pinMode(sensor_mandibula, BOTAO);
+  pinMode(fotocelula, BOTAO);
   pinMode(sensor_porta, BOTAO);
   pinMode(sensor_painel, BOTAO);
   pinMode(sensor_maquina, BOTAO);
@@ -221,6 +223,8 @@
     reiniciaCiclo(millis());
   }
   if (conta_ciclos >= 3) {
+    liberaFotocelula();
+    leFotocelula();
     funcaoSimples(mandibula, NomeMandibula, ti_mandibula, tf_mandibula);
     funcaoSegura(faca, NomeFaca, ti_faca, tf_faca, sensor_mandibula);
     funcaoSimples(refrigeracao, NomeRefrigeracao, ti_refrigeracao, tf_refrigeracao);
@@ -351,7 +355,7 @@
 void funcaoSimples(const byte saida, String nome, unsigned long inicio, unsigned long fim) {
   inicio += inicio_ciclo;
   fim += inicio_ciclo;
-  if (desligado(saida)){
+  if (desligado(saida) && !fotocelula_cortou){
     if (tempo_atual >= inicio && tempo_atual < fim) {
       ligaFuncao(saida, nome);
     }
@@ -368,9 +372,30 @@
   }
 }

+void liberaFotocelula() {
+  unsigned long inicio = ti_fotocelula + inicio_ciclo;
+  unsigned long fim = tf_fotocelula + inicio_ciclo;
+  if (!fotocelula_cortou){
+    if (tempo_atual >= inicio && tempo_atual < fim) {
+      fotocelula_liberada = VERDADEIRO;
+    }
+  } else if (tempo_atual >= fim) {
+    fotocelula_liberada = FALSO;
+  }
+}
+
+void leFotocelula(){
+  if (fotocelula_liberada && !fotocelula_cortou){
+    if (ativo(fotocelula)){
+      fotocelula_cortou = VERDADEIRO;
+      reiniciaSaidas();
+    }
+  }
+}
+
 // FERRAMENTAS AUXILIARES

-byte leEntrada(byte pino) { return digitalRead(pino); }
+byte lePino(byte pino) { return digitalRead(pino); }

 void liga(byte saida) { digitalWrite(saida, LIGA); }

@@ -395,7 +420,7 @@
 }

 boolean ligado(byte saida) {
-  if (digitalRead(saida) == LIGA) {
+  if (lePino(saida) == LIGA) {
     return VERDADEIRO;
   } else {
     return FALSO;
@@ -403,7 +428,7 @@
 }

 boolean desligado(byte saida) {
-  if (digitalRead(saida) == DESLIGA) {
+  if (lePino(saida) == DESLIGA) {
     return VERDADEIRO;
   } else {
     return FALSO;
@@ -411,7 +436,7 @@
 }

 boolean ativo(byte entrada) {
-  if (digitalRead(entrada) == ALTO) {
+  if (lePino(entrada) == ALTO) {
     return VERDADEIRO;
   } else {
     return FALSO;
@@ -419,7 +444,7 @@
 }

 boolean inativo(byte entrada) {
-  if (digitalRead(entrada) == BAIXO) {
+  if (lePino(entrada) == BAIXO) {
     return VERDADEIRO;
   } else {
     return FALSO;
@@ -428,7 +453,7 @@

 void btUmClique(byte botao, int *estado, int *est_ant, unsigned long *atr_ant,
                 boolean *funcao) {
-  byte estado_atual = leEntrada(botao);
+  byte estado_atual = lePino(botao);
   if (estado_atual != *est_ant) {
     *atr_ant = millis();
   }
@@ -451,8 +476,6 @@
 }

 void reiniciaSaidas() {
-  desligaFuncao(dosador, NomeDosador);
-  desligaFuncao(led_datador, NomeDatador);
   desligaFuncao(mandibula, NomeMandibula);
   desligaFuncao(faca, NomeFaca);
   desligaFuncao(refrigeracao, NomeRefrigeracao);


ifdef around SD support just in case its not enabled

--- examples/GuiMetroGridImages/GuiMetroGridImages.ino
+++ examples/GuiMetroGridImages/GuiMetroGridImages.ino
@@ -21,8 +21,9 @@
 #include <Adafruit_ILI9341.h>
 #include "TouchScreen.h"
 #include "GuiLibrary.h"
+#if USING_SD
 #include <SdFat.h>
-
+#endif
 // These are the four touchscreen analog pins
 #define YP A0  // must be an analog pin, use "An" notation!
 #define XM A1  // must be an analog pin, use "An" notation!
@@ -42,7 +43,9 @@
 #define TFT_DC 5
 #define SD_CS 8

+#if USING_SD
 SdFat sd;
+#endif

 Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

@@ -189,11 +192,13 @@
   delay(1000);
   Serial.println(F("Gui Widgets test!"));

+#if USING_SD
   // SD is a go
   if (!sd.begin(SD_CS, SPI_HALF_SPEED)) {
     Serial.println("Begin failed");
     return;
   }
+#endif

   // TFT is a go
   tft.begin();


Saving time to EEPROM

Saving time to EEPROM

--- arduino/autofowl/autofowl.ino
+++ arduino/autofowl/autofowl.ino
@@ -3,14 +3,18 @@
 #include <Stepper.h>
 #include <AccelStepper.h>
 #include <Wire.h>
-#include "RTClib.h"
-
-const int INT_MAX = 32767;
-const int NONE = -1;
-const int TICK = 150; // microseconds
-const int EEPROM_UNINIT_VALUE = -1;
-
-const int BUTTON_UP = LOW;
+#include <RTClib.h>
+
+// --------------------------------------
+// -- Constants
+// --------------------------------------
+
+const int INT_MAX               = 32767;
+const int NONE                  = -1;
+const int TICK                  = 150; // microseconds
+const byte EEPROM_UNINIT_VALUE  = -1;
+
+const int BUTTON_UP   = LOW;
 const int BUTTON_DOWN = HIGH;

 // Run modes
@@ -51,19 +55,19 @@

 // Motor constants
 const int MOTOR_RPMS            = 60;
+const int STEPS_PER_REVOLUTION  = 200;

 // Number of ticks beyond threshold to wait before changing door position
 const int LIGHT_THRESH_TICKS_TO_CHANGE = 100;
-
-// Motor constants
-const int STEPS_PER_REVOLUTION = 200;
+// Number to change the light threshold by per button press
+const int LIGHT_THRESH_CHANGE_INCREMENT = 20;

 // Number of minutes to increment per click
 const int CLOCK_MIN_INCREMENT = 15;

 // Door-specific constants
 // Number of revolutions to fully change door position
-const int REVOLUTIONS_TO_CHANGE   = 100;
+const int REVOLUTIONS_TO_CHANGE = 100;

 // Pins
 // Arduino Uno / Buttons
@@ -77,6 +81,7 @@
 const int PIN_LCD_D5      = 4;
 const int PIN_LCD_D6      = 3;
 const int PIN_LCD_D7      = 2;
+const int PIN_LCD_BL      = 9;
 // Arduino Uno / Photocell
 const int PIN_PHOTOCELL   = A0;
 // Arduino Uno / Motor controller
@@ -85,9 +90,13 @@
 const int PIN_MOTOR_3     = 11; // pin 15 on L293D
 const int PIN_MOTOR_4     = 10; // pin 10 on L293D

+// --------------------------------------
+// -- Runtime variables
+// --------------------------------------
+
 // Global State variables
 int CurrentMode           = MODE_AUTO;
-int DoorPosition          = DOOR_POSITION_UNKNOWN;
+int DoorPosition          = DOOR_POSITION_UNKNOWN;
 int DoorDirection         = DOOR_STATIONARY;
 // Used for detecting button presses
 int UpButtonState         = BUTTON_UP;
@@ -99,15 +108,15 @@
 // Used for light sensor
 int LightCurrent          = 0;             // Current reading
 int LightLast             = LightCurrent;  // Last reading
-int LightThreshUp         = 100;
-int LightThreshDown       = 10;
-int LightThreshTicks      = 0;              // Ticks needed to start door position change
+int LightThreshUp         = 400;
+int LightThreshDown       = 100;
+int LightThreshTicks      = 0;             // Ticks needed to start door position change
 // Used for clock
 DateTime Now;
 TimeSpan ClockThreshUp;
 TimeSpan ClockThreshDown;

-// Initialize the LCD
+// Initialize the LCD
 LiquidCrystal Lcd(PIN_LCD_RS, PIN_LCD_ENABLE, PIN_LCD_D4, PIN_LCD_D5, PIN_LCD_D6, PIN_LCD_D7);

 // Initialize the stepper motor controller
@@ -117,7 +126,7 @@
 RTC_DS1307 RTC;

 void setup() {
-
+
   // initialize serial and wait for port to open:
   Serial.begin(9600);
   while (!Serial) {
@@ -133,32 +142,43 @@
   pinMode(PIN_MOTOR_2,      OUTPUT);
   pinMode(PIN_MOTOR_3,      OUTPUT);
   pinMode(PIN_MOTOR_4,      OUTPUT);
-
+  pinMode(PIN_LCD_BL,       OUTPUT);
+
+  // Set backlight brightness
+  analogWrite(PIN_LCD_BL, 30); // 0 = off, 255 = fully on
+
   // set up the LCD's number of columns and rows:
   Lcd.begin(16, 2);
   // Print a message to the LCD.
-  Lcd.print("eCoop v2.0");
+  Lcd.print("AutoFowl v2.0");

   // Start the Real Time Clock
   Wire.begin();
   RTC.begin();
   // Check to see if the RTC is keeping time.  If it is, load the time from your computer.
   if (! RTC.isrunning()) {
-    Serial.println("RTC is NOT running! Adjusting time now.");
     // This will reflect the time that your sketch was compiled
     RTC.adjust(DateTime(__DATE__, __TIME__));
   }

   // Read clock settings from EEPROM
-  ClockThreshUp = TimeSpan(0,
-    EEPROM.read((CLOCK_HOUR_THRESH_UP_ADDRESS) == -1) ? 0 : EEPROM.read(CLOCK_HOUR_THRESH_UP_ADDRESS),
-    EEPROM.read((CLOCK_MIN_THRESH_UP_ADDRESS) == -1) ? 0 : EEPROM.read(CLOCK_MIN_THRESH_UP_ADDRESS),
-    0 );
-  ClockThreshDown = TimeSpan(0,
-    EEPROM.read((CLOCK_HOUR_THRESH_DOWN_ADDRESS) == -1) ? 0 : EEPROM.read(CLOCK_HOUR_THRESH_DOWN_ADDRESS),
-    EEPROM.read((CLOCK_MIN_THRESH_DOWN_ADDRESS) == -1) ? 0 : EEPROM.read(CLOCK_MIN_THRESH_DOWN_ADDRESS),
-    0 );
-
+  byte clockHourThreshUp = EEPROM.read(CLOCK_HOUR_THRESH_UP_ADDRESS);
+  byte clockMinThreshUp = EEPROM.read(CLOCK_MIN_THRESH_UP_ADDRESS);
+  byte clockHourThreshDown = EEPROM.read(CLOCK_HOUR_THRESH_DOWN_ADDRESS);
+  byte clockMinThreshDown = EEPROM.read(CLOCK_MIN_THRESH_DOWN_ADDRESS);
+  ClockThreshUp = TimeSpan(
+    0, // days
+    clockHourThreshUp == EEPROM_UNINIT_VALUE ? 0 : clockHourThreshUp,
+    clockMinThreshUp == EEPROM_UNINIT_VALUE ? 0 : clockMinThreshUp ,
+    0 // seconds
+  );
+  ClockThreshDown = TimeSpan(
+    0, // days
+    clockHourThreshDown == EEPROM_UNINIT_VALUE ? 0 : clockHourThreshDown,
+    clockMinThreshDown == EEPROM_UNINIT_VALUE ? 0 : clockMinThreshDown,
+    0 // seconds
+  );
+
   // Set up the motor
   Motor.setSpeed( ( MOTOR_RPMS / 60 ) * STEPS_PER_REVOLUTION );

@@ -172,7 +192,7 @@
   // Handle DoorPosition == DOOR_POSITION_UNKNOWN or never set
   if (DoorPosition == DOOR_POSITION_UNKNOWN || DoorPosition == EEPROM_UNSET ) {
     CurrentMode = MODE_MANUAL;
-  }
+  }

   // Read current mode from eeprom
   CurrentMode = EEPROM.read(CURRENT_MODE_ADDRESS);
@@ -181,6 +201,7 @@
     CurrentMode = MODE_AUTO;
   }

+  // Display greeting on LCD for 1 second
   delay(1000);
   updateLCD();
 }
@@ -192,8 +213,9 @@

   handleTriggers();

+  // Write debug info to terminal
   debug();
-
+
   // Sleep to avoid busy wait
   delay(TICK);
 }
@@ -270,17 +292,21 @@
       stopDoor();
     }
   } else if ( CurrentMode == MODE_SET_OPEN_THRESH ) {
-    LightThreshUp++;
+    LightThreshUp += LIGHT_THRESH_CHANGE_INCREMENT;
   } else if ( CurrentMode == MODE_SET_CLOSE_THRESH ) {
-    LightThreshDown++;
+    LightThreshDown += LIGHT_THRESH_CHANGE_INCREMENT;
   } else if ( CurrentMode == MODE_SET_CLOCK_CLOSE_HOUR_THRESH ) {
     ClockThreshDown = TimeSpan(0, ClockThreshDown.hours() + 1, ClockThreshDown.minutes(), 0);
+    EEPROM.write(CLOCK_HOUR_THRESH_DOWN_ADDRESS, ClockThreshDown.hours());
   } else if ( CurrentMode == MODE_SET_CLOCK_CLOSE_MIN_THRESH ) {
     ClockThreshDown = TimeSpan(0, ClockThreshDown.hours(), ClockThreshDown.minutes() + CLOCK_MIN_INCREMENT, 0);
+    EEPROM.write(CLOCK_MIN_THRESH_DOWN_ADDRESS, ClockThreshDown.minutes());
   } else if ( CurrentMode == MODE_SET_CLOCK_OPEN_HOUR_THRESH ) {
     ClockThreshUp = TimeSpan(0, ClockThreshUp.hours() + 1, ClockThreshUp.minutes(), 0);
+    EEPROM.write(CLOCK_HOUR_THRESH_UP_ADDRESS, ClockThreshUp.hours());
   } else if ( CurrentMode == MODE_SET_CLOCK_OPEN_MIN_THRESH ) {
     ClockThreshUp = TimeSpan(0, ClockThreshUp.hours(), ClockThreshUp.minutes() + CLOCK_MIN_INCREMENT, 0);
+    EEPROM.write(CLOCK_MIN_THRESH_UP_ADDRESS, ClockThreshUp.minutes());
   }
 }

@@ -295,22 +321,26 @@
       stopDoor();
     }
   } else if ( CurrentMode == MODE_SET_OPEN_THRESH ) {
-    LightThreshUp = LightThreshUp - 1;
+    LightThreshUp -= LIGHT_THRESH_CHANGE_INCREMENT;
   } else if ( CurrentMode == MODE_SET_CLOSE_THRESH ) {
-    LightThreshDown = LightThreshDown - 1;
+    LightThreshDown -= LIGHT_THRESH_CHANGE_INCREMENT;
   } else if ( CurrentMode == MODE_SET_CLOCK_CLOSE_HOUR_THRESH ) {
     ClockThreshDown = TimeSpan(0, ClockThreshDown.hours() - 1, ClockThreshDown.minutes(), 0);
+    EEPROM.write(CLOCK_HOUR_THRESH_DOWN_ADDRESS, ClockThreshDown.hours());
   } else if ( CurrentMode == MODE_SET_CLOCK_CLOSE_MIN_THRESH ) {
     ClockThreshDown = TimeSpan(0, ClockThreshDown.hours(), ClockThreshDown.minutes() - CLOCK_MIN_INCREMENT, 0);
+    EEPROM.write(CLOCK_MIN_THRESH_DOWN_ADDRESS, ClockThreshDown.minutes());
   } else if ( CurrentMode == MODE_SET_CLOCK_OPEN_HOUR_THRESH ) {
     ClockThreshUp = TimeSpan(0, ClockThreshUp.hours() - 1, ClockThreshUp.minutes(), 0);
+    EEPROM.write(CLOCK_HOUR_THRESH_UP_ADDRESS, ClockThreshUp.hours());
   } else if ( CurrentMode == MODE_SET_CLOCK_OPEN_MIN_THRESH ) {
     ClockThreshUp = TimeSpan(0, ClockThreshUp.hours(), ClockThreshUp.minutes() - CLOCK_MIN_INCREMENT, 0);
+    EEPROM.write(CLOCK_MIN_THRESH_UP_ADDRESS, ClockThreshUp.minutes());
   }
 }

 void handleTriggers() {
-
+
   updateLight();
   updateTime();

@@ -331,7 +361,7 @@
     if ( DoorPosition == DOOR_POSITION_UP ) {
       return;
     }
-
+
     LightThreshTicks++;
     updateLCD();
     if ( LightThreshTicks > LIGHT_THRESH_TICKS_TO_CHANGE ) {
@@ -347,7 +377,7 @@
     if ( DoorPosition == DOOR_POSITION_DOWN ) {
       return;
     }
-
+
     LightThreshTicks++;
     updateLCD();
     if ( LightThreshTicks > LIGHT_THRESH_TICKS_TO_CHANGE ) {
@@ -368,7 +398,7 @@
 }

 void updateTime() {
-  Now = RTC.now();
+  Now = RTC.now();
 }

 void openDoor() {
@@ -400,12 +430,12 @@
   updateDoorStatus(DOOR_STATIONARY, DOOR_POSITION_DOWN);
 }

-// Moves door either up or down.
+// Moves door either up or down.
 // If revolutions is positive, door goes up; if negative, door goes down.
 void moveDoor(int revolutions) {
   // Set the motor target position i.e. number of steps to move
   Motor.move(revolutions * (long) STEPS_PER_REVOLUTION);
-
+
   // Start stepping motor
   // for (int rev = 1; rev <= revolutions; rev++) {
   while (true) {
@@ -447,17 +477,16 @@

 // Update LCD with current status
 void updateLCD() {
-
+
   Lcd.clear();
+  // Lcd.home();

   if ( CurrentMode <= MODE_MANUAL && CurrentMode >= MODE_DISABLED ) {
-    // Render run mode
-
+    // Render run mode
+
     // Print first line
-
     Lcd.print("Mode: ");
     Lcd.print(prettyMode());
-
     Lcd.print(" Door: ");
     Lcd.print(prettyDoorPosition());

@@ -476,21 +505,21 @@
     } else {
       Lcd.print(doorDirection);
     }
-
+
   } else {
     // Render settings

     // Render first line
     if ( CurrentMode == MODE_SET_OPEN_THRESH ) {
-      Lcd.print("Open Threshold");
+      Lcd.print("Open Threshold  ");
     } else if ( CurrentMode == MODE_SET_CLOSE_THRESH ) {
-      Lcd.print("Close Threshold");
+      Lcd.print("Close Threshold ");
     } else if (CurrentMode == MODE_SET_CLOCK_OPEN_HOUR_THRESH || CurrentMode == MODE_SET_CLOCK_OPEN_MIN_THRESH) {
       Lcd.print("Open Time Threshold");
     } else if (CurrentMode == MODE_SET_CLOCK_CLOSE_HOUR_THRESH || CurrentMode == MODE_SET_CLOCK_CLOSE_MIN_THRESH) {
       Lcd.print("Close Time Threshold");
     } else {
-      Lcd.print("Unknown Mode");
+      Lcd.print("Unknown Mode    ");
     }

     // Render second line
@@ -551,7 +580,7 @@
 }

 int32_t totalseconds(DateTime timestamp) {
-  return ( timestamp.hour() * 360 ) + ( timestamp.minute() * 60 ) + timestamp.second();
+  return ( timestamp.hour() * 360 ) + ( timestamp.minute() * 60 ) + timestamp.second();
 }

 /**
@@ -588,4 +617,3 @@

   Serial.println();
 }
-


add goStraightlineISR() for checklist

add goStraightlineISR() for checklist

--- arduino_motor/mains/mains.ino
+++ arduino_motor/mains/mains.ino
@@ -60,14 +60,27 @@
   //sideEye->test_readings();
   //Serial.print(F("Get Right Reading: ")); Serial.println(sideEye->get_reading_right());
   //sideEye->test_readings();
-  moveForward(80);
+
+
+
+  if (frontEye->get_ulra_reading()<15){
+
+     goStraightlineISR();
+  }
+
+  moveForward(15);
+
+
+
+
+
   //printCounts();
   //turnLeft(90);
   //printCounts();
   //errorCumulator->compass->printAxis();

   //delay(1000);
-
+
   //turnRight(90);
   //moveForward(80);
   //turnLeft(90);
@@ -88,5 +101,19 @@
 }
 ///////////////////////////////////////////////////////////////////////////////////////////////////

+void goStraightlineISR(){
+
+  turnRight(90);
+  moveForward(15);
+  turnLeft(90);
+  moveForward(15);
+  turnLeft(90);
+  moveForward(15);
+  turnRight(90);
+  //finish

+
+
+}
+


Added sound library code, sounds

Added sound library code, sounds

--- Skulleyes.ino
+++ Skulleyes.ino
@@ -20,31 +20,22 @@

   Modified 2014 by Jeff D. Conrad as skulleyes project.
   * Controls two 8x8 eyes.
+  * Plays sounds (commented out).
+  * Might need to remove functionality from sound library to work - mp3 etc.

   http://ledlogic.blogspot.com/2014/10/arduino-8x8-shields.html
  ****************************************************/

+#include <SD.h>
+#include <SPI.h>
+#include <MusicPlayer.h>
 #include <Wire.h>
-#include "Adafruit_LEDBackpack.h"
-#include "Adafruit_GFX.h"
+#include <Adafruit_LEDBackpack.h>
+#include <Adafruit_GFX.h>

 Adafruit_8x8matrix matrix = Adafruit_8x8matrix();

-// Pin 13 has an LED connected on most Arduino boards.
-// give it a name:
-//int led = 12;
-
-int wait = 500;
-
-void setup() {
-  Serial.begin(9600);
-
-  //pinMode(led, OUTPUT);
-
-  randomSeed(analogRead(0));
-
-  matrix.begin(0x70);  // pass in the address
-}
+const int wait = 500;

 static const uint8_t PROGMEM
 eye_off[] =
@@ -147,63 +138,75 @@
   B01111110,
   B00111100
 };
-;
+
+static char* soundFiles[] = {
+  "BOOLEAN.mp3",
+  "DYLNSCRY.mp3",
+  "GHOSTMCH.mp3",
+  "HASKULL.mp3",
+  "ICDEADCD.mp3",
+
+  "JSTNSCAP.mp3",
+  "MNSTERHM.mp3",
+  "NOBODY.mp3",
+  "PUMPKNPI.mp3",
+  "SPIRITS.mp3",
+
+  "TOBNOTB.mp3",
+  "TRVRSCRY.mp3",
+  "UNLBYTES.mp3",
+  "WWW.mp3",
+  "YEARBOO.mp3",
+
+  "TRVRSCRY.mp3"
+};
+
+void setup() {
+  Serial.begin(9600);
+
+  player.begin();
+  player.setVolume(MAXVOL);
+
+  randomSeed(analogRead(0));
+  matrix.begin(0x70);
+}
+
+void eyesWait(int minWait, int maxWait) {
+  delay(random(minWait, maxWait));
+}

 void eyesDraw(const uint8_t *bitmap) {
   matrix.clear();
   matrix.drawBitmap(0, 0, bitmap, 8, 8, LED_ON);
   matrix.writeDisplay();
-  eyesWait();
-}
-
-void eyesWait() {
-  delay(wait);
-}
-
-void eyesRandomWait() {
-  delay(random(1000, 6000));
+  eyesWait(wait, wait);
 }

 void eyesUp() {
-  wait = 500;
-
-  eyesDraw(eye_off);
   eyesDraw(eye_up_left);
   eyesDraw(eye_up_center);
   eyesDraw(eye_up_right);
   eyesDraw(eye_up_center);
   eyesDraw(eye_up_left);
-  eyesDraw(eye_off);
 }

 void eyesMiddle() {
-  wait = 500;
-
-  eyesDraw(eye_off);
   eyesDraw(eye_left);
   eyesDraw(eye_center);
   eyesDraw(eye_right);
   eyesDraw(eye_center);
   eyesDraw(eye_left);
-  eyesDraw(eye_off);
 }

 void eyesDown() {
-  wait = 500;
-
-  eyesDraw(eye_off);
   eyesDraw(eye_down_left);
   eyesDraw(eye_down_center);
   eyesDraw(eye_down_right);
   eyesDraw(eye_down_center);
   eyesDraw(eye_down_left);
-  eyesDraw(eye_off);
 }

 void eyesClock() {
-  wait = 200;
-
-  eyesDraw(eye_off);
   eyesDraw(eye_up_center);
   eyesDraw(eye_up_right);
   eyesDraw(eye_right);
@@ -213,28 +216,24 @@
   eyesDraw(eye_left);
   eyesDraw(eye_up_left);
   eyesDraw(eye_up_center);
+}
+
+void eyesTalk() {
+  int choice = random(16);
+  char* fn = soundFiles[choice];
+  player.playOne(fn);
+  for (int i = 0; i < 4; i++) {
+    eyesDraw(eye_off);
+    eyesDraw(eye_center);
+    eyesWait(100, 300);
+  }
+  //player.play();
+}
+
+void loop() {
   eyesDraw(eye_off);
-}
-
-/*
-void eyesTalk() {
-  eyesDraw(eye_off);
-  eyesDraw(eye_center);
-
-  int choice = random(20,40);
-  for (int i=0; i<choice; i++) {
-    digitalWrite(led, HIGH);
-    delay(random(100, 300));
-    digitalWrite(led, LOW);
-    delay(random(100, 300));
-  }
-
-  eyesDraw(eye_off);
-}
-*/
-
-void loop() {
-  int choice = random(4);
+  //int choice = random(4);
+  int choice = random(3);
   switch (choice) {
     case 0:
       eyesUp();
@@ -248,11 +247,9 @@
     case 3:
       eyesClock();
       break;
-    //case 4:
+    //case 4:
     //  eyesTalk();
     //  break;
-    default:
-      ;
   }
-  eyesRandomWait();
-}
+  eyesDraw(eye_off);
+}


Cleanup the RF69_RESET code to use define

--- arduino/Powermon433/Powermon433.ino
+++ arduino/Powermon433/Powermon433.ino
@@ -266,12 +266,11 @@
 static void resetRf69(void)
 {
 #if defined(DPIN_RF69_RESET)
-  const uint8_t pin = 7;
-  pinMode(pin, OUTPUT);
-  digitalWrite(pin, HIGH);
+  pinMode(DPIN_RF69_RESET, OUTPUT);
+  digitalWrite(DPIN_RF69_RESET, HIGH);
   delayMicroseconds(100);
-  digitalWrite(pin, LOW);
-  pinMode(pin, INPUT);
+  digitalWrite(DPIN_RF69_RESET, LOW);
+  pinMode(DPIN_RF69_RESET, INPUT);
   delay(5);
   Serial.println(F("RFM reset"));
 #endif // DPIN_RF69_RESET


[avr] decoderBusy() should include g_RxDirty so we don't change thresholds in the short intrapacket delay

--- arduino/Powermon433/Powermon433.ino
+++ arduino/Powermon433/Powermon433.ino
@@ -381,7 +381,7 @@

 static bool decoderBusy()
 {
-  return decoder.state || decoder.bit || decoder.pos;
+  return g_RxDirty || decoder.state || decoder.bit || decoder.pos;
 }

 static void decoderAddBit(uint8_t bit)
@@ -634,7 +634,7 @@
       offset = 2;
     else if (g_RxErrCnt > 250)
       offset = 1;
-    else if (g_RxErrCnt < 5)
+    else if (g_RxErrCnt < 1)
       offset = -1;

     if (offset != 0)


Happier

Happier

--- alan/alan.ino
+++ alan/alan.ino
@@ -477,7 +477,6 @@
   Serial.println("STOP!");
   action_state = A_STOPPED;
   motionStop();
-  actionTimeoutDone();
   pingStop();
   whiskersStop();
 }
@@ -569,28 +568,32 @@
  */
 void actionHappy()
 {
-  timer.setTimeout(2000, actionStop);
   if (action_state != A_HAPPY) {
-    actionStop();
     Serial.println("Happy");

     // Set the state, so the action can be handled by the state machine.
     action_state = A_HAPPY;
+
+    actionTimeoutStart(random(500,700));
+    motionRotateLeft(255);
   }
 }

 void actionHappyStateMachine(byte motion_state)
 {
-
+  static byte count = 0;
+
+  // Loop through left & right a few times.
+  if (count > 3) {
+    count = 0;
+    actionStop();
+  }
+
   switch (motion_state) {
-    case M_STOP:
-      // Spin left for random amount of time
-      actionTimeoutStart(random(500,700));
-      motionRotateLeft(255);
-      break;
-
+
     case M_ROTATE_LEFT:
       if (action_done) {
+        count++;
         // Spin right for random amount of time
         actionTimeoutStart(random(500,700));
         motionRotateRight(255);
@@ -599,6 +602,7 @@

     case M_ROTATE_RIGHT:
       if (action_done) {
+        count++;
         // Spin left for random amount of time
         actionTimeoutStart(random(500,700));
         motionRotateLeft(255);
@@ -608,6 +612,7 @@
     default:
       break;
   }
+
 }

 /**
@@ -882,7 +887,16 @@
 ********************************************************************************/

 /* Function returns the button name relating to the received code */
-void irHandleInput(unsigned long code){
+void irHandleInput(unsigned long code)
+{
+  // Debounce the remote buttons.
+  static unsigned long last_millis;
+  unsigned long now = millis();
+  if (now - last_millis < 200) {
+    return;
+  }
+  last_millis = now;
+
   /* Character array used to hold the received button name */
   char CodeName[3];
   /* Is the received code is a repeat code (NEC protocol) */
@@ -920,8 +934,13 @@
     /* Received code is for the  PLAY/PAUSE button */
   case 0xFFC23D:
     strcpy (CodeName, "PL");
-    soundPower();
-    actionTrundle();
+    if (action_state == A_STOPPED) {
+      soundPower();
+      actionTrundle();
+    } else {
+      soundPause();
+      actionStop();
+    }
     break;
     /* Received code is for the EQ button */
   case 0xFFE01F:


Added code for heater

Added code for heater

--- src/HC_NodeMcuCode.ino
+++ src/HC_NodeMcuCode.ino
@@ -407,47 +407,46 @@
     }}}

 // Returns true if heating is required
-boolean checkHeatRequired(float roomTemperature, float targetTemperature, float targetTempHyst) {
-  // Is room too cold ?
-  if (roomTemperature <= (targetTemperature - targetTempHyst))
+boolean checkHeatRequired(float roomTemperature, float targetTemperature, float targetTempHyst, bool poweredState) {
+  // Check if heating is active.
+  if (!poweredState) {
+    // Heating is not active. Room is cooling down
+    // Use Hyst to delay starting heating until we are passed the target to avoid over cycling the heater.
+    if (roomTemperature < (targetTemperature - targetTempHyst))
+      return true; // Heating is now needed
+    else // Else room is not cold enough
+      return false; // Heating not needed yet
+  }
+  else
   {
-    return true;
-  } // Heat needed
-  else // Else room is hot enough
-  {
-    return false;
-  }
-} // No heat needed
+    // Heater is active. Room is heating up.
+    // Use Hyst to delay stopping heating until we are passed the target to avoid over cycling the heater.
+    if (roomTemperature > (targetTemperature + targetTempHyst))
+      return false; // Heating no longer needed
+    else // Else room is not hot enough
+      return true; // Heating is still needed
+  }
+}

 // Returns true if cooling is required
 boolean checkCoolRequired(float roomTemperature, float targetTemperature, float targetTempHyst, bool poweredState) {
-  // Is room too hot ?
-
   // Check if cooling is active.
-  if (!poweredState)
-  {
-    // Cooler is not active
-    // Room is warming up
+  if (!poweredState) {
+    // Cooler is not active. Room is warming up
     // Use Hyst to delay starting cooling until we are passed the target to avoid over cycling the cooler.
     if (roomTemperature > (targetTemperature + targetTempHyst))
-    {
-      return true; // Cooling needed
-    }
+      return true; // Cooling is now needed
     else // Else room is not warm enough
-    {
-      return false; // No cooling needed
-    }
-  }  else  {
-    // Cooler is active
+      return false; // Cooling not needed yet
+  }
+  else
+  {
+    // Cooler is active. Room is cooling down.
     // Use Hyst to delay stopping cooling until we are passed the target to avoid over cycling the cooler.
     if (roomTemperature < (targetTemperature - targetTempHyst))
-    {
-      return false; // No cooling needed
-    }
+      return false; // Cooling no longer needed
     else // Else room is not cold enough
-    {
-      return true; // Cooling needed
-    }
+      return true; // Cooling is still needed
   }
 }


glove update

glove update

--- src/MIDI_CC/ADXL_locking_pan/ADXL_locking_pan.ino
+++ src/MIDI_CC/ADXL_locking_pan/ADXL_locking_pan.ino
@@ -192,31 +192,17 @@

      if(count%2==0)
       serialcomm(event.acceleration.z, xreading, count);
-     /*{//if switch is not pressed or pressed even number of times then send the values according to accelerometer z values
-        Serial.print(event.acceleration.z);
-        Serial.print(" ");
-        Serial.print(xreading);
-        Serial.print(" ");
-        Serial.println(count);
-     }
-     */
+      //if switch is not pressed or pressed even number of times then send the values according to accelerometer z values

-    else
+     else
         serialcomm(zreading,xreading,count);
-      /*{//if button is presssed once or odd numberof times then send the value of reading when it is pressed(zreading)
-      Serial.print(zreading);
-      Serial.print(" ");
-      Serial.print(xreading);
-      Serial.print(" ");
-      Serial.println(count);
-      }
-      */

       delay(400);
-   /*MESSAGE FROM ARDUINO TO COM PORT IS IN  THE FORM OF a string "zvalue<space>xvalue<space>count<newline character>"
-    In python I used a function called split() which will split a string in substrings whereever it sees a whitespace character...and puts all substrings in a list
-    eg:if my msg is "-10 10 2\n" then in pyhon read it using readline() and stored it in a variable called reading
-    reading=readin.split() gives me the list reading containing the substrings "-10" and "10" and "2"
+   /* Arduino Packet Syntax:  "zvalue <space> xvalue <space> count <newline character> "
+    Split() method was used in Python to generate a list "zvalue, xvalue, count"
+    reading= ser.readline.rstrip().split()
+    print reading
+    will give output "-10, 10, 2"
     */


more test code removed, silly me...

more test code removed, silly me...

--- examples/RF12/roomNode/roomNode.ino
+++ examples/RF12/roomNode/roomNode.ino
@@ -30,8 +30,6 @@
 // set the sync mode to 2 if the fuses are still the Arduino default
 // mode 3 (full powerdown) can only be used with 258 CK startup fuses
 #define RADIO_SYNC_MODE 2
-
-#define rf12_sleep(x)

 // The scheduler makes it easy to perform various tasks at various times:

@@ -68,7 +66,7 @@
 #if PIR_PORT
     #define PIR_HOLD_TIME   30  // hold PIR value this many seconds after change
     #define PIR_PULLUP      1   // set to one to pull-up the PIR input pin
-    #define PIR_FLIP        1   // 0 or 1, to match PIR reporting high or low
+    #define PIR_FLIP        0   // 0 or 1, to match PIR reporting high or low

     class PIR : public Port {
         volatile byte value, changed;


smoothing, adaptive window adjustment

smoothing, adaptive window adjustment

--- examples/RF12/syncRecv/syncRecv.ino
+++ examples/RF12/syncRecv/syncRecv.ino
@@ -11,6 +11,8 @@
 #define SEND_ID     9             // listen for this node ID

 #define CYCLE_TIME  3000          // expected cycle, milliseconds
+#define MIN_WIN     8             // minimum window size, power of 2
+#define MAX_WIN     1024          // maximum window size, power of 2

 #define EEADDR ((word*) 0)        // save estimate at this EEPROM address

@@ -22,9 +24,12 @@
 ISR(WDT_vect) { Sleepy::watchdogEvent(); }

 static void radioSleep (word ms) {
+  bitSet(DDRB, 1);
+  bitSet(PORTB, 1); // LED off
   rf12_sleep(RF12_SLEEP);
   Sleepy::loseSomeTime(ms);
   rf12_sleep(RF12_WAKEUP);
+  bitClear(PORTB, 1); // LED on
 }

 static bool isDesiredPacket () {
@@ -51,9 +56,10 @@
   estimate = lastRecv - start;
   int offset = (estimate - lowEstimate) - window;

-  Serial.print(" got "); Serial.print(estimate);
-  Serial.print(", window = "); Serial.print(window);
-  Serial.print(", offset = "); Serial.println(offset);
+  Serial.print(" t "); Serial.print(lastRecv / 1000);
+  Serial.print(" e "); Serial.print(estimate);
+  Serial.print(" w "); Serial.print(window);
+  Serial.print(" o "); Serial.println(offset);
   return true;
 }

@@ -63,53 +69,68 @@
   if (estimate < CYCLE_TIME - CYCLE_TIME/5 ||
       estimate > CYCLE_TIME + CYCLE_TIME/5)
     estimate = CYCLE_TIME;
-  Serial.print("start estimate = "); Serial.println(estimate);
+  Serial.print("start "); Serial.println(estimate);
   // narrow down estimate from 20 % -> 2 %
   window = estimate / 5;
-  while (window >= 16)
+  while (window >= 2 * MIN_WIN)
     if (estimateWithWatchdog())
       window /= 2;
-  // save best estimaet so far
+  // save best estimate so far
   eeprom_write_word(EEADDR, estimate);
-  Serial.print("save estimate "); Serial.println(estimate);
+  Serial.print("save "); Serial.println(estimate);
 }

 void setup () {
   Serial.begin(57600);
-  Serial.println("\n[syncRecv]");
+  Serial.println("\n[syncRecv] " __TIME__);
   rf12_initialize(1, SEND_FREQ, SEND_GROUP); // we never send
   chooseEstimate();
+  Serial.flush(); delayMicroseconds(250);
+  window = MIN_WIN;
 }

 void loop () {
   uint32_t now = millis();
+  // make a guess as to how many packets we lost
   byte lost = (now - lastRecv + estimate/2) / estimate;
-  Serial.print(" #"); Serial.print(lost);
-  if (lost > 20)
+
+  // if things are really bad, resync from scratch
+  if (lost > 20) {
     chooseEstimate();
-  else {
-    uint32_t predict = lastRecv + (lost + 1) * estimate;
-    word sleep = predict - now - window;
+    return;
+  }

-    Serial.print(" s "); Serial.print(sleep);
-    Serial.flush(); delayMicroseconds(250);
+  // double the window every 4 additional packets lost
+  if (lost > 0 && lost % 4 == 0 && window < MAX_WIN)
+    window *= 2;

-    radioSleep(sleep);
+  // make a prediction for when the next packet should arrive
+  uint32_t predict = lastRecv + (lost + 1) * estimate;
+  word sleep = predict - now - (lost ? 0 : window);
+  radioSleep(sleep);

-    uint32_t recvTime;
-    do {
-      recvTime = millis();
-      if (recvTime > predict + window)
-        return;
-    } while (!isDesiredPacket());
+  // listen to the radio until one window past predicted time
+  uint32_t recvTime;
+  do {
+    recvTime = millis();
+    if (recvTime > predict + window)
+      return;
+  } while (!isDesiredPacket());

-    estimate = (recvTime - lastRecv) / (lost + 1);
-    int offset = (estimate - sleep) - window;
-    lastRecv = recvTime;
+  // adjust our estimate and prepare for more packets
+  word newEst = (recvTime - lastRecv) / (lost + 1);
+  estimate = (5 * estimate + newEst) / 6; // 6-fold smoothing
+  int offset = (estimate - sleep) - window;
+  lastRecv = recvTime;

-    Serial.print(" e "); Serial.print(estimate);
-    Serial.print(" w "); Serial.print(window);
-    Serial.print(" o "); Serial.print(offset);
-    Serial.print(" rf "); Serial.println(offset + window);
-  }
+  Serial.print(" n "); Serial.print(lost);
+  Serial.print(" e "); Serial.print(estimate);
+  Serial.print(" w "); Serial.print(window);
+  Serial.print(" o "); Serial.print(offset);
+  Serial.print(" rf "); Serial.println(offset + window);
+  Serial.flush(); delayMicroseconds(250);
+
+  // successful reception means we can narrow down the window
+  if (window > MIN_WIN)
+    window /= 2;
 }


Add more SD performance information.

Add more SD performance information.


TODO-728: TDD!

TODO-728: TDD!

Need to create RX counter for new association
set to all zeros by default.

--- test_SECFRAME/test_SECFRAME.ino
+++ test_SECFRAME/test_SECFRAME.ino
@@ -897,6 +897,9 @@
   AssertIsEqual(0, OTV0P2BASE::getNextMatchingNodeID(0, NULL, 0, NULL));
   for(uint8_t i = 0; i <= sizeof(ID0); ++i)
     { AssertIsEqual(0, OTV0P2BASE::getNextMatchingNodeID(0, ID0, i, NULL)); }
+  // Check that RX msg count for new association is OK, and all zeros.
+  AssertIsTrue(OTRadioLink::SimpleSecureFrame32or0BodyV0p2::getInstance().getLastRXMessageCounter(ID0, mcbuf));
+  AssertIsEqual(0, memcmp(mcbuf, zeroKey, sizeof(mcbuf)));
   const uint8_t ID1[] = { 0x88, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0x8f };
   AssertIsEqual(1, OTV0P2BASE::addNodeAssociation(ID1));
   AssertIsEqual(2, OTV0P2BASE::countNodeAssociations());


Amend explanation of literals.

Amend explanation of literals.

--- Dremelfuge.ino
+++ Dremelfuge.ino
@@ -54,15 +54,24 @@
   lcd.begin(LCD_COLUMNS, LCD_ROWS);

   /* Explanation of `F()` macro and contants/literals:
+    Note: Literals are not temporaries.
     All literals, at least in C, are obviously constants--their values can't be
     changed during program execution--and so in the programming sense are
-    unnamed, unchangeable "variables." And, like all variables, literals are
-    stored in RAM.
-    This is a problem when dealing with string literals, which are const char
-    arrays that can take up a lot of RAM without contributing anything to the
-    program! All we want to do with string literals is print them, but they come
-    at a huge RAM cost, so does that mean that we shouldn't make any MCU projects
-    with text or GUI involved? No! Enter `F()`:
+    unnamed, unchangeable "variables." And like all variables, literals are
+    stored in memory (RAM by default). However, in order for the value of a
+    literal to always be remembered each time the value is needed in the current
+    scope (in a recurring function call for instance), literals are also
+    statically allocated (see giant comment below for more info on `static`). So,
+    `int bar = 17;` is the same as `static const int foo = 17; bar = foo;`--
+    Using unnamed literals is the exact same thing as using const variables,
+    except the former is worse because literal values are unnamed and so without
+    context, making them seem "magical" where they appear.
+
+    Literals being stored in RAM is problematic when dealing with string
+    literals, which are const char arrays that can take up a lot of RAM without
+    contributing anything to the program! All we want to do with string literals
+    is to print them, but they come at a huge RAM cost, so does that mean that we
+     shouldn't make any MCU projects with text or GUI involved? No! Enter `F()`:
     `F()` is a macro (for more complex inline code) for AVR MCUs that tells the
     compiler to store string literals in flash memory instead of RAM, and when it
     comes time to use that string literal in your program, the MCU will retrieve


Updated mic code to working version

Updated mic code to working version


blink ok with delay and response

blink ok with delay and response

--- scripts-arduino/bp_led_lp.ino
+++ scripts-arduino/bp_led_lp.ino
@@ -15,9 +15,8 @@
 int button_pressed_counter;         // press running duration
 boolean button_was_pressed;         // previous state

-long previousMillis = 0;
-long interval = 100;           // interval at which to blink (milliseconds)
-
+boolean serialReadTemp = false;
+boolean isSync = false;
 // ######## ENUM ########
 enum {
     EV_NONE=0,
@@ -30,7 +29,8 @@
     VAL_ON = 1,
     VAL_DESC = 2,
     VAL_SYNC = 3,
-    VAL_END_SYNC = 4
+    VAL_END_SYNC = 4,
+    VAL_WAIT_SYNC = 5
 };
 // ######## SETUP ########
 void setup() {
@@ -105,10 +105,23 @@
     Serial.println(VAL_SYNC);
 }
 void turnBlink(){
-   for (int i=0; i <= 255; i++){
-      digitalWrite(LED_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
-      delay(100);               // wait for a second
-      digitalWrite(LED_PIN, LOW);    // turn the LED off by making the voltage LOW
-      delay(100);               // wait for a second
-   }
+    for (int i=0; i <= 255; i++){
+        if(!isSync){
+            if(serialReadTemp != VAL_END_SYNC){
+                int serialReadTemp = Serial.read();
+
+                if (serialReadTemp == 52){
+                    isSync = true;
+                }
+                digitalWrite(LED_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
+                delay(100);               // wait for a second
+                digitalWrite(LED_PIN, LOW);    // turn the LED off by making the voltage LOW
+                delay(100);               // wait for a second
+            }
+        }
+        else{
+            Serial.println(VAL_END_SYNC);
+            break;
+        }
+    }
 }


Rearrange MazeRunner functions

Rearrange MazeRunner functions

--- src/MazeRunner/MazeRunner.ino
+++ src/MazeRunner/MazeRunner.ino
@@ -3,19 +3,8 @@

 Car car;

-void setup() {
-  car.stop();
-  car.lightOff();
-}
-
-void go();
-void loop() {
-  if(car.buttonPressed()) {
-    go();
-  }
-}
-
 void go() {
+  //Alter the code in this function to make the car drive as desired
   delay(1000);
   car.forward(2000);
   car.turnRight(800);
@@ -24,3 +13,15 @@
   car.stop();
 }

+void setup() {
+  car.stop();
+  car.lightOff();
+}
+
+void loop() {
+  if(car.buttonPressed()) {
+    go();
+  }
+}
+
+


Silly mistake with characters and strings, try again

--- src/WiFiSensor/WiFiSensor.ino
+++ src/WiFiSensor/WiFiSensor.ino
@@ -156,11 +156,11 @@
         topicname += String("/");
         snprintf(msg, 25, "%s", String(lastmeasurement.temperature).c_str());
         if(client.publish( (topicname + mqtttemperaturetopic).c_str(), msg)){
-			Serial.println("Successful Publish Data: " + (topicname + mqtttemperaturetopic).c_str() );
+			Serial.println("Successful Published Data: " + topicname + mqtttemperaturetopic + " Value: " + msg );
 		}
         snprintf(msg, 75, "%s", String(lastmeasurement.humidity).c_str());
         if(client.publish((topicname + mqtthumiditytopic).c_str(), msg)){
-			Serial.println("Successful Published Data 2: " + (topicname + mqtthumiditytopic).c_str() );
+			Serial.println("Successful Published Data 2: " + topicname + mqtthumiditytopic + " Value: " + msg );
 		}
       }
     }


Improving clapMeter

Improving clapMeter

--- sketches/clapMeter/clapMeter.ino
+++ sketches/clapMeter/clapMeter.ino
@@ -1,4 +1,9 @@
 /*
+LCD - no combina bien con pintar tambien en la matrix porque no se refresca bien
+SENSORES - los probamos en la ofi por no andar gritando en casa
+BARRAS
+MEJORAR PALABRAS
+
   The circuit:
   * A connect to digital 2
   * B connect to digital 3
@@ -18,11 +23,9 @@

 #define SOUND_SENSOR A0
 #define SOUND_SENSOR_2 A2
-#define THRESHOLD_FAIL 400 //The threshold to turn the led on 400.00*5/1024 = 1.95v
-#define THRESHOLD_GOOD 400
-#define THRESHOLD_WIN 600
-
-#define LCD_OUT 8
+#define THRESHOLD_FAIL 100 //The threshold to turn the led on 400.00*5/1024 = 1.95v
+#define THRESHOLD_GOOD 200
+#define THRESHOLD_WIN 300

 #define RowA 2
 #define RowB 3
@@ -46,16 +49,10 @@
 int badClap = 0;
 int result = 0;
 boolean scanning = true;
-SoftwareSerial lcd(99, LCD_OUT);

 void setup()
 {
     Serial.begin(9600);
-
-    // INIT LCD
-    pinMode(LCD_OUT, OUTPUT);
-    lcd.begin(9600);
-    lcd_init();

     // INIT SOUND SENSORS
     pinMode(SOUND_SENSOR, INPUT);
@@ -120,11 +117,24 @@
             if(sensorValue > THRESHOLD_FAIL){
                 clapMeter = clapMeter + sensorValue;
                 goodClap++;
+                //setHistogram(sensorValue);
+                hz = zero;
+                for(row=0;row<16;row++){
+                    for (int i=0;i<2;i++){
+                        SPI.transfer(~(hz[i*32+row*2]));
+                        SPI.transfer(~(hz[i*32+row*2+1]));
+                    }
+                    digitalWrite(OE,HIGH);
+                    hc138sacn(row);
+                    digitalWrite(STB,LOW);
+                    digitalWrite(STB,HIGH);
+                    digitalWrite(OE,LOW);
+                }
             } else {
                 if(badClap<100){
                     badClap++;
                 } else {
-                    keep = false;
+                    //keep = false;
                 }
             }

@@ -137,42 +147,6 @@
     scanning = false;

     return result;
-}
-
-        /*
-        setHistogram(sensorValue);
-
-        for(row=0;row<16;row++){
-            for (int i=0;i<2;i++){
-                SPI.transfer(~(hz[i*32+row*2]));
-                SPI.transfer(~(hz[i*32+row*2+1]));
-            }
-            digitalWrite(OE,HIGH);
-            hc138sacn(row);
-            digitalWrite(STB,LOW);
-            digitalWrite(STB,HIGH);
-            delayMicroseconds(500);
-            digitalWrite(OE,LOW);
-            delayMicroseconds(500);
-        }
-        */
-
-
-void lcd_init()
-{
-    lcd.write(0XFE);
-    lcd.write(0X01);
-
-}
-
-void lcd_blink(int value)
-{
-    for(int i=0; i<=10; i++){
-        lcd_init();
-        //delay(200);
-        lcd.print(value);
-        //delay(200);
-    }
 }

 void hc138sacn(byte r){
@@ -209,7 +183,7 @@
       hz = six;
      }
      else if (normValue == 7){
-      hz = seven;
+      hz =  seven;
      }
      else if (normValue == 8){
       hz = eight;


Version 3.3 - 1st June 2020

Version 3.3 - 1st June 2020

--- ulisp.ino
+++ ulisp.ino
@@ -1,5 +1,5 @@
-/* uLisp AVR Version 3.2 - www.ulisp.com
-   David Johnson-Davies - www.technoblogy.com - 29th April 2020
+/* uLisp AVR Version 3.3 - www.ulisp.com
+   David Johnson-Davies - www.technoblogy.com - 1st June 2020

    Licensed under the MIT license: https://opensource.org/licenses/MIT
 */
@@ -75,6 +75,13 @@
 enum type { ZZERO=0, SYMBOL=2, NUMBER=4, STREAM=6, CHARACTER=8, FLOAT=10, STRING=12, PAIR=14 };  // STRING and PAIR must be last
 enum token { UNUSED, BRA, KET, QUO, DOT };
 enum stream { SERIALSTREAM, I2CSTREAM, SPISTREAM, SDSTREAM };
+
+// Stream names used by printobject
+const char serialstream[] PROGMEM = "serial";
+const char i2cstream[] PROGMEM = "i2c";
+const char spistream[] PROGMEM = "spi";
+const char sdstream[] PROGMEM = "sd";
+PGM_P const streamname[] PROGMEM = {serialstream, i2cstream, spistream, sdstream};

 enum function { NIL, TEE, NOTHING, OPTIONAL, AMPREST, LAMBDA, LET, LETSTAR, CLOSURE, SPECIAL_FORMS, QUOTE,
 DEFUN, DEFVAR, SETQ, LOOP, RETURN, PUSH, POP, INCF, DECF, SETF, DOLIST, DOTIMES, TRACE, UNTRACE,
@@ -115,7 +122,7 @@
 typedef object *(*fn_ptr_type)(object *, object *);

 typedef struct {
-  const char *string;
+  PGM_P string;
   fn_ptr_type fptr;
   uint8_t minmax;
 } tbl_entry_t;
@@ -154,7 +161,7 @@
   #define EEPROMSIZE 256                  /* Bytes */
   #define SYMBOLTABLESIZE BUFFERSIZE      /* Bytes - no long symbols */
   #define STACKDIFF 320
-
+
 #elif defined(ARDUINO_AVR_ATmega4809)     /* Curiosity Nano using MegaCoreX */
   #define Serial Serial3
   #define WORKSPACESIZE 1066-SDSIZE       /* Objects (4*bytes) */
@@ -167,7 +174,7 @@
   #define EEPROMSIZE 256                  /* Bytes */
   #define SYMBOLTABLESIZE BUFFERSIZE      /* Bytes - no long symbols */
   #define STACKDIFF 320
-
+
 #endif

 object Workspace[WORKSPACESIZE] WORDALIGNED;
@@ -292,7 +299,7 @@
 object *character (char c) {
   object *ptr = myalloc();
   ptr->type = CHARACTER;
-  ptr->integer = c;
+  ptr->chars = c;
   return ptr;
 }

@@ -313,7 +320,7 @@
 object *newsymbol (symbol_t name) {
   for (int i=WORKSPACESIZE-1; i>=0; i--) {
     object *obj = &Workspace[i];
-    if (obj->type == SYMBOL && obj->name == name) return obj;
+    if (symbolp(obj) && obj->name == name) return obj;
   }
   return symbol(name);
 }
@@ -692,7 +699,7 @@

 int checkchar (symbol_t name, object *obj) {
   if (!characterp(obj)) error(name, PSTR("argument is not a character"), obj);
-  return obj->integer;
+  return obj->chars;
 }

 int isstream (object *obj){
@@ -858,13 +865,6 @@
     env = cdr(env);
   }
   return nil;
-}
-
-bool boundp (object *var, object *env) {
-  symbol_t varname = var->name;
-  if (value(varname, env) != NULL) return true;
-  if (value(varname, GlobalEnv) != NULL) return true;
-  return false;
 }

 object *findvalue (object *var, object *env) {
@@ -923,10 +923,7 @@
       } else {
         if (args == NULL) {
           if (optional) value = nil;
-          else {
-            if (name) error2(name, toofewargs);
-            else error2(0, PSTR("function has too few arguments"));
-          }
+          else error2(name, toofewargs);
         } else { value = first(args); args = cdr(args); }
       }
       push(cons(var,value), *env);
@@ -934,10 +931,7 @@
     }
     params = cdr(params);
   }
-  if (args != NULL) {
-    if (name) error2(name, toomanyargs);
-    else error2(0, PSTR("function has too many arguments"));
-  }
+  if (args != NULL) error2(name, toomanyargs);
   if (trace) { pserial(')'); pln(pserial); }
   // Do an implicit progn
   if (tc) push(nil, *env);
@@ -969,26 +963,29 @@
 object **place (symbol_t name, object *args, object *env) {
   if (atom(args)) return &cdr(findvalue(args, env));
   object* function = first(args);
-  if (issymbol(function, CAR) || issymbol(function, FIRST)) {
-    object *value = eval(second(args), env);
-    if (!listp(value)) error(name, PSTR("can't take car"), value);
-    return &car(value);
-  }
-  if (issymbol(function, CDR) || issymbol(function, REST)) {
-    object *value = eval(second(args), env);
-    if (!listp(value)) error(name, PSTR("can't take cdr"), value);
-    return &cdr(value);
-  }
-  if (issymbol(function, NTH)) {
-    int index = checkinteger(NTH, eval(second(args), env));
-    object *list = eval(third(args), env);
-    if (atom(list)) error(name, PSTR("second argument to nth is not a list"), list);
-    while (index > 0) {
-      list = cdr(list);
-      if (list == NULL) error2(name, PSTR("index to nth is out of range"));
-      index--;
-    }
-    return &car(list);
+  if (symbolp(function)) {
+    symbol_t fname = function->name;
+    if (fname == CAR || fname == FIRST) {
+      object *value = eval(second(args), env);
+      if (!listp(value)) error(name, PSTR("can't take car"), value);
+      return &car(value);
+    }
+    if (fname == CDR || fname == REST) {
+      object *value = eval(second(args), env);
+      if (!listp(value)) error(name, PSTR("can't take cdr"), value);
+      return &cdr(value);
+    }
+    if (fname == NTH) {
+      int index = checkinteger(NTH, eval(second(args), env));
+      object *list = eval(third(args), env);
+      if (atom(list)) error(name, PSTR("second argument to nth is not a list"), list);
+      while (index > 0) {
+        list = cdr(list);
+        if (list == NULL) error2(name, PSTR("index to nth is out of range"));
+        index--;
+      }
+      return &car(list);
+    }
   }
   error2(name, PSTR("illegal place"));
   return nil;
@@ -996,13 +993,13 @@

 // Checked car and cdr

-inline object *carx (object *arg) {
+object *carx (object *arg) {
   if (!listp(arg)) error(0, PSTR("can't take car"), arg);
   if (arg == nil) return nil;
   return car(arg);
 }

-inline object *cdrx (object *arg) {
+object *cdrx (object *arg) {
   if (!listp(arg)) error(0, PSTR("can't take cdr"), arg);
   if (arg == nil) return nil;
   return cdr(arg);
@@ -1257,9 +1254,9 @@

 void checkanalogwrite (int pin) {
 #if defined(__AVR_ATmega328P__)
-  if (!(pin>=3 && pin<=11 && pin!=4 && pin!=7 && pin!=8)) error(ANALOGWRITE, invalidpin, number(pin));
+  if (!((pin>=2 && pin<=13) || pin==4 || pin==7 || pin==8)) error(ANALOGWRITE, invalidpin, number(pin));
 #elif defined(__AVR_ATmega2560__)
-  if (!((pin>=2 && pin<=13) || (pin>=44 && pin <=46))) error(ANALOGWRITE, invalidpin, number(pin));
+  if (!((pin>=2 && pin<=13) || (pin>=44 && pin<=46))) error(ANALOGWRITE, invalidpin, number(pin));
 #elif defined(__AVR_ATmega1284P__)
   if (!(pin==3 || pin==4 || pin==6 || pin==7 || (pin>=12 && pin<=15))) error(ANALOGWRITE, invalidpin, number(pin));
 #elif defined(ARDUINO_AVR_NANO_EVERY)
@@ -1432,7 +1429,7 @@
 }

 const int ppspecials = 15;
-const char ppspecial[ppspecials] PROGMEM =
+const uint8_t ppspecial[ppspecials] PROGMEM =
   { DOTIMES, DOLIST, IF, SETQ, TEE, LET, LETSTAR, LAMBDA, WHEN, UNLESS, WITHI2C, WITHSERIAL, WITHSPI, WITHSDCARD, FORMILLIS };

 void supersub (object *form, int lm, int super, pfun_t pfun) {
@@ -1545,36 +1542,27 @@

 // Accessors

-object *sp_incf (object *args, object *env) {
-  checkargs(INCF, args);
-  object **loc = place(INCF, first(args), env);
-  int increment = 1;
-  int result = checkinteger(INCF, *loc);
+object *incfdecf (symbol_t name, object *args, int increment, object *env) {
+  checkargs(name, args);
+  object **loc = place(name, first(args), env);
+  int result = checkinteger(name, *loc);
   args = cdr(args);
-  if (args != NULL) increment = checkinteger(INCF, eval(first(args), env));
+  if (args != NULL) increment = checkinteger(name, eval(first(args), env)) * increment;
   #if defined(checkoverflow)
-  if (increment < 1) { if (INT_MIN - increment > result) error2(INCF, overflow); }
-  else { if (INT_MAX - increment < result) error2(INCF, overflow); }
+  if (increment < 1) { if (INT_MIN - increment > result) error2(name, overflow); }
+  else { if (INT_MAX - increment < result) error2(name, overflow); }
   #endif
   result = result + increment;
   *loc = number(result);
   return *loc;
 }

+object *sp_incf (object *args, object *env) {
+  incfdecf(INCF, args, 1, env);
+}
+
 object *sp_decf (object *args, object *env) {
-  checkargs(DECF, args);
-  object **loc = place(DECF, first(args), env);
-  int decrement = 1;
-  int result = checkinteger(DECF, *loc);
-  args = cdr(args);
-  if (args != NULL) decrement = checkinteger(DECF, eval(first(args), env));
-  #if defined(checkoverflow)
-  if (decrement < 1) { if (INT_MAX + decrement < result) error2(DECF, overflow); }
-  else { if (INT_MIN + decrement > result) error2(DECF, overflow); }
-  #endif
-  result = result - decrement;
-  *loc = number(result);
-  return *loc;
+  incfdecf(DECF, args, -1, env);
 }

 object *sp_setf (object *args, object *env) {
@@ -2069,7 +2057,7 @@
     last = cdr(last);
   }
   object *arg = car(last);
-  if (!listp(arg)) error(APPLY, PSTR("last argument is not a list"), arg);
+  if (!listp(arg)) error(APPLY, notalist, arg);
   cdr(previous) = arg;
   return apply(APPLY, first(args), cdr(args), env);
 }
@@ -2449,11 +2437,6 @@
   return integerp(first(args)) ? tee : nil;
 }

-object *fn_numberp (object *args, object *env) {
-  (void) env;
-  return integerp(first(args)) ? tee : nil;
-}
-
 // Characters

 object *fn_char (object *args, object *env) {
@@ -2730,7 +2713,7 @@

 object *fn_break (object *args, object *env) {
   (void) args;
-  pfstring(PSTR("\rBreak!\r"), pserial);
+  pfstring(PSTR("\nBreak!\n"), pserial);
   BreakLevel++;
   repl(env);
   BreakLevel--;
@@ -2845,7 +2828,7 @@
   pint(Freespace - initial, pserial);
   pfstring(PSTR(" bytes, Time: "), pserial);
   pint(elapsed, pserial);
-  pfstring(PSTR(" us\r"), pserial);
+  pfstring(PSTR(" us\n"), pserial);
   return nil;
 }

@@ -3038,50 +3021,56 @@
   int len = stringlength(formatstr);
   uint8_t n = 0, width = 0, w, bra = 0;
   char pad = ' ';
-  bool tilde = false, comma, quote;
+  bool tilde = false, mute = false, comma, quote;
   while (n < len) {
     char ch = nthchar(formatstr, n);
     char ch2 = ch & ~0x20; // force to upper case
     if (tilde) {
-      if (comma && quote) { pad = ch; comma = false, quote = false; }
-      else if (ch == '\'') {
-        if (comma) quote = true;
-        else formaterr(formatstr, PSTR("quote not valid"), n);
-      }
-      else if (ch == '~') { pfun('~'); tilde = false; }
-      else if (ch >= '0' && ch <= '9') width = width*10 + ch - '0';
-      else if (ch == ',') comma = true;
-      else if (ch == '%') { pln(pfun); tilde = false; }
-      else if (ch == '&') { pfl(pfun); tilde = false; }
-      else if (ch == '{') {
-        if (save != NULL) formaterr(formatstr, PSTR("can't nest ~{"), n);
-        if (args == NULL) formaterr(formatstr, noargument, n);
-        if (!listp(first(args))) formaterr(formatstr, notalist, n);
-        save = args; args = first(args); bra = n; tilde = false;
-      }
-      else if (ch == '}') {
+     if (ch == '}') {
         if (save == NULL) formaterr(formatstr, PSTR("no matching ~{"), n);
         if (args == NULL) { args = cdr(save); save = NULL; } else n = bra;
-        tilde = false;
+        mute = false; tilde = false;
+      }
+      else if (!mute) {
+        if (comma && quote) { pad = ch; comma = false, quote = false; }
+        else if (ch == '\'') {
+          if (comma) quote = true;
+          else formaterr(formatstr, PSTR("quote not valid"), n);
+        }
+        else if (ch == '~') { pfun('~'); tilde = false; }
+        else if (ch >= '0' && ch <= '9') width = width*10 + ch - '0';
+        else if (ch == ',') comma = true;
+        else if (ch == '%') { pln(pfun); tilde = false; }
+        else if (ch == '&') { pfl(pfun); tilde = false; }
+        else if (ch == '^') {
+          if (save != NULL && args == NULL) mute = true;
+          tilde = false;
+        }
+        else if (ch == '{') {
+          if (save != NULL) formaterr(formatstr, PSTR("can't nest ~{"), n);
+          if (args == NULL) formaterr(formatstr, noargument, n);
+          if (!listp(first(args))) formaterr(formatstr, notalist, n);
+          save = args; args = first(args); bra = n; tilde = false;
+        }
+        else if (ch2 == 'A' || ch2 == 'S' || ch2 == 'D' || ch2 == 'G' || ch2 == 'X') {
+          if (args == NULL) formaterr(formatstr, noargument, n);
+          object *arg = first(args); args = cdr(args);
+          uint8_t aw = atomwidth(arg);
+          if (width < aw) w = 0; else w = width-aw;
+          tilde = false;
+          if (ch2 == 'A') { prin1object(arg, pfun); indent(w, pad, pfun); }
+          else if (ch2 == 'S') { printobject(arg, pfun); indent(w, pad, pfun); }
+          else if (ch2 == 'D' || ch2 == 'G') { indent(w, pad, pfun); prin1object(arg, pfun); }
+          else if (ch2 == 'X' && integerp(arg)) {
+            uint8_t hw = hexwidth(arg); if (width < hw) w = 0; else w = width-hw;
+            indent(w, pad, pfun); pinthex(arg->integer, pfun);
+          } else if (ch2 == 'X') { indent(w, pad, pfun); prin1object(arg, pfun); }
+          tilde = false;
+        } else formaterr(formatstr, PSTR("invalid directive"), n);
       }
-      else if (ch2 == 'A' || ch2 == 'S' || ch2 == 'D' || ch2 == 'G' || ch2 == 'X') {
-        if (args == NULL) formaterr(formatstr, noargument, n);
-        object *arg = first(args); args = cdr(args);
-        uint8_t aw = atomwidth(arg);
-        if (width < aw) w = 0; else w = width-aw;
-        tilde = false;
-        if (ch2 == 'A') { prin1object(arg, pfun); indent(w, pad, pfun); }
-        else if (ch2 == 'S') { printobject(arg, pfun); indent(w, pad, pfun); }
-        else if (ch2 == 'D' || ch2 == 'G') { indent(w, pad, pfun); prin1object(arg, pfun); }
-        else if (ch2 == 'X' && integerp(arg)) {
-          uint8_t hw = hexwidth(arg); if (width < hw) w = 0; else w = width-hw;
-          indent(w, pad, pfun); pinthex(arg->integer, pfun);
-        } else if (ch2 == 'X') { indent(w, pad, pfun); prin1object(arg, pfun); }
-        tilde = false;
-      } else formaterr(formatstr, PSTR("invalid directive"), n);
     } else {
       if (ch == '~') { tilde = true; pad = ' '; width = 0; comma = false; quote = false; }
-      else pfun(ch);
+      else if (!mute) pfun(ch);
     }
     n++;
   }
@@ -3400,7 +3389,7 @@
   { string100, fn_oddp, 0x11 },
   { string101, fn_evenp, 0x11 },
   { string102, fn_integerp, 0x11 },
-  { string103, fn_numberp, 0x11 },
+  { string103, fn_integerp, 0x11 },
   { string104, fn_char, 0x22 },
   { string105, fn_charcode, 0x11 },
   { string106, fn_codechar, 0x11 },
@@ -3582,7 +3571,7 @@
     if ((name == LET) || (name == LETSTAR)) {
       int TCstart = TC;
       object *assigns = first(args);
-      if (!listp(assigns)) error(name, PSTR("first argument is not a list"), assigns);
+      if (!listp(assigns)) error(name, notalist, assigns);
       object *forms = cdr(args);
       object *newenv = env;
       push(newenv, GCStack);
@@ -3708,8 +3697,12 @@
     pfun('#'); pfun('\\');
     if (c > 32) pfun(c);
     else {
-      const char *p = ControlCodes;
+      PGM_P p = ControlCodes;
+      #if defined(__AVR_ATmega4809__) || defined(ARDUINO_AVR_ATmega4809)
       while (c > 0) {p = p + strlen(p) + 1; c--; }
+      #else
+      while (c > 0) {p = p + strlen_P(p) + 1; c--; }
+      #endif
       pfstring(p, pfun);
     }
   }
@@ -3780,38 +3773,40 @@
   if (LastPrint != '\n') pfun('\n');
 }

+void plist (object *form, pfun_t pfun) {
+  pfun('(');
+  printobject(car(form), pfun);
+  form = cdr(form);
+  while (form != NULL && listp(form)) {
+    pfun(' ');
+    printobject(car(form), pfun);
+    form = cdr(form);
+  }
+  if (form != NULL) {
+    pfstring(PSTR(" . "), pfun);
+    printobject(form, pfun);
+  }
+  pfun(')');
+}
+
+void pstream (object *form, pfun_t pfun) {
+  pfun('<');
+  pfstring(streamname[(form->integer)>>8], pfun);
+  pfstring(PSTR("-stream "), pfun);
+  pint(form->integer & 0xFF, pfun);
+  pfun('>');
+}
+
 void printobject (object *form, pfun_t pfun) {
   if (form == NULL) pfstring(PSTR("nil"), pfun);
   else if (listp(form) && issymbol(car(form), CLOSURE)) pfstring(PSTR("<closure>"), pfun);
-  else if (listp(form)) {
-    pfun('(');
-    printobject(car(form), pfun);
-    form = cdr(form);
-    while (form != NULL && listp(form)) {
-      pfun(' ');
-      printobject(car(form), pfun);
-      form = cdr(form);
-    }
-    if (form != NULL) {
-      pfstring(PSTR(" . "), pfun);
-      printobject(form, pfun);
-    }
-    pfun(')');
-  } else if (integerp(form)) pint(form->integer, pfun);
+  else if (listp(form)) plist(form, pfun);
+  else if (integerp(form)) pint(form->integer, pfun);
   else if (symbolp(form)) { if (form->name != NOTHING) pstring(symbolname(form->name), pfun); }
   else if (characterp(form)) pcharacter(form->chars, pfun);
   else if (stringp(form)) printstring(form, pfun);
-  else if (streamp(form)) {
-    pfun('<');
-    if ((form->integer)>>8 == SPISTREAM) pfstring(PSTR("spi"), pfun);
-    else if ((form->integer)>>8 == I2CSTREAM) pfstring(PSTR("i2c"), pfun);
-    else if ((form->integer)>>8 == SDSTREAM) pfstring(PSTR("sd"), pfun);
-    else pfstring(PSTR("serial"), pfun);
-    pfstring(PSTR("-stream "), pfun);
-    pint(form->integer & 0xFF, pfun);
-    pfun('>');
-  } else
-    error2(0, PSTR("Error in print"));
+  else if (streamp(form)) pstream(form, pfun);
+  else error2(0, PSTR("Error in print"));
 }

 void prin1object (object *form, pfun_t pfun) {
@@ -4100,7 +4095,7 @@
   initworkspace();
   initenv();
   initsleep();
-  pfstring(PSTR("uLisp 3.2 "), pserial); pln(pserial);
+  pfstring(PSTR("uLisp 3.3 "), pserial); pln(pserial);
 }

 // Read/Evaluate/Print loop
@@ -4142,7 +4137,7 @@
   }
   // Come here after error
   delay(100); while (Serial.available()) Serial.read();
-  clrflag(NOESC);
+  clrflag(NOESC); BreakLevel = 0;
   for (int i=0; i<TRACEMAX; i++) TraceDepth[i] = 0;
   #if defined(sdcardsupport)
   SDpfile.close(); SDgfile.close();


remove serial port reporting from pollPS3()

--- OS_pollPS3.ino
+++ OS_pollPS3.ino
@@ -120,14 +120,11 @@
       if (millis()-roundButtonPressTimer[ii]>longPress){

         //Store stage location in this button
-        Serial.print("Stored: ");
         for (byte jj=0; jj<numAxes; jj++){
           if (axisPresent[jj]==0)
             continue;
           buttonStageLocations[ii][jj]=stagePosition[jj];
-          Serial.print(stagePosition[jj]);
-          Serial.print(" ");
-         }
+        }

       Serial.println(' ');