单相计量芯片RN8209D使用经验分享
本帖最后由 Baldwin 于 2018-10-16 08:24 编辑之前用了三相计量芯片RN8302,RN8302计量芯片使用经验分享https://www.amobbs.com/thread-5697512-1-1.html
最近产品的另外一个系列需要单向计量,于是用了RN8209D,做下来效果还可以{:lol:} ,能满足1级的精度,实际可以做到0.5S,总的来说这款芯片还是蛮不错的;老规矩,把相关资料分享给大家,少走弯路;
以下是实验时的误差记录
HFConst,功率转换系数,启动功率寄存器值换算方法
1---------------------------------------硬件部分-----------------------------------------------------------------------------------
电压和电流都采用互感器,电压采样采用泽明1:1电压互感器,电流采样采用5A:2.5mA互感器;RN8209D采用模拟SPI与单片机进行通信;电路相对比较简单;
2---------------------------------------RN8209D通信部分,采用模拟SPI-------------------------------------------------------------------------
void RN8209D_ReadRegNoCheck(uint8_t addr,uint8_t *regbuf,uint8_t regbuflen)
{
uint8_t ucI,ucK;
RN8209D_CS_CLR();
delay_us(10);
addr |= 0x00; //发送读数据命令(bit.7=0)
for(ucI=0;ucI<8;ucI++) //发送读数据命令,下降沿接收数据,高位在前,低位在后
{
if( addr & 0x80 )
RN8209D_MOSI_SET();
else
RN8209D_MOSI_CLR();
RN8209D_SCK_SET();
delay_us(RN_CLOCKWIDTH);
RN8209D_SCK_CLR(); //在时钟的下降沿写数据
addr<<=1;
delay_us(RN_CLOCKWIDTH);
}
RN8209D_MOSI_CLR();
RN8209D_SCK_CLR();
delay_us(50);
for(ucK=0;ucK<regbuflen;ucK++)
{
regbuf=0x00;
for(ucI=0;ucI<8;ucI++)
{
RN8209D_SCK_SET();
delay_us(RN_CLOCKWIDTH);
regbuf<<=1;
RN8209D_SCK_CLR(); //在时钟的下降沿读数据
delay_us(RN_CLOCKWIDTH/2);
if(RN8209D_Read_MISO())
regbuf=regbuf|0x01;
delay_us(RN_CLOCKWIDTH/2);
}
}
RN8209D_CS_SET();
delay_us(10);
RN8209D_SCK_CLR();
delay_us(10);
}
uint8_t RN8209D_ReadReg(uint8_t addr,uint8_t *regbuf,uint8_t regbuflen)
{
uint8_t buf;
RN8209D_ReadRegNoCheck(addr,regbuf,regbuflen);
m_memset(buf,0x01,4);
RN8209D_ReadRegNoCheck(Reg_RData,buf,4);
if(regbuflen == 3){
if(m_memcmp(regbuf,buf+1,regbuflen) == 0)
return 0;
else
return 1;
}
else if(regbuflen == 4){
if(m_memcmp(regbuf,buf,regbuflen) == 0)
return 0;
else
return 1;
}
else if(regbuflen == 2){
if(m_memcmp(regbuf,buf+2,regbuflen) == 0)
return 0;
else
return 1;
}
else{
return 1;
}
}
void RN8209D_WriteRegNoCheck(uint8_t addr,uint8_t *regbuf,uint8_t regbuflen)
{
uint8_t ucI,ucK;
RN8209D_CS_CLR();
delay_us(100);
addr |= 0x80; //发送写数据命令(bit.7=1)
for(ucI=0;ucI<8;ucI++)
{
if( addr & 0x80 )
RN8209D_MOSI_SET();
else
RN8209D_MOSI_CLR(); ;
RN8209D_SCK_SET();
delay_us(RN_CLOCKWIDTH);
RN8209D_SCK_CLR(); //在时钟的下降沿写数据
addr<<=1;
delay_us(RN_CLOCKWIDTH);
}
RN8209D_MOSI_CLR();
RN8209D_SCK_CLR();
delay_us(500);
for(ucK=0;ucK<regbuflen;ucK++)
{
for(ucI=0;ucI<8;ucI++)
{
if(regbuf & 0x80 )
RN8209D_MOSI_SET();
else
RN8209D_MOSI_CLR();
RN8209D_SCK_SET();
delay_us(RN_CLOCKWIDTH);
RN8209D_SCK_CLR(); //在时钟的下降沿写数据
regbuf<<=1;
delay_us(RN_CLOCKWIDTH);
}
}
RN8209D_MOSI_CLR();
delay_us(100);
RN8209D_CS_SET();
delay_us(100);
RN8209D_SCK_CLR();
delay_us(100);
}
uint8_t RN8209D_WriteReg(uint8_t addr,uint8_t *regbuf,uint8_t regbuflen)
{
uint8_t buf;
RN8209D_WriteRegNoCheck(addr,regbuf,regbuflen);
m_memset(buf,0,4);
RN8209D_WriteRegNoCheck(Reg_WData,buf,regbuflen);
if(regbuflen == 3){
if(m_memcmp(regbuf,buf+1,regbuflen) == 0)
return 0;
else
return 1;
}
else if(regbuflen == 4){
if(m_memcmp(regbuf,buf,regbuflen) == 0)
return 0;
else
return 1;
}
else if(regbuflen == 2){
if(m_memcmp(regbuf,buf+2,regbuflen) == 0)
return 0;
else
return 1;
}
else{
return 1;
}
}
3---------------------------------------RN8209 寄存器-------------------------------------------------------------------------
寄存器主要分2块,校表参数寄存器和计量参数寄存器
4---------------------------------------RN8209 特殊命令------------------------------------------------------------------------
RN8209部分寄存器进行写操作时,需要先发送写使能,才可以对寄存器操作,这点需要注意;同时,对RN8209芯片操作时,需要先发送复位命令哦;
5---------------------------------------RN8209 初始化(非校表初始化)------------------------------------------------------------------------
这是RN8209需要用的变量,我把它放到结构体里,方便观察
typedef struct{
uint16_t Cst_HFConst;
uint16_t Cst_PStart;//有功启动功率
uint16_t Cst_DStart;
uint16_t Cst_GPQA; //A通道功率增益校正
uint16_t Cst_GPQB; //B通道功率增益校正
uint8_tCst_PhsA; //A通道相位校正
uint8_tCst_PhsB; //B通道相位校正
uint16_t Cst_QPhsCal; //无功相位校正
uint16_t Cst_APOSA; //A通道有功功率offset校正
uint16_t Cst_APOSB; //B通道有功功率offset校正
uint16_t Cst_RPOSA; //A通道无功功率offset校正
uint16_t Cst_RPOSB; //B通道无功功率offset校正
uint16_t Cst_IARMSOS; //A通道电流有效值offset校正
uint16_t Cst_IBRMSOS; //B通道电流有效值offset校正
uint16_t Cst_IBGain;//B通道电流增益
uint16_t Cst_Ku;
uint32_t Cst_Kia;
uint32_t Cst_Kib;
uint16_t cheskSum;
}StDef_RN8209DPara;
uint8_t RN8209D_Init(void)
{
uint8_t regbuf;
uint8_t status = 1;
RN8209D_GPIOConfig();
RN8209D_RST_CLR();
delay_ms(100);
RN8209D_RST_SET();
delay_ms(100);
//读取RN8209 DeviceID
if(RN8209D_ReadReg(Reg_DeviceID,regbuf,3) == 0)
{
if((regbuf==0x82)&&(regbuf==0x09)&&(regbuf==0x00)){
status = 0;
}
else{
status = 1;
}
}
//默认换算系数
//StDef_RN8209DPara_Reg.Cst_Kia = 41938;
//StDef_RN8209DPara_Reg.Cst_Kib = 44529;
//StDef_RN8209DPara_Reg.Cst_Ku= 8711;
if(status == 0)
{
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//复位
regbuf = 0xFA;
RN8209D_WriteReg(WREN,regbuf,1);
delay_ms(20);
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//系统控制寄存器
regbuf = 0x00;
regbuf = 0x51;//开启通道B,A、B通道增益2
RN8209D_WriteReg(Reg_SYSCON,regbuf,2);
m_memset(regbuf,0,2);
RN8209D_ReadReg(Reg_SYSCON,regbuf,2);
//写HFCONST
regbuf = 0x35;
regbuf = 0x7B;
RN8209D_WriteReg(Reg_HFCONST,regbuf,2);
m_memset(regbuf,0,2);
RN8209D_ReadReg(Reg_HFCONST,regbuf,2);
//启动功率
regbuf = 0x01;
regbuf = 0x2D;
RN8209D_WriteReg(Reg_PStart,regbuf,2);
regbuf = 0x01;
regbuf = 0x2D;
RN8209D_WriteReg(Reg_DStart,regbuf,2);
//计量控制
regbuf = 0x80;//电能读后清零
regbuf = 0x03;
RN8209D_WriteReg(Reg_EMUCON,regbuf,2);
//计量控制2
regbuf = 0x00;
regbuf = 0xB0;
RN8209D_WriteReg(Reg_EMUCON2,regbuf,2);
//A通道有功功率增益
//StDef_RN8209DPara_Reg.Cst_GPQA = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_GPQA/256;
regbuf = StDef_RN8209DPara_Reg.Cst_GPQA%256;
RN8209D_WriteReg(Reg_GPQA,regbuf,2);
//B通道有功功率增益
//StDef_RN8209DPara_Reg.Cst_GPQB = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_GPQB/256;
regbuf = StDef_RN8209DPara_Reg.Cst_GPQB%256;
RN8209D_WriteReg(Reg_GPQB,regbuf,2);
//A通道相位校正
//StDef_RN8209DPara_Reg.Cst_PhsA = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_PhsA;
RN8209D_WriteReg(Reg_PhsA,regbuf,1);
//B通道相位校正
//StDef_RN8209DPara_Reg.Cst_PhsB = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_PhsB;
RN8209D_WriteReg(Reg_PhsB,regbuf,1);
//A通道有功功率offset
//StDef_RN8209DPara_Reg.Cst_APOSA = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_APOSA/256;
regbuf = StDef_RN8209DPara_Reg.Cst_APOSA%256;
RN8209D_WriteReg(Reg_APOSA,regbuf,2);
//B通道有功功率offset
//StDef_RN8209DPara_Reg.Cst_APOSB = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_APOSB/256;
regbuf = StDef_RN8209DPara_Reg.Cst_APOSB%256;
RN8209D_WriteReg(Reg_APOSB,regbuf,2);
//A通道无功功率offset
StDef_RN8209DPara_Reg.Cst_RPOSA = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_RPOSA/256;
regbuf = StDef_RN8209DPara_Reg.Cst_RPOSA%256;
RN8209D_WriteReg(Reg_RPOSA,regbuf,2);
//B通道无功功率offset
StDef_RN8209DPara_Reg.Cst_RPOSB = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_RPOSB/256;
regbuf = StDef_RN8209DPara_Reg.Cst_RPOSB%256;
RN8209D_WriteReg(Reg_RPOSB,regbuf,2);
//A通道电流offset
//StDef_RN8209DPara_Reg.Cst_IARMSOS = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_IARMSOS/256;
regbuf = StDef_RN8209DPara_Reg.Cst_IARMSOS%256;
RN8209D_WriteReg(Reg_IARMSOS,regbuf,2);
//B通道电流offset
//StDef_RN8209DPara_Reg.Cst_IBRMSOS = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_IBRMSOS/256;
regbuf = StDef_RN8209DPara_Reg.Cst_IBRMSOS%256;
RN8209D_WriteReg(Reg_IBRMSOS,regbuf,2);
//B通道电流增益
StDef_RN8209DPara_Reg.Cst_IBGain = 0;
regbuf = StDef_RN8209DPara_Reg.Cst_IBGain/256;
regbuf = StDef_RN8209DPara_Reg.Cst_IBGain%256;
RN8209D_WriteReg(Reg_IBGain,regbuf,2);
//直流通道
regbuf=0;regbuf=0;
RN8209D_WriteReg(Reg_D2FPL,regbuf,2);
regbuf=0;regbuf=0;
RN8209D_WriteReg(Reg_D2FPH,regbuf,2);
regbuf=0;regbuf=0;
RN8209D_WriteReg(Reg_DCIAH,regbuf,2);
regbuf=0;regbuf=0;
RN8209D_WriteReg(Reg_DCIBH,regbuf,2);
regbuf=0;regbuf=0;
RN8209D_WriteReg(Reg_DCUH,regbuf,2);
regbuf=0;regbuf=0;
RN8209D_WriteReg(Reg_DCL,regbuf,2);
//写保护
regbuf = 0xDC;
RN8209D_WriteReg(WREN,regbuf,1);
//获取校表寄存器校验值
RN8209D_GetCheckSum();
}
return status;
}
6---------------------------------------RN8209 校表初始化)------------------------------------------------------------------------
void RN8209D_CalibrateInit(void)
{
uint8_t regbuf;
uint8_t status = 1;
//读取RN8209 DeviceID
if(RN8209D_ReadReg(Reg_DeviceID,regbuf,3) == 0){
if((regbuf==0x82)&&(regbuf==0x09)&&(regbuf==0x00)){
status = 0;
}
else{
status = 1;
}
}
//默认换算系数
//StDef_RN8209DPara_Reg.Cst_Kia = 41938;
//StDef_RN8209DPara_Reg.Cst_Kib = 44529;
//StDef_RN8209DPara_Reg.Cst_Ku = 8711;
if(status == 0){
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//复位
regbuf = 0xFA;
RN8209D_WriteReg(WREN,regbuf,1);
delay_ms(20);
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//系统控制寄存器
regbuf = 0x00;
regbuf = 0x51;//开启通道B
RN8209D_WriteReg(Reg_SYSCON,regbuf,2);
m_memset(regbuf,0,2);
RN8209D_ReadReg(Reg_SYSCON,regbuf,2);
//写HFCONST
regbuf = 0x35;
regbuf = 0x7B;
RN8209D_WriteReg(Reg_HFCONST,regbuf,2);
m_memset(regbuf,0,2);
RN8209D_ReadReg(Reg_HFCONST,regbuf,2);
//启动功率
regbuf = 0x01;
regbuf = 0x2D;
RN8209D_WriteReg(Reg_PStart,regbuf,2);
regbuf = 0x01;
regbuf = 0x2D;
RN8209D_WriteReg(Reg_DStart,regbuf,2);
//计量控制
regbuf = 0x80;//电能读后清零
regbuf = 0x03;
RN8209D_WriteReg(Reg_EMUCON,regbuf,2);
//计量控制2
regbuf = 0x00;
regbuf = 0xB0;//自定义电能寄存器为B通道
RN8209D_WriteReg(Reg_EMUCON2,regbuf,2);
//B通道电流增益
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_IBGain,regbuf,2);
//A通道有功功率增益
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_GPQA,regbuf,2);
//B通道有功功率增益
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_GPQB,regbuf,2);
//A通道相位校正
regbuf = 0;
RN8209D_WriteReg(Reg_PhsA,regbuf,1);
//B通道相位校正
regbuf = 0;
RN8209D_WriteReg(Reg_PhsB,regbuf,1);
//A通道有功功率offset
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_APOSA,regbuf,2);
//B通道有功功率offset
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_APOSB,regbuf,2);
//A通道无功功率offset
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_RPOSA,regbuf,2);
//B通道无功功率offset
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_RPOSB,regbuf,2);
//A通道电流offset
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_IARMSOS,regbuf,2);
//B通道电流offset
regbuf = 0;
regbuf = 0;
RN8209D_WriteReg(Reg_IBRMSOS,regbuf,2);
//校表时不要写保护
}
}
7---------------------------------------RN8209 校表步骤------------------------------------------------------------------------
详细流程参考手册
将校表台电压设置220V,5A
(1)电压、电流系数校准
/********************************************************
功能描述: 计算电压、电流显示转换系数
参数说明:
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
void RN8209D_CalibrateKx(uint8_t phase)
{
uint8_t regbuf;
//uint32_t tempValue;
uint32_t regtemp,regtotal=0;
uint8_t i = 0;
if(phase == phase_A){
for(i=0;i<12;i++)
{
if(RN8209D_ReadReg(Reg_URMS,regbuf,3)==0){
regtemp = (regbuf<<16)+(regbuf<<8)+(regbuf);
}
delay_ms(350);
}
//第一个数据不要
for(i=1;i<12;i++){
regtotal += regtemp;
}
regtotal /= 11;
StDef_RN8209DPara_Reg.Cst_Ku = regtotal / 220;
regtotal = 0;
for(i=0;i<12;i++)
{
if(RN8209D_ReadReg(Reg_IARMS,regbuf,3)==0){
regtemp = (regbuf<<16)+(regbuf<<8)+(regbuf);
}
delay_ms(350);
}
//第一个数据不要
for(i=1;i<12;i++){
regtotal += regtemp;
}
regtotal /= 11;
StDef_RN8209DPara_Reg.Cst_Kia = regtotal / 5;
}
else if(phase == phase_B){
for(i=0;i<12;i++)
{
if(RN8209D_ReadReg(Reg_URMS,regbuf,3)==0){
regtemp = (regbuf<<16)+(regbuf<<8)+(regbuf);
}
delay_ms(350);
}
//第一个数据不要
for(i=1;i<12;i++){
regtotal += regtemp;
}
regtotal /= 11;
StDef_RN8209DPara_Reg.Cst_Ku = regtotal / 220;
regtotal = 0;
for(i=0;i<12;i++)
{
if(RN8209D_ReadReg(Reg_IBRMS,regbuf,3)==0){
regtemp = (regbuf<<16)+(regbuf<<8)+(regbuf);
}
delay_ms(350);
}
//第一个数据不要
for(i=1;i<12;i++){
regtotal += regtemp;
}
regtotal /= 11;
StDef_RN8209DPara_Reg.Cst_Kib = regtotal / 5;
}
}
(2)1.0功率校准
/********************************************************
功能描述: 误差法校准功率增益
参数说明:
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
void RN8209D_CalibrateGPQxErr(uint8_t phase,int16_t err)
{
const uint16_t regGPx[]={Reg_GPQA,Reg_GPQB};
const uint16_t regArry[]={Reg_PowerPA,Reg_PowerPB};
uint8_t regbuf;
float k = 0;
uint16_t GPQx;
uint16_t tempValue;
//判断是否是负数
if(err & 0x8000){
err &= 0x7fff;
err = -err;
}
k = (-err/10000.0)/(1+err/10000.0);
if(k > 0){
GPQx = (uint16_t)(k*32768);
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
regbuf = GPQx/256;
regbuf = GPQx%256;
RN8209D_WriteReg(regGPx,regbuf,2);
}
else{
GPQx = (uint16_t)(k*32768+65536);
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//写寄存器
regbuf = GPQx/256;
regbuf = GPQx%256;
RN8209D_WriteReg(regGPx,regbuf,2);
m_memset(regbuf,0x00,2);
RN8209D_ReadReg(regGPx,regbuf,2);
}
if(phase == phase_A){
StDef_RN8209DPara_Reg.Cst_GPQA = GPQx;
if(RN8209D_ReadReg(regArry,regbuf,2)==0){
tempValue = regbuf*256+regbuf;
//StDef_RN8209DPara_Reg.Cst_Kpa = tempValue / 1100;
}
}
else if(phase == phase_B){
StDef_RN8209DPara_Reg.Cst_GPQB = GPQx;
if(RN8209D_ReadReg(regArry,regbuf,2)==0){
tempValue = regbuf*256+regbuf;
//StDef_RN8209DPara_Reg.Cst_Kpb = tempValue / 1100;
}
}
}
(3)0.5L相位校正
将校表台电压设置220V,5A,0.5L
/********************************************************
功能描述: 误差法校准相位
参数说明:
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
void RN8209D_CalibratePhsXErr(uint8_t phase,int16_t err)
{
double k = 0;
uint8_t phsValue = 0;
const uint16_t regGPx[]={Reg_PhsA,Reg_PhsB};
uint8_t regbuf;
k = asin(-err/10000.0/1.732)*180/3.142;
if(k > 0){
phsValue = (uint8_t)(k/0.02);
}
else{
phsValue = (uint8_t)(k/0.02+512);
}
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//写寄存器
regbuf = phsValue;
RN8209D_WriteReg(regGPx,regbuf,1);
if(phase == phase_A){
StDef_RN8209DPara_Reg.Cst_PhsA = phsValue;
}
else if(phase == phase_B){
StDef_RN8209DPara_Reg.Cst_PhsB = phsValue;
}
}
(4)5% Ib 功率Offset校正
将校表台电压设置220V,0.25A,1.0
void RN8209D_CalibrateAPOSx(uint8_t phase)
{
uint8_t regbuf;
uint32_t regtemp,regtotal=0;
const uint16_t regArry[]={Reg_PowerPA,Reg_PowerPB};
const uint16_t reg_APOSArry[]={Reg_APOSA,Reg_APOSB};
const uint16_t reg_GPQxArry[]={Reg_GPQA,Reg_GPQB};
uint8_t i = 0;
uint16_t temp;
float gGPQx = 0;
double k = 0;
for(i=0;i<12;i++){
if(RN8209D_ReadReg(regArry,regbuf,4)==0){
regtemp = (regbuf<<24)+(regbuf<<16)+(regbuf<<8)+(regbuf);
//求补码
if(regtemp&0x80000000){
regtemp = ~regtemp;
regtemp += 1;
}
}
delay_ms(350);
}
//第一个数据不要
for(i=1;i<12;i++){
regtotal += regtemp;
}
regtotal /= 11;
RN8209D_ReadReg(reg_GPQxArry,regbuf,2);
temp = regbuf*256+regbuf;
if(temp&0x8000)
{
gGPQx = (temp-65536)/32768.0;
}
else{
gGPQx = temp/32768.0;
}
k = (602299-regtotal)/(1+gGPQx);
if(k > 0){
temp = (uint16_t)k;
}
else{
temp = (uint16_t)(k+65536);
}
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//写寄存器
regbuf = temp/256;regbuf = temp%256;
RN8209D_WriteReg(reg_APOSArry,regbuf,2);
if(phase == phase_A){
StDef_RN8209DPara_Reg.Cst_APOSA = temp;
}
else if(phase == phase_B){
StDef_RN8209DPara_Reg.Cst_APOSB = temp;
}
}
(5)电流Offset校正
将校表台电压设置220V,0A,1.0,只提供电压
/********************************************************
功能描述: 计算电流通道offset
参数说明:
返回说明:
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
void RN8209D_CalibrateCurrentOffset(uint8_t phase)
{
uint8_t regbuf;
uint32_t regtemp,regtotal=0;
const uint16_t regArry[]={Reg_IARMS,Reg_IBRMS};
const uint16_t regIx_OS[]={Reg_IARMSOS,Reg_IBRMSOS};
uint8_t i = 0;
uint16_t temp;
for(i=0;i<12;i++)
{
if(RN8209D_ReadReg(regArry,regbuf,3)==0){
regtemp = (regbuf<<16)+(regbuf<<8)+(regbuf);
}
delay_ms(350);
}
//第一个数据不要
for(i=1;i<12;i++){
regtotal += regtemp;
}
regtotal /= 11;
regtotal = regtotal * regtotal;
//求反码
regtotal = ~regtotal;
temp = (regtotal>>8);
//符号位
if(regtotal & 0x80000000)
temp |= 0x8000;
//写使能
regbuf = 0xE5;
RN8209D_WriteReg(WREN,regbuf,1);
//写寄存器
regbuf = temp/256;regbuf = temp%256;
RN8209D_WriteReg(regIx_OS,regbuf,2);
if(phase == phase_A){
StDef_RN8209DPara_Reg.Cst_IARMSOS = temp;
}
else if(phase == phase_B){
StDef_RN8209DPara_Reg.Cst_IBRMSOS = temp;
}
}
8---------------------------------------RN8209计量参数读取------------------------------------------------------------------------
(1)电压
/********************************************************
功能描述:
参数说明:
返回说明: 扩大10倍
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
uint8_t RN8209D_ReadVoltage(uint16_t *vol)
{
uint8_tregbuf;
uint32_t tempValue;
if(RN8209D_ReadReg(Reg_URMS,regbuf,3)==0){
tempValue = (regbuf<<16)+(regbuf<<8)+(regbuf);
if(tempValue & 0x800000){
tempValue = 0;
}
else{
*vol = (uint16_t)(tempValue*10.0/StDef_RN8209DPara_Reg.Cst_Ku);
}
return 0;
}
return 1;
}
(2)电流
/********************************************************
功能描述:
参数说明:
返回说明: 扩大1000倍
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
uint8_t RN8209D_ReadCurrent(uint8_t phase,uint16_t *current)
{
uint8_tregbuf;
uint32_t tempValue;
if(phase == phase_A){
if(RN8209D_ReadReg(Reg_IARMS,regbuf,3)==0){
tempValue = (regbuf<<16)+(regbuf<<8)+(regbuf);
if(tempValue & 0x800000){
tempValue = 0;
}
else{
*current = (uint16_t)(tempValue*1000.0/StDef_RN8209DPara_Reg.Cst_Kia);
}
return 0;
}
}
else if(phase == phase_B){
if(RN8209D_ReadReg(Reg_IBRMS,regbuf,3)==0){
tempValue = (regbuf<<16)+(regbuf<<8)+(regbuf);
if(tempValue & 0x800000){
tempValue = 0;
}
else{
*current = (uint16_t)(tempValue*1000.0/StDef_RN8209DPara_Reg.Cst_Kib);
}
return 0;
}
}
return 1;
}
(3)有功功率
/********************************************************
功能描述: 读取有功功率
参数说明:
返回说明: 扩大1000倍
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
uint8_t RN8209D_ReadPower(uint8_t phase,uint32_t *p)
{
uint8_tregbuf;
uint32_t tempValue;
if(phase == phase_A){
if(RN8209D_ReadReg(Reg_PowerPA,regbuf,4)==0){
tempValue = (regbuf<<24)+(regbuf<<16)+(regbuf<<8)+(regbuf);
if(tempValue&0x80000000){
tempValue = ~tempValue;
tempValue += 1;
}
// if(tempValue>=21903393){
// *p = (uint32_t)(tempValue*0.0000457);
// }
// else if(tempValue<21903393 && tempValue>=2190339){
// *p = (uint32_t)(tempValue*10*0.0000457);
// }
// else if(tempValue<2190339 && tempValue>=219033){
// *p = (uint32_t)(tempValue*100*0.0000457);
// }
// else if(tempValue<219033){
// *p = (uint32_t)(tempValue*1000*0.0000457);
// }
*p = (uint32_t)(tempValue*0.000457);
return 0;
}
}
else if(phase == phase_B){
if(RN8209D_ReadReg(Reg_PowerPB,regbuf,4)==0){
tempValue = (regbuf<<24)+(regbuf<<16)+(regbuf<<8)+(regbuf);
if(tempValue&0x80000000){
tempValue = ~tempValue;
tempValue += 1;
}
*p = (uint32_t)(tempValue*0.0000457);
return 0;
}
}
return 1;
}
(4)有功电能
/********************************************************
功能描述: 读取累计电量
参数说明:
返回说明: 扩大100倍
调用方式:
全局变量:
读写时间:
注意事项:
日期 :
********************************************************/
uint8_t RN8209D_ReadTotalE(uint8_t phase,uint32_t *p)
{
uint8_tregbuf;
uint32_t tempValue;
if(phase == phase_A){
if(RN8209D_ReadReg(Reg_EnergyP,regbuf,3)==0){
tempValue = (regbuf<<16)+(regbuf<<8)+(regbuf);
//*p = (uint32_t)(tempValue*100.0/1200);
*p = tempValue;
return 0;
}
}
else if(phase == phase_B){
if(RN8209D_ReadReg(Reg_EnergyD,regbuf,3)==0){
tempValue = (regbuf<<16)+(regbuf<<8)+(regbuf);
//*p = (uint32_t)(tempValue*100.0/1200);
*p = tempValue;
return 0;
}
}
return 1;
}
----------------------------------------------------------------
RN8209.C
是不是自己用来做一个功率计绰绰有余啊? 功率因数只能自己计算? 谁知道这货和ATT7053BU 有啥关系,2个芯片有好多相似之处,ATT7053里有些东西说的很明白,8209文档中就没提,搞得我验证了n次,找技术沟通也没解决,昨晚看了7053手册才明白,而且这两货都有阉割的产品,阉割的也一样 PCBBOY1991 发表于 2018-10-15 11:31
是不是自己用来做一个功率计绰绰有余啊?
精度蛮高的,误差在1% atl0402 发表于 2018-10-15 11:56
谁知道这货和ATT7053BU 有啥关系,2个芯片有好多相似之处,ATT7053里有些东西说的很明白,8209文档中就没提,搞 ...
之前用的ATT7053AU,停产了,感觉还是RN8209好一些,国网一直在用 cqfeiyu 发表于 2018-10-15 11:48
功率因数只能自己计算?
单相计量功率关注比较少 楼主辛苦了mark 电量检测 看到好多单相电表上用,,, 这个可以用在直流上的吧,可以利用内部24位的AD做个直流表头了 chaplin1999 发表于 2018-10-15 15:08
这个可以用在直流上的吧,可以利用内部24位的AD做个直流表头了
直流没用过额,没有相应的设备进行校准
楼主辛苦 EMC菜鸟 发表于 2018-10-15 15:03
看到好多单相电表上用,,,
现在有些物联网设备也在搞了 收藏一发以后有用再细细研读 资料好详细,mark,谢谢分享! 本帖最后由 atl0402 于 2018-10-16 23:45 编辑
lz不能搞个工程文件方便下载吗,
谢谢 {:smile:},楼主好人,感谢热心分享,值得借鉴! 感谢分享。 用这个芯片很久了,这是我见到最全面的资料,比FAE 提供的好多了! 楼主,你这款芯片和HLW8032 哪个更好?
https://www.amobbs.com/forum.php?mod=viewthread&tid=5680149&highlight=hlw8032&_dsign=a5103b06 谢谢楼主分享,校表台设个什么东西呢? 用过ATT7053BU,不过有些内容规格书说的不明白,还有电话技术支持才能明白。 不错,谢谢分享{:lol:}
写的很详细,谢谢分享 atl0402 发表于 2018-10-15 22:59
lz不能搞个工程文件方便下载吗,
谢谢
你好,工程不太方便,刚提供了RN8209D 程序的C文件 梨花 发表于 2018-10-18 09:08
谢谢楼主分享,校表台设个什么东西呢?
校表台能提供精度比较准备的电压、电流、相位的仪器;比如220V 5A 1.0,主要就是校准时需要输入源的参数,才能进行误差修正 光明星1号 发表于 2018-10-18 08:27
楼主,你这款芯片和HLW8032 哪个更好?
https://www.amobbs.com/forum.php?mod=viewthread&tid=5680149&hig ...
HLW8032相对于RN8209来说是应该是为了方便应用做了简化;RN8209通过校准精度可以做的相对较高(提供100Ib,5%Ib校准点),相位也可以进行校准; 非常好的东西,做的很详细的呢 数据更新率多少? wzavr 发表于 2018-10-18 11:20
数据更新率多少?
默认是350ms可以更快,手册里有的 这个电表做好后,是如何标定的?需要什么设备? Baldwin 发表于 2018-10-18 11:03
HLW8032相对于RN8209来说是应该是为了方便应用做了简化;RN8209通过校准精度可以做的相对较高(提供100Ib ...
这个精度高是源于芯片内部的AD精度高吗? 校表的话需要校准台,校准一个电表都不用五分钟。RN8209C玩过吗?这个芯片管脚少很多。 留声而过 发表于 2018-10-18 21:38
校表的话需要校准台,校准一个电表都不用五分钟。RN8209C玩过吗?这个芯片管脚少很多。 ...
2个功能是一样的,只是RN8209C只支持uart通信,RN8209D支持spi和uart通信 光明星1号 发表于 2018-10-18 20:22
这个精度高是源于芯片内部的AD精度高吗?
一个是内部精度,另外它支持多种校准手段,可以把精度提高 jiaoyi 发表于 2018-10-18 13:02
这个电表做好后,是如何标定的?需要什么设备?
需要校表台就可以 楼主分享的好 感谢楼主,单芯片计量,有些项目还是很有用的 单芯片计量对很多项目还是很有用处的,感谢分享 校表的话需要校准台,请兄台推荐个校表台,有型号和厂家最好,谢谢 谢谢分享。
jiaoyi 发表于 2018-10-20 08:33
校表的话需要校准台,请兄台推荐个校表台,有型号和厂家最好,谢谢
我们公司用的南自的 本帖最后由 guanxiaomin 于 2018-10-31 18:18 编辑
Baldwin 发表于 2018-10-22 13:10
我们公司用的南自的
您好,我参照您的程序,测出的波形对应RN8209的读写波形,但是就是没有数据反馈,MISO的数据一直是高。换了2,3块板试了都是一样,请教大神指点一二。
guanxiaomin 发表于 2018-10-31 18:12
您好,我参照您的程序,测出的波形对应RN8209的读写波形,但是就是没有数据反馈,MISO的数据一直是高。换 ...
sclk频率是多少 guanxiaomin 发表于 2018-10-31 18:12
您好,我参照您的程序,测出的波形对应RN8209的读写波形,但是就是没有数据反馈,MISO的数据一直是高。换 ...
再测试一下REFV脚电压多少 最近正在用RN8209C,感谢楼主的资料和例程!{:smile:} 校表台 用的什么型号的做类似的项目 想买一台 多谢! Halley 发表于 2018-11-18 18:47
校表台 用的什么型号的做类似的项目 想买一台 多谢!
用的南自,你也可以用新开普的;最好是借用现成的,买一台价格比较高啊 {:shocked:} 监控, 做节能功能设备,似乎用得上 请教楼主一个问题,Kp(有功系数)我翻遍了厂家提供的数据手册,都没找到,应用笔记里是有提到,但从哪里得到的呢? 请教下楼主,对于掉电的情况,怎么做到及时保存电量呢?是加掉电检测好呢?还是固定时间存储一次电量好呢? EMC菜鸟 发表于 2018-12-14 10:10
请教楼主一个问题,Kp(有功系数)我翻遍了厂家提供的数据手册,都没找到,应用笔记里是有提到,但从哪里得 ...
锐能微第三代单相计量芯片应用笔记v1.3 第19页有讲的 梨花 发表于 2019-3-31 22:27
请教下楼主,对于掉电的情况,怎么做到及时保存电量呢?是加掉电检测好呢?还是固定时间存储一次电量好呢? ...
有2种方式:
1、采用掉电存储,这种方式最可靠,平常只需要按照固定电量来存储,比如增加1度电就存储一次;等到掉电时再存储一次;
2、采用固定电量存储,存储就需要采用铁电储存器,这样可以做到0.01度电就存储一次;但是会存在电量计不满0.01度电时因为掉电导致数据丢失的情况;
另外,按照固定时间存储不可取,因为有的时间用电多,有的时间用电少;
我们是按照0.01度电储存一次+掉电储存来做的 Baldwin 发表于 2019-4-1 10:19
有2种方式:
1、采用掉电存储,这种方式最可靠,平常只需要按照固定电量来存储,比如增加1度电就存储一次 ...
好的,谢谢哈 能不能讲一下功率法校表? 电能计量IC很有用MARK 标记,收藏下,学习学习。 ztlchina 发表于 2019-4-12 14:44
能不能讲一下功率法校表?
功率校表法对稳压源的精度要求比较高,什么场合需要用到功率校表法 楼主有RN8209模块卖吗? skype 发表于 2019-4-21 14:45
楼主有RN8209模块卖吗?
你需要什么样的,隔离还是非隔离的?是否带互感器? 不好意思,要的急,在淘宝在拍了。 楼主、公司不打算买校表台、如果买一个三相或单相标准源是否可以完成校表 你的校表台是什么型号的,我也想入手一台。 atl0402 发表于 2018-10-15 11:56
谁知道这货和ATT7053BU 有啥关系,2个芯片有好多相似之处,ATT7053里有些东西说的很明白,8209文档中就没提,搞 ...
如果没记错的话,钜泉光电和锐能微最早应该是一家公司,一个在上海,一个在深圳。现在锐能微的市场份额可能更大些,主要用在入户的电表里的,量也不小。 whitekang82 发表于 2019-5-21 16:33
楼主、公司不打算买校表台、如果买一个三相或单相标准源是否可以完成校表 ...
可以校表,但是不能复校 Baldwin 发表于 2019-5-23 15:54
可以校表,但是不能复校
楼主啊,你好,我现在也要用到电量计量芯片,就是这个校准,我不知道怎么整
,我这只有一个继电保护仪,能产生三相100v的电压,三相的电流,你说的那个交表的台,是不是通过芯片输出的脉冲,直接就可以接上这个仪器, 然后通过根据误差调整软件的寄存器的值,也就是说,校准一个电表是不是都得需要两次填入寄存器的值,第一次是大概的值,第二次是根据仪器的误差值,然后计算出来寄存器的值,然后根据这个计算值,填入校表寄存器,还有一个问题就是我现在只有标准源,不用脉冲 ,不用交表台,这个误差怎么样,你觉得
liangshanguang 发表于 2019-5-30 19:26
楼主啊,你好,我现在也要用到电量计量芯片,就是这个校准,我不知道怎么整
,我这只有一个继电保护仪, ...
还有你说的复校,是不是指的是重复校准,能再说的具体点吗,拜托了{:3_59:} Baldwin 发表于 2019-5-23 15:54
可以校表,但是不能复校
楼主是不是没有进行无功校正啊,我看手册有无功校正,没有无功校正是怎么考虑的
liangshanguang 发表于 2019-5-30 19:28
还有你说的复校,是不是指的是重复校准,能再说的具体点吗,拜托了...
复校不是重复校表,而是验证初校是否正确 liangshanguang 发表于 2019-6-13 09:43
楼主是不是没有进行无功校正啊,我看手册有无功校正,没有无功校正是怎么考虑的
...
单相一般对无功不太关注,所以没有进行无功校准 Baldwin 发表于 2019-6-13 14:36
单相一般对无功不太关注,所以没有进行无功校准
感谢回答, 楼主还有一个问题,就是StDef_RN8209DPara_Reg 这个结构体是用来,写到eeprom里面的 吗,为什么要把数据都写到eeprom里面啊,这个交表的数值不是已经定下来,直接用寄存器写函数,写到芯片里面吗,还需要从eeprom里面读取,然后执行一次交表程序吗, 校准表的程序,是不是只执行一次,然后之后,只有初始化程序了, 谢谢楼主 liangshanguang 发表于 2019-6-14 16:22
感谢回答, 楼主还有一个问题,就是StDef_RN8209DPara_Reg 这个结构体是用来,写到eeprom里面的 吗,为什 ...
每块计量芯片的校表参数都不一样,没法用程序写死的 Baldwin 发表于 2019-6-14 16:33
每块计量芯片的校表参数都不一样,没法用程序写死的
那你现在的做法,是每一次上电,都初始化,就是把校准的寄存器都清0 ,然后执行校准程序 ,写入校准寄存器值 ,这这样吗, liangshanguang 发表于 2019-6-14 17:18
那你现在的做法,是每一次上电,都初始化,就是把校准的寄存器都清0 ,然后执行校准程序 ,写入校准寄存 ...
懂了,谢了,交表需要eeprom 因为交表的参数是由程序完成的,程序在有外部标准信号输入的的情况下,计算出来的,不是自己用计算器计算的,如果不保存交表数据的话,那么需要每一次都要输入标准信号,所以这个交表程序应该有一个触发信号,我又找了个工程文件,给有需要的人 mark一记 学习一下 电表的供电是不是采用隔离电源?有采用非隔离电源的 吗? zhcj66 发表于 2019-8-27 14:19
电表的供电是不是采用隔离电源?有采用非隔离电源的 吗?
如果把采样隔离就可以不用隔离电源了,用电压互感器,电流互感器 Baldwin 发表于 2019-8-27 16:23
如果把采样隔离就可以不用隔离电源了,用电压互感器,电流互感器
我问的是电表 的mcu部分供电是隔离的还是非隔离的? zhcj66 发表于 2019-8-27 16:36
我问的是电表 的mcu部分供电是隔离的还是非隔离的?
mcu非隔离,485通信隔离的 Baldwin 发表于 2019-8-27 21:59
mcu非隔离,485通信隔离的
使用的什么电源芯片? 单相计量计量仪表标定困难公司要需要一名培训合格的计量工作证的人员 电量计量芯片 lb0857 发表于 2019-8-28 08:13
单相计量计量仪表标定困难公司要需要一名培训合格的计量工作证的人员
没有这么严格的,但是要有校表台,现在都是软件自动的,不需要生产人员懂校表原理的 楼主你好,我想问一下p启动是怎么来的啊,计算功率的时候为什么要乘以0.0000457? liupeng08305 发表于 2019-11-7 11:52
楼主你好,我想问一下p启动是怎么来的啊,计算功率的时候为什么要乘以0.0000457? ...
你好,在应用手册里有讲的哦 liupeng08305 发表于 2019-11-7 11:52
楼主你好,我想问一下p启动是怎么来的啊,计算功率的时候为什么要乘以0.0000457? ...
PStart是20%P1.0 Baldwin 发表于 2019-11-7 19:30
PStart是20%P1.0
好的,谢谢,我看看应用手册!! 单相电量计 电流互感器5A意思是只能测最大5A电流吗 picobox 发表于 2019-11-7 21:57
电流互感器5A意思是只能测最大5A电流吗
不是的,一般互感器是5(60),60A是测量最大值(保证精度范围),超过60A其实也能测,只是性能会所偏差 斩波调压后的非标准正弦波的交流电用这个芯片能测量出电流和电压的有效值吗? 怎么两个PDF我都下载不了呢? 谢谢分享
不错的方案,mark 最近要用到这款芯片,非常好的资料 这电量统计芯片还支持串口通讯。方便 电能计量芯片 Mark
电能计量芯片 Mark 电能计量芯片 Mark 好贴顶起
页:
[1]
2