read temperature from DHT11, using pi4j
我尝试了以下链接中的代码和先决条件:
Java 1.8.0_65
pi4j 1.1
Raspberry Pi 3 Model B
DHT22温度传感器。
当我尝试执行以下链接中可用的两个代码时,我面临代码中LibPins
的问题
public DHT11(int pin) {
final GpioController gpio = GpioFactory.getInstance();
dht11Pin = gpio.provisionDigitalMultipurposePin(LibPins.getPin(pin),
PinMode.DIGITAL_INPUT, PinPullResistance.PULL_UP);
}
在另一个代码片段中,我得到输出为"数据不好,跳过" 但是对于链接中的第二个代码,我得到了几组读数的输出,并在输出后输出为"数据不好,跳过"。
我正在使用java和pi4j库读取连接到pi gpio引脚的温度。
先谢谢。
答案 0 :(得分:1)
我很幸运(从另一个线程修改)。
您还需要安装接线pi sudo apt-get install wiringpi
应该注意的是,我把这个类放入它自己的线程中并通过调用run()来循环它。然后它将变量填充到本地状态,我可以在我的主类中引用它们。
import com.pi4j.wiringpi.Gpio;
import com.pi4j.wiringpi.GpioUtil;
public class DHT22 implements Runnable {
private static final int maxTimings = 85;
private final int[] dht22_dat = {0, 0, 0, 0, 0};
private float temperature = 9999;
private float humidity = 9999;
boolean shuttingDown = false;
public DHT22() {
// setup wiringPi
if (Gpio.wiringPiSetup() == -1) {
System.out.println(" ==>> GPIO SETUP FAILED");
return;
}
GpioUtil.export(3, GpioUtil.DIRECTION_OUT);
}
private int pollDHT22() {
int lastState = Gpio.HIGH;
int j = 0;
dht22_dat[0] = dht22_dat[1] = dht22_dat[2] = dht22_dat[3] = dht22_dat[4] = 0;
int pinNumber = 16;
Gpio.pinMode(pinNumber, Gpio.OUTPUT);
Gpio.digitalWrite(pinNumber, Gpio.LOW);
Gpio.delay(18);
Gpio.digitalWrite(pinNumber, Gpio.HIGH);
Gpio.pinMode(pinNumber, Gpio.INPUT);
for (int i = 0; i < maxTimings; i++) {
int counter = 0;
while (Gpio.digitalRead(pinNumber) == lastState) {
counter++;
Gpio.delayMicroseconds(1);
if (counter == 255) {
break;
}
}
lastState = Gpio.digitalRead(pinNumber);
if (counter == 255) {
break;
}
/* ignore first 3 transitions */
if (i >= 4 && i % 2 == 0) {
/* shove each bit into the storage bytes */
dht22_dat[j / 8] <<= 1;
if (counter > 16) {
dht22_dat[j / 8] |= 1;
}
j++;
}
}
return j;
}
private void refreshData() {
int pollDataCheck = pollDHT22();
if (pollDataCheck >= 40 && checkParity()) {
final float newHumidity = (float) ((dht22_dat[0] << 8) + dht22_dat[1]) / 10;
final float newTemperature = (float) (((dht22_dat[2] & 0x7F) << 8) + dht22_dat[3]) / 10;
if (humidity == 9999 || ((newHumidity < humidity + 40) && (newHumidity > humidity - 40))) {
humidity = newHumidity;
if (humidity > 100) {
humidity = dht22_dat[0]; // for DHT22
}
}
if (temperature == 9999 || ((newTemperature < temperature + 40) && (newTemperature > temperature - 40))) {
temperature = (float) (((dht22_dat[2] & 0x7F) << 8) + dht22_dat[3]) / 10;
if (temperature > 125) {
temperature = dht22_dat[2]; // for DHT22
}
if ((dht22_dat[2] & 0x80) != 0) {
temperature = -temperature;
}
}
}
}
float getHumidity() {
if (humidity == 9999) {
return 0;
}
return humidity;
}
@SuppressWarnings("unused")
float getTemperature() {
if (temperature == 9999) {
return 0;
}
return temperature;
}
float getTemperatureInF() {
if (temperature == 9999) {
return 32;
}
return temperature * 1.8f + 32;
}
private boolean checkParity() {
return dht22_dat[4] == (dht22_dat[0] + dht22_dat[1] + dht22_dat[2] + dht22_dat[3] & 0xFF);
}
@Override
public void run() {
while (!shuttingDown) {
refreshData();
}
}
}
答案 1 :(得分:0)
此版本使用java纳秒计时读取二进制数据。它使用使用WiringPi的Pi4J。希望对您有所帮助。 (https://github.com/dougculnane/java-pi-thing)
import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.RaspiPin;
import com.pi4j.wiringpi.Gpio;
/**
* Implements the DHT22 / AM2302 reading in Java using Pi4J.
*
* See (AM2302.pdf) specksheet for details of timings.
*
* @author Doug Culnane
*/
public class DHT22 {
/**
* Time in nanoseconds to separate ZERO and ONE signals.
*/
private static final int LONGEST_ZERO = 50000;
/**
* PI4J Pin number.
*/
private int pinNumber;
/**
* 40 bit Data from sensor
*/
private byte[] data = null;
/**
* Value of last successful humidity reading.
*/
private Double humidity = null;
/**
* Value of last successful temperature reading.
*/
private Double temperature = null;
/**
* Last read attempt
*/
private Long lastRead = null;
/**
* Constructor with pin used for signal. See PI4J and WiringPI for
* pin numbering systems.....
*
* @param pin
*/
public DHT22(Pin pin) {
pinNumber = pin.getAddress();
}
/**
* Communicate with sensor to get new reading data.
*
* @throws Exception if failed to successfully read data.
*/
private void getData() throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
ReadSensorFuture readSensor = new ReadSensorFuture();
Future<byte[]> future = executor.submit(readSensor);
// Reset data
data = new byte[5];
try {
data = future.get(3, TimeUnit.SECONDS);
readSensor.close();
} catch (TimeoutException e) {
readSensor.close();
future.cancel(true);
executor.shutdown();
throw e;
}
readSensor.close();
executor.shutdown();
}
/**
* Make a new sensor reading.
*
* @throws Exception
*/
public boolean read() throws Exception {
checkLastReadDelay();
lastRead = System.currentTimeMillis();
getData();
checkParity();
humidity = getReadingValueFromBytes(data[0], data[1]);
temperature = getReadingValueFromBytes(data[2], data[3]);
lastRead = System.currentTimeMillis();
return true;
}
private void checkLastReadDelay() throws Exception {
if (Objects.nonNull(lastRead)) {
if (lastRead > System.currentTimeMillis() - 2000) {
throw new Exception("Last read was under 2 seconds ago. Please wait longer between reads!");
}
}
}
private double getReadingValueFromBytes(final byte hi, final byte low) {
ByteBuffer bb = ByteBuffer.allocate(2);
bb.order(ByteOrder.BIG_ENDIAN);
bb.put(hi);
bb.put(low);
short shortVal = bb.getShort(0);
return new Double(shortVal) / 10;
}
private void checkParity() throws ParityChheckException {
if (!(data[4] == (data[0] + data[1] + data[2] + data[3] & 0xFF))) {
throw new ParityChheckException();
}
}
public Double getHumidity() {
return humidity;
}
public Double getTemperature() {
return temperature;
}
/**
* Run from command line to loop and make readings.
* @throws IOException
*/
public static void main(String[] args) throws IOException {
System.out.println("Starting DHT22");
if (Gpio.wiringPiSetup() == -1) {
System.out.println("GPIO wiringPiSetup Failed!");
return;
}
DHT22 dht22 = new DHT22(RaspiPin.GPIO_05);
int LOOP_SIZE = 10;
int countSuccess = 0;
for (int i=0; i < LOOP_SIZE; i++) {
try {
Thread.sleep(3000);
System.out.println();
dht22.read();
System.out.println("Humidity=" + dht22.getHumidity() +
"%, Temperature=" + dht22.getTemperature() + "*C");
countSuccess++;
} catch (TimeoutException e) {
System.out.println("ERROR: " + e);
} catch (Exception e) {
System.out.println("ERROR: " + e);
}
}
System.out.println("Read success rate: "+ countSuccess + " / " + LOOP_SIZE);
System.out.println("Ending DHT22");
}
/**
* Callable Future for reading sensor. Allows timeout if it gets stuck.
*/
private class ReadSensorFuture implements Callable<byte[]>, Closeable {
private boolean keepRunning = true;
public ReadSensorFuture() {
Gpio.pinMode(pinNumber, Gpio.OUTPUT);
Gpio.digitalWrite(pinNumber, Gpio.HIGH);
}
@Override
public byte[] call() throws Exception {
// do expensive (slow) stuff before we start.
byte[] data = new byte[5];
long startTime = System.nanoTime();
sendStartSignal();
waitForResponseSignal();
for (int i = 0; i < 40; i++) {
while (keepRunning && Gpio.digitalRead(pinNumber) == Gpio.LOW) {
}
startTime = System.nanoTime();
while (keepRunning && Gpio.digitalRead(pinNumber) == Gpio.HIGH) {
}
long timeHight = System.nanoTime() - startTime;
data[i / 8] <<= 1;
if ( timeHight > LONGEST_ZERO) {
data[i / 8] |= 1;
}
}
return data;
}
private void sendStartSignal() {
// Send start signal.
Gpio.pinMode(pinNumber, Gpio.OUTPUT);
Gpio.digitalWrite(pinNumber, Gpio.LOW);
Gpio.delay(1);
Gpio.digitalWrite(pinNumber, Gpio.HIGH);
}
/**
* AM2302 will pull low 80us as response signal, then
* AM2302 pulls up 80us for preparation to send data.
*/
private void waitForResponseSignal() {
Gpio.pinMode(pinNumber, Gpio.INPUT);
while (keepRunning && Gpio.digitalRead(pinNumber) == Gpio.HIGH) {
}
while (keepRunning && Gpio.digitalRead(pinNumber) == Gpio.LOW) {
}
while (keepRunning && Gpio.digitalRead(pinNumber) == Gpio.HIGH) {
}
}
@Override
public void close() throws IOException {
keepRunning = false;
// Set pin high for end of transmission.
Gpio.pinMode(pinNumber, Gpio.OUTPUT);
Gpio.digitalWrite(pinNumber, Gpio.HIGH);
}
}
private class ParityChheckException extends Exception {
private static final long serialVersionUID = 1L;
}
}