|
1 | 1 | 'use strict'; |
2 | 2 | const Gpio = require('pigpio').Gpio; |
| 3 | +const eventEmitter = require('events').EventEmitter; |
3 | 4 |
|
4 | 5 | module.exports = function(pin, type) { |
| 6 | + const dht = Object.create(new eventEmitter()); |
5 | 7 | const gpio = new Gpio(pin, { mode: Gpio.OUTPUT, pullUpDown: Gpio.PUD_OFF }; |
6 | 8 |
|
7 | | - gpio.trigger(80, 0); |
| 9 | + dht.reading = false; |
8 | 10 |
|
9 | | - gpio.enableAlert(); |
10 | | - gpio.disableAlert(); |
| 11 | + var lastHighTick = 0; |
| 12 | + var bits = 0; |
| 13 | + |
| 14 | + var rhumHigh = 0; |
| 15 | + var rhumLow = 0; |
| 16 | + var tempHigh = 0; |
| 17 | + var tempLow = 0; |
| 18 | + var checksum = 0; |
| 19 | + |
| 20 | + function startReading() { |
| 21 | + if (dht.reading) { |
| 22 | + // cancel out if we are already reading |
| 23 | + return false; |
| 24 | + } |
| 25 | + dht.emmit('start'); |
| 26 | + // Trigger a new relative humidity and temperature reading. |
| 27 | + // write low for 18 ms |
| 28 | + gpio.digitalWrite(0); |
| 29 | + // after that let the line go high and start reading |
| 30 | + setTimeout(() => { |
| 31 | + // reset all values |
| 32 | + bits = -2; // initialized at -2 because the first 2 lows are the ack |
| 33 | + rhumHigh = 0; |
| 34 | + rhumLow = 0; |
| 35 | + tempHigh = 0; |
| 36 | + tempLow = 0; |
| 37 | + checksum = 0; |
| 38 | + |
| 39 | + // start reading input |
| 40 | + gpio.mode(Gpio.INPUT); |
| 41 | + gpio.enableAlert(); |
| 42 | + }, 18); |
| 43 | + |
| 44 | + return true; |
| 45 | + } |
| 46 | + function endReading() { |
| 47 | + dht.reading = false; |
| 48 | + gpio.disableAlert(); |
| 49 | + gpio.mode(Gpio.OUTPUT); |
| 50 | + dht.emmit('end'); |
| 51 | + } |
11 | 52 |
|
12 | 53 | gpio.on('alert', (level, tick) => { |
13 | | - //TODO communication logic goes here |
14 | | - var startTick = 0xffffffff; // 2^32-1 or 4294967295, the max unsigned 32 bit integer |
15 | | - var endTick = 1; |
16 | | - console.log((endTick >> 0) - (startTick >> 0)); // prints 2 which is what we want |
| 54 | + // Accumulate the 40 data bits. Format into 5 bytes, humidity high, |
| 55 | + // humidity low, temperature high, temperature low, checksum. |
| 56 | + |
| 57 | + // bits are only accumulated on the low level |
| 58 | + if (level == 0) { |
| 59 | + let diff = (tick >> 0) - (lastHighTick >> 0); |
| 60 | + |
| 61 | + // Edge length determines if bit is 1 or 0. |
| 62 | + let val = 0; |
| 63 | + // low bit is between 26 and 28 µs |
| 64 | + // high bit is 70 µs |
| 65 | + // So we check on the value in between to avoid small differences |
| 66 | + if (diff >= 50) { |
| 67 | + val = 1; |
| 68 | + if (diff >= 200) { // Bad bit? |
| 69 | + checksum = 256; // Force bad checksum. |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + if (bits < 0) { |
| 74 | + // header bits |
| 75 | + // we don't need to do anything with these |
| 76 | + } else if (bits < 8) { |
| 77 | + // in humidity high byte |
| 78 | + rhumHigh = (rhumHigh << 1) + val; |
| 79 | + } else if (bits < 16) { |
| 80 | + // in humidity low byte |
| 81 | + rhumLow = (rhumLow << 1) + val; |
| 82 | + } else if (bits < 24) { |
| 83 | + // in temp high byte |
| 84 | + tempHigh = (tempHigh << 1) + val; |
| 85 | + } else if (bits < 32) { |
| 86 | + // in temp low byte |
| 87 | + tempLow = (tempLow << 1) + val; |
| 88 | + } else { |
| 89 | + // In checksum byte. |
| 90 | + checksum = (checksum << 1) + val; |
| 91 | + |
| 92 | + if (bits == 39) { |
| 93 | + // 40th bit received. |
| 94 | + endReading(); |
| 95 | + |
| 96 | + let total = rhumHigh + rhumLow + tempHigh + tempLow; |
| 97 | + |
| 98 | + // Is checksum ok? |
| 99 | + if ((total & 255) == checksum) { |
| 100 | + let rhum = ((rhumHigh << 8) + rhumLow) * 0.1; |
| 101 | + |
| 102 | + // check the temperature sign |
| 103 | + let mult = (tempHigh & 128) ? -0.1 : 0.1; |
| 104 | + tempHigh = tempHigh & 127; // strip the sign bit |
| 105 | + let temp = ((tempHigh << 8) + tempLow) * mult; |
| 106 | + |
| 107 | + dht.emit('result', { temperature: temp, humidity: rhum }); |
| 108 | + } else { |
| 109 | + dht.emmit('badChecksum'); |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + ++bits; |
| 115 | + } else if (level == 1) { |
| 116 | + lastHighTick = tick; |
| 117 | + } |
17 | 118 | }); |
18 | 119 |
|
19 | | - function trigger() { |
20 | | - //Trigger a new relative humidity and temperature reading. |
21 | | - |
22 | | - //TODO implement |
23 | | - /*self.pi.write(self.gpio, pigpio.LOW) |
24 | | - time.sleep(0.017) // 17 ms |
25 | | - self.pi.set_mode(self.gpio, pigpio.INPUT) |
26 | | - self.pi.set_watchdog(self.gpio, 200)*/ |
27 | | - } |
| 120 | + return Object.assign(dht, { |
| 121 | + gpio, |
| 122 | + read: startReading |
| 123 | + }); |
28 | 124 | }; |
0 commit comments