Prop driver for Sensirion SHT1x SHT7x, integer math.
Tracy Allen
Posts: 6,664
New obex object:
http://obex.parallax.com/object/517
I usually avoid using floating point if at all possible, and Cam's object is meant partly as an illustration of how to use his floating point library. My version uses Cam's driver code but the math is all-integer. The calls to ReadTemperature and ReadHumidity simply return the values in units of 1/100 degC and 1/10 %RH respectively.
http://obex.parallax.com/object/517
I usually avoid using floating point if at all possible, and Cam's object is meant partly as an illustration of how to use his floating point library. My version uses Cam's driver code but the math is all-integer. The calls to ReadTemperature and ReadHumidity simply return the values in units of 1/100 degC and 1/10 %RH respectively.
Comments
Its annoying, but also kind of fun to work all the floats out of an equation.
I'm a big fan of ** as fractional multiply, ever since working on the SHT code for the BASIC Stamp. BR's integer math is different from mine, and I'm sure there are a lot of other ways to parse it too.
Yesterday evening, I uploaded a revision. The revision is mainly in the demo, because I realized that I hadn't handled display of negative decimals quite right, and I also wanted to add code to print "NA" when the routine returns negx for timeout or range errors.
I am experimenting with humidity sensors for a friend to monitor the enviorment for his house plants.
My first experiment was over on the Ardunio side with a DHT11 and I purchased the Parallax SHT11
sensor for comparison. I did not realize there was a OBEX driver and was bit banging my own, which
has been a good exercise, but I was producing strange answers and yesterday when I saw your post I
had something to run and see if it was me or the only sensor I had was bad. I knew there was a 99.9
percent chance it was me but you never know. It was I forgot to cycle the clock at the ACQ bit location and
it thru off everything.
Tom
I see that Parallax is currently out of stock on the #28018 module on the DIP format carrier. It still is accompanied by my original Stamp code, but for the Prop there is only a link to the generic OBEX listing for sensors. Nothing specific. There should be an easier path to follow.
Tracy's Sensirion Integer Object: http://obex.parallax.com/object/517
Cam Thompson's Sensirion Demo Object: http://obex.parallax.com/object/515
75.324
75.32
75.3
75
Anyhow, here's code:
There is possibility for roundoff, for example, 75324 --> 753 --> 75.3 and 75364 --> 754 --> 75.4.
degF := (degC + 50) / 100 ' okay for positive only
or better, proper rounding for either positive or negative numbers...
degF := (degC + degC//100) / 100 ' okay for positive or negative. rounds °F*1000 off to °F*10
Keep in mind that both operators, division / and modulus // on the Prop work correctly on both positive and negative 2s complement integers.
Another way to convert °C*100 directly to °F*10 is to use the ** operator.
degF :=degC ** 773094114 + 320 ' convert degC*100 to degF*10
The multiplier is 2^32 * (18/100) = 773094114. That is okay for either positive or negative degC. Caveat: Watch out when constructing a multiplier, keep it between zero and 1/2-, that is, up to ** 2147483647.
~~~~~~~~~
Been playing around with the Sensirion code a bit more and changed it to work with an LCD instead of PST as well as turn on the backlight if the temp changes more than 1 degree and even had a version changing the color of an WS2812B RGB LED based upon temp ranges:
I think you must mean something more complicated than 102 = 10*10? Fractional powers? Those are digested by the computer using the relation z*10x = z*2x/log10(2). Then that new exponent is separated into integer and fractional parts, using the identity 2y = 2integer part of y*2fractional part of y. The integer part is saved as a shift operation to be used later. The fractional part is determined by some means, such as a lookup and interpolation in the HUB exponential table. Then multiply times z, apply the shift by the saved factor of two, and then apply the inverse of that first identity to convert back to a number with a power of 10. It is not easy in integer math, but the floating point package takes care of all of those details. Of course, floating point is at its core a number and exponent in powers of two.
Nope, just that. In the code, to vary the number of decimal places used, you divide by 10, 100, or 1000. So it would be nice to use a variable (say "decplace") set to 1, 2, or 3 for number of decimal places and then at the beginning of my routine, I can just make decplace = 10 to the decplace power. Now in my formula, when I divide by decplace, it would be 10, 100, or 1000. I guess I could easily use a lookup table or case statement, but was hoping to just use powers of 10, but stay away from floating point objects.
Actually, just realize that there are two values in the code that change depending on decimal places. So maybe a set of lookup tables would be clean. The three unique lines to obtain the decimal places:
Thanks for the compliment, I have been wondering if my code is ok or a mess, LOL. Agree with the SHT71 series. That concept was one of the reasons for the shape of my module. Several of my customers have told me the main value in mine is the quick response by being able to locate the module into the desired path of airflow easily.