devicescript
devicescript copied to clipboard
DHT11/DHT22
** Device description **
DH11 is a popular temperature/humidity sensor, I2c.
** Datasheet, firmware, etc... **
https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
Personally I am using the DHT22, since it is a little bit better in accuracy than the dht11. I have written for Moddable a driver for the DHT11/22 using the RMT-functionality. It is based on the Espruino-implementation. I was considering to do the same in devicescript. Hence my request for the setWatch-type of functionality.
Very interresting. Could you point us to the implementation of your driver?
I have used the following class in Makecode/STS
class DHT11 {
constructor(public pin: DigitalPin) {
}
public setTimeout(callBack: Function, time: number) {
control.runInParallel(function () {
// console.log("pause voor")
pause(time);
// console.log("pause na")
callBack();
// console.log("callback klaar")
});
};
public read(
cb: (data: { raw: number[]; rh: number; t: number; err: boolean }) => void,
n = 10
) {
let d: number[];
let data: string = "";
let ht = this;
this.pin.digitalWrite(false);
this.pin.setWatch(
(t: any) => {
d.push(t > 0.00005 * 1e6 ? 1 : 0);
// console.log("CB Called");
}
);
pause(20);
this.pin.pin.setPull(PinPullMode.PullUp); // force pin state to output
pause(50)
/* this.setTimeout(() => {
this.pin.setPull(PinPullMode.PullUp)
}, 1); */
// this.setTimeout(() => {
this.pin.clearWatch(); // delete this.watch;
let cks =
this.decode(d.slice(2, 8)) +
this.decode(d.slice(10, 8)) +
this.decode(d.slice(18, 8)) +
this.decode(d.slice(26, 8));
if (cks && (cks & 0xff) == this.decode(d.slice(34, 8))) {
cb({
raw: d,
rh: this.decode(d.slice(2, 8)),
t: this.decode(d.slice(18, 8)),
err: false
});
} else {
if (n > 1) {
// this.setTimeout(() => {
pause(500)
this.read(cb, --n);
// }, 500);
} else {
cb({ raw: d, t: -1, rh: -1, err: cks > 0 });
}
}
// }, 50);
}
public decode = (omega: number[]) => {
let max = omega.length;
let result = omega[max - 1] ? 1 : 0;
let temp = 2;
for (let i = max - 2; i > -1; i--) {
result += omega[i] * temp;
temp *= 2;
}
return result;
};
}
// https://www.mouser.com/datasheet/2/758/DHT11-Technical-Data-Sheet-Translated-Version-1143054.pdf
import * as ds from "@devicescript/core"
import { pinMode, digitalWrite, subscribeDigital } from "@devicescript/gpio/src"
import { uptime } from "@devicescript/runtime/src"
type ARHT = { raw: string, absHumidity: number, humidity: number, celsius: number, fahrenheit: number }
export class dht {
#dhtPin: ds.InputPin & ds.OutputPin & ds.AnalogInPin & ds.AnalogOutPin
#lastTime: number
#result: ARHT
#raw = '' // bit-string
constructor(public dhtPin: ds.InputPin & ds.OutputPin, public dhtVCC?: ds.OutputPin) {
}
#handler = async (value: ds.DigitalValue) => {
const currentTime = await uptime()
const deltaTime = currentTime - this.#lastTime
if (value === 0) { // falling. Rising interval should be 50 microseconds
this.#raw += 0 | <any>(deltaTime > 60) // >70 => "1" 26-28 => 0
}
this.#lastTime = currentTime
}
async read(n = 10): Promise<boolean> {
if (this.dhtVCC) {
pinMode(this.dhtVCC, ds.GPIOMode.Output)
digitalWrite(this.dhtVCC, 1)
}
pinMode(this.dhtPin, ds.GPIOMode.Output)
digitalWrite(this.dhtPin, 0)
await ds.sleep(20) //?????maybe skip the first two interrupts???x
const unSubscribe = subscribeDigital(this.#dhtPin, this.#handler) //look for falling
pinMode(this.dhtPin, ds.GPIOMode.InputPullUp)
await ds.delay(50)
unSubscribe()
if (this.dhtVCC) {
pinMode(this.dhtVCC, ds.GPIOMode.Output)
digitalWrite(this.dhtVCC, 0)
}
if (this.#raw.length > 39) {
const cks =
this.#parseInt(this.#raw.slice(0, 8), 2) +
this.#parseInt(this.#raw.slice(8, 16), 2) +
this.#parseInt(this.#raw.slice(16, 24), 2) +
this.#parseInt(this.#raw.slice(24, 32), 2);
const checkSum = this.#parseInt(this.#raw.slice(32, 40), 2)
const ok = cks && ((cks & 0xFF) === checkSum)
if (ok === false) {
if (n > 1) {
await ds.delay(500)
return await this.read(--n)
}
else { return false }
}
else { return true }
}
return true
}
#parseInt = (string: string, radix: number = 2): number => {
let base = 1
let result = 0
const strArr = string.split('')
for (let i = strArr.length - 1; i >= 0; i--) {
result += parseInt(strArr[i]) * radix ** (base - 1)
base += 1
}
return result
}
#parseFloat = (number: number): number => {
return Math.round(number * 100) / 100 // emulate toFixed(2)
}
dht11 = () => {
this.#result.humidity = this.#parseInt(this.#raw.slice(0, 8), 2) + this.#parseInt(this.#raw.slice(8, 16), 2) * 0.1
this.#result.celsius = this.#parseInt(this.#raw.slice(16, 24), 2) + this.#parseInt(this.#raw.slice(24, 32), 2) * 0.1
this.#result.absHumidity = this.#parseFloat((this.#result.humidity * 0.42 * Math.exp(this.#result.celsius * 10 * 0.006235398) / 10))
this.#result.fahrenheit = 32 + this.#result.celsius * 1.8
return this.#result;
}
dht22 = () => {
this.#result.humidity = this.#parseFloat((this.#parseInt(this.#raw.slice(0, 16), 2) * 0.1))
this.#result.celsius = this.#parseFloat((this.#parseInt(this.#raw.slice(17, 32), 2) * 0.2 * (0.5 - parseInt(this.#raw[16]))))
this.#result.absHumidity = this.#parseFloat((this.#result.humidity * 0.42 * Math.exp(this.#result.celsius * 10 * 0.006235398) / 10))
this.#result.fahrenheit = 32 + this.#result.celsius * 1.8
return this.#result;
}
}
The above DHT is just a sample, which will not work. With setWatch as a replacement for subscribeDigital+upTime I assume it will work.