Merge and change uart timer modes to pause between bytes (5..50)

This commit is contained in:
MichaelDvP
2020-06-16 11:02:15 +02:00
17 changed files with 440 additions and 163 deletions

72
.travis.yml Normal file
View 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

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
};

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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

View File

@@ -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"),

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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];
}

View File

@@ -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 {