2020-02-05 08:30 AM
Hello,
I'm using a STPM32 to measure the ac line voltage and current. It is connected via a galvanic isolator ISO7341CDW to a STM32F072 with SPI. Most of the time, this works just fine. I can read the correct RMS values for I1 and V1 (Register DSP_REG14 at 0x48) as well as the period (Register DSP_REG1 at 0x2E) to convert it to the line frequency. I can change the ac voltage with a adjustable transformer and see the correct values. I'm polling the values every 1 second, but the STPM32 is set to autolatching.
So sometimes something seem to go wrong:
I just read some of the received data from register DSP_REG14 in the Atollic True Studio for debugging purposes. These data frames were received exactly in this order with no other frame in between after flashing and starting the firmware to the STM32F072 in debug mode. The actual ac voltage was ~130 VAC, the actual current was ~240 mA.
1) rx_data[0] 0x13 (V1 RMS Data [7:0])
rx_data[1] 0xda (V1 RMS Data [14:8], C1 RMS Data [15])
rx_data[2] 0x7f (C1 RMS Data [23:16])
rx_data[3] 0x03 (C1 RMS Data [31:24])
rx_data[4] 0x9d (CRC)
VOLTAGE_RMS 461.180 VAC (calculated)
CURRENT_RMS 234 mA (calculated)
2) rx_data[0] 0xc4 (V1 RMS Data [7:0])
rx_data[1] 0x18 (V1 RMS Data [14:8], C1 RMS Data [15])
rx_data[2] 0x82 (C1 RMS Data [23:16])
rx_data[3] 0x03 (C1 RMS Data [31:24])
rx_data[4] 0x94 (CRC)
VOLTAGE_RMS 126.800 VAC (calculated)
CURRENT_RMS 234 mA (calculated)
3) rx_data[0] 0x12 (V1 RMS Data [7:0])
rx_data[1] 0x16 (V1 RMS Data [14:8], C1 RMS Data [15])
rx_data[2] 0x81 (C1 RMS Data [23:16])
rx_data[3] 0x03 (C1 RMS Data [31:24])
rx_data[4] 0x3e (CRC)
VOLTAGE_RMS 113.000 VAC (calculated)
CURRENT_RMS 234 mA (calculated)
4) rx_data[0] 0x00 (V1 RMS Data [7:0])
rx_data[1] 0x00 (V1 RMS Data [14:8], C1 RMS Data [15])
rx_data[2] 0x80 (C1 RMS Data [23:16])
rx_data[3] 0x03 (C1 RMS Data [31:24])
rx_data[4] 0xbf (CRC)
VOLTAGE_RMS 0 VAC (calculated)
CURRENT_RMS 234 mA (calculated)
5) rx_data[0] 0x00 (V1 RMS Data [7:0])
rx_data[1] 0x80 (V1 RMS Data [14:8], C1 RMS Data [15])
rx_data[2] 0x82 (C1 RMS Data [23:16])
rx_data[3] 0x03 (C1 RMS Data [31:24])
rx_data[4] 0x9e (CRC)
VOLTAGE_RMS 0 VAC (calculated)
CURRENT_RMS 235 mA (calculated)
I first thought about corrupted data packages, but it seems like the CRC is right. Also, when the ac input voltage is read wrong, the current value is still perfectly correct. Even Bit 15 of register DSP_REG14 fits to the current value. This Bit represents the LSB of the current value.
I also do not think, that it is a problem due to wrong calculation in the STM32F072 e.g. overflow, as it works most of the time just fine in the full range of ~80 VAC to 270 VAC. Also I'm using uint32_t values there and verified this independently.
In the STM32F072 I'm using this command to receive the data shown above. Is this fine or would be the single command "HAL_SPI_TransmitReceive(&hspi2, tx_data, rx_data, 5, 1000);" be better?
//////// prepare array for reading data
// - first Byte = Address to read = 0x48 = DSP_REG14
// - Byte 2-4 = could be command to write, but will be ignored when set to 0xFF
// - Byte 5 = CRC, calculated by separate function. Set to 0x99 for debugging
uint8_t tx_data[5] = {0x48, 0xFF, 0xFF, 0xFF, 0x99};
// reset CS-signal for sending the read request
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);
// send and receive request data via SPI
HAL_SPI_Transmit(&hspi2, (uint8_t*) tx_data, 5, 1000) );
// set CS-signal
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);
HAL_Delay(1);
// reset CS-signal for receiving requested data
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);
// receive data via SPI
HAL_SPI_Receive(&hspi2, (uint8_t *) rx_data, 5, 1000);
// set CS-signal
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);
Has anyone any idea, what this problem could be about?
Solved! Go to Solution.
2020-04-14 11:29 PM
I found my error in the meantime. I missed the sending of dummy bytes to receive the actual measurement data...
2020-04-14 11:29 PM
I found my error in the meantime. I missed the sending of dummy bytes to receive the actual measurement data...
2020-12-25 08:33 AM
Hello. Could you please share what exactly you fixed in your code? I'm having exactly the same problems with stpm32
.STPM: Act e:10065 p:101331 Rea e:127 p:1422 App e:10043 p:101705
18:38:11.690>
states: dsp_sr1: 00044008 dsp_sr2: 02044008
rms U:230.57V I:0.43A
....
.STPM: Act e:37339 p:7361171 Rea e:17 p:-46066 App e:35105 p:11417695
18:38:25.614>
states: dsp_sr1: 03144008 dsp_sr2: 03144008
rms U:226.35V I:50.40A
For a while stpm32 read the correct voltage and current values U: 230.57V I: 0.43A
But after, completely wrong values or 0 values begin to come
with correct values, the value of the registers DSP_SR1 and DSP_SR2
dsp_sr1: 00044008 dsp_sr2: 02044008
with erroneous readings, it starts to come
states: dsp_sr1: 03144008 dsp_sr2: 03144008
The following registers bits are set according to the datasheet description
0x00044008 = "00000000 00000100 01000000 00001000"
0x03144008 = "00000011 00010100 01000000 00001000"
20 - Primary current sigma-delta bitstream stuck
24 - Primary voltage sigma-delta bitstream stuck
25 - Primary voltage period error
What could be causing this?
2021-01-03 11:14 PM
As I wrote, I missed to send dummy data to receive the actual data right after it has been requested. In this case, after sending the read request to the STPM32, the SPI clock will be stopped by the SPI master. When the SPI clock is enabled again (e.g. when sending the next read request to the STPM32), the STPM32 still needs to send the data requested previously. These will be send but somehow get corrupted?! The solution is to send enough dummy data with the value 0xFF. This data will be ignored by the STPM32 but keeps the SPI clock turned on, so that the STPM32 data can be received. My routine looks like this:
HAL_StatusTypeDef STPM3x_read_frame(uint8_t * const rx_data, uint8_t read_address, uint8_t CRC_en)
{
HAL_StatusTypeDef retVal = HAL_OK;
/*******************************************************************************
* Prepare array for reading data
* - first Byte = Address to read
* - Byte 2-4 = could be command to write, but will be ignored when set to 0xFF
* - Byte 5 = CRC, calculated by STPM3x_send_frame()
******************************************************************************/
uint8_t tx_data[AC_METRO_FRAME_LEN] = {read_address, 0xFF, 0xFF, 0xFF, 0x00};
/*******************************************************************************
* Set CS and keep it low during the duration of sending and receiving
******************************************************************************/
STPM3x_CS_SET_LOW();
/*******************************************************************************
* Send the frame with the address to read from to the STPM3x
******************************************************************************/
retVal |= STPM3x_send_frame(tx_data, CRC_en, FALSE);
/*******************************************************************************
* Change the TX frame to indicate that we want to read now
******************************************************************************/
tx_data[0] = 0xFF;
/*******************************************************************************
* Calculate CRC
******************************************************************************/
tx_data[AC_METRO_FRAME_LEN-1] = crc8_update( 0x00u, tx_data, AC_METRO_FRAME_LEN-1 );
/*******************************************************************************
* Receive the requested data frame
******************************************************************************/
retVal |= HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) tx_data, (uint8_t *) rx_data, AC_METRO_FRAME_LEN, 100 );
/*******************************************************************************
* Set CS high after everything has been transmitted and received
******************************************************************************/
STPM3x_CS_SET_HIGH();
/*******************************************************************************
* Check if received CRC is correct, but only if CRC was enabled
******************************************************************************/
if ( CRC_en == TRUE )
{
if ( rx_data[AC_METRO_FRAME_LEN-1] == crc8_update( 0x00u, rx_data, (AC_METRO_FRAME_LEN-1) ) )
{
/*******************************************************************************
* CRC correct
******************************************************************************/
retVal |= HAL_OK;
}
else
{
/*******************************************************************************
* CRC wrong, repeat transmission or do something similar
******************************************************************************/
retVal |= HAL_ERROR;
}
}
return retVal;
}
2022-07-07 11:39 PM
Hello @Christian Wächter,
Could you please have a look at my question? Did you ever faced similar kind of issue while interfacing stpm32?