cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to understand the value from STPM34

vivek_7
Associate II

I am using this code to read the RMS Voltage and Current. I am also able to get output which I have attached as a .txt file. The expected voltage from the hardware which I am using STPM34 is up to range of 20 V. I am unable to understand where I am going wrong.

#include <HardwareSerial.h>
#include <math.h>
#include <stdint.h>
#include <string.h>
#include <Arduino.h>
#include "soc/uart_reg.h"

const int  STPM34_ENABLE_PIN = 4; //Enable pin for STPM3x

//UART2 Pins of ESP32 connected to STPM32
const int PIN_16 = 16; //UART Rx pin of STPM3x
const int PIN_17 = 17; //UART Tx pin of STPM3x

HardwareSerial stpm3xSerial(2);
hw_timer_t *timer;

const int baud_rate = 9600;
uint8_t CRC_u8Checksum = 0;
#define BUFFER_SIZE 5
uint16_t STPM3x_RCV[BUFFER_SIZE];
volatile bool timer_call = false;
volatile uint8_t u2_chk=0;
uint16_t RawRms_volt;
uint16_t RawRms_curr;
float CalcRMS_volt;
float RMS_Volt;
float RMS_Curr;
float CalcRMS_curr;
float active_pwr;
float Active_Pwr;
float active_nrj;
float Active_Nrj;
float total_nrj;
float Total_Nrj;
int32_t energy;
int32_t energy_extension;
const int TIME_OUT =1000;// 1s timeout
int32_t BRR_REG1;
int32_t raw_apparent_pwr=0;
int64_t calc_apparent_pwr=0;
int32_t raw_act_nrj=0;
int32_t raw_tot_nrj=0;
uint32_t DSP_CR2_LSB;
uint32_t DSP_CR2_MSB;
uint32_t DSP_CR3_LSB;
uint32_t DSP_CR5_LSB;
uint32_t DSP_CR5_MSB;
uint8_t readAddress;
uint8_t writeAddress;
uint8_t lsbData;
uint8_t msbData;
uint8_t endian_data1;
uint8_t endian_data2;
uint16_t recvd_data;
uint32_t stpmData;
volatile bool udr = false;
volatile int rcvInd = 0;
#define RCV_DATA_SIZE 5
uint8_t recvData[RCV_DATA_SIZE];
uint8_t reverse_data1;
uint8_t reverse_data2;
uint8_t reverse_data3;
uint8_t reverse_data4;
uint8_t reverse_data5;

uint8_t CalcCRC8(uint8_t *pBuf);
void Crc8Calc(uint8_t in_Data);
uint8_t u8ByteReverse(uint8_t in_byte);
bool UartWriteCheck(const uint8_t reg_addr);
void snd_cmmnd_stpm3x(uint8_t READ_ADDRESS,uint8_t WRITE_ADDRESS,uint16_t DATA);
void rcvData(uint8_t read_addr);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Starting ESP32.....");
  stpm3xSerial.begin(baud_rate,SERIAL_8N1,PIN_16,PIN_17);
  pinMode(STPM34_ENABLE_PIN,OUTPUT);
  digitalWrite(STPM34_ENABLE_PIN,HIGH);
  delay(100);
  digitalWrite(STPM34_ENABLE_PIN,LOW);
  Serial.println("STPM3x Enabled");
  STPM_UART_init();//Establish STPM3x UART communication
  stpm3x_init();
  stpm3xSerial.setTimeout(1000);
}

void loop() {
  // put your main code here, to run repeatedly:")
    RMS_Volt = readRMSvoltage();
            Serial.print("RMS Voltage =");
            Serial.print(RMS_Volt);
            Serial.print("V");
            Serial.println();
            delay(100);
     RMS_Curr=readRMScurrent();
            Serial.print("RMS Current =");
            Serial.print(RMS_Curr);
            Serial.print("A");
            Serial.println();
            delay(100);
}

void STPM_UART_init()
{
  snd_cmmnd_stpm3x(0xFF,0x24,0x4007);//US_REG1 LSB configuration
  snd_cmmnd_stpm3x(0xFF,0x25,0x000);// US_REG1 MSB configuration Timeout = 1 ms
  snd_cmmnd_stpm3x(0xFF,0x26,0x0683);// US_REG2 LSB config Buadrate = 9600 bps
  snd_cmmnd_stpm3x(0xFF,0x27,0x0000);// US_REG2 MSB config Frame delay = 0
  snd_cmmnd_stpm3x(0xFF,0x28,0x0066);// US_REG3
  snd_cmmnd_stpm3x(0xFF,0x29,0x0000);// US_REG3 
}

void stpm3x_init()
{
  snd_cmmnd_stpm3x(0xFF,0x00,0x00A0);// DSP_CR1 LSB
  snd_cmmnd_stpm3x(0xFF,0x01,0x0400);
	snd_cmmnd_stpm3x(0xFF,0x02,0x00A0);
	snd_cmmnd_stpm3x(0xFF,0x03,0x2400);
	snd_cmmnd_stpm3x(0xFF,0x04,0x04E0);
	snd_cmmnd_stpm3x(0xFF,0x05,0x0020);
	snd_cmmnd_stpm3x(0xFF,0x06,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x07,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x08,0xF800);
	snd_cmmnd_stpm3x(0xFF,0x09,0x003F);
	snd_cmmnd_stpm3x(0xFF,0x0A,0xF800);
	snd_cmmnd_stpm3x(0xFF,0x0B,0x003F);
	snd_cmmnd_stpm3x(0xFF,0x0C,0xF800);		//Calibration register of secondary voltage channel
	snd_cmmnd_stpm3x(0xFF,0x0D,0x003F);		//Swell threshold of secondary voltage channel
	snd_cmmnd_stpm3x(0xFF,0x0E,0xF800);		//Calibration register of secondary current channel
	snd_cmmnd_stpm3x(0xFF,0x0F,0x003F);		//Swell threshold of secondary current channel
	snd_cmmnd_stpm3x(0xFF,0x10,0x0FFF);		//Primary channel RMS upper threshold (for AH)
	snd_cmmnd_stpm3x(0xFF,0x11,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x12,0x0FFF);		//Primary channel RMS lower threshold (for AH)
	snd_cmmnd_stpm3x(0xFF,0x13,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x14,0x0FFF);		//Secondary channel RMS upper threshold (for AH
	snd_cmmnd_stpm3x(0xFF,0x15,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x16,0x0FFF);		//Secondary channel RMS lower threshold (for AH)
	snd_cmmnd_stpm3x(0xFF,0x17,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x18,0x0327);		//current 1 gain
	snd_cmmnd_stpm3x(0xFF,0x19,0x0327);
	snd_cmmnd_stpm3x(0xFF,0x1A,0x0327);		//current 2 gain
	snd_cmmnd_stpm3x(0xFF,0x1B,0x0327);
	snd_cmmnd_stpm3x(0xFF,0x1C,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x1D,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x1E,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x1F,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x20,0x777F);
	snd_cmmnd_stpm3x(0xFF,0x21,0x0204);
	snd_cmmnd_stpm3x(0xFF,0x22,0x0000);
	snd_cmmnd_stpm3x(0xFF,0x23,0x0200);
}

void snd_cmmnd_stpm3x(uint8_t READ_ADDRESS,uint8_t WRITE_ADDRESS,uint16_t DATA)
{
        uint8_t LSB_DATA = 0;
        uint8_t MSB_DATA = 0;
        uint8_t CRC_DATA = 0;
        uint8_t DATA_WITHOUT_CRC[4] = {0,0,0,0};
				LSB_DATA =  DATA & 0xFF;
				MSB_DATA = (DATA>>8) & 0xFF;
					
				DATA_WITHOUT_CRC[0]=u8ByteReverse(READ_ADDRESS);
				DATA_WITHOUT_CRC[1]=u8ByteReverse(WRITE_ADDRESS);
				DATA_WITHOUT_CRC[2]=u8ByteReverse(LSB_DATA);
				DATA_WITHOUT_CRC[3]=u8ByteReverse(MSB_DATA);
				
			//	memset(STPM3x_RCV,0,sizeof(STPM3x_RCV));// Clear the uart buffer for stpm3x
        CRC_DATA = CalcCRC8(DATA_WITHOUT_CRC);
        CRC_DATA = u8ByteReverse(CRC_DATA);
        if(UartWriteCheck(DATA_WITHOUT_CRC[0]));
        delay(1); 
        if(stpm3xSerial.available())
        {
          reverse_data1 = stpm3xSerial.read();
          lsbData = u8ByteReverse(reverse_data1);
          Serial.print("LSB = 0x");
          Serial.print(lsbData,HEX);Serial.println();
        }
        if(UartWriteCheck(DATA_WITHOUT_CRC[1]));
        delay(1);
        if(stpm3xSerial.available())
        {
          reverse_data2 = stpm3xSerial.read();
          endian_data1 = u8ByteReverse(reverse_data2);
          Serial.print("Byte2 = 0x");
          Serial.print(endian_data1,HEX);Serial.println();
         } 
         
        if(UartWriteCheck(DATA_WITHOUT_CRC[2]));
        delay(1);
        if(stpm3xSerial.available())
        {
          reverse_data3 = stpm3xSerial.read();
          endian_data2 = u8ByteReverse(reverse_data3);
          Serial.print("Byte3 = 0x");
          Serial.print(endian_data2,HEX);Serial.println();
        }
        if(UartWriteCheck(DATA_WITHOUT_CRC[3]));
        delay(1);
        if(stpm3xSerial.available())
        {
          reverse_data4 = stpm3xSerial.read();
          msbData = u8ByteReverse(reverse_data4);
          Serial.print("MSB = 0x");
          Serial.print(msbData,HEX);Serial.println();
        }
        stpm3xSerial.write(CRC_DATA);
}

bool UartWriteCheck(const uint8_t reg_addr)
{
  stpm3xSerial.write(reg_addr);
   uint32_t status_reg = READ_PERI_REG(UART_STATUS_REG(2));
  if(status_reg)// & UART_TXFIFO_EMPTY_INT_ENA)
  {
    //Serial.println("The data is  written  STPM34");
    return true;
  }
  else
  {
    Serial.println("The data is not written properly to registers of STPM34");
    return false;
  }
}

void rcvData(uint8_t read_addr)
{
  //Send data to read from register
   snd_cmmnd_stpm3x(read_addr,0xFF,0xFFFF);
   snd_cmmnd_stpm3x(read_addr,0xFF,0xFFFF);
}

/*
uint8_t rcvData(uint8_t read_addr)
{
   uint8_t bytesRead=0;
   unsigned long start_time = millis();
   while(bytesRead<BUFFER_SIZE)
   {
    if(stpm3xSerial.available()){
      STPM3x_RCV[bytesRead++] = stpm3xSerial.read();
    }
   if(millis() - start_time>100)
   {
    Serial.print("Waiting for UART data");
    break;
   }
   }
}
*/

int32_t nrj_calc(uint32_t raw_nrj)
{
	int64_t calc_nrj = 0;

  /* manage the 2 U32 to have enougth place to save energy cumulated */
  /* Make sure between two reads inside hardware registers if we have to add carry inside ext U32 */
  if (((uint32_t)energy>0xA0000000)  && ((uint32_t)raw_nrj<0x60000000))
  {
		energy_extension++;
  }
  if (((uint32_t)energy<0x60000000) && ((uint32_t)raw_nrj>0xA0000000))
  {
    energy_extension--;
  }

  /* save the new result cumulated come from register inside internal structure */
  energy = raw_nrj;

  /* calculate the nrj value and add the 32 bits extension */
  calc_nrj = (uint64_t)raw_nrj + ((int64_t)energy_extension<< 32);
	
  calc_nrj *= (int64_t)35145;
  
  /* multiply by 10 to have in milli- */
  calc_nrj *= 10;
  /* Put the result in 32 bits format */
  calc_nrj >>= 32;
	/* return the nrj value */
  return((int32_t)calc_nrj);
}

/*		CRC CALUCULATIOPN		*/
uint8_t CalcCRC8(uint8_t *pBuf)
{
		void Crc8Calc(uint8_t in_Data);
    uint8_t     i;
   uint8_t CRC_u8Checksum = 0x00;
    for (i=0; i<4; i++)
    {
        Crc8Calc(pBuf[i]);
    }
    return CRC_u8Checksum;
}

void Crc8Calc(uint8_t in_Data)
{
    uint8_t loc_u8Idx;
    uint8_t loc_u8Temp=0;
  
    for(loc_u8Idx=0;loc_u8Idx<8;loc_u8Idx++)
    {
        loc_u8Temp=in_Data^CRC_u8Checksum;
        CRC_u8Checksum<<=1;
        if(loc_u8Temp&0x80)
        {
            CRC_u8Checksum^=0x7;
        }
        in_Data<<=1;
    }
}

/*		BYTE REVERSE FUNCTION		*/	
uint8_t u8ByteReverse(uint8_t in_byte)
{
    in_byte = ((in_byte >> 1) & 0x55) | ((in_byte << 1) & 0xaa);
    in_byte = ((in_byte >> 2) & 0x33) | ((in_byte << 2) & 0xcc);
    in_byte = ((in_byte >> 4) & 0x0F) | ((in_byte << 4) & 0xF0);
    return in_byte;
}

float readRMSvoltage()
{
    uint32_t raw_RMS_Voltage  = 0;
    uint64_t calc_RMS_Voltage = 0;
    uint16_t v1;
    uint8_t received_data[5] = {0};//array to store received bytes
    uint8_t revData[5] = {0};
     /********		LATCHING		********/
	   snd_cmmnd_stpm3x(0xFF,0x05,0x0060);
  	/********		 Vrms and Irms 		********/
    rcvData(0x48);
    
    raw_RMS_Voltage =  (uint32_t)(msbData<<24)|(endian_data2<<16)|(endian_data1<<8)| lsbData;
    RawRms_volt=raw_RMS_Voltage;
    Serial.print("Raw RMS Voltage=");
    Serial.print(RawRms_volt);Serial.println();
    raw_RMS_Voltage=(raw_RMS_Voltage&0x7FFF);
    calc_RMS_Voltage = (uint64_t)raw_RMS_Voltage*116274;
    calc_RMS_Voltage *=  10;
		calc_RMS_Voltage >>= 15;
    CalcRMS_volt=calc_RMS_Voltage/1000;
    return CalcRMS_volt;
}

float readRMScurrent()
{
  uint8_t received_data[5] = {0};//array to store receeived bytes
  uint8_t revData[5] = {0};
  uint32_t raw_RMS_Current  = 0;
  uint64_t calc_RMS_Current = 0;
   /********		LATCHING		********/
	snd_cmmnd_stpm3x(0xFF,0x05,0x0060);
  rcvData(0x48);
    raw_RMS_Current = (uint32_t)(msbData<<24)|(endian_data2<<16)|(endian_data1<<8)| lsbData;
    Serial.print("Raw RMS Current=");
    Serial.print(raw_RMS_Current);Serial.println();
  raw_RMS_Current=(raw_RMS_Current>>15);
  RawRms_curr=raw_RMS_Current;
  calc_RMS_Current = (uint64_t)raw_RMS_Current*25934;
	calc_RMS_Current *=  10;
	calc_RMS_Current >>= 17;
  CalcRMS_curr=calc_RMS_Current/1000;
  return CalcRMS_curr;
}

float readActivePower()
{
     int32_t raw_ACT_power=0;
     int64_t calc_ACT_power=0;
     uint8_t received_data[5] = {0};//array to store receeived bytes
     /********		LATCHING		********/
   	snd_cmmnd_stpm3x(0xFF,0x05,0x0060);
    rcvData(0x5C);
    for(int i=0;i<5;i++)
    {
      if(stpm3xSerial.available())
      {
      delay(1);  
      received_data[i] = stpm3xSerial.read();
      Serial.print("Received Data Byte:0x");
      Serial.print(received_data[i],HEX);
      Serial.println();
      }
    }  	  
    for(int i=0;i<5;i++)
    {
      raw_ACT_power |= (uint32_t)u8ByteReverse(received_data[i])<<(8*i);
    }   
		raw_ACT_power=raw_ACT_power&(uint32_t)0x1FFFFFFF;
		raw_ACT_power <<= 4;  // handle sign extension as power is on 28 bits
    raw_ACT_power >>= 4;
		calc_ACT_power=((int64_t)raw_ACT_power*30154605);
		calc_ACT_power *= 10;
		calc_ACT_power >>= 28;
		active_pwr=(int32_t)calc_ACT_power/1000;//kW
    return active_pwr;
}
float readActiveEnergy()
{
   uint8_t received_data[5] = {0};//array to store receeived bytes
     /********		LATCHING		********/
	  snd_cmmnd_stpm3x(0xFF,0x05,0x0060);
    rcvData(0x54);		
		for(int i=0;i<5;i++)
    {
      while(stpm3xSerial.available())
      {
      delay(1);  
      received_data[i] = stpm3xSerial.read();
      Serial.print("Received Data Byte:0x");
      Serial.print(received_data[i],HEX);
      Serial.println();
      }
    }  	  
    for(int i=0;i<5;i++)
    {
      raw_act_nrj |= (uint32_t)u8ByteReverse(received_data[i])<<(8*i);
    }  
		active_nrj=nrj_calc(raw_act_nrj);
		active_nrj = active_nrj/1000;// dividing by 1000 to get watt hour mWh to Wh
    return active_nrj;
}

 

 

0 REPLIES 0