温度の次は湿度である。mbedでいろいろトライしてみた。
1年以上ほったらかしにしてあった湿度センサー(HS-15P)を引っ張り出す。秋月であまり気にせず買ったのだが、直流電流を流すとセンサーが壊れてしまうらしい。そのため、発振信号を入力して、抵抗測定をするという面倒なことが必要らしい。
さらに、このセンサーの面倒なことは、湿度によって抵抗が数百オームから、数Mオームまで大きく変わることである。そんな、広い範囲の抵抗値をきちんと図るのは結構難しい。テスターのオートレンジ機能がないと正確には測れない。
WEBを探してみると頑張った方がいました(ここ:リンク切れ)。
PICを使っているが、PICからPWMの信号を出力させて、その信号を入力として抵抗値を求めている。
良いことに、オートレンジの機能をいれて、小さい値の時は11倍にして信号を測定している。
ただ、残念なことに、温度補正が無く25℃固定の湿度計算しかできない。そこで少々手を加えることにした。
HS-15Pのデータシートから、抵抗値を読みとった。さらに、マニュアル線形補完をかけて温度範囲と湿度範囲を広くした。
その抵抗値をまとめたのが下の表。さらに、1℃あたりの抵抗値の減少率を10の乗数としてもとめた。
例えば、湿度40%のとき、25℃のときは220KΩ、15℃のときは630KΩである。20℃のときは220K+10^(0.042334459*(20-15))という計算式で求まる。
ある温度における、湿度 vs 抵抗値が求めることができれば、あとは同じアルゴリズムで湿度をもとめることができる。
オリジナルは、C言語のmathライブラリを使わないようにうまく処理していたが、やっぱり面倒になってLOG10とか使ってしまった。
ブレッドボードの回路図を以下のとおり。
プログラムは以下のとおり。
#include “mbed.h”
#include “math.h”
#include “TextLCD.h”
#define MAXLOOP 10
TextLCD g_lcd(dp25, dp26, dp1, dp2, dp4, dp6); // RS, E, DB4, DB5, DB6, DB7
AnalogIn temp_in(dp13);
AnalogIn temp_v1(dp9);
AnalogIn temp_v2(dp10);
AnalogIn temp_v3(dp11);
PwmOut pwmout(dp18);
double rtable[6][6] =
/* 0 20 40 60 80 100 */
{{35404472972, 499200000, 7038677, 482944, 45171, 6000}, /* -5C */
{ 7200000000, 120000000, 2000000, 140000, 18000, 2800}, /* 5C */
{ 1428571429, 30000000, 630000, 50000, 7600, 1400}, /* 15C */
{ 276545455, 7800000, 220000, 22000, 3400, 750}, /* 25C */
{ 69397590, 2400000, 83000, 9700, 1800, 410}, /* 35C */
{ 23823529, 900000, 34000, 5100, 1100, 230}}; /* 45C */
double ttable[6][6] =
/* 0 20 40 60 80 100 */
{{0.0691725637, 0.0619093331, 0.0546461024, 0.0537768739, 0.0399583150, 0.0330993219}, /* -5C */
{0.0702430536, 0.0602059991, 0.0501689446, 0.0447158031, 0.0374458913, 0.0301029996}, /* 5C */
{0.0713135435, 0.0585026652, 0.0456917869, 0.0356547324, 0.0349334675, 0.0271066772}, /* 15C */
{0.0600422134, 0.0511883361, 0.0423344588, 0.0355650947, 0.0276206412, 0.0262277407}, /* 25C */
{0.0464338289, 0.0425968732, 0.0387599175, 0.0279201558, 0.0213879820, 0.0251056021}, /* 35C */
{0.0328254445, 0.0340054104, 0.0351853762, 0.0202752170, 0.0151553228, 0.0239834635}};/* 45C */
double rtt[6] ={ 276545455, 7800000, 220000, 22000, 3400, 750} ;
float adc_average5(int channel)
{
int i;
float add ;
while (temp_v1.read() > 0.1) {
// wait(0.1);
}
while (temp_v1.read() < 0.9 ) {
// wait(0.1);
}
if ( channel == 1 ) {
add = 0;
for (i = 0; i < 5; i++) {
add += temp_v1.read() ;
wait(0.1);
}
return (add / 5);
} else if (channel ==2 ) {
add = 0;
for (i = 0; i < 5; i++) {
add += temp_v2.read() ;
wait(0.1);
}
return (add / 5);
} else if (channel ==3 ) {
add = 0;
for (i = 0; i < 5; i++) {
add += temp_v3.read() ;
wait(0.1);
}
return (add / 5);
}
return(0);
}
int main()
{
float t_temp, temp;
float v1, v2, v3 ;
int k, index, mtemp ;
double facta, factb, hum, res ;
pwmout.period(0.020);
pwmout.write(0.5);
temp=25.0;
hum=40.0;
wait(0.1);
g_lcd.cls();
wait(0.1);
g_lcd.locate(0, 0);
wait(0.1);
g_lcd.printf( “Tempsensor” );
wait(1.0);
g_lcd.cls();
wait(0.1);
while(1) {
t_temp=0.0;
v1=0;
v2=0;
v3=0;
for (k=0;k<MAXLOOP;k++){
g_lcd.locate(0, 0);
wait(0.1);
g_lcd.printf( “%d”,k );
wait(0.1);
pwmout.period(100);
pwmout.write(1.0);
wait(0.1);
temp=1.0;
while ( temp >0.99 ) {
temp = temp_in.read();
// wait(0.1);
}
t_temp+=temp;
pwmout.period(0.020);
pwmout.write(0.5);
wait(0.1);
v1+=adc_average5(1);
wait(0.1);
v2+=adc_average5(2);
wait(0.1);
v3+=adc_average5(3);
wait(0.1);
// g_lcd.locate(0, 0);
// wait(0.1);
// g_lcd.printf(“times=%d”,k );
// wait(0.0);
}
t_temp=(t_temp/MAXLOOP*3330/1000-0.6+0.055)*100 ;
v1=v1/MAXLOOP*3.33;
v2=v2/MAXLOOP*3.33;
v3=v3/MAXLOOP*3.33;
if (v3 < 3.20) {
v2 = v3 / 11;
}
res = (double)(v1 – v2) / ((double)v2 / 10000);
index=(int)((t_temp+5)/10);
mtemp=(int)(index*10+5) ;
for (k=0; k<6; k++ ){
rtt[k]=pow(10, log10(rtable[index+1][k])+(double)(mtemp-t_temp)*ttable[index][k]);
}
hum=0;
for (k=0; k<5; k++ ){
if ( res <= rtt[k] && res > rtt[k+1] ) {
facta=(log10(rtt[k+1])-log10(rtt[k]))/20 ;
factb=log10(rtt[k])-k*20*facta;
hum=(log10(res)-factb)/facta ;
break ;
}
}
g_lcd.locate(0, 0);
wait(0.1);
g_lcd.printf( “T:%4.1fC”, t_temp );
wait(0.1);
g_lcd.locate(8, 0);
wait(0.1);
g_lcd.printf( “H:%4.1f%%”, hum );
wait(0.1);
g_lcd.locate(0, 1);
wait(0.1);
g_lcd.printf( “R:%4.1f”, res );
wait(0.1);
g_lcd.locate(8, 1);
wait(0.1);
g_lcd.printf( “V2:%4.1fV”, v2 );
wait(0.1);
}
}
安定して測定できなかったので、いたるところにwait文が入っている。wait文のほとんどはいらないと思う。
結局安定して測定できなかったのは、どうも自分の出しているPWM波形で、自分自身にノイズが乗ってしまっているように思える。
温度測定のときはPWMを停止することによって、ようやく安定して測定することができた。ただし、まだ時々不安定になってしまう。
やっぱり、AVDDとAGNDは、VDDとVSSとフェライトビーズか何かで分離しないとまずいかもしれない。
苦労してせっかく作ったが、安定して測れないのでは使い物にならない。温度センサの精度も今一だしね。
ユニバーサル基盤で作り直すのは、少々考えもんだ。