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

#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