Added support for average measurements
This commit is contained in:
parent
93ef495c3c
commit
86139abc42
|
@ -1,5 +1,5 @@
|
||||||
#ifndef ARDUINO_AVR_MEGA2560
|
#ifndef ARDUINO_AVR_MEGA2560
|
||||||
#error This program was written for an Atmega2560
|
#error This program was written for an Arduino Mega (Atmega2560)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
|
@ -469,6 +469,9 @@ void loop() {
|
||||||
setParams(p);
|
setParams(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.process();
|
||||||
|
d.process();
|
||||||
|
|
||||||
#if _MODBUS == 1
|
#if _MODBUS == 1
|
||||||
mb.process();
|
mb.process();
|
||||||
checkModbusParams();
|
checkModbusParams();
|
||||||
|
@ -482,6 +485,8 @@ void loop() {
|
||||||
bitClear(modbusData[1], 14);
|
bitClear(modbusData[1], 14);
|
||||||
// Nachden die 'ReferenzZeit' erstmalig gesetzt wurde, wird dieses Bit gelöscht
|
// Nachden die 'ReferenzZeit' erstmalig gesetzt wurde, wird dieses Bit gelöscht
|
||||||
bitClear(modbusData[1], 15);
|
bitClear(modbusData[1], 15);
|
||||||
|
// Setze die Durchschnittswerte für die Messwerte zurück
|
||||||
|
c.resetAverageCounters();
|
||||||
_println("Der 12 Bit Timer wurde zurückgesetzt");
|
_println("Der 12 Bit Timer wurde zurückgesetzt");
|
||||||
}
|
}
|
||||||
if (!timeStampOverflow && (millis() - timeStamp) / 100 > 0xFFF) {
|
if (!timeStampOverflow && (millis() - timeStamp) / 100 > 0xFFF) {
|
||||||
|
@ -495,15 +500,13 @@ void loop() {
|
||||||
}
|
}
|
||||||
modbusData[5] = (millis() - timeStamp) / 100;
|
modbusData[5] = (millis() - timeStamp) / 100;
|
||||||
#endif // _MODBUS ==
|
#endif // _MODBUS ==
|
||||||
c.process();
|
|
||||||
d.process();
|
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
static unsigned long counter = 0;
|
static unsigned long counter = 0;
|
||||||
static unsigned long tl = millis();
|
static unsigned long tl = millis();
|
||||||
if (millis() - tl > 1000) {
|
if (millis() - tl > 1000) {
|
||||||
tl = millis();
|
tl = millis();
|
||||||
_print("Loops: "); _println(counter);
|
_print("Loops / Sekunde: "); _println(counter);
|
||||||
counter = 0;
|
counter = 0;
|
||||||
} else {
|
} else {
|
||||||
counter++;
|
counter++;
|
|
@ -4,6 +4,13 @@ Experimentelle Firmware für einen Tankregler, der die Temperatur und den Druck
|
||||||
|
|
||||||
Das Programm ist für den Atmega2560 (Arduino Mega 2560) geschrieben.
|
Das Programm ist für den Atmega2560 (Arduino Mega 2560) geschrieben.
|
||||||
|
|
||||||
|
## Probleme
|
||||||
|
|
||||||
|
- ***Großes Problem:*** Während des Gedrückthaltens einer Menütaste am Regler blockiert das Programm fast (nur noch ca. 10 Loops / Sekunde). In diesem Fall funktioiert Modbus nicht mehr.
|
||||||
|
***### TODO - Das liegt an der Zeit, die gebraucht wird, um das Display zu beschreiben (70 - 100+ ms). Wenn praktisch dauernd das Display neu beschrieben wird, bleibt einfach keine Zeit für was anderes -- SCHNELL LEINE LÖSUNG FINDEN***
|
||||||
|
- Solange nur ein Kühlkreis implementiert ist, lässt sich das maximale Abfrageintervall (siehe Modbus-Holding-Register 0xC0; wenn _TEMP_CONVERSION_DELAY und _ANALOG_READ_DELAY nicht reduziert werden (800 bzw. 500 ms)) auf dem Wert des internen 12 Bit Timers halten (409,6 Sekunden), da der RAM wegen den Arrays zur Messwert-Mittelung schon jetzt gerade so ausreicht (Bei einem Test waren **nur noch 874 Bytes** für lokale Variablen über).
|
||||||
|
***### Temperatur-Mittelung wieder entfernen, da die Temperaturschwankungen BEI WEITEM nicht so stark sind wie die des Drucks?*** (Da der Drucksensor in einer Leitung außerhalb des Tanks sitzt, schwankt der Druck extrem beim Schalten der Druckventile)
|
||||||
|
|
||||||
# Modbus
|
# Modbus
|
||||||
|
|
||||||
## Coils - FC 1, 5, 15
|
## Coils - FC 1, 5, 15
|
||||||
|
@ -78,7 +85,7 @@ Sollwerte:
|
||||||
|
|
||||||
Setzen der Referenzzeit:
|
Setzen der Referenzzeit:
|
||||||
|
|
||||||
- ***0xC0***: Es muss ein vom vorigen Wert abweichender Wert (z.B. ein Zähler oder die 16 LSBs der UNIX-Zeit in Zehntelsekunden – beim ersten Mal jedenfalls NICHT *0xFFFF*, da das Register damit initialisiert ist und kein Unterschied festgestellt werden könnte) übergeben werden. Der Regler verwendet diesen Wert prinzipiell für nichts, außer dass der interne 12 Bit-Timer (1/10 Sekunden) und der Event-Counter auf 0 zurückgesetzt werden (siehe Input-Register ***0x00*** und ***0x06***), wenn sich dieser Wert ändert. Der Master kann entweder
|
- ***0xC0***: Es muss ein vom vorigen Wert abweichender Wert (z.B. ein Zähler – beim ersten Mal jedenfalls NICHT *0xFFFF*, da das Register damit initialisiert ist und kein Unterschied festgestellt werden könnte) übergeben werden. Der Regler verwendet diesen Wert prinzipiell für nichts, außer dass der interne 12 Bit-Timer (1/10 Sekunden) und der Event-Counter auf 0 zurückgesetzt werden (siehe Input-Register ***0x00*** und ***0x06***), wenn sich dieser Wert ändert. Der Master kann entweder
|
||||||
|
|
||||||
- den entsprechenden Zeitstempel im speichern, und den Zeitstempel der Antwort (siehe Input-Register ***0x06***) dazu addieren, um den tatsächlichen Zeitpunkt des Ereignisses zu ermitteln, oder
|
- den entsprechenden Zeitstempel im speichern, und den Zeitstempel der Antwort (siehe Input-Register ***0x06***) dazu addieren, um den tatsächlichen Zeitpunkt des Ereignisses zu ermitteln, oder
|
||||||
- den in ***0x05*** gespeicherten Referenzzeitpunkt (Zehntelsekunden seit Reglerstart bzw. letzter Referenzierung (siehe Holding-Register ***0xC0***)) mit dem Event-Zeitpunkt und dem aktuellen Zeitstempel des Masters gegenrechnen.
|
- den in ***0x05*** gespeicherten Referenzzeitpunkt (Zehntelsekunden seit Reglerstart bzw. letzter Referenzierung (siehe Holding-Register ***0xC0***)) mit dem Event-Zeitpunkt und dem aktuellen Zeitstempel des Masters gegenrechnen.
|
||||||
|
|
21
src/common.h
21
src/common.h
|
@ -2,7 +2,6 @@
|
||||||
#define _MY_STUFF_H_INCLUDED
|
#define _MY_STUFF_H_INCLUDED
|
||||||
|
|
||||||
#include "./DallasTemperature/DallasTemperature.h"
|
#include "./DallasTemperature/DallasTemperature.h"
|
||||||
// #include <math.h> // NAN
|
|
||||||
|
|
||||||
#define _VERSION_MAJOR 0
|
#define _VERSION_MAJOR 0
|
||||||
#define _VERSION_MINOR 0
|
#define _VERSION_MINOR 0
|
||||||
|
@ -10,13 +9,26 @@
|
||||||
#define _VERSION_NUMBER _VERSION_MICRO | (_VERSION_MINOR << 6) | (_VERSION_MAJOR << 12)
|
#define _VERSION_NUMBER _VERSION_MICRO | (_VERSION_MINOR << 6) | (_VERSION_MAJOR << 12)
|
||||||
#define _VERSION_STRING "v0.0.1"
|
#define _VERSION_STRING "v0.0.1"
|
||||||
|
|
||||||
#define _DEBUG 1
|
#define _DEBUG 0
|
||||||
#define _DEBUG_SENSORS 0
|
#define _DEBUG_SENSORS 0
|
||||||
#define _MODBUS 1
|
#define _MODBUS 1
|
||||||
|
|
||||||
#if _DEBUG == 1
|
#if _DEBUG == 1
|
||||||
#define _print(x) Serial.print(x)
|
#define _print(x) Serial.print(x)
|
||||||
#define _println(x) Serial.println(x)
|
#define _println(x) Serial.println(x)
|
||||||
|
struct _printTimeStruct {
|
||||||
|
_printTimeStruct(const char *text) : _text(text) {
|
||||||
|
_t0 = millis();
|
||||||
|
};
|
||||||
|
~_printTimeStruct() {
|
||||||
|
_print("Vergangene Millisekunden ["); _print(_text);
|
||||||
|
_print("]: "); _println(millis() - _t0);
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
u32 _t0;
|
||||||
|
const char *_text;
|
||||||
|
};
|
||||||
|
#define _printtime(text) _printTimeStruct __printt(text)
|
||||||
#if _DEBUG_SENSORS == 1
|
#if _DEBUG_SENSORS == 1
|
||||||
#define _prints(x) Serial.print(x)
|
#define _prints(x) Serial.print(x)
|
||||||
#define _printsln(x) Serial.println(x)
|
#define _printsln(x) Serial.println(x)
|
||||||
|
@ -29,6 +41,7 @@
|
||||||
#define _println(x)
|
#define _println(x)
|
||||||
#define _prints(x)
|
#define _prints(x)
|
||||||
#define _printsln(x)
|
#define _printsln(x)
|
||||||
|
#define _printtime()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _REGS_INFRONTOF_EVENTS 6
|
#define _REGS_INFRONTOF_EVENTS 6
|
||||||
|
@ -57,10 +70,10 @@ extern u16 modbusData[];
|
||||||
eventCounter++;\
|
eventCounter++;\
|
||||||
}\
|
}\
|
||||||
}
|
}
|
||||||
#define _setModbusValue(index, val) modbusData[index] = val
|
//#define _setModbusValue(index, val) modbusData[index] = val
|
||||||
#else
|
#else
|
||||||
#define _setModbusValve(index, val)
|
#define _setModbusValve(index, val)
|
||||||
#define _setModbusValue(index, val)
|
//#define _setModbusValue(index, val)
|
||||||
#endif // _MODBUS ==
|
#endif // _MODBUS ==
|
||||||
|
|
||||||
#define _MODBUS_ADDR_MIN 1
|
#define _MODBUS_ADDR_MIN 1
|
||||||
|
|
|
@ -58,7 +58,7 @@ void Controller::init(bool startup=false)
|
||||||
|
|
||||||
void Controller::process()
|
void Controller::process()
|
||||||
{
|
{
|
||||||
if (_initOk && millis() - _lastConversion > _CONVERSION_DELAY) {
|
if (_initOk && millis() - _lastConversion > _TEMP_CONVERSION_DELAY) {
|
||||||
_lastConversion = millis();
|
_lastConversion = millis();
|
||||||
_requestConversion = true;
|
_requestConversion = true;
|
||||||
float temp = _dallas.getTempC(_tempAddr1);
|
float temp = _dallas.getTempC(_tempAddr1);
|
||||||
|
@ -101,7 +101,9 @@ void Controller::process()
|
||||||
_setT1Valve(0, stateIdle);
|
_setT1Valve(0, stateIdle);
|
||||||
_printsln();
|
_printsln();
|
||||||
}
|
}
|
||||||
_setModbusValue(_MODBUS_T1_INDEX, _vals->t1);
|
#if _MODBUS == 1
|
||||||
|
_averageTemperature1();
|
||||||
|
#endif
|
||||||
} else if (_requestConversion) {
|
} else if (_requestConversion) {
|
||||||
_requestConversion = false;
|
_requestConversion = false;
|
||||||
_dallas.requestTemperatures();
|
_dallas.requestTemperatures();
|
||||||
|
@ -126,7 +128,9 @@ void Controller::process()
|
||||||
_vals->p = (float) _rawP / 1.705f; // 1023 / 6 * 100 (0-5 1/100 bar)
|
_vals->p = (float) _rawP / 1.705f; // 1023 / 6 * 100 (0-5 1/100 bar)
|
||||||
_prints(" (Gems), p: "); _prints(_vals->p);
|
_prints(" (Gems), p: "); _prints(_vals->p);
|
||||||
}
|
}
|
||||||
_setModbusValue(_MODBUS_P_INDEX, _vals->p);
|
#if _MODBUS == 1
|
||||||
|
_averagePressure();
|
||||||
|
#endif
|
||||||
if (_vals->p != _SENSOR_FAULT && _params->cEn) {
|
if (_vals->p != _SENSOR_FAULT && _params->cEn) {
|
||||||
switch (_pState) {
|
switch (_pState) {
|
||||||
case stateIdle:
|
case stateIdle:
|
||||||
|
@ -213,7 +217,81 @@ void Controller::_setPValves(States state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// uint16_t Controller::_convertFloat(const float &x)
|
#if _MODBUS == 1
|
||||||
// {
|
void Controller::resetAverageCounters()
|
||||||
// return (uint16_t) (x * 100);
|
{
|
||||||
// }
|
_print("Setze Zähler zurück (_t1_c: ");
|
||||||
|
_print(_t1_c); _print(", _t2_c: ");
|
||||||
|
_print(_t2_c); _print(", _p_c: ");
|
||||||
|
_print(_p_c); _println(")");
|
||||||
|
_t1_c = 0;
|
||||||
|
_t2_c = 0;
|
||||||
|
_p_c = 0;
|
||||||
|
_t1_of = false;
|
||||||
|
_t2_of = false;
|
||||||
|
_p_of = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Controller::_averageTemperature1()
|
||||||
|
{
|
||||||
|
int32_t total = 0;
|
||||||
|
int16_t result = _SENSOR_FAULT;
|
||||||
|
u8 valid = 0;
|
||||||
|
u8 invalid = 0;
|
||||||
|
if (_t1_c >= _T_ARR_LEN) {
|
||||||
|
_t1_c = 0;
|
||||||
|
_t1_of = true;
|
||||||
|
}
|
||||||
|
// Falls das Array schon voll ist, wird es wieder vom Anfang befüllt
|
||||||
|
_t1_arr[_t1_c++] = _vals->t1;
|
||||||
|
// Dabei läuft die for-Schleife dann über alle Einträge, ansonsten nur bis zum aktuellen
|
||||||
|
u16 loopTill = (_t1_of) ? _T_ARR_LEN : _t1_c;
|
||||||
|
for (u16 i=0; i<loopTill; i++) {
|
||||||
|
if (_t1_arr[i] != _SENSOR_FAULT) {
|
||||||
|
total += _t1_arr[i];
|
||||||
|
valid++;
|
||||||
|
} else {
|
||||||
|
invalid++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valid >= invalid) {
|
||||||
|
result = total / valid;
|
||||||
|
}
|
||||||
|
modbusData[_MODBUS_T1_INDEX] = result;
|
||||||
|
// _setModbusValue(_MODBUS_T1_INDEX, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Controller::_averageTemperature2()
|
||||||
|
{
|
||||||
|
// noch nicht implementiert
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Controller::_averagePressure()
|
||||||
|
{
|
||||||
|
int32_t total = 0;
|
||||||
|
int16_t result = _SENSOR_FAULT;
|
||||||
|
u8 valid = 0;
|
||||||
|
u8 invalid = 0;
|
||||||
|
if (_p_c >= _P_ARR_LEN) {
|
||||||
|
_p_c = 0;
|
||||||
|
_p_of = true;
|
||||||
|
}
|
||||||
|
// Falls das Array schon voll ist, wird es wieder vom Anfang befüllt
|
||||||
|
_p_arr[_p_c++] = _vals->p;
|
||||||
|
// Dabei läuft die for-Schleife dann über alle Einträge, ansonsten nur bis zum aktuellen
|
||||||
|
u16 loopTill = (_p_of) ? _P_ARR_LEN : _p_c;
|
||||||
|
for (u16 i=0; i<_p_c; i++) {
|
||||||
|
if (_p_arr[i] != _SENSOR_FAULT) {
|
||||||
|
total += _p_arr[i];
|
||||||
|
valid++;
|
||||||
|
} else {
|
||||||
|
invalid++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valid >= invalid) {
|
||||||
|
result = total / valid;
|
||||||
|
}
|
||||||
|
modbusData[_MODBUS_P_INDEX] = result;
|
||||||
|
// _setModbusValue(_MODBUS_P_INDEX, result);
|
||||||
|
}
|
||||||
|
#endif // _MODBUS == 1
|
||||||
|
|
|
@ -6,8 +6,14 @@
|
||||||
#include "../display/display.h"
|
#include "../display/display.h"
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#define _CONVERSION_DELAY 800
|
#define _TEMP_CONVERSION_DELAY 800
|
||||||
#define _ANALOG_READ_DELAY 500
|
#define _ANALOG_READ_DELAY 500
|
||||||
|
// Maximal nötige Anzahl an Temperatur-Einträgen, bevor der interne 12 Bit Timer überläuft
|
||||||
|
#define _T_ARR_LEN (409600 / _TEMP_CONVERSION_DELAY) + 1
|
||||||
|
// Maximal nötige Anzahl an Druck-Einträgen, bevor der interne 12 Bit Timer überläuft
|
||||||
|
#define _P_ARR_LEN (409600 / _ANALOG_READ_DELAY) + 1
|
||||||
|
// #define _T_ARR_LEN 255
|
||||||
|
// #define _P_ARR_LEN 255
|
||||||
|
|
||||||
class Controller
|
class Controller
|
||||||
{
|
{
|
||||||
|
@ -23,13 +29,21 @@ private:
|
||||||
uint8_t _t1Pin;
|
uint8_t _t1Pin;
|
||||||
uint8_t _t2Pin;
|
uint8_t _t2Pin;
|
||||||
|
|
||||||
|
int16_t _t1_arr[_T_ARR_LEN]; // Array, aus dem der Durchschnittswert ermittelt wird
|
||||||
|
u16 _t1_c = 0; // Anzahl der Einträge, aus denen der Durchschnitt gebildet wird
|
||||||
|
bool _t1_of = false; // Flag, die anzeigt, ob das _t1_arr-Array schon voll ist
|
||||||
|
// int16_t _t2_arr[_T_ARR_LEN]; // Array, aus dem der Durchschnittswert ermittelt wird
|
||||||
|
u16 _t2_c = 0; // Anzahl der Einträge, aus denen der Durchschnitt gebildet wird
|
||||||
|
bool _t2_of = false; // Flag, die anzeigt, ob das _t2_arr-Array schon voll ist
|
||||||
|
int16_t _p_arr[_P_ARR_LEN]; // Array, aus dem der Durchschnittswert ermittelt wird
|
||||||
|
u16 _p_c = 0; // Anzahl der Einträge, aus denen der Durchschnitt gebildet wird
|
||||||
|
bool _p_of = false; // Flag, die anzeigt, ob das _p_arr-Array schon voll ist
|
||||||
|
|
||||||
OneWire _oneWire;
|
OneWire _oneWire;
|
||||||
DallasTemperature _dallas;
|
DallasTemperature _dallas;
|
||||||
DeviceAddress _tempAddr1;
|
DeviceAddress _tempAddr1;
|
||||||
|
|
||||||
enum States : uint8_t {
|
enum States : uint8_t { stateIdle, stateRising, stateFalling };
|
||||||
stateIdle, stateRising, stateFalling
|
|
||||||
};
|
|
||||||
States _tState = stateIdle;
|
States _tState = stateIdle;
|
||||||
States _pState = stateIdle;
|
States _pState = stateIdle;
|
||||||
|
|
||||||
|
@ -39,11 +53,14 @@ private:
|
||||||
unsigned long _lastAnalogRead;
|
unsigned long _lastAnalogRead;
|
||||||
uint16_t _rawP;
|
uint16_t _rawP;
|
||||||
|
|
||||||
// void _setTState(States curr, States next);
|
|
||||||
// void _setPState(States curr, States next);
|
|
||||||
void _setT1Valve(uint8_t, States);
|
void _setT1Valve(uint8_t, States);
|
||||||
void _setPValves(States);
|
void _setPValves(States);
|
||||||
// uint16_t _convertFloat(const float &x);
|
|
||||||
|
#if _MODBUS == 1
|
||||||
|
void _averageTemperature1();
|
||||||
|
void _averageTemperature2();
|
||||||
|
void _averagePressure();
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Controller(const uint8_t pAnalaogPin,
|
Controller(const uint8_t pAnalaogPin,
|
||||||
|
@ -61,6 +78,9 @@ private:
|
||||||
|
|
||||||
void init(bool startup=false);
|
void init(bool startup=false);
|
||||||
void process();
|
void process();
|
||||||
|
#if _MODBUS == 1
|
||||||
|
void resetAverageCounters();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MY_CONTROLLER_H_INCLUDED
|
#endif // MY_CONTROLLER_H_INCLUDED
|
||||||
|
|
|
@ -278,6 +278,7 @@ void Display::_select(const uint8_t selection, const bool restoreCursor=false)
|
||||||
|
|
||||||
void Display::_select()
|
void Display::_select()
|
||||||
{
|
{
|
||||||
|
// _printtime("select screen");
|
||||||
setFont(_SEL_FONT);
|
setFont(_SEL_FONT);
|
||||||
setFontRefHeightAll();
|
setFontRefHeightAll();
|
||||||
_inputValueActive = false;
|
_inputValueActive = false;
|
||||||
|
@ -386,6 +387,7 @@ void Display::_home()
|
||||||
bool tState = _vStates->t1;
|
bool tState = _vStates->t1;
|
||||||
// %u in sprintf() geht nur bis uint16_t
|
// %u in sprintf() geht nur bis uint16_t
|
||||||
String baudStr(_modbusParams->baudrate);
|
String baudStr(_modbusParams->baudrate);
|
||||||
|
// _printtime("homescreen");
|
||||||
firstPage();
|
firstPage();
|
||||||
do {
|
do {
|
||||||
setFont(u8g2_font_fub20_tf);
|
setFont(u8g2_font_fub20_tf);
|
||||||
|
|
Loading…
Reference in a new issue