我正在尝试使用DHT11温度传感器读取温度数据,使用pi4j。我遵循了这个站点中用c和python编写的代码:http://www.uugear.com/portfolio/dht11-h .或者-模块/但它不起作用。当我测试指令'dht11Pin.getState()‘时,它总是处于高状态,永不改变。我的代码有什么问题吗?
下面是我的代码:
import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.pi4j.component.ObserveableComponentBase;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;
import com.pi4j.io.gpio.GpioPinDigitalMultipurpose;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.PinMode;
import com.pi4j.io.gpio.PinPullResistance;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
public class DHT11 extends ObserveableComponentBase {
private static final Pin DEFAULT_PIN = RaspiPin.GPIO_04;
private static final int MAXTIMINGS = 85;
private int[] dht11_dat = { 0, 0, 0, 0, 0 };
private GpioPinDigitalMultipurpose dht11Pin;
private static final Logger LOGGER = LogManager.getLogger(DHT11.class
.getName());
public DHT11() {
final GpioController gpio = GpioFactory.getInstance();
dht11Pin = gpio.provisionDigitalMultipurposePin(DEFAULT_PIN,
PinMode.DIGITAL_INPUT, PinPullResistance.PULL_UP);
}
public DHT11(int pin) {
final GpioController gpio = GpioFactory.getInstance();
dht11Pin = gpio.provisionDigitalMultipurposePin(LibPins.getPin(pin),
PinMode.DIGITAL_INPUT, PinPullResistance.PULL_UP);
}
public double getTemperature() {
PinState laststate = PinState.HIGH;
int j = 0;
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
StringBuilder value = new StringBuilder();
try {
dht11Pin.setMode(PinMode.DIGITAL_OUTPUT);
dht11Pin.low();
Thread.sleep(18);
dht11Pin.high();
TimeUnit.MICROSECONDS.sleep(40);
dht11Pin.setMode(PinMode.DIGITAL_INPUT);
for (int i = 0; i < MAXTIMINGS; i++) {
int counter = 0;
while (dht11Pin.getState() == laststate) {
counter++;
TimeUnit.MICROSECONDS.sleep(1);
if (counter == 255) {
break;
}
}
laststate = dht11Pin.getState();
if (counter == 255) {
break;
}
/* ignore first 3 transitions */
if ((i >= 4) && (i % 2 == 0)) {
/* shove each bit into the storage bytes */
dht11_dat[j / 8] <<= 1;
if (counter > 16) {
dht11_dat[j / 8] |= 1;
}
j++;
}
}
// check we read 40 bits (8bit x 5 ) + verify checksum in the last
// byte
if ((j >= 40) && checkParity()) {
value.append(dht11_dat[2]).append(".").append(dht11_dat[3]);
LOGGER.info("temperature value readed: " + value.toString());
}
} catch (InterruptedException e) {
LOGGER.error("InterruptedException: " + e.getMessage(), e);
}
if (value.toString().isEmpty()) {
value.append(-1);
}
return Double.parseDouble(value.toString());
}
private boolean checkParity() {
return (dht11_dat[4] == ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xFF));
}}
发布于 2016-01-24 13:52:46
我从最初的海报java代码开始,用com.pi4j.io.gpio包替换了com.pi4j.wiringpi包引用。我最近在我的Raspberry上安装了最新的pi4j软件包和wiringpi版本。
使用该包,下面的Java代码的工作原理与这个程序的c++版本大致相同。我得到了大约80% - 85%的精确反应与DHT-11。这与我在c ++中使用wiringPi时得到的结果大致相同。
package gpio;
import com.pi4j.wiringpi.Gpio;
import com.pi4j.wiringpi.GpioUtil;
public class DHT11 {
private static final int MAXTIMINGS = 85;
private final int[] dht11_dat = { 0, 0, 0, 0, 0 };
public DHT11() {
// setup wiringPi
if (Gpio.wiringPiSetup() == -1) {
System.out.println(" ==>> GPIO SETUP FAILED");
return;
}
GpioUtil.export(3, GpioUtil.DIRECTION_OUT);
}
public void getTemperature(final int pin) {
int laststate = Gpio.HIGH;
int j = 0;
dht11_dat[0] = dht11_dat[1] = dht11_dat[2] = dht11_dat[3] = dht11_dat[4] = 0;
Gpio.pinMode(pin, Gpio.OUTPUT);
Gpio.digitalWrite(pin, Gpio.LOW);
Gpio.delay(18);
Gpio.digitalWrite(pin, Gpio.HIGH);
Gpio.pinMode(pin, Gpio.INPUT);
for (int i = 0; i < MAXTIMINGS; i++) {
int counter = 0;
while (Gpio.digitalRead(pin) == laststate) {
counter++;
Gpio.delayMicroseconds(1);
if (counter == 255) {
break;
}
}
laststate = Gpio.digitalRead(pin);
if (counter == 255) {
break;
}
/* ignore first 3 transitions */
if (i >= 4 && i % 2 == 0) {
/* shove each bit into the storage bytes */
dht11_dat[j / 8] <<= 1;
if (counter > 16) {
dht11_dat[j / 8] |= 1;
}
j++;
}
}
// check we read 40 bits (8bit x 5 ) + verify checksum in the last
// byte
if (j >= 40 && checkParity()) {
float h = (float) ((dht11_dat[0] << 8) + dht11_dat[1]) / 10;
if (h > 100) {
h = dht11_dat[0]; // for DHT11
}
float c = (float) (((dht11_dat[2] & 0x7F) << 8) + dht11_dat[3]) / 10;
if (c > 125) {
c = dht11_dat[2]; // for DHT11
}
if ((dht11_dat[2] & 0x80) != 0) {
c = -c;
}
final float f = c * 1.8f + 32;
System.out.println("Humidity = " + h + " Temperature = " + c + "(" + f + "f)");
} else {
System.out.println("Data not good, skip");
}
}
private boolean checkParity() {
return dht11_dat[4] == (dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3] & 0xFF);
}
public static void main(final String ars[]) throws Exception {
final DHT11 dht = new DHT11();
for (int i = 0; i < 10; i++) {
Thread.sleep(2000);
dht.getTemperature(21);
}
System.out.println("Done!!");
}
}发布于 2018-11-11 02:04:09
我发现加载了Raspian的RPi3b太慢了,无法使用这里所示的代码示例。可能与java>pi4j>wiringpi传播延迟有关。我的方法如下:在发送命令以激活传感器后,我读取所需引脚上的时间级别变化,并将值保存到数组中。然后,解析将在稍后完成。我得到了95%的成功率与此代码。我让它在一个带循环的可运行类中运行,所以它有自己的线程。如果您发现您的时间不太正确,请尝试调整计数器偏移量。此外,启用标记为调试的println,它有助于指示未接收到哪些位(由0表示)。
public void scopeSensor(int pin){
int x = 0;
int lastState = 1;
int valueRead = 1;
int counter = 0;
int limit = 84;
int timeout = 0;
int[] results = new int[limit];
int[] pinState = new int[limit];
//set pin low for 18ms to request data
Gpio.pinMode(pin, Gpio.OUTPUT);
Gpio.digitalWrite(pin, Gpio.LOW);
Gpio.delay(18);
//get ready to recieve data back from dht11
Gpio.pinMode(pin, Gpio.INPUT);
Gpio.pullUpDnControl(pin, Gpio.PUD_UP); //activate internal pullup
while (x < limit) //84 sample changes to cover DHT11
{
timeout = 0;
counter = 2; //offset for time taken to perform read by pi
while (valueRead == lastState && timeout < 300){
Gpio.delayMicroseconds(1);
valueRead = Gpio.digitalRead(pin);
counter++;
timeout++;
}
if (timeout < 300)
{
results[x] = counter;
pinState[x] = lastState;
lastState = valueRead;
}
x++;
}
//reset our bytes
dht11_dat[0] = dht11_dat[1] =dht11_dat[2]=dht11_dat[3]=dht11_dat[4]=0;
int pointer = 0;
for (int i = 4; i<x; i=i+2){
//shift left so we are ready for next result
pointer = ((i-4) / 2) / 8;
dht11_dat[pointer] = dht11_dat[pointer] <<= 1;
//if more than 30, mark bit as 1
if (results[i] > 30){
dht11_dat[pointer] = dht11_dat[pointer] |= 1;
}
//for debugging only
// System.out.println(Integer.toString(pinState[i]) + "," + Integer.toString(results[i]));
}
int checksumByte = ((dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3]) & 0xff);
if (dht11_dat[4] != checksumByte){
System.out.println("Warning: Bad checksum value!");
}
System.out.println(" Temp: " + Integer.toString((dht11_dat[2])) + " RH: " + Integer.toString((dht11_dat[0])));
WriteToFile.writeTextToFile("RH-T.csv", Integer.toString((dht11_dat[0])) + "," + Integer.toString((dht11_dat[2])));
}run方法:
@Override
public void run() {
ReadTempRH dht = new ReadTempRH();
while (NbSerialApp.runThreads){
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Logger.getLogger(ReadTempRH.class.getName()).log(Level.SEVERE, null, ex);
}
//getTempRH(7);
scopeSensor(7);
}
}ReadTempRH构造函数:
private final int[] dht11_dat = {0,0,0,0,0};
public ReadTempRH() {
//setup wiringPi
if (Gpio.wiringPiSetup() == -1){
System.out.println("GPIO setup failed!");
return;
}
GpioUtil.export(3, GpioUtil.DIRECTION_OUT);
System.out.println("GPIO setup complete!");
}对不起,我的代码有点乱七八糟,我没有时间整理东西!但你应该有个主意。我通常是一个c#的家伙和Netbeans不像VS在整理前!
发布于 2015-02-14 14:02:53
我也有同样的问题,不幸的是,我读到Java不能以这种方式读取DHT11 11/22中的数据,因为计时问题。
我在Raspberry论坛上找到了一条线索,你可以通过SPI或pigpio找到一些解决方案。另一个完整的Java解决方案是那里。
我昨天收到了我的感应器,我还没有尝试过这个解决方案。当我尝试的时候,我会告诉你的。
编辑
嗨,我已经解决了调用python脚本(它使用Adafruit司机)并读取它的输出的问题。python脚本只是发布在Adafruit库中的示例。我只更改了第48行的输出
print '{0:0.1f} {1:0.1f}'.format(temperature, humidity)用新值更新值的Java方法是:
public void update() {
String cmd = "sudo python DHTReader.py 11 4";
try {
String ret = "";
try {
String line;
Process p = Runtime.getRuntime().exec(cmd.split(" "));
p.waitFor();
BufferedReader input = new BufferedReader
(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
output += (line + '\n');
}
input.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
ret.trim();
if (ret.length() == 0) // Library is not present
throw new RuntimeException(LIB_NOT_PRESENT_MESSAGE);
else{
// Error reading the the sensor, maybe is not connected.
if(ret.contains(ERROR_READING)){
String msg = String.format(ERROR_READING_MSG,toString());
throw new Exception(msg);
}
else{
// Read completed. Parse and update the values
String[] vals = ret.split(" ");
float t = Float.parseFloat(vals[0].trim());
float h = Float.parseFloat(vals[1].trim());
if( (t != lastTemp) || (h != lastHum) ){
lastUpdate = new Date();
lastTemp = t;
lastHum = h;
}
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
if( e instanceof RuntimeException)
System.exit(-1);
}
}要使其正常工作,您必须安装链接页面中描述的Adafruit库,并使用and的路径更改DHTReader.py。我正在建一个“图书馆”。如果您需要,当我完成时,我将在GitHub上发布它。
https://stackoverflow.com/questions/28486159
复制相似问题