Skip to content

Commit

Permalink
Bunch of fixes
Browse files Browse the repository at this point in the history
- Remove exponential smoothing because the capacitor is still needed
- Add `livoloShift`
- Add serial debugging
- Add watchdog timer
  • Loading branch information
Pavel Perestoronin committed Jan 15, 2020
1 parent c3e5d80 commit 747273e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 24 deletions.
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ You need to generate the `table.h` for your particular NTC thermistor. It contai
Measure your NTC resistance at two different temperature points. Then call `table.py` specifying your measurements:

```sh
python table.py \
--t1 <temperature-1> --r1 <resistance-at-t1> \
--t2 <temperature-2> --r2 <resistance-at-t2> \
--rf <fixed-resistor>
python table.py --t1 <temperature-1> --r1 <resistance-at-t1> --t2 <temperature-2> --r2 <resistance-at-t2> --rf <fixed-resistor>
```

I recommend to measure your fixed resistor actual resistance to improve accuracy.
Expand All @@ -25,13 +22,10 @@ See [Measuring the temperature with NTCs](http://www.giangrandi.ch/electronics/n

### Note for Livolo thermostats

Livolo's 1-Wire master has non-standard timings and does not read all the data transmitted. You'll need to patch OneWireHub's `OneWireHub_config.h` and `DS18B20.cpp` using the included `livolo.patch`.
Damn them!

See also https://github.com/orgua/OneWireHub/issues/84.

### Smoothing filter

The code implementes the simplest [exponential smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing) of converted temperature. You may want to adjust `smoothingFactor` according to your needs.
1. Supposingly, one has to solder out the second sensor deep inside the thermostat **even before turning it on for the first time**. If you've already done that, you may try to figure out the calibrated temperature shift that the thermostat has calculated and remembered. Wait ~4 minutes and note the difference between displayed and real temperatures. Then, change `livoloShift` in the source code to compensate this.
2. Livolo's 1-Wire master has non-standard timings and does not read all the data transmitted. You'll need to patch OneWireHub's `OneWireHub_config.h` and `DS18B20.cpp` using the included `livolo.patch`. See also https://github.com/orgua/OneWireHub/issues/84.

### Connections

Expand Down
3 changes: 3 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@
platform = atmelavr
board = nanoatmega328
framework = arduino
upload_port = /dev/cu.wchusbserial*
monitor_port = /dev/cu.wchusbserial*
monitor_speed = 2000000
lib_deps =
OneWireHub
43 changes: 29 additions & 14 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
#include <Arduino.h>
#include <avr/wdt.h>

#include <DS18B20.h>

#include "table.h"

// NTC input.
// NTC input pin.
constexpr uint8_t adcPin = A1;

// Temperature measurement interval (approximate).
constexpr unsigned long interval = 1000;

// 1-Wire I/O.
auto hub = OneWireHub(12); // PB4/MISO
auto hub = OneWireHub(12); // PB4 aka MISO
auto ds18b20 = DS18B20(0x28, 0x92, 0x23, 0xC5, 0x1E, 0x19, 0x01); // Copied from a real sensor: 289223C51E190171.

// Exponential smoothing factor.
constexpr float smoothingFactor = 0.2;

// Error flag indicator.
// Error LED pin.
constexpr uint8_t ledPin = 13;

// Livolo thermostat performs some calibration.
// This is the temperature shift we apply to match the actual temperature.
constexpr float livoloShift = +3.0f;

void setup() {
// TODO: setup WDT.
wdt_disable();
wdt_enable(WDTO_8S);

Serial.begin(2000000);
while (!Serial);

pinMode(adcPin, INPUT);

Expand All @@ -38,22 +45,30 @@ float readTemperature(const uint8_t pin) {

void loop() {
static uint32_t nextMillis = millis();
static float temperature = readTemperature(adcPin);

// TODO: reset WDT before polling the hub.
wdt_reset();
hub.poll();

// Display the error flag. Timeouts are okay.
const auto error = (uint8_t)hub.getError();
digitalWrite(13, ((error != 0) && (error != 3)) ? HIGH : LOW);
const auto isError = (error != 0) && (error != 3);
digitalWrite(13, isError ? HIGH : LOW);
if (isError) {
Serial.print("E: ");
Serial.println(error);
}

if (millis() > nextMillis) {
// Schedule the next measurement.
nextMillis = millis() + 1000;

// Apply basic exponential smoothing filter.
// https://en.wikipedia.org/wiki/Exponential_smoothing#Basic_exponential_smoothing
temperature = temperature + smoothingFactor * (readTemperature(adcPin) - temperature);
ds18b20.setTemperature(temperature);
const auto reading = readTemperature(adcPin);
ds18b20.setTemperature(reading + livoloShift);

Serial.print(millis());
Serial.print(" ms | ");
Serial.print(reading);
Serial.println(" °C");
Serial.flush();
}
}

0 comments on commit 747273e

Please sign in to comment.