1
\$\begingroup\$

I'm currently developing a board for my dissertation that should monitor voltage, current and power consumption of a given load. For that purpose I chose to use the Allegro ACS71020. The one I chose was the SPI model with an IPR of 30 amps. To interface with the ACS71020 I'm using the PSoC 5LP but this shouldn't differ much from MCU to MCU. However I am getting incorrect voltage and current readings from the ACS71020.

This is the schematic for my hardware setup. I decided to use pull-up resistors because the development board schematic also uses them when you try to buy the SPI version.

Schematic.

Figure 1: Schematic

I'm working with 230 V @ 50 Hz power source (European), therefore I'm using a 2 kΩ resistor for Rsense giving me a full-scale voltage of 550 V (this value will be needed later on).

After this I connected it to the PSoC using these pins (taking care to use a 3.3 V reference for the PSoC output so that I wouldn't damage the ACS71020).

PSoC Pinout

Figure 2: PSoC Pinout


My problem here is that when measuring voltage, without it connected, it measures around 30 V. And when doing a practical test using a light bulb as the load, the voltage measurements fluctuate from about 140 V to 230 V which is not the correct value. Also the current value is always really low. Why are these incorrect values being reported?


This is data I got when requesting a voltage and current readings every 4 seconds:

Light bulb on

Table 1: Voltage and current readings with light bulb ON

Light bulb off

Table 2: Voltage and current readings with light bulb OFF

As you can see, if the power is off the readings although incorrect are consistent. When the power is on, the readings are mostly incorrect and inconsistent for both voltage and current.

Here is the code I used to get the readings:

void SPIrequestData32 (_Bool rw, uint8 addr, uint8 p, uint8 s, uint8 t, uint8 q){
/*******************************************************************
*   Requests data from and address with read or write permissions
*   and stores 32bit answer in SPI Rx buffer
*   Inputs int RW, uint8 addr Clears TxRx&FIFO
*   RW == 1 READ RW==0 Write
*   32bit answer is stored in SPI_RxDataBuffer
*******************************************************************/
        uint8 Address = 0x00;
        //clear buffers
        SPIM_1_ClearTxBuffer();
        SPIM_1_ClearRxBuffer();
        SPIM_1_ClearFIFO();   
        //Sends address with rw bit
        //uint8 Address = ((0x1E) | read);  
        if(rw==1){
             Address = ((addr) | read);
        }else if (rw == 0){
             Address = ((addr) | write);
        }
        //waits for a 32bit response = 4frames
        if(rw==1){    
        SPIM_1_WriteTxData(Address);
        SPIM_1_WriteTxData(0x00);
        SPIM_1_WriteTxData(0x00);
        SPIM_1_WriteTxData(0x00);
        SPIM_1_WriteTxData(0x00);}
        if(rw==0){    
        SPIM_1_WriteTxData(Address);
        SPIM_1_WriteTxData(p);
        SPIM_1_WriteTxData(s);
        SPIM_1_WriteTxData(t);
        SPIM_1_WriteTxData(q);}
        while(!(SPIM_1_ReadTxStatus() & SPIM_1_STS_SPI_DONE));
}

In this function, I receive the address I wish to read from or write to. If it's a read, I just drive the line low so that the ACS71020 has the CS and CLK active. If it's a write, I proceed to write the byte I wish.

After receiving the data from the MISO line, I call the function to convert the first 15 bytes to a voltage value and convert the next 15 bytes to a current value, with the help of the lackluster datasheet.

void V_I_RMS (){
/*******************************************************************
*   Transforms 32bit response in VRMS(V) and IRMS(A) values
*   output is global variable VRMs IRMs
*******************************************************************/
    uint8 zero = 0;
    uint8 primeiro = 0;
    uint8 segundo = 0;
    uint8 terceiro = 0;
    uint8 quarto = 0;
    uint16 V = 0;
    uint16 I = 0;
    uint16 aux = 0;
    uint16 aux2 = 0;
        for(uint8 i = 0u; i<5u; i++){
            //ignorar o primeiro
            switch(i){
            case 0: zero = SPIM_1_ReadRxData(); break;   //The first one is to be ignored
            case 1: primeiro = SPIM_1_ReadRxData(); break;
            case 2: segundo = SPIM_1_ReadRxData(); break;
            case 3: terceiro = SPIM_1_ReadRxData(); break;
            case 4: quarto = SPIM_1_ReadRxData(); break;
            default:break;               
            }
            
        }
        V = ((segundo<<8) | primeiro); //Voltage is 16bit number with 15 fractional bits
        VRMs = (fullscaleV *( (float)V / (float)0x8000) );
       
        
        I = ((quarto<<8) | terceiro);   //current is a 15bit number with 14fractinal bits
        aux = I & 0b0100000000000000;   //Mask to check if its 1.xxx or 0.xxx
        if(aux == 0x4000){ aux = 1;}
        else if (aux == 0){aux = 0;}
        aux2 = (I & 0b0011111111111111);    //checks for fractional bits
        IRMs = IPR*(aux + (aux2*Istep));      //currents is given but IPR*(unit+fraction*(2^14))
        

}

I don't understand if I'm doing anything wrong while converting or requesting data, to give such bad results. If anyone asks, my SPI master block is setup in this way. Referring to the datasheet, it's the correct way. I've tried increasing or decreasing its bit rate, but the results I get are the same.

I've also tried to change some shadow registers and the customer access code, but when I read the register afterwards, it comes all messed up - sometimes showing nothing but zeros, sometimes showing the what I've written into them.

SPI master

Figure 3: Screenshot of SPI master block setup

This is a printscreen of my digital oscilloscope, showing that by requesting to read register 0x1E with the 7th bit high (which is the read bit) it results in 0x9E (reading mode). By driving the MOSI line high or low, it maintains CS and CLK working as intended.

Oscilloscope printscreen

Figure 4: Screenshot of digital oscilloscope

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Why not post the code instead of screenshots? Where do you control the CS line? Do you have other SPI devices on bus? \$\endgroup\$
    – Justme
    Aug 1, 2020 at 19:47
  • 1
    \$\begingroup\$ I'm not familiar with this i thought screenshots were good. The CS line is controlled automaticaly by the SPI module in the PSoC, there are no more devices on the bus. \$\endgroup\$ Aug 1, 2020 at 20:02
  • \$\begingroup\$ How do you know it is automatically controlling it in the correct way? It must be taken low, then do the transaction you want, and then taken high. How do you make sure it does that? \$\endgroup\$
    – Justme
    Aug 1, 2020 at 20:13
  • 1
    \$\begingroup\$ I have a digital oscilloscope to check the behaviour. I can post i screenshot of it. \$\endgroup\$ Aug 1, 2020 at 20:13
  • \$\begingroup\$ "This fixed my issues with random readings." : If you solved the problem, please feel free to post the solution formally as an answer yourself (It is allowed by SE policy). It will help future readers. \$\endgroup\$
    – AJN
    Aug 4, 2020 at 9:26

1 Answer 1

1
\$\begingroup\$

This fixed my issues with random readings.

I've done some testing and i've found out that as stated in the cover of the datasheet the power supply of your ASEK71020KMAB-090B3-I2C and your Micro-controller unit needs to be isolated. I tested this out by powering it all from a laptop using only it's battery (it shouldn't be charging otherwise it wont be isolated).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.