Added BME280 humidity and altitude information

Can start heater if high humidity
Altitude reported to heater per BMP180 in OEM controllers.
lowered min Hz limit to 500
This commit is contained in:
Ray Jones 2020-01-13 19:48:32 +11:00
parent 083fb63764
commit 7e1a4940ac
48 changed files with 1028 additions and 11 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

BIN
icons/humidity.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

View File

@ -0,0 +1,36 @@
#!/bin/bash
export ARDUINO_ESP32_PATH="$ARDUINO_USR_PATH/hardware/espressif/esp32"
if [ ! -d "$ARDUINO_ESP32_PATH" ]; then
echo "Installing ESP32 Arduino Core ..."
script_init_path="$PWD"
mkdir -p "$ARDUINO_USR_PATH/hardware/espressif"
cd "$ARDUINO_USR_PATH/hardware/espressif"
echo "Installing Python Serial ..."
pip install pyserial > /dev/null
if [ "$OS_IS_WINDOWS" == "1" ]; then
echo "Installing Python Requests ..."
pip install requests > /dev/null
fi
if [ "$GITHUB_REPOSITORY" == "espressif/arduino-esp32" ]; then
echo "Linking Core..."
ln -s $GITHUB_WORKSPACE esp32
else
echo "Cloning Core Repository..."
git clone https://github.com/espressif/arduino-esp32.git esp32 > /dev/null 2>&1
fi
echo "Updating Submodules ..."
cd esp32
git submodule update --init --recursive > /dev/null 2>&1
echo "Installing Platform Tools ..."
cd tools && python get.py
cd $script_init_path
echo "ESP32 Arduino has been installed in '$ARDUINO_ESP32_PATH'"
echo ""
fi

View File

@ -0,0 +1,220 @@
#!/bin/bash
#OSTYPE: 'linux-gnu', ARCH: 'x86_64' => linux64
#OSTYPE: 'msys', ARCH: 'x86_64' => win32
#OSTYPE: 'darwin18', ARCH: 'i386' => macos
OSBITS=`arch`
if [[ "$OSTYPE" == "linux"* ]]; then
export OS_IS_LINUX="1"
ARCHIVE_FORMAT="tar.xz"
if [[ "$OSBITS" == "i686" ]]; then
OS_NAME="linux32"
elif [[ "$OSBITS" == "x86_64" ]]; then
OS_NAME="linux64"
elif [[ "$OSBITS" == "armv7l" || "$OSBITS" == "aarch64" ]]; then
OS_NAME="linuxarm"
else
OS_NAME="$OSTYPE-$OSBITS"
echo "Unknown OS '$OS_NAME'"
exit 1
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
export OS_IS_MACOS="1"
ARCHIVE_FORMAT="zip"
OS_NAME="macosx"
elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
export OS_IS_WINDOWS="1"
ARCHIVE_FORMAT="zip"
OS_NAME="windows"
else
OS_NAME="$OSTYPE-$OSBITS"
echo "Unknown OS '$OS_NAME'"
exit 1
fi
export OS_NAME
ARDUINO_BUILD_DIR="$HOME/.arduino/build.tmp"
ARDUINO_CACHE_DIR="$HOME/.arduino/cache.tmp"
if [ "$OS_IS_MACOS" == "1" ]; then
export ARDUINO_IDE_PATH="/Applications/Arduino.app/Contents/Java"
export ARDUINO_USR_PATH="$HOME/Documents/Arduino"
elif [ "$OS_IS_WINDOWS" == "1" ]; then
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
export ARDUINO_USR_PATH="$HOME/Documents/Arduino"
else
export ARDUINO_IDE_PATH="$HOME/arduino_ide"
export ARDUINO_USR_PATH="$HOME/Arduino"
fi
if [ ! -d "$ARDUINO_IDE_PATH" ]; then
echo "Installing Arduino IDE on $OS_NAME ..."
echo "Downloading 'arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT' to 'arduino.$ARCHIVE_FORMAT' ..."
if [ "$OS_IS_LINUX" == "1" ]; then
wget -O "arduino.$ARCHIVE_FORMAT" "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
tar xf "arduino.$ARCHIVE_FORMAT" > /dev/null
mv arduino-nightly "$ARDUINO_IDE_PATH"
else
curl -o "arduino.$ARCHIVE_FORMAT" -L "https://www.arduino.cc/download.php?f=/arduino-nightly-$OS_NAME.$ARCHIVE_FORMAT" > /dev/null 2>&1
echo "Extracting 'arduino.$ARCHIVE_FORMAT' ..."
unzip "arduino.$ARCHIVE_FORMAT" > /dev/null
if [ "$OS_IS_MACOS" == "1" ]; then
mv "Arduino.app" "/Applications/Arduino.app"
else
mv arduino-nightly "$ARDUINO_IDE_PATH"
fi
fi
rm -rf "arduino.$ARCHIVE_FORMAT"
mkdir -p "$ARDUINO_USR_PATH/libraries"
mkdir -p "$ARDUINO_USR_PATH/hardware"
echo "Arduino IDE Installed in '$ARDUINO_IDE_PATH'"
echo ""
fi
function build_sketch(){ # build_sketch <fqbn> <path-to-ino> [extra-options]
if [ "$#" -lt 2 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_sketch <fqbn> <path-to-ino> [extra-options]"
return 1
fi
local fqbn="$1"
local sketch="$2"
local xtra_opts="$3"
local win_opts=""
if [ "$OS_IS_WINDOWS" == "1" ]; then
local ctags_version=`ls "$ARDUINO_IDE_PATH/tools-builder/ctags/"`
local preprocessor_version=`ls "$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/"`
win_opts="-prefs=runtime.tools.ctags.path=$ARDUINO_IDE_PATH/tools-builder/ctags/$ctags_version -prefs=runtime.tools.arduino-preprocessor.path=$ARDUINO_IDE_PATH/tools-builder/arduino-preprocessor/$preprocessor_version"
fi
echo ""
echo "Compiling '"$(basename "$sketch")"' ..."
mkdir -p "$ARDUINO_BUILD_DIR"
mkdir -p "$ARDUINO_CACHE_DIR"
$ARDUINO_IDE_PATH/arduino-builder -compile -logger=human -core-api-version=10810 \
-fqbn=$fqbn \
-warnings="all" \
-tools "$ARDUINO_IDE_PATH/tools-builder" \
-tools "$ARDUINO_IDE_PATH/tools" \
-built-in-libraries "$ARDUINO_IDE_PATH/libraries" \
-hardware "$ARDUINO_IDE_PATH/hardware" \
-hardware "$ARDUINO_USR_PATH/hardware" \
-libraries "$ARDUINO_USR_PATH/libraries" \
-build-cache "$ARDUINO_CACHE_DIR" \
-build-path "$ARDUINO_BUILD_DIR" \
$win_opts $xtra_opts "$sketch"
}
function count_sketches() # count_sketches <examples-path>
{
local examples="$1"
rm -rf sketches.txt
if [ ! -d "$examples" ]; then
touch sketches.txt
return 0
fi
local sketches=$(find $examples -name *.ino)
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
continue
fi;
if [[ -f "$sketchdir/.test.skip" ]]; then
continue
fi
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
done
return $sketchnum
}
function build_sketches() # build_sketches <fqbn> <examples-path> <chunk> <total-chunks> [extra-options]
{
local fqbn=$1
local examples=$2
local chunk_idex=$3
local chunks_num=$4
local xtra_opts=$5
if [ "$#" -lt 2 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_sketches <fqbn> <examples-path> [<chunk> <total-chunks>] [extra-options]"
return 1
fi
if [ "$#" -lt 4 ]; then
chunk_idex="0"
chunks_num="1"
xtra_opts=$3
fi
if [ "$chunks_num" -le 0 ]; then
echo "ERROR: Chunks count must be positive number"
return 1
fi
if [ "$chunk_idex" -ge "$chunks_num" ]; then
echo "ERROR: Chunk index must be less than chunks count"
return 1
fi
set +e
count_sketches "$examples"
local sketchcount=$?
set -e
local sketches=$(cat sketches.txt)
rm -rf sketches.txt
local chunk_size=$(( $sketchcount / $chunks_num ))
local all_chunks=$(( $chunks_num * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( $chunk_size + 1 ))
fi
local start_index=$(( $chunk_idex * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "Skipping job"
return 0
fi
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
local start_num=$(( $start_index + 1 ))
echo "Found $sketchcount Sketches";
echo "Chunk Count : $chunks_num"
echo "Chunk Size : $chunk_size"
echo "Start Sketch: $start_num"
echo "End Sketch : $end_index"
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|| [ -f "$sketchdir/.test.skip" ]; then
continue
fi
sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
build_sketch "$fqbn" "$sketch" "$xtra_opts"
local result=$?
if [ $result -ne 0 ]; then
return $result
fi
done
return 0
}

View File

@ -0,0 +1,133 @@
#!/bin/bash
echo "Installing Python Wheel ..."
pip install wheel > /dev/null 2>&1
echo "Installing PlatformIO ..."
pip install -U platformio > /dev/null 2>&1
echo "PlatformIO has been installed"
echo ""
function build_pio_sketch(){ # build_pio_sketch <board> <path-to-ino>
if [ "$#" -lt 2 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_pio_sketch <board> <path-to-ino>"
return 1
fi
local board="$1"
local sketch="$2"
local sketch_dir=$(dirname "$sketch")
echo ""
echo "Compiling '"$(basename "$sketch")"' ..."
python -m platformio ci -l '.' --board "$board" "$sketch_dir" --project-option="board_build.partitions = huge_app.csv"
}
function count_sketches() # count_sketches <examples-path>
{
local examples="$1"
rm -rf sketches.txt
if [ ! -d "$examples" ]; then
touch sketches.txt
return 0
fi
local sketches=$(find $examples -name *.ino)
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
continue
fi;
if [[ -f "$sketchdir/.test.skip" ]]; then
continue
fi
echo $sketch >> sketches.txt
sketchnum=$(($sketchnum + 1))
done
return $sketchnum
}
function build_pio_sketches() # build_pio_sketches <board> <examples-path> <chunk> <total-chunks>
{
if [ "$#" -lt 2 ]; then
echo "ERROR: Illegal number of parameters"
echo "USAGE: build_pio_sketches <board> <examples-path> [<chunk> <total-chunks>]"
return 1
fi
local board=$1
local examples=$2
local chunk_idex=$3
local chunks_num=$4
if [ "$#" -lt 4 ]; then
chunk_idex="0"
chunks_num="1"
fi
if [ "$chunks_num" -le 0 ]; then
echo "ERROR: Chunks count must be positive number"
return 1
fi
if [ "$chunk_idex" -ge "$chunks_num" ]; then
echo "ERROR: Chunk index must be less than chunks count"
return 1
fi
set +e
count_sketches "$examples"
local sketchcount=$?
set -e
local sketches=$(cat sketches.txt)
rm -rf sketches.txt
local chunk_size=$(( $sketchcount / $chunks_num ))
local all_chunks=$(( $chunks_num * $chunk_size ))
if [ "$all_chunks" -lt "$sketchcount" ]; then
chunk_size=$(( $chunk_size + 1 ))
fi
local start_index=$(( $chunk_idex * $chunk_size ))
if [ "$sketchcount" -le "$start_index" ]; then
echo "Skipping job"
return 0
fi
local end_index=$(( $(( $chunk_idex + 1 )) * $chunk_size ))
if [ "$end_index" -gt "$sketchcount" ]; then
end_index=$sketchcount
fi
local start_num=$(( $start_index + 1 ))
echo "Found $sketchcount Sketches";
echo "Chunk Count : $chunks_num"
echo "Chunk Size : $chunk_size"
echo "Start Sketch: $start_num"
echo "End Sketch : $end_index"
local sketchnum=0
for sketch in $sketches; do
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [ "${sketchdirname}.ino" != "$sketchname" ] \
|| [ -f "$sketchdir/.test.skip" ]; then
continue
fi
sketchnum=$(($sketchnum + 1))
if [ "$sketchnum" -le "$start_index" ] \
|| [ "$sketchnum" -gt "$end_index" ]; then
continue
fi
build_pio_sketch "$board" "$sketch"
local result=$?
if [ $result -ne 0 ]; then
return $result
fi
done
return 0
}

64
lib/AsyncTCP/.github/scripts/on-push.sh vendored Normal file
View File

@ -0,0 +1,64 @@
#!/bin/bash
set -e
if [ ! -z "$TRAVIS_BUILD_DIR" ]; then
export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR"
export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG"
elif [ -z "$GITHUB_WORKSPACE" ]; then
export GITHUB_WORKSPACE="$PWD"
export GITHUB_REPOSITORY="me-no-dev/AsyncTCP"
fi
CHUNK_INDEX=$1
CHUNKS_CNT=$2
BUILD_PIO=0
if [ "$#" -lt 2 ] || [ "$CHUNKS_CNT" -le 0 ]; then
CHUNK_INDEX=0
CHUNKS_CNT=1
elif [ "$CHUNK_INDEX" -gt "$CHUNKS_CNT" ]; then
CHUNK_INDEX=$CHUNKS_CNT
elif [ "$CHUNK_INDEX" -eq "$CHUNKS_CNT" ]; then
BUILD_PIO=1
fi
if [ "$BUILD_PIO" -eq 0 ]; then
# ArduinoIDE Test
source ./.github/scripts/install-arduino-ide.sh
source ./.github/scripts/install-arduino-core-esp32.sh
echo "Installing AsyncTCP ..."
cp -rf "$GITHUB_WORKSPACE" "$ARDUINO_USR_PATH/libraries/AsyncTCP"
FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
build_sketches "$FQBN" "$GITHUB_WORKSPACE/examples"
if [ ! "$OS_IS_WINDOWS" == "1" ]; then
echo "Installing ESPAsyncWebServer ..."
git clone https://github.com/me-no-dev/ESPAsyncWebServer "$ARDUINO_USR_PATH/libraries/ESPAsyncWebServer" > /dev/null 2>&1
echo "Installing ArduinoJson ..."
git clone https://github.com/bblanchon/ArduinoJson "$ARDUINO_USR_PATH/libraries/ArduinoJson" > /dev/null 2>&1
build_sketches "$FQBN" "$ARDUINO_USR_PATH/libraries/ESPAsyncWebServer/examples"
fi
else
# PlatformIO Test
source ./.github/scripts/install-platformio.sh
echo "Installing AsyncTCP ..."
python -m platformio lib --storage-dir "$GITHUB_WORKSPACE" install
BOARD="esp32dev"
build_pio_sketches "$BOARD" "$GITHUB_WORKSPACE/examples"
if [[ "$OSTYPE" != "cygwin" ]] && [[ "$OSTYPE" != "msys" ]] && [[ "$OSTYPE" != "win32" ]]; then
echo "Installing ESPAsyncWebServer ..."
python -m platformio lib -g install https://github.com/me-no-dev/ESPAsyncWebServer.git > /dev/null 2>&1
git clone https://github.com/me-no-dev/ESPAsyncWebServer "$HOME/ESPAsyncWebServer" > /dev/null 2>&1
echo "Installing ArduinoJson ..."
python -m platformio lib -g install https://github.com/bblanchon/ArduinoJson.git > /dev/null 2>&1
build_pio_sketches "$BOARD" "$HOME/ESPAsyncWebServer/examples"
fi
fi

31
lib/AsyncTCP/.github/stale.yml vendored Normal file
View File

@ -0,0 +1,31 @@
# Configuration for probot-stale - https://github.com/probot/stale
daysUntilStale: 60
daysUntilClose: 14
limitPerRun: 30
staleLabel: stale
exemptLabels:
- pinned
- security
- "to be implemented"
- "for reference"
- "move to PR"
- "enhancement"
only: issues
onlyLabels: []
exemptProjects: false
exemptMilestones: false
exemptAssignees: false
markComment: >
[STALE_SET] This issue has been automatically marked as stale because it has not had
recent activity. It will be closed in 14 days if no further activity occurs. Thank you
for your contributions.
unmarkComment: >
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.
closeComment: >
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.

32
lib/AsyncTCP/.github/workflows/push.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Async TCP CI
on:
push:
branches:
- master
- release/*
pull_request:
jobs:
build-arduino:
name: Arduino on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
steps:
- uses: actions/checkout@v1
- name: Build Tests
run: bash ./.github/scripts/on-push.sh 0 1
build-pio:
name: PlatformIO on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
steps:
- uses: actions/checkout@v1
- name: Build Tests
run: bash ./.github/scripts/on-push.sh 1 1

2
lib/AsyncTCP/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.DS_Store

View File

@ -0,0 +1,15 @@
set(COMPONENT_SRCDIRS
"src"
)
set(COMPONENT_ADD_INCLUDEDIRS
"src"
)
set(COMPONENT_REQUIRES
"arduino-esp32"
)
register_component()
target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti)

View File

@ -152,6 +152,7 @@ void checkDisplayUpdate();
void checkDebugCommands();
void manageCyclicMode();
void manageFrostMode();
void manageHumidity();
bool preemptCyclicMode();
void doStreaming();
void heaterOn();
@ -877,6 +878,7 @@ void loop()
manageCyclicMode();
manageFrostMode();
manageHumidity();
}
}
else {
@ -996,6 +998,21 @@ void manageFrostMode()
}
}
void manageHumidity()
{
uint8_t humidity = NVstore.getUserSettings().humidityStart;
if(humidity) {
float reading;
if(getTempSensor().getHumidity(reading)) {
uint8_t testval = (uint8_t)reading;
if(testval > humidity) {
DebugPort.printf("HUMIDITY MODE: Starting heater, > %d%%\r\n", humidity);
requestOn();
}
}
}
}
bool preemptCyclicMode()
{
const sCyclicThermostat& cyclic = NVstore.getUserSettings().cyclic;

99
src/OLED/BME280Screen.cpp Normal file
View File

@ -0,0 +1,99 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2019 Ray Jones <ray@mrjones.id.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "128x64OLED.h"
#include "BME280Screen.h"
#include "KeyPad.h"
#include "fonts/Icons.h"
#include "../Utility/TempSense.h"
CBME280Screen::CBME280Screen(C128x64_OLED& display, CScreenManager& mgr) : CPasswordScreen(display, mgr)
{
_initUI();
}
bool
CBME280Screen::show()
{
char msg[32];
_display.clearDisplay();
if(!CPasswordScreen::show()) { // for showing "saving settings"
_showTitle("BME280 status");
if(getTempSensor().getBME280().getCount()) {
float temperature;
float humidity;
float altitude;
_printMenuText(76, 16, "Temperature:", false, eRightJustify);
_printMenuText(76, 26, "Humidity:", false, eRightJustify);
_printMenuText(76, 36, "Altitude:", false, eRightJustify);
getTempSensor().getTemperatureBME280(temperature);
getTempSensor().getHumidity(humidity);
getTempSensor().getAltitude(altitude);
sprintf(msg, "%.01f`C", temperature);
_printMenuText(80, 16, msg, false);
sprintf(msg, "%.01f%%", humidity);
_printMenuText(80, 26, msg, false);
sprintf(msg, "%.0fm", altitude);
_printMenuText(80, 36, msg, false);
}
else {
_printMenuText(64, 16, "Sensor not found", false, eCentreJustify);
}
_printMenuText(_display.xCentre(), 52, " \021 Exit \020 ", true, eCentreJustify);
}
return true;
}
bool
CBME280Screen::keyHandler(uint8_t event)
{
if(event & keyPressed) {
// LEFT press
if(event & key_Left) {
_ScreenManager.prevMenu();
}
// RIGHT press
if(event & key_Right) {
_ScreenManager.nextMenu();
}
// CENTRE press
if(event & key_Centre) {
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
}
}
_ScreenManager.reqUpdate();
return true;
}

40
src/OLED/BME280Screen.h Normal file
View File

@ -0,0 +1,40 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2019 Ray Jones <ray@mrjones.id.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef __BME280SCREEN_H__
#define __BME280SCREEN_H__
#include <stdint.h>
#include "PasswordScreen.h"
#include "../Utility/NVStorage.h"
class C128x64_OLED;
class CScreenManager;
class CBME280Screen : public CPasswordScreen
{
public:
CBME280Screen(C128x64_OLED& display, CScreenManager& mgr);
bool show();
bool keyHandler(uint8_t event);
};
#endif

View File

@ -253,7 +253,7 @@ CFuelMixtureScreen::_adjustSetting(int dir)
}
BOUNDSLIMIT(adjPump[0], 0.5f, 10.f);
BOUNDSLIMIT(adjPump[1], 0.5f, 10.f);
BOUNDSLIMIT(adjFan[0], 1000, 5000);
BOUNDSLIMIT(adjFan[0], 500, 5000);
BOUNDSLIMIT(adjFan[1], 1000, 5000);
}

187
src/OLED/HumidityScreen.cpp Normal file
View File

@ -0,0 +1,187 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2019 Ray Jones <ray@mrjones.id.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "128x64OLED.h"
#include "HumidityScreen.h"
#include "KeyPad.h"
#include "fonts/Icons.h"
CHumidityScreen::CHumidityScreen(C128x64_OLED& display, CScreenManager& mgr) : CUIEditScreen(display, mgr)
{
}
void
CHumidityScreen::onSelect()
{
CUIEditScreen::onSelect();
_humidityThresh = NVstore.getUserSettings().humidityStart;
_scrollChar = 0;
}
bool
CHumidityScreen::show()
{
char msg[16];
_display.clearDisplay();
if(CUIEditScreen::show()) // for showing "saving settings"
return true;
_showTitle("Humidity Mode");
_drawBitmap(25, 20, humidityIconInfo);
_drawBitmap(50, 21, StartIconInfo);
if(_humidityThresh == 0) {
strcpy(msg, "Disabled");
}
else {
sprintf(msg, "> %d%%", _humidityThresh);
}
_printMenuText(62, 22, msg, _rowSel == 2);
return true;
}
bool
CHumidityScreen::animate()
{
if(_saveBusy()) {
return false;
}
const char* pMsg = NULL;
switch(_rowSel) {
case 0:
_printMenuText(_display.xCentre(), 53, " \021 \030Edit Exit \020 ", true, eCentreJustify);
break;
case 1:
pMsg = " Define humidity threshold to start heater automatically. ";
break;
}
if(pMsg != NULL) {
_display.drawFastHLine(0, 52, 128, WHITE);
_scrollMessage(56, pMsg, _scrollChar);
}
return true;
}
bool
CHumidityScreen::keyHandler(uint8_t event)
{
if(CUIEditScreen::keyHandler(event)) { // handles save confirm
return true;
}
if(event & keyRepeat) {
// LEFT hold
if(event & key_Left) {
if(_rowSel == 0)
_ScreenManager.prevMenu();
else
adjust(-1);
}
// RIGHT hold
if(event & key_Right) {
if(_rowSel == 0)
_ScreenManager.nextMenu();
else
adjust(+1);
}
}
if(event & keyPressed) {
// UP press
if(event & key_Up) {
_scrollChar = 0;
_rowSel++;
UPPERLIMIT(_rowSel, 1);
}
// DOWN press
if(event & key_Down) {
_scrollChar = 0;
_rowSel--;
LOWERLIMIT(_rowSel, 0);
}
// CENTRE press
if(event & key_Centre) {
if(_rowSel == 0) {
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
}
else {
_confirmSave();
_rowSel = 0;
}
}
// LEFT press
if(event & key_Left) {
if(_rowSel == 0)
_ScreenManager.prevMenu();
else
adjust(-1);
}
// RIGHT press
if(event & key_Right) {
if(_rowSel == 0)
_ScreenManager.nextMenu();
else
adjust(+1);
}
}
_ScreenManager.reqUpdate();
return true;
}
void
CHumidityScreen::adjust(int dir)
{
switch(_rowSel) {
case 1:
if(dir > 0) {
_humidityThresh++;
BOUNDSLIMIT(_humidityThresh, 50, 100);
}
else {
if(_humidityThresh) {
if(_humidityThresh == 50)
_humidityThresh = 0;
else
_humidityThresh--;
}
}
break;
}
}
void
CHumidityScreen::_saveNV()
{
sUserSettings us = NVstore.getUserSettings();
us.humidityStart = _humidityThresh;
NVstore.setUserSettings(us);
NVstore.save();
}

47
src/OLED/HumidityScreen.h Normal file
View File

@ -0,0 +1,47 @@
/*
* This file is part of the "bluetoothheater" distribution
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
*
* Copyright (C) 2019 Ray Jones <ray@mrjones.id.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef __HUMIDITYSCREEN_H__
#define __HUMIDITYSCREEN_H__
#include <stdint.h>
#include "UIEditScreen.h"
#include "../Utility/NVStorage.h"
class C128x64_OLED;
class CScreenManager;
class CHumidityScreen : public CUIEditScreen
{
int _scrollChar;
uint8_t _humidityThresh;
protected:
void _saveNV();
public:
CHumidityScreen(C128x64_OLED& display, CScreenManager& mgr);
bool show();
bool animate();
bool keyHandler(uint8_t event);
void onSelect();
void adjust(int dir);
};
#endif

View File

@ -46,8 +46,10 @@
#include "MenuTrunkScreen.h"
#include "MQTTScreen.h"
#include "DS18B20Screen.h"
#include "BME280Screen.h"
#include "TempSensorScreen.h"
#include "FrostScreen.h"
#include "HumidityScreen.h"
#include <Wire.h>
#include "../cfg/pins.h"
#include "../cfg/BTCConfig.h"
@ -459,19 +461,22 @@ CScreenManager::_loadScreens()
// create User Settings screens loop
menuloop.clear();
if(NVstore.getUserSettings().menuMode == 0) {
if(NVstore.getUserSettings().menuMode == 0) { // standard heater control menu set
menuloop.push_back(new CThermostatModeScreen(*_pDisplay, *this)); // thermostat settings screen
menuloop.push_back(new CFrostScreen(*_pDisplay, *this)); // frost mode screen
if(getTempSensor().getBME280().getCount()) {
menuloop.push_back(new CHumidityScreen(*_pDisplay, *this)); // humidity settings screen
}
menuloop.push_back(new CHomeMenuSelScreen(*_pDisplay, *this)); // Home menu settings screen
menuloop.push_back(new CTimeoutsScreen(*_pDisplay, *this)); // Other options screen
menuloop.push_back(new CMenuSelScreen(*_pDisplay, *this)); // Menu mode screen
if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support ?
menuloop.push_back(new CGPIOSetupScreen(*_pDisplay, *this)); // GPIO settings screen
}
else if(NVstore.getUserSettings().menuMode == 1) {
else if(NVstore.getUserSettings().menuMode == 1) { // "no fiddle" menu set
menuloop.push_back(new CMenuSelScreen(*_pDisplay, *this)); // Menu mode screen
}
else if(NVstore.getUserSettings().menuMode == 2) {
else if(NVstore.getUserSettings().menuMode == 2) { // no heater menu set
menuloop.push_back(new CNoHeaterHomeMenuSelScreen(*_pDisplay, *this)); // No Heater Home menu settings screen
menuloop.push_back(new CMenuSelScreen(*_pDisplay, *this)); // Menu mode screen
if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support ?
@ -489,10 +494,13 @@ CScreenManager::_loadScreens()
menuloop.push_back(new CWiFiScreen(*_pDisplay, *this));
menuloop.push_back(new CMQTTScreen(*_pDisplay, *this));
menuloop.push_back(new CBTScreen(*_pDisplay, *this));
if(getTempSensor().getBME280().getCount())
if(getTempSensor().getBME280().getCount()) {
menuloop.push_back(new CTempSensorScreen(*_pDisplay, *this));
else
menuloop.push_back(new CBME280Screen(*_pDisplay, *this));
}
else {
menuloop.push_back(new CDS18B20Screen(*_pDisplay, *this));
}
_Screens.push_back(menuloop);
}

View File

@ -1324,3 +1324,23 @@ const uint8_t PROGMEM frostIcon[] =
const BITMAP_INFO frostIconInfo(11, 13, frostIcon);
const uint8_t PROGMEM humidityIcon[] =
{
0x20, 0x10, // # #
0x50, 0x28, // # # # #
0x50, 0x28, // # # # #
0x88, 0x44, // # # # #
0x88, 0x44, // # # # #
0x88, 0x82, // # # # #
0x70, 0x82, // ### # #
0x04, 0x82, // # # #
0x0A, 0x44, // # # # #
0x0A, 0x38, // # # ###
0x11, 0x00, // # #
0x11, 0x00, // # #
0x11, 0x00, // # #
0x0E, 0x00, // ###
};
const BITMAP_INFO humidityIconInfo(15, 14, humidityIcon);

View File

@ -160,4 +160,4 @@ extern const BITMAP_INFO algIconInfo;
extern const BITMAP_INFO passwordIconInfo;
extern const BITMAP_INFO threshIconInfo;
extern const BITMAP_INFO frostIconInfo;
extern const BITMAP_INFO humidityIconInfo;

View File

@ -230,6 +230,15 @@ CProtocol::getVoltage_Supply() const
return getVoltage_SupplyRaw() + 0.6; // compensate for series protection diode
}
void
CProtocol::setAltitude(float altitude)
{
int16_t alt = (int16_t)altitude;
Controller.Altitude_MSB = (alt >> 8) & 0xff;
Controller.Altitude_LSB = (alt >> 0) & 0xff;
}
void
CProtocol::Init(int FrameMode)
{
@ -252,8 +261,8 @@ CProtocol::Init(int FrameMode)
Controller.Prime = 0; // 00: normal, 0x5A: fuel prime
Controller.Unknown1_MSB = 0x01; // always 0x01
Controller.Unknown1_LSB = 0x2c; // always 0x2c 16bit: "300 secs = max run without burn detected" ??
Controller.Unknown2_MSB = 0x0d; // always 0x0d
Controller.Unknown2_LSB = 0xac; // always 0xac 16bit: "3500" ?? Ignition fan max RPM????
Controller.Altitude_MSB = 0x0d; // basic controllers always 0x0d
Controller.Altitude_LSB = 0xac; // basic controllersalways 0xac 16bit: "3500"
setCRC();
}
else if(FrameMode == HeatMode){

View File

@ -51,8 +51,8 @@ public:
uint8_t Prime; // [17] 00: normal, 0x5A: fuel prime
uint8_t Unknown1_MSB; // [18] always 0x01
uint8_t Unknown1_LSB; // [19] always 0x2c "300 secs = max run without burn detected"?
uint8_t Unknown2_MSB; // [20] always 0x0d
uint8_t Unknown2_LSB; // [21] always 0xac "3500 ?"
uint8_t Altitude_MSB; // [20]
uint8_t Altitude_LSB; // [21]
uint8_t CRC_MSB; // [22]
uint8_t CRC_LSB; // [23]
} Controller;
@ -161,6 +161,8 @@ public:
// heat exchanger
int16_t getTemperature_HeatExchg() const; // temperature of heat exchanger
void setTemperature_HeatExchg(uint16_t degC); // temperature of heat exchanger
// altitude
void setAltitude(float altitude);
void DebugReport(const char* hdr, const char* ftr);

View File

@ -145,6 +145,14 @@ CTxManage::PrepareFrame(const CProtocol& basisFrame, bool isBTCmaster)
m_TxFrame.setPump_Min(NVstore.getHeaterTuning().getPmin());
m_TxFrame.setPump_Max(NVstore.getHeaterTuning().getPmax());
float altitude;
if(getTempSensor().getAltitude(altitude)) { // if a BME280 is fitted
m_TxFrame.setAltitude(altitude);
}
else {
m_TxFrame.setAltitude(3500); // default height - yes it is weird, but that's what the simple controllers send!
}
float tActual = getTemperatureSensor();
int8_t s8Temp = (int8_t)(tActual + 0.5);
m_TxFrame.setTemperature_Actual(s8Temp); // use current temp, for now

View File

@ -432,6 +432,7 @@ sUserSettings::load()
validatedLoad("menuMode", menuMode, 0, u8inBounds, 0, 2);
validatedLoad("Clock12hr", clock12hr, 0, u8inBounds, 0, 1);
validatedLoad("holdPassword", holdPassword, 0, u8inBounds, 0, 1);
validatedLoad("humidityStart", humidityStart, 0, u8inBounds, 0, 100);
preferences.end();
}
@ -471,6 +472,7 @@ sUserSettings::save()
preferences.putUChar("menuMode", menuMode);
preferences.putUChar("Clock12hr", clock12hr);
preferences.putUChar("holdPassword", holdPassword);
preferences.putUChar("humidityStart", humidityStart);
preferences.end();
}

View File

@ -298,6 +298,7 @@ struct sUserSettings : public CESP32_NVStorage {
uint8_t menuMode; // 0 normal, 1, basic, 2 no heater
uint8_t clock12hr;
uint8_t holdPassword;
uint8_t humidityStart;
bool valid() {
bool retval = true;
@ -348,6 +349,7 @@ struct sUserSettings : public CESP32_NVStorage {
menuMode = 0;
clock12hr = 0;
holdPassword = 0;
humidityStart = 0;
};
void load();
void save();
@ -378,6 +380,7 @@ struct sUserSettings : public CESP32_NVStorage {
menuMode = rhs.menuMode;
clock12hr = rhs.clock12hr;
holdPassword = rhs.holdPassword;
humidityStart = rhs.humidityStart;
return *this;
}
};

View File

@ -437,6 +437,20 @@ CBME280Sensor::getTemperature(float& tempReading, bool filtered)
return true;
}
bool
CBME280Sensor::getAltitude(float& reading)
{
reading = _bme.readAltitude(1013.25); //use standard atmosphere as reference
return true;
}
bool
CBME280Sensor::getHumidity(float& reading)
{
reading = _bme.readHumidity();
return true;
}
const char*
CBME280Sensor::getID()
{
@ -596,3 +610,27 @@ CTempSense::format(char* msg, float fTemp)
sprintf(msg, "%.1f`C", fTemp);
}
}
bool
CTempSense::getTemperatureBME280(float& reading)
{
return BME280.getTemperature(reading, false);
}
bool
CTempSense::getAltitude(float& reading)
{
if(BME280.getCount())
return BME280.getAltitude(reading);
else
return false;
}
bool
CTempSense::getHumidity(float& reading)
{
if(BME280.getCount())
return BME280.getHumidity(reading);
else
return false;
}

View File

@ -94,6 +94,8 @@ public:
CBME280Sensor();
bool begin(int ID);
bool getTemperature(float& tempReading, bool filtered) ;
bool getAltitude(float& reading);
bool getHumidity(float& reading);
const char* getID();
int getCount() const { return _count; };
};
@ -117,6 +119,8 @@ public:
bool getTemperatureBME280(float& tempReading) ; // index is sensor discovery order on one-wire bus
bool getTemperatureDS18B20Idx(int sensIdx, float& tempReading) ; // index is sensor discovery order on one-wire bus
int getNumSensors() const;
bool getAltitude(float& reading);
bool getHumidity(float& reading);
CBME280Sensor& getBME280() { return BME280; };
CDS18B20SensorSet& getDS18B20() { return DS18B20; };
static void format(char* msg, float fTemp);