I am using an ACS71020 3.3 V I2C version hooked up to an ESP32. I have connected the IC as proposed in the datasheet. Rsense used is 1.8 kΩ as proposed in the evaluation board user manual for 230-240 VRMS.
With a load connected I get reasonable results for IRMS when reading register 0x20, but VRMS is much lower than expected, and I guess as a result PRMS is also not correct.
Above is my implementation (I2C pull-ups are present).
It is also stated that the maximum voltage for the VINP pin is 0.275 V. I measured Rsense with a multimeter and got something around 0.100 VRMS (which will not be close to 0.275 V in amplitude).
I thought that might be an issue and I tried to recreate the scenario in LtSpice:
And indeed it showed that the the voltage across R5 would be around 0.100 VRMS. I was not sure of the role of R3 and R5, so I tried removing them and got ~0.290 V max amplitude; changing Rsense to 1.7 kΩ would yield ~0.275 V max amplitude exactly.
I removed R3 and R5 from my PCB, but I still got pretty similar results (I will attach the results later, when I get my hands on the test PCB again)
Regarding the code, maybe I am doing something wrong there as well, but as far as I understand the basic flow should be:
- Read the values from the VRMS and IRMS registers;
- Transform them from Q
number()
format tofloat
; - Multiply VRMS by 325 (full-scale voltage, or should it 230?) and IRMS by 30 as I have a 30 A AC71020 version.
I expect that the values would oscillate based on at which time of the cycle they are being read by the ESP32, therefore they should by averaged.
Code snippet:
void acs171020_read_2_15Bytes(byte address) {
uint16_t Irms;
uint16_t Vrms;
byte buff[4];
Wire.beginTransmission(0x66);
Wire.write( 0x20);
Wire.endTransmission();
Wire.requestFrom(0x66, 4);
int nrrr = 0;
while (Wire.available()) { // slave may send less than requested
char c = Wire.read(); // receive a byte as character
buff[nrrr++] = c;
}
Vrms = (buff[1] << 8) + buff[0];
bitClear(Vrms, 15);
Irms = (buff[3] << 8) + buff[2];
bitClear(Irms, 15);
float testVRM = ((float)Vrms) * 0.00003051757; //or /32768.0
float testVRMMM = qToFloat<uint16_t>(Vrms, 15);
// both give same value
testVRMMM = testVRMMM *325;
float testIRM = qToFloat<uint16_t>(Irms, 14); // ((float)Irms) * 0.00006103515;
float testIRMS = ((float)Irms) * 0.00006103515; //or /32768.0
testIRMS = testIRMS * 30;
To sum up : Are two 1 MΩ resistors really needed on the VIN line? Am I missing something crucial in the code part?
UPDATE: OK, in order to improve improve performance a bit and let the IC actualy do its job, I have enabled the customer mode and set the register 0x1C to make an average of 62 samples per minute. Then I read 0x27 once a second. The Q to float value is now ~0.3121337891 so to get 230 the full-scale voltage should then considered to be 736.86351184 V. Where does this number come from, how can I verify it?