Initial Upload of OilBurner Code

Initial Upload of OilBurner Code

OilBurner Version 0.6.3 uploaded. Previous versions of code not documented on Github

/*
	WVO Controller

	This is the code for the WVO Controller development for my pickup. It is intended
	to handle the switching of fuel control valves and display important information on
	the touch screen display.

	The Code is written for use with an Arduino Mega, and may potentially be rewritten for
	an arduino micro.

	A Seeedstudio 2.8" TFT Touch Shield is used. A touch screen breakout may be used in the future.

	The circuit:
	*INPUTS:
		A10 - Photodiode for Auto Backlight Adjustment
		A11 - WVO Filter Head TEMP
    A14 - Fuel Pressure Sender
    A15 - Fuel Level Sender

		Future Implementations:
			Analog - Engine Coolant Temperature

	*OUTPUTS:
		22 - Piezo Buzzer Pin
		24 - Return Valve MOSFET Gate
		26 - Supply Valve/Fuel Pump MOSFET Gate

	Touchscreen Features:
		grid coordinates start: (0, 0) end: (239, 319)

	Code in Work
  By Max Sauer
------------------------------------------------------------------------------------------------------------------------------------------------------------------

Changelog:
  0.1.0   -   2/1/2015    -   Initial Prototype with TFT
  0.2.0   -   2/24/2015   -   Features added: Buzzer, Temp Sensor, Mosfets for Switching Valves
  0.3.0   -   3/15/2015   -   Temperature Set Point and Brightness Menu Options Added, creating Settings Window to Hold all settings options
  0.4.0   -   4/20/2015   -   EGT Gage Added
  0.5.0   -   unknown     -   Eeprom function added to save settings
  0.5.1   -   8/25/2015   -   Fixed Bug allowing access to the EGT screen while the controller was in Purge Mode.
  0.5.2   -   8/26/2015   -   Brightness Scaling Equation Improved. Brightness button now has a smoother transition from dim to bright.
  0.6.0   -   5/17/2016   -   Auto Brightness Equation Added. Photodiode added to hardware to sense Ambient light for Auto Brightness Equation. Changed Lettering to White.
  0.6.1   -   6/3/2016    -   Added Fuel Gage functionality.
  0.6.2   -   8/1/2016    -   Bug Fixes which causes fuel gage lines not to display when reloading homescreen
                          -   Added a Cancel Button to the Purging Page, which allows the purge sequence to be cancelled in the event of an accidental Purge
  0.6.3   -   8/21/2017   -   Added Fuel Pressure to display. This utilizes a 3 wire fuel pressure sender. More info at https://www.amazon.com/gp/product/B00RCPDE40/ref=oh_aui_search_detailpage?ie=UTF8&psc=1
                          -   fixed bug causing cancel button not to revert back to oil
                          -   added alarm for fuel pressure when on oil if pressure falls below 6 psi, also added color to fuel pressure indicator on screen
*/

#include <stdint.h>
#include <SeeedTouchScreen.h>
#include <TFTv2.h>
#include <SPI.h>
#include <Adafruit_MAX31855.h>
#include <EEPROM.h>

#define DO    28
#define CS    30
#define CLK   32
Adafruit_MAX31855 thermocouple(CLK, CS, DO);

const int numReadings = 10.00;				// number of readings to be taken for temperature average
int readings[numReadings];  				// the readings from the analog input
int index = 0;              				// the index of the current reading
int total = 0;              				// the running total
int average = 0;            				// the average of temperature readings
int oldaverage = 0;          				// the old average to overwrite on the scree
int temperaturePin = A11;			        // temperature input pin to read temperature of oil temperature
int temp = 0;
int EGT = 0;
int oldEGT = 0;

double gageMin = 50.00;
double gageMax = 950.00;
double theta;
double oldTheta;

boolean circle = 0;

const int buzzerPin = 22;
const int returnValve = 24;      			// red LED
const int supplyValve = 26;    				// green LED, will also power bypass valve and Fuel pump Relay
int page = 0;                  				// the page to prevent button pushes from working on pages where the button doesnt exist
// homescreen = 0, settings = 2, purgeSetTime = 3, tempSet = 4
int number = 0;						// unknown variable.....

int purgeTime;					// purge time of the of valves in seconds. Set to 5 now for ease of troubleshooting.
// minimum in purgeSetTime menu is 30. this value will be changed for final code.
unsigned long Timer = 0;				// unkown variable.....
boolean autoState;    				// whether the controller is running in auto or manual mode. Auto = 1, manual = 0.
boolean oilState = 0;     				// whether the controller is switched to oil or not. Oil = 1, diesel = 0.
boolean tempState = 0;     				// whether the temp is above or below set temp. Above setTemp = 1, below setTemp = 0.
boolean oldtempState = 0;				// used to get into if statements only when tempState has just switched and oldTempState is different.
boolean purgeState = 0;					// whether or not purgeTimer is running. Purging = 1, not purging = 0.
int setTemp;       				// Automatic oil switch and purge temperature threshold in degrees Farenheit
long previousMillis = 0;				// time in millis when purge timer function begins
unsigned long currentMillis = 0;			// current time in millis compared to previousMillis to determine when purgeTime is met
int countdown = 0;					// purgeTime left in seconds, to be displayed during purge process
int oldCountdown = 0;					// old purgeTime value , compared to countdown to determine when to overwrite countdown value.

int backlightPin = 7;
float backlightValue;
float dayLightVal;
float backlightPercent = 100;
float backlightPerc;
int backlightVal = 255;
int oldBacklightVal;
int oldLightLevel;
int lightLevel;

//const int returnCheckPin = 34;                          // analog pin to check state of return valve with the use of a reed switch to check for magnetic field
//const int bypassCheckPin = 36;                          // analog pin to check state of bypass valve with the use of a reed switch to check for magnetic field
//const int supplyCheckPin = 38;                          // analog pin to check state of supply valve with the use of a reed switch to check for magnetic field

boolean returnState = 0;
boolean oldReturnState = 0;
boolean bypassState = 0;
boolean oldBypassState = 0;
boolean supplyState = 0;
boolean oldSupplyState = 0;

int autoStateAddress = 0;
int purgeTimeAddress = 1;
int tempSetPointAddress = 2;
int brightnessAddress = 3;

int fuelLevel;                                          // value from 0 to 100 equating to the fuel level
float fuelLevelVal;                                     // analog value from 728 to 254, read from the fuel level voltage divider;
int xLength;                                            // length of bar in fuel level bar graph
int oldxLength;
int fuelLevelPin = A15;                                    // pin that is reading the voltage of the voltage divider for the fuel sender

int readingP[numReadings];          // the readings from the analog input
int indexP = 0;                      // the index of the current reading
int sumP = 0;                      // the running total
int psi = 0;
int pressure = 0;                   // current fuel pressure
int oldpressure = 0;                // old fuel pressure
int pressurePin = A14;              // analog pressure pin
double pressureVoltage;

TouchScreen ts = TouchScreen(XP, YP, XM, YM);	        // values for coordinate system inputs on touchscreen.

void setup()
{
  dayLightVal = analogRead(A10);
  //Serial.println(dayLightVal);
  //backlightPerc = (0.0000003*(dayLightVal*dayLightVal*dayLightVal))-(0.0006*(dayLightVal*dayLightVal))+(0.397*dayLightVal);
  //Serial.println(backlightPerc);
  backlightValue = 0.2138*dayLightVal + 20.5;
  //Serial.println(backlightValue);
  //backlightValue = ((backlightPercent*backlightPercent*backlightPercent)/3937) + 1.5;
  //backlightValue = (127 * backlightPercent) / 50 + 1;
  analogWrite(backlightPin, backlightValue);
  //Serial.println(backlightValue);

  Tft.TFTinit();                                        // init TFT library

  pinMode(24, OUTPUT);					// needed to set digital pin to high at 5v for switching MOSFET
  pinMode(26, OUTPUT);					// needed to set digital pin to high at 5v for switching MOSFET

  Serial.begin(9600);

  //Tft.fillRectangle(0, 0, 239, 319, WHITE);

  Tft.drawRectangle(10, 20, 220, 280, GREEN); 	    // (X-coord start, Y-coord start, X length, y length, color)
  Tft.drawString("OIL", 73, 38, 5, GREEN);
  Tft.drawString("OIL", 75, 40, 5, BLUE);
  delay(500);
  Tft.drawString("BURNER", 23, 78, 5, GREEN);
  Tft.drawString("BURNER", 25, 80, 5, BLUE);
  delay(500);
  Tft.drawString("V 0.6.3", 55, 200, 3, BLUE);
  delay(500);
  Tft.drawString("Max Sauer", 40, 250, 3, WHITE);

  pinMode(buzzerPin, OUTPUT);
  //tone(buzzerPin, 500, 250);
  delay(250);
  //tone(buzzerPin, 750, 500);
  delay(200);

  autoState = EEPROM.read(autoStateAddress);
  backlightPercent = EEPROM.read(brightnessAddress);
  purgeTime = EEPROM.read(purgeTimeAddress);
  setTemp = EEPROM.read(tempSetPointAddress);

  delay(3000);						// display boot screen for set time in millis
  Tft.fillScreen();					// clear display

  homescreen();						// draw homescreen once boot screen is cleared

  Point p = ts.getPoint();				// setup point to read touch values
  p.x = 0;
  p.y = 0;
}

/*
*************************************************************************************************************************************************************
								END OF SETUP
*************************************************************************************************************************************************************
*/

void loop()
{

  Point p = ts.getPoint();
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);

  Serial.print("oil state ");
  Serial.println(oilState);

  dayLightVal = analogRead(A10);
  //Serial.println(dayLightVal);
  //backlightPerc = (0.0000003*(dayLightVal*dayLightVal*dayLightVal))-(0.0006*(dayLightVal*dayLightVal))+(0.397*dayLightVal);
  //Serial.println(backlightPerc);
  backlightValue = 0.2138*dayLightVal + 20.5;
  //Serial.println(backlightValue);
  //backlightValue = ((backlightPercent*backlightPercent*backlightPercent)/3937) + 1.5;
  //backlightValue = (127 * backlightPercent) / 50 + 1;
  analogWrite(backlightPin, backlightValue);
  //Serial.println(backlightValue);

  int sensorValue = analogRead(A11);
  float voltage = sensorValue * (5.0 / 1023.0);
  float v6 = voltage * voltage * voltage * voltage * voltage * voltage;
  float v5 = voltage * voltage * voltage * voltage * voltage;
  float v4 = voltage * voltage * voltage * voltage;
  float v3 = voltage * voltage * voltage;
  float v2 = voltage * voltage;

  temp = (-1.4591 * v6 + 21.784 * v5 - 125.74 * v4 + 350.06 * v3 - 473.05 * v2 + 216.06 * voltage + 267.96) * 0.93;
  // polynomial approximation of signal voltages vs temperature of temp sender with experimentally determined correction factor of 0.93.
  // see excel sheet for more info.       C:\Users\Max\Google Drive\Sync\Bub\WVO Controller\Oil Temp gage values
  //float voltage, degreesC, degreesF;			// calculate temperature reading based on voltages
  //voltage = getVoltage(temperaturePin);
  //degreesC = (voltage - 0.5) * 100.0;
  //degreesF = degreesC * (9.0/5.0) + 32.0;
  // subtract the last reading:
  total = total - readings[index];
  // read from the sensor:
  readings[index] = temp;
  // add the reading to the total:
  total = total + readings[index];
  // advance to the next position in the array:
  index = index + 1;
  // if we're at the end of the array...
  if (index >= numReadings)
    // ...wrap around to the beginning:
    index = 0;
  // calculate the average:
  average = total / numReadings;

fuelGage();
fuelPressure();

  if (page == 0 && purgeState == 0)
  {
    EGT = thermocouple.readFarenheit();
    if (EGT != oldEGT)
    {
      if (EGT > 999)			// if EGT is 1000 or bigger, display value to left for centering
      {
        Tft.fillRectangle(165, 180, 75, 25, BLACK);      		    // clear old exhaust gas temperature
        Tft.drawNumber(EGT, 165, 180, 3, WHITE);  		// write new exhaust gas temperature
      }
      else					        	// else, temperature is smaller than 1000, display in line with oil and coolant temps
      {
        Tft.fillRectangle(165, 180, 75, 25, BLACK);  			// clear old exhaust gas temperature
        Tft.drawNumber(EGT, 180, 180, 3, WHITE);  		// write new exhaust gas temperature
      }
    }
    oldEGT = EGT;						// once new average has been written, store value in old average for next loop iteration  					        	// plot temperature

    if (EGT > 1100)                                       // sound alarm, EGT is too high
    {
      delay(250);
      tone(buzzerPin, 750, 250);
      delay(250);
      tone(buzzerPin, 500, 250);
      delay(250);
    }

    if (page == 0)
    {
      /*
      returnState = digitalRead(returnCheckPin);
      bypassState = digitalRead(bypassCheckPin);
      supplyState = digitalRead(supplyCheckPin);

      if (returnState != oldReturnState)
      {
        if (returnState == LOW)
        {
          Tft.fillCircle(200, 200, 14, RED);
        }
        else
        {
          Tft.fillCircle(200, 200, 14, BLACK);
        }
      }

      if (bypassState != oldBypassState)
      {
        if (bypassState == LOW)
        {
          Tft.fillCircle(120, 200, 14, RED);
        }
        else
        {
          Tft.fillCircle(120, 200, 14, BLACK);
        }
      }

      if (supplyState != oldSupplyState)
      {
        if (supplyState == LOW)
        {
          Tft.fillCircle(40, 200, 14, RED);
        }
        else
        {
          Tft.fillCircle(40, 200, 14, BLACK);
        }
      }

      oldReturnState = returnState;
      oldBypassState = bypassState;
      oldSupplyState = supplyState;
      */
    }

    if (average != oldaverage)
    {
      Tft.drawString("FUEL TEMP", 0, 120, 3, WHITE);
      Tft.drawString("FUEL PRES.", 0, 150,3,WHITE);
      if (pressure > 6)
      {
        Tft.drawNumber(pressure, 200, 150, 3, GREEN);
      }
      if (pressure <= 6 && oilState == 1)
      {
        Tft.drawNumber(pressure, 200, 150, 3, RED);
        delay(250);
        tone(buzzerPin, 750, 250);
        delay(250);
        tone(buzzerPin, 500, 250);
        delay(250);
      }
      if (oilState == 0)
      {
        Tft.drawNumber(pressure, 200, 150, 3, WHITE);
      }
      Tft.drawString("EGT", 0, 180, 3, WHITE);
      Tft.drawNumber(oldaverage, 180, 120, 3, BLACK);   	    // clear old oil temperature
      Tft.drawNumber(average, 180, 120, 3, WHITE);        		// write new average oil temperature
      //Tft.drawNumber(oldaverage,180,150,3,BLACK);    		// clear old average engine temperature
      //Tft.drawNumber(average,180,150,3,YELLOW);    		// write new average oil temperature
      oldaverage = average;
    }

    if (pressure != oldpressure)
    {
      Tft.drawString("FUEL TEMP", 0, 120, 3, WHITE);
      Tft.drawString("FUEL PRES.", 0, 150,3,WHITE);
      Tft.drawNumber(oldpressure, 200, 150, 3, BLACK);
      if (pressure > 6)
      {
        Tft.drawNumber(pressure, 200, 150, 3, GREEN);
      }
      if (pressure <= 6 && oilState == 1)
      {
        Tft.drawNumber(pressure, 200, 150, 3, RED);
        delay(250);
        tone(buzzerPin, 750, 250);
        delay(250);
        tone(buzzerPin, 500, 250);
        delay(250);
      }
      if (oilState == 0)
      {
        Tft.drawNumber(pressure, 200, 150, 3, WHITE);
      }
      Tft.drawString("EGT", 0, 180, 3, WHITE);
      Tft.drawNumber(average, 180, 120, 3, WHITE);            // write new average oil temperature
      //Tft.drawNumber(oldaverage,180,150,3,BLACK);       // clear old average engine temperature
      //Tft.drawNumber(average,180,150,3,YELLOW);       // write new average oil temperature
      oldpressure = pressure;
    }

  }

  if (purgeState == 1)						// display purge timer on screen if controller is in purge mode
  {
    currentMillis = millis();
    //Serial.println(previousMillis);
    //Serial.println(currentMillis);
    countdown = (purgeTime - (currentMillis - previousMillis) / 1000); 		// if time since purge started is less than purgeSetTime, keep running purge
    if (countdown != oldCountdown)						// if old and new countdown values are different, write countdown to screen
    {
      if (countdown >= 10)							// if countdown is < 10, center countdown value on screen
      {
        Tft.fillRectangle(90, 140, 70, 40, BLACK);
        Tft.drawNumber(countdown, 90, 140, 5, WHITE);
      }
      else									// otherwise, countdown is greater than 9, and countdown is centered
      {
        Tft.fillRectangle(90, 140, 60, 40, BLACK);
        Tft.drawNumber(countdown, 100, 140, 5, WHITE);
      }
    }
    oldCountdown = countdown;
    if ((currentMillis - previousMillis > purgeTime * 1000UL))		// if the purge time has ran longer than purgeSetTime,
      // run returnOff which will turn off the Return valve
    {
      p.x = 0;
      p.y = 0;
      returnOff();
    }

    if ((p.x > 0 && p.x < 240 && p.y > 250 && p.y < 320))         // if cancel button is pressed, turn back on supply valve
    {
        tone(buzzerPin, 750, 250);
        p.x = 0;
        p.y = 0;
        digitalWrite(supplyValve, HIGH);
        purgeState = 0;
        oilState = 1;
        homescreen();
    }
  }

  if (average > setTemp)						        // if actual temperature is above temperature threshold, change tempState to true
  {
    tempState = 1;
  }
  if (average < setTemp - 5)							// if actual temp. is below temperature threshold with 5 degree buffer, set tempState to false
  {
    tempState = 0;
  }

  if (tempState == 1 && oilState == 0 && oldtempState == 0 && autoState == 0 && page == 0 && purgeState == 0)
    // display switch button, temp is now high enough for manual switching
  {
    Tft.fillRectangle(0, 250, 240, 70, GREEN);
    Tft.drawString("SWITCH", 44, 270, 4, BLUE);
    oldtempState = tempState;
  }

  if (tempState == 0 && oldtempState == 1 && page == 0 )
    // remove switch button, temp has fallen below set temp for manual switching
  {
    Tft.fillRectangle(0, 250, 240, 70, BLACK);
    oldtempState = tempState;
  }

  if (tempState == 1 && autoState == 1 && oilState == 0 && purgeState == 0 && page == 0)  		//switch to oil, temp is now high enough. Automatic Mode is On.
  {
    oilSwitch();
    tone(buzzerPin, 750, 250);
    digitalWrite(supplyValve, HIGH);
    digitalWrite(returnValve, HIGH);
    Tft.drawString("DIESEL", 52, 70, 4, BLACK);
    Tft.drawString("OIL", 85, 70, 4, GREEN);
    Tft.fillRectangle(0, 250, 240, 70, RED);
    Tft.drawString("PURGE", 54, 270, 4, WHITE);
    delay(500);
  }

  if (oilState == 1 && tempState == 0 && page == 0)				        	// if temperature falls below setTemp, run fuelPurge whether mode is Auto or Manual
  {
    tone(buzzerPin, 750, 250);    						// Give a Warning beep to notify user that temp is low.
    delay(500);
    tone(buzzerPin, 750, 250);
    currentMillis = millis();
    previousMillis = currentMillis;
    oilSwitch();
    fuelPurge();
    //Tft.drawString("OIL",85,70,4,BLACK);
    //Tft.drawString("DIESEL",52,70,4,BLUE);
  }

  if (p.z > __PRESURE)								// Purge Time set button
  {
    if ((p.x > 130) && (p.x < 240) && (p.y > 0) && (p.y < 50))
    {
      if (page == 0 && purgeState == 0)
      {
        tone(buzzerPin, 750, 250);
        settings();
      }
    }
  }

  if (p.z > __PRESURE)								// EGT Button
  {
    if ((p.x > 0) && (p.x < 120) && (p.y > 140) && (p.y < 190))
    {
      if (page == 0 && purgeState ==0)
      {
        tone(buzzerPin, 750, 250);
        gage();
      }
    }
  }

  if (page == 6)
  {
    EGT = thermocouple.readFarenheit();
    if (EGT != oldEGT)
    {
      if (EGT > 999)			// if EGT is 1000 or bigger, display value to left for centering
      {
        Tft.fillRectangle(100, 140, 75, 30, BLACK);      		    // clear old exhaust gas temperature
        Tft.drawNumber(EGT, 100, 140, 3, WHITE);  		// write new exhaust gas temperature
      }
      else					        	// else, temperature is smaller than 1000, display in line with oil and coolant temps
      {
        Tft.fillRectangle(100, 140, 75, 30, BLACK);  			// clear old exhaust gas temperature
        Tft.drawNumber(EGT, 100, 140, 3, WHITE);  		// write new exhaust gas temperature
      }
    }
    oldEGT = EGT;						// once new average has been written, store value in old average for next loop iteration
    theta = 3.14 - 3.14 * ((EGT - gageMin) / (gageMax - gageMin));
    //Serial.println(theta);
    //Serial.println(EGT);
    Tft.fillCircle(120, 120, 5, WHITE);
    if (oldTheta != theta)
    {
      Tft.drawLine(120, 120, 120 + 60 * cos(oldTheta), 120 - 60 * sin(oldTheta), BLACK);
      Tft.fillCircle(120, 120, 5, WHITE);
      Tft.drawLine(120, 120, 120 + 60 * cos(theta), 120 - 60 * sin(theta), WHITE);
    }
    oldTheta = theta;
  }

  if (p.z > __PRESURE)								// switch/purge button
  {
    if (p.x > 0 && p.x < 240 && p.y > 250 && p.y < 320)
    {
      if (page == 0 && autoState == 0 && tempState == 1 && purgeState == 0)
      {
        oilSwitch();
        tone(buzzerPin, 750, 250);
        if (oilState == 0)
        {
          currentMillis = millis();
          previousMillis = currentMillis;
          fuelPurge();
          //Tft.drawString("OIL",85,70,4,BLACK);
          //Tft.drawString("DIESEL",52,70,4,BLUE);
          //Tft.fillRectangle(0,250,240,70,GREEN);
          //Tft.drawString("SWITCH",44,270,4,BLUE);
        }
        if ( oilState == 1)
        {
          digitalWrite(supplyValve, HIGH);
          digitalWrite(returnValve, HIGH);
          Tft.drawString("DIESEL", 52, 70, 4, BLACK);
          Tft.drawString("OIL", 85, 70, 4, GREEN);
          Tft.fillRectangle(0, 250, 240, 70, RED);
          Tft.drawString("PURGE", 54, 270, 4, WHITE);
        }
      }
      if (page == 0 && autoState == 1 && purgeState == 0)
      {
        autoState = 0;
        oilSwitch();
        tone(buzzerPin, 750, 250);
        currentMillis = millis();
        previousMillis = currentMillis;
        fuelPurge();

      }
      delay(500);
    }
  }

  if (p.z > __PRESURE)								// home button
  {
    if (p.x > 200 && p.x < 240 && p.y > 280 && p.y < 320)
    {
      if (page == 2 || page == 3 || page == 4 || page == 5 || page == 6)
      {
        EEPROM.update(brightnessAddress, backlightPercent);
        EEPROM.update(purgeTimeAddress, purgeTime);
        EEPROM.update(tempSetPointAddress, setTemp);
        tone(buzzerPin, 500, 250);
        homescreen();
      }
    }
  }

  if (p.z > __PRESURE)								// back button
  {
    if (p.x < 40 && p.y > 280 && p.y < 320)
    {
      if (page == 2)
      {
        tone(buzzerPin, 1000, 250);
        homescreen();
      }
      if (page == 4 || page == 3 || page == 5 )
      {
        p.x = 0;
        p.y = 0;
        EEPROM.update(brightnessAddress, backlightPercent);
        EEPROM.update(purgeTimeAddress, purgeTime);
        EEPROM.update(tempSetPointAddress, setTemp);
        tone(buzzerPin, 1000, 250);
        settings();
      }
    }
  }

  if (p.z > __PRESURE)								// purge plus button
  {
    if (p.x > 50 && p.x < 190 && p.y > 40 && p.y < 110)
    {
      if (page == 3)
      {
        tone(buzzerPin, 1000, 125);
        purgeTime = purgeTime + 5;
        delay(50);
        Tft.fillRectangle(50, 120, 140, 80, BLACK);
        if (purgeTime < 100)
        {
          Tft.drawNumber(purgeTime, 85, 140, 5, WHITE);
        }
        else
        {
          Tft.drawNumber(purgeTime, 70, 140, 5, WHITE);
        }
      }
      if (page == 4)
      {
        tone(buzzerPin, 1000, 125);
        setTemp = setTemp + 5;
        delay(50);
        Tft.fillRectangle(50, 120, 140, 80, BLACK);
        Tft.drawNumber(setTemp, 70, 140, 5, WHITE);
      }
      if (page == 5)
      {
        tone(buzzerPin, 1000, 125);
        if (backlightPercent < 100)
        {
          backlightPercent = backlightPercent + 5;
          delay(50);
          //backlightValue = ((backlightPercent*backlightPercent*backlightPercent)/3937) + 1;
          //backlightValue = (127 * backlightPercent) / 50 + 1;
          analogWrite(backlightPin, backlightValue);
          Tft.fillRectangle(50, 120, 160, 80, BLACK);
          if (backlightPercent < 10)
          {
            Tft.drawNumber(backlightPercent, 85, 140, 5, WHITE);
            Tft.drawString("%", 125, 140, 5, WHITE);
          }
          if (backlightPercent < 100 && backlightPercent >= 10)
          {
            Tft.drawNumber(backlightPercent, 65, 140, 5, WHITE);
            Tft.drawString("%", 145, 140, 5, WHITE);
          }
          if (backlightPercent == 100)
          {
            Tft.drawNumber(backlightPercent, 50, 140, 5, WHITE);
            Tft.drawString("%", 165, 140, 5, WHITE);
          }
        }
      }
    }
  }

  if (p.z > __PRESURE)								// purge minus button
  {
    if (p.x > 50 && p.x < 190 && p.y > 210 && p.y < 280)
    {
      if (page == 3)
      {
        tone(buzzerPin, 650, 125);
        if (purgeTime >= 35)
        {
          purgeTime = purgeTime - 5;
          delay(50);
          Tft.fillRectangle(50, 120, 140, 80, BLACK);
          if (purgeTime < 100)
          {
            Tft.drawNumber(purgeTime, 85, 140, 5, WHITE);
          }
          else
          {
            Tft.drawNumber(purgeTime, 70, 140, 5, WHITE);
          }
        }
      }
      if (page == 4)
      {
        tone(buzzerPin, 650, 125);
        if (setTemp >= 105)
        {
          setTemp = setTemp - 5;
          delay(50);
          Tft.fillRectangle(50, 120, 140, 80, BLACK);
          Tft.drawNumber(setTemp, 70, 140, 5, WHITE);
        }
      }
      if (page == 5)
      {
        tone(buzzerPin, 650, 125);
        if (backlightPercent > 0)
        {
          backlightPercent = backlightPercent - 5;
          delay(50);
          //backlightValue = ((backlightPercent*backlightPercent*backlightPercent)/3937) + 1;
          //backlightValue = (127 * backlightPercent) / 50 + 1;
          analogWrite(backlightPin, backlightValue);
          Tft.fillRectangle(50, 120, 160, 80, BLACK);
          if (backlightPercent < 10)
          {
            Tft.drawNumber(backlightPercent, 85, 140, 5, WHITE);
            Tft.drawString("%", 125, 140, 5, WHITE);
          }
          if (backlightPercent < 100 && backlightPercent >= 10)
          {
            Tft.drawNumber(backlightPercent, 65, 140, 5, WHITE);
            Tft.drawString("%", 145, 140, 5, WHITE);
          }
          if (backlightPercent == 100)
          {
            Tft.drawNumber(backlightPercent, 50, 140, 5, WHITE);
            Tft.drawString("%", 165, 140, 5, WHITE);
          }
        }
      }
    }
  }

  if (p.z > __PRESURE)								// Various Buttons
  {
    if (p.y > 50 && p.y < 110 && page == 2) 					// purgeSetTime button
    {
      tone(buzzerPin, 750, 250);
      purgeSetTime();
    }

    if (p.y > 125 && p.y < 190 && page == 2) 				       // tempSetTime button
    {
      tone(buzzerPin, 750, 250);
      tempSet();
    }

    if (p.y > 210 && p.y < 270 && page == 2) 				       // brightness button
    {
      tone(buzzerPin, 750, 250);
      brightness();
    }

    if (p.x > 0 && p.x < 109 && p.y > 0 && p.y < 50) 			       // auto/manual button on homescreen
    {
      if (page == 0 && purgeState == 0)
      {
        tone(buzzerPin, 650, 125);
        autoButton();
        EEPROM.update(autoStateAddress, autoState);
        delay(250);
        if (autoState == 1 && oilState == 0)
        {
          Tft.fillRectangle(0, 250, 240, 70, BLACK);
        }
        if (autoState == 0 && average > setTemp && oilState == 0)
        {
          Tft.fillRectangle(0, 250, 240, 70, GREEN);
          Tft.drawString("SWITCH", 44, 270, 4, BLUE);
        }
      }
    }
  }

}

/*
***************************************************************************************************************************************************************
								END of LOOP
***************************************************************************************************************************************************************
*/

void homescreen()						// function that draws homescreen buttons and info
{
  page = 0;
  circle = 0;
  Tft.fillScreen();
  //Tft.fillRectangle(0, 0, 239, 319, WHITE);
  if (oilState == 0)
  {
    Tft.drawString("OIL", 85, 70, 4, BLACK);
    Tft.drawString("DIESEL", 52, 70, 4, WHITE);
  }
  else
  {
    Tft.drawString("DIESEL", 52, 70, 4, BLACK);
    Tft.drawString("OIL", 85, 70, 4, GREEN);
  }
  //settings button
  Tft.fillRectangle(130, 0, 109, 50, BLUE);
  Tft.drawString("SETTINGS", 137, 18, 2, WHITE);

  //auto/manual button
  Tft.fillRectangle(0, 0, 109, 50, BLUE);
  if (autoState == 1)
  {
    Tft.drawString("MANUAL", 15, 18, 2, BLUE);
    Tft.drawString("AUTO", 15, 15, 3, WHITE);
  }
  else
  {
    Tft.drawString("AUTO", 15, 15, 3, BLUE);
    Tft.drawString("MANUAL", 15, 18, 2, WHITE);
  }

  //switch/purge button
  if (autoState == 0 && average > setTemp && oilState == 0)
  {
    Tft.fillRectangle(0, 250, 240, 70, GREEN);
    Tft.drawString("SWITCH", 44, 270, 4, BLUE);
  }

  if (oilState == 1)
  {
    Tft.fillRectangle(0, 250, 240, 70, RED);
    Tft.drawString("PURGE", 54, 270, 4, WHITE);
  }
  if (page == 0)                                              //plot temperature
  {
    Tft.drawString("FUEL TEMP", 0, 120, 3, WHITE);
    Tft.drawString("FUEL PRES.", 0, 150,3,WHITE);
    Tft.drawNumber(oldpressure, 200, 150, 3, BLACK);
    if (pressure > 6)
    {
      Tft.drawNumber(pressure, 200, 150, 3, GREEN);
    }
    if (pressure <= 6 && oilState == 1)
    {
      Tft.drawNumber(pressure, 200, 150, 3, RED);
      delay(250);
      tone(buzzerPin, 750, 250);
      delay(250);
      tone(buzzerPin, 500, 250);
      delay(250);
    }
    if (oilState == 0)
    {
      Tft.drawNumber(pressure, 200, 150, 3, WHITE);
    }
    Tft.drawString("EGT", 0, 180, 3, WHITE);
    Tft.drawNumber(oldaverage, 180, 120, 3, BLACK);               //oil temp
    Tft.drawNumber(average, 180, 120, 3, WHITE);                    //oil temp
    //Tft.drawNumber(oldaverage,180,150,3,BLACK);                   //engine temp
    //Tft.drawNumber(average,180,150,3,YELLOW);                     //engine temp
    if (oldEGT > 999 && EGT > 999)
    {
      Tft.fillRectangle(165, 180, 75, 30, BLACK);                  //exhaust temp
      Tft.drawNumber(EGT, 165, 180, 3, WHITE);          //exhaust temp
    }
    else
    {
      Tft.fillRectangle(165, 180, 75, 30, BLACK);                  //exhaust temp
      Tft.drawNumber(EGT, 180, 180, 3, WHITE);          //exhaust temp
    }
    oldaverage = average;
    oldpressure = pressure;
  }
//
    Tft.drawString("TANK", 0, 210, 3, WHITE);
    Tft.fillRectangle(130,208,106,26,BLUE);
    if (xLength > 100)
    {
      xLength = 100;
    }
    if (xLength < 0)
    {
      xLength = 0;
    }
    Tft.fillRectangle(133, 211, xLength, 20, WHITE);
    for(int xCoord = 133; xCoord <243; xCoord+=10)
    {
      Tft.drawLine(xCoord,211,xCoord,231,BLACK);
    }
    fuelGage();
}

void oilSwitch()				        	// changes oilState for comparison when purging
{
  if (oilState == 0)
  {
    oilState = 1;
  }
  else
  {
    oilState = 0;
  }
}

void homebutton()						// function that draws the home button
{
  // home icon (rotated right now)
  //Tft.drawLine(219, 280, 200, 299, WHITE);
  //Tft.drawLine(200, 300, 204, 304, WHITE);
  //Tft.drawLine(203, 304, 200, 304, WHITE);
  //Tft.drawLine(200, 305, 200, 307, WHITE);
  //Tft.drawLine(200, 308, 208, 308, WHITE);
  //Tft.drawLine(209, 309, 219, 319, WHITE);
  //Tft.drawLine(219, 281, 219, 283, WHITE);
  //Tft.drawLine(219, 316, 219, 318, WHITE);
  //Tft.drawRectangle(219, 284, 21, 32, WHITE);
  //Tft.drawRectangle(225, 295, 15, 10, WHITE);

  Tft.drawRectangle(203, 300, 32, 19, WHITE);
  Tft.drawRectangle(214, 304, 10, 15, WHITE);
  Tft.drawRectangle(207, 282, 4, 10, WHITE);
  Tft.drawTriangle(201, 300, 219, 282, 237, 300, WHITE);
}

void backArrow()						// function that draws the back arrow button
{
  Tft.drawTriangle(3, 300, 21, 278, 21, 318, WHITE);
  Tft.drawRectangle(21, 288, 30, 20, WHITE);
}

void tempSet()							// function that draws buttons for tempSet Page
{
  page = 4;
  Tft.fillScreen();
  homebutton();
  backArrow();
  Tft.drawString("SWITCH TEMP", 55, 5, 2, WHITE);
  Tft.fillRectangle(50, 40, 140, 70, GREEN);
  Tft.fillRectangle(50, 210, 140, 70, GREEN);
  Tft.drawNumber(setTemp, 70, 140, 5, WHITE);
  Tft.drawChar('+', 103, 58, 5, WHITE);
  Tft.drawChar('-', 103, 228, 5, WHITE);
}

void purgeSetTime()						// function that draws buttons for purgeSetTime page
{
  page = 3;
  Tft.fillScreen();
  homebutton();
  backArrow();
  Tft.drawString("Purge Time in Sec", 15, 5, 2, WHITE);
  Tft.fillRectangle(50, 40, 140, 70, GREEN);
  Tft.fillRectangle(50, 210, 140, 70, GREEN);
  if (purgeTime < 100)
  {
    Tft.drawNumber(purgeTime, 85, 140, 5, WHITE);
  }
  else
  {
    Tft.drawNumber(purgeTime, 70, 140, 5, WHITE);
  }
  Tft.drawChar('+', 103, 58, 5, WHITE);
  Tft.drawChar('-', 103, 228, 5, WHITE);
}

void autoButton()						// function that displays autoState in auto/manual button on homescreen
{
  if (autoState == 1)
  {
    autoState = 0;
    Tft.drawString("AUTO", 15, 15, 3, BLUE);
    Tft.drawString("MANUAL", 15, 18, 2, WHITE);
  }
  else
  {
    autoState = 1;
    Tft.drawString("MANUAL", 15, 18, 2, BLUE);
    Tft.drawString("AUTO", 15, 15, 3, WHITE);
  }
}

void fuelPurge()						// function that changes purgeState for purging the oil system
{
  digitalWrite(supplyValve, LOW);
  Tft.fillScreen();
  Tft.drawString("PURGING", 35, 70, 4, WHITE);
  Tft.fillRectangle(0, 250, 240, 70, RED);
  Tft.drawString("CANCEL", 54, 270, 4, WHITE);
  purgeState = 1;
  //timer functions only with delay(), screen is locked up during purge process
  //if(millis() - Timer >= purgeTime*1000UL);
  {
    //digitalWrite(returnValve,LOW);
    //tone(buzzerPin, 500, 250);
    //delay(500);
    //tone(buzzerPin, 750, 250);
  }
}

void returnOff()						// function that turns off returnValve after fuelPurge is complete
{
  digitalWrite(returnValve, LOW);
  tone(buzzerPin, 500, 250);
  delay(500);
  tone(buzzerPin, 750, 250);
  Tft.fillScreen();
  oilState = 0;
  purgeState = 0;
  homescreen();
}

void settings()							// function that draws buttons for settings menu
{
  page = 2;
  Tft.fillScreen();
  homebutton();
  backArrow();
  Tft.drawString("SETTINGS", 43, 10, 3, WHITE);
  Tft.fillRectangle(20, 50, 200, 60, BLUE);
  Tft.fillRectangle(20, 130, 200, 60, BLUE);
  Tft.fillRectangle(20, 210, 200, 60, BLUE);
  Tft.drawString("PURGE TIME", 55, 75, 2, WHITE);
  Tft.drawString("TEMP. SET POINT", 30, 155, 2, WHITE);
  Tft.drawString("BRIGHTNESS", 60, 235, 2, WHITE);
}

void brightness()
{
  page = 5;
  Tft.fillScreen();
  homebutton();
  backArrow();
  Tft.drawString("SCREEN BRIGHTNESS", 15, 5, 2, WHITE);
  Tft.fillRectangle(50, 40, 140, 70, GREEN);
  Tft.fillRectangle(50, 210, 140, 70, GREEN);
  if (backlightPercent < 10)
  {
    Tft.drawNumber(backlightPercent, 85, 140, 5, WHITE);
    Tft.drawString("%", 125, 140, 5, WHITE);
  }
  if (backlightPercent < 100 && backlightPercent >= 10)
  {
    Tft.drawNumber(backlightPercent, 65, 140, 5, WHITE);
    Tft.drawString("%", 145, 140, 5, WHITE);
  }
  if (backlightPercent == 100)
  {
    Tft.drawNumber(backlightPercent, 50, 140, 5, WHITE);
    Tft.drawString("%", 165, 140, 5, WHITE);
  }
  Tft.drawChar('+', 103, 58, 5, WHITE);
  Tft.drawChar('-', 103, 228, 5, WHITE);
}

void gage()
{
  page = 6;
  Tft.fillScreen();
  homebutton();
  if (circle == 0)
  {
    Tft.fillCircle(120, 120, 78, GREEN);  					        	// plot temperature
    Tft.fillCircle(120, 120, 68, BLACK);
    Tft.fillRectangle(0, 120, 240, 115, BLACK);
    circle = 1;
    Tft.drawString("50", 12, 110, 2, WHITE);
    Tft.drawString("500", 103, 23, 2, WHITE);
    Tft.drawString("950", 200, 110, 2, WHITE);
  }

  theta = 3.14 - 3.14 * ((EGT - gageMin) / (gageMax - gageMin));
  //Serial.println(theta);
  //Serial.println(EGT);
  Tft.fillCircle(120, 120, 5, WHITE);
  if (oldTheta != theta)
  {
    Tft.drawLine(120, 120, 120 + 60 * cos(oldTheta), 120 - 60 * sin(oldTheta), BLACK);
    Tft.fillCircle(120, 120, 5, WHITE);
    Tft.drawLine(120, 120, 120 + 60 * cos(theta), 120 - 60 * sin(theta), WHITE);
  }
  oldTheta = theta;
}

void fuelGage()
{
  fuelLevelVal = analogRead(fuelLevelPin);
  fuelLevel = -0.0256*fuelLevelVal + 18.926;
  xLength = fuelLevel*10;
  //Serial.println(fuelLevelVal);
  if (xLength != oldxLength && page == 0)
  {
//    Serial.print("xLength   ");
//    Serial.print(xLength);
//    Serial.print("    ");
//    Serial.println(oldxLength);

    oldxLength = xLength;

    if (xLength > 100)
    {
      xLength = 100;
    }
    if (xLength < 0)
    {
      xLength = 0;
    }

    Tft.drawString("TANK", 0, 210, 3, WHITE);
    Tft.fillRectangle(130,208,106,26,BLUE);
    Tft.fillRectangle(133, 211, xLength, 20, WHITE);
    for(int xCoord = 133; xCoord <243; xCoord+=10)
    {
      Tft.drawLine(xCoord,211,xCoord,231,BLACK);
    }
  }
}

void fuelPressure()
{
  pressureVoltage = analogRead(pressurePin)*5.0/1023.0;
  psi = 7.5*pressureVoltage - 3.075;

  sumP = sumP - readingP[indexP];
  // read from the sensor:
  readingP[indexP] = psi;
  // add the reading to the total:
  sumP = sumP + readingP[indexP];
  // advance to the next position in the array:
  indexP = indexP + 1;
  // if we're at the end of the array...
  if (indexP >= numReadings)
    // ...wrap around to the beginning:
    indexP = 0;
  // calculate the average:
  pressure = sumP / numReadings;
}

//float getVoltage(int pin)				        // function that reads the value of the temperature pin and returns it
// to be converted into a temperature value.
//{
//return(analogRead(pin)*0.004882814);
//}

/*
***********************************************************************************************************************************************
                                        END OF CODE
***********************************************************************************************************************************************
*/

error: pathspec 'WVO_Controller_0.6.3.ino' did not match any file(s) known to git


no message

no message

error: pathspec 'Can' did not match any file(s) known to git
error: pathspec 'Code/Atlantis/Atlantis.ino' did not match any file(s) known to git


web example with json

web example with json

/*
    Copyright(c) Microsoft Open Technologies, Inc. All rights reserved.

    The MIT License(MIT)

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files(the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions :

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

// Include the ArduinoJson library, a dependency.
#include <ArduinoJson.h>

// VirtualShield is the core of all shields.
#include <VirtualShield.h>

// Text is to display text onscreen.
#include <Text.h>

// Web is the web shield.
#include <Web.h>

// Instantiate the shields.
VirtualShield shield;
Text screen = Text(shield);
Web web = Web(shield);

void webEvent(ShieldEvent* shieldEvent)
{
  const int MAX_RESPONSE = 100;
  char response[MAX_RESPONSE];

  screen.printAt(3, "ResponseCode:");
  screen.printAt(4, shieldEvent->resultId);

  web.getResponse(response, MAX_RESPONSE);

  EPtr eptrs[3];
  int parts = EPtr::parse(response, eptrs, 3, '|', 0);

  screen.printAt(5, "The weather for:");

  String message = eptrs[0].value;
  screen.printAt(7, message.substring(0,eptrs[0].length));
  screen.printAt(8, "for");

  message = eptrs[1].value;
  screen.printAt(9, message.substring(0,eptrs[1].length));
  screen.printAt(10, "is");

  message = eptrs[2].value;
  screen.printAt(11, message.substring(0,eptrs[2].length));
}

// Callback for startup, reconnection, and when the pushing 'Refresh' button
void refresh(ShieldEvent* shieldEvent)
{
  // clear the screen to a color
  screen.clear();

  screen.printAt(1, "Retrieving the forecast");

  String url = "http://forecast.weather.gov/MapClick.php?lat=47.6694&lon=-122.1239&FcstType=json";
  String parsingInstructions = "J:location.areaDescription|&^J:time.startPeriodName[0]|&^J:data.weather[0]";

  web.get(url, parsingInstructions);
}

void setup()
{
  // Call 'refresh' on startup, on reconnection, and when the pushing 'Refresh' button
  shield.setOnRefresh(refresh);

  // When web has a result, call the webEvent method
  web.setOnEvent(webEvent);

  // Begin the shield communication
  shield.begin();
}

void loop()
{
  // checkSensors() checks for return events and handles them (calling callbacks). This is VirtualShield's single loop() method.
  shield.checkSensors();
}

error: pathspec 'VirtualShield/examples/Basic-Web/Basic-Web.ino' did not match any file(s) known to git


Remove duplicate code.

Remove duplicate code.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/spoollord/MyOurWeather.git/'


Add Code for Pro Mini

Add Code for Pro Mini

#include <SPI.h>

#include <RadioHead.h>
#include <RH_ASK.h>
#include <DHT.h>
#include <LowPower.h>

#define GROUP_ID 2 // Temperature + Humidity sensor
#define NODE_ID  1

#define DHTPIN 2 // what pin we're connected to
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
// Initialize DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE,1);
// NOTE: For working with a faster chip, like an Arduino Due or Teensy, you
// might need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold. It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value. The default for a 16mhz AVR is a value of 6. For an
// Arduino Due that runs at 84mhz a value of 30 works.
// Example to initialize DHT sensor for Arduino Due:
//DHT dht(DHTPIN, DHTTYPE, 30);
const int transmit_pin = 10;
const int transmit_en_pin = 12;
const int receive_pin = 5;
const int dht_power_pin = 9;
const int led_pin = 13;
uint16_t speed = 2000;

RH_ASK driver(speed);

void setup() {

  Serial.begin(9600);
  pinMode(dht_power_pin, OUTPUT);
  dht.begin();
  //driver.init();
  if (!driver.init())
    Serial.println("init failed");
}
void loop() {

  digitalWrite(dht_power_pin, HIGH);
  digitalWrite(led_pin, HIGH);
  delay(500);
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    float h = dht.readHumidity();
    // Read temperature as Celsius
    float t = dht.readTemperature();
    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t) ){
      //Serial.println("Failed to read from DHT sensor!");
      return;
    }
     char tempHum [50];
     //snprintf(tempHum, 50, "%i,TS:%lu,G:%d,N:%d,H:%d,T:%i", ++nbLoop, millis(), GROUP_ID, NODE_ID,(int)(h*100), (int)(t*100));
     snprintf(tempHum, 50, "*#%lu*%i*%i*%i*%i##", millis(), GROUP_ID, NODE_ID,(int)((t-1)*100), (int)(h*100));
     driver.send((uint8_t *)  tempHum, strlen(tempHum));
     //driver.send(tempHum, strlen(tempHum));
     driver.waitPacketSent();

    digitalWrite(dht_power_pin, LOW);
    digitalWrite(led_pin, LOW);

    //Serial.print("Transmitting at speed:");
    //Serial.println(speed);
    Serial.print("Sending:");
    Serial.println(tempHum);
    Serial.print("strlen:");
    Serial.println(strlen(tempHum));
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: ");
    Serial.print(t);
    Serial.println(" *C");

    delay(1000 + NODE_ID);
    //delay(4000);
    // Enter power down state for 8 s with ADC and BOD module disabled
    for(int i = 0; i < 7; i++) //56 sec
     LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

    delay(100 + NODE_ID);
}

error: pathspec 'Arduino-Node/Group-2/Node_1-nano_temperature_sensor/Node_1-Pro-mini_temperature_sensor.ino' did not match any file(s) known to git


WIP: Temperature and Pressure sensore

WIP: Temperature and Pressure sensore

Sensor using BMP280 and SI7021 over I2C

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <SI7021.h>

// device specifics
#include "WirelessConfig.h"

#define TRANSMIT_INTERVAL_SECONDS 120

IPAddress server(10, 1, 1, 186);

Adafruit_BMP280 bmp;
SI7021 sensor;

WiFiClient wclient;
ESP8266WiFiGenericClass wifi;
PubSubClient client(wclient, server);

void setup() {
  // wait a bit to let things settle
  delay(1000);

  Serial.begin(115200);
  Serial.println("starting");

  // use pins 4,5 for SDA, SCL
  Wire.begin(D4, D5);
  sensor.begin(D4, D5);

  // start the bmp sensor
  if (!bmp.begin(0x76)) {
    Serial.println("No BMP280 sensor");
  }

  // turn of the Access Point as we are not using it
  wifi.mode(WIFI_STA);
}

void loop() {
  char conversionBuffer[20];

  client.loop();

  // make sure we are good for wifi
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, pass);

    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
      return;
    }
    Serial.println("WiFi connected");
  }

  if (!client.connected()) {
    if (client.connect("sensclient")) {
      client.subscribe("inTopic");
    }
  }

  client.publish("house/mcuSensor/1/temp1",
                 dtostrf(bmp.readTemperature(), 2, 2, conversionBuffer));

  client.publish("house/mcuSensor/1/temp2",
                 dtostrf(((float)sensor.getCelsiusHundredths())/100, 2, 2, conversionBuffer));

  client.publish("house/mcuSensor/1/pressure",
                 dtostrf(bmp.readPressure(), 2, 2, conversionBuffer));

  sprintf(conversionBuffer, "%d", sensor.getHumidityPercent());
  client.publish("house/mcuSensor/1/humidity", conversionBuffer);

  delay(TRANSMIT_INTERVAL_SECONDS * 1000);

}

error: pathspec 'TempAndPressure/TempAndPressure.ino' did not match any file(s) known to git


Added Edison Sample

Added Edison Sample

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/TheBeachMaster/AfricasTalkingIOT.git/'


base

base

base

#include <LiquidCrystal_I2C.h>
//#include <LiquidCrystal.h>
#include <RCSwitch.h>
#include "BMP280.h"
#include <Wire.h>

#define temperature 1  // BMP(temperature); // vrati teplotu
#define pressure    2  // BMP(pressure); // vrati tlak

#define upPin    6
#define downPin  5
#define enterPin 7
#define backPin  8

//menu piny
int klavesa;
int mZobrazeny = 1;
int keyPressed = 0;
int16_t mPozice = 0;
int mFlip = 0;
bool mZacatek;

uint16_t refreshCount = 0;

uint16_t rgb[4];
int mState = 0;

//definice nazvu polozek v seznamu
String mChar[] = {
  "1>Show IP adress",
  "2>Set color     ",
  "3>Show temp.    ",
  "4>Show Humidity ",
  "5>Show pressure ",
  "6>Restart       "
};

//zjisteni poctu polozek v seznamu
int mPocet = (sizeof(mChar) / sizeof(mChar[0]));

LiquidCrystal_I2C lcd(0x3F, 16, 2);  //pro i2c
//LiquidCrystal lcd(RS, RW, EN, D4, D5, D6, D7);  //pro normalni displej

#define R_led_pin 9
#define G_led_pin 10
#define B_led_pin 11
#define test_led_pin 13
#define transmit_pin 12

RCSwitch mySwitch = RCSwitch();

int Rled = 0;
int Gled = 0;
int Bled = 0;
String LED_address;

const int HTU_ADRESA = 0x40;
const int HTU_TEPLOTA = 0xE3;
const int HTU_VLHKOST = 0xE5;

double BMP_TEPLOTA;
double BMP_TLAK;

String dsc;
String codeToSend;

bool light = false;

BMP280 bmp;

byte degree[8] = {
  0b00010,
  0b00101,
  0b00010,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//

void setup()
{
   /*
    ////////piny pro lcd////////
    pinMode(54, OUTPUT);      //
    pinMode(55, OUTPUT);      //
    pinMode(67, OUTPUT);      //
    pinMode(68, OUTPUT);      //
    pinMode(13, OUTPUT);      //
    digitalWrite(54, LOW);    //
    digitalWrite(55, HIGH);   //
    digitalWrite(67, HIGH);   //
    digitalWrite(68, LOW);    //
    analogWrite(13, 130);//jas//
    ////////////////////////////
  */
  pinMode(upPin,    INPUT);  //up
  pinMode(downPin,  INPUT);  //down
  pinMode(enterPin, INPUT);  //enter
  pinMode(backPin,  INPUT);  //back

  Serial.begin(9600);

  lcd.init();
  lcd.backlight();
  //lcd.begin(16, 2);
  lcd.createChar(0, degree);

  lcd.setCursor(0, 1); lcd.print(F("Loading...      "));

  pinMode(R_led_pin, OUTPUT);
  pinMode(G_led_pin, OUTPUT);
  pinMode(B_led_pin, OUTPUT);

  mySwitch.enableTransmit(transmit_pin);

  Wire.begin();
  if (!bmp.begin())
  {
    //Serial.println(F("BMP nebylo nacteno!"));
  }
  else
  {
    //Serial.println(F("BMP pripojeno!"));
  }
  bmp.setOversampling(4);

}

String SerialRead(int count)
{
  String dsc;
  for (int i = 0; i < count; i++)
  {
    dsc += char(Serial.read());
  }
  return dsc;
}

//resetovaci funkce, nevim presne jak to funguje, nasel jsem to na netu
//void(* reset) (void) = 0;

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

void loop()
{
  HandleSerial();
  refresh_lcd(); //bacha, tohle je na displej!
  refresh_led(); //bacha, tohle je na RGB led pasek!
  mMenu();
  analogWrite(R_led_pin, 0);
  analogWrite(G_led_pin, 0);
  analogWrite(B_led_pin, 255);
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

void zobrazitIP()
{
  lcd.setCursor(0, 0); lcd.print(F("IP:             "));
  lcd.setCursor(0, 1); lcd.print(F("10.0.0.106      ")); //sem se doplni kod na zjisteni pravdive IP
}

void nastavitBarvu()
{
  int colorNow = 1;
  lcd.setCursor(0, 0); lcd.print(F("Nastav postupne "));
  lcd.setCursor(0, 1); lcd.print(F("hodnoty barev:  "));
  delay(1800);

  ///////////////////////////////////////////////////////////////////////////////////////////////////////////

  lcd.setCursor(0, 0); lcd.print(F("Hodnota cervene "));
  lcd.setCursor(0, 1); lcd.print(F("barvy:          "));

  do
  {
    keyPressed = wait4key();
    wait4antikey(keyPressed);
    switch (keyPressed) {
      case 1:
        if (rgb[1] == 99) {
          rgb[1]--;
        }
        rgb[1]++;
        break;

      case 2:
        if (rgb[1] == 0) {
          rgb[1]++;
        }
        rgb[1]--;
        break;

      case 3:
        lcd.setCursor(0, 0); lcd.print(F("Cervena barva   "));
        lcd.setCursor(0, 1); lcd.print(F("                "));
        colorNow = 2;
        delay(500);
        goto colorEnter1;
        break;

      case 4:

        break;

      default:

        break;
    }

    lcd.setCursor(7, 1); lcd.print(rgb[1]); lcd.print(F("    "));
  }
  while (true);
colorEnter1:
  lcd.setCursor(0, 1); lcd.print(F("nastavena!      "));
  delay(500);

  lcd.setCursor(0, 0); lcd.print(F("Hodnota zelene  "));
  lcd.setCursor(0, 1); lcd.print(F("barvy:          "));

  do
  {
    keyPressed = wait4key();
    wait4antikey(keyPressed);
    switch (keyPressed) {
      case 1:
        if (rgb[2] == 99) {
          rgb[2]--;
        }
        rgb[2]++;
        break;

      case 2:
        if (rgb[2] == 0) {
          rgb[2]++;
        }
        rgb[2]--;
        break;

      case 3:
        lcd.setCursor(0, 0); lcd.print(F("Zelena barva    "));
        lcd.setCursor(0, 1); lcd.print(F("                "));
        colorNow = 2;
        delay(500);
        goto colorEnter2;
        break;

      case 4:

        break;

      default:

        break;
    }

    lcd.setCursor(7, 1); lcd.print(rgb[2]); lcd.print("    ");
  }
  while (true);
colorEnter2:
  lcd.setCursor(0, 1); lcd.print(F("nastavena!      "));
  delay(500);

  lcd.setCursor(0, 0); lcd.print(F("Hodnota modre   "));
  lcd.setCursor(0, 1); lcd.print(F("barvy:          "));

  do
  {
    keyPressed = wait4key();
    wait4antikey(keyPressed);
    switch (keyPressed) {
      case 1:
        if (rgb[3] == 99) {
          rgb[3]--;
        }
        rgb[3]++;
        break;

      case 2:
        if (rgb[3] == 0) {
          rgb[3]++;
        }
        rgb[3]--;
        break;

      case 3:
        lcd.setCursor(0, 0); lcd.print(F("Modra barva     "));
        lcd.setCursor(0, 1); lcd.print(F("                "));
        colorNow = 2;
        delay(500);
        goto colorEnter3;
        break;

      case 4:

        break;

      default:

        break;
    }

    lcd.setCursor(7, 1); lcd.print(rgb[3]); lcd.print(F("    "));
  }
  while (true);
colorEnter3:
  lcd.setCursor(0, 1); lcd.print(F("nastavena!      "));
  delay(1000);

  lcd.setCursor(0, 0); lcd.print(F("Hodnoty barev   "));
  lcd.setCursor(0, 1); lcd.print(F("nastaveny!      "));

}

void ukazatTeplotu()
{
  lcd.setCursor(0, 0); lcd.print(F("                "));
  lcd.setCursor(0, 1); lcd.print(F("Temp: 21 C   ")); //sem se doplni kod na zjisteni pravdive teploty
}

void ukazatVlhkost()
{
  lcd.setCursor(0, 0); lcd.print(F("                "));
  lcd.setCursor(0, 1); lcd.print(F("Humi: 59 %   ")); //sem se doplni kod na zjisteni pravdive vlhkosti
}

void ukazatTlak()
{
  lcd.setCursor(0, 0); lcd.print(F("                "));
  lcd.setCursor(0, 1); lcd.print(F("Press: 1000 hPa ")); //sem se doplni kod na zjisteni pravdiveho tlaku
}

void restartovatKC()
{
  lcd.setCursor(0, 0); lcd.print(F("                "));

  lcd.setCursor(0, 1); lcd.print(F("Restarting      "));
  delay(250);
  lcd.setCursor(0, 1); lcd.print(F("Restarting.     "));
  delay(250);
  lcd.setCursor(0, 1); lcd.print(F("Restarting..    "));
  delay(250);
  lcd.setCursor(0, 1); lcd.print(F("Restarting...   "));
  delay(500);

  digitalWrite(11, LOW);

  //reset();//zatim nefunguje, bude priste
}

void refresh_lcd()
{
  //preicteni pocitadla
  refreshCount += 1;

  //IFy casove spinane, v poslednim je refreshCount = 0;
  if (refreshCount == 150)
  {
    lcd.setCursor(0, 0); lcd.print(F("Temperature:    "));
    //lcd.setCursor(0, 1); lcd.print(String(BMP(temperature)));
    lcd.setCursor(0, 1); lcd.print(F("26.18"));
    lcd.write(byte(0)); //stupen
    lcd.print("C  ");
    lcd.print("79.12"); //vypise hodnotu ve fahrenheitech
    lcd.write(byte(0)); //stupen
    lcd.write('F');
  }

  if (refreshCount == 300)
  {
    lcd.setCursor(0, 0); lcd.print(F("Pressure:       "));
    //lcd.setCursor(0, 1); lcd.print(String(BMP(pressure)) + " hPa     ");
    lcd.setCursor(0, 1); lcd.print(F("1012.73 hPa     "));
  }

  if (refreshCount == 450)
  {
    lcd.setCursor(0, 0); lcd.print(F("Humidity:       "));
    lcd.setCursor(0, 1); lcd.print(String(HTU_convHumi()) + " %         ");
    //lcd.setCursor(0, 1); lcd.print(F("46.96 %         "));
  }

  if (refreshCount == 600)
  {
    lcd.setCursor(0, 0); lcd.print(F("Users:          "));
    lcd.setCursor(0, 1); lcd.print(F("1               ")); //sem se doplni kod na zjisteni poctu lidi
    refreshCount = 0;
  }
}

void refresh_led()
{
  static byte r;
  static byte g;
  static byte b;
  static int x;
  int rychlost = 3;

  delay(10); //celkove cekani mezi vsemi operacemi (proste snizovani taktu CPU :D)

  if (b >= 200)
  {
    x = 1;
  }
  if (b <= 50)
  {
    x = 2;
  }

  switch (x)
  {
    case 0:
      b = 161;
      x = 2;
      break;
    case 1:
      b -= rychlost;
      break;
    case 2:
      b += rychlost;
      break;
  }

  analogWrite(R_led_pin, r);
  analogWrite(G_led_pin, g);
  analogWrite(B_led_pin, b);
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\

void HandleSerial()
{
  if (Serial.available() > 0)
  {
    if (Serial.peek() == '#')
    {
      delay(100);
      Serial.read();
      dsc = "";
      dsc = SerialRead(1);
      if (dsc == "D")
      {
        dsc = SerialRead(1);
        if (dsc == "S")
        {
          //sending info
          dsc = SerialRead(1);
          if (dsc == "T")
          {
            //sending temperature
            dsc = SerialRead(3);
            if (dsc == "00E")
            {
              //Serial.println("RRT" + String(HTU_convTemp()*100, 0) + "E");
              Serial.println("#RRT-212E");
            }
          }
          else if (dsc == "H")
          {
            dsc = SerialRead(3);
            if (dsc == "00E")
            {
              //HERE SERIAL PRINT HUMIDITY
              Serial.println("#RRH99E");
            }
          }
          else if (dsc == "P")
          {
            dsc = SerialRead(3);
            if (dsc == "00E")
            {
              //HERE SERIAL PRINT PRESSURE
              Serial.println("#RRP1024321E");
            }
          }
        }
        else if (dsc == "C")
        {
          //DO CHANGE
          if (Serial.read() == 'C')
          {
            //color change
            LED_address = SerialRead(2);
            Rled = SerialRead(2).toInt();
            Gled = SerialRead(2).toInt();
            Bled = SerialRead(2).toInt();
            if (Serial.read() == 'E')
            {
              Serial.println("Changing color on: " + LED_address + " to:  B" + String(Rled) + " G" + String(Gled) + " B" + String(Bled));
//9 10 11

            }
          }
        }
        else if (dsc == "B")
        {
          //DO BROADCAST
          dsc = SerialRead(1);
          if (dsc == "C")
          {
            if (SerialRead(1) == ";")
            {
              codeToSend = "";
              while (Serial.peek() != ';')
              {
                codeToSend += SerialRead(1);
              }
              Serial.read();
              if (SerialRead(1) == "E")
              {
                //HERE DIRECTLY BROADCAST CODE (v promenne codeToSend)
                //Serial.println("Broadcasting code: " + codeToSend);
                mySwitch.send(codeToSend.toInt(), 24);
              }
            }
          }
        }
        else if (dsc == "R")
        {
          //response receiving
        }
      }
      else
      {
        Serial.read();
      }
    }
    dsc == "";
  }
}

long htu(int adresa, int kod)
{
  Wire.beginTransmission(adresa);
  Wire.write(kod);
  Wire.endTransmission();
  byte DataHIGH;
  byte DataLOW;
  byte CRC;
  long data;
  Wire.requestFrom(adresa, 3);
  while (Wire.available())
  {
    DataHIGH = Wire.read();
    DataLOW = Wire.read();
    CRC = Wire.read();
  }
  data = DataHIGH;
  data = data << 8;
  data = data + DataLOW;
  return data;
}

float HTU_convTemp()
{
  return -46.85 + 175.72 * ((htu(HTU_ADRESA, HTU_TEPLOTA)) / pow(2, 16));
}

float HTU_convHumi()
{
  return -6 + 125 * ((htu(HTU_ADRESA, HTU_VLHKOST)) / pow(2, 16));
}

float BMP(int in)
{
  const int P0 = 1013.25;
  double T, P;
  char result = bmp.startMeasurment();

  if (result != 0) {
    delay(result);
    result = bmp.getTemperatureAndPressure(T, P);

    if (result != 0)
    {
      double A = bmp.altitude(P, P0);
      switch (in) {
        case 1:
          return T;

        case 2:
          P += 40;
          return P;

        case 3:
          return A;
      }
    }
  }
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//

int mMenu()
{
  mPozice = 1;
  mZacatek = true;
  mZobrazeny = 1;

  refresh_led();
  if (digitalRead(upPin)    == 1) {
    wait4antikey(1);
    goto preskoc;

  }
  if (digitalRead(downPin)  == 1) {
    wait4antikey(2);
    goto preskoc;

  }
  if (digitalRead(enterPin) == 1) {
    wait4antikey(3);
    goto preskoc;
  }
  if (digitalRead(backPin)  == 1) {
    wait4antikey(4);
    goto preskoc;
  }

  return 0;

preskoc:

  lcd.setCursor(0, 0); lcd.print(F("KeepCUBE setup  "));
  lcd.setCursor(0, 1); lcd.print(mChar[0]);

  mStart();
}

int mStart()
{

  while (true) {

    lcd.setCursor(0, 0); lcd.print(F("KeepCUBE setup  "));
    keyPressed = wait4key();
    wait4antikey(keyPressed);

    switch (keyPressed) {
      case 1:

        if (mFlip == 2) {
          mPozice -= 2;
        }

        //if (mFlip == 1 && mPozice == mPocet) {
        //  mPozice = (mPocet - 1);
        //}

        //if (mZacatek == true) {mPozice -= 1; mZacatek = false;}
        mUp();
        break;

      case 2:
        if (mFlip == 1) {
          mPozice += 2;
        }
        mDown();
        break;

      case 3:
        mEnter();
        break;

      case 4:
        return 0;
        break;
    }
  }
}

void mUp()
{
  if (mPozice < 0) {
    mPozice = 0;
  }

  if (mPozice == mPocet) {
    mPozice = mPocet;
    mPozice--;
  }
  lcd.setCursor(0, 1); lcd.print(mChar[mPozice]);
  mZobrazeny = mPozice;
  mZobrazeny++;
  mPozice--;
  mFlip = 1;
}

void mDown()
{
  lcd.setCursor(0, 1); lcd.print(mChar[mPozice]);
  mZobrazeny = mPozice;
  mZobrazeny++;
  mPozice++;

  if (mPozice == mPocet) {
    mPozice = mPozice - 1;
  }
  mFlip = 2;
}

void mEnter()
{
  switch (mZobrazeny) { //Tady se zpousti ty funkce z menu
    case 1:
      zobrazitIP();
      mBack();
      break;

    case 2:
      nastavitBarvu();
      mBack();
      break;

    case 3:
      ukazatTeplotu();
      mBack();
      break;

    case 4:
      ukazatVlhkost();
      mBack();
      break;

    case 5:
      ukazatTlak();
      mBack();
      break;

    case 6:
      restartovatKC();
      mBack();
      break;
  }
}

void mBack()
{
zacatek:
  keyPressed = wait4key();
  wait4antikey(keyPressed);
  if (keyPressed == 4) {
    goto konec;
  }
  goto zacatek;
konec:
  int mToCoSeMaZobrazit = mZobrazeny;
  mToCoSeMaZobrazit--;
  lcd.setCursor(0, 1); lcd.print(mChar[mToCoSeMaZobrazit]);
}

int wait4key()
{
  while (true)
  {
    refresh_led();
    if (digitalRead(upPin)    == 1) {
      return 1;
    }
    if (digitalRead(downPin)  == 1) {
      return 2;
    }
    if (digitalRead(enterPin) == 1) {
      return 3;
    }
    if (digitalRead(backPin)  == 1) {
      return 4;
    }
  }
}

void wait4antikey(int key)
{
  switch (key) {
    case 1:
      while (digitalRead(upPin)    != 0) {
        refresh_led();
      }
      break;
    case 2:
      while (digitalRead(downPin)  != 0) {
        refresh_led();
      }
      break;
    case 3:
      while (digitalRead(enterPin) != 0) {
        refresh_led();
      }
      break;
    case 4:
      while (digitalRead(backPin)  != 0) {
        refresh_led();
      }
      break;
  }
}

void wait4randomkey()
{
  int key = wait4key();

  switch (key) {
    case 1:
      while (digitalRead(upPin)    != 0) {
        refresh_led();
      }
      break;
    case 2:
      while (digitalRead(downPin)  != 0) {
        refresh_led();
      }
      break;
    case 3:
      while (digitalRead(enterPin) != 0) {
        refresh_led();
      }
      break;
    case 4:
      while (digitalRead(backPin)  != 0) {
        refresh_led();
      }
      break;
  }
}

error: pathspec 'Base/Base.ino' did not match any file(s) known to git


[lmr] Use only one digital pin for sourcing power to the measurement dividers

#include <avr/wdt.h>
#include <avr/sleep.h>
#include <rf12_itplus.h>

// Enabling LMREMOTE_SERIAL also disables several power saving features
#define LMREMOTE_SERIAL 38400

// Base Idenfier for the RFM12B (0-63)
// The transmitted ID is this ID plus the pin number
const char _rfNodeBaseId = 0;
// RFM12B band RF12_433MHZ, RF12_868MHZ, RF12_915MHZ
const unsigned char _rfBand = RF12_915MHZ;
// How many seconds to delay between measurements
const unsigned char _sleepInterval = 2;
// Analog pins to read. This is a bitfield, LSB is analog 0
const unsigned char _enabledProbePins = 0x01;
// Analog pin connected to source power.  Set to 0xff to disable sampling
const unsigned char _pinBattery = 1;
// Digital pins for LEDs, 0xff to disable
const unsigned char _pinLedRx = 0xff;
const unsigned char _pinLedTx = 0xff; //9
// Digital pin used for sourcing power to the probe dividers
const unsigned char _pinProbeSupply = 4;
// Percentage (integer) of VCC where the battery is considered low (33% = 1.1V)
#define BATTERY_LOW_PCT 33
// Number of seconds to keep the "recent/new" bit set
#define RECENT_EXPIRE_SECS 1800
// Number of oversampling bits when measuring temperature [0-2]
#define TEMP_OVERSAMPLE_BITS 1

#define RF_PINS_PER_SOURCE 6
#define PIN_DISABLED(pin) ((_enabledProbePins & (1 << pin)) == 0)

// Bits used in output packet
// byte0/1 reserved Node IDs
#define NODEID_MASTER      0x3F
// byte1
#define BYTE1_DUAL_PROBE   0x10
#define BYTE1_RECENT_BOOT  0x20
// hygro byte
#define HYGRO_BATTERY_OK   0x00
#define HYGRO_BATTERY_LOW  0x80
#define HYGRO_NO_HYGRO     0x6A
#define HYGRO_SECOND_PROBE 0x7D
#define HYGRO_LMREMOTE_KEY 0x7F

#ifdef LMREMOTE_SERIAL
  #define SLEEPMODE_TX    1
  #define SLEEPMODE_ADC   SLEEP_MODE_IDLE
#else
  #define SLEEPMODE_TX    2
  #define SLEEPMODE_ADC   SLEEP_MODE_ADC
#endif

#define RECV_CYCLE_TIME  5000    // expected receive cycle, millisecond
#define MIN_RECV_WIN     8       // minimum window size, power of 2
#define MAX_RECV_WIN     512     // maximum window size, power of 2

static unsigned int _previousReads[RF_PINS_PER_SOURCE];
static unsigned long _tempReadLast;
static unsigned int _loopCnt;
static unsigned char _sameCount;
static unsigned char _isRecent = BYTE1_RECENT_BOOT;
static unsigned char _isBattLow;

static unsigned int _recvCycleAct;
static unsigned int _recvWindow;
static unsigned long _recvLast;
static bool _recvSynced;

static volatile bool _adcBusy;
static volatile bool _watchdogWaiting;

// The WDT is used solely to wake us from sleep
ISR(WDT_vect) { _watchdogWaiting = false; }
ISR(ADC_vect) { _adcBusy = false; }

static bool packetReceived(unsigned char nodeId, unsigned int val)
{
#if LMREMOTE_SERIAL
  Serial.print(F("IN("));
  Serial.print(nodeId);
  Serial.print(',');
  Serial.print(rf12_rssi(), DEC);
  Serial.print(F(")="));
  Serial.print(val);
  Serial.print('\n');
#endif

  if (nodeId != NODEID_MASTER)
    return false;
  // val contains requested fan speed percent
  return true;
}

static bool rf12_doWork(void)
{
  if (rf12_recvDone() && rf12_crc == 0)
  {
    if (_pinLedRx != 0xff) digitalWrite(_pinLedRx, HIGH);

    unsigned char nodeId = ((rf12_buf[0] & 0x0f) << 2) | (rf12_buf[1] >> 6);
    unsigned int val = (rf12_buf[1] & 0x0f) << 8 | rf12_buf[2];
    return packetReceived(nodeId, val);
  }
  if (_pinLedRx != 0xff) digitalWrite(_pinLedRx, LOW);
  return false;
}

static unsigned int analogReadSleep(unsigned char pin)
{
  _adcBusy = true;
  ADMUX = (DEFAULT << 6) | pin;
  bitSet(ADCSRA, ADIE);
  set_sleep_mode(SLEEPMODE_ADC);
  while (_adcBusy)
    sleep_mode();
  return ADC;
}

static void sleepPeriod(uint8_t wdt_period)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // Set the watchdog to wake us up and turn on its interrupt
  wdt_enable(wdt_period);
  WDTCSR |= bit(WDIE);

  // Turn off Brown Out Detector
  // sleep must be entered within 3 cycles of BODS being set
  sleep_enable();
  MCUCR = MCUCR | bit(BODSE) | bit(BODS);
  MCUCR = (MCUCR & ~bit(BODSE)) | bit(BODS);

  // Sleep
  sleep_cpu();

  // Back from sleep
  wdt_disable();
  sleep_disable();
}

static void sleep(unsigned int msec)
// Code copied from Sleepy::loseSomeSleep(), jeelib
{
  unsigned int msleft = msec;
  while (msleft >= 16)
  {
    char wdp = 0; // wdp 0..9 corresponds to roughly 16..8192 ms
    // calc wdp as log2(msleft/16), i.e. loop & inc while next value is ok
    for (unsigned int m = msleft; m >= 32; m >>= 1)
      if (++wdp >= 9)
        break;
    _watchdogWaiting = true;
    sleepPeriod(wdp);
    unsigned int halfms = 8 << wdp;
    msleft -= halfms;
    if (_watchdogWaiting)
      continue;
    msleft -= halfms;
  }

  // adjust the milli ticks, since we will have missed several
#if defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny85__) || defined (__AVR_ATtiny44__)
    extern volatile unsigned long millis_timer_millis;
    millis_timer_millis += msecs - msleft;
#else
    extern volatile unsigned long timer0_millis;
    timer0_millis += msec - msleft;
#endif
}

static void resetEstimate(void)
{
#if _DEBUG
  Serial.print(F("Resetting Estimate\n"));
#endif
  _recvCycleAct = RECV_CYCLE_TIME;
  _recvWindow = MAX_RECV_WIN;
  _recvSynced = false;

  unsigned long start = millis();
  while (!rf12_doWork())
    if (millis() - start > RECV_CYCLE_TIME)
      return;
  _recvLast = millis();
}

static bool optimalSleep(void)
// Code adapted from jeelib/examples/syncRecv optimalSleep()
{
  unsigned char lost = (millis() - _recvLast + _recvCycleAct / 2) / _recvCycleAct;
  if (lost > 10)
  {
    resetEstimate();
    return false;
  }

  // double the window every N packets lost
  if (lost > 0 && lost % 2 == 0 && _recvWindow < MAX_RECV_WIN)
    _recvWindow *= 2;

  unsigned long predict = _recvLast + (lost + 1) * _recvCycleAct;
  unsigned int sleepDur =  predict - _recvWindow - millis();
  sleep(sleepDur);
  rf12_sleep(RF12_WAKEUP);

  unsigned long recvTime;
  unsigned long timeout = predict + _recvWindow;
  do {
    recvTime = millis();
    if ((long)(recvTime - timeout) >= 0)
    {
#if _DEBUG
      Serial.print(" f "); Serial.print(lost);
      Serial.print(" s "); Serial.print(sleepDur);
      Serial.print(" e "); Serial.print(_recvCycleAct);
      Serial.print(" w "); Serial.print(_recvWindow);
      Serial.print(" p "); Serial.print(predict);
      Serial.print(" r "); Serial.println(recvTime);
      Serial.flush();
#endif
      return false;
    }
  } while (!rf12_doWork());

  unsigned int newEst = (recvTime - _recvLast) / (lost + 1);
  if (_recvSynced)
    _recvCycleAct = (4 * _recvCycleAct + newEst + 3) / 5; // 5-fold smoothing
  else
    _recvCycleAct = newEst;
  _recvLast = recvTime;

#if _DEBUG
  Serial.print(" n "); Serial.print(lost);
  Serial.print(" e "); Serial.print(_recvCycleAct);
  Serial.print(" E "); Serial.print(newEst);
  Serial.print(" w "); Serial.print(_recvWindow);
  Serial.print(" p "); Serial.print(predict);
  Serial.print(" r "); Serial.println(recvTime);
#endif

  if (_recvWindow > MIN_RECV_WIN)
    _recvWindow /= 2;
  else
    _recvSynced = true;

  return true;
}

static void updateBatteryLow(void)
{
  const unsigned char BATREAD_COUNT = 4;

  _isBattLow = HYGRO_BATTERY_OK;
  if (_pinBattery != 0xff)
  {
    unsigned int adcSum = 0;
    unsigned char battPct;
    for (unsigned char i=0; i<BATREAD_COUNT; ++i)
      adcSum += analogReadSleep(_pinBattery);
    // Percent of VCC
    battPct = (adcSum * 100UL) / (1024 * BATREAD_COUNT);

#ifdef LMREMOTE_SERIAL
    Serial.print("Battery %: "); Serial.print(battPct, DEC); Serial.print('\n');
#endif

    if (battPct < BATTERY_LOW_PCT)
      _isBattLow = HYGRO_BATTERY_LOW;
  }
}

static void transmitTemp(unsigned char pin)
{
  unsigned char outbuf[4];
  unsigned char nodeId = _rfNodeBaseId + pin;
  unsigned int val = _previousReads[pin];
  val <<= (12 - (10 + TEMP_OVERSAMPLE_BITS));
  outbuf[0] = 0x90 | ((nodeId & 0x3f) >> 2);
  outbuf[1] = ((nodeId & 0x3f) << 6) | _isRecent | (val >> 8);
  outbuf[2] = (val & 0xff);
  outbuf[3] = HYGRO_LMREMOTE_KEY | _isBattLow;
  //Serial.println(outbuf[3], HEX);

  // Don't check for air to be clear, we just woke from sleep and it will be milliseconds before
  // the RFM chip is actually up and running
  rf12_sendStart(outbuf, sizeof(outbuf));
  rf12_sendWait(SLEEPMODE_TX);
}

static void newTempsAvailable(void)
{
  // Enable the transmitter because it takes 1-5ms to turn on (3ms in my testing)
  rf12_sleep(RF12_WAKEUP);

  updateBatteryLow();
  // We're done with the ADC shut it down until the next wake cycle
  ADCSRA &= ~bit(ADEN);
  if (_isRecent && (millis() > RECENT_EXPIRE_SECS))
  {
    //Serial.print("No longer recent\n");
    _isRecent = 0;
  }

  boolean hasTransmitted = false;
  for (unsigned char pin=0; pin < RF_PINS_PER_SOURCE; ++pin)
  {
    if (PIN_DISABLED(pin))
      continue;
    if (hasTransmitted) sleep(16);
    transmitTemp(pin);
    hasTransmitted = true;
  }

  rf12_sleep(RF12_SLEEP);
  if (_pinLedTx != 0xff)
  {
    digitalWrite(_pinLedTx, HIGH);
    sleep(16);
    digitalWrite(_pinLedTx, LOW);
  }
}

static void stabilizeAdc(void)
{
  const unsigned char INTERNAL_REF = 0b1110;
  unsigned int last;
  unsigned char totalCnt = 0;
  unsigned char sameCnt = 0;
  unsigned int curr = analogReadSleep(INTERNAL_REF);
  // Reads the adc a bunch of times until the value settles
  // Usually you hear "discard the first few ADC readings after sleep"
  // but this seems a bit more scientific as we wait for the AREF cap to charge
  do {
    ++totalCnt;
#ifdef LMREMOTE_SERIAL
    Serial.print(curr, DEC);
    Serial.print(' ');
#endif
    last = curr;
    curr = analogReadSleep(INTERNAL_REF);
    if (last == curr)
      ++sameCnt;
    else
      sameCnt = 0;
  } while ((totalCnt < 64) && (sameCnt < 4));
}

static void checkTemps(void)
{
  const unsigned char OVERSAMPLE_COUNT[] = {1, 4, 16, 64};  // 4^n
  boolean modified = false;
  unsigned int oversampled_adc = 0;

#ifdef LMREMOTE_SERIAL
  Serial.print(millis(), DEC);
  Serial.print(" Checking temps: ");
#endif

  // Enable the ADC
  ADCSRA |= bit(ADEN);
  // The probe themistor voltage dividers are normally powered down
  // to save power, using digital lines to supply Vcc to them.
  digitalWrite(_pinProbeSupply, HIGH);
  // Wait for AREF capacitor to charge
  stabilizeAdc();

  for (unsigned char pin=0; pin < RF_PINS_PER_SOURCE; ++pin)
  {
    if (PIN_DISABLED(pin))
      continue;

    for (unsigned char o=0; o<OVERSAMPLE_COUNT[TEMP_OVERSAMPLE_BITS]; ++o)
    {
      unsigned int adc = analogReadSleep(pin);
      if (adc == 0 || adc >= 1023)
      {
        oversampled_adc = 0;
        break;
      }
      oversampled_adc += adc;
    }
    oversampled_adc = oversampled_adc >> TEMP_OVERSAMPLE_BITS;

#ifdef LMREMOTE_SERIAL
    Serial.print(oversampled_adc, DEC); Serial.print(' ');
#endif
    if (oversampled_adc != _previousReads[pin])
      modified = true;
    _previousReads[pin] = oversampled_adc;
  }
  digitalWrite(_pinProbeSupply, LOW);

#ifdef LMREMOTE_SERIAL
  Serial.print('\n');
#endif

  if (modified || (_sameCount > (30 / _sleepInterval)))
  {
    _sameCount = 0;
    newTempsAvailable();
  }
  else
    ++_sameCount;
  // Disable the ADC
  ADCSRA &= ~bit(ADEN);

  _tempReadLast = millis();
}

void setup(void)
{
  // Turn off the units we never use (this only affects non-sleep power)
  PRR = bit(PRUSART0) | bit(PRTWI) | bit(PRTIM1) | bit(PRTIM2);
  // Disable digital input buffers on the analog in ports
  DIDR0 = bit(ADC5D) | bit(ADC4D) | bit(ADC3D) | bit(ADC2D) | bit(ADC1D) | bit(ADC0D);
  DIDR1 = bit(AIN1D) | bit(AIN0D);

#ifdef LMREMOTE_SERIAL
  PRR &= ~bit(PRUSART0);
  Serial.begin(LMREMOTE_SERIAL); Serial.println("$UCID,lmremote"); delay(10);
#endif

  rf12_initialize(1, _rfBand);
  // Crystal 1.66MHz Low Battery Detect 2.2V
  rf12_control(0xC040);

  if (_pinLedRx != 0xff) pinMode(_pinLedRx, OUTPUT);
  if (_pinLedTx != 0xff) pinMode(_pinLedTx, OUTPUT);

  pinMode(_pinProbeSupply, OUTPUT);

  // Force a transmit on next read
  memset(_previousReads, 0xff, sizeof(_previousReads));
}

void loop(void)
{
  if (_loopCnt % 2 == 0)
    checkTemps();

#ifdef LMREMOTE_SERIAL
  Serial.flush(); delay(2);
#endif

  if (_recvLast == 0)
    resetEstimate();
  else
    optimalSleep();
  rf12_sleep(RF12_SLEEP);

  ++_loopCnt;
}

#include <avr/wdt.h>
#include <avr/sleep.h>
#include <rf12_itplus.h>

// Enabling LMREMOTE_SERIAL also disables several power saving features
#define LMREMOTE_SERIAL 38400

// Base Idenfier for the RFM12B (0-63)
// The transmitted ID is this ID plus the pin number
const char _rfNodeBaseId = 0;
// RFM12B band RF12_433MHZ, RF12_868MHZ, RF12_915MHZ
const unsigned char _rfBand = RF12_915MHZ;
// How many seconds to delay between measurements
const unsigned char _sleepInterval = 2;
// Analog pins to read. This is a bitfield, LSB is analog 0
const unsigned char _enabledProbePins = 0x01;
// Analog pin connected to source power.  Set to 0xff to disable sampling
const unsigned char _pinBattery = 1;
// Digital pins for LEDs, 0xff to disable
const unsigned char _pinLedRx = 0xff;
const unsigned char _pinLedTx = 0xff; //9
// Digital pins used for sourcing power to the probe dividers
const unsigned char _pinProbeSupplyBase = 4;
// Percentage (integer) of VCC where the battery is considered low (33% = 1.1V)
#define BATTERY_LOW_PCT 33
// Number of seconds to keep the "recent/new" bit set
#define RECENT_EXPIRE_SECS 1800
// Number of oversampling bits when measuring temperature [0-2]
#define TEMP_OVERSAMPLE_BITS 1

#define RF_PINS_PER_SOURCE 6
#define PIN_DISABLED(pin) ((_enabledProbePins & (1 << pin)) == 0)

// Bits used in output packet
// byte0/1 reserved Node IDs
#define NODEID_MASTER      0x3F
// byte1
#define BYTE1_DUAL_PROBE   0x10
#define BYTE1_RECENT_BOOT  0x20
// hygro byte
#define HYGRO_BATTERY_OK   0x00
#define HYGRO_BATTERY_LOW  0x80
#define HYGRO_NO_HYGRO     0x6A
#define HYGRO_SECOND_PROBE 0x7D
#define HYGRO_LMREMOTE_KEY 0x7F

#ifdef LMREMOTE_SERIAL
  #define SLEEPMODE_TX    1
  #define SLEEPMODE_ADC   SLEEP_MODE_IDLE
#else
  #define SLEEPMODE_TX    2
  #define SLEEPMODE_ADC   SLEEP_MODE_ADC
#endif

#define RECV_CYCLE_TIME  5000    // expected receive cycle, millisecond
#define MIN_RECV_WIN     8       // minimum window size, power of 2
#define MAX_RECV_WIN     512     // maximum window size, power of 2

static unsigned int _previousReads[RF_PINS_PER_SOURCE];
static unsigned long _tempReadLast;
static unsigned int _loopCnt;
static unsigned char _sameCount;
static unsigned char _isRecent = BYTE1_RECENT_BOOT;
static unsigned char _isBattLow;

static unsigned int _recvCycleAct;
static unsigned int _recvWindow;
static unsigned long _recvLast;
static bool _recvSynced;

static volatile bool _adcBusy;
static volatile bool _watchdogWaiting;

// The WDT is used solely to wake us from sleep
ISR(WDT_vect) { _watchdogWaiting = false; }
ISR(ADC_vect) { _adcBusy = false; }

static bool packetReceived(unsigned char nodeId, unsigned int val)
{
#if LMREMOTE_SERIAL
  Serial.print(F("IN("));
  Serial.print(nodeId);
  Serial.print(',');
  Serial.print(rf12_rssi(), DEC);
  Serial.print(F(")="));
  Serial.print(val);
  Serial.print('\n');
#endif

  if (nodeId != NODEID_MASTER)
    return false;
  // val contains requested fan speed percent
  return true;
}

static bool rf12_doWork(void)
{
  if (rf12_recvDone() && rf12_crc == 0)
  {
    if (_pinLedRx != 0xff) digitalWrite(_pinLedRx, HIGH);

    unsigned char nodeId = ((rf12_buf[0] & 0x0f) << 2) | (rf12_buf[1] >> 6);
    unsigned int val = (rf12_buf[1] & 0x0f) << 8 | rf12_buf[2];
    return packetReceived(nodeId, val);
  }
  if (_pinLedRx != 0xff) digitalWrite(_pinLedRx, LOW);
  return false;
}

static unsigned int analogReadSleep(unsigned char pin)
{
  _adcBusy = true;
  ADMUX = (DEFAULT << 6) | pin;
  bitSet(ADCSRA, ADIE);
  set_sleep_mode(SLEEPMODE_ADC);
  while (_adcBusy)
    sleep_mode();
  return ADC;
}

static void sleepPeriod(uint8_t wdt_period)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // Set the watchdog to wake us up and turn on its interrupt
  wdt_enable(wdt_period);
  WDTCSR |= bit(WDIE);

  // Turn off Brown Out Detector
  // sleep must be entered within 3 cycles of BODS being set
  sleep_enable();
  MCUCR = MCUCR | bit(BODSE) | bit(BODS);
  MCUCR = (MCUCR & ~bit(BODSE)) | bit(BODS);

  // Sleep
  sleep_cpu();

  // Back from sleep
  wdt_disable();
  sleep_disable();
}

static void sleep(unsigned int msec)
// Code copied from Sleepy::loseSomeSleep(), jeelib
{
  unsigned int msleft = msec;
  while (msleft >= 16)
  {
    char wdp = 0; // wdp 0..9 corresponds to roughly 16..8192 ms
    // calc wdp as log2(msleft/16), i.e. loop & inc while next value is ok
    for (unsigned int m = msleft; m >= 32; m >>= 1)
      if (++wdp >= 9)
        break;
    _watchdogWaiting = true;
    sleepPeriod(wdp);
    unsigned int halfms = 8 << wdp;
    msleft -= halfms;
    if (_watchdogWaiting)
      continue;
    msleft -= halfms;
  }

  // adjust the milli ticks, since we will have missed several
#if defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny85__) || defined (__AVR_ATtiny44__)
    extern volatile unsigned long millis_timer_millis;
    millis_timer_millis += msecs - msleft;
#else
    extern volatile unsigned long timer0_millis;
    timer0_millis += msec - msleft;
#endif
}

static void resetEstimate(void)
{
#if _DEBUG
  Serial.print(F("Resetting Estimate\n"));
#endif
  _recvCycleAct = RECV_CYCLE_TIME;
  _recvWindow = MAX_RECV_WIN;
  _recvSynced = false;

  unsigned long start = millis();
  while (!rf12_doWork())
    if (millis() - start > RECV_CYCLE_TIME)
      return;
  _recvLast = millis();
}

static bool optimalSleep(void)
// Code adapted from jeelib/examples/syncRecv optimalSleep()
{
  unsigned char lost = (millis() - _recvLast + _recvCycleAct / 2) / _recvCycleAct;
  if (lost > 10)
  {
    resetEstimate();
    return false;
  }

  // double the window every N packets lost
  if (lost > 0 && lost % 2 == 0 && _recvWindow < MAX_RECV_WIN)
    _recvWindow *= 2;

  unsigned long predict = _recvLast + (lost + 1) * _recvCycleAct;
  unsigned int sleepDur =  predict - _recvWindow - millis();
  sleep(sleepDur);
  rf12_sleep(RF12_WAKEUP);

  unsigned long recvTime;
  unsigned long timeout = predict + _recvWindow;
  do {
    recvTime = millis();
    if ((long)(recvTime - timeout) >= 0)
    {
#if _DEBUG
      Serial.print(" f "); Serial.print(lost);
      Serial.print(" s "); Serial.print(sleepDur);
      Serial.print(" e "); Serial.print(_recvCycleAct);
      Serial.print(" w "); Serial.print(_recvWindow);
      Serial.print(" p "); Serial.print(predict);
      Serial.print(" r "); Serial.println(recvTime);
      Serial.flush();
#endif
      return false;
    }
  } while (!rf12_doWork());

  unsigned int newEst = (recvTime - _recvLast) / (lost + 1);
  if (_recvSynced)
    _recvCycleAct = (4 * _recvCycleAct + newEst + 3) / 5; // 5-fold smoothing
  else
    _recvCycleAct = newEst;
  _recvLast = recvTime;

#if _DEBUG
  Serial.print(" n "); Serial.print(lost);
  Serial.print(" e "); Serial.print(_recvCycleAct);
  Serial.print(" E "); Serial.print(newEst);
  Serial.print(" w "); Serial.print(_recvWindow);
  Serial.print(" p "); Serial.print(predict);
  Serial.print(" r "); Serial.println(recvTime);
#endif

  if (_recvWindow > MIN_RECV_WIN)
    _recvWindow /= 2;
  else
    _recvSynced = true;

  return true;
}

static void updateBatteryLow(void)
{
  const unsigned char BATREAD_COUNT = 4;

  _isBattLow = HYGRO_BATTERY_OK;
  if (_pinBattery != 0xff)
  {
    unsigned int adcSum = 0;
    unsigned char battPct;
    for (unsigned char i=0; i<BATREAD_COUNT; ++i)
      adcSum += analogReadSleep(_pinBattery);
    // Percent of VCC
    battPct = (adcSum * 100UL) / (1024 * BATREAD_COUNT);

#ifdef LMREMOTE_SERIAL
    Serial.print("Battery %: "); Serial.print(battPct, DEC); Serial.print('\n');
#endif

    if (battPct < BATTERY_LOW_PCT)
      _isBattLow = HYGRO_BATTERY_LOW;
  }
}

static void transmitTemp(unsigned char pin)
{
  unsigned char outbuf[4];
  unsigned char nodeId = _rfNodeBaseId + pin;
  unsigned int val = _previousReads[pin];
  val <<= (12 - (10 + TEMP_OVERSAMPLE_BITS));
  outbuf[0] = 0x90 | ((nodeId & 0x3f) >> 2);
  outbuf[1] = ((nodeId & 0x3f) << 6) | _isRecent | (val >> 8);
  outbuf[2] = (val & 0xff);
  outbuf[3] = HYGRO_LMREMOTE_KEY | _isBattLow;
  //Serial.println(outbuf[3], HEX);

  // Don't check for air to be clear, we just woke from sleep and it will be milliseconds before
  // the RFM chip is actually up and running
  rf12_sendStart(outbuf, sizeof(outbuf));
  rf12_sendWait(SLEEPMODE_TX);
}

static void newTempsAvailable(void)
{
  // Enable the transmitter because it takes 1-5ms to turn on (3ms in my testing)
  rf12_sleep(RF12_WAKEUP);

  updateBatteryLow();
  // We're done with the ADC shut it down until the next wake cycle
  ADCSRA &= ~bit(ADEN);
  if (_isRecent && (millis() > RECENT_EXPIRE_SECS))
  {
    //Serial.print("No longer recent\n");
    _isRecent = 0;
  }

  boolean hasTransmitted = false;
  for (unsigned char pin=0; pin < RF_PINS_PER_SOURCE; ++pin)
  {
    if (PIN_DISABLED(pin))
      continue;
    if (hasTransmitted) sleep(16);
    transmitTemp(pin);
    hasTransmitted = true;
  }

  rf12_sleep(RF12_SLEEP);
  if (_pinLedTx != 0xff)
  {
    digitalWrite(_pinLedTx, HIGH);
    sleep(16);
    digitalWrite(_pinLedTx, LOW);
  }
}

static void enableAdcPullups(void)
{
  for (unsigned char pin=0; pin < RF_PINS_PER_SOURCE; ++pin)
  {
    if (PIN_DISABLED(pin))
      continue;

    // The probe themistor voltage dividers are normally powered down
    // to save power, using digital lines to supply Vcc to them.
    // Lines are used sequentially starting from _pinProbeSupplyBase
    // Note you can use the analog internal pullups as the fixed half of
    // the divider by setting this value to A0 (or higher).
    // The analog pullups are 20k-40kOhms, about 36k on my handful of chips.
    // If using digital lines you will supply your own resistor for the fixed half.
    digitalWrite(_pinProbeSupplyBase + pin, HIGH);
  }
}

static void stabilizeAdc(void)
{
  const unsigned char INTERNAL_REF = 0b1110;
  unsigned int last;
  unsigned int totalCnt = 0;
  unsigned int sameCnt = 0;
  unsigned int curr = analogReadSleep(INTERNAL_REF);
  // Reads the adc a bunch of times until the value settles
  // Usually you hear "discard the first few ADC readings after sleep"
  // but this seems a bit more scientific as we wait for the AREF cap to charge
  do {
    ++totalCnt;
#ifdef LMREMOTE_SERIAL
    Serial.print(curr, DEC);
    Serial.print(' ');
#endif
    last = curr;
    curr = analogReadSleep(INTERNAL_REF);
    if (last == curr)
      ++sameCnt;
    else
      sameCnt = 0;
  } while ((totalCnt < 64) && (sameCnt < 4));
}

static void checkTemps(void)
{
  const unsigned char OVERSAMPLE_COUNT[] = {1, 4, 16, 64};  // 4^n
  boolean modified = false;
  unsigned int oversampled_adc = 0;

#ifdef LMREMOTE_SERIAL
  Serial.print(millis(), DEC);
  Serial.print(" Checking temps: ");
#endif

  // Enable the ADC
  ADCSRA |= bit(ADEN);
  enableAdcPullups();
  stabilizeAdc();
  for (unsigned char pin=0; pin < RF_PINS_PER_SOURCE; ++pin)
  {
    if (PIN_DISABLED(pin))
      continue;

    for (unsigned char o=0; o<OVERSAMPLE_COUNT[TEMP_OVERSAMPLE_BITS]; ++o)
    {
      unsigned int adc = analogReadSleep(pin);
      if (adc == 0 || adc >= 1023)
      {
        oversampled_adc = 0;
        break;
      }
      oversampled_adc += adc;
    }
    oversampled_adc = oversampled_adc >> TEMP_OVERSAMPLE_BITS;

#ifdef LMREMOTE_SERIAL
    Serial.print(oversampled_adc, DEC); Serial.print(' ');
#endif
    if (oversampled_adc != _previousReads[pin])
      modified = true;
    _previousReads[pin] = oversampled_adc;

    digitalWrite(_pinProbeSupplyBase + pin, LOW);
  }

#ifdef LMREMOTE_SERIAL
  Serial.print('\n');
#endif

  if (modified || (_sameCount > (30 / _sleepInterval)))
  {
    _sameCount = 0;
    newTempsAvailable();
  }
  else
    ++_sameCount;
  // Disable the ADC
  ADCSRA &= ~bit(ADEN);

  _tempReadLast = millis();
}

static void setupSupplyPins(void)
{
  // Analog pullup supply pins don't need DIR set
  if (_pinProbeSupplyBase >= A0)
    return;
  for (unsigned char pin=0; pin < RF_PINS_PER_SOURCE; ++pin)
  {
    if (PIN_DISABLED(pin))
      continue;
    pinMode(_pinProbeSupplyBase + pin, OUTPUT);
  }
}

void setup(void)
{
  // Turn off the units we never use (this only affects non-sleep power)
  PRR = bit(PRUSART0) | bit(PRTWI) | bit(PRTIM1) | bit(PRTIM2);
  // Disable digital input buffers on the analog in ports
  DIDR0 = bit(ADC5D) | bit(ADC4D) | bit(ADC3D) | bit(ADC2D) | bit(ADC1D) | bit(ADC0D);
  DIDR1 = bit(AIN1D) | bit(AIN0D);

#ifdef LMREMOTE_SERIAL
  PRR &= ~bit(PRUSART0);
  Serial.begin(LMREMOTE_SERIAL); Serial.println("$UCID,lmremote"); delay(10);
#endif

  rf12_initialize(1, _rfBand);
  // Crystal 1.66MHz Low Battery Detect 2.2V
  rf12_control(0xC040);

  if (_pinLedRx != 0xff) pinMode(_pinLedRx, OUTPUT);
  if (_pinLedTx != 0xff) pinMode(_pinLedTx, OUTPUT);

  setupSupplyPins();

  // Force a transmit on next read
  memset(_previousReads, 0xff, sizeof(_previousReads));
}

void loop(void)
{
  if (_loopCnt % 2 == 0)
    checkTemps();

#ifdef LMREMOTE_SERIAL
  Serial.flush(); delay(2);
#endif

  if (_recvLast == 0)
    resetEstimate();
  else
    optimalSleep();
  rf12_sleep(RF12_SLEEP);

  ++_loopCnt;
}


add port register test code using DDRD

add port register test code using DDRD

byte pinTable[] = {2};

void setup() {
Serial.begin(0);
for (int i=0; i<8; i++) { pinMode(pinTable[i],INPUT_PULLUP); }
}

void loop() {
byte eight,prev_eight;
do {
eight = GPIOD_PDIR & 0xFF;

if (eight != prev_eight)
{
prev_eight = eight;
Serial.println(eight,HEX);
}
} while (1==1);
}

error: pathspec 'Kirbi/testing/port_manipulation/port_manipulation.ino' did not match any file(s) known to git


Add demo on new functionality

Add demo on new functionality

This demo shows how the new functionality added here can be used - it
allows the user to interactively toggle IR signal modulation and
inversion using the serial connection.

/*
 * IRremote: IRInvertModulate - demonstrates the ability enable/disable
 * IR signal modulation and inversion.
 * An IR LED must be connected to Arduino PWM pin 3.
 * To view the results, attach an Oscilloscope or Signal Analyser across the
 * legs of the IR LED.
 * Version 0.1 November, 2013
 * Copyright 2013 Aaron Snoswell
 * http://elucidatedbinary.com
 */

#include <IRremote.h>

IRsend irsend;

void setup()
{
  Serial.begin(9600);
  Serial.println("Welcome, visitor");
  Serial.println("Press 'm' to toggle IR modulation");
  Serial.println("Press 'i' to toggle IR inversion");
}

bool modulate = true;
bool invert = false;

void loop() {
  if (!Serial.available()) {
    // Send some random data
    irsend.sendNEC(0xa90, 12);
  } else {
    char c;
    do {
      c = Serial.read();
    } while(Serial.available());

    if(c == 'm') {
      modulate = !modulate;
      if(modulate) Serial.println("Enabling Modulation");
      else Serial.println("Disabling Modulation");
      irsend.enableIRModulation(modulate);
    } else if(c == 'i') {
      invert = !invert;
      if(invert) Serial.println("Enabling Invert");
      else Serial.println("Disabling Invert");
      irsend.enableIRInvert(invert);
    } else {
      Serial.println("Unknown Command");
    }
  }

  delay(300);
}

error: pathspec 'examples/IRInvertModulate/IRInvertModulate.ino' did not match any file(s) known to git


Found code

Found code

Found some missing code for the project from before my computer crashed.
Hopefully it still works. The code was to run an arduino bluno (some off
brand bluetooth arduino uno).

error: pathspec 'Arduino' did not match any file(s) known to git
error: pathspec 'code/sketch_sep29a/sketch_sep29a.ino' did not match any file(s) known to git


Teste passo

Teste passo

/* Bibliotecas de Controle de Motores de passo */
/* #include <Stepper.h> */
/* #include <AccelStepper.h> */
#include <CustomStepper.h> /* http://playground.arduino.cc/uploads/Main/CustomStepper.zip */

/* Define pinos */
#define DIRECAO_DIREITA_1 8
#define DIRECAO_DIREITA_2 9

#define DIRECAO_ESQUERDA_1 10
#define DIRECAO_ESQUERDA_2 11

/* Define váriaveis do motor */
#define NUMERO_PASSOS 4075.7728395
#define VELOCIDADE_RPM 12
#define ANGULO_GIRO 90

/* Define os parametros iniciais de ligacao do motor de passo */
CustomStepper stepper(DIRECAO_DIREITA_1, DIRECAO_DIREITA_2, DIRECAO_ESQUERDA_1, DIRECAO_ESQUERDA_2, (byte[]) {
  8, B1000, B1100, B0100,
  B0110, B0010, B0011, B0001, B1001
}, NUMERO_PASSOS, VELOCIDADE_RPM, CW);

/* Funcoes */

#define IR_PARA_FRENTE() do { stepper.setDirection(CW); stepper.setRPM(VELOCIDADE_RPM); } while(false)
#define IR_PARA_TRAS() do { stepper.setDirection(CCW); stepper.setRPM(VELOCIDADE_RPM); } while(false)
#define GIRAR_ESQUERDA() do { stepper.setDirection(CCW);  stepper.rotateDegrees(ANGULO_GIRO); } while(false)
#define GIRAR_DIREITA() do { stepper.setDirection(CW);  stepper.rotateDegrees(ANGULO_GIRO); } while(false)
#define FREIO() do { stepper.setDirection(STOP); } while(false)

void setup() {
  serial.begin(115200);

  pinMode(DIRECAO_DIREITA_1, OUTPUT);
  pinMode(DIRECAO_DIREITA_2, OUTPUT);
  pinMode(DIRECAO_ESQUERDA_1, OUTPUT);
  pinMode(DIRECAO_ESQUERDA_2, OUTPUT);

}

void loop() {
  stepper.run();
}

error: pathspec 'utils/testSketch/testeStep.ino' did not match any file(s) known to git


Initial commit of arduino code

Initial commit of arduino code

// Code for Scatdat door sensors with power saving shield installed.
// Arduino ESP8266 Wifi library
#include <ESP8266WiFi.h>

//////////////////////////
// Constant Definitions //
//////////////////////////
#define CLOSED 0
#define OPEN 1
#define VOLTAGE_DIVIDER_CONST 5.7

//////////////////////
// WiFi Definitions //
//////////////////////
const char WIFI_SSID[] = "exoplanet";  //planetoids
const char WIFI_PSK[] = "kEf8Qr28vNSv";  //62D4A6ED
const char STALL_ID[] = "Floor2Mens1";

/////////////////////////////
// Remote Site Definitions //
/////////////////////////////
const char http_site[] = "scatdat.earth.planet.com";
const int http_port = 5000;

/////////////////////
// Pin Definitions //
/////////////////////
const int LED_PIN = 5;
const int ANALOG_PIN = A0; // The only analog pin on the Thing
const int DOOR_SENSOR_PIN = 4; // Digital pin to be read
const int SLEEP_TIME_S = 3600; //sleep time between non door wakeups (in seconds), max is about 1 hr

//////////////////////
// Global Variables //
//////////////////////
WiFiClient client;
int doorState = OPEN;
int analogValue = 0;
int vbatt = 0;

//////////////////////////
// connectWiFi Function //
//////////////////////////
void connectWiFi() {

  byte led_status = 0;

  // Set WiFi mode to station (client)
  WiFi.mode(WIFI_STA);

  // Initiate connection with SSID and PSK
  WiFi.begin(WIFI_SSID, WIFI_PSK);

  // Blink LED while we wait for WiFi connection
  while ( WiFi.status() != WL_CONNECTED ) {
    digitalWrite(LED_PIN, led_status);
    led_status ^= 0x01;
    delay(100);
  }

  // Turn LED on when we are connected
  digitalWrite(LED_PIN, LOW);
}

////////////////////////
// postEvent Function //
////////////////////////
// Perform an HTTP POST to a remote page
bool postEvent(int doorOpen,int battmV) {
  char paramString[256];
  Serial.println("Attempting to connect to");
  sprintf(paramString,"%s:%i",http_site,http_port);
  Serial.print(paramString);

  // Attempt to make a connection to the remote server
  if ( !client.connect(http_site, http_port) ) {
    return false;
  }
  // Construct parameter string
  sprintf(paramString,"?stallId=%s&doorOpen=%i&battV=%i",STALL_ID,doorOpen,battmV);
  // Make an HTTP GET request
  client.print("GET /newdata");
  client.print(paramString);
  client.println(" HTTP/1.1");
  client.print("Host: ");
  client.println(http_site);
  client.println("Connection: close");
  client.println();

  return true;
}

///////////////////////////
// initHardware Function //
///////////////////////////
void initHardware(){
  Serial.begin(9600);
  // Set door sensor pin as input, no pull up needed because there is an external pull up
  pinMode(DOOR_SENSOR_PIN, INPUT);
  // Set led pin as output and turn it off
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  // Don't need to set ANALOG_PIN as input, that's all it can be.
}

//////////////////////////////
// calcBattVoltage Function //
//////////////////////////////
int calcBattmV(int analogValue){
  // Input is the ADC, its 10 bit so 0-1023 for 1V FSR
  // The power saver has a built in voltage divider
  // R1 = 470000  R2 = 100000
  // VOUT = R2/ (R1+R2) * VIN
  float v_adc = 0;
  float battmV = 0;
  v_adc = (float) analogValue / 1023;
  battmV = VOLTAGE_DIVIDER_CONST * v_adc * 1000;
  return (int) battmV;
}

////////////////////
// setup Function //
////////////////////
void setup() {

  // setup pins/serial comms
  initHardware();

  // connect to the newtwork
  connectWiFi();

  // turn on LED
  digitalWrite(LED_PIN, HIGH);

  // Read door sensor state
  doorState = digitalRead(DOOR_SENSOR_PIN);

  // get analog reading & calculate battery voltage
  analogValue = analogRead(ANALOG_PIN);
  vbatt = calcBattmV(analogValue);

  // Post the data
  if (!postEvent(doorState,vbatt)) {
    Serial.println("POST request failed");
  }

  // turn off LED
  digitalWrite(LED_PIN,LOW);

  // go into deep sleep mode
  ESP.deepSleep(SLEEP_TIME_S * 1000000, WAKE_RF_DEFAULT);
}

///////////////////
// loop Function //
///////////////////
void loop() {
  // intentially left empty
 }

error: pathspec 'scatdat_v2.ino' did not match any file(s) known to git


half step done! 	new file:   half_expriment/half_expriment.ino

const int A = 8;
const int B = 9;
const int C = 10;
const int D = 11;

int count = 12;

// speed at 20-500
const unsigned width = 20;

void setup() {
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
}

void loop() {

  while(count > 0)
  {
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  delay(width);

  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
  delay(width);

  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  delay(width);

  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  delay(width);

  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  delay(width);

  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
  delay(width);

  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  delay(width);

  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  delay(width);

  --count;
}
  delay(3000);
  count = 12;

}

error: pathspec 'half_expriment/half_expriment.ino' did not match any file(s) known to git