В этой статье подключим датчики DHT11 и DHT22 к Raspberry Pi, а точнее к Orange Pi PC, так как эта плата у меня есть. В принципе это не имеет значения, потому что ниже приведённые библиотеки и примеры запустятся и на Banana Pi, Odroid и NanoPi. Это что касается примеров на Java, использующие библиотеки Pi4J. А примеры на C/C++ можно запустить на все платы, на которые можно установить WiringPi.
Я раньше писал о популярных датчиках влажности и температуры DHT11 и DHT22 в статье Датчики температуры и влажности DHT11 и DHT22. Там же и документация по DHT11 и DHT22.
За основу использовалась библиотека от Adafruit — одна из стабильных версий, найденных мною в Интернете. Это Python библиотека для чтения данных с датчиков влажности и температуры DHT серии на Raspberry Pi и Beaglebone Black. Однако для чтения данных непосредственно с датчика используется язык программирования C, чтобы уменьшить вероятность ошибки во время чтения.
Библиотека C/C++
Изначально планировал сделать только на Java, так как это серия уроков по Pi4J, но решил сделать библиотеку и на C/C++, чтобы не писать отдельную статью.
DHTxx.h
#ifndef DHTXX_H_ #define DHTXX_H_ #include <stdint.h> /* * Define errors and return values. */ #define DHT_ERROR_TIMEOUT -1 #define DHT_ERROR_CHECKSUM -2 #define DHT_ERROR_ARGUMENT -3 #define DHT_ERROR_GPIO -4 #define DHT_SUCCESS 0 /* * Define sensor types. */ #define DHT11 11 #define DHT22 22 #define AM2302 22 /** * This is the only processor specific magic value, the maximum amount of time to * spin in a loop before bailing out and considering the read a timeout. This should * be a high value, but if you're running on a much faster platform than a Raspberry * Pi or Beaglebone Black then it might need to be increased. */ #define DHT_MAXCOUNT 32000 /** * Number of bit pulses to expect from the DHT. Note that this is 41 because * the first pulse is a constant 50 microsecond pulse, with 40 pulses to represent * the data afterwards. */ #define DHT_PULSES 41 class DHTxx { private: int pin; int sensor; public: DHTxx(int pin, int sensor); virtual ~DHTxx(); int init(); /** * Read DHT sensor connected to GPIO pin (using BCM numbering). Humidity and temperature will be * returned in the provided parameters. If a successfull reading could be made a value of 0 * (DHT_SUCCESS) will be returned. If there was an error reading the sensor a negative value will * be returned. Some errors can be ignored and retried, specifically DHT_ERROR_TIMEOUT or DHT_ERROR_CHECKSUM. */ int read(float* humidity, float* temperature); int getPin() const; void setPin(int pin); int getSensor() const; void setSensor(int sensor); private: /** * Busy wait delay for most accurate timing, but high CPU usage. * Only use this for short periods of time (a few hundred milliseconds at most)! */ void busyWaitMilliseconds(uint32_t millis); /** * General delay that sleeps so CPU usage is low, but accuracy is potentially bad. */ void sleepMilliseconds(uint32_t millis); /** * Increase scheduling priority and algorithm to try to get 'real time' results. */ void setMaxPriority(void); /** * Drop scheduling priority back to normal/default. */ void setDefaultPriority(void); }; #endif /* DHTXX_H_ */
init()
Инициализация GPIO и WiringPi.
int init();
read(float*, float*)
Считывает данные с датчика DHT, подключенного к выводу GPIO (с использованием нумерации WiringPi). Влажность и температура будут возвращены в заданных параметрах. Если чтение успешное, будет возвращено значение 0 (DHT_SUCCESS
). Если при считывании данных произошла ошибка, возвращается отрицательное значение. Некоторые ошибки можно игнорировать и повторять чтение, в частности DHT_ERROR_TIMEOUT
или DHT_ERROR_CHECKSUM
.
int read(float* humidity, float* temperature);
busyWaitMilliseconds(uint32_t)
Приостанавливает работу потока, в котором она была вызвана, на указанное в аргументе время, загрузка процессора высокая, а точность высокая. Используйте этот метод только в течение короткого периода времени (не более нескольких сотен миллисекунд)!
void busyWaitMilliseconds(uint32_t millis);
sleepMilliseconds(uint32_t)
Приостанавливает работу потока, в котором она была вызвана, на указанное в аргументе время, загрузка процессора низкая, но точность потенциально плохая.
void sleepMilliseconds(uint32_t millis);
setMaxPriority()
Увеличивает приоритет планирования и алгоритм, чтобы попытаться получить результаты «реального времени» (SCHED_FIFO: планировщик FIFO (First In-First Out)).
void setMaxPriority(void);
setDefaultPriority();
Сбрасывает приоритет на нормальный/по умолчанию (SCHED_OTHER: стандартный алгоритм планировщика с разделением времени).
void setDefaultPriority(void);
DHTxx.cpp
#include <stdbool.h> #include <stdlib.h> #include <errno.h> #include <sched.h> #include <string.h> #include <sys/time.h> #include <time.h> #include <wiringPi.h> #include "DHTxx.h" DHTxx::DHTxx(int pin, int sensor) { this->pin = pin; this->sensor = sensor; } DHTxx::~DHTxx() { } int DHTxx::init() { /* * Initialize GPIO library. */ if (wiringPiSetup() == -1) { return DHT_ERROR_GPIO; } return DHT_SUCCESS; } int DHTxx::read(float* humidity, float* temperature) { /* * Validate humidity and temperature arguments and set them to zero. */ if (humidity == NULL || temperature == NULL) { return DHT_ERROR_ARGUMENT; } *temperature = 0.0f; *humidity = 0.0f; /* * Store the count that each DHT bit pulse is low and high. * Make sure array is initialized to start at zero. */ uint32_t pulseCounts[DHT_PULSES * 2] = { 0 }; /* * Set pin to output. */ pinMode(pin, OUTPUT); /* * Bump up process priority and change scheduler to try to try to make process more 'real time'. */ setMaxPriority(); /* * Set pin high for ~500 milliseconds. */ digitalWrite(pin, HIGH); sleepMilliseconds(500); /* * The next calls are timing critical and care should be taken * to ensure no unnecssary work is done below. */ /* * Set pin low for ~20 milliseconds. */ digitalWrite(pin, LOW); busyWaitMilliseconds(20); /* * Set pin at input. */ pinMode(pin, INPUT); /* * Need a very short delay before reading pins or else value is sometimes still low. */ for (volatile int i = 0; i < 50; ++i) { } /* * Wait for DHT to pull pin low. */ uint32_t count = 0; while (digitalRead(pin)) { if (++count >= DHT_MAXCOUNT) { /* * Timeout waiting for response. */ setDefaultPriority(); return DHT_ERROR_TIMEOUT; } } /* * Record pulse widths for the expected result bits. */ for (int i = 0; i < DHT_PULSES * 2; i += 2) { /* * Count how long pin is low and store in pulseCounts[i] */ while (!digitalRead(pin)) { if (++pulseCounts[i] >= DHT_MAXCOUNT) { /* * Timeout waiting for response. */ setDefaultPriority(); return DHT_ERROR_TIMEOUT; } } /* * Count how long pin is high and store in pulseCounts[i+1] */ while (digitalRead(pin)) { if (++pulseCounts[i + 1] >= DHT_MAXCOUNT) { /* * Timeout waiting for response. */ setDefaultPriority(); return DHT_ERROR_TIMEOUT; } } } /* * Done with timing critical code, now interpret the results. */ /* * Drop back to normal priority. */ setDefaultPriority(); /* * Compute the average low pulse width to use as a 50 microsecond reference threshold. * Ignore the first two readings because they are a constant 80 microsecond pulse. */ uint32_t threshold = 0; for (int i = 2; i < DHT_PULSES * 2; i += 2) { threshold += pulseCounts[i]; } threshold /= DHT_PULSES - 1; /* * Interpret each high pulse as a 0 or 1 by comparing it to the 50us reference. * If the count is less than 50us it must be a ~28us 0 pulse, and if it's higher * then it must be a ~70us 1 pulse. */ uint8_t data[5] = { 0 }; for (int i = 3; i < DHT_PULSES * 2; i += 2) { int index = (i - 3) / 16; data[index] <<= 1; if (pulseCounts[i] >= threshold) { /* * One bit for long pulse. */ data[index] |= 1; } /* * Else zero bit for short pulse. */ } /* * Verify checksum of received data. */ if (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { if (sensor == DHT11) { /* * Get humidity and temp for DHT11 sensor. */ *humidity = (float) data[0]; if (data[1] > 0) { if (data[1] <= 9) { *humidity += data[1] / 10.0; } else { *humidity += data[1] / 100.0; } } *temperature = (float) data[2]; if (data[3] > 0) { if (data[3] <= 9) { *temperature += data[3] / 10.0; } else { *temperature += data[3] / 100.0; } } } else if (sensor == DHT22) { /* * Calculate humidity and temp for DHT22 sensor. */ *humidity = (data[0] * 256 + data[1]) / 10.0f; *temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0f; if (data[2] & 0x80) { *temperature *= -1.0f; } } return DHT_SUCCESS; } else { return DHT_ERROR_CHECKSUM; } } int DHTxx::getPin() const { return pin; } void DHTxx::setPin(int pin) { this->pin = pin; } int DHTxx::getSensor() const { return sensor; } void DHTxx::setSensor(int sensor) { this->sensor = sensor; } void DHTxx::busyWaitMilliseconds(uint32_t millis) { /* * Set delay time period. */ struct timeval deltatime; deltatime.tv_sec = millis / 1000; deltatime.tv_usec = (millis % 1000) * 1000; struct timeval walltime; /* * Get current time and add delay to find end time. */ gettimeofday(&walltime, NULL); struct timeval endtime; timeradd(&walltime, &deltatime, &endtime); /* * Tight loop to waste time (and CPU) until enough time as elapsed. */ while (timercmp(&walltime, &endtime, <)) { gettimeofday(&walltime, NULL); } } void DHTxx::sleepMilliseconds(uint32_t millis) { struct timespec sleep; sleep.tv_sec = millis / 1000; sleep.tv_nsec = (millis % 1000) * 1000000L; while (clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, &sleep) && errno == EINTR) ; } void DHTxx::setMaxPriority(void) { struct sched_param sched; memset(&sched, 0, sizeof(sched)); /* * Use FIFO scheduler with highest priority for the lowest chance of the kernel context switching. */ sched.sched_priority = sched_get_priority_max(SCHED_FIFO); sched_setscheduler(0, SCHED_FIFO, &sched); } void DHTxx::setDefaultPriority(void) { struct sched_param sched; memset(&sched, 0, sizeof(sched)); /* * Go back to default scheduler with default 0 priority. */ sched.sched_priority = 0; sched_setscheduler(0, SCHED_OTHER, &sched); }
Подключение DHT11 к Orange Pi One
Чтобы проверить работоспособность приведённого выше года, я подключил DHT11 к Orange Pi PC, скомпилировал и запустил ниже приведённый пример. На схеме Orange Pi One, потому что не нашёл компонент Orange Pi PC в fritzing.
Схема подключения DHT11 к Orange Pi One
Лучше использовать подтягивающий резистор на 10 кОм, при подключении резистора номинала 4.7 к — датчик не заработал.
Пример программы на C/C++
main.cpp
#include <iostream> #include <unistd.h> #include "DHTxx.h" using namespace std; int main() { float humidity; float temperature; int pin = 7; DHTxx dht11(pin, DHT11); if (dht11.init() == DHT_SUCCESS) { for (int i = 0; i < 10; ++i) { int result = dht11.read(&humidity, &temperature); switch (result) { case DHT_ERROR_TIMEOUT: cout << "DHT_ERROR_TIMEOUT" << endl; break; case DHT_ERROR_CHECKSUM: cout << "DHT_ERROR_CHECKSUM" << endl; break; case DHT_ERROR_ARGUMENT: cout << "DHT_ERROR_ARGUMENT" << endl; break; case DHT_ERROR_GPIO: cout << "DHT_ERROR_GPIO" << endl; break; case DHT_SUCCESS: cout << "humidity = " << humidity << " %" << endl; cout << "temperature = " << temperature << " °C" << endl; break; default: break; } sleep(3); } } return 0; }
Принцип работы примера
- Включаем файл
DHTxx.h
#include "DHTxx.h"
- Объявляем переменные
humidity
иtemperature
для сохранения данных температуры и относительной влажностиfloat humidity; float temperature;
- Создаём объект класса
DHTxx
. Первый параметр — это WiringPi пин, а второй — тип датчикаDHTxx dht11(pin, DHT11);
- Инициализируем датчик и продолжаем читать данные, если возвращаемый результат метода
init()
равенDHT_SUCCESS
if (dht11.init() == DHT_SUCCESS) {/*...*/}
- Создаём цикл и читаем данные при помощи метода
int result = dht11.read(&humidity, &temperature);
. Если возвращаемый результат методаread()
в переменнуюresult
равенDHT_SUCCESS
, тогда выводим температуру и влажность на экран. А если во время чтения возникла какая-то ошибка, тогда выводим на экран код ошибки.for (int i = 0; i < 10; ++i) { int result = dht11.read(&humidity, &temperature); switch (result) { case DHT_ERROR_TIMEOUT: cout << "DHT_ERROR_TIMEOUT" << endl; break; case DHT_ERROR_CHECKSUM: cout << "DHT_ERROR_CHECKSUM" << endl; break; case DHT_ERROR_ARGUMENT: cout << "DHT_ERROR_ARGUMENT" << endl; break; case DHT_ERROR_GPIO: cout << "DHT_ERROR_GPIO" << endl; break; case DHT_SUCCESS: cout << "humidity = " << humidity << " %" << endl; cout << "temperature = " << temperature << " °C" << endl; break; default: break; } sleep(3); }
- Минимальный интервал очередного чтения около двух секунд, я поставил 3.
sleep(3);
Результат
humidity = 53 % temperature = 29.1 °C DHT_ERROR_CHECKSUM humidity = 53 % temperature = 29 °C humidity = 53 % temperature = 29 °C humidity = 53 % temperature = 29 °C humidity = 53 % temperature = 29 °C humidity = 53 % temperature = 29 °C humidity = 53 % temperature = 29 °C humidity = 53 % temperature = 29 °C humidity = 52 % temperature = 28.9 °C
Подключение DHT22 к Orange Pi One
Всё вышесказанное про DHT11 подойдёт и для DHT22. Единственное отличие только в том, что, при инициализации объекта класса DHTxx
, второй параметр — это DHT22
.
DHTxx dht22(pin, DHT22);
Схема подключения DHT22 к Orange Pi One
Пример программы на C/C++
main.cpp
#include <iostream> #include <unistd.h> #include "DHTxx.h" using namespace std; int main() { float humidity; float temperature; int pin = 7; DHTxx dht22(pin, DHT22); if (dht22.init() == 0) { for (int i = 0; i < 10; ++i) { int result = dht22.read(&humidity, &temperature); switch (result) { case DHT_ERROR_TIMEOUT: cout << "DHT_ERROR_TIMEOUT" << endl; break; case DHT_ERROR_CHECKSUM: cout << "DHT_ERROR_CHECKSUM" << endl; break; case DHT_ERROR_ARGUMENT: cout << "DHT_ERROR_ARGUMENT" << endl; break; case DHT_ERROR_GPIO: cout << "DHT_ERROR_GPIO" << endl; break; case DHT_SUCCESS: cout << "humidity = " << humidity << " %" << endl; cout << "temperature = " << temperature << " °C" << endl; break; default: break; } sleep(3); } } return 0; }
Результат
humidity = 49 % temperature = 28.8 °C humidity = 49.1 % temperature = 28.8 °C humidity = 49.1 % temperature = 28.8 °C humidity = 49.1 % temperature = 28.8 °C humidity = 49.1 % temperature = 28.8 °C humidity = 49 % temperature = 28.8 °C humidity = 49 % temperature = 28.8 °C humidity = 49 % temperature = 28.8 °C humidity = 49 % temperature = 28.8 °C DHT_ERROR_TIMEOUT
Библиотека Java
С помощью инструмента Pi4J я перевёл C/C++ код на Java. Проблема Джавы в том, что при чтении данных с датчика очень часто возникают ошибки. Проблема может быть решена двумя костылями: первое — это использовать нативные методы и вызывать C/C++ функции с помощью JNI, что является более правильным решением; второе и самое простое — это запросить данные с датчика пока не получим правильный результат.
Если ещё не установили Pi4J на вашу плату перейдите на страницу Установка Pi4J на Raspberry Pi и Orange Pi, Banana Pi.
DhtData.java
Класс DhtData
содержит информацию о влажности и температуре.
package ru.micropi.pi4j.dhtxx; public class DhtData { private double temperature; private double humidity; public DhtData() { super(); } public DhtData(double temperature, double humidity) { super(); this.temperature = temperature; this.humidity = humidity; } public double getTemperature() { return temperature; } public void setTemperature(double temperature) { this.temperature = temperature; } public double getHumidity() { return humidity; } public void setHumidity(double humidity) { this.humidity = humidity; } @Override public String toString() { return "Temperature: " + temperature + "°C\nHumidity: " + humidity + "%"; } }
DHTxx.java
Интерфейс DHTxx
— это абстракция устройств DHT. Он позволяет инициализировать GPIO/WiringPi и читать данные с DHT11/DHT22.
package ru.micropi.pi4j.dhtxx; import com.pi4j.io.gpio.Pin; public interface DHTxx { public void init() throws Exception; public Pin getPin(); public void setPin(Pin pin); public DhtData getData() throws Exception; }
init()
Метод инициализирует GPIO/WiringPi, выбрасывает исключение, если это не удалось сделать.
public void init() throws Exception;
getData()
Метод считывает и проверяет данные с датчика, а после возвращает эти данные в виде объекта класса DhtData. В случае ошибки выбрасывает исключение.
public DhtData getData() throws Exception;
DHTxxBase.java
В абстрактном классе DHTxxBase реализованы методы: getPin()
, setPin()
и init()
. Также добавлен метод getRawData()
, именно здесь происходит чтение и преобразование данных с датчиков DHT11/DHT22. Эти методы являются общими для обоих датчиков.
package ru.micropi.pi4j.dhtxx; import com.pi4j.io.gpio.Pin; import com.pi4j.wiringpi.Gpio; public abstract class DHTxxBase implements DHTxx { private static final int DHT_MAXCOUNT = 32000; private static final int DHT_PULSES = 41; private Pin pin; public DHTxxBase(Pin pin) { this.pin = pin; } public Pin getPin() { return pin; } public void setPin(Pin pin) { this.pin = pin; } @Override public void init() throws Exception { /* * Initialize GPIO library. */ if (Gpio.wiringPiSetup() == -1) { throw new Exception("DHT_ERROR_GPIO"); } } protected int[] getRawData() throws Exception { /* * Store the count that each DHT bit pulse is low and high. Make sure array * is initialized to start at zero. */ int pulseCounts[] = new int[DHT_PULSES * 2]; /* * Set pin to output. */ Gpio.pinMode(pin.getAddress(), Gpio.OUTPUT); /* * Bump up process priority and change scheduler to try to try to make * process more 'real time'. */ Thread.currentThread().setPriority(Thread.MAX_PRIORITY); /* * Set pin high for ~500 milliseconds. */ Gpio.digitalWrite(pin.getAddress(), Gpio.HIGH); Gpio.delay(500); /* * The next calls are timing critical and care should be taken to ensure no * unnecessary work is done below. */ /* * Set pin low for ~20 milliseconds. */ Gpio.digitalWrite(pin.getAddress(), Gpio.LOW); Gpio.delay(20); /* * Set pin at input. */ Gpio.pinMode(pin.getAddress(), Gpio.INPUT); /* * Need a very short delay before reading pins or else value is sometimes * still low. */ /* * for (int i = 0; i < 50; ++i) {} */ /* * Wait for DHT to pull pin low. */ long count = 0; while (Gpio.digitalRead(pin.getAddress()) == 1) { if (++count >= DHT_MAXCOUNT) { /* * Timeout waiting for response. */ Thread.currentThread().setPriority(Thread.NORM_PRIORITY); throw new Exception("DHT_ERROR_TIMEOUT"); } } // Record pulse widths for the expected result bits. for (int i = 0; i < DHT_PULSES * 2; i += 2) { /* * Count how long pin is low and store in pulseCounts[i] */ while (Gpio.digitalRead(pin.getAddress()) == 0) { if (++pulseCounts[i] >= DHT_MAXCOUNT) { /* * Timeout waiting for response. */ Thread.currentThread().setPriority(Thread.NORM_PRIORITY); throw new Exception("DHT_ERROR_TIMEOUT: " + pulseCounts[i] + " pulses, " + i); } } /* * Count how long pin is high and store in pulseCounts[i+1] */ while (Gpio.digitalRead(pin.getAddress()) == 1) { if (++pulseCounts[i + 1] >= DHT_MAXCOUNT) { /* * Timeout waiting for response. */ Thread.currentThread().setPriority(Thread.NORM_PRIORITY); throw new Exception("DHT_ERROR_TIMEOUT: " + pulseCounts[i + 1] + " pulses, " + i); } } } /* * Done with timing critical code, now interpret the results. */ /* * Drop back to normal priority. */ Thread.currentThread().setPriority(Thread.NORM_PRIORITY); /* * Compute the average low pulse width to use as a 50 microsecond reference * threshold. Ignore the first two readings because they are a constant 80 * microsecond pulse. */ long threshold = 0; for (int i = 2; i < DHT_PULSES * 2; i += 2) { threshold += pulseCounts[i]; } threshold /= DHT_PULSES - 1; /* * Interpret each high pulse as a 0 or 1 by comparing it to the 50us * reference. If the count is less than 50us it must be a ~28us 0 pulse, and * if it's higher then it must be a ~70us 1 pulse. */ int data[] = new int[5]; for (int i = 3; i < DHT_PULSES * 2; i += 2) { int index = (i - 3) / 16; data[index] <<= 1; if (pulseCounts[i] >= threshold) { /* * One bit for long pulse. */ data[index] |= 1; } /* * Else zero bit for short pulse. */ } return data; } }
DHTxxBase(Pin)
Конструктор класса DHTxxBase
, как параметр получает номер пина по WiringPi, к которому подключён DHT датчик.
public DHTxxBase(Pin pin)
getRawData()
Метод считывает и преобразовывает данные с датчиков DHT11/DHT22. Возвращает массив из 5 байт, содержащий сведения о влажности, температуре и контрольной сумме. Выбрасывает исключение, если во время чтения возникла ошибка.
protected int[] getRawData() throws Exception
DHT11.java
package ru.micropi.pi4j.dhtxx; import com.pi4j.io.gpio.Pin; import com.pi4j.wiringpi.Gpio; public class DHT11 extends DHTxxBase { private static final int DHT_WAIT_INTERVAL = 2000; public DHT11(Pin pin) { super(pin); } @Override public DhtData getData() throws Exception { int atempts = 0; while (true) { try { int[] data = getRawData(); /* * Verify checksum of received data. */ if (data[4] != ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { throw new Exception("DHT_ERROR_CHECKSUM"); } /* * Get humidity and temp for DHT11 sensor. */ double humidity = data[0]; if (data[1] > 0) { if (data[1] <= 9) { humidity += data[1] / 10.0; } else { humidity += data[1] / 100.0; } } double temperature = data[2]; if (data[3] > 0) { if (data[3] <= 9) { temperature += data[3] / 10.0; } else { temperature += data[3] / 100.0; } } return new DhtData(temperature, humidity); } catch (Exception e) { atempts++; if (atempts <= 3) { Gpio.delay(DHT_WAIT_INTERVAL); continue; } throw new Exception("Atempts " + atempts, e); } } } @Override public String toString() { return "DHT11, pin: " + getPin(); } }
DHT22.java
package ru.micropi.pi4j.dhtxx; import com.pi4j.io.gpio.Pin; import com.pi4j.wiringpi.Gpio; public class DHT22 extends DHTxxBase { private static final int DHT_WAIT_INTERVAL = 2000; public DHT22(Pin pin) { super(pin); } @Override public DhtData getData() throws Exception { int atempts = 0; while (true) { try { int[] data = getRawData(); /* * Verify checksum of received data. */ if (data[4] != ((data[0] + data[1] + data[2] + data[3]) & 0xFF)) { throw new Exception("DHT_ERROR_CHECKSUM"); } /* * Calculate humidity and temp for DHT22 sensor. */ double humidity = (data[0] * 256 + data[1]) / 10.0; double temperature = ((data[2] & 0x7F) * 256 + data[3]) / 10.0; if ((data[2] & 0x80) != 0) { temperature *= -1.0f; } return new DhtData(temperature, humidity); } catch (Exception e) { atempts++; if (atempts <= 3) { Gpio.delay(DHT_WAIT_INTERVAL); continue; } throw new Exception("Atempts " + atempts, e); } } } @Override public String toString() { return "DHT22, pin: " + getPin(); } }
Классы DHT11
и DHT22
расширяют класс DHTxxBase
, переопределён конструктор класса и реализован метод getData()
.
getData()
Метод getData()
классов DHT11
и DHT22
почти одинаковые, отличаются лишь тем, как преобразовываются данные в градусах цельсия и процентах. Полученные данные возвращаются в виде объекта класс DhtData
.
public DhtData getData() throws Exception {}
Из-за того, что очень часто при чтении возникают ошибки, функция пытается считывать данные из датчика до первой удачной попытки. Количество попыток ограничено 3.
if (atempts <= 3) { Gpio.delay(DHT_WAIT_INTERVAL); continue; }
Если не удалось получить результат, тогда выбрасывается исключение.
Проблема в том, Raspberry Pi/Orange Pi не работают в режиме реального времени, то есть, программные задержки не всегда точны и это приводит к ошибкам при считывании данных.
Работа с DHT11 из Java
Ниже приведён пример программы, которая 10 запрашивает данные с интервалом в 2 секунд и выводит результат в терминале. Для DHT11 нужно создать экземпляр класса DHT11
.
DHTxx dht11 = new DHT11(OrangePiPin.GPIO_07);
Схема подключения DHT11 к Orange Pi One
Пример программы на Java, DHT11Test.java
package ru.micropi.pi4j.dhtxx.tests; import ru.micropi.pi4j.dhtxx.DHT11; import ru.micropi.pi4j.dhtxx.DHTxx; import com.pi4j.io.gpio.OrangePiPin; public class DHT11Test { private static final int DHT_WAIT_INTERVAL = 2000; public static void main(String[] args) { DHTxx dht11 = new DHT11(OrangePiPin.GPIO_07); System.out.println(dht11); try { dht11.init(); for (int i = 0; i < 10; i++) { try { System.out.println(dht11.getData()); Thread.sleep(DHT_WAIT_INTERVAL); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e1) { e1.printStackTrace(); } } }
Результат
DHT11, pin: GPIO 7 Temperature: 28.6°C Humidity: 54.0% Temperature: 28.6°C Humidity: 53.0% Temperature: 28.6°C Humidity: 53.0% Temperature: 28.6°C Humidity: 52.0% Temperature: 28.6°C Humidity: 52.0% Temperature: 28.6°C Humidity: 52.0% Temperature: 28.6°C Humidity: 52.0% Temperature: 28.6°C Humidity: 52.0% Temperature: 28.6°C Humidity: 51.0% Temperature: 28.6°C Humidity: 51.0%
Работа с DHT22 из Java
Для работы с DHT22 создаём экземпляр класса DHT22
, в остальном всё то же самое как и с DHT11.
DHTxx dht22 = new DHT22(OrangePiPin.GPIO_07);
Схема подключения DHT22 к Orange Pi One
Пример программы на Java, DHT22Test.java
package ru.micropi.pi4j.dhtxx.tests; import ru.micropi.pi4j.dhtxx.DHT22; import ru.micropi.pi4j.dhtxx.DHTxx; import com.pi4j.io.gpio.OrangePiPin; public class DHT22Test { private static final int DHT_WAIT_INTERVAL = 2000; public static void main(String[] args) { DHTxx dht22 = new DHT22(OrangePiPin.GPIO_07); System.out.println(dht22); try { dht22.init(); for (int i = 0; i < 10; i++) { try { System.out.println(dht22.getData()); Thread.sleep(DHT_WAIT_INTERVAL); } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e1) { e1.printStackTrace(); } } }
Результат
DHT22, pin: GPIO 7 Temperature: 28.3°C Humidity: 48.7% Temperature: 28.3°C Humidity: 48.6% Temperature: 28.3°C Humidity: 48.9% Temperature: 28.3°C Humidity: 48.5% Temperature: 28.3°C Humidity: 48.5% Temperature: 28.3°C Humidity: 48.5% Temperature: 28.2°C Humidity: 48.4% Temperature: 28.3°C Humidity: 48.5% Temperature: 28.2°C Humidity: 48.4% Temperature: 28.3°C Humidity: 48.5%
Проекты Eclipse
DHT11 — Eclipse C++
DHTxx — Eclipse Java
Материалы
Adafruit Python DHT Sensor Library
Датчики температуры и влажности DHT11 и DHT22
Проект OpenNet: MAN sched_setscheduler (2) Системные вызовы (FreeBSD и Linux)
Отличная статья!Жаль нет пошаговой инструкции для чайников.Будем разбираться 🙂
Здравствуйте, спасибо за ваше руководство. Когда я запускаю программу, время от времени я получаю следующую ошибку. Мой метод использует аннотацию @Scheduled (fixedRate = 10000). Как ее решить?
java.lang.Exception: Atempts 4
Caused by: java.lang.Exception: DHT_ERROR_TIMEOUT: 32000 pulses, 70
at ru.micropi.pi4j.dhtxx.DHTxxBase.getRawData(DHTxxBase.java:119)
at ru.micropi.pi4j.dhtxx.DHT22.getData(DHT22.java:19)
Здравствуйте. Что-то не получается скомпилировать C++
/tmp/ccRZ5e8m.o: In function `main’:
/dht22/cpp/dht.cpp:12: undefined reference to `DHTxx::DHTxx(int, int)’
/dht22/cpp/dht.cpp:14: undefined reference to `DHTxx::init()’
/dht22/cpp/dht.cpp:16: undefined reference to `DHTxx::read(float*, float*)’
/dht22/cpp/dht.cpp:12: undefined reference to `DHTxx::~DHTxx()’
/dht22/cpp/dht.cpp:12: undefined reference to `DHTxx::~DHTxx()’
Добрый день!
при компиляции получаю ошибку
DHTxx.cpp:256:1: error: stray ‘\177’ in program
датчик dht22
))) сам дурак, все поправил.
Подскажите еще такой момент, чем теперь удобнее собирать данные в файл или еще лучше прикрутить график для удаленного мониторинга?
Насколько я понимаю это уже в perl или python, что лучше выбрать?
Ранее программированием не занимался.
Ошибка компиляции 🙁
sudo g++ -o app main.cpp DHTxx.cpp
/usr/bin/ld: /tmp/cccirMw9.o: in function `DHTxx::init()’:
DHTxx.cpp:(.text+0x88): undefined reference to `wiringPiSetup’
/usr/bin/ld: /tmp/cccirMw9.o: in function `DHTxx::read(float*, float*)’:
DHTxx.cpp:(.text+0x110): undefined reference to `pinMode’
/usr/bin/ld: DHTxx.cpp:(.text+0x12a): undefined reference to `digitalWrite’
/usr/bin/ld: DHTxx.cpp:(.text+0x148): undefined reference to `digitalWrite’
/usr/bin/ld: DHTxx.cpp:(.text+0x164): undefined reference to `pinMode’
/usr/bin/ld: DHTxx.cpp:(.text+0x1a4): undefined reference to `digitalRead’
/usr/bin/ld: DHTxx.cpp:(.text+0x200): undefined reference to `digitalRead’
/usr/bin/ld: DHTxx.cpp:(.text+0x266): undefined reference to `digitalRead’
Что еще можно сделать, куда копать ?
Судя по комментариям на гите, библиотеку под BPI-M2 делали с BPI-M3, а позже платы стали отличаться распайкой пинов, и поддежку моей платы выпилили.
По указанной Вами ссылке ставил:
home@banana:/mnt/lan/cc/BPI-WiringPi$ gpio readall
Unable to determine hardware version. I see: Hardware : Allwinner sun8i Family
,
— expecting BCM2708 or BCM2709. Please report this to projects@drogon.net
Спасибо большое за участие но пожалуй вернусь к спайке Banan PiArduino
cheapest online pharmacy india top 10 online pharmacy in india reputable indian pharmacies
reputable indian pharmacies: reputable indian pharmacies — india pharmacy
https://canadianpharmacy.win/# reputable canadian online pharmacy
https://canadianpharmacy.win/# northern pharmacy canada
onlinepharmaciescanada com best online canadian pharmacy best online canadian pharmacy
https://mexicanpharmacy.store/# pharmacies in mexico that ship to usa
http://canadianpharmacy.win/# pharmacies in canada that ship to the us
http://indianpharmacy.win/# world pharmacy india
mexican online pharmacies prescription drugs: medication from mexico pharmacy — mexico pharmacies prescription drugs
http://indianpharmacy.win/# best online pharmacy india
https://canadianpharmacy.win/# canadian pharmacy meds review
northern pharmacy canada canadian pharmacy world safe reliable canadian pharmacy
https://mexicanpharmacy.store/# mexican drugstore online
http://canadianpharmacy.win/# legal to buy prescription drugs from canada
https://mexicanpharmacy.store/# mexico pharmacies prescription drugs
http://indianpharmacy.win/# pharmacy website india
mexican drugstore online: buying from online mexican pharmacy — mexican mail order pharmacies
online shopping pharmacy india: indian pharmacy — Online medicine home delivery
http://indianpharmacy.win/# Online medicine order
https://mexicanpharmacy.store/# pharmacies in mexico that ship to usa
http://mexicanpharmacy.store/# best online pharmacies in mexico
https://canadianpharmacy.win/# real canadian pharmacy
http://mexicanpharmacy.store/# pharmacies in mexico that ship to usa
medication from mexico pharmacy: medication from mexico pharmacy — pharmacies in mexico that ship to usa
canada pharmacy world: best online canadian pharmacy — canadian drugs
https://mexicanpharmacy.store/# medication from mexico pharmacy
https://indianpharmacy.win/# best india pharmacy
canadian world pharmacy canadian pharmacies that deliver to the us canadian compounding pharmacy
http://mexicanpharmacy.store/# best online pharmacies in mexico
http://canadianpharmacy.win/# canadian pharmacy drugs online
http://mexicanpharmacy.store/# medicine in mexico pharmacies
mexican rx online medicine in mexico pharmacies buying from online mexican pharmacy
https://indianpharmacy.win/# pharmacy website india
http://mexicanpharmacy.store/# mexican rx online
http://mexicanpharmacy.store/# mexico drug stores pharmacies
best canadian pharmacy online: best online canadian pharmacy — trustworthy canadian pharmacy
https://fastpillseasy.com/# cheapest ed medication
viagra without prescription: buy viagra online — viagra without prescription
https://maxpillsformen.com/# Generic Cialis price
how to get ed pills: fast pills easy — cheap erectile dysfunction pills
http://maxpillsformen.com/# Buy Tadalafil 10mg
https://fastpillseasy.com/# best online ed medication
Generic Cialis without a doctor prescription Generic Cialis without a doctor prescription cheapest cialis
Cialis over the counter Generic Cialis without a doctor prescription Buy Tadalafil 5mg
https://maxpillsformen.com/# Buy Tadalafil 10mg
http://maxpillsformen.com/# cheapest cialis
Generic Viagra online: FastPillsForMen — generic sildenafil
п»їed pills online erectile dysfunction meds online ed prescription online
Tadalafil Tablet MaxPillsForMen.com Cialis 20mg price in USA
ed pills cheap: FastPillsEasy — where can i get ed pills
where can i get ed pills: fast pills easy — cheapest ed online
http://maxpillsformen.com/# buy cialis pill
http://gss-online.ru/bitrix/redirect.php?goto=https://t.me/s/bonus_za_registratsiyu_bez_depa
viagra without prescription: cheap viagra — Buy Viagra online cheap
покерные школы
покерные школы онлайн
академия покера вход в личный кабинет
https://t.me/s/officiallwebsitethePoker_Ac
http://maps.google.lu/url?q=https%3A%2F%2Ft.me/s/bonus_za_registratsiyu_bez_depa
viagra canada cheap viagra Cheapest Sildenafil online
Buy Tadalafil 5mg Max Pills For Men Generic Tadalafil 20mg price
Buy Tadalafil 20mg: Max Pills For Men — Buy Tadalafil 5mg
Cheap generic Viagra online: Fast Pills For Men — Buy generic 100mg Viagra online
курс по покеру бесплатно
слив курсов по покеру
академия покера вход в личный кабинет
https://t.me/s/poker_academy_login
лучшая школа покера в москве
московская школа покера
курс по покеру бесплатно
курс по покеру бесплатно скачать
школа покера бесплатно
бесплатная школа онлайн покера
академия покера официальный сайт
академия покера сайт
https://fastpillseasy.com/# cheap ed
Generic Cialis price: buy cialis online — Cialis over the counter
ed doctor online: cheap ed — best online ed meds
школа покера дмитрия лесного
покерная школа дмитрия лесного
https://maxpillsformen.com/# Generic Cialis price
mtt poker school курс
https://t.me/s/poker_schools2
https://maxpillsformen.com/# Generic Tadalafil 20mg price
лучшая школа игры в покер
https://t.me/s/shkola_igry_v_poker
cheapest cialis: MaxPillsForMen.com — Generic Tadalafil 20mg price
ed meds by mail online erectile dysfunction ed medicines
buy cialis pill MaxPillsForMen Buy Cialis online
академия покера сайт
на сайте академия покера
академия покера сайт
на сайте академия покера
Buy Tadalafil 10mg: MaxPillsForMen — Buy Tadalafil 5mg
https://maxpillsformen.com/# Tadalafil price
buy Viagra online: Fast Pills For Men — cheapest viagra
Generic Cialis price: MaxPillsForMen.com — Cheap Cialis
Cialis without a doctor prescription: Tadalafil Tablet — Cheap Cialis
ed medications cost: online ed medication — erectile dysfunction pills online
http://maxpillsformen.com/# Tadalafil Tablet
online erectile dysfunction pills cheap cialis online ed prescription
Buy Tadalafil 5mg: Max Pills For Men — п»їcialis generic
https://maxpillsformen.com/# cialis for sale
sildenafil 50 mg price: cheap viagra — buy viagra here
https://fastpillseasy.com/# best ed meds online
cheapest cialis: Tadalafil price — cheapest cialis
игра в покер обучение видео
игра в покер онлайн с обучением
Buy Cialis online Generic Cialis without a doctor prescription Generic Cialis without a doctor prescription
cheap ed drugs cheapest ed medication cheap ed drugs
быстрое обучение игры в покер
игра в покер обучение
https://maxpillsformen.com/# Buy Tadalafil 10mg
онлайн школа покера
лучшая онлайн школа покера
Generic Cialis without a doctor prescription: MaxPillsForMen — Tadalafil price
ed meds cheap cheap cialis ed online pharmacy
покер обучение с нуля онлайн бесплатно
покер онлайн игра обучение бесплатно
обучение покеру онлайн бесплатно
покер обучение с нуля онлайн бесплатно
online ed meds: boner pills online — cheap ed pills
Generic Tadalafil 20mg price Generic Cialis price cheapest cialis
https://fastpillseasy.com/# online ed meds
ed meds cheap: FastPillsEasy — online ed medications
http://fastpillsformen.com/# Viagra online price
https://maxpillsformen.com/# Cheap Cialis
Viagra tablet online: Fast Pills For Men — order viagra
как играть в покер обучение
обучение покеру
обучение игры в покер бесплатно
как играть в покер обучение
http://maxpillsformen.com/# Generic Cialis price
https://maxpillsformen.com/# Generic Tadalafil 20mg price
Cheap Cialis: Max Pills For Men — Buy Tadalafil 5mg
академия покера войти
академия покера вход на сайт
Cialis 20mg price: cialis for sale — Generic Cialis price
erectile dysfunction medicine online: ed pills — cheap erection pills
Buy Tadalafil 20mg [url=http://maxpillsformen.com/#]buy cialis online[/url] п»їcialis generic
cheapest cialis MaxPillsForMen.com Generic Cialis price
онлайн школа покера
лучшая онлайн школа покера
игра в покер обучение с нуля бесплатно
игра в покер обучение с нуля видео
https://maxpillsformen.com/# Tadalafil Tablet
cheap boner pills buy ed medication online get ed meds today
Buy Tadalafil 5mg Generic Cialis price Cialis 20mg price
уроки покера
покер видео уроки
https://maxpillsformen.com/# Generic Tadalafil 20mg price
cheap viagra: cheap viagra — Viagra online price
лучшая онлайн школа покера
интернет школа покера
ed medicine online: fast pills easy — cheap ed pills online
cheap viagra sildenafil over the counter over the counter sildenafil
Viagra without a doctor prescription Canada Fast Pills For Men Generic Viagra online
Buy Tadalafil 10mg: Tadalafil price — Cialis 20mg price
научиться играть в покер онлайн с нуля
научиться играть в покер онлайн по видео
научиться играть в покер онлайн
научиться играть в покер онлайн бесплатно
уроки покера для начинающих с нуля
уроки покера для начинающих бесплатно
покер обучение онлайн играть бесплатно для новичков
https://t.me/s/Poker_trainingonline
slot oyunlar? puf noktalar? az parayla cok kazandiran slot oyunlar? slot oyunlar?
denemebonusuverensiteler25: yat?r?ms?z deneme bonusu veren siteler — yeni deneme bonusu veren siteler
покер обучение с нуля играть бесплатно
https://t.me/s/poker_obuchenie_s_nulya
покер обучение с нуля играть бесплатно
https://t.me/s/poker_obuchenie_s_nulya
sweet bonanza guncel: sweet bonanza kazanma saatleri — sweet bonanza slot
http://slotsiteleri25.com/# en cok kazand?ran slot oyunlar?
yeni deneme bonusu veren siteler deneme bonusu veren yeni siteler deneme bonusu veren yeni siteler
deneme bonusu veren siteler yeni deneme bonusu veren yeni siteler deneme bonusu veren siteler yeni
slot casino siteleri: az parayla cok kazandiran slot oyunlar? — slot siteleri
обучение игры в покер онлайн с нуля
https://t.me/s/obuchenie_igry_v_poker
slot oyunlar? puf noktalar?: guvenilir slot siteleri — slot siteleri
Casino Siteleri: casinoda en Г§ok kazandД±ran oyun — en guvenilir casino siteleri
https://sweetbonanza25.com/# sweet bonanza slot
sweet bonanza oyna sweet bonanza yorumlar sweet bonanza guncel
sweet bonanza kazanma saatleri: sweet bonanza — sweet bonanza slot
guvenilir slot siteleri: slot casino siteleri — az parayla cok kazandiran slot oyunlar?
guvenilir slot siteleri: slot oyunlar? — en kazancl? slot oyunlar?
https://sweetbonanza25.com/# sweet bonanza guncel
https://denemebonusuverensiteler25.com/# deneme bonusu veren siteler yeni
sweet bonanza giris sweet bonanza guncel sweet bonanza oyna
Deneme Bonusu Veren Siteler: en guvenilir casino siteleri — guvenilir casino siteleri
https://denemebonusuverensiteler25.com/# denemebonusuverensiteler25
deneme bonusu veren siteler yat?r?ms?z deneme bonusu veren siteler yat?r?ms?z deneme bonusu veren siteler
deneme bonusu veren gГјvenilir siteler guvenilir casino siteleri Canl? Casino Siteleri
deneme bonusu veren casino siteleri: Canl? Casino Siteleri — guvenilir casino siteleri
slot oyunlar?: slot oyunlar? — en cok kazand?ran slot oyunlar?
Deneme Bonusu Veren Siteler: en guvenilir casino siteleri — Canl? Casino Siteleri
slot oyunlar? puf noktalar?: en cok kazand?ran slot oyunlar? — slot casino siteleri
slot siteleri: guvenilir slot siteleri — en kazancl? slot oyunlar?
casino en iyi siteler
deneme bonusu veren siteler yeni deneme bonusu veren siteler yat?r?ms?z deneme bonusu veren siteler
покерное обучение для новичков
покерное обучение по видео
покерное обучение онлайн
покерное обучение бесплатно
casino bahis siteleri: Deneme Bonusu Veren Siteler — en guvenilir casino siteleri
guvenilir slot siteleri: slot oyunlar? — slot casino siteleri
en yeni bet siteleri
deneme bonusu veren siteler yeni yeni deneme bonusu veren siteler deneme bonusu veren yeni siteler
slot oyunlar? puf noktalar? en cok kazand?ran slot oyunlar? slot siteleri
покер онлайн научиться
научится играть в покер онлайн
как научится играть в покер онлайн
https://t.me/s/poker_onlayn_nauchitsya_igrat
canl? casino siteleri: Canl? Casino Siteleri — Canl? Casino Siteleri
sweet bonanza kazanma saatleri: sweet bonanza oyna — sweet bonanza slot
sweet bonanza giris: sweet bonanza oyna — sweet bonanza
обучение покеру с нуля онлайн
обучение покеру с нуля онлайн бесплатно
обучение покеру с нуля онлайн видео
https://t.me/s/obuchenie_pokeru_s_nulya_onlayn
denemebonusuverensiteler25 deneme bonusu veren siteler yeni deneme bonusu veren yeni siteler
casino: Canl? Casino Siteleri — canl? casino siteleri
yat?r?ms?z deneme bonusu veren siteler: yat?r?ms?z deneme bonusu veren siteler — deneme bonusu veren siteler yeni
sweet bonanza yorumlar: sweet bonanza guncel — sweet bonanza
уроки покера онлайн бесплатно
уроки покера в интернете
уроки в онлайн покер
уроки покера онлайн бесплатно
https://denemebonusuverensiteler25.com/# yeni deneme bonusu veren siteler
sweet bonanza demo oyna: sweet bonanza giris — sweet bonanza demo oyna
Casino Siteleri canl? casino siteleri casino bahis siteleri
Casino Siteleri deneme bonusu veren casino siteleri Canl? Casino Siteleri