|
本帖最后由 365mcu 于 2013-12-5 21:14 编辑
最近用到HR202湿敏电阻传感器。
之前的设计电路在这里http://www.amobbs.com/thread-5561567-1-1.html(原始资料里面都有就不再重复上传了)
按照手册上给的推荐电路设计好了(采用所谓RC充电方式),标定电阻能冲上电,但是通过HR202始终充不上。自己折腾了两天,也在论坛求助了,可能是使用的人少,没什么回应。
上面帖子都是我自己一个人自问自答,也算是记录了问题解决的过程吧。
原理图:(这个原理图是不正确的,但是后面找到了问题修改一下就可以了)
问题1:
对于HR202手册的理解:有两个要点Power supply: 1.5V AC(Max sine)【1.5V AC】,Operating frequency: 500Hz-2kHz【供电频率】
所以上面的电路图对于这两点是有理解的但是理解的不到位,手册中推荐的输入高电平占空比要大于低电平才能将电容冲满电的方法是不对的,因为对于湿敏电阻来说她不是一个确切的电阻。
而是Central value: 31kΩ(at 25Celsius, 1kHz ,1V AC, 60%RH)在湿度为60%的条件下对湿敏电阻提供频率1Khz 的1VAC时的阻抗。所以单纯的施加高占空比的1Khz不能体现湿敏电阻的阻抗特性。
问题2:
由于上诉方法不成功所以,我就查淘宝有卖相关模块的没有,发现销量貌似都还不错。但是都是电阻分压然后通过比较器LM393输出DO信号,也提供了所谓的AO输出接口。
模块图片如下
但是手册上明明写的要求提供交流电啊!这货能对吗?自己搭了个电路,我去毛输出没有啊。。。疑惑别人买回去还写好评的是怎么用的!
方法:
没办法了找供应商,搞了半天找到了一份资料,看着很有到里就将原来错误的电路修改了一下:
将充电电容去掉,湿敏电阻(Rh)不变,标定电阻(Rf)换成51K(接近31K即可),检测IO接到AD输入端口(我用的STM32 的PC0即ADC_IN10)。
测量方法是将Rh和Rf接口IO设置为 推挽输出,然后输出频率为1KHz的方波,两个方波相位相反(即Rh高电平时Rf低电平,Rh低电平时Rf高电平)。模拟AC输入。
然后在Rh接的IO口置位1的时候检测AI输入(在高电平中间时间采样比较准确),因为这时候相当于Rh与Rf串联,Rh接在Vcc端,中间采集到的AD对应电压就是Rf分压Vf。
所以Rf/(Rh+Rf) = Vf/Vcc,可以求得此时湿敏电阻的阻抗值然后根据阻值与温度偏移转换为湿度值。
总结:
什么事都得自己想办法解决,希望这篇帖子对以后用到HR202湿敏电阻的童鞋有帮助,节省电工们宝贵的时间啊。
注:对于手册中1.5V AC (Max),现在我使用的相当于3.3V,感觉只要提供这样一个模拟交流信号,湿敏电阻就能够达相应的阻抗特性。不知道是不是额定值误差更小呢?
对了下面附上在STM32中的相关程序,移植可用。实测精度在2%RH左右,估计软件在优化一下能达到1%。
还有对我有帮助的参考文件也在附件中,但是里面也有一点小错误,需要的仔细看看哦。
- #define HR202_CONTR1_OUT GPIOC->CRH &= 0xffffff0f;GPIOC->CRH &= 0x00000030;//湿敏电阻 Rh
- #define HR202_CONTR1_CLR GPIOC->BRR = (uint32_t)GPIO_Pin_9
- #define HR202_CONTR1_SET GPIOC->BSRR = (uint32_t)GPIO_Pin_9
- #define HR202_CONTR2_OUT GPIOC->CRH &= 0xfffffff0;GPIOC->CRH &= 0x00000003;//标定电阻 Rf
- #define HR202_CONTR2_CLR GPIOC->BRR = (uint32_t)GPIO_Pin_8
- #define HR202_CONTR2_SET GPIOC->BSRR = (uint32_t)GPIO_Pin_8
- #define HR202_CONTR2_RD GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_8)
- #define HR202_DECT_IN GPIOC->CRL &= 0xfffffff0;//模拟量输入
- //全局变量定义
- INT16U HUMI_vule,temp_vule; //湿温值
- INT32U R_Humideal_int; //湿温电阻阻值
- INT8U PwmTimeCnt = 0;
- _HR202_ADC HR202_ADCTbl;
- //求u16型数组[num]平均值,去掉最大最小值
- u16 AdcConvertAverage(u16 *p,u8 num)
- {
- u8 i;
- u16 ret=0;
- u16 max_id,min_id,max_value,min_value;
- for(i=0;i<num;i++)
- {
- ret+=(*(p+i));
- }
- //找到最大和最小值索引
- ret/=num;
- max_id=min_id=1;
- max_value=min_value=0;
- for(i=0;i<num;i++)
- {
- if((*(p+i)) > ret)
- {
- if((*(p+i)) - ret > max_value)
- {
- max_value=(*(p+i)) - ret;
- max_id=i;
- }
- }
- else
- {
- if(ret - (*(p+i)) > min_value)
- {
- min_value=ret - (*(p+i));
- min_id=i;
- }
- }
- }
-
- //去掉第一个和最大最小值后的平均值
- ret=0;
- for(i=0;i<num;i++)
- {
- if((i!=min_id)&&(i!=max_id))
- ret+=(*(p+i));
- }
- if(min_id!=max_id)
- ret = (ret+(num/2))/(num-2);
- else
- ret = (ret+(num/2))/(num-1);
- return ret;
- }
- /***************************************************************************
- *** 函数名称 : HR202Dect_Init
- *** 创建人 : xx
- *** 创建日期 : xxxx
- *** 修改人者 :
- *** 修改日期 :
- *** 输入 :
- *** 返回 :
- *** 函数功能 : AI 初始化
- ***************************************************************************/
- void HR202Dect_Init(void)
- {
- //Param 参数初始化
- for(INT8U i=0;i<10;i++)
- {
- HR202_ADCTbl.AITbl[i] = 0;//采集AD数据 10个
- }
- HR202_ADCTbl.AIEnable = OS_FALSE;//采集是否完成
- HR202_ADCTbl.AICnt = 0;//采集数量
- //Pin 初始化IO模拟输入
- HR202_DECT_IN;
- //ADC2 初始化
- ADC_InitTypeDef ADC_InitStructure;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2,ENABLE);
-
- ADC_DeInit(ADC2);
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
- ADC_InitStructure.ADC_ScanConvMode = ENABLE;
- ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
- ADC_InitStructure.ADC_NbrOfChannel = 1;
- ADC_Init(ADC2, &ADC_InitStructure);
- ADC_RegularChannelConfig(ADC2, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5); //RH
-
- ADC_DMACmd(ADC2, ENABLE);
- ADC_Cmd(ADC2, ENABLE);
- ADC_ResetCalibration(ADC2);
- while(ADC_GetResetCalibrationStatus(ADC2) == SET);
- ADC_StartCalibration(ADC2);
- while(ADC_GetCalibrationStatus(ADC2) == SET);
-
- ADC_SoftwareStartConvCmd(ADC2, ENABLE);
- }
- ///ADC2 GetValue
- INT16U HR202Dect_GetADValue(void)
- {
- INT16U GetValue = 0;
- ADC_SoftwareStartConvCmd(ADC2, ENABLE);
- GetValue = ADC_GetConversionValue(ADC2);
- return GetValue;
- }
- /*****************************************
- //湿敏电阻采集数据 返回湿敏阻值R_Humideal_int
- *****************************************/
- void dataHM_colleck(void)
- {
- INT16U ADValueTemp = 0;
- if(HR202_ADCTbl.AIEnable == OS_FALSE)
- {
- ADValueTemp = AdcConvertAverage(&HR202_ADCTbl.AITbl[0],10);
- HR202_ADCTbl.AIEnable = OS_TRUE;
- }
- //获得实际湿敏电阻阻抗值(单位Ω)
- R_Humideal_int = (51000*4096)/ADValueTemp-51000;//Rf = 51K (Rh+Rf)/Rf=Vcc/Vh;
- }
- /*****************************************
- //31K湿敏电阻获取湿度值
- *****************************************/
- void get_31HUMI_vule(void)
- {
- //分段计算湿度值
- if((R_Humideal_int/1000)>=2600) HUMI_vule=(146000-10*(R_Humideal_int/1000))*10/4800; //20-25
- else if(1300<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<2600) HUMI_vule=(91000-10*(R_Humideal_int/1000))*10/2600; //25-30
- else if(630<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<1300) HUMI_vule=(53200-10*(R_Humideal_int/1000))*10/1340; //30-35
- else if(310<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<630) HUMI_vule=(28700-10*(R_Humideal_int/1000))*10/640; //35-40
- else if(160<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<310) HUMI_vule=(15100-10*(R_Humideal_int/1000))*10/300; //40-45
- else if(87<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<160) HUMI_vule=(8170-10*(R_Humideal_int/1000))*10/146; //45-50
- else if(49<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<87) HUMI_vule=(4670-10*(R_Humideal_int/1000))*10/76; //50-55
- else if(31<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<49) HUMI_vule=(2470-10*(R_Humideal_int/1000))*10/36; //55-60
- else if(20<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<31) HUMI_vule=(1630-10*(R_Humideal_int/1000))*10/22; //60-65
- else if(13<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<20) HUMI_vule=(1110-10*(R_Humideal_int/1000))*10/14; //65-70
- else if(8<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<13) HUMI_vule=(7740-100*(R_Humideal_int/1000))*10/92;//70-75
- else if(6<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<8) HUMI_vule=(4890-100*(R_Humideal_int/1000))*10/54;//75-80
- //else if(5<=(R_Humideal_int/1000)&(R_Humideal_int/1000)<6) HUMI_vule=(2010-100*(R_Humideal_int/1000))*10/18;//80-85
- else if((R_Humideal_int/1000)<6) HUMI_vule=(388-10*(R_Humideal_int/1000))*10/4;//85-90
-
- //温度补偿0-60℃
- if(temp_vule<=25) HUMI_vule= HUMI_vule+((25-temp_vule)*2); //小于25一度加0.2
- if((25<temp_vule)&(temp_vule<=40)) HUMI_vule= HUMI_vule-((temp_vule-25)*2); //大于25一度减0.2
- if(HUMI_vule>=999) HUMI_vule=999; //大于99
- }
- static INT8U HR202_Step = 0;
- static INT8U HR202_Flag = 0;
- void HR202_TMR2_ISR(void)//100us定时器中断调用函数
- {
- if(HR202_Step == 0x00)
- {
- if(HR202_Flag == 0x00)
- {
- HR202_CONTR1_OUT;//
- HR202_CONTR2_OUT;//
- HR202_Flag = 0x10;//
- }
- else if(HR202_Flag == 0x10)
- {
- //PWM输出
- if(PwmTimeCnt > 0)
- {
- PwmTimeCnt--;
- }
- else
- {
- PwmTimeCnt = 9;
- }
- if(PwmTimeCnt>=5)//1Khz 方波
- {
- HR202_CONTR1_SET;//Rh 1
- HR202_CONTR2_CLR;//Rf 0
- }
- else
- {
- HR202_CONTR1_CLR;//Rh 0
- HR202_CONTR2_SET;//Rf 1
- }
- if(PwmTimeCnt == 2)//在Rh 为高电平时的200us 进行AD采集
- {
- if(HR202_ADCTbl.AIEnable == OS_TRUE)//是否可以采集
- {
- HR202_ADCTbl.AITbl[HR202_ADCTbl.AICnt++] = HR202Dect_GetADValue();//采集当前AD值
- if(HR202_ADCTbl.AICnt == 10)//采集10次 取平均
- {
- HR202_ADCTbl.AIEnable = OS_FALSE;//完成一组数据采集
- HR202_ADCTbl.AICnt = 0;
- }
- }
- }
- }
- }
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|