#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */
#define DHT11_EDGES_PREAMBLE 2 #define DHT11_BITS_PER_READ 40 /* * Note that when reading the sensor actually 84 edges are detected, but * since the last edge is not significant, we only store 83:
*/ #define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \
DHT11_EDGES_PREAMBLE + 1)
/* * Data transmission timing: * Data bits are encoded as pulse length (high time) on the data line. * 0-bit: 22-30uS -- typically 26uS (AM2302) * 1-bit: 68-75uS -- typically 70uS (AM2302) * The acutal timings also depend on the properties of the cable, with * longer cables typically making pulses shorter. * * Our decoding depends on the time resolution of the system: * timeres > 34uS ... don't know what a 1-tick pulse is * 34uS > timeres > 30uS ... no problem (30kHz and 32kHz clocks) * 30uS > timeres > 23uS ... don't know what a 2-tick pulse is * timeres < 23uS ... no problem * * Luckily clocks in the 33-44kHz range are quite uncommon, so we can * support most systems if the threshold for decoding a pulse as 1-bit * is chosen carefully. If somebody really wants to support clocks around * 40kHz, where this driver is most unreliable, there are two options. * a) select an implementation using busy loop polling on those systems * b) use the checksum to do some probabilistic decoding
*/ #define DHT11_START_TRANSMISSION_MIN 18000 /* us */ #define DHT11_START_TRANSMISSION_MAX 20000 /* us */ #define DHT11_MIN_TIMERES 34000 /* ns */ #define DHT11_THRESHOLD 49000 /* ns */ #define DHT11_AMBIG_LOW 23000 /* ns */ #define DHT11_AMBIG_HIGH 30000 /* ns */
/* num_edges: -1 means "no transmission in progress" */ int num_edges; struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
};
#ifdef CONFIG_DYNAMIC_DEBUG /* * dht11_edges_print: show the data as actually received by the * driver.
*/ staticvoid dht11_edges_print(struct dht11 *dht11)
{ int i;
dev_dbg(dht11->dev, "%d edges detected:\n", dht11->num_edges); for (i = 1; i < dht11->num_edges; ++i) {
dev_dbg(dht11->dev, "%d: %lld ns %s\n", i,
dht11->edges[i].ts - dht11->edges[i - 1].ts,
str_high_low(dht11->edges[i - 1].value));
}
} #endif/* CONFIG_DYNAMIC_DEBUG */
staticunsignedchar dht11_decode_byte(char *bits)
{ unsignedchar ret = 0; int i;
for (i = 0; i < 8; ++i) {
ret <<= 1; if (bits[i])
++ret;
}
return ret;
}
staticint dht11_decode(struct dht11 *dht11, int offset)
{ int i, t; char bits[DHT11_BITS_PER_READ]; unsignedchar temp_int, temp_dec, hum_int, hum_dec, checksum;
for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
t = dht11->edges[offset + 2 * i + 2].ts -
dht11->edges[offset + 2 * i + 1].ts; if (!dht11->edges[offset + 2 * i + 1].value) {
dev_dbg(dht11->dev, "lost synchronisation at edge %d\n",
offset + 2 * i + 1); return -EIO;
}
bits[i] = t > DHT11_THRESHOLD;
}
if (dht11->num_edges >= DHT11_EDGES_PER_READ)
complete(&dht11->completion);
}
return IRQ_HANDLED;
}
staticint dht11_read_raw(struct iio_dev *iio_dev, conststruct iio_chan_spec *chan, int *val, int *val2, long m)
{ struct dht11 *dht11 = iio_priv(iio_dev); int ret, timeres, offset;
mutex_lock(&dht11->lock); if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_boottime_ns()) {
timeres = ktime_get_resolution_ns();
dev_dbg(dht11->dev, "current timeresolution: %dns\n", timeres); if (timeres > DHT11_MIN_TIMERES) {
dev_err(dht11->dev, "timeresolution %dns too low\n",
timeres); /* In theory a better clock could become available * at some point ... and there is no error code * that really fits better.
*/
ret = -EAGAIN; goto err;
} if (timeres > DHT11_AMBIG_LOW && timeres < DHT11_AMBIG_HIGH)
dev_warn(dht11->dev, "timeresolution: %dns - decoding ambiguous\n",
timeres);
reinit_completion(&dht11->completion);
dht11->num_edges = 0;
ret = gpiod_direction_output(dht11->gpiod, 0); if (ret) goto err;
usleep_range(DHT11_START_TRANSMISSION_MIN,
DHT11_START_TRANSMISSION_MAX);
ret = gpiod_direction_input(dht11->gpiod); if (ret) goto err;
ret = request_irq(dht11->irq, dht11_handle_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
iio_dev->name, iio_dev); if (ret) goto err;
ret = wait_for_completion_killable_timeout(&dht11->completion,
HZ);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.