mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-05 12:11:39 +02:00
Neue Version von Hubi vom 28.04.2022 - siehe:
https://www.mikrocontroller.net/topic/525778?page=4#7048605 ersetzt NRF24_SendRcv Kommentare dazu: - Projekt jetzt umgenannt in HoyDtuSim (Hoymiles DTU Simulation) -Läuft auf Arduino (bei mir auf Pro Mini) und ESP (Wemos D1 mini), je nachdem wie man kompiliert - Channel hopping für senden und Empfangen (poor man's ...) ist eingebaut und bringt konstante Antworten; obige Erkenntnisse über Kanäle abwärts sind noch nicht eingebaut - da manchmal ein Abbruch der RF-Verbindung vorkam (auch schon oben erwähnt) wird jetzt nach ca 50 Sekunden ohne Empfang das RF-Modul neu initialisiert und es geht problemlos weiter - Definitionen für HM-600 und HM-1200 sind implementiert, andere können anhand der beiden Beispiele sicher leicht impl. werden - Anpassungen sind in der Settings.h zu machen
This commit is contained in:
parent
20cd77a6c2
commit
c0140f9fc1
12 changed files with 1959 additions and 0 deletions
283
tools/HoyDtuSim/Inverters.h
Normal file
283
tools/HoyDtuSim/Inverters.h
Normal file
|
@ -0,0 +1,283 @@
|
|||
#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
|
Loading…
Add table
Add a link
Reference in a new issue