mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
Merge and change uart timer modes to pause between bytes (5..50)
This commit is contained in:
72
.travis.yml
Normal file
72
.travis.yml
Normal file
@@ -0,0 +1,72 @@
|
||||
os: linux
|
||||
dist: bionic
|
||||
language: python
|
||||
python:
|
||||
- "3.8"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- ${HOME}/.pio
|
||||
|
||||
env:
|
||||
global:
|
||||
- BUILDER_TOTAL_THREADS=1
|
||||
- OWNER=${TRAVIS_REPO_SLUG%/*}
|
||||
- DEV=${OWNER/proddy/v2}
|
||||
- BRANCH=${TRAVIS_BRANCH/v2/}
|
||||
- TAG=${DEV}${BRANCH:+_}${BRANCH}
|
||||
|
||||
install:
|
||||
- env | grep TRAVIS
|
||||
- set -e
|
||||
- pip install -U platformio
|
||||
- pio platform update -p
|
||||
- set +e
|
||||
|
||||
branches:
|
||||
except:
|
||||
- /^travis-.*-build$/
|
||||
|
||||
script:
|
||||
- ./scripts/build.sh
|
||||
|
||||
stages:
|
||||
- name: Release
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: Release
|
||||
|
||||
before_deploy:
|
||||
- export FIRMWARE_VERSION=$(grep -E '^#define EMSESP_APP_VERSION' ./src/version.h | awk '{print $3}' | sed 's/"//g')
|
||||
- git tag -f travis-${TAG}-build
|
||||
- git remote add gh
|
||||
https://${OWNER}:${GITHUB_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git
|
||||
- git push gh :travis-${TAG}-build || true
|
||||
- git push -f gh travis-${TAG}-build
|
||||
- git remote remove gh
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
edge:
|
||||
branch: master
|
||||
token: ${GITHUB_TOKEN}
|
||||
file_glob: true
|
||||
file: "*.bin"
|
||||
name: latest v2 development builds
|
||||
release_notes:
|
||||
Version $FIRMWARE_VERSION.
|
||||
Automatic firmware builds of the current EMS-ESP branch built on $(date +'%F %T %Z') from commit $TRAVIS_COMMIT.
|
||||
Warning, this is a development build and not fully tested. Use at your own risk.
|
||||
cleanup: false
|
||||
prerelease: true
|
||||
overwrite: true
|
||||
target_commitish: $TRAVIS_COMMIT
|
||||
on:
|
||||
tags: false
|
||||
branch: v2
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
16
README.md
16
README.md
@@ -35,14 +35,14 @@ Note: Version 2.0 is not backward compatible with v1.0. The File system structur
|
||||
|
||||
### Uploading the firmware
|
||||
|
||||
- If you don't have Python 3.8, install it (https://www.python.org/downloads/)
|
||||
#### Using direct to USB:
|
||||
- install `esptool` using the command `pip install esptool`
|
||||
- connect an ESP8266 to the USB. Figure out which COM port it's on (e.g. windows device manager)
|
||||
- `esptool.py -p COM6 -b 921600 write_flash 0x00000 <firmware.bin>`
|
||||
#### Using OTA (Over The Air):
|
||||
- download `espota` from https://github.com/esp8266/Arduino/blob/master/tools/espota.py
|
||||
- `espota.py --debug --progress --port 8266 --auth neo -i <ip address> -f <firmware.bin>`
|
||||
- If you don't have Python 3.8:
|
||||
- first install it (https://www.python.org/downloads/)
|
||||
- install `esptool` using the command `pip install esptool`
|
||||
- also for OTA updates later, download `espota` from https://github.com/esp8266/Arduino/blob/master/tools/espota.py
|
||||
|
||||
- Grab the firmware binary from https://github.com/proddy/EMS-ESP/releases/tag/travis-v2-build
|
||||
- Using direct to USB: `esptool.py -p <COM PORT> -b 921600 write_flash 0x00000 <firmware.bin>`
|
||||
- Using OTA (Over The Air): `espota.py --debug --progress --port 8266 --auth neo -i <ip address> -f <firmware.bin>`
|
||||
|
||||
### Setting up for the first time:
|
||||
|
||||
|
||||
169
scripts/build.sh
Executable file
169
scripts/build.sh
Executable file
@@ -0,0 +1,169 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
### Functions
|
||||
|
||||
is_git() {
|
||||
command -v git >/dev/null 2>&1 || return 1
|
||||
command git rev-parse >/dev/null 2>&1 || return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
stat_bytes() {
|
||||
filesize=`du -k "$1" | cut -f1;`
|
||||
echo 'size:' $filesize 'bytes'
|
||||
}
|
||||
|
||||
# Available environments
|
||||
list_envs() {
|
||||
grep env: platformio.ini | sed 's/\[env:\(.*\)\]/\1/g'
|
||||
}
|
||||
|
||||
print_available() {
|
||||
echo "--------------------------------------------------------------"
|
||||
echo "Available environments:"
|
||||
for environment in $available; do
|
||||
echo "-> $environment"
|
||||
done
|
||||
}
|
||||
|
||||
print_environments() {
|
||||
echo "--------------------------------------------------------------"
|
||||
echo "Current environments:"
|
||||
for environment in $environments; do
|
||||
echo "-> $environment"
|
||||
done
|
||||
}
|
||||
|
||||
set_default_environments() {
|
||||
# Hook to build in parallel when using travis
|
||||
if [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Release" ]] && ${par_build}; then
|
||||
environments=$(echo ${available} | \
|
||||
awk -v par_thread=${par_thread} -v par_total_threads=${par_total_threads} \
|
||||
'{ for (i = 1; i <= NF; i++) if (++j % par_total_threads == par_thread ) print $i; }')
|
||||
return
|
||||
fi
|
||||
|
||||
# Only build travis target
|
||||
if [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Test" ]]; then
|
||||
environments=$travis
|
||||
return
|
||||
fi
|
||||
|
||||
# Fallback to all available environments
|
||||
environments=$available
|
||||
}
|
||||
|
||||
build_environments() {
|
||||
echo "--------------------------------------------------------------"
|
||||
echo "Building firmware images..."
|
||||
# don't move to firmware folder until Travis fixed (see https://github.com/travis-ci/dpl/issues/846#issuecomment-547157406)
|
||||
# mkdir -p $destination
|
||||
|
||||
for environment in $environments; do
|
||||
echo "* EMS-ESP-$version-$environment.bin"
|
||||
platformio run --silent --environment $environment || exit 1
|
||||
stat_bytes .pio/build/$environment/firmware.bin
|
||||
# mv .pio/build/$environment/firmware.bin $destination/EMS-ESP-$version-$environment.bin
|
||||
# mv .pio/build/$environment/firmware.bin EMS-ESP-$version-$environment.bin
|
||||
mv .pio/build/$environment/firmware.bin EMS-ESP-dev-$environment.bin
|
||||
done
|
||||
echo "--------------------------------------------------------------"
|
||||
}
|
||||
|
||||
|
||||
####### MAIN
|
||||
|
||||
destination=firmware
|
||||
version_file=./src/version.h
|
||||
version=$(grep -E '^#define EMSESP_APP_VERSION' $version_file | awk '{print $3}' | sed 's/"//g')
|
||||
|
||||
if ${TRAVIS:-false}; then
|
||||
git_revision=${TRAVIS_COMMIT::7}
|
||||
git_tag=${TRAVIS_TAG}
|
||||
elif is_git; then
|
||||
git_revision=$(git rev-parse --short HEAD)
|
||||
git_tag=$(git tag --contains HEAD)
|
||||
else
|
||||
git_revision=unknown
|
||||
git_tag=
|
||||
fi
|
||||
|
||||
echo $git_tag
|
||||
|
||||
if [[ -n $git_tag ]]; then
|
||||
new_version=${version/-*}
|
||||
sed -i -e "s@$version@$new_version@" $version_file
|
||||
version=$new_version
|
||||
trap "git checkout -- $version_file" EXIT
|
||||
fi
|
||||
|
||||
par_build=false
|
||||
par_thread=${BUILDER_THREAD:-0}
|
||||
par_total_threads=${BUILDER_TOTAL_THREADS:-4}
|
||||
if [ ${par_thread} -ne ${par_thread} -o \
|
||||
${par_total_threads} -ne ${par_total_threads} ]; then
|
||||
echo "Parallel threads should be a number."
|
||||
exit
|
||||
fi
|
||||
if [ ${par_thread} -ge ${par_total_threads} ]; then
|
||||
echo "Current thread is greater than total threads. Doesn't make sense"
|
||||
exit
|
||||
fi
|
||||
|
||||
# travis platformio target is used for nightly Test
|
||||
travis=$(list_envs | grep travis | sort)
|
||||
|
||||
# get all taregts, excluding travis and debug
|
||||
available=$(list_envs | grep -Ev -- 'travis|debug|release' | sort)
|
||||
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS}"
|
||||
|
||||
# get command line Parameters
|
||||
# l prints environments
|
||||
# 2 does parallel builds
|
||||
# d uses next arg as destination folder
|
||||
while getopts "lpd:" opt; do
|
||||
case $opt in
|
||||
l)
|
||||
print_available
|
||||
exit
|
||||
;;
|
||||
p)
|
||||
par_build=true
|
||||
;;
|
||||
d)
|
||||
destination=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND-1))
|
||||
|
||||
# Welcome message
|
||||
echo "--------------------------------------------------------------"
|
||||
echo "EMS-ESP FIRMWARE BUILDER"
|
||||
echo "Building for version ${version}" ${git_revision:+($git_revision)}
|
||||
|
||||
# Environments to build
|
||||
environments=$@
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
set_default_environments
|
||||
fi
|
||||
|
||||
if ${CI:-false}; then
|
||||
print_environments
|
||||
fi
|
||||
|
||||
# for debugging
|
||||
echo "* git_revision = $git_revision"
|
||||
echo "* git_tag = $git_tag"
|
||||
echo "* TRAVIS_COMMIT = $TRAVIS_COMMIT"
|
||||
echo "* TRAVIS_TAG = $TRAVIS_TAG"
|
||||
echo "* TRAVIS_BRANCH = $TRAVIS_BRANCH"
|
||||
echo "* TRAVIS_BUILD_STAGE_NAME = $TRAVIS_BUILD_STAGE_NAME"
|
||||
|
||||
build_environments
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
|
||||
{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
|
||||
{224, DeviceType::CONTROLLER, F("Bosch 9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
{224, DeviceType::CONTROLLER, F("9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Mixing::Mixing(uint8_t device_type, uint8_t device_id, uint8_t product_id, const
|
||||
LOG_DEBUG(F("Registering new Mixing module with device ID 0x%02X"), device_id);
|
||||
|
||||
if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) {
|
||||
if (device_id < 0x28) {
|
||||
if (device_id <= 0x27) {
|
||||
// telegram handlers 0x20 - 0x27 for HC
|
||||
register_telegram_type(device_id - 0x20 + 0x02D7, F("MMPLUSStatusMessage_HC"), true, std::bind(&Mixing::process_MMPLUSStatusMessage_HC, this, _1));
|
||||
} else {
|
||||
@@ -126,7 +126,9 @@ void Mixing::publish_values() {
|
||||
Mqtt::publish(topic, doc);
|
||||
}
|
||||
|
||||
// heating circuits 0x02D7, 0x02D8 etc...
|
||||
// heating circuits 0x02D7, 0x02D8 etc...
|
||||
// e.g. A0 00 FF 00 01 D7 00 00 00 80 00 00 00 00 03 C5
|
||||
// A0 0B FF 00 01 D7 00 00 00 80 00 00 00 00 03 80
|
||||
void Mixing::process_MMPLUSStatusMessage_HC(std::shared_ptr<const Telegram> telegram) {
|
||||
type_ = Type::HC;
|
||||
hc_ = telegram->type_id - 0x02D7 + 1; // determine which circuit this is
|
||||
@@ -172,6 +174,7 @@ void Mixing::process_MMConfigMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
// pos 0: active FF = on
|
||||
// pos 1: valve runtime 0C = 120 sec in units of 10 sec
|
||||
}
|
||||
|
||||
// Mixing on a MM10 - 0xAC
|
||||
// e.g. Thermostat -> Mixing Module, type 0xAC, telegram: 10 21 AC 00 1E 64 01 AB
|
||||
void Mixing::process_MMSetMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
@@ -35,6 +35,9 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const s
|
||||
// telegram handlers
|
||||
register_telegram_type(0x0097, F("SM10Monitor"), true, std::bind(&Solar::process_SM10Monitor, this, _1));
|
||||
register_telegram_type(0x0362, F("SM100Monitor"), true, std::bind(&Solar::process_SM100Monitor, this, _1));
|
||||
register_telegram_type(0x0363, F("SM100Monitor2"), true, std::bind(&Solar::process_SM100Monitor2, this, _1));
|
||||
register_telegram_type(0x0366, F("SM100Config"), true, std::bind(&Solar::process_SM100Config, this, _1));
|
||||
|
||||
register_telegram_type(0x0364, F("SM100Status"), false, std::bind(&Solar::process_SM100Status, this, _1));
|
||||
register_telegram_type(0x036A, F("SM100Status2"), false, std::bind(&Solar::process_SM100Status2, this, _1));
|
||||
register_telegram_type(0x038E, F("SM100Energy"), true, std::bind(&Solar::process_SM100Energy, this, _1));
|
||||
@@ -134,7 +137,7 @@ void Solar::process_SM10Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
/*
|
||||
* SM100Monitor - type 0x0262 EMS+ - for SM100 and SM200
|
||||
* SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
|
||||
* e.g. B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
|
||||
* e.g, 30 00 FF 00 02 62 01 AC
|
||||
* 30 00 FF 18 02 62 80 00
|
||||
@@ -149,8 +152,27 @@ void Solar::process_SM100Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
telegram->read_value(bottomTemp2_, 16); // is *10
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
// SM100Monitor2 - 0x0363
|
||||
// e.g. B0 00 FF 00 02 63 80 00 80 00 00 00 80 00 80 00 80 00 00 80 00 5A
|
||||
void Solar::process_SM100Monitor2(std::shared_ptr<const Telegram> telegram) {
|
||||
// not implemented yet
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// SM100Config - 0x0366
|
||||
// e.g. B0 00 FF 00 02 66 01 62 00 13 40 14
|
||||
void Solar::process_SM100Config(std::shared_ptr<const Telegram> telegram) {
|
||||
telegram->read_value(availabilityFlag_, 0);
|
||||
telegram->read_value(configFlag_, 1);
|
||||
telegram->read_value(userFlag_, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
* SM100Status - type 0x0264 EMS+ for pump modulation - for SM100 and SM200
|
||||
* SM100Status - type 0x0364 EMS+ for pump modulation - for SM100 and SM200
|
||||
* e.g. 30 00 FF 09 02 64 64 = 100%
|
||||
* 30 00 FF 09 02 64 1E = 30%
|
||||
*/
|
||||
@@ -159,7 +181,7 @@ void Solar::process_SM100Status(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
/*
|
||||
* SM100Status2 - type 0x026A EMS+ for pump on/off at offset 0x0A - for SM100 and SM200
|
||||
* SM100Status2 - type 0x036A EMS+ for pump on/off at offset 0x0A - for SM100 and SM200
|
||||
* e.g. B0 00 FF 00 02 6A 03 03 03 03 01 03 03 03 03 03 01 03
|
||||
* byte 4 = VS2 3-way valve for cylinder 2 : test=01, on=04 and off=03
|
||||
* byte 10 = PS1 Solar circuit pump for collector array 1: test=01, on=04 and off=03
|
||||
@@ -170,7 +192,7 @@ void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
/*
|
||||
* SM100Energy - type 0x028E EMS+ for energy readings
|
||||
* SM100Energy - type 0x038E EMS+ for energy readings
|
||||
* e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35
|
||||
*/
|
||||
void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) {
|
||||
@@ -180,7 +202,7 @@ void Solar::process_SM100Energy(std::shared_ptr<const Telegram> telegram) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Junkers ISM1 Solar Module - type 0x0003 EMS+ for energy readings
|
||||
* Junkers ISM1 Solar Module - type 0x0103 EMS+ for energy readings
|
||||
* e.g. B0 00 FF 00 00 03 32 00 00 00 00 13 00 D6 00 00 00 FB D0 F0
|
||||
*/
|
||||
void Solar::process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram) {
|
||||
@@ -192,11 +214,11 @@ void Solar::process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram)
|
||||
}
|
||||
|
||||
/*
|
||||
* Junkers ISM1 Solar Module - type 0x0001 EMS+ for setting values
|
||||
* Junkers ISM1 Solar Module - type 0x0101 EMS+ for setting values
|
||||
* e.g. 90 30 FF 06 00 01 50
|
||||
*/
|
||||
void Solar::process_ISM1Set(std::shared_ptr<const Telegram> telegram) {
|
||||
telegram->read_value(setpoint_maxBottomTemp_, 6);
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -58,11 +58,20 @@ class Solar : public EMSdevice {
|
||||
uint32_t energyTotal_ = EMS_VALUE_ULONG_NOTSET;
|
||||
uint32_t pumpWorkMin_ = EMS_VALUE_ULONG_NOTSET; // Total solar pump operating time
|
||||
|
||||
uint8_t availabilityFlag_ = EMS_VALUE_BOOL_NOTSET;
|
||||
uint8_t configFlag_ = EMS_VALUE_BOOL_NOTSET;
|
||||
uint8_t userFlag_ = EMS_VALUE_BOOL_NOTSET;
|
||||
|
||||
void process_SM10Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Monitor(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Monitor2(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_SM100Config(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_SM100Status(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Status2(std::shared_ptr<const Telegram> telegram);
|
||||
void process_SM100Energy(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_ISM1StatusMessage(std::shared_ptr<const Telegram> telegram);
|
||||
void process_ISM1Set(std::shared_ptr<const Telegram> telegram);
|
||||
};
|
||||
|
||||
@@ -100,6 +100,8 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
||||
register_telegram_type(monitor_typeids[i], F("RC300Monitor"), false, std::bind(&Thermostat::process_RC300Monitor, this, _1));
|
||||
register_telegram_type(set_typeids[i], F("RC300Set"), false, std::bind(&Thermostat::process_RC300Set, this, _1));
|
||||
}
|
||||
register_telegram_type(0x31D, F("RC300WWmode"), false, std::bind(&Thermostat::process_RC300WWmode, this, _1));
|
||||
register_telegram_type(0x31E, F("RC300WWmode"), false, std::bind(&Thermostat::process_RC300WWmode, this, _1));
|
||||
|
||||
// JUNKERS/HT3
|
||||
} else if (flags == EMSdevice::EMS_DEVICE_FLAG_JUNKERS) {
|
||||
@@ -462,27 +464,27 @@ void Thermostat::publish_values() {
|
||||
if (datetime_.size()) {
|
||||
rootThermostat["time"] = datetime_.c_str();
|
||||
}
|
||||
if (dampedoutdoortemp != EMS_VALUE_INT_NOTSET) {
|
||||
rootThermostat["dampedtemp"] = dampedoutdoortemp;
|
||||
if (dampedoutdoortemp_ != EMS_VALUE_INT_NOTSET) {
|
||||
rootThermostat["dampedtemp"] = dampedoutdoortemp_;
|
||||
}
|
||||
if (tempsensor1 != EMS_VALUE_USHORT_NOTSET) {
|
||||
rootThermostat["inttemp1"] = (float)tempsensor1 / 10;
|
||||
if (tempsensor1_ != EMS_VALUE_USHORT_NOTSET) {
|
||||
rootThermostat["inttemp1"] = (float)tempsensor1_ / 10;
|
||||
}
|
||||
if (tempsensor2 != EMS_VALUE_USHORT_NOTSET) {
|
||||
rootThermostat["inttemp2"] = (float)tempsensor2 / 10;
|
||||
if (tempsensor2_ != EMS_VALUE_USHORT_NOTSET) {
|
||||
rootThermostat["inttemp2"] = (float)tempsensor2_ / 10;
|
||||
}
|
||||
if (ibaCalIntTemperature != EMS_VALUE_INT_NOTSET) {
|
||||
rootThermostat["intoffset"] = (float)ibaCalIntTemperature / 2;
|
||||
if (ibaCalIntTemperature_ != EMS_VALUE_INT_NOTSET) {
|
||||
rootThermostat["intoffset"] = (float)ibaCalIntTemperature_ / 2;
|
||||
}
|
||||
if (ibaMinExtTemperature != EMS_VALUE_INT_NOTSET) {
|
||||
rootThermostat["minexttemp"] = (float)ibaMinExtTemperature; // min ext temp for heating curve, in deg.
|
||||
if (ibaMinExtTemperature_ != EMS_VALUE_INT_NOTSET) {
|
||||
rootThermostat["minexttemp"] = (float)ibaMinExtTemperature_; // min ext temp for heating curve, in deg.
|
||||
}
|
||||
if (ibaBuildingType != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaBuildingType == 0) {
|
||||
if (ibaBuildingType_ != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaBuildingType_ == 0) {
|
||||
rootThermostat["building"] = "light";
|
||||
} else if (ibaBuildingType == 1) {
|
||||
} else if (ibaBuildingType_ == 1) {
|
||||
rootThermostat["building"] = "medium";
|
||||
} else if (ibaBuildingType == 2) {
|
||||
} else if (ibaBuildingType_ == 2) {
|
||||
rootThermostat["building"] = "heavy";
|
||||
}
|
||||
}
|
||||
@@ -809,67 +811,67 @@ void Thermostat::show_values(uuid::console::Shell & shell) {
|
||||
|
||||
if (datetime_.size()) {
|
||||
shell.printfln(F(" Clock: %s"), datetime_.c_str());
|
||||
if (ibaClockOffset != EMS_VALUE_UINT_NOTSET && flags == EMS_DEVICE_FLAG_RC30_1) {
|
||||
print_value(shell, 2, F("Offset clock"), Helpers::render_value(buffer, ibaClockOffset, 1)); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
if (ibaClockOffset_ != EMS_VALUE_UINT_NOTSET && flags == EMS_DEVICE_FLAG_RC30_1) {
|
||||
print_value(shell, 2, F("Offset clock"), Helpers::render_value(buffer, ibaClockOffset_, 1)); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
}
|
||||
}
|
||||
|
||||
if (flags == EMS_DEVICE_FLAG_RC35) {
|
||||
print_value(shell, 2, F("Damped Outdoor temperature"), F_(degrees), Helpers::render_value(buffer, dampedoutdoortemp, 1));
|
||||
print_value(shell, 2, F("Temp sensor 1"), F_(degrees), Helpers::render_value(buffer, tempsensor1, 10));
|
||||
print_value(shell, 2, F("Temp sensor 2"), F_(degrees), Helpers::render_value(buffer, tempsensor2, 10));
|
||||
print_value(shell, 2, F("Damped Outdoor temperature"), F_(degrees), Helpers::render_value(buffer, dampedoutdoortemp_, 1));
|
||||
print_value(shell, 2, F("Temp sensor 1"), F_(degrees), Helpers::render_value(buffer, tempsensor1_, 10));
|
||||
print_value(shell, 2, F("Temp sensor 2"), F_(degrees), Helpers::render_value(buffer, tempsensor2_, 10));
|
||||
}
|
||||
if (flags == EMS_DEVICE_FLAG_RC30_1) {
|
||||
// settings parameters
|
||||
if (ibaMainDisplay != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaMainDisplay == 0) {
|
||||
if (ibaMainDisplay_ != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaMainDisplay_ == 0) {
|
||||
shell.printfln(F(" Display: internal temperature"));
|
||||
} else if (ibaMainDisplay == 1) {
|
||||
} else if (ibaMainDisplay_ == 1) {
|
||||
shell.printfln(F(" Display: internal setpoint"));
|
||||
} else if (ibaMainDisplay == 2) {
|
||||
} else if (ibaMainDisplay_ == 2) {
|
||||
shell.printfln(F(" Display: external temperature"));
|
||||
} else if (ibaMainDisplay == 3) {
|
||||
} else if (ibaMainDisplay_ == 3) {
|
||||
shell.printfln(F(" Display: burner temperature"));
|
||||
} else if (ibaMainDisplay == 4) {
|
||||
} else if (ibaMainDisplay_ == 4) {
|
||||
shell.printfln(F(" Display: WW temperature"));
|
||||
} else if (ibaMainDisplay == 5) {
|
||||
} else if (ibaMainDisplay_ == 5) {
|
||||
shell.printfln(F(" Display: functioning mode"));
|
||||
} else if (ibaMainDisplay == 6) {
|
||||
} else if (ibaMainDisplay_ == 6) {
|
||||
shell.printfln(F(" Display: time"));
|
||||
} else if (ibaMainDisplay == 7) {
|
||||
} else if (ibaMainDisplay_ == 7) {
|
||||
shell.printfln(F(" Display: date"));
|
||||
} else if (ibaMainDisplay == 9) {
|
||||
} else if (ibaMainDisplay_ == 9) {
|
||||
shell.printfln(F(" Display: smoke temperature"));
|
||||
}
|
||||
}
|
||||
|
||||
if (ibaLanguage != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaLanguage == 0) {
|
||||
if (ibaLanguage_ != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaLanguage_ == 0) {
|
||||
shell.printfln(F(" Language: German"));
|
||||
} else if (ibaLanguage == 1) {
|
||||
} else if (ibaLanguage_ == 1) {
|
||||
shell.printfln(F(" Language: Dutch"));
|
||||
} else if (ibaLanguage == 2) {
|
||||
} else if (ibaLanguage_ == 2) {
|
||||
shell.printfln(F(" Language: French"));
|
||||
} else if (ibaLanguage == 3) {
|
||||
} else if (ibaLanguage_ == 3) {
|
||||
shell.printfln(F(" Language: Italian"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flags == EMS_DEVICE_FLAG_RC35 || flags == EMS_DEVICE_FLAG_RC30_1) {
|
||||
if (ibaCalIntTemperature != EMS_VALUE_INT_NOTSET) {
|
||||
print_value(shell, 2, F("Offset int. temperature"), F_(degrees), Helpers::render_value(buffer, ibaCalIntTemperature, 2));
|
||||
if (ibaCalIntTemperature_ != EMS_VALUE_INT_NOTSET) {
|
||||
print_value(shell, 2, F("Offset int. temperature"), F_(degrees), Helpers::render_value(buffer, ibaCalIntTemperature_, 2));
|
||||
}
|
||||
|
||||
if (ibaMinExtTemperature != EMS_VALUE_INT_NOTSET) {
|
||||
print_value(shell, 2, F("Min ext. temperature"), F_(degrees), Helpers::render_value(buffer, ibaMinExtTemperature, 0)); // min ext temp for heating curve, in deg.
|
||||
if (ibaMinExtTemperature_ != EMS_VALUE_INT_NOTSET) {
|
||||
print_value(shell, 2, F("Min ext. temperature"), F_(degrees), Helpers::render_value(buffer, ibaMinExtTemperature_, 0)); // min ext temp for heating curve, in deg.
|
||||
}
|
||||
|
||||
if (ibaBuildingType != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaBuildingType == 0) {
|
||||
if (ibaBuildingType_ != EMS_VALUE_UINT_NOTSET) {
|
||||
if (ibaBuildingType_ == 0) {
|
||||
shell.printfln(F(" Building: light"));
|
||||
} else if (ibaBuildingType == 1) {
|
||||
} else if (ibaBuildingType_ == 1) {
|
||||
shell.printfln(F(" Building: medium"));
|
||||
} else if (ibaBuildingType == 2) {
|
||||
} else if (ibaBuildingType_ == 2) {
|
||||
shell.printfln(F(" Building: heavy"));
|
||||
}
|
||||
}
|
||||
@@ -976,9 +978,9 @@ void Thermostat::process_JunkersSet(std::shared_ptr<const Telegram> telegram) {
|
||||
|
||||
// type 0xA3 - for external temp settings from the the RC* thermostats (e.g. RC35)
|
||||
void Thermostat::process_RCOutdoorTemp(std::shared_ptr<const Telegram> telegram) {
|
||||
telegram->read_value(dampedoutdoortemp, 0);
|
||||
telegram->read_value(tempsensor1, 3); // sensor 1 - is * 10
|
||||
telegram->read_value(tempsensor2, 5); // sensor 2 - is * 10
|
||||
telegram->read_value(dampedoutdoortemp_, 0);
|
||||
telegram->read_value(tempsensor1_, 3); // sensor 1 - is * 10
|
||||
telegram->read_value(tempsensor2_, 5); // sensor 2 - is * 10
|
||||
}
|
||||
|
||||
// 0x91 - data from the RC20 thermostat (0x17) - 15 bytes long
|
||||
@@ -1000,13 +1002,13 @@ void Thermostat::process_EasyMonitor(std::shared_ptr<const Telegram> telegram) {
|
||||
// Settings Parameters - 0xA5 - RC30_1
|
||||
void Thermostat::process_IBASettings(std::shared_ptr<const Telegram> telegram) {
|
||||
// 22 - display line on RC35
|
||||
telegram->read_value(ibaMainDisplay,
|
||||
telegram->read_value(ibaMainDisplay_,
|
||||
0); // display on Thermostat: 0 int. temp, 1 int. setpoint, 2 ext. temp., 3 burner temp., 4 ww temp, 5 functioning mode, 6 time, 7 data, 9 smoke temp
|
||||
telegram->read_value(ibaLanguage, 1); // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
|
||||
telegram->read_value(ibaCalIntTemperature, 2); // offset int. temperature sensor, by * 0.1 Kelvin
|
||||
telegram->read_value(ibaBuildingType, 6); // building type: 0 = light, 1 = medium, 2 = heavy
|
||||
telegram->read_value(ibaMinExtTemperature, 5); // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1
|
||||
telegram->read_value(ibaClockOffset, 12); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
telegram->read_value(ibaLanguage_, 1); // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
|
||||
telegram->read_value(ibaCalIntTemperature_, 2); // offset int. temperature sensor, by * 0.1 Kelvin
|
||||
telegram->read_value(ibaBuildingType_, 6); // building type: 0 = light, 1 = medium, 2 = heavy
|
||||
telegram->read_value(ibaMinExtTemperature_, 5); // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1
|
||||
telegram->read_value(ibaClockOffset_, 12); // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
}
|
||||
|
||||
// type 0x6F - FR10/FR50/FR100 Junkers
|
||||
@@ -1053,6 +1055,16 @@ void Thermostat::process_RC300Set(std::shared_ptr<const Telegram> telegram) {
|
||||
telegram->read_value(hc->nighttemp, 4); // is * 2
|
||||
}
|
||||
|
||||
// types 0x31D and 0x31E
|
||||
void Thermostat::process_RC300WWmode(std::shared_ptr<const Telegram> telegram) {
|
||||
// 0x31D for WW system 1, 0x31E for WW system 2
|
||||
wwSystem_ = telegram->type_id - 0x31D + 1;
|
||||
telegram->read_value(wwExtra_, 0); // 0=no, 1=yes
|
||||
// pos 1 = holiday mode
|
||||
// pos 2 = current status of DHW setpoint
|
||||
// pos 3 = current status of DHW circulation pump
|
||||
}
|
||||
|
||||
// type 0x41 - data from the RC30 thermostat(0x10) - 14 bytes long
|
||||
void Thermostat::process_RC30Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
|
||||
|
||||
@@ -113,17 +113,20 @@ class Thermostat : public EMSdevice {
|
||||
uint8_t mqtt_format_; // single, nested or ha
|
||||
|
||||
// Installation parameters
|
||||
uint8_t ibaMainDisplay =
|
||||
uint8_t ibaMainDisplay_ =
|
||||
EMS_VALUE_UINT_NOTSET; // display on Thermostat: 0 int. temp, 1 int. setpoint, 2 ext. temp., 3 burner temp., 4 ww temp, 5 functioning mode, 6 time, 7 data, 9 smoke temp
|
||||
uint8_t ibaLanguage = EMS_VALUE_UINT_NOTSET; // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
|
||||
int8_t ibaCalIntTemperature = EMS_VALUE_INT_NOTSET; // offset int. temperature sensor, by * 0.1 Kelvin (-5.0 to 5.0K)
|
||||
int8_t ibaMinExtTemperature = EMS_VALUE_INT_NOTSET; // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1
|
||||
uint8_t ibaBuildingType = EMS_VALUE_UINT_NOTSET; // building type: 0 = light, 1 = medium, 2 = heavy
|
||||
uint8_t ibaClockOffset = EMS_VALUE_UINT_NOTSET; // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
uint8_t ibaLanguage_ = EMS_VALUE_UINT_NOTSET; // language on Thermostat: 0 german, 1 dutch, 2 french, 3 italian
|
||||
int8_t ibaCalIntTemperature_ = EMS_VALUE_INT_NOTSET; // offset int. temperature sensor, by * 0.1 Kelvin (-5.0 to 5.0K)
|
||||
int8_t ibaMinExtTemperature_ = EMS_VALUE_INT_NOTSET; // min ext temp for heating curve, in deg., 0xF6=-10, 0x0 = 0, 0xFF=-1
|
||||
uint8_t ibaBuildingType_ = EMS_VALUE_UINT_NOTSET; // building type: 0 = light, 1 = medium, 2 = heavy
|
||||
uint8_t ibaClockOffset_ = EMS_VALUE_UINT_NOTSET; // offset (in sec) to clock, 0xff = -1 s, 0x02 = 2 s
|
||||
|
||||
int8_t dampedoutdoortemp = EMS_VALUE_INT_NOTSET;
|
||||
uint16_t tempsensor1 = EMS_VALUE_USHORT_NOTSET;
|
||||
uint16_t tempsensor2 = EMS_VALUE_USHORT_NOTSET;
|
||||
int8_t dampedoutdoortemp_ = EMS_VALUE_INT_NOTSET;
|
||||
uint16_t tempsensor1_ = EMS_VALUE_USHORT_NOTSET;
|
||||
uint16_t tempsensor2_ = EMS_VALUE_USHORT_NOTSET;
|
||||
|
||||
uint8_t wwSystem_ = EMS_VALUE_UINT_NOTSET;
|
||||
uint8_t wwExtra_ = EMS_VALUE_UINT_NOTSET;
|
||||
|
||||
std::vector<std::shared_ptr<HeatingCircuit>> heating_circuits_; // each thermostat can have multiple heating circuits
|
||||
|
||||
@@ -193,7 +196,6 @@ class Thermostat : public EMSdevice {
|
||||
static constexpr uint8_t EMS_OFFSET_JunkersSetMessage2_eco_temp = 6;
|
||||
static constexpr uint8_t EMS_OFFSET_JunkersSetMessage3_heat = 7;
|
||||
|
||||
// static constexpr uint8_t DEFAULT_HEATING_CIRCUIT = 1; // default heating circuit is always 1
|
||||
#define DEFAULT_HEATING_CIRCUIT 1
|
||||
|
||||
// Installation settings
|
||||
@@ -229,6 +231,8 @@ class Thermostat : public EMSdevice {
|
||||
|
||||
void process_EasyMonitor(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
void process_RC300WWmode(std::shared_ptr<const Telegram> telegram);
|
||||
|
||||
// set functions
|
||||
void set_settings_minexttemp(const int8_t mt);
|
||||
void set_settings_calinttemp(const int8_t ct);
|
||||
|
||||
@@ -568,14 +568,15 @@ void EMSESP::send_write_request(const uint16_t type_id,
|
||||
// this is main entry point when data is received on the Rx line, via emsuart library
|
||||
// we check if its a complete telegram or just a single byte (which could be a poll or a return status)
|
||||
void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
// LOG_DEBUG(F("Rx: %s"), Helpers::data_to_hex(data, length).c_str());
|
||||
static uint32_t tx_time_ = 0;
|
||||
// check first for echo
|
||||
uint8_t first_value = data[0];
|
||||
if (((first_value & 0x7F) == txservice_.ems_bus_id()) && (length > 1)) {
|
||||
// if we ask ourself at roomcontrol for version e.g. 0B 98 02 00 20
|
||||
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data);
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("[DEBUG] Echo: %s"), Helpers::data_to_hex(data, length).c_str());
|
||||
// get_uptime is only updated once per loop, does not give the right time
|
||||
LOG_DEBUG(F("[DEBUG] Echo after %d ms: %s"), ::millis() - tx_time_, Helpers::data_to_hex(data, length).c_str());
|
||||
#endif
|
||||
return; // it's an echo
|
||||
}
|
||||
@@ -638,6 +639,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
// if ht3 poll must be ems_bus_id else if Buderus poll must be (ems_bus_id | 0x80)
|
||||
if ((first_value ^ 0x80 ^ rxservice_.ems_mask()) == txservice_.ems_bus_id()) {
|
||||
EMSbus::last_bus_activity(uuid::get_uptime()); // set the flag indication the EMS bus is active
|
||||
tx_time_ = ::millis(); // get_uptime is only updated once per loop, does not give the right time
|
||||
txservice_.send();
|
||||
}
|
||||
// send remote room temperature if active
|
||||
@@ -731,7 +733,7 @@ void EMSESP::console_commands(Shell & shell, unsigned int context) {
|
||||
flash_string_vector{F_(n_mandatory)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10);
|
||||
if ((tx_mode > 0) && (tx_mode <= 30)) {
|
||||
if ((tx_mode > 0) && (tx_mode <= 50)) {
|
||||
Settings settings;
|
||||
settings.ems_tx_mode(tx_mode);
|
||||
settings.commit();
|
||||
|
||||
@@ -206,7 +206,11 @@ void System::start() {
|
||||
settings.app_version(EMSESP_APP_VERSION);
|
||||
settings.commit();
|
||||
|
||||
#if defined(ESP32)
|
||||
LOG_INFO(F("System booted (EMS-ESP version %s ESP32)"), settings.app_version().c_str());
|
||||
#else
|
||||
LOG_INFO(F("System booted (EMS-ESP version %s)"), settings.app_version().c_str());
|
||||
#endif
|
||||
|
||||
if (LED_GPIO) {
|
||||
pinMode(LED_GPIO, OUTPUT); // LED pin, 0 is disabled
|
||||
|
||||
@@ -463,7 +463,7 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) {
|
||||
|
||||
#if defined(ESP8266)
|
||||
Settings settings;
|
||||
if (settings.ems_tx_mode() <= 5) {
|
||||
if (settings.ems_tx_mode() <= 4) {
|
||||
#endif
|
||||
// This logging causes errors with timer based tx-modes on esp8266!
|
||||
LOG_DEBUG(F("Sending %s Tx [#%d], telegram: %s"),
|
||||
|
||||
@@ -358,6 +358,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
EMSESP::add_device(0x28, 160, version, EMSdevice::Brand::BUDERUS); // MM100, WWC
|
||||
EMSESP::add_device(0x29, 161, version, EMSdevice::Brand::BUDERUS); // MM200, WWC
|
||||
|
||||
EMSESP::add_device(0x20, 160, version, EMSdevice::Brand::BOSCH); // MM100
|
||||
|
||||
EMSESP::rxservice_.loop();
|
||||
|
||||
// WWC1 on 0x29
|
||||
@@ -365,6 +367,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & command) {
|
||||
|
||||
// WWC2 on 0x28
|
||||
rx_telegram({0xA8, 0x00, 0xFF, 0x00, 0x02, 0x31, 0x02, 0x35, 0x00, 0x3C, 0x00, 0x3C, 0x3C, 0x46, 0x02, 0x03, 0x03, 0x00, 0x3C});
|
||||
|
||||
// check for error "[emsesp] No telegram type handler found for ID 0x255 (src 0x20, dest 0x00)"
|
||||
rx_telegram({0xA0, 0x00, 0xFF, 0x00, 0x01, 0x55, 0x00, 0x1A});
|
||||
}
|
||||
|
||||
// finally dump to console
|
||||
|
||||
@@ -62,6 +62,10 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
|
||||
|
||||
if (EMS_UART.int_st.brk_det) {
|
||||
EMS_UART.int_clr.brk_det = 1; // clear flag
|
||||
if (emsTxBufIdx < emsTxBufLen) { // timer tx_mode is interrupted by <brk>
|
||||
emsTxBufIdx = emsTxBufLen; // stop timer mode
|
||||
drop_next_rx = true; // we have trash in buffer
|
||||
}
|
||||
length = 0;
|
||||
while (EMS_UART.status.rxfifo_cnt) {
|
||||
uint8_t rx = EMS_UART.fifo.rw_byte; // read all bytes from fifo
|
||||
@@ -81,10 +85,12 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
|
||||
|
||||
|
||||
void IRAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
|
||||
if (emsTxBufIdx > 32) {
|
||||
if (emsTxBufIdx > EMS_MAXBUFFERSIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
emsTxBufIdx++;
|
||||
|
||||
if (emsTxBufIdx < emsTxBufLen) {
|
||||
EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx];
|
||||
timerAlarmWrite(timer, emsTxWait, false);
|
||||
@@ -98,23 +104,14 @@ void IRAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
|
||||
* init UART driver
|
||||
*/
|
||||
void EMSuart::start(uint8_t tx_mode) {
|
||||
if(tx_mode > 10 ) {
|
||||
emsTxWait = EMSUART_BIT_TIME * tx_mode;
|
||||
} else if(tx_mode > 5 ) {
|
||||
emsTxWait = EMSUART_BIT_TIME * tx_mode * 2;
|
||||
} else if(tx_mode == 3) {
|
||||
emsTxWait = EMSUART_BIT_TIME * 17;
|
||||
} else if(tx_mode == 2) {
|
||||
emsTxWait = EMSUART_BIT_TIME * 20;
|
||||
} else if(tx_mode == 1) {
|
||||
emsTxWait = EMSUART_BIT_TIME * 11;
|
||||
}
|
||||
emsTxWait = EMSUART_TX_BIT_TIME * (tx_mode + 10);
|
||||
if (tx_mode_ != 0xFF) { // uart already initialized
|
||||
tx_mode_ = tx_mode;
|
||||
restart();
|
||||
return;
|
||||
}
|
||||
tx_mode_ = tx_mode;
|
||||
tx_mode_ = tx_mode;
|
||||
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = EMSUART_BAUD,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
@@ -123,9 +120,6 @@ void EMSuart::start(uint8_t tx_mode) {
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
};
|
||||
uart_param_config(EMSUART_UART, &uart_config);
|
||||
if (tx_mode_ == 5) {
|
||||
EMS_UART.conf0.stop_bit_num = UART_STOP_BITS_1_5;
|
||||
}
|
||||
uart_set_pin(EMSUART_UART, EMSUART_TXPIN, EMSUART_RXPIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
EMS_UART.int_ena.val = 0; // disable all intr.
|
||||
EMS_UART.int_clr.val = 0xFFFFFFFF; // clear all intr. flags
|
||||
@@ -160,27 +154,22 @@ void EMSuart::restart() {
|
||||
drop_next_rx = true; // and drop first frame
|
||||
}
|
||||
EMS_UART.int_ena.brk_det = 1; // activate only break
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = 0;
|
||||
if (tx_mode_ == 5) {
|
||||
EMS_UART.conf0.stop_bit_num = UART_STOP_BITS_1_5;
|
||||
} else {
|
||||
EMS_UART.conf0.stop_bit_num = UART_STOP_BITS_1;
|
||||
}
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a 1-byte poll, ending with a <BRK>
|
||||
*/
|
||||
void EMSuart::send_poll(uint8_t data) {
|
||||
if (tx_mode_ > 5 || tx_mode_ < 4) { // modes 1, 2, 3 also here
|
||||
// if (tx_mode_ > 5) {
|
||||
// if (tx_mode_ >= 6 || tx_mode_ < 4) { // modes 1, 2, 3 also here
|
||||
if (tx_mode_ >= 5) {
|
||||
EMS_UART.fifo.rw_byte = data;
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = 1;
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = 1;
|
||||
timerAlarmWrite(timer, emsTxWait, false);
|
||||
timerAlarmEnable(timer);
|
||||
} else if (tx_mode_ >= EMS_TXMODE_NEW) {
|
||||
} else if (tx_mode_ == EMS_TXMODE_NEW) {
|
||||
EMS_UART.fifo.rw_byte = data;
|
||||
EMS_UART.conf0.txd_brk = 1; // <brk> after send
|
||||
} else if (tx_mode_ == EMS_TXMODE_HT3) {
|
||||
@@ -198,7 +187,9 @@ void EMSuart::send_poll(uint8_t data) {
|
||||
} else {
|
||||
volatile uint8_t _usrxc = EMS_UART.status.rxfifo_cnt;
|
||||
EMS_UART.fifo.rw_byte = data;
|
||||
while (EMS_UART.status.rxfifo_cnt == _usrxc) {
|
||||
uint8_t timeoutcnt = EMSUART_TX_TIMEOUT;
|
||||
while ((EMS_UART.status.rxfifo_cnt == _usrxc) && (--timeoutcnt > 0)) {
|
||||
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
|
||||
}
|
||||
EMS_UART.conf0.txd_brk = 1; // <brk>
|
||||
}
|
||||
@@ -213,19 +204,19 @@ uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
if (len == 0 || len >= EMS_MAXBUFFERSIZE) {
|
||||
return EMS_TX_STATUS_ERR;
|
||||
}
|
||||
if (tx_mode_ > 5 || tx_mode_ < 4) { // timer controlled modes, also modes 1, 2, 3 because delays not working
|
||||
// if (tx_mode_ > 5) { // timer controlled modes
|
||||
// if (tx_mode_ >= 6 || tx_mode_ < 4) { // timer controlled modes, also modes 1, 2, 3 because delays not working
|
||||
if (tx_mode_ >= 5) { // timer controlled modes
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
emsTxBuf[i] = buf[i];
|
||||
}
|
||||
EMS_UART.fifo.rw_byte = buf[0];
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = len;
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = len;
|
||||
timerAlarmWrite(timer, emsTxWait, false);
|
||||
timerAlarmEnable(timer);
|
||||
return EMS_TX_STATUS_OK;
|
||||
}
|
||||
if (tx_mode_ >= EMS_TXMODE_NEW) { // hardware controlled modes
|
||||
if (tx_mode_ == EMS_TXMODE_NEW) { // hardware controlled modes
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
EMS_UART.fifo.rw_byte = buf[i];
|
||||
}
|
||||
@@ -258,10 +249,10 @@ uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
// EMS_UART.conf0.txfifo_rst = 1;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
volatile uint8_t _usrxc = EMS_UART.status.rxfifo_cnt;
|
||||
EMS_UART.fifo.rw_byte = buf[i]; // send each Tx byte
|
||||
// wait for echo
|
||||
while (EMS_UART.status.rxfifo_cnt == _usrxc) {
|
||||
// delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
|
||||
EMS_UART.fifo.rw_byte = buf[i]; // send each Tx byte
|
||||
uint8_t timeoutcnt = EMSUART_TX_TIMEOUT;
|
||||
while ((EMS_UART.status.rxfifo_cnt == _usrxc) && (--timeoutcnt > 0)) {
|
||||
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
|
||||
}
|
||||
}
|
||||
EMS_UART.conf0.txd_brk = 1; // <brk> after send, cleard by hardware after send
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#define EMSUART_UART UART_NUM_2 // on the ESP32 we're using UART2
|
||||
#define EMS_UART UART2 // for intr setting
|
||||
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
|
||||
#define EMSUART_BIT_TIME 104 // bit time @9600 baud
|
||||
|
||||
#define EMS_TXMODE_DEFAULT 1
|
||||
#define EMS_TXMODE_EMSPLUS 2
|
||||
@@ -51,12 +50,14 @@
|
||||
|
||||
// EMS 1.0
|
||||
#define EMSUART_TX_BUSY_WAIT (EMSUART_TX_BIT_TIME / 8) // 13
|
||||
#define EMSUART_TX_TIMEOUT (22 * EMSUART_TX_BIT_TIME / EMSUART_TX_BUSY_WAIT) // 176
|
||||
|
||||
// HT3/Junkers - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) plus 7 bit delay. The -8 is for lag compensation.
|
||||
#define EMSUART_TX_WAIT_HT3 (EMSUART_TX_BIT_TIME * 17) - 8 // 1760
|
||||
// since we use a faster processor the lag is negligible
|
||||
#define EMSUART_TX_WAIT_HT3 (EMSUART_TX_BIT_TIME * 17) // 1768
|
||||
|
||||
// EMS+ - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) and delay of another Bytetime.
|
||||
#define EMSUART_TX_WAIT_PLUS 2070
|
||||
#define EMSUART_TX_WAIT_PLUS (EMSUART_TX_BIT_TIME * 20) // 2080
|
||||
|
||||
|
||||
// customize the GPIO pins for RX and TX here
|
||||
|
||||
@@ -46,8 +46,10 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
|
||||
|
||||
if (USIS(EMSUART_UART) & ((1 << UIBD))) { // BREAK detection = End of EMS data block
|
||||
USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
|
||||
// just for testing if break isn't finished yet
|
||||
// while((USS(EMSUART_UART) >> USRXD) == 0); // wait for idle state of pin
|
||||
if (emsTxBufIdx < emsTxBufLen) { // timer tx_mode is interrupted by <brk>
|
||||
emsTxBufIdx = emsTxBufLen; // stop timer mode
|
||||
drop_next_rx = true; // we have trash in buffer
|
||||
}
|
||||
USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt
|
||||
length = 0;
|
||||
while ((USS(EMSUART_UART) >> USRXC) & 0x0FF) { // read fifo into buffer
|
||||
@@ -94,7 +96,7 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_flush_fifos() {
|
||||
|
||||
// ISR to Fire when Timer is triggered
|
||||
void ICACHE_RAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
|
||||
if (emsTxBufIdx > 32) {
|
||||
if (emsTxBufIdx > EMS_MAXBUFFERSIZE) {
|
||||
return;
|
||||
}
|
||||
emsTxBufIdx++;
|
||||
@@ -103,30 +105,15 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
|
||||
timer1_write(emsTxWait);
|
||||
} else if (emsTxBufIdx == emsTxBufLen) {
|
||||
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
|
||||
if (tx_mode_ > 5 || tx_mode_ < 11) {
|
||||
timer1_write(5 * EMSUART_TX_BIT_TIME * 11);
|
||||
USIE(EMSUART_UART) &= ~(1 << UIBD); // disable break interrupt
|
||||
}
|
||||
} else if (USC0(EMSUART_UART) & (1 << UCBRK)) {
|
||||
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
|
||||
USIE(EMSUART_UART) |= (1 << UIBD); // enable break interrupt
|
||||
}
|
||||
}
|
||||
/*
|
||||
* init UART0 driver
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
|
||||
if (tx_mode > 10) {
|
||||
emsTxWait = 5 * EMSUART_TX_BIT_TIME * tx_mode; // bittimes for tx_mode
|
||||
} else if (tx_mode > 5) {
|
||||
emsTxWait = 10 * EMSUART_TX_BIT_TIME * tx_mode; // bittimes for tx_mode
|
||||
if (tx_mode >= 5) {
|
||||
emsTxWait = 5 * EMSUART_TX_BIT_TIME * (tx_mode + 10); // bittimes for tx_mode
|
||||
}
|
||||
if (tx_mode == 5) {
|
||||
USC0(EMSUART_UART) = 0x2C; // 8N1,5
|
||||
} else {
|
||||
USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1
|
||||
}
|
||||
|
||||
if (tx_mode_ != 0xFF) { // it's a restart no need to configure uart
|
||||
tx_mode_ = tx_mode;
|
||||
restart();
|
||||
@@ -152,6 +139,7 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
|
||||
|
||||
// set 9600, 8 bits, no parity check, 1 stop bit
|
||||
USD(EMSUART_UART) = (UART_CLK_FREQ / EMSUART_BAUD);
|
||||
USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1
|
||||
|
||||
emsuart_flush_fifos();
|
||||
|
||||
@@ -165,7 +153,7 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
|
||||
// Otherwise, we're only noticed by UCTOT or RxBRK!
|
||||
// change: don't care, we do not use these interrupts
|
||||
USC1(EMSUART_UART) = 0; // reset config first
|
||||
// USC1(EMSUART_UART) = (0x7F << UCFFT) | (0x04 << UCTOT) | (1 << UCTOE); // enable interupts
|
||||
// USC1(EMSUART_UART) = (0x7F << UCFFT) | (0x01 << UCTOT) | (1 << UCTOE); // enable interupts
|
||||
|
||||
// set interrupts for triggers
|
||||
USIC(EMSUART_UART) = 0xFFFF; // clear all interupts
|
||||
@@ -234,14 +222,8 @@ void ICACHE_FLASH_ATTR EMSuart::tx_brk() {
|
||||
ETS_UART_INTR_DISABLE();
|
||||
USC0(EMSUART_UART) |= (1 << UCBRK); // set bit
|
||||
|
||||
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ mode
|
||||
delayMicroseconds(EMSUART_TX_WAIT_PLUS); // 2070
|
||||
} else if (tx_mode_ == EMS_TXMODE_HT3) { // junkers
|
||||
delayMicroseconds(EMSUART_TX_WAIT_BRK); // 1144
|
||||
} else { // EMS1.0
|
||||
while (!(USIR(EMSUART_UART) & (1 << UIBD))) {
|
||||
}
|
||||
}
|
||||
// also for EMS+ there is no need to wait longer, we are finished and can free the bus.
|
||||
delayMicroseconds(EMSUART_TX_WAIT_BRK); // 1144
|
||||
|
||||
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear BRK bit
|
||||
ETS_UART_INTR_ENABLE();
|
||||
@@ -252,15 +234,15 @@ void ICACHE_FLASH_ATTR EMSuart::tx_brk() {
|
||||
* It's a bit dirty. there is no special wait logic per tx_mode type, fifo flushes or error checking
|
||||
*/
|
||||
void EMSuart::send_poll(uint8_t data) {
|
||||
// reset tx-brk, just in case it is accidently set
|
||||
// reset tx-brk, just in case it is accidentally set
|
||||
USC0(EMSUART_UART) &= ~(1 << UCBRK);
|
||||
|
||||
if (tx_mode_ > 5) { // timer controlled modes
|
||||
if (tx_mode_ >= 5) { // timer controlled modes
|
||||
USF(EMSUART_UART) = data;
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = 1;
|
||||
timer1_write(emsTxWait);
|
||||
} else if (tx_mode_ >= EMS_TXMODE_NEW) { // hardware controlled modes
|
||||
} else if (tx_mode_ == EMS_TXMODE_NEW) { // hardware controlled modes
|
||||
USF(EMSUART_UART) = data;
|
||||
USC0(EMSUART_UART) |= (1 << UCBRK); // brk after sendout
|
||||
} else if (tx_mode_ == EMS_TXMODE_HT3) {
|
||||
@@ -271,7 +253,7 @@ void EMSuart::send_poll(uint8_t data) {
|
||||
USF(EMSUART_UART) = data;
|
||||
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
|
||||
tx_brk(); // send <BRK>
|
||||
} else { // EMS1.0
|
||||
} else { // EMS1.0, same logic as in transmit
|
||||
ETS_UART_INTR_DISABLE();
|
||||
volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF;
|
||||
USF(EMSUART_UART) = data;
|
||||
@@ -299,11 +281,11 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
return EMS_TX_STATUS_ERR; // nothing or to much to send
|
||||
}
|
||||
|
||||
// reset tx-brk, just in case it is accidently set
|
||||
// reset tx-brk, just in case it is accidentally set
|
||||
USC0(EMSUART_UART) &= ~(1 << UCBRK);
|
||||
|
||||
// timer controlled modes with extra delay
|
||||
if (tx_mode_ > 5) {
|
||||
if (tx_mode_ >= 5) {
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
emsTxBuf[i] = buf[i];
|
||||
}
|
||||
@@ -314,8 +296,8 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
return EMS_TX_STATUS_OK;
|
||||
}
|
||||
|
||||
// hardware controlled modes with 1 and 1,5 stopbits
|
||||
if (tx_mode_ >= EMS_TXMODE_NEW) {
|
||||
// new code from Michael. See https://github.com/proddy/EMS-ESP/issues/380
|
||||
if (tx_mode_ == EMS_TXMODE_NEW) { // tx_mode 4
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
USF(EMSUART_UART) = buf[i];
|
||||
}
|
||||
|
||||
@@ -49,10 +49,11 @@
|
||||
#define EMSUART_TX_TIMEOUT (22 * EMSUART_TX_BIT_TIME / EMSUART_TX_BUSY_WAIT) // 176
|
||||
|
||||
// HT3/Junkers - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) plus 7 bit delay. The -8 is for lag compensation.
|
||||
#define EMSUART_TX_WAIT_HT3 (EMSUART_TX_BIT_TIME * 17) - 8 // 1760
|
||||
// since we use a faster processor the lag is negligible
|
||||
#define EMSUART_TX_WAIT_HT3 (EMSUART_TX_BIT_TIME * 17) // 1768
|
||||
|
||||
// EMS+ - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) and delay of another Bytetime.
|
||||
#define EMSUART_TX_WAIT_PLUS 2070
|
||||
#define EMSUART_TX_WAIT_PLUS (EMSUART_TX_BIT_TIME * 20) // 2080
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user