Saturday, May 21, 2016

40: C++ map() function vs. the HIH-4030 Humidity Sensor
-- revised 5/22/2016 --
-- re-revised5/25/2016 --

So I got my expensive HIH sensor (explained in post 39).

tiny, isn't it

According to Honeywell's graph there is a straight line relationship between voltage output (at 5v, 20C) and relative humidity. I.e., 0.8v = 0% to 3.75v = 100%.

So I wrote this Arduino sketch:
=============
#define spr(x) Serial.print(x)   // because I'm a slow typist
#define spl(x) Serial.println(x) //      " "

void setup() {

  pinMode(A1, INPUT);
  Serial.begin(9600);
  delay(5000);
  spl("HIH-4030");
}

void loop() {

  int r = analogRead(A1);
  spr("raw: ");spr(r);
  float v = r * (5.0 / 1023.0);
  spr(", V: ");spr(v); 
  float rh = map(v, 0.8,3.75, 0.01,100.0);
  spr(", rh%: ");spl(rh);
  delay(5000);

============
This produced the following output (from Mac Coolterm):
============
raw: 297, V: 1.45, rh%: 33.00
raw: 305, V: 1.49, rh%: 33.00
raw: 289, V: 1.41, rh%: 33.00
raw: 224, V: 1.09, rh%: 33.00
raw: 651, V: 3.18, rh%: 100.00 *
raw: 526, V: 2.57, rh%: 66.00
raw: 367, V: 1.79, rh%: 33.00
raw: 322, V: 1.57, rh%: 33.00
raw: 291, V: 1.42, rh%: 33.00
raw: 278, V: 1.36, rh%: 33.00
============ * I breathed on the sensor
The "33", "66", etc.  made me suspect that while the C++ map() function happily accepts float arguments, it treats them as integers. So I wrote my own float version:
============
#define spr(x) Serial.print(x)
#define spl(x) Serial.println(x)

float mapf(float value, float istart, float istop, float ostart, float ostop) {

    return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}
void setup() {
  pinMode(A1, INPUT);
  Serial.begin(9600);
  delay(5000);
  spl("HIH-4030");
}

void loop() {

  int r = analogRead(A1);
  spr("raw: ");spr(r);
  float v = r * (5.0 / 1023.0);
  spr(", V: ");spr(v); 
  float rh = mapf(v, 0.8,3.75, 0.0,100.0);
  spr(", rh%: ");spl(int(rh));
  delay(5000);
}
============
Here's the "mapf()" output:
============
raw: 295, V: 1.44, rh%: 25
raw: 294, V: 1.44, rh%: 24
raw: 293, V: 1.43, rh%: 24
raw: 318, V: 1.55, rh%: 29
raw: 449, V: 2.19, rh%: 52 *
raw: 378, V: 1.85, rh%: 39
raw: 306, V: 1.50, rh%: 27
raw: 293, V: 1.43, rh%: 24
raw: 291, V: 1.42, rh%: 24
============ * hot breath, again
Nasty! I wonder whether the provided map() code protects against divide-by-zero? It could happen.

Now I just have to worry about why my HIH-4030 values are screwy -- readings around my house are in the 40s, at the moment.

Later: Then I moved the program to the Particle Photon. The only source change was for the 12-bit analog return (4095 instead of 1023). The Particle C++ map() function bug ("feature") was the same. But, for some reason the results were correct!
============ code:
#define spr(x) Serial.print(x)
#define spl(x) Serial.println(x)
// sensor to Photon: 5v to Vin, 0v to A1, GND to GND

float mapf(float value, float istart, float istop, float ostart, float ostop) {

    return ostart + (ostop-ostart) * ((value-istart) / (istop-istart));
}

void setup() {
  pinMode(A1, INPUT);
  Serial.begin(9600);
  delay(5000);
  spl("HIH-4030");
}

void loop() {

  int r = analogRead(A1);
  spr("raw: ");spr(r);
  float v = r * (5.0 / 4095.0);
  spr(", V: ");spr(v); 
  float rh = mapf(v, 0.8,3.75, 0.0,100.0);
  spr(", rh%: ");spl(int(rh));
  delay(5000);
}
============ ok results?
rawh: 1674, V: 2.04, rh%: 42
rawh: 1576, V: 1.92, rh%: 38
rawh: 1607, V: 1.96, rh%: 39
rawh: 1562, V: 1.91, rh%: 37
============
Finally, about the HIH readings: they vary a lot between samples so my latest code reports a weighted running average -- 3 previous readings and the latest one doubled.

Revision: I soldered the tiny board to wires -- trying to keep from frying it in the process. I found new software on Github. Now the Arduino is right (seemingly) and the Photon is too high*. The HIH-4030 is a pain. The mounting board should be bigger just to protect the sensor part.

* Because the Photon analog pins are only rated for 3.3v. It's in their Docs -- but not obvious. Forget my code. Use the more accurate code from github.

No comments:

Post a Comment