├── CalibrationRegs.xlsx ├── docs ├── CalibrationRegs.xlsx ├── Test_ATM90E36.psimsch ├── Atmel-46004-SE-M90E36A-Datasheet.pdf └── Atmel-46104-SE-M90E36A- ApplicationNote .pdf ├── keywords.txt ├── examples ├── ATM90E36_Basic │ └── ATM90E36_Basic.ino └── ATM90E36_OLED │ └── ATM90E36_OLED.ino ├── ATM90E36.h └── ATM90E36.cpp /CalibrationRegs.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CircuitSetup/ATM90E36/master/CalibrationRegs.xlsx -------------------------------------------------------------------------------- /docs/CalibrationRegs.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CircuitSetup/ATM90E36/master/docs/CalibrationRegs.xlsx -------------------------------------------------------------------------------- /docs/Test_ATM90E36.psimsch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CircuitSetup/ATM90E36/master/docs/Test_ATM90E36.psimsch -------------------------------------------------------------------------------- /docs/Atmel-46004-SE-M90E36A-Datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CircuitSetup/ATM90E36/master/docs/Atmel-46004-SE-M90E36A-Datasheet.pdf -------------------------------------------------------------------------------- /docs/Atmel-46104-SE-M90E36A- ApplicationNote .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CircuitSetup/ATM90E36/master/docs/Atmel-46104-SE-M90E36A- ApplicationNote .pdf -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For ATM90E36 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | ATM90E36 KEYWORD1 9 | ####################################### 10 | # Methods and Functions (KEYWORD2) 11 | ####################################### 12 | 13 | begin KEYWORD2 14 | 15 | GetLineVoltageA KEYWORD2 16 | GetLineVoltageB KEYWORD2 17 | GetLineVoltageC KEYWORD2 18 | 19 | GetLineCurrentA KEYWORD2 20 | GetLineCurrentB KEYWORD2 21 | GetLineCurrentC KEYWORD2 22 | GetLineCurrentN KEYWORD2 23 | 24 | GetActivePowerA KEYWORD2 25 | GetActivePowerB KEYWORD2 26 | GetActivePowerC KEYWORD2 27 | GetTotalActivePower KEYWORD2 28 | 29 | GetReactivePowerA KEYWORD2 30 | GetReactivePowerB KEYWORD2 31 | GetReactivePowerC KEYWORD2 32 | GetTotalReactivePower KEYWORD2 33 | 34 | GetApparentPowerA KEYWORD2 35 | GetApparentPowerB KEYWORD2 36 | GetApparentPowerC KEYWORD2 37 | GetTotalApparentPower KEYWORD2 38 | 39 | GetFrequency KEYWORD2 40 | GetTemperature KEYWORD2 41 | 42 | GetPowerFactorA KEYWORD2 43 | GetPowerFactorB KEYWORD2 44 | GetPowerFactorC KEYWORD2 45 | GetTotalPowerFactor KEYWORD2 46 | 47 | GetPhaseA KEYWORD2 48 | GetPhaseB KEYWORD2 49 | GetPhaseC KEYWORD2 50 | 51 | GetValueRegister KEYWORD2 52 | 53 | SetVoltageGainA KEYWORD2 54 | SetVoltageGainB KEYWORD2 55 | SetVoltageGainC KEYWORD2 56 | 57 | SetCurrentGainA KEYWORD2 58 | SetCurrentGainB KEYWORD2 59 | SetCurrentGainC KEYWORD2 60 | SetCurrentGainN KEYWORD2 61 | 62 | GetImportEnergy KEYWORD2 63 | GetExportEnergy KEYWORD2 64 | GetSysStatus0 KEYWORD2 65 | GetSysStatus1 KEYWORD2 66 | GetMeterStatus0 KEYWORD2 67 | GetMeterStatus1 KEYWORD2 68 | 69 | ####################################### 70 | # Constants (LITERAL1) 71 | ####################################### 72 | 73 | WRITE LITERAL1 74 | READ LITERAL1 75 | 76 | -------------------------------------------------------------------------------- /examples/ATM90E36_Basic/ATM90E36_Basic.ino: -------------------------------------------------------------------------------- 1 | /* ATM90E36 Energy Monitor Demo Application 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2016 whatnick and Ryzee 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | */ 13 | #include 14 | #include 15 | 16 | ATM90E36 eic(10); 17 | 18 | void setup() { 19 | /* Initialize the serial port to host */ 20 | Serial.begin(115200); 21 | while (!Serial) { 22 | ; // wait for serial port to connect. Needed for native USB 23 | } 24 | Serial.println("Start ATM90E36"); 25 | /*Initialise the ATM90E36 + SPI port */ 26 | eic.begin(); 27 | delay(1000); 28 | } 29 | 30 | 31 | 32 | void loop() { 33 | 34 | /*Repeatedly fetch some values from the ATM90E36 */ 35 | double voltageA,freq,voltageB,voltageC,currentA,currentB,currentC,power,pf,new_current,new_power; 36 | int sys0=eic.GetSysStatus0(); 37 | int sys1=eic.GetSysStatus1(); 38 | int en0=eic.GetMeterStatus0(); 39 | int en1=eic.GetMeterStatus1(); 40 | Serial.println("S0:0x"+String(sys0,HEX)); 41 | delay(10); 42 | Serial.println("S1:0x"+String(sys1,HEX)); 43 | delay(10); 44 | Serial.println("E0:0x"+String(en0,HEX)); 45 | delay(10); 46 | Serial.println("E1:0x"+String(en1,HEX)); 47 | voltageA=eic.GetLineVoltageA(); 48 | Serial.println("VA:"+String(voltageA)+"V"); 49 | voltageB=eic.GetLineVoltageB(); 50 | Serial.println("VB:"+String(voltageB)+"V"); 51 | voltageC=eic.GetLineVoltageC(); 52 | Serial.println("VC:"+String(voltageC)+"V"); 53 | delay(10); 54 | currentA = eic.GetLineCurrentA(); 55 | Serial.println("IA:"+String(currentA)+"A"); 56 | currentB = eic.GetLineCurrentB(); 57 | Serial.println("IB:"+String(currentB)+"A"); 58 | currentC = eic.GetLineCurrentC(); 59 | Serial.println("IC:"+String(currentC)+"A"); 60 | delay(10); 61 | freq=eic.GetFrequency(); 62 | delay(10); 63 | Serial.println("f"+String(freq)+"Hz"); 64 | delay(1000); 65 | } 66 | -------------------------------------------------------------------------------- /examples/ATM90E36_OLED/ATM90E36_OLED.ino: -------------------------------------------------------------------------------- 1 | /* ATM90E36 Energy Monitor Demo Application 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2016 whatnick and Ryzee 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define OLED_RESET 4 20 | Adafruit_SSD1306 display(OLED_RESET); 21 | 22 | ATM90E36 eics[2] = {ATM90E36(10),ATM90E36(9)}; 23 | 24 | void setup() { 25 | /* Initialize the serial port to host */ 26 | Serial.begin(115200); 27 | while (!Serial) { 28 | ; // wait for serial port to connect. Needed for native USB 29 | } 30 | Serial.println("Start ATM90E36"); 31 | // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) 32 | display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32) 33 | // init done 34 | 35 | // Show image buffer on the display hardware. 36 | // Since the buffer is intialized with an Adafruit splashscreen 37 | // internally, this will display the splashscreen. 38 | display.display(); 39 | display.setTextSize(1); 40 | display.setTextColor(WHITE); 41 | display.setCursor(0,0); 42 | /*Initialise the ATM90E36 + SPI port */ 43 | eics[0].begin(); 44 | delay(1000); 45 | eics[1].begin(); 46 | delay(1000); 47 | } 48 | 49 | void scanEic(ATM90E36 eic) 50 | { 51 | double voltageA,freq,voltageB,voltageC,currentA,currentB,currentC,power,pf,new_current,new_power; 52 | int sys0=eic.GetSysStatus0(); 53 | int sys1=eic.GetSysStatus1(); 54 | int en0=eic.GetMeterStatus0(); 55 | int en1=eic.GetMeterStatus1(); 56 | Serial.println("S0:0x"+String(sys0,HEX)); 57 | delay(10); 58 | Serial.println("S1:0x"+String(sys1,HEX)); 59 | delay(10); 60 | Serial.println("E0:0x"+String(en0,HEX)); 61 | delay(10); 62 | Serial.println("E1:0x"+String(en1,HEX)); 63 | display.clearDisplay(); 64 | display.setCursor(0,0); 65 | voltageA=eic.GetLineVoltageA(); 66 | Serial.println("VA:"+String(voltageA)+"V"); 67 | display.println("VA:"+String(voltageA)+"V"); 68 | voltageB=eic.GetLineVoltageB(); 69 | Serial.println("VB:"+String(voltageB)+"V"); 70 | display.println("VB:"+String(voltageB)+"V"); 71 | voltageC=eic.GetLineVoltageC(); 72 | Serial.println("VC:"+String(voltageC)+"V"); 73 | display.println("VC:"+String(voltageC)+"V"); 74 | delay(10); 75 | currentA = eic.GetLineCurrentA(); 76 | Serial.println("IA:"+String(currentA)+"A"); 77 | currentB = eic.GetLineCurrentB(); 78 | Serial.println("IB:"+String(currentB)+"A"); 79 | currentC = eic.GetLineCurrentC(); 80 | Serial.println("IC:"+String(currentC)+"A"); 81 | delay(10); 82 | freq=eic.GetFrequency(); 83 | delay(10); 84 | Serial.println("f"+String(freq)+"Hz"); 85 | display.println("f"+String(freq)+"Hz"); 86 | display.display(); 87 | delay(1000); 88 | } 89 | 90 | 91 | void loop() { 92 | /*Repeatedly fetch some values from the ATM90E36 */ 93 | scanEic(eics[0]); 94 | scanEic(eics[1]); 95 | } 96 | -------------------------------------------------------------------------------- /ATM90E36.h: -------------------------------------------------------------------------------- 1 | #ifndef ATM90E36_h 2 | #define ATM90E36_h 3 | #include 4 | #include 5 | 6 | #define WRITE 0 // WRITE SPI 7 | #define READ 1 // READ SPI 8 | #define DEBUG_SERIAL 1 9 | 10 | /* STATUS REGISTERS */ 11 | #define SoftReset 0x00 // Software Reset 12 | #define SysStatus0 0x01 // System Status0 13 | #define SysStatus1 0x02 // System Status1 14 | #define FuncEn0 0x03 // Function Enable0 15 | #define FuncEn1 0x04 // Function Enable1 16 | #define ZXConfig 0x07 // Zero-Crossing Config 17 | #define SagTh 0x08 // Voltage Sag Th 18 | #define PhaseLossTh 0x09 // Voltage Phase Losing Th 19 | #define INWarnTh0 0x0A // N Current Line Th 20 | #define INWarnTh1 0x0B // Voltage ADC Th 21 | #define THDNUTh 0x0C // Voltage THD Th 22 | #define THDNITh 0x0D // Current THD Th 23 | #define DMACtrl 0x0E // DMA Int. Control 24 | #define LastSPIData 0x0F // Last Read/Write SPI Value 25 | 26 | /* LOW POWER MODE REGISTERS - NOT USED */ 27 | #define DetectCtrl 0x10 28 | #define DetectTh1 0x11 29 | #define DetectTh2 0x12 30 | #define DetectTh3 0x13 31 | #define PMOffsetA 0x14 32 | #define PMOffsetB 0x15 33 | #define PMOffsetC 0x16 34 | #define PMPGA 0x17 35 | #define PMIrmsA 0x18 36 | #define PMIrmsB 0x19 37 | #define PMIrmsC 0x1A 38 | #define PMConfig 0x10B 39 | #define PMAvgSamples 0x1C 40 | #define PMIrmsLSB 0x1D 41 | 42 | /* CONFIGURATION REGISTERS */ 43 | #define ConfigStart 0x30 // Configuration Start 44 | #define PLconstH 0x31 // High Word of PL_Constant 45 | #define PLconstL 0x32 // Low Word of PL_Constant 46 | #define MMode0 0x33 // Metering Mode Config 47 | #define MMode1 0x34 // Metering Mode Config 48 | #define PStartTh 0x35 // Startup Power Th (P) 49 | #define QStartTh 0x36 // Startup Power Th (Q) 50 | #define SStartTh 0x37 // Startup Power Th (S) 51 | #define PPhaseTh 0x38 // Startup Power Accum Th (P) 52 | #define QPhaseTh 0x39 // Startup Power Accum Th (Q) 53 | #define SPhaseTh 0x3A // Startup Power Accum Th (S) 54 | #define CSZero 0x3B // Checksum 0 55 | 56 | /* CALIBRATION REGISTERS */ 57 | #define CalStart 0x40 // Cal Start 58 | #define PoffsetA 0x41 // A Line Power Offset (P) 59 | #define QoffsetA 0x42 // A Line Power Offset (Q) 60 | #define PoffsetB 0x43 // B Line Power Offset (P) 61 | #define QoffsetB 0x44 // B Line Power Offset (Q) 62 | #define PoffsetC 0x45 // C Line Power Offset (P) 63 | #define QoffsetC 0x46 // C Line Power Offset (Q) 64 | #define GainA 0x47 // A Line Calibration Gain 65 | #define PhiA 0x48 // A Line Calibration Angle 66 | #define GainB 0x49 // B Line Calibration Gain 67 | #define PhiB 0x4A // B Line Calibration Angle 68 | #define GainC 0x4B // C Line Calibration Gain 69 | #define PhiC 0x4C // C Line Calibration Angle 70 | #define CSOne 0x4D // Checksum 1 71 | 72 | /* HARMONIC & ENERGY REGISTERS */ 73 | #define HarmStart 0x50 // Harmonic Cal Start 74 | #define POffsetAF 0x51 // A Fund Power Offset (P) 75 | #define POffsetBF 0x52 // B Fund Power Offset (P) 76 | #define POffsetCF 0x53 // C Fund Power Offset (P) 77 | #define PGainAF 0x54 // A Fund Power Gain (P) 78 | #define PGainBF 0x55 // B Fund Power Gain (P) 79 | #define PGainCF 0x56 // C Fund Power Gain (P) 80 | #define CSTwo 0x57 // Checksum 2 81 | 82 | /* MEASUREMENT CALIBRATION REGISTERS */ 83 | #define AdjStart 0x60 // Measurement Cal Start 84 | #define UgainA 0x61 // A Voltage RMS Gain 85 | #define IgainA 0x62 // A Current RMS Gain 86 | #define UoffsetA 0x63 // A Voltage Offset 87 | #define IoffsetA 0x64 // A Current Offset 88 | #define UgainB 0x65 // B Voltage RMS Gain 89 | #define IgainB 0x66 // B Current RMS Gain 90 | #define UoffsetB 0x67 // B Voltage Offset 91 | #define IoffsetB 0x68 // B Current Offset 92 | #define UgainC 0x69 // C Voltage RMS Gain 93 | #define IgainC 0x6A // C Current RMS Gain 94 | #define UoffsetC 0x6B // C Voltage Offset 95 | #define IoffsetC 0x6C // C Current Offset 96 | #define IgainN 0x6D // N Current Gain 97 | #define IoffsetN 0x6E // N Current Offset 98 | #define CSThree 0x6F // Checksum 3 99 | 100 | /* ENERGY REGISTERS */ 101 | #define APenergyT 0x80 // Total Forward Active 102 | #define APenergyA 0x81 // A Forward Active 103 | #define APenergyB 0x82 // B Forward Active 104 | #define APenergyC 0x83 // C Forward Active 105 | #define ANenergyT 0x84 // Total Reverse Active 106 | #define ANenergyA 0x85 // A Reverse Active 107 | #define ANenergyB 0x86 // B Reverse Active 108 | #define ANenergyC 0x87 // C Reverse Active 109 | #define RPenergyT 0x88 // Total Forward Reactive 110 | #define RPenergyA 0x89 // A Forward Reactive 111 | #define RPenergyB 0x8A // B Forward Reactive 112 | #define RPenergyC 0x8B // C Forward Reactive 113 | #define RNenergyT 0x8C // Total Reverse Reactive 114 | #define RNenergyA 0x8D // A Reverse Reactive 115 | #define RNenergyB 0x8E // B Reverse Reactive 116 | #define RNenergyC 0x8F // C Reverse Reactive 117 | 118 | #define SAenergyT 0x90 // Total Apparent Energy 119 | #define SenergyA 0x91 // A Apparent Energy 120 | #define SenergyB 0x92 // B Apparent Energy 121 | #define SenergyC 0x93 // C Apparent Energy 122 | #define SVenergyT 0x94 // Total Apparent Energy (Arit) 123 | 124 | #define EnStatus0 0x95 // Metering Status 0 125 | #define EnStatus1 0x96 // Metering Status 1 126 | ///////////////// 0x97 // Reserved Register 127 | #define SVmeanT 0x98 // Total Apparent Energy (Vect) 128 | #define SVmeanTLSB 0x99 // LSB of Vector Sum 129 | 130 | /* FUNDAMENTAL / HARMONIC ENERGY REGISTERS */ 131 | #define APenergyTF 0xA0 // Total Forward Fund. Energy 132 | #define APenergyAF 0xA1 // A Forward Fund. Energy 133 | #define APenergyBF 0xA2 // B Forward Fund. Energy 134 | #define APenergyCF 0xA3 // C Forward Fund. Energy 135 | #define ANenergyTF 0xA4 // Total Reverse Fund Energy 136 | #define ANenergyAF 0xA5 // A Reverse Fund. Energy 137 | #define ANenergyBF 0xA6 // B Reverse Fund. Energy 138 | #define ANenergyCF 0xA7 // C Reverse Fund. Energy 139 | #define APenergyTH 0xA8 // Total Forward Harm. Energy 140 | #define APenergyAH 0xA9 // A Forward Harm. Energy 141 | #define APenergyBH 0xAA // B Forward Harm. Energy 142 | #define APenergyCH 0xAB // C Forward Harm. Energy 143 | #define ANenergyTH 0xAC // Total Reverse Harm. Energy 144 | #define ANenergyAH 0xAD // A Reverse Harm. Energy 145 | #define ANenergyBH 0xAE // B Reverse Harm. Energy 146 | #define ANenergyCH 0xAF // C Reverse Harm. Energy 147 | 148 | /* POWER & P.F. REGISTERS */ 149 | #define PmeanT 0xB0 // Total Mean Power (P) 150 | #define PmeanA 0xB1 // A Mean Power (P) 151 | #define PmeanB 0xB2 // B Mean Power (P) 152 | #define PmeanC 0xB3 // C Mean Power (P) 153 | #define QmeanT 0xB4 // Total Mean Power (Q) 154 | #define QmeanA 0xB5 // A Mean Power (Q) 155 | #define QmeanB 0xB6 // B Mean Power (Q) 156 | #define QmeanC 0xB7 // C Mean Power (Q) 157 | #define SmeanT 0xB8 // Total Mean Power (S) 158 | #define SmeanA 0xB9 // A Mean Power (S) 159 | #define SmeanB 0xBA // B Mean Power (S) 160 | #define SmeanC 0xBB // C Mean Power (S) 161 | #define PFmeanT 0xBC // Mean Power Factor 162 | #define PFmeanA 0xBD // A Power Factor 163 | #define PFmeanB 0xBE // B Power Factor 164 | #define PFmeanC 0xBF // C Power Factor 165 | 166 | #define PmeanTLSB 0xC0 // Lower Word (Tot. Act. Power) 167 | #define PmeanALSB 0xC1 // Lower Word (A Act. Power) 168 | #define PmeanBLSB 0xC2 // Lower Word (B Act. Power) 169 | #define PmeanCLSB 0xC3 // Lower Word (C Act. Power) 170 | #define QmeanTLSB 0xC4 // Lower Word (Tot. React. Power) 171 | #define QmeanALSB 0xC5 // Lower Word (A React. Power) 172 | #define QmeanBLSB 0xC6 // Lower Word (B React. Power) 173 | #define QmeanCLSB 0xC7 // Lower Word (C React. Power) 174 | #define SAmeanTLSB 0xC8 // Lower Word (Tot. App. Power) 175 | #define SmeanALSB 0xC9 // Lower Word (A App. Power) 176 | #define SmeanBLSB 0xCA // Lower Word (B App. Power) 177 | #define SmeanCLSB 0xCB // Lower Word (C App. Power) 178 | 179 | /* FUND/HARM POWER & V/I RMS REGISTERS */ 180 | #define PmeanTF 0xD0 // Total Active Fund. Power 181 | #define PmeanAF 0xD1 // A Active Fund. Power 182 | #define PmeanBF 0xD2 // B Active Fund. Power 183 | #define PmeanCF 0xD3 // C Active Fund. Power 184 | #define PmeanTH 0xD4 // Total Active Harm. Power 185 | #define PmeanAH 0xD5 // A Active Harm. Power 186 | #define PmeanBH 0xD6 // B Active Harm. Power 187 | #define PmeanCH 0xD7 // C Active Harm. Power 188 | #define IrmsN1 0xD8 // N Sampled Current 189 | #define UrmsA 0xD9 // A RMS Voltage 190 | #define UrmsB 0xDA // B RMS Voltage 191 | #define UrmsC 0xDB // C RMS Voltage 192 | #define IrmsN0 0xDC // N Calculated Current 193 | #define IrmsA 0xDD // A RMS Current 194 | #define IrmsB 0xDE // B RMS Current 195 | #define IrmsC 0xDF // C RMS Current 196 | 197 | #define PmeanTFLSB 0xE0 // Lower Word (Tot. Act. Fund. Power) 198 | #define PmeanAFLSB 0xE1 // Lower Word (A Act. Fund. Power) 199 | #define PmeanBFLSB 0xE2 // Lower Word (B Act. Fund. Power) 200 | #define PmeanCFLSB 0xE3 // Lower Word (C Act. Fund. Power) 201 | #define PmeanTHLSB 0xE4 // Lower Word (Tot. Act. Harm. Power) 202 | #define PmeanAHLSB 0xE5 // Lower Word (A Act. Harm. Power) 203 | #define PmeanBHLSB 0xE6 // Lower Word (B Act. Harm. Power) 204 | #define PmeanCHLSB 0xE7 // Lower Word (C Act. Harm. Power) 205 | ///////////////// 0xE8 // Reserved Register 206 | #define UrmsALSB 0xE9 // Lower Word (A RMS Voltage) 207 | #define UrmsBLSB 0xEA // Lower Word (B RMS Voltage) 208 | #define UrmsCLSB 0xEB // Lower Word (C RMS Voltage) 209 | ///////////////// 0xEC // Reserved Register 210 | #define IrmsALSB 0xED // Lower Word (A RMS Current) 211 | #define IrmsBLSB 0xEE // Lower Word (B RMS Current) 212 | #define IrmsCLSB 0xEF // Lower Word (C RMS Current) 213 | 214 | /* THD, FREQUENCY, ANGLE & TEMP REGISTERS*/ 215 | #define THDNUA 0xF1 // A Voltage THD+N 216 | #define THDNUB 0xF2 // B Voltage THD+N 217 | #define THDNUC 0xF3 // C Voltage THD+N 218 | ///////////////// 0xF4 // Reserved Register 219 | #define THDNIA 0xF5 // A Current THD+N 220 | #define THDNIB 0xF6 // B Current THD+N 221 | #define THDNIC 0xF7 // V Current THD+N 222 | #define Freq 0xF8 // Frequency 223 | #define PAngleA 0xF9 // A Mean Phase Angle 224 | #define PAngleB 0xFA // B Mean Phase Angle 225 | #define PAngleC 0xFB // C Mean Phase Angle 226 | #define Temp 0xFC // Measured Temperature 227 | #define UangleA 0xFD // A Voltage Phase Angle 228 | #define UangleB 0xFE // B Voltage Phase Angle 229 | #define UangleC 0xFF // C Voltage Phase Angle 230 | 231 | class ATM90E36 232 | { 233 | private: 234 | unsigned short CommEnergyIC(unsigned char RW, unsigned short address, unsigned short val); 235 | int _energy_CS; 236 | unsigned short _lineFreq; 237 | unsigned short _pgagain; 238 | unsigned short _ugain; 239 | unsigned short _igainA; 240 | unsigned short _igainB; 241 | unsigned short _igainC; 242 | unsigned short _igainN; 243 | int Read32Register(signed short regh_addr, signed short regl_addr); 244 | public: 245 | /* Construct */ 246 | ATM90E36(void); 247 | /* Destruct */ 248 | ~ATM90E36(void); 249 | 250 | /* Initialization Functions */ 251 | void begin(int pin, unsigned short lineFreq, unsigned short pgagain, unsigned short ugain, unsigned short igainA, unsigned short igainB, unsigned short igainC, unsigned short igainN); 252 | uint16_t checkSum(int start, int end); 253 | 254 | /* Main Electrical Parameters (GET)*/ 255 | double GetLineVoltageA(); 256 | double GetLineVoltageB(); 257 | double GetLineVoltageC(); 258 | 259 | double GetLineCurrentA(); 260 | double GetLineCurrentB(); 261 | double GetLineCurrentC(); 262 | double GetLineCurrentN(); 263 | double GetCalcLineCurrentN(); 264 | 265 | double GetActivePowerA(); 266 | double GetActivePowerB(); 267 | double GetActivePowerC(); 268 | double GetTotalActivePower(); 269 | 270 | double GetReactivePowerA(); 271 | double GetReactivePowerB(); 272 | double GetReactivePowerC(); 273 | double GetTotalReactivePower(); 274 | 275 | double GetApparentPowerA(); 276 | double GetApparentPowerB(); 277 | double GetApparentPowerC(); 278 | double GetTotalApparentPower(); 279 | 280 | double GetFrequency(); 281 | 282 | double GetPowerFactorA(); 283 | double GetPowerFactorB(); 284 | double GetPowerFactorC(); 285 | double GetTotalPowerFactor(); 286 | 287 | double GetVHarmA(); 288 | double GetVHarmB(); 289 | double GetVHarmC(); 290 | 291 | double GetCHarmA(); 292 | double GetCHarmB(); 293 | double GetCHarmC(); 294 | 295 | double GetPhaseA(); 296 | double GetPhaseB(); 297 | double GetPhaseC(); 298 | 299 | double GetTemperature(); 300 | 301 | /* Gain Parameters (GET)*/ 302 | unsigned short GetValueRegister(unsigned short registerRead); 303 | 304 | /* Energy Consumption */ 305 | double GetImportEnergy(); 306 | double GetExportEnergy(); 307 | 308 | /* System Status */ 309 | unsigned short GetSysStatus0(); 310 | unsigned short GetSysStatus1(); 311 | unsigned short GetMeterStatus0(); 312 | unsigned short GetMeterStatus1(); 313 | 314 | /* Checksum Function */ 315 | bool calibrationError(); 316 | }; 317 | #endif -------------------------------------------------------------------------------- /ATM90E36.cpp: -------------------------------------------------------------------------------- 1 | #include "ATM90E36.h" 2 | 3 | ATM90E36::ATM90E36(void){ 4 | } 5 | 6 | ATM90E36::~ATM90E36() { 7 | // end 8 | } 9 | 10 | /* CommEnergyIC - Communication Establishment */ 11 | /* 12 | - Defines Register Mask 13 | - Treats the Register and SPI Comms 14 | - Outputs the required value in the register 15 | */ 16 | unsigned short ATM90E36::CommEnergyIC(unsigned char RW, unsigned short address, unsigned short val) 17 | { 18 | unsigned char* data = (unsigned char*)&val; 19 | unsigned char* adata = (unsigned char*)&address; 20 | unsigned short output; 21 | unsigned short address1; 22 | 23 | // Slows the SPI interface to communicate 24 | #if !defined(ENERGIA) && !defined(ESP8266) && !defined(ESP32) && !defined(ARDUINO_ARCH_SAMD) 25 | SPISettings settings(200000, MSBFIRST, SPI_MODE0); 26 | #endif 27 | 28 | #if defined(ESP8266) 29 | SPISettings settings(200000, MSBFIRST, SPI_MODE2); 30 | #endif 31 | 32 | #if defined(ESP32) 33 | SPISettings settings(200000, MSBFIRST, SPI_MODE3); 34 | #endif 35 | 36 | #if defined(ARDUINO_ARCH_SAMD) 37 | SPISettings settings(400000, MSBFIRST, SPI_MODE3); 38 | #endif 39 | 40 | // Switch MSB and LSB of value 41 | output = (val >> 8) | (val << 8); 42 | val = output; 43 | 44 | // Set R/W flag 45 | address |= RW << 15; 46 | 47 | // Swap byte address 48 | address1 = (address >> 8) | (address << 8); 49 | address = address1; 50 | 51 | // Transmit & Receive Data 52 | #if !defined(ENERGIA) 53 | SPI.beginTransaction(settings); 54 | #endif 55 | 56 | // Chip enable and wait for SPI activation 57 | digitalWrite (_energy_CS, LOW); 58 | delayMicroseconds(10); 59 | 60 | // Write address byte by byte 61 | for (byte i=0; i<2; i++) 62 | { 63 | SPI.transfer (*adata); 64 | adata++; 65 | } 66 | 67 | /* Must wait 4 us for data to become valid */ 68 | delayMicroseconds(4); 69 | 70 | // READ Data 71 | // Do for each byte in transfer 72 | if (RW) 73 | { 74 | for (byte i=0; i<2; i++) 75 | { 76 | *data = SPI.transfer (0x00); 77 | data++; 78 | } 79 | } 80 | else 81 | { 82 | for (byte i=0; i<2; i++) 83 | { 84 | SPI.transfer(*data); 85 | data++; 86 | } 87 | } 88 | 89 | // Chip enable and wait for transaction to end 90 | digitalWrite(_energy_CS, HIGH); 91 | delayMicroseconds(10); 92 | #if !defined(ENERGIA) 93 | SPI.endTransaction(); 94 | #endif 95 | 96 | output = (val >> 8) | (val << 8); // reverse MSB and LSB 97 | return output; 98 | } 99 | 100 | int ATM90E36::Read32Register(signed short regh_addr, signed short regl_addr) { 101 | int val, val_h, val_l; 102 | val_h = CommEnergyIC(READ, regh_addr, 0xFFFF); 103 | val_l = CommEnergyIC(READ, regl_addr, 0xFFFF); 104 | val = CommEnergyIC(READ, regh_addr, 0xFFFF); 105 | 106 | val = val_h << 16; 107 | val |= val_l; //concatenate the 2 registers to make 1 32 bit number 108 | 109 | return (val); 110 | } 111 | 112 | /* Parameters Functions*/ 113 | /* 114 | - Gets main electrical parameters, 115 | such as: Voltage, Current, Power, Energy, 116 | and Frequency 117 | - Also gets the temperature 118 | */ 119 | // VOLTAGE 120 | double ATM90E36::GetLineVoltageA() { 121 | unsigned short voltage = CommEnergyIC(READ, UrmsA, 0xFFFF); 122 | return (double)voltage / 100; 123 | } 124 | 125 | double ATM90E36::GetLineVoltageB() { 126 | unsigned short voltage = CommEnergyIC(READ, UrmsB, 0xFFFF); 127 | return (double)voltage / 100; 128 | } 129 | 130 | double ATM90E36::GetLineVoltageC() { 131 | unsigned short voltage = CommEnergyIC(READ, UrmsC, 0xFFFF); 132 | return (double)voltage / 100; 133 | } 134 | 135 | // CURRENT 136 | double ATM90E36::GetLineCurrentA() { 137 | unsigned short current = CommEnergyIC(READ, IrmsA, 0xFFFF); 138 | return (double)current / 1000; 139 | } 140 | double ATM90E36::GetLineCurrentB() { 141 | unsigned short current = CommEnergyIC(READ, IrmsB, 0xFFFF); 142 | return (double)current / 1000; 143 | } 144 | double ATM90E36::GetLineCurrentC() { 145 | unsigned short current = CommEnergyIC(READ, IrmsC, 0xFFFF); 146 | return (double)current / 1000; 147 | } 148 | double ATM90E36::GetLineCurrentN() { 149 | unsigned short current = CommEnergyIC(READ, IrmsN1, 0xFFFF); 150 | return (double)current / 1000; 151 | } 152 | double ATM90E36::GetCalcLineCurrentN() { 153 | unsigned short current = CommEnergyIC(READ, IrmsN0, 0xFFFF); 154 | return (double)current / 1000; 155 | } 156 | 157 | // ACTIVE POWER 158 | double ATM90E36::GetActivePowerA() { 159 | signed short apower = (signed short) CommEnergyIC(READ, PmeanA, 0xFFFF); 160 | return (double)apower / 1000; 161 | } 162 | double ATM90E36::GetActivePowerB() { 163 | signed short apower = (signed short) CommEnergyIC(READ, PmeanB, 0xFFFF); 164 | return (double)apower / 1000; 165 | } 166 | double ATM90E36::GetActivePowerC() { 167 | signed short apower = (signed short) CommEnergyIC(READ, PmeanC, 0xFFFF); 168 | return (double)apower / 1000; 169 | } 170 | double ATM90E36::GetTotalActivePower() { 171 | signed short apower = (signed short) CommEnergyIC(READ, PmeanT, 0xFFFF); 172 | return (double)apower / 250; 173 | } 174 | 175 | // REACTIVE POWER 176 | double ATM90E36::GetReactivePowerA() { 177 | signed short apower = (signed short) CommEnergyIC(READ, QmeanA, 0xFFFF); 178 | return (double)apower / 1000; 179 | } 180 | double ATM90E36::GetReactivePowerB() { 181 | signed short apower = (signed short) CommEnergyIC(READ, QmeanB, 0xFFFF); 182 | return (double)apower / 1000; 183 | } 184 | double ATM90E36::GetReactivePowerC() { 185 | signed short apower = (signed short) CommEnergyIC(READ, QmeanC, 0xFFFF); 186 | return (double)apower / 1000; 187 | } 188 | double ATM90E36::GetTotalReactivePower() { 189 | signed short apower = (signed short) CommEnergyIC(READ, QmeanT, 0xFFFF); 190 | return (double)apower / 250; 191 | } 192 | 193 | // APPARENT POWER 194 | double ATM90E36::GetApparentPowerA() { 195 | signed short apower = (signed short) CommEnergyIC(READ, SmeanA, 0xFFFF); 196 | return (double)apower / 1000; 197 | } 198 | double ATM90E36::GetApparentPowerB() { 199 | signed short apower = (signed short) CommEnergyIC(READ, SmeanB, 0xFFFF); 200 | return (double)apower / 1000; 201 | } 202 | double ATM90E36::GetApparentPowerC() { 203 | signed short apower = (signed short) CommEnergyIC(READ, SmeanC, 0xFFFF); 204 | return (double)apower / 1000; 205 | } 206 | double ATM90E36::GetTotalApparentPower() { 207 | signed short apower = (signed short) CommEnergyIC(READ, SmeanT, 0xFFFF); 208 | return (double)apower / 250; 209 | } 210 | 211 | // FREQUENCY 212 | double ATM90E36::GetFrequency() { 213 | unsigned short freq = CommEnergyIC(READ, Freq, 0xFFFF); 214 | return (double)freq / 100; 215 | } 216 | 217 | // POWER FACTOR 218 | double ATM90E36::GetPowerFactorA() { 219 | signed short pf = (signed short) CommEnergyIC(READ, PFmeanA, 0xFFFF); 220 | return (double)pf / 1000; 221 | } 222 | double ATM90E36::GetPowerFactorB() { 223 | signed short pf = (signed short) CommEnergyIC(READ, PFmeanB, 0xFFFF); 224 | return (double)pf / 1000; 225 | } 226 | double ATM90E36::GetPowerFactorC() { 227 | signed short pf = (signed short) CommEnergyIC(READ, PFmeanC, 0xFFFF); 228 | return (double)pf / 1000; 229 | } 230 | double ATM90E36::GetTotalPowerFactor() { 231 | signed short pf = (signed short) CommEnergyIC(READ, PFmeanT, 0xFFFF); 232 | return (double)pf / 1000; 233 | } 234 | 235 | // VOLTAGE Harmonics 236 | double ATM90E36::GetVHarmA() { 237 | unsigned short value = CommEnergyIC(READ, THDNUA, 0xFFFF); 238 | return (double)value; 239 | } 240 | double ATM90E36::GetVHarmB() { 241 | unsigned short value = CommEnergyIC(READ, THDNUB, 0xFFFF); 242 | return (double)value; 243 | } 244 | double ATM90E36::GetVHarmC() { 245 | unsigned short value = CommEnergyIC(READ, THDNUC, 0xFFFF); 246 | return (double)value; 247 | } 248 | 249 | // CURRENT Harmonics 250 | double ATM90E36::GetCHarmA() { 251 | unsigned short value = CommEnergyIC(READ, THDNIA, 0xFFFF); 252 | return (double)value; 253 | } 254 | double ATM90E36::GetCHarmB() { 255 | unsigned short value = CommEnergyIC(READ, THDNIB, 0xFFFF); 256 | return (double)value; 257 | } 258 | double ATM90E36::GetCHarmC() { 259 | unsigned short value = CommEnergyIC(READ, THDNIC, 0xFFFF); 260 | return (double)value; 261 | } 262 | 263 | // PHASE ANGLE 264 | double ATM90E36::GetPhaseA() { 265 | signed short apower = (signed short) CommEnergyIC(READ, PAngleA, 0xFFFF); 266 | return (double)apower / 10; 267 | } 268 | double ATM90E36::GetPhaseB() { 269 | signed short apower = (signed short) CommEnergyIC(READ, PAngleB, 0xFFFF); 270 | return (double)apower / 10; 271 | } 272 | double ATM90E36::GetPhaseC() { 273 | signed short apower = (signed short) CommEnergyIC(READ, PAngleC, 0xFFFF); 274 | return (double)apower / 10; 275 | } 276 | 277 | // TEMPERATURE 278 | double ATM90E36::GetTemperature() { 279 | short int apower = (short int) CommEnergyIC(READ, Temp, 0xFFFF); 280 | return (double)apower; 281 | } 282 | 283 | /* Gets the Register Value if Desired */ 284 | // REGISTER 285 | unsigned short ATM90E36::GetValueRegister(unsigned short registerRead) { 286 | return (CommEnergyIC(READ, registerRead, 0xFFFF)); //returns value register 287 | } 288 | 289 | // ENERGY MEASUREMENT 290 | double ATM90E36::GetImportEnergy() { 291 | unsigned short ienergyT = CommEnergyIC(READ, APenergyT, 0xFFFF); 292 | // unsigned short ienergyA = CommEnergyIC(READ, APenergyA, 0xFFFF); 293 | // unsigned short ienergyB = CommEnergyIC(READ, APenergyB, 0xFFFF); 294 | // unsigned short ienergyC = CommEnergyIC(READ, APenergyC, 0xFFFF); 295 | 296 | // unsigned short renergyT = CommEnergyIC(READ, RPenergyT, 0xFFFF); 297 | // unsigned short renergyA = CommEnergyIC(READ, RPenergyA, 0xFFFF); 298 | // unsigned short renergyB = CommEnergyIC(READ, RPenergyB, 0xFFFF); 299 | // unsigned short renergyC = CommEnergyIC(READ, RPenergyC, 0xFFFF); 300 | 301 | // unsigned short senergyT = CommEnergyIC(READ, SAenergyT, 0xFFFF); 302 | // unsigned short senergyA = CommEnergyIC(READ, SenergyA, 0xFFFF); 303 | // unsigned short senergyB = CommEnergyIC(READ, SenergyB, 0xFFFF); 304 | // unsigned short senergyC = CommEnergyIC(READ, SenergyC, 0xFFFF); 305 | 306 | return (double)(((double)ienergyT / 32) * 3600); // returns kWh 307 | } 308 | 309 | double ATM90E36::GetExportEnergy() { 310 | 311 | unsigned short eenergyT = CommEnergyIC(READ, ANenergyT, 0xFFFF); 312 | // unsigned short eenergyA = CommEnergyIC(READ, ANenergyA, 0xFFFF); 313 | // unsigned short eenergyB = CommEnergyIC(READ, ANenergyB, 0xFFFF); 314 | // unsigned short eenergyC = CommEnergyIC(READ, ANenergyC, 0xFFFF); 315 | 316 | // unsigned short reenergyT = CommEnergyIC(READ, RNenergyT, 0xFFFF); 317 | // unsigned short reenergyA = CommEnergyIC(READ, RNenergyA, 0xFFFF); 318 | // unsigned short reenergyB = CommEnergyIC(READ, RNenergyB, 0xFFFF); 319 | // unsigned short reenergyC = CommEnergyIC(READ, RNenergyC, 0xFFFF); 320 | 321 | return (double)(((double)eenergyT / 32) * 3600); // returns kWh 322 | } 323 | 324 | /* System Status Registers */ 325 | unsigned short ATM90E36::GetSysStatus0() { 326 | return CommEnergyIC(READ, SysStatus0, 0xFFFF); 327 | } 328 | unsigned short ATM90E36::GetSysStatus1() { 329 | return CommEnergyIC(READ, SysStatus1, 0xFFFF); 330 | } 331 | unsigned short ATM90E36::GetMeterStatus0() { 332 | return CommEnergyIC(READ, EnStatus0, 0xFFFF); 333 | } 334 | unsigned short ATM90E36::GetMeterStatus1() { 335 | return CommEnergyIC(READ, EnStatus1, 0xFFFF); 336 | } 337 | 338 | 339 | /* Checksum Error Function */ 340 | bool ATM90E36::calibrationError() { 341 | bool CS0, CS1, CS2, CS3; 342 | unsigned short systemstatus0 = GetSysStatus0(); 343 | 344 | if (systemstatus0 & 0x4000) { 345 | CS0 = true; 346 | } else { 347 | CS0 = false; 348 | } 349 | 350 | if (systemstatus0 & 0x1000) { 351 | CS1 = true; 352 | } else { 353 | CS1 = false; 354 | } 355 | if (systemstatus0 & 0x0400) { 356 | CS2 = true; 357 | } else { 358 | CS2 = false; 359 | } 360 | if (systemstatus0 & 0x0100) { 361 | CS3 = true; 362 | } else { 363 | CS3 = false; 364 | } 365 | #if DEBUG_SERIAL 366 | if (CS0) { 367 | Serial.println("Error in CS0"); 368 | } 369 | if (CS1) { 370 | Serial.println("Error in CS1"); 371 | } 372 | if (CS2) { 373 | Serial.println("Error in CS2"); 374 | } 375 | if (CS3) { 376 | Serial.println("Error in CS3"); 377 | } 378 | #endif 379 | 380 | if (CS0 || CS1 || CS2 || CS3) return (true); 381 | else return (false); 382 | 383 | } 384 | 385 | uint16_t ATM90E36::checkSum(int start, int end) { 386 | int tmpl = 0; 387 | int tmph = 0; 388 | for (int i = start; i <= end; i++) { 389 | uint16_t registerValue = GetValueRegister(i); 390 | tmpl += (byte)(registerValue) + (byte)(registerValue >> 8); 391 | tmph ^= (byte)(registerValue) ^ (byte)(registerValue >> 8); 392 | } 393 | uint16_t CS = (uint16_t)((byte)(((tmpl % 256) + 256) % 256) + 394 | (uint16_t)((tmph << 8) & 0xFF00)); 395 | #if DEBUG_SERIAL 396 | Serial.print(" Value of checksum : "); 397 | Serial.println(CS, HEX); 398 | #endif 399 | return CS; 400 | } 401 | 402 | /* BEGIN FUNCTION */ 403 | /* 404 | - Define the pin to be used as Chip Select 405 | - Set serialFlag to true for serial debugging 406 | - Use SPI MODE 0 for the ATM90E36 407 | */ 408 | void ATM90E36::begin(int pin, unsigned short lineFreq, unsigned short pgagain, unsigned short ugain, unsigned short igainA, unsigned short igainB, unsigned short igainC, unsigned short igainN) 409 | { 410 | _energy_CS = pin; // SS PIN 411 | _lineFreq = lineFreq; //frequency of power 412 | _pgagain = pgagain; //PGA Gain for current channels 413 | _ugain = ugain; //voltage rms gain 414 | _igainA = igainA; //CT1 415 | _igainB = igainB; //CT2 416 | _igainC = igainC; //CT3 417 | _igainN = igainN; //N 418 | 419 | //pinMode(_energy_CS, OUTPUT); 420 | 421 | /* Enable SPI */ 422 | //SPI.begin(); //moved to main program to assign different SPI pins 423 | 424 | Serial.println("Connecting to ATM90E36"); 425 | #if defined(ENERGIA) 426 | SPI.setBitOrder(MSBFIRST); 427 | SPI.setDataMode(SPI_MODE0); 428 | SPI.setClockDivider(SPI_CLOCK_DIV16); 429 | #endif 430 | 431 | CommEnergyIC(WRITE, SoftReset, 0x789A); // Perform soft reset 432 | delay(100); 433 | CommEnergyIC(WRITE, FuncEn0, 0x0000); // Voltage sag 434 | CommEnergyIC(WRITE, FuncEn1, 0x0000); // Voltage sag 435 | CommEnergyIC(WRITE, SagTh, 0x0001); // Voltage sag threshold 436 | //CommEnergyIC(WRITE, ZXConfig, 0xD654); // 07 ZX2, ZX1, ZX0 pin config - set to current channels, all polarity 437 | 438 | /* SagTh = Vth * 100 * sqrt(2) / (2 * Ugain / 32768) */ 439 | 440 | //Set metering config values (CONFIG) 441 | CommEnergyIC(WRITE, ConfigStart, 0x5678); // Metering calibration startup 442 | CommEnergyIC(WRITE, PLconstH, 0x0861); // PL Constant MSB (default) 443 | CommEnergyIC(WRITE, PLconstL, 0xC468); // PL Constant LSB (default) 444 | CommEnergyIC(WRITE, MMode0, _lineFreq); // Mode Config (60 Hz, 3P4W) 445 | CommEnergyIC(WRITE, MMode1, _pgagain); // 0x5555 (x2) // 0x0000 (1x) 446 | CommEnergyIC(WRITE, PStartTh, 0x1D4C); // Active Startup Power Threshold 447 | CommEnergyIC(WRITE, QStartTh, 0x1D4C); // Reactive Startup Power Threshold 448 | CommEnergyIC(WRITE, SStartTh, 0x1D4C); // Apparent Startup Power Threshold 449 | CommEnergyIC(WRITE, PPhaseTh, 0x02EE); // Active Phase Threshold 450 | CommEnergyIC(WRITE, QPhaseTh, 0x02EE); // Reactive Phase Threshold 451 | CommEnergyIC(WRITE, SPhaseTh, 0x02EE); // Apparent Phase Threshold 452 | CommEnergyIC(WRITE, CSZero, checkSum(PLconstH, SPhaseTh)); // Checksum 0 453 | 454 | //Set metering calibration values (CALIBRATION) 455 | CommEnergyIC(WRITE, CalStart, 0x5678); // Metering calibration startup 456 | CommEnergyIC(WRITE, GainA, 0x0000); // Line calibration gain 457 | CommEnergyIC(WRITE, PhiA, 0x0000); // Line calibration angle 458 | CommEnergyIC(WRITE, GainB, 0x0000); // Line calibration gain 459 | CommEnergyIC(WRITE, PhiB, 0x0000); // Line calibration angle 460 | CommEnergyIC(WRITE, GainC, 0x0000); // Line calibration gain 461 | CommEnergyIC(WRITE, PhiC, 0x0000); // Line calibration angle 462 | CommEnergyIC(WRITE, PoffsetA, 0x0000); // A line active power offset 463 | CommEnergyIC(WRITE, QoffsetA, 0x0000); // A line reactive power offset 464 | CommEnergyIC(WRITE, PoffsetB, 0x0000); // B line active power offset 465 | CommEnergyIC(WRITE, QoffsetB, 0x0000); // B line reactive power offset 466 | CommEnergyIC(WRITE, PoffsetC, 0x0000); // C line active power offset 467 | CommEnergyIC(WRITE, QoffsetC, 0x0000); // C line reactive power offset 468 | CommEnergyIC(WRITE, CSOne, checkSum(PoffsetA, PhiC)); // Checksum 1 469 | 470 | //Set metering calibration values (HARMONIC) 471 | CommEnergyIC(WRITE, HarmStart, 0x5678); // Metering calibration startup 472 | CommEnergyIC(WRITE, POffsetAF, 0x0000); // A Fund. active power offset 473 | CommEnergyIC(WRITE, POffsetBF, 0x0000); // B Fund. active power offset 474 | CommEnergyIC(WRITE, POffsetCF, 0x0000); // C Fund. active power offset 475 | CommEnergyIC(WRITE, PGainAF, 0x0000); // A Fund. active power gain 476 | CommEnergyIC(WRITE, PGainBF, 0x0000); // B Fund. active power gain 477 | CommEnergyIC(WRITE, PGainCF, 0x0000); // C Fund. active power gain 478 | CommEnergyIC(WRITE, CSTwo, checkSum(POffsetAF, PGainCF)); // Checksum 2 479 | 480 | //Set measurement calibration values (ADJUST) 481 | CommEnergyIC(WRITE, AdjStart, 0x5678); // Measurement calibration 482 | CommEnergyIC(WRITE, UgainA, _ugain); // A Voltage rms gain 483 | CommEnergyIC(WRITE, IgainA, _igainA); // A line current gain 484 | CommEnergyIC(WRITE, UoffsetA, 0x0000); // A Voltage offset 485 | CommEnergyIC(WRITE, IoffsetA, 0x0000); // A line current offset 486 | CommEnergyIC(WRITE, UgainB, _ugain); // B Voltage rms gain 487 | CommEnergyIC(WRITE, IgainB, _igainB); // B line current gain 488 | CommEnergyIC(WRITE, UoffsetB, 0x0000); // B Voltage offset 489 | CommEnergyIC(WRITE, IoffsetB, 0x0000); // B line current offset 490 | CommEnergyIC(WRITE, UgainC, _ugain); // C Voltage rms gain 491 | CommEnergyIC(WRITE, IgainC, _igainC); // C line current gain 492 | CommEnergyIC(WRITE, UoffsetC, 0x0000); // C Voltage offset 493 | CommEnergyIC(WRITE, IoffsetC, 0x0000); // C line current offset 494 | CommEnergyIC(WRITE, IgainN, _igainN); // C line current gain 495 | CommEnergyIC(WRITE, CSThree, checkSum(UgainA, IoffsetN)); // Checksum 3 496 | 497 | // Done with the configuration 498 | CommEnergyIC(WRITE, ConfigStart, 0x8765); 499 | CommEnergyIC(WRITE, CalStart, 0x8765); // 0x6886 //0x5678 //8765); 500 | CommEnergyIC(WRITE, HarmStart, 0x8765); // 0x6886 //0x5678 //8765); 501 | CommEnergyIC(WRITE, AdjStart, 0x8765); // 0x6886 //0x5678 //8765); 502 | 503 | //CommEnergyIC(WRITE, SoftReset, 0x789A); // Perform soft reset 504 | } --------------------------------------------------------------------------------