mirror of https://github.com/lumapu/ahoy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
8.9 KiB
284 lines
8.9 KiB
3 years ago
|
#ifndef __INVERTERS_H
|
||
|
#define __INVERTERS_H
|
||
|
|
||
|
// Ausgabe von Debug Infos auf der seriellen Console
|
||
|
|
||
|
#include "Settings.h"
|
||
|
#include "Debug.h"
|
||
|
|
||
|
|
||
|
typedef struct _NRF24_packet_t {
|
||
|
uint32_t timestamp;
|
||
|
uint8_t packetsLost;
|
||
|
uint8_t rcvChannel;
|
||
|
uint8_t packet[MAX_RF_PAYLOAD_SIZE];
|
||
|
} NRF24_packet_t;
|
||
|
|
||
|
|
||
|
typedef struct _Serial_header_t {
|
||
|
unsigned long timestamp;
|
||
|
uint8_t packetsLost;
|
||
|
uint8_t address[RF_MAX_ADDR_WIDTH]; // MSB first, always RF_MAX_ADDR_WIDTH bytes.
|
||
|
} Serial_header_t;
|
||
|
|
||
|
|
||
|
// structs für Inverter und Kanalwerte
|
||
|
|
||
|
// Liste der Einheiten
|
||
|
enum UNITS {UNIT_V = 0, UNIT_HZ, UNIT_A, UNIT_W, UNIT_WH, UNIT_C, UNIT_KWH, UNIT_MA, UNIT_PCT};
|
||
|
const char* const units[] = {"V", "Hz", "A", "W", "Wh", "°C", "KWh", "mA", "%"};
|
||
|
|
||
|
// CH0 is default channel (freq, ac, temp)
|
||
|
enum CHANNELS {CH0 = 0, CH1, CH2, CH3, CH4};
|
||
|
enum CMDS {CMD01 = 0x01, CMD02, CMD03, CMD83 = 0x83, CMD84};
|
||
|
enum DIVS {DIV1 = 0, DIV10, DIV100, DIV1000};
|
||
|
|
||
|
#define BYTES2 2
|
||
|
#define BYTES4 4
|
||
|
|
||
|
const char UDC[] PROGMEM = "Udc";
|
||
|
const char IDC[] PROGMEM = "Idc";
|
||
|
const char PDC[] PROGMEM = "Pdc";
|
||
|
const char E_WOCHE[] PROGMEM = "E-Woche";
|
||
|
const char E_TOTAL[] PROGMEM = "E-Total";
|
||
|
const char E_TAG[] PROGMEM = "E-Tag";
|
||
|
const char UAC[] PROGMEM = "Uac";
|
||
|
const char FREQ[] PROGMEM = "Freq.ac";
|
||
|
const char PAC[] PROGMEM = "Pac";
|
||
|
const char E_HEUTE[] PROGMEM = "E-heute";
|
||
|
const char IPV[] PROGMEM = "Ipv";
|
||
|
const char WR_TEMP[] PROGMEM = "WR-Temp";
|
||
|
const char PERCNT[] PROGMEM = "Pct";
|
||
|
|
||
|
#define IDX_UDC 0
|
||
|
#define IDX_IDC 1
|
||
|
#define IDX_PDC 2
|
||
|
#define IDX_E_WOCHE 3
|
||
|
#define IDX_E_TOTAL 4
|
||
|
#define IDX_E_TAG 5
|
||
|
#define IDX_UAC 6
|
||
|
#define IDX_FREQ 7
|
||
|
#define IDX_PAC 8
|
||
|
#define IDX_E_HEUTE 9
|
||
|
#define IDX_IPV 10
|
||
|
#define IDX_WR_TEMP 11
|
||
|
#define IDX_PERCNT 12
|
||
|
|
||
|
const char* const NAMES[]
|
||
|
= {UDC, IDC, PDC, E_WOCHE, E_TOTAL, E_TAG, UAC, FREQ, PAC, E_HEUTE, IPV, WR_TEMP, PERCNT};
|
||
|
|
||
|
typedef float (*calcValueFunc)(float *);
|
||
|
|
||
|
struct measureDef_t {
|
||
|
uint8_t nameIdx; //const char* name; // Zeiger auf den Messwertnamen
|
||
|
uint8_t channel; // 0..4,
|
||
|
uint8_t unitIdx; // Index in die Liste der Einheiten 'units'
|
||
|
uint8_t teleId; // Telegramm ID, das was hinter der 2. WR Nummer im Telegramm, 02, 03, 83
|
||
|
uint8_t pos; // ab dieser POsition beginnt der Wert (Big Endian)
|
||
|
uint8_t bytes; // Anzahl der Bytes
|
||
|
uint8_t digits;
|
||
|
};
|
||
|
|
||
|
struct measureCalc_t {
|
||
|
uint8_t nameIdx; //const char* name; // Zeiger auf den Messwertnamen
|
||
|
uint8_t unitIdx; // Index in die Liste der Einheiten 'units'
|
||
|
uint8_t digits;
|
||
|
calcValueFunc f; // die Funktion zur Berechnung von Werten, zb Summe von Werten
|
||
|
};
|
||
|
|
||
|
|
||
|
struct inverter_t {
|
||
|
uint8_t ID; // Inverter-ID = Index
|
||
|
char name[20]; // Name des Inverters zb HM-600.1
|
||
|
uint64_t serialNo; // dier Seriennummer wie im Barcode auf dem WR, also 1141.....
|
||
|
uint64_t RadioId; // die gespiegelte (letzte 4 "Bytes") der Seriennummer
|
||
|
const measureDef_t *measureDef; // aus Include HMxxx.h : Liste mit Definitionen der Messwerte, wie Telgramm, offset, länge, ...
|
||
|
uint8_t anzMeasures; // Länge der Liste
|
||
|
measureCalc_t *measureCalculated; // Liste mit Defintion für berechnete Werte
|
||
|
uint8_t anzMeasureCalculated; // Länge der Liste
|
||
|
uint8_t anzTotalMeasures; // Gesamtanzahl Messwerte
|
||
|
float values[MAX_MEASURE_PER_INV]; // DIE Messewerte
|
||
|
};
|
||
|
|
||
|
|
||
|
char _buffer[20];
|
||
|
|
||
|
uint8_t anzInv = 0;
|
||
|
inverter_t inverters[MAX_ANZ_INV];
|
||
|
|
||
|
union longlongasbytes {
|
||
|
uint64_t ull;
|
||
|
uint32_t ul[2];
|
||
|
uint8_t bytes[8];
|
||
|
};
|
||
|
|
||
|
char *uint64toa (uint64_t s) {
|
||
|
//--------------------------------
|
||
|
//0x1141 72607952ULL
|
||
|
sprintf(_buffer, "%lX%08lX", (unsigned long)(s>>32), (unsigned long)(s&0xFFFFFFFFULL));
|
||
|
return _buffer;
|
||
|
}
|
||
|
|
||
|
|
||
|
uint64_t Serial2RadioID (uint64_t sn) {
|
||
|
//----------------------------------
|
||
|
longlongasbytes llsn;
|
||
|
longlongasbytes res;
|
||
|
llsn.ull = sn;
|
||
|
res.ull = 0;
|
||
|
res.bytes[4] = llsn.bytes[0];
|
||
|
res.bytes[3] = llsn.bytes[1];
|
||
|
res.bytes[2] = llsn.bytes[2];
|
||
|
res.bytes[1] = llsn.bytes[3];
|
||
|
res.bytes[0] = 0x01;
|
||
|
return res.ull;
|
||
|
}
|
||
|
|
||
|
|
||
|
void addInverter (uint8_t _ID, const char * _name, uint64_t _serial,
|
||
|
const measureDef_t * liste, int anzMeasure,
|
||
|
measureCalc_t * calcs, int anzMeasureCalculated) {
|
||
|
//-------------------------------------------------------------------------------------
|
||
|
if (anzInv >= MAX_ANZ_INV) {
|
||
|
DEBUG_OUT.println(F("ANZ_INV zu klein!"));
|
||
|
return;
|
||
|
}
|
||
|
inverter_t *p = &(inverters[anzInv]);
|
||
|
p->ID = _ID;
|
||
|
strcpy (p->name, _name);
|
||
|
p->serialNo = _serial;
|
||
|
p->RadioId = Serial2RadioID(_serial);
|
||
|
p->measureDef = liste;
|
||
|
p->anzMeasures = anzMeasure;
|
||
|
p->anzMeasureCalculated = anzMeasureCalculated;
|
||
|
p->measureCalculated = calcs;
|
||
|
p->anzTotalMeasures = anzMeasure + anzMeasureCalculated;
|
||
|
memset (p->values, 0, sizeof(p->values));
|
||
|
|
||
|
DEBUG_OUT.print (F("WR : ")); DEBUG_OUT.println(anzInv);
|
||
|
DEBUG_OUT.print (F("Type : ")); DEBUG_OUT.println(_name);
|
||
|
DEBUG_OUT.print (F("Serial : ")); DEBUG_OUT.println(uint64toa(_serial));
|
||
|
DEBUG_OUT.print (F("Radio-ID : ")); DEBUG_OUT.println(uint64toa(p->RadioId));
|
||
|
|
||
|
anzInv++;
|
||
|
}
|
||
|
|
||
|
|
||
|
static uint8_t toggle = 0; // nur für Test, ob's auch für mehere WR funzt
|
||
|
uint8_t findInverter (uint8_t *fourbytes) {
|
||
|
//---------------------------------------
|
||
|
for (uint8_t i = 0; i < anzInv; i++) {
|
||
|
longlongasbytes llb;
|
||
|
llb.ull = inverters[i].serialNo;
|
||
|
if (llb.bytes[3] == fourbytes[0] &&
|
||
|
llb.bytes[2] == fourbytes[1] &&
|
||
|
llb.bytes[1] == fourbytes[2] &&
|
||
|
llb.bytes[0] == fourbytes[3] )
|
||
|
{
|
||
|
return i;
|
||
|
//if (toggle) toggle = 0; else toggle = 1; return toggle; // Test ob mehr WR auch geht
|
||
|
}
|
||
|
}
|
||
|
return 0xFF; // nicht gefunden
|
||
|
}
|
||
|
|
||
|
|
||
|
char * error = {"error"};
|
||
|
|
||
|
char *getMeasureName (uint8_t wr, uint8_t i){
|
||
|
//------------------------------------------
|
||
|
inverter_t *p = &(inverters[wr]);
|
||
|
if (i >= p->anzTotalMeasures) return error;
|
||
|
uint8_t idx, channel = 0;
|
||
|
if (i < p->anzMeasures) {
|
||
|
idx = p->measureDef[i].nameIdx;
|
||
|
channel = p->measureDef[i].channel;
|
||
|
}
|
||
|
else {
|
||
|
idx = p->measureCalculated[i - p->anzMeasures].nameIdx;
|
||
|
}
|
||
|
char tmp[20];
|
||
|
strcpy_P (_buffer, NAMES[idx]);
|
||
|
if (channel) {
|
||
|
sprintf_P (tmp, PSTR(".CH%d"), channel);
|
||
|
strcat(_buffer,tmp);
|
||
|
}
|
||
|
return _buffer;
|
||
|
}
|
||
|
|
||
|
const char *getUnit (uint8_t wr, uint8_t i) {
|
||
|
//------------------------------------------
|
||
|
inverter_t *p = &(inverters[wr]);
|
||
|
if (i >= p->anzTotalMeasures) return error;
|
||
|
uint8_t idx;
|
||
|
if (i < p->anzMeasures)
|
||
|
idx = p->measureDef[i].unitIdx;
|
||
|
else
|
||
|
idx = p->measureCalculated[i-p->anzMeasures].unitIdx;
|
||
|
|
||
|
//strcpy (_buffer, units[i]);
|
||
|
//return _buffer;
|
||
|
return units[idx];
|
||
|
}
|
||
|
|
||
|
|
||
|
float getMeasureValue (uint8_t wr, uint8_t i) {
|
||
|
//------------------------------------------
|
||
|
if (i >= inverters[wr].anzTotalMeasures) return 0.0;
|
||
|
return inverters[wr].values[i];
|
||
|
}
|
||
|
|
||
|
|
||
|
int getDivisor (uint8_t wr, uint8_t i) {
|
||
|
//------------------------------------
|
||
|
inverter_t *p = &(inverters[wr]);
|
||
|
if (i >= p->anzTotalMeasures) return 1;
|
||
|
if (i < p->anzMeasures) {
|
||
|
uint8_t digits = p->measureDef[i].digits;
|
||
|
if (digits == DIV1) return 1;
|
||
|
if (digits == DIV10) return 10;
|
||
|
if (digits == DIV100) return 100;
|
||
|
if (digits == DIV1000) return 1000;
|
||
|
return 1;
|
||
|
}
|
||
|
else
|
||
|
return p->measureCalculated[i].digits;
|
||
|
}
|
||
|
|
||
|
|
||
|
uint8_t getDigits (uint8_t wr, uint8_t i) {
|
||
|
//---------------------------------------
|
||
|
inverter_t *p = &(inverters[wr]);
|
||
|
if (i >= p->anzTotalMeasures) return 0;
|
||
|
if (i < p->anzMeasures)
|
||
|
return p->measureDef[i].digits;
|
||
|
else
|
||
|
return p->measureCalculated[i-p->anzMeasures].digits;
|
||
|
}
|
||
|
|
||
|
// +++++++++++++++++++++++++++++++++++ Inverter ++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
#include "HM600.h" // für HM-600 und HM-700
|
||
|
|
||
|
#include "HM1200.h"
|
||
|
|
||
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
|
||
|
|
||
|
void setupInverts() {
|
||
|
//-----------------
|
||
|
|
||
|
addInverter (0,"HM-600", 0x114172607952ULL,
|
||
|
hm600_measureDef, HM600_MEASURE_LIST_LEN, // Tabelle der Messwerte
|
||
|
hm600_measureCalc, HM600_CALCED_LIST_LEN); // Tabelle berechnete Werte
|
||
|
|
||
|
/*
|
||
|
addInverter (1,"HM-1200", 0x114172607952ULL,
|
||
|
hm1200_measureDef, HM1200_MEASURE_LIST_LEN, // Tabelle der Messwerte
|
||
|
hm1200_measureCalc, HM1200_CALCED_LIST_LEN); // Tabelle berechnete Werte
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|