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.
		
		
		
		
		
			
		
			
				
					
					
						
							283 lines
						
					
					
						
							8.9 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							283 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
 | |
| 
 |