本帖最后由 Baldwin 于 2018-10-16 08:24 编辑
之前用了三相计量芯片RN8302,RN8302计量芯片使用经验分享
https://www.amobbs.com/thread-5697512-1-1.html
最近产品的另外一个系列需要单向计量,于是用了RN8209D,做下来效果还可以
,能满足1级的精度,实际可以做到0.5S,总的来说这款芯片还是蛮不错的;老规矩,把相关资料分享给大家,少走弯路;
以下是实验时的误差记录
误差.png (5.95 KB, 下载次数: 0)
下载附件
2018-10-15 11:13 上传
HFConst,功率转换系数,启动功率寄存器值换算方法
HFConst换算.png (26.85 KB, 下载次数: 0)
下载附件
2018-10-15 11:16 上传
1---------------------------------------硬件部分-----------------------------------------------------------------------------------
RN8209D电路.png (92.71 KB, 下载次数: 0)
下载附件
2018-10-15 10:21 上传
电压和电流都采用互感器,电压采样采用泽明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[ucK]=0x00;
- for(ucI=0;ucI<8;ucI++)
- {
- RN8209D_SCK_SET();
- delay_us(RN_CLOCKWIDTH);
- regbuf[ucK]<<=1;
- RN8209D_SCK_CLR(); //在时钟的下降沿读数据
- delay_us(RN_CLOCKWIDTH/2);
- if(RN8209D_Read_MISO())
- regbuf[ucK]=regbuf[ucK]|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[4];
- 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[ucK] & 0x80 )
- RN8209D_MOSI_SET();
- else
- RN8209D_MOSI_CLR();
- RN8209D_SCK_SET();
- delay_us(RN_CLOCKWIDTH);
- RN8209D_SCK_CLR(); //在时钟的下降沿写数据
- regbuf[ucK]<<=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[4];
- 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块,校表参数寄存器和计量参数寄存器
RN8209校表寄存器.png (137.38 KB, 下载次数: 0)
下载附件
2018-10-15 10:28 上传
RN8209计量参数寄存器.png (138.01 KB, 下载次数: 0)
下载附件
2018-10-15 10:28 上传
4---------------------------------------RN8209 特殊命令------------------------------------------------------------------------
RN8209部分寄存器进行写操作时,需要先发送写使能,才可以对寄存器操作,这点
需要注意;同时,对RN8209芯片操作时,需要先发送复位命令哦;
RN8209特殊命令.png (131.62 KB, 下载次数: 0)
下载附件
2018-10-15 10:40 上传
5---------------------------------------RN8209 初始化(非校表初始化)------------------------------------------------------------------------
RN8209参数设置.png (21.54 KB, 下载次数: 0)
下载附件
2018-10-15 10:55 上传
这是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_t Cst_PhsA; //A通道相位校正
- uint8_t Cst_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[4];
- 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[0]==0x82)&&(regbuf[1]==0x09)&&(regbuf[2]==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[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //复位
- regbuf[0] = 0xFA;
- RN8209D_WriteReg(WREN,regbuf,1);
- delay_ms(20);
- //写使能
- regbuf[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //系统控制寄存器
- regbuf[0] = 0x00;
- regbuf[1] = 0x51; //开启通道B,A、B通道增益2
- RN8209D_WriteReg(Reg_SYSCON,regbuf,2);
- m_memset(regbuf,0,2);
- RN8209D_ReadReg(Reg_SYSCON,regbuf,2);
- //写HFCONST
- regbuf[0] = 0x35;
- regbuf[1] = 0x7B;
- RN8209D_WriteReg(Reg_HFCONST,regbuf,2);
- m_memset(regbuf,0,2);
- RN8209D_ReadReg(Reg_HFCONST,regbuf,2);
- //启动功率
- regbuf[0] = 0x01;
- regbuf[1] = 0x2D;
- RN8209D_WriteReg(Reg_PStart,regbuf,2);
- regbuf[0] = 0x01;
- regbuf[1] = 0x2D;
- RN8209D_WriteReg(Reg_DStart,regbuf,2);
- //计量控制
- regbuf[0] = 0x80; //电能读后清零
- regbuf[1] = 0x03;
- RN8209D_WriteReg(Reg_EMUCON,regbuf,2);
- //计量控制2
- regbuf[0] = 0x00;
- regbuf[1] = 0xB0;
- RN8209D_WriteReg(Reg_EMUCON2,regbuf,2);
- //A通道有功功率增益
- //StDef_RN8209DPara_Reg.Cst_GPQA = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_GPQA/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_GPQA%256;
- RN8209D_WriteReg(Reg_GPQA,regbuf,2);
- //B通道有功功率增益
- //StDef_RN8209DPara_Reg.Cst_GPQB = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_GPQB/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_GPQB%256;
- RN8209D_WriteReg(Reg_GPQB,regbuf,2);
- //A通道相位校正
- //StDef_RN8209DPara_Reg.Cst_PhsA = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_PhsA;
- RN8209D_WriteReg(Reg_PhsA,regbuf,1);
- //B通道相位校正
- //StDef_RN8209DPara_Reg.Cst_PhsB = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_PhsB;
- RN8209D_WriteReg(Reg_PhsB,regbuf,1);
- //A通道有功功率offset
- //StDef_RN8209DPara_Reg.Cst_APOSA = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_APOSA/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_APOSA%256;
- RN8209D_WriteReg(Reg_APOSA,regbuf,2);
- //B通道有功功率offset
- //StDef_RN8209DPara_Reg.Cst_APOSB = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_APOSB/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_APOSB%256;
- RN8209D_WriteReg(Reg_APOSB,regbuf,2);
- //A通道无功功率offset
- StDef_RN8209DPara_Reg.Cst_RPOSA = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_RPOSA/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_RPOSA%256;
- RN8209D_WriteReg(Reg_RPOSA,regbuf,2);
- //B通道无功功率offset
- StDef_RN8209DPara_Reg.Cst_RPOSB = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_RPOSB/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_RPOSB%256;
- RN8209D_WriteReg(Reg_RPOSB,regbuf,2);
- //A通道电流offset
- //StDef_RN8209DPara_Reg.Cst_IARMSOS = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_IARMSOS/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_IARMSOS%256;
- RN8209D_WriteReg(Reg_IARMSOS,regbuf,2);
- //B通道电流offset
- //StDef_RN8209DPara_Reg.Cst_IBRMSOS = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_IBRMSOS/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_IBRMSOS%256;
- RN8209D_WriteReg(Reg_IBRMSOS,regbuf,2);
- //B通道电流增益
- StDef_RN8209DPara_Reg.Cst_IBGain = 0;
- regbuf[0] = StDef_RN8209DPara_Reg.Cst_IBGain/256;
- regbuf[1] = StDef_RN8209DPara_Reg.Cst_IBGain%256;
- RN8209D_WriteReg(Reg_IBGain,regbuf,2);
- //直流通道
- regbuf[0]=0;regbuf[1]=0;
- RN8209D_WriteReg(Reg_D2FPL,regbuf,2);
- regbuf[0]=0;regbuf[1]=0;
- RN8209D_WriteReg(Reg_D2FPH,regbuf,2);
- regbuf[0]=0;regbuf[1]=0;
- RN8209D_WriteReg(Reg_DCIAH,regbuf,2);
- regbuf[0]=0;regbuf[1]=0;
- RN8209D_WriteReg(Reg_DCIBH,regbuf,2);
- regbuf[0]=0;regbuf[1]=0;
- RN8209D_WriteReg(Reg_DCUH,regbuf,2);
- regbuf[0]=0;regbuf[1]=0;
- RN8209D_WriteReg(Reg_DCL,regbuf,2);
- //写保护
- regbuf[0] = 0xDC;
- RN8209D_WriteReg(WREN,regbuf,1);
- //获取校表寄存器校验值
- RN8209D_GetCheckSum();
- }
- return status;
- }
复制代码
6---------------------------------------RN8209 校表初始化)------------------------------------------------------------------------
- void RN8209D_CalibrateInit(void)
- {
- uint8_t regbuf[4];
- uint8_t status = 1;
- //读取RN8209 DeviceID
- if(RN8209D_ReadReg(Reg_DeviceID,regbuf,3) == 0){
- if((regbuf[0]==0x82)&&(regbuf[1]==0x09)&&(regbuf[2]==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[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //复位
- regbuf[0] = 0xFA;
- RN8209D_WriteReg(WREN,regbuf,1);
- delay_ms(20);
- //写使能
- regbuf[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //系统控制寄存器
- regbuf[0] = 0x00;
- regbuf[1] = 0x51; //开启通道B
- RN8209D_WriteReg(Reg_SYSCON,regbuf,2);
- m_memset(regbuf,0,2);
- RN8209D_ReadReg(Reg_SYSCON,regbuf,2);
- //写HFCONST
- regbuf[0] = 0x35;
- regbuf[1] = 0x7B;
- RN8209D_WriteReg(Reg_HFCONST,regbuf,2);
- m_memset(regbuf,0,2);
- RN8209D_ReadReg(Reg_HFCONST,regbuf,2);
- //启动功率
- regbuf[0] = 0x01;
- regbuf[1] = 0x2D;
- RN8209D_WriteReg(Reg_PStart,regbuf,2);
- regbuf[0] = 0x01;
- regbuf[1] = 0x2D;
- RN8209D_WriteReg(Reg_DStart,regbuf,2);
- //计量控制
- regbuf[0] = 0x80; //电能读后清零
- regbuf[1] = 0x03;
- RN8209D_WriteReg(Reg_EMUCON,regbuf,2);
- //计量控制2
- regbuf[0] = 0x00;
- regbuf[1] = 0xB0; //自定义电能寄存器为B通道
- RN8209D_WriteReg(Reg_EMUCON2,regbuf,2);
- //B通道电流增益
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_IBGain,regbuf,2);
- //A通道有功功率增益
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_GPQA,regbuf,2);
- //B通道有功功率增益
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_GPQB,regbuf,2);
- //A通道相位校正
- regbuf[0] = 0;
- RN8209D_WriteReg(Reg_PhsA,regbuf,1);
- //B通道相位校正
- regbuf[0] = 0;
- RN8209D_WriteReg(Reg_PhsB,regbuf,1);
- //A通道有功功率offset
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_APOSA,regbuf,2);
- //B通道有功功率offset
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_APOSB,regbuf,2);
- //A通道无功功率offset
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_RPOSA,regbuf,2);
- //B通道无功功率offset
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_RPOSB,regbuf,2);
- //A通道电流offset
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_IARMSOS,regbuf,2);
- //B通道电流offset
- regbuf[0] = 0;
- regbuf[1] = 0;
- RN8209D_WriteReg(Reg_IBRMSOS,regbuf,2);
- //校表时不要写保护
- }
- }
复制代码
7---------------------------------------RN8209 校表步骤------------------------------------------------------------------------
详细流程参考手册
RN8209校表流程.png (22.33 KB, 下载次数: 0)
下载附件
2018-10-15 11:04 上传
将校表台电压设置220V,5A
(1)电压、电流系数校准
- /********************************************************
- 功能描述: 计算电压、电流显示转换系数
- 参数说明:
- 返回说明:
- 调用方式:
- 全局变量:
- 读写时间:
- 注意事项:
- 日期 :
- ********************************************************/
- void RN8209D_CalibrateKx(uint8_t phase)
- {
- uint8_t regbuf[3];
- //uint32_t tempValue;
- uint32_t regtemp[12],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[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- }
- delay_ms(350);
- }
- //第一个数据不要
- for(i=1;i<12;i++){
- regtotal += regtemp[i];
- }
- 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[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- }
- delay_ms(350);
- }
- //第一个数据不要
- for(i=1;i<12;i++){
- regtotal += regtemp[i];
- }
- 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[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- }
- delay_ms(350);
- }
- //第一个数据不要
- for(i=1;i<12;i++){
- regtotal += regtemp[i];
- }
- 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[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- }
- delay_ms(350);
- }
- //第一个数据不要
- for(i=1;i<12;i++){
- regtotal += regtemp[i];
- }
- 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[5];
- 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[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- regbuf[0] = GPQx/256;
- regbuf[1] = GPQx%256;
- RN8209D_WriteReg(regGPx[phase],regbuf,2);
- }
- else{
- GPQx = (uint16_t)(k*32768+65536);
- //写使能
- regbuf[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //写寄存器
- regbuf[0] = GPQx/256;
- regbuf[1] = GPQx%256;
- RN8209D_WriteReg(regGPx[phase],regbuf,2);
- m_memset(regbuf,0x00,2);
- RN8209D_ReadReg(regGPx[phase],regbuf,2);
- }
- if(phase == phase_A){
- StDef_RN8209DPara_Reg.Cst_GPQA = GPQx;
- if(RN8209D_ReadReg(regArry[phase],regbuf,2)==0){
- tempValue = regbuf[0]*256+regbuf[1];
- //StDef_RN8209DPara_Reg.Cst_Kpa = tempValue / 1100;
- }
- }
- else if(phase == phase_B){
- StDef_RN8209DPara_Reg.Cst_GPQB = GPQx;
- if(RN8209D_ReadReg(regArry[phase],regbuf,2)==0){
- tempValue = regbuf[0]*256+regbuf[1];
- //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[5];
- 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[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //写寄存器
- regbuf[0] = phsValue;
- RN8209D_WriteReg(regGPx[phase],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[5];
- uint32_t regtemp[12],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[phase],regbuf,4)==0){
- regtemp[i] = (regbuf[0]<<24)+(regbuf[1]<<16)+(regbuf[2]<<8)+(regbuf[3]);
- //求补码
- if(regtemp[i]&0x80000000){
- regtemp[i] = ~regtemp[i];
- regtemp[i] += 1;
- }
- }
- delay_ms(350);
- }
- //第一个数据不要
- for(i=1;i<12;i++){
- regtotal += regtemp[i];
- }
- regtotal /= 11;
- RN8209D_ReadReg(reg_GPQxArry[phase],regbuf,2);
- temp = regbuf[0]*256+regbuf[1];
- 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[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //写寄存器
- regbuf[0] = temp/256;regbuf[1] = temp%256;
- RN8209D_WriteReg(reg_APOSArry[phase],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[5];
- uint32_t regtemp[12],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[phase],regbuf,3)==0){
- regtemp[i] = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- }
- delay_ms(350);
- }
- //第一个数据不要
- for(i=1;i<12;i++){
- regtotal += regtemp[i];
- }
- regtotal /= 11;
- regtotal = regtotal * regtotal;
- //求反码
- regtotal = ~regtotal;
- temp = (regtotal>>8);
- //符号位
- if(regtotal & 0x80000000)
- temp |= 0x8000;
- //写使能
- regbuf[0] = 0xE5;
- RN8209D_WriteReg(WREN,regbuf,1);
- //写寄存器
- regbuf[0] = temp/256;regbuf[1] = temp%256;
- RN8209D_WriteReg(regIx_OS[phase],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_t regbuf[3];
- uint32_t tempValue;
- if(RN8209D_ReadReg(Reg_URMS,regbuf,3)==0){
- tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- 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_t regbuf[3];
- uint32_t tempValue;
- if(phase == phase_A){
- if(RN8209D_ReadReg(Reg_IARMS,regbuf,3)==0){
- tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- 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[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- 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_t regbuf[4];
- uint32_t tempValue;
- if(phase == phase_A){
- if(RN8209D_ReadReg(Reg_PowerPA,regbuf,4)==0){
- tempValue = (regbuf[0]<<24)+(regbuf[1]<<16)+(regbuf[2]<<8)+(regbuf[3]);
- 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[0]<<24)+(regbuf[1]<<16)+(regbuf[2]<<8)+(regbuf[3]);
- 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_t regbuf[3];
- uint32_t tempValue;
- if(phase == phase_A){
- if(RN8209D_ReadReg(Reg_EnergyP,regbuf,3)==0){
- tempValue = (regbuf[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- //*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[0]<<16)+(regbuf[1]<<8)+(regbuf[2]);
- //*p = (uint32_t)(tempValue*100.0/1200);
- *p = tempValue;
- return 0;
- }
- }
- return 1;
- }
复制代码
----------------------------------------------------------------
单相计量芯片RN8209C、RN8209D用户手册_v1_7.pdf
(780.49 KB, 下载次数: 144)
2018-10-15 11:21 上传
点击文件名下载附件
锐能微第三代单相计量芯片应用笔记v1.3.pdf
(702.31 KB, 下载次数: 165)
2018-10-15 11:21 上传
点击文件名下载附件
RN8209.C
rn8209.rar
(5.08 KB, 下载次数: 127)
2018-10-16 08:24 上传
点击文件名下载附件
楼主是不是没有进行无功校正啊,我看手册有无功校正,没有无功校正是怎么考虑的
复校不是重复校表,而是验证初校是否正确
单相一般对无功不太关注,所以没有进行无功校准
每块计量芯片的校表参数都不一样,没法用程序写死的
那你现在的做法,是每一次上电,都初始化,就是把校准的寄存器都清0 ,然后执行校准程序 ,写入校准寄存器值 ,这这样吗,
一周热门 更多>