Erik de Ruiter
Published © MIT

Gorgy Meteo Clock

My 'Gorgy' clock! Enhanced with an IR remote, a TFT display, a barometer, and a humidity and temperature sensor.

AdvancedWork in progress20,616
Gorgy Meteo Clock

Things used in this project

Story

Read more

Custom parts and enclosures

Arduino sketch LIBRARIES for the clock

IMPORTANT!
please read the README file in de ZIP...

Schematics

schematic

Code

Code version 2017-03

Arduino
The date display now displays the day of the week - day - month. For example Mo 13 - 05
It should compile with Arduino IDE 1.6 up to 1.6.9, maybe not the newer versions of the IDE!!

PLEASE note: the needed LIBRARIES are found as a ZIP file under "CUSTOM PARTS AND ENCLOSURES"
/*

  GorgyMeteoClock

  2017-07-13 changing date display to also display day-of-the-week
  2017-07-14 small edit: clear date display first and no decimal point

                                                                                            ####    ######     ###     ####
  ##   ##   #####   ######   ##   ##    ####            ##   ##  #######    ####     ##     ##  ##   ##        ##      ##  ##
  ##   ##  ##   ##    ##     ###  ##   ##  ##           ##   ##  ##        ##  ##    ##         ##   ##       ##       ##  ##
  ##   ##  ##         ##     ###  ##  ##                ### ###  ##       ##        ####       ##    #####    #####    ##  ##
  ##   ##   #####     ##     ## # ##  ##                ## # ##  #####    ##        ## #      ##         ##   ##  ##   ##  ##
  ##   ##       ##    ##     ## # ##  ##  ###           ## # ##  ##       ##  ###  ######    ##          ##   ##  ##   ##  ##
  ##   ##  ##   ##    ##     ##  ###   ##  ##           ##   ##  ##        ##  ##  ##   #   ##       ##  ##   ##  ##   ##  ##
  #####    #####   ######   ##   ##    #####           ##   ##  #######    ##### ###   ##  ######    ####     ####     ####

*/

//----------------------------------------------------------------------------------------------------------
// Libraries
//----------------------------------------------------------------------------------------------------------
//

#include <SPI.h>                // SPI interface library
// -> http://arduino.cc/en/Reference/SPI
#include <Time.h>               // Arduino (new) Time library
// -> http://www.pjrc.com/teensy/td_libs_Time.html
#include <Timezone.h>           // facilitate time zone conversions and automatic DST adjustments.
//https://github.com/JChristensen/Timezone
#include <Wire.h>               // Enable this line if using Arduino Uno, Mega, etc.
//
#include <LedControl.h>         // Maxim 7219 displays library
// -> http://playground.arduino.cc/Main/LEDMatrix
#include <OneWire.h>            // OneWire lets you access 1-wire devices made by Maxim/Dallas,
// such as DS18S20, DS18B20, DS1822.
// http://www.pjrc.com/teensy/td_libs_OneWire.html
// http://milesburton.com/Dallas_Temperature_Control_Library
#include <IRremote.h>           //
#include "ClickButton.h"        // A simple one-button Arduino library to get short and long clicks,
// multiple clicks (double click, triple click etc.).
// Click-and-hold is also possible.
// -> https://code.google.com/p/clickbutton/
#include <Adafruit_GFX_AS.h>    // Adafruit Core graphics library
#include <Adafruit_ST7735_AS.h> // Adafruit 1.8" TFT
#include "Adafruit_HTU21DF.h"   // Adafruit HTU21D-F Temperature & Humidity Sensor
#include <Streaming.h>
#include <Adafruit_Sensor.h>    // Adafruit Unified Sensor Driver
#include <Adafruit_BMP183.h>    // Adafruit BMP183 Barometric Pressure + Temp sensor
#include "eeprom_routines.h"    // EEprom routines for storing data
//#include "RotaryEncoder.h"    // smallest and best rotary lib I have seen...
// https://code.google.com/p/arduino-rotary-encoder-with-velocity/
//----------------------------------------------------------------------------------------------------------
// I2C addresses
//----------------------------------------------------------------------------------------------------------
#define CHRONODOT_ADDRESS    0x68       // Chronodot I2C address
#define BH1750_ADDRESS       0x23       // BH1750 Lux Sensor I2C address
#define TSL2561_ADDRESS      0x39       // Lux Sensor I2C address
#define HTU21DF_ADDRESS      0x40       // Humidity Sensor I2C address
#define EEPROM_ADDRESS       0x50       // EEprom address for storing barametric array data etc.

//----------------------------------------------------------------------------------------------------------
// Humidity Sensor init
//----------------------------------------------------------------------------------------------------------
Adafruit_HTU21DF htu21df = Adafruit_HTU21DF();

//----------------------------------------------------------------------------------------------------------
// Barometric pressure sensor init
//----------------------------------------------------------------------------------------------------------
#define BMP183_CLK  52  // SCK to SPI Clock
#define BMP183_SDO  50  // MISO
#define BMP183_SDI  51  // MOSI
#define BMP183_CS   42  // CS: Chip Select Pin
// initialize BMP183 sensor with hardware SPI
Adafruit_BMP183 bmp183 = Adafruit_BMP183(BMP183_CS);

// or initialize with software SPI and use any 4 pins
//                                    CLK SDO SDI CS);
//Adafruit_BMP183 bmp = Adafruit_BMP183( 3, 6, 2, 7);

//----------------------------------------------------------------------------------------------------------
// DS18B20 initialization
//----------------------------------------------------------------------------------------------------------
OneWire  ds(46); // define Onewire instance DS
// address: 0x28, 0xF0, 0xEC, 0xE2, 0x04, 0x00, 0x00, 0x47

//----------------------------------------------------------------------------------------------------------
// IRreceiver initialization
//----------------------------------------------------------------------------------------------------------
IRrecv irrecv(44);
decode_results irReceive;

//----------------------------------------------------------------------------------------------------------
// Adafruit 1.8" TFT display init
//----------------------------------------------------------------------------------------------------------
//Connect to hardware SPI on Mega2560:

#define sclk 52 // Uno:13  // Don't change
#define mosi 51 // Uno:11  // Don't change
#define cs   48 // Uno:9
#define dc   49 // Uno:8
#define rst  47 // Uno:7  // you can also connect this to the Arduino reset

Adafruit_ST7735_AS tft = Adafruit_ST7735_AS(cs, dc, rst);       // Invoke custom library

// or use any pins but a little slower
//                                    cs  dc mosi sclk, rst);
//Adafruit_ST7735 tft = Adafruit_ST7735(10, 9, 11, 13, 8);

// define colors for TFTdisplay
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define ORANGE  0xFD20
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define LGRAY   0xC618
#define DGRAY   0x8410

//----------------------------------------------------------------------------------------------------------
// Maxim 7219 Matrix Display initialization
//----------------------------------------------------------------------------------------------------------
//***** Please set the number of devices you have *****
// But the maximum default of 8 MAX72XX wil also work.
// LedConrol( DATAIN(SDI/MOSI), CLOCK, CS/LOAD , NUMBER OF MAXIM CHIPS,)
LedControl maxim = LedControl(40, 36, 38, 3, false); // Define pins for Maxim 72xx and how many 72xx we use
//LedControl maxim = LedControl(40, 39, 38, 3, false); // Define pins for Maxim 72xx and how many 72xx we use
//LedControl maxim = LedControl(11, 13, 6, 1, false); // Define pins for Maxim 72xx and how many 72xx we use

//----------------------------------------------------------------------------------------------------------
// Rotary encoder
//----------------------------------------------------------------------------------------------------------
//RotaryEncoder encoder(A0,A1,1,1,1);
//#define BUTTON_SELECT_PIN A2

//----------------------------------------------------------------------------------------------------------
// Miscellaneous
//----------------------------------------------------------------------------------------------------------
// Adafruit TFT screen things
#if defined(__SAM3X8E__)
#undef __FlashStringHelper::F(string_literal)
#define F(string_literal) string_literal
#endif

//----------------------------------------------------------------------------------------------------------
// Daylight Savings Time calculation parameters
//----------------------------------------------------------------------------------------------------------
//Europe, Amsterdam Time Zone (ZT = DST, WT = DST)
TimeChangeRule myZT = {"ZT", Last, Sun, Mar, 2, +120};    //Daylight time = UTC +2 hours
TimeChangeRule myWT = {"WT", Last, Sun, Oct, 3, +60};     //Standard time = UTC +1  hours
Timezone myTZ(myZT, myWT);

//----------------------------------------------------------------------------------------------------------
// RTC DS3231 stuff
//----------------------------------------------------------------------------------------------------------
// set SQW output DS3231 RTC chip
#define SQW_FREQ SQWAVE_1_HZ        // 0b00000000     1Hz
//#define SQW_FREQ SQWAVE_4096_HZ   // 0b00001000  1024Hz
//#define SQW_FREQ SQWAVE_1024_HZ   // 0b00010000  4096Hz
//#define SQW_FREQ SQWAVE_8192_HZ   // 0b00010000  4096Hz
//#define SQW_FREQ SQWAVE_NONE      // DISABLE


//----------------------------------------------------------------------------------------------------------
// EEPROM
//----------------------------------------------------------------------------------------------------------
// memory start address to for barometer array data
#define BAROGRAPH_START_ADDRESS 100


//----------------------------------------------------------------------------------------------------------
// Variable and array defenitions
//----------------------------------------------------------------------------------------------------------
// define Maxim 7219 display parameters
#define TIMEDISPLAY              1           // first Maxim 7219 in 'daisychain' must be '0', next '1' etc.
#define SECONDSDISPLAY           2           // first Maxim 7219 in 'daisychain' must be '0', next '1' etc.
#define DATEDISPLAY              0

//----------------------------------------------------------------------------------------------------------
// LED pins
//----------------------------------------------------------------------------------------------------------
#define ERRORLED 36

//----------------------------------------------------------------------------------------------------------
// PWM brightness ports
//----------------------------------------------------------------------------------------------------------
#define MARKERS_HOURS   10 // PWM
#define MARKERS_MINUTES 11 // PWM
#define TFT_LIGHT       12 // Lite - this is the PWM input for the backlight control. Connect to 3-5VDC to turn on the
// backlight. Connect to ground to turn it off. Or, you can PWM at any frequency.
//----------------------------------------------------------------------------------------------------------
// Buttons definition
//----------------------------------------------------------------------------------------------------------
// create 3 Clickbutton instances, one for each button
#define BUTTON_SELECT_PIN      A0
#define BUTTON_UP_PIN          A1
#define BUTTON_DOWN_PIN        A2

ClickButton buttonUp(BUTTON_UP_PIN, LOW, CLICKBTN_PULLUP);
ClickButton buttonDown(BUTTON_DOWN_PIN, LOW, CLICKBTN_PULLUP);
ClickButton buttonSelect(BUTTON_SELECT_PIN, LOW, CLICKBTN_PULLUP);


//// user input actions
//enum {NO_ACTION, BTN_CLICK, BTN_DOUBLE_CLICK, BTN_HOLD, ROTATE_L, ROTATE_R}; // used for rotary
enum {NO_ACTION, BTN_SELECT, BTN_SELECT_HOLD, BTN_UP, BTN_DOWN, LED_RING_MODE, MEMORY_RESET, EEPROM_WRITE_BARO, EEPROM_READ_BARO};
//----------------------------------------------------------------------------------------------------------
// Related to the State Machine
//----------------------------------------------------------------------------------------------------------
// The different states of the system
enum states
{
  STATE_MAIN,
  STATE_TEMP_DISPLAY,
  STATE_HUMIDITY_DISPLAY,
  STATE_TIME_DETAIL,
  STATE_BAROGRAPH,
  STATE_BAROGRAPH_TREND,
  STATE_MENU_ALARM_TIME,
  STATE_MENU_SET_ALARM_HOUR,
  STATE_MENU_SET_ALARM_MINUTES,
  STATE_MENU_SECONDS_RING,
  STATE_MENU_SET_SECONDS_RING_MODE,
  STATE_MENU_LCD_MODE,
  STATE_MENU_SET_LCD_MODE,
  STATE_MENU_TIME,
  STATE_MENU_SET_TIME_HOUR,
  STATE_MENU_SET_TIME_MINUTES,
  STATE_MENU_DATE,
  STATE_MENU_SET_DAY,
  STATE_MENU_SET_MONTH,
  STATE_MENU_SET_YEAR,
  STATE_MENU_BAROGRAPH,
  STATE_MENU_SET_SEA_LEVEL_PRESSURE,
  STATE_MENU_SET_PRESSURE_CORRECTION,
};
states currState;       // Holds the current state of the system

/***************************************************************************************************************************************************

  ##   ##    ##     ######   ######     ##     ######   ##       #######   #####
  ##   ##    ##     ##   ##    ##       ##     ##   ##  ##       ##       ##   ##
  ##   ##   ####    ##   ##    ##      ####    ##   ##  ##       ##       ##
  ## ##    ## #    ######     ##      ## #    ######   ##       #####     #####
  ## ##   ######   ## ##      ##     ######   ##   ##  ##       ##            ##
   ###    ##   #   ##  ##     ##     ##   #   ##   ##  ##       ##       ##   ##
   ###   ###   ##  ##   ##  ######  ###   ##  ######   ######   #######   #####

****************************************************************************************************************************************************/
#define plotLimitH                    130 // graph plotlimit Horizontal 
#define plotRangeH                    130 // graph plot size Horizontal
#define plotLimitV                    115 // graph plotlimit Vertical
#define plotRangeV                    100 // graph plot size Vertical
// Horizontal Grid lines
#define grid24HstartpositionXaxis       0
#define grid24HstartpositionYaxis      15
#define grid24HlineSpacing             20
#define grid24HlinePixelSpacing         2
#define grid24HlinePixelSpacing1H       5
#define grid24HlinePixelSpacing2H      10
#define grid24HlinePixelSpacing4H      20
#define grid24XaxisTicksStart           5
// Vertical Grid lines
#define grid24VstartpositionXaxis      10
#define grid24VstartpositionYaxis      15
#define grid24VlineSpacing             20
#define grid24VlinePixelSpacing         2
#define grid24VlinePixelSpacing10Hpa   20
#define grid24VlinePixelSpacing5Hpa    10

#define GRIDCOLOR          LGRAY
#define PLOTCOLOR          BLUE
#define XAXISCOLOR         WHITE
#define YAXISCOLOR         WHITE
#define XTEXTCOLOR         WHITE
#define YTEXTCOLOR         WHITE
#define PRESSUREVALUECOLOR GREEN
#define TEMPVALUECOLOR     MAGENTA
#define HYGROVALUECOLOR    ORANGE

char* strDOW[8] = {"null", "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"};
int strDOWlength[8] = {0, 6, 7, 7, 8, 9, 7, 8};
char* strMonth[13] = {"null", "Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"};
//char* strMonth[13] = {"null","Januari","Februari","Maart","April","Mei","Juni","Juli","Augustus","September","Oktober","November","December"};


byte readWeatherdataInterval                 = 12;

bool secondsRingUpdated                      = false;
bool tftMainUpdated                          = false;
bool tftTimeUpdated                          = false;
bool tftBarographUpdated                     = false;
bool tftBaroTrendUpdated                     = false;



int baroTrendValue = 0;
int baroTrend = 0;
enum {NA, ZEER_SNEL_DALEND, SNEL_DALEND, DALEND, LANGZAAM_DALEND, STABIEL, LANGZAAM_STIJGEND, STIJGEND, SNEL_STIJGEND, ZEER_SNEL_STIJGEND};
bool pressureDataUpdated                     = false;
bool pressureDataStored                      = false;
bool pressureDataToEEprom                    = false;
bool pressureDataFromEEprom                  = false;
long pressureSample                          = 0;
long pressure                                = 0;
long pressureMin                             = 0;
long pressureMax                             = 0;
int minPressureHour = 0;
int minPressureMinute = 0;
int maxPressureHour = 0;
int maxPressureMinute = 0;


int testpressure                             = 980;
int step                                     = 5;
int previousPressureMin                      = 0;
int previousPressureMax                      = 0;
int meanSeaLevelPressure                     = 10155;
int pressureCorrection                      = 2;
bool resetBarograph                          = false;

int countdown = 10800;

int x                                        = 0;
int plotvalueP                               = 0;
int plotvalueP1                              = 0;
int plotvalueT                               = 0;
bool highScale                               = false;
bool currentScale                            = false;
int barometerData[132];                                     // array to hold barometric data
unsigned int readings = 0;
int pressureHourAvarage[130];
int pressureHourlyTrend = 0;

unsigned long timer1                         = millis();
unsigned long lastRotation                   = millis();
unsigned long lastUpdate1                    = millis();
bool startup                                 = true;
int q;


// Humidity related variables
int humidity                                 = 0;
int climateComfort                           = 0;
int minHumidity = 0;
int maxHumidity = 0;
int minHumidityHour = 0;
int minHumidityMinute = 0;
int maxHumidityHour = 0;
int maxHumidityMinute = 0;
bool humidityMemoryReset = false;

#define ccRED 0
#define ccYELLOW 1
#define ccGREEN 2


// temperature variables
bool temperatureMemoryReset                  = true;
int tempCelcius         = 0;
int minTemp = 0;
int maxTemp = 0;
int minTempHour = 0;
int minTempMinute = 0;
int maxTempHour = 0;
int maxTempMinute = 0;
//@1
byte tCount;
byte present = 0;
byte data[12];
byte addr[8] = {0x28, 0xF0, 0xEC, 0xE2, 0x04, 0x00, 0x00, 0x47};


// Time related variables
bool setSecondsToZero = false;
int previousDay                                  = 0;
int lastMinute                               = 0;
time_t t;
byte previousSecond = 0;
byte previousMinute = 0;
byte previousHour = 0;
int TMPsecond;                                           // holds time & date while setting the time
int TMPminute;
int TMPhour;
int TMPweekday;
int TMPday;
int TMPmonth;
int TMPyear;
int daylightSavingTime = 0;
bool daylightSavingTimeHasChanged = false;
boolean RTCERROR                             = true;        // flag to check RTC communication, used in SHOW_TIME_DATE_WEATHER_DATE_WEATHER and SHOW_DATE
short dayNumber;   //Returns the number of day in the year
short weekNumber;  //Returns the number of the week in the year

byte alarmHour                               = 8;
byte alarmMinute                             = 30;


bool sw1                                     = true;
bool stateChange                             = false;
int userAction                               = 0;
int previousMenu                             = 0;
volatile unsigned long timeOfLastButtonPress = 0;
bool secondsRingFull                         = true;
bool lcdScrollModeAuto                       = false;
bool needToSaveTime                          = false;
bool needToUpdateBarograph                   = false;
bool needToUpdateTFT                         = false;
bool isWaitingforTimeout                     = false;

//Brightness
byte brightnessTimeDisplay                   = 1;   // value from 0-15
byte brightnessSecondsRing                   = 0;   // value from 0-15
byte brightnessDateDisplay                   = 3;   // value from 0-15
byte brightnessMinuteMarkers                 = 505; // USE PWM value from 0 - 512, higher is dimmer
byte brightnessHourMarkers                   = 512; // USE PWM value from 0 - 512
byte brightnessLcdBacklight                  = 420; // USE PWM value from 0 - 512


bool irRemote = false;

byte ledRingMode = 0;
bool ledRingModeIsChanged = false;

int sec = 0;



// Define Interrupt function

volatile boolean updateTime = false;

// DS3231 1Hz pulse ISR
void pulseISR()
{
  updateTime = true;
}










/***************************************************************************************************************************************************

                                                 ##      ##
  #####   #######  ######   ##   ##  ######     ##        ##
  ##   ##  ##         ##     ##   ##  ##   ##    ##        ##
  ##       ##         ##     ##   ##  ##   ##   ##          ##
  #####   #####      ##     ##   ##  ######    ##          ##
      ##  ##         ##     ##   ##  ##        ##          ##
  ##   ##  ##         ##     ##   ##  ##         ##        ##
  #####   #######    ##      #####   ##         ##        ##
                                                 ##      ##

****************************************************************************************************************************************************/


void setup()
{
  //DEBUG
  pinMode(A8,  OUTPUT);
  pinMode(A9,  OUTPUT);
  pinMode(A10, OUTPUT);
  pinMode(A11, OUTPUT);
  //END DEBUG ;)


  pinMode(ERRORLED, OUTPUT);
  pinMode(TFT_LIGHT, OUTPUT);
  pinMode(MARKERS_HOURS, OUTPUT);
  pinMode(MARKERS_MINUTES, OUTPUT);
  pinMode(53, OUTPUT);                    // Set to OUTPUT NEEDED FOR SPI HARDWARE MASTER MODE

  Wire.begin();                           // start I2C
  irrecv.enableIRIn();                    // Start the IR remote receiver

  Serial.begin(115200);                   // start Serial for debug purposes

  //RTC.squareWave(SQW_FREQ);               // Set RTC DS3231 SQW frequency (1 Hz in this case)
  attachInterrupt(0, pulseISR, RISING);   // DS3231 sends an 1Hz pulse - we use this to update the display

  readRTC();
  setTime(TMPhour, TMPminute, TMPsecond, TMPday, TMPmonth, TMPyear);

  //setTime(2, 59, 45, 25, 10, 15); // test for change to winter time
  //setTime(1, 59, 45, 29, 3, 15); // test for change to summer time
  //timeDateToTemporaryMem();
  //writeRTC();

  // store current DST value in variable to check if DST is changed
  daylightSavingTime = myTZ.locIsDST(now());


  //setTime(RTC.get());
  //setSyncProvider(RTC.get);             // set RTC as the Syncprovider
  //setSyncInterval(5);                   // time in sec of resync with RTC

  // clear barometer pressure data array
  for (int i = 0; i <= 130; i++)
  {
    barometerData[i] = 0;
  }

  initTFT();                              // Initialize the TFT screen
  clearTFT();
  init7SegDisplay();                      // initialize 7 segment display
  initHumiditySensor();                   // start Humidity Sensor
  initBaroSensor();                       // initialize Pressure sensor
  brightnessAdj();

  requestTemperature();
  readHumidity();

  // initialize array
  for (int i = 0; i < 133; i++)
  {
    barometerData[i] = 0;
  }

  currState = STATE_MAIN;                 // Initial state of the FSM

}



/***************************************************************************************************************************************************

                                        ##      ##
  ##         ###      ###    ######     ##        ##
  ##        ## ##    ## ##   ##   ##    ##        ##
  ##       ##   ##  ##   ##  ##   ##   ##          ##
  ##       ##   ##  ##   ##  ######    ##          ##
  ##       ##   ##  ##   ##  ##        ##          ##
  ##        ## ##    ## ##   ##         ##        ##
  ######     ###      ###    ##         ##        ##
                                        ##      ##

****************************************************************************************************************************************************/


void loop()
{


  if (updateTime == true)
  {
    updateTime = false;
    executeState();
  }

  userAction = checkUserAction();
  if (userAction != NO_ACTION) // user has pressed a button
  {
    processAction(userAction);
  }
  else if (isWaitingforTimeout == true && millis() - timeOfLastButtonPress > 5000)
  {
    isWaitingforTimeout = false;
    clearTFT();
    clearTimeDisplay();
    clearDateDisplay();
    clearSecondsDisplay();
    startup = true;
    currState = STATE_MAIN;
  }

}















/***************************************************************************************************************************************************

   ####   ##   ##  ##   ##           ##   ##   #####   #######  ######              ##       ####   ######   ######     ###    ##   ##
  ##  ##  ##   ##  ##  ##            ##   ##  ##   ##  ##       ##   ##             ##      ##  ##    ##       ##      ## ##   ###  ##
  ##       ##   ##  ## ##             ##   ##  ##       ##       ##   ##            ####    ##         ##       ##     ##   ##  ###  ##
  ##       #######  ####              ##   ##   #####   #####    ######             ## #    ##         ##       ##     ##   ##  ## # ##
  ##       ##   ##  ## ##             ##   ##       ##  ##       ## ##             ######   ##         ##       ##     ##   ##  ## # ##
  ##  ##  ##   ##  ##  ##            ##   ##  ##   ##  ##       ##  ##            ##   #    ##  ##    ##       ##      ## ##   ##  ###
   ####   ##   ##  ##   ##            #####    #####   #######  ##   ##          ###   ##    ####     ##     ######     ###    ##   ##

****************************************************************************************************************************************************/
// check for user input
int checkUserAction()
{
  //////////////////////////////////
  // check for IR remote commands //
  //////////////////////////////////
  if (irrecv.decode(&irReceive))
  {
    switch (irReceive.value)
    {
      case 0x1C3B939F: // "Menu" key
        userAction = BTN_SELECT_HOLD;
        irRemote = true;// needed to check for IR input!
        break;

      case 0x75E8EBA3: // "Select" key
        userAction = BTN_SELECT;
        irRemote = true;
        break;

      case 0x150ADC43: // "Up" key
        userAction = BTN_UP;
        irRemote = true;
        break;

      case 0xA8A8B363: // "Play"

        irRemote = true;
        break;

      case 0x6551963F: // "Down"
        userAction = BTN_DOWN;
        irRemote = true;
        break;

      case 0x2560B67:  // "+" key
        userAction = EEPROM_WRITE_BARO;
        irRemote = true;
        break;

      case 0x5655FCFF: // "-" key
        userAction = EEPROM_READ_BARO;
        irRemote = true;
        break;

      case 0x3C1B0E83: // "|<<" key

        break;

      case 0xB55AE2FF: // ">>|" key
        readArray(); // Debug. read array and display on Serial Monitor
        readRTC(); // DEBUG. read RTC time and update system time
        setTime(TMPhour, TMPminute, TMPsecond, TMPday, TMPmonth, TMPyear);
        break;

      case 0xD293DA9F: // "Spatial" key
        userAction = MEMORY_RESET;
        irRemote = true;
        break;

      case 0xF761B2A3: // "Power" key

        break;

      case 0x12284AC3: // "Shuffle" key

        break;

      case 0x509BADB:  // "Repeat" key
        userAction = LED_RING_MODE;
        irRemote = true;
        ledRingModeIsChanged = true;
        break;
    }// switch

    //Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }

  // if IR remote is used, activate time-out function, used in the settings menu
  if (irRemote == true)
  {
    irRemote = false;
    timeOfLastButtonPress = millis();
    return userAction;
  }

  ////////////////////////////
  // check for button input //
  ////////////////////////////

  // no IR signals received, next check for button input

  // check state of each button
  buttonUp.Update();
  buttonDown.Update();                    // 1 = short click, -1 = long click (>1 second)
  buttonSelect.Update();                  // 0 = no input, Duh!

  if (buttonSelect.clicks != 0)           // check for user action of SELECT BUTTON
  {
    int clicks = buttonSelect.clicks;
    if (clicks > 1) clicks = 1;         // no double clicks...

    switch (clicks)
    {
      case 1:                         // Select button is pressed 1x
        userAction = BTN_SELECT;
        break;

      case -1:                        // Select button is pressed 1x for > 1 second
        userAction = BTN_SELECT_HOLD;
        break;
    }
  }
  else if (buttonUp.clicks == 1)               // check for user action of UP BUTTON
  {
    userAction = BTN_UP;
  }
  else if (buttonDown.clicks == 1)             // check for user action of DOWN BUTTON
  {
    userAction = BTN_DOWN;
  }
  // no IR commands or button press
  else
  {
    userAction = NO_ACTION;
  }

  if (userAction != NO_ACTION)
  {
    timeOfLastButtonPress = millis();
  }

  return userAction;
}

/***************************************************************************************************************************************************

  ######   ######     ###      ####   #######   #####    #####              ##       ####   ######   ######     ###    ##   ##
  ##   ##  ##   ##   ## ##    ##  ##  ##       ##   ##  ##   ##             ##      ##  ##    ##       ##      ## ##   ###  ##
  ##   ##  ##   ##  ##   ##  ##       ##       ##       ##                 ####    ##         ##       ##     ##   ##  ###  ##
  ######   ######   ##   ##  ##       #####     #####    #####             ## #    ##         ##       ##     ##   ##  ## # ##
  ##       ## ##    ##   ##  ##       ##            ##       ##           ######   ##         ##       ##     ##   ##  ## # ##
  ##       ##  ##    ## ##    ##  ##  ##       ##   ##  ##   ##           ##   #    ##  ##    ##       ##      ## ##   ##  ###
  ##       ##   ##    ###      ####   #######   #####    #####           ###   ##    ####     ##     ######     ###    ##   ##

****************************************************************************************************************************************************/
// change state of the "state machine" based on the user input;
// also perform one-time actions required by the change of state (e.g. clear display);
void processAction(int userAction)
{
  // Uses the current state to decide what to process
  switch (currState)
  {
    case STATE_MAIN:                      //---------------------{ 0 }--{ STATE MAIN }--------------------

      if (userAction == BTN_SELECT_HOLD)
      {
        currState = STATE_MENU_ALARM_TIME;
        stateChange = true;
        isWaitingforTimeout = true;
        clearTFT();
        clearTimeDisplay();
        clearDateDisplay();
        clearSecondsDisplay();
        drawSettingsMenu();
      }

      if (userAction == BTN_DOWN)
      {
        clearTFT();
        currState = STATE_TEMP_DISPLAY;
        stateChange = true;
      }

      if (userAction == BTN_UP)
      {
        clearTFT();
        currState = STATE_BAROGRAPH_TREND;
        stateChange = true;
      }

      if (userAction == LED_RING_MODE)
      {
        ledRingMode++;
        if (ledRingMode > 3)
        {
          ledRingMode = 0;
        }
      }

      break;
    case STATE_TEMP_DISPLAY:              //---------------------{ 1 }--{ STATE TEMP DISPLAY }--------------------

      if (userAction == BTN_SELECT_HOLD)
      {
        currState = STATE_MENU_ALARM_TIME;
        stateChange = true;
        isWaitingforTimeout = true;
        clearTFT();
        clearTimeDisplay();
        clearDateDisplay();
        clearSecondsDisplay();
        drawSettingsMenu();
      }

      if (userAction == BTN_DOWN)
      {
        clearTFT();
        currState = STATE_HUMIDITY_DISPLAY;
        stateChange = true;
      }

      if (userAction == BTN_UP)
      {
        clearTFT();
        currState = STATE_MAIN;
        stateChange = true;
      }

      if (userAction == LED_RING_MODE)
      {
        ledRingMode++;
        if (ledRingMode > 3)
        {
          ledRingMode = 0;
        }
      }

      if (userAction == MEMORY_RESET)
      {
        temperatureMemoryReset = true;
        minTemp = maxTemp = tempCelcius;
        minTempHour =  maxTempHour = hour();
        minTempMinute = maxTempMinute = minute();
      }

      break;
    case STATE_HUMIDITY_DISPLAY:               //---------------------{ 2 }--{ STATE HUMIDITY DISPLAY }--------------------

      if (userAction == BTN_SELECT_HOLD)
      {
        currState = STATE_MENU_ALARM_TIME;
        stateChange = true;
        isWaitingforTimeout = true;
        clearTFT();
        clearTimeDisplay();
        clearDateDisplay();
        clearSecondsDisplay();
        drawSettingsMenu();
      }

      if (userAction == BTN_DOWN)
      {
        clearTFT();
        currState = STATE_TIME_DETAIL;
        stateChange = true;
      }

      if (userAction == BTN_UP)
      {
        clearTFT();
        currState = STATE_TEMP_DISPLAY;
        stateChange = true;
      }

      if (userAction == LED_RING_MODE)
      {
        ledRingMode++;
        if (ledRingMode > 3)
        {
          ledRingMode = 0;
        }
      }

      if (userAction == MEMORY_RESET)
      {
        humidityMemoryReset = true;
        minHumidity = maxHumidity = humidity;
        minHumidityHour =  maxHumidityHour = hour();
        minHumidityMinute = maxHumidityMinute = minute();
      }

      break;
    case STATE_TIME_DETAIL:               //---------------------{ 3 }--{ STATE TIME DETAIL }--------------------

      if (userAction == BTN_SELECT_HOLD)
      {
        currState = STATE_MENU_ALARM_TIME;
        stateChange = true;
        isWaitingforTimeout = true;
        clearTFT();
        clearTimeDisplay();
        clearDateDisplay();
        clearSecondsDisplay();
        drawSettingsMenu();
      }

      if (userAction == BTN_DOWN)
      {
        clearTFT();
        currState = STATE_BAROGRAPH;
        stateChange = true;
      }

      if (userAction == BTN_UP)
      {
        clearTFT();
        currState = STATE_HUMIDITY_DISPLAY;
        stateChange = true;
      }

      if (userAction == MEMORY_RESET)
      {
        setSecondsToZero = true;
      }

      if (userAction == LED_RING_MODE)
      {
        ledRingMode++;
        if (ledRingMode > 3)
        {
          ledRingMode = 0;
        }
      }

      break;
    case STATE_BAROGRAPH:                 //---------------------{ 4 }--{ STATE BAROGRAPH }--------------------

      if (userAction == BTN_SELECT_HOLD)
      {
        currState = STATE_MENU_ALARM_TIME;
        stateChange = true;
        isWaitingforTimeout = true;
        clearTFT();
        clearTimeDisplay();
        clearDateDisplay();
        clearSecondsDisplay();
        drawSettingsMenu();
      }

      if (userAction == BTN_DOWN)
      {
        clearTFT();
        currState = STATE_BAROGRAPH_TREND;
        stateChange = true;
      }

      if (userAction == BTN_UP)
      {
        clearTFT();
        currState = STATE_TIME_DETAIL;
        stateChange = true;
      }

      if (userAction == EEPROM_WRITE_BARO)
      {
        // + button of remote pressed: store barometer pressur data array in EEPROM
        pressureDataToEEprom = true;
      }

      if (userAction == EEPROM_READ_BARO)
      {
        // + button of remote pressed: store barometer pressur data array in EEPROM
        pressureDataFromEEprom = true;
      }

      if (userAction == LED_RING_MODE)
      {
        ledRingMode++;
        if (ledRingMode > 3)
        {
          ledRingMode = 0;
        }
      }

      break;
    case STATE_BAROGRAPH_TREND:           //---------------------{ 5 }--{ STATE BAROGRAPH TREND }--------------------

      if (userAction == BTN_SELECT_HOLD)
      {
        currState = STATE_MENU_ALARM_TIME;
        stateChange = true;
        isWaitingforTimeout = true;
        clearTFT();
        clearTimeDisplay();
        clearDateDisplay();
        clearSecondsDisplay();
        drawSettingsMenu();
      }

      if (userAction == BTN_DOWN)
      {
        clearTFT();
        currState = STATE_MAIN;
        stateChange = true;
      }

      if (userAction == BTN_UP)
      {
...

This file has been truncated, please download it to see its full contents.

Credits

Erik de Ruiter

Erik de Ruiter

6 projects • 88 followers

Comments