Added support for average measurements
This commit is contained in:
parent
93ef495c3c
commit
86139abc42
|
@ -1,5 +1,5 @@
|
|||
#ifndef ARDUINO_AVR_MEGA2560
|
||||
#error This program was written for an Atmega2560
|
||||
#error This program was written for an Arduino Mega (Atmega2560)
|
||||
#endif
|
||||
|
||||
#include <EEPROM.h>
|
||||
|
@ -469,6 +469,9 @@ void loop() {
|
|||
setParams(p);
|
||||
}
|
||||
|
||||
c.process();
|
||||
d.process();
|
||||
|
||||
#if _MODBUS == 1
|
||||
mb.process();
|
||||
checkModbusParams();
|
||||
|
@ -482,6 +485,8 @@ void loop() {
|
|||
bitClear(modbusData[1], 14);
|
||||
// Nachden die 'ReferenzZeit' erstmalig gesetzt wurde, wird dieses Bit gelöscht
|
||||
bitClear(modbusData[1], 15);
|
||||
// Setze die Durchschnittswerte für die Messwerte zurück
|
||||
c.resetAverageCounters();
|
||||
_println("Der 12 Bit Timer wurde zurückgesetzt");
|
||||
}
|
||||
if (!timeStampOverflow && (millis() - timeStamp) / 100 > 0xFFF) {
|
||||
|
@ -495,15 +500,13 @@ void loop() {
|
|||
}
|
||||
modbusData[5] = (millis() - timeStamp) / 100;
|
||||
#endif // _MODBUS ==
|
||||
c.process();
|
||||
d.process();
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
static unsigned long counter = 0;
|
||||
static unsigned long tl = millis();
|
||||
if (millis() - tl > 1000) {
|
||||
tl = millis();
|
||||
_print("Loops: "); _println(counter);
|
||||
_print("Loops / Sekunde: "); _println(counter);
|
||||
counter = 0;
|
||||
} else {
|
||||
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.
|
||||
|
||||
## 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
|
||||
|
||||
## Coils - FC 1, 5, 15
|
||||
|
@ -78,7 +85,7 @@ Sollwerte:
|
|||
|
||||
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 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
|
||||
|
||||
#include "./DallasTemperature/DallasTemperature.h"
|
||||
// #include <math.h> // NAN
|
||||
|
||||
#define _VERSION_MAJOR 0
|
||||
#define _VERSION_MINOR 0
|
||||
|
@ -10,13 +9,26 @@
|
|||
#define _VERSION_NUMBER _VERSION_MICRO | (_VERSION_MINOR << 6) | (_VERSION_MAJOR << 12)
|
||||
#define _VERSION_STRING "v0.0.1"
|
||||
|
||||
#define _DEBUG 1
|
||||
#define _DEBUG 0
|
||||
#define _DEBUG_SENSORS 0
|
||||
#define _MODBUS 1
|
||||
|
||||
#if _DEBUG == 1
|
||||
#define _print(x) Serial.print(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
|
||||
#define _prints(x) Serial.print(x)
|
||||
#define _printsln(x) Serial.println(x)
|
||||
|
@ -29,6 +41,7 @@
|
|||
#define _println(x)
|
||||
#define _prints(x)
|
||||
#define _printsln(x)
|
||||
#define _printtime()
|
||||
#endif
|
||||
|
||||
#define _REGS_INFRONTOF_EVENTS 6
|
||||
|
@ -57,10 +70,10 @@ extern u16 modbusData[];
|
|||
eventCounter++;\
|
||||
}\
|
||||
}
|
||||
#define _setModbusValue(index, val) modbusData[index] = val
|
||||
//#define _setModbusValue(index, val) modbusData[index] = val
|
||||
#else
|
||||
#define _setModbusValve(index, val)
|
||||
#define _setModbusValue(index, val)
|
||||
//#define _setModbusValue(index, val)
|
||||
#endif // _MODBUS ==
|
||||
|
||||
#define _MODBUS_ADDR_MIN 1
|
||||
|
|
|
@ -58,7 +58,7 @@ void Controller::init(bool startup=false)
|
|||
|
||||
void Controller::process()
|
||||
{
|
||||
if (_initOk && millis() - _lastConversion > _CONVERSION_DELAY) {
|
||||
if (_initOk && millis() - _lastConversion > _TEMP_CONVERSION_DELAY) {
|
||||
_lastConversion = millis();
|
||||
_requestConversion = true;
|
||||
float temp = _dallas.getTempC(_tempAddr1);
|
||||
|
@ -101,7 +101,9 @@ void Controller::process()
|
|||
_setT1Valve(0, stateIdle);
|
||||
_printsln();
|
||||
}
|
||||
_setModbusValue(_MODBUS_T1_INDEX, _vals->t1);
|
||||
#if _MODBUS == 1
|
||||
_averageTemperature1();
|
||||
#endif
|
||||
} else if (_requestConversion) {
|
||||
_requestConversion = false;
|
||||
_dallas.requestTemperatures();
|
||||
|
@ -126,7 +128,9 @@ void Controller::process()
|
|||
_vals->p = (float) _rawP / 1.705f; // 1023 / 6 * 100 (0-5 1/100 bar)
|
||||
_prints(" (Gems), p: "); _prints(_vals->p);
|
||||
}
|
||||
_setModbusValue(_MODBUS_P_INDEX, _vals->p);
|
||||
#if _MODBUS == 1
|
||||
_averagePressure();
|
||||
#endif
|
||||
if (_vals->p != _SENSOR_FAULT && _params->cEn) {
|
||||
switch (_pState) {
|
||||
case stateIdle:
|
||||
|
@ -213,7 +217,81 @@ void Controller::_setPValves(States state)
|
|||
}
|
||||
}
|
||||
|
||||
// uint16_t Controller::_convertFloat(const float &x)
|
||||
// {
|
||||
// return (uint16_t) (x * 100);
|
||||
// }
|
||||
#if _MODBUS == 1
|
||||
void Controller::resetAverageCounters()
|
||||
{
|
||||
_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 "../common.h"
|
||||
|
||||
#define _CONVERSION_DELAY 800
|
||||
#define _TEMP_CONVERSION_DELAY 800
|
||||
#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
|
||||
{
|
||||
|
@ -23,13 +29,21 @@ private:
|
|||
uint8_t _t1Pin;
|
||||
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;
|
||||
DallasTemperature _dallas;
|
||||
DeviceAddress _tempAddr1;
|
||||
|
||||
enum States : uint8_t {
|
||||
stateIdle, stateRising, stateFalling
|
||||
};
|
||||
enum States : uint8_t { stateIdle, stateRising, stateFalling };
|
||||
States _tState = stateIdle;
|
||||
States _pState = stateIdle;
|
||||
|
||||
|
@ -39,11 +53,14 @@ private:
|
|||
unsigned long _lastAnalogRead;
|
||||
uint16_t _rawP;
|
||||
|
||||
// void _setTState(States curr, States next);
|
||||
// void _setPState(States curr, States next);
|
||||
void _setT1Valve(uint8_t, States);
|
||||
void _setPValves(States);
|
||||
// uint16_t _convertFloat(const float &x);
|
||||
|
||||
#if _MODBUS == 1
|
||||
void _averageTemperature1();
|
||||
void _averageTemperature2();
|
||||
void _averagePressure();
|
||||
#endif
|
||||
|
||||
public:
|
||||
Controller(const uint8_t pAnalaogPin,
|
||||
|
@ -61,6 +78,9 @@ private:
|
|||
|
||||
void init(bool startup=false);
|
||||
void process();
|
||||
#if _MODBUS == 1
|
||||
void resetAverageCounters();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // MY_CONTROLLER_H_INCLUDED
|
||||
|
|
|
@ -278,6 +278,7 @@ void Display::_select(const uint8_t selection, const bool restoreCursor=false)
|
|||
|
||||
void Display::_select()
|
||||
{
|
||||
// _printtime("select screen");
|
||||
setFont(_SEL_FONT);
|
||||
setFontRefHeightAll();
|
||||
_inputValueActive = false;
|
||||
|
@ -386,6 +387,7 @@ void Display::_home()
|
|||
bool tState = _vStates->t1;
|
||||
// %u in sprintf() geht nur bis uint16_t
|
||||
String baudStr(_modbusParams->baudrate);
|
||||
// _printtime("homescreen");
|
||||
firstPage();
|
||||
do {
|
||||
setFont(u8g2_font_fub20_tf);
|
||||
|
|
Loading…
Reference in New Issue