Accessing 1-wire Protocol Devices from Java

More Raspberry Pi fun with Java! For an Adafruit LCD Shield library, check out my previous blog.

So, instead of just playing around for fun, I decided to actually do something useful. In this case I wanted a little remote sensor station, which I can plug-in wherever I want to, and communicate with over http over GSM.

Building It

First of all you need to bunker up on as many DS18B20s and as many AM2302/DHT11/DHT22’s you think you’ll need. There are plenty of articles out there on how to configure them. I decided to do it a tiny bit differently to most examples by hooking up the power pin to the 5V rail (both since the specs indicate that you can run longer cable lengths if you do so and since more current can be sourced from the 5V rail). The data is pulled up to the 3.3V rail, just like in all the examples. Note that a bunch of DS18B20s can be hooked up in parallel and communicated with over a single GPIO port. Also note that this is NOT possible with the DHT sensors, which will need one GPIO port per sensor.

Ultimately I decided to have two (optional) DS18B20s and one AM2302 on my board, and I used an Adafruit Perma Proto to hook it all up. Mostly because they are pretty. 😉 To connect the AM2302, I used a Molex jumper assembly, and for the DS18B20s I decided to use RJ-11s. I can highly recommend the RJ-11s! The connectors take a bit of space on the card, and they do require you to mutilate the poor Perma Proto a bit (drill larger holes), but attaching/removing sensors is a joy. Here is a picture of the thingy with all the sensors connected:

sensor_board

In my build I will also use an LCD shield for local control and readouts without necessarily having access to a monitor. I also added a few buttons and LEDs, mostly to satisfy my youngest son.

I guess those could come in handy for diagnostics later. 🙂

Now, the 1-wire protocol used by the DS18B20 (Dallas 1-wire) and the 1-wire protocol used by the DHT sensors (AM2302, DHT11, DHT22) are quite different. Both of these require a bit of time sensitive bit-banging. Fortunately, that work has already been done for us.

For the DS18B20 there are two modules available which will expose all the DS18B20s as files under /sys/bus/w1/devices. Simply add w1-gpio and w1-therm to /etc/modules. Note that you must have the DS18B20s on GPIO port 4 for the module to work.

For the DHT sensors there is no module, but I’ve adapted the Adafruit native library described here, to create a native library for Java. Read the README.txt provided in the zip for more information.

Java Access

Once you have added the modules and put native libraries on the library path, there is only a tiny bit of configuration left to do. The library should automatically discover all DS18B20s you have. If you only happen to have one AM2302 on GPIO-pin 22, you are good to go. If not, you need to edit the property file dhtsensors.properties in the w1.jar to correspond to your setup:

# Specify devices to use with the dht library in this file.
# If you have no such devices, just comment everything out.
#
# Type can be one of the following:
# 2302 (for AM2302)
# 11 (for DHT-11)
# 22 (for DHT-22)
sensor0.pin=22
sensor0.type=2302

If you have no DHT sensors, simply comment out the lines. If you have more than one, simply add two more lines for every sensor, indicating which type and what pin they are on. For example:

sensor0.pin=22
sensor0.type=2302
sensor1.pin=23
sensor1.type=2302
sensor2.pin=24
sensor2.type=22

To test that everything is set up properly, simply run:

sudo java -Djava.library.path=<library path> –jar w1.jar

Note that Pi4J isn’t needed on the classpath. We’re relying on the native library and the w1-gpio mod to provide the necessary interfaces.

The output should look something along the lines of this:

Found 4 sensors!

Temperature(28-000004f7960a):23,38°C
Temperature(28-000004f78caf):23,56°C
Temperature(2302@22-temperature):23,00°C
Humidity(2302@22-hygrometer):36,50%

Temperature(28-000004f7960a):23,38°C
Temperature(28-000004f78caf):23,56°C
Temperature(2302@22-temperature):23,00°C
Humidity(2302@22-hygrometer):36,50%

Temperature(28-000004f7960a):23,44°C
Temperature(28-000004f78caf):23,56°C
Temperature(2302@22-temperature):23,10°C
Humidity(2302@22-hygrometer):36,50%

Library Usage

The code is very simple. To get all the sensors, do:

Set<Sensor> sensors = Sensors.getSensors();

To print the sensors like in the example, do:

System.out.println(String.format(“Found %d sensors!”, sensors.size()));
while (true) {
    for (Sensor sensor : sensors) {
        System.out.println(String.format(“%s(%s):%3.2f%s”, sensor.getPhysicalQuantity(),
                                     sensor.getID(), sensor.getValue(), sensor.getUnitString()));
        Thread.sleep(1000);
    }
    System.out.println(“”);
    System.out.flush();
}       

That’s really all there is to it.

Conclusion

A simple Java library to read a few different kinds of temperature and hygrometer sensors was introduced.

Downloads:

37 Responses to "Accessing 1-wire Protocol Devices from Java"

  1. Ola says:

    Hi!

    I am not good at java and I am having a hard time with the DHT22 sensor. I want to get the values and use them in processing.org. It is based on java so it should work I guess?

    I have been able to modify the jar file and now it works when I type

    sudo java –jar w1.jar

    I have put the w1 jar in /sketchbook/libraries/w1/library/

    In the processing sketch I have put:
    import se.hirt.w1.Sensors;

    and then I try to access the sensor trough:
    Set sensors = Sensors.getSensors();

    But I really don’t know what to type. The only thing i want is to get the value for temp and hum and place it in floats to use it in my application. Sorry, I am not good at java. And thank you for your explanation so far.

    /Ola

  2. Edgar says:

    Hi!
    I do have a exception like this
    sudo java –jar w1.jar

    Exception in thread “main” java.io.IOException: Could not find w1 devices! Please ensure that mods w1-gpio and w1-therm are loaded.

    Im using DHT22 Sensor
    Thanks!!

  3. admin says:

    Hi Edgar,

    Did you follow the instructions in the article to add the w1-gpio and w1-therm modules?

    Kind regards,
    Marcus

  4. Fabien says:

    The Adafruit_DHT must be somewhere on the path for the Java library to work, for example /usr/bin

    Must be ok if I place those files https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/tree/master/Adafruit_DHT_Driver to this folder: /usr/bin ??
    I don’t exactly understood what you’re saying here…

  5. Marcus says:

    Hi there! Yes, adding the driver to /usr/bin is one way to achieve it. Another one is to make sure that whatever folder you have put the driver binary is on the path. Depending on which platform you are using, the exact syntax will differ. On Ubuntu you would typically do export PATH=/path/to/add:$PATH.

  6. Simon says:

    Hi
    I’m using DHT 22 Sensor on Raspberry pi .. and I have a exception like this…

    $ sudo java –jar w1.jar

    Exception in thread “main” java.io.IOException: Could not find w1 devices! Please ensure that mods w1-gpio and w1-therm are loaded.

    but I have no idea how to add w1-gpio and w10therm modules..
    Could you give me some advices?

    Thanks.

  7. Tom says:

    Hi Marcus, I am using a DHT-11 and this is my error after running “sudo -jar w1.jar”

    Found 2 sensors!
    Could not read the 11 sensor at pin 4
    java.io.IOException: Cannot run program “Adafruit_DHT”: error=13, Permission denied

  8. Tom says:

    typed it wrong. here is a copy

    sudo java -jar w1.jar
    Found 2 sensors!
    Could not read the 11 sensor at pin 4
    java.io.IOException: Cannot run program “Adafruit_DHT”: error=13, Permission denied

  9. Marcus says:

    Hi Tom,

    Hmm. Are you sure you got the pin right? What happens if you’re running the Adafruit_DHT driver from the terminal? I.e. >Adafruit_DHT 11 4?

  10. Marcus says:

    Aaaah, note that I reseved pin 4 for the Dallas sensors. You may want to use another one for your DHT sensor.

  11. Tom says:

    Thanks for the quick reply! Im using GPIO 4, I will try to switch it to a different port. Thanks for the reponse!

  12. Tom says:

    I changed my port to GPIO17 and changed my config file. I seem to still be getting the same errors:

    Found 2 sensors!
    Could not read the 11 sensor at pin 17
    java.io.IOException: Cannot run program “Adafruit_DHT”: error=13, Permission denied

  13. Tom says:

    When I try using the driver from the cmd line:

    pi@rpimonitor1 ~/Downloads $ Adafruit_DHT 11 17
    -bash: /usr/local/bin/Adafruit_DHT: Permission denied

  14. Tom says:

    Hello Marcus, I found out what happened: I needed to chmod 777 /usr/bin/Adafruit_DHT. Thank you so much for your help! Now I can finish my project for school!

  15. Marcus says:

    Ah. 😉 Well, glad you sorted it out! Have fun!

  16. Thomas says:

    Okay, I’ll try to make this a bit simpler for people like me. You can copy the ‘Adafruit_DHT’ file from (https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/tree/master/Adafruit_DHT_Driver) to /usr/bin/ and type:
    cd /usr/bin
    sudo chmod 777 Adafruit_DHT
    I think you will need to edit your modules file to add the w1 modules:
    sudo nano /etc/modules
    add the following lines to the end if they are not already there:
    w1-gpio
    w1-therm

    Then go to your folder where you put the w1.jar file and run the command:
    java -jar w1.jar
    (not ‘sudo java -jar w1.jar’ – at least sudo didn’t work for me)
    However, I get the following output, so it is not really working, but at least I am getting somewhere:
    $ java -jar w1.jar
    Found 2 sensors!
    Temperature(2302@4-temperature):0.00°C
    Humidity(2302@4-hygrometer):0.00%

    When I test the sensor using the command:
    /usr/bin/python /home/pi/Adafruit_Python_DHT/examples/AdafruitDHT.py 2302 4
    I get the following output so the sensor is working:
    Temp=17.4* Humidity=57.2%

  17. Thomas says:

    Further to my previous post, I get the same 0.00 results when choosing any GPIO pin number, whether the sensor is connect to the pin or not. If I run the command ‘sudo java -jar w1.jar’ I only get the output ‘Found 2 sensors!’ then nothing else. I presume that it is not reading from the sensor correctly. Can anyone provide a proper start to finish guide explaining how to read and output the temperature and humidity from a DHT11/DHT22/AM2302 using Java? This post is the closest and most useful I have found – apart from the let me google it for you comment which would have been much quicker just saying what to do 😉

  18. Marcus says:

    Hi Thomas,

    It’s been a while since I’ve used the 1-wire stuff in my designs, so this little hack I haven’t used in a bit. E-mail me at marcus@hirt.se, and I’ll dust off my old stuff and help you out. 🙂

  19. Marcus says:

    So, as Thomas noted, some things have changed. I’ve replaced the previous downloads in this article with a single zip containing the source. Had to write a native lib instead, which is actually a good thing. No need to create new processes all the time.

    The new file is located here:
    http://hirt.se/downloads/software/rpi/w1.zip

    Please read the README.txt in the zip.

  20. i2c says:

    I tried to get my dht22 working. First I wanted to run the example code. I used:

    root@raspberrypi:~# java -Djava.library.path=libdht.so -jar ./w1.jar

    but I get the following error:

    Modules w1-gpio do not seem to be enabled. If you want to use DS18[B|S]20 sensors, please enable them.
    Exception in thread “main” java.lang.UnsatisfiedLinkError: no dht in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
    at java.lang.Runtime.loadLibrary0(Runtime.java:849)
    at java.lang.System.loadLibrary(System.java:1088)
    at se.hirt.w1.impl.DHTSensor.(DHTSensor.java:51)
    at se.hirt.w1.Sensors.addDHTSensors(Sensors.java:115)
    at se.hirt.w1.Sensors.getSensors(Sensors.java:79)
    at se.hirt.w1.Sensors.main(Sensors.java:60)

    I’m running the Rpi 2 B. The UnsatisfiedLinkError -Exception occurs on impl.DHTSensor.java on line 51 containts:

    System.loadLibrary(“dht”);

    What should I do? Should the library not be inlcuded in the shared object file?

    Please help! Thanks!

  21. Marcus says:

    The path should be to the folder where you keep the library. Try using the absolute path.

  22. Greg says:

    Hello,

    Thanks for the write up.

    I am getting the same error as i2c with my DHT22 connected to GPIO4 on my pi B+.

    pi@raspberrypi:~/java/dht22/w1 $ sudo java -Djava.library.path=/home/pi/java/dht22/w1/lib -jar w1.jar
    Modules w1-gpio do not seem to be enabled. If you want to use DS18[B|S]20 sensors, please enable them.
    Exception in thread “main” java.lang.UnsatisfiedLinkError: no dht in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1119)
    at se.hirt.w1.impl.DHTSensor.(DHTSensor.java:51)
    at se.hirt.w1.Sensors.addDHTSensors(Sensors.java:115)
    at se.hirt.w1.Sensors.getSensors(Sensors.java:79)
    at se.hirt.w1.Sensors.main(Sensors.java:60)

    I’ve tried it with both the java.library.path set to ./lib and by using the absolute path as shown above.

    I’ve used JNI quite a bit and am familiar with this error. It’s basically saying that it can’t find the native libraries (.so files). Am I missing something? The ./lib directory contains libdhtpi1.so and libdhtpi2.so.

    I also updated the dhtsensors.properties file in the w1.jar. I have a DHT22 connected to GPIO4, so I changed the following values to these: sensor0.pin=4 and sensor0.type=22. Is that correct?

    Thanks!

  23. Marcus says:

    Follow the instructions in the readme. 🙂 It says rename the correct library (depending on which version of PI you are using) to libdht.so.

    Kind regards,
    Marcus

  24. Greg says:

    AH! R.T.F.M. or at least the readme… 😉 Thanks for the response. Amazing how following the directions can lead to good results. 🙂

  25. Marcus says:

    Happy it helped! 🙂

  26. rbghongade@gmail.com says:

    Dear Marcus,
    I am getting the temperature readings perfectly, great work ! I am using only DS18B20 and I want to periodically acquire the temperature data, how can I embed your library in my program? I am completely new to java and using B4J (https://www.b4x.com/)

  27. Marcus says:

    Have never used B4J, but from a brief look at their webpage it seems you can configure the library path etc during setup.

  28. hitesh says:

    how to edit dhtsensors.properties ……sorry bt i m not much familiar with java and raspberry pi 2…thnx in advance..

  29. Marcus says:

    Unzip the jar, edit, zip it up again. 😉

  30. marko says:

    Do I need Adafruit files or just files in that zip on this site?

    I think I´ve done everything according to readme text.
    I’ve enabled w1-gpio and w1-therm.
    I’ve edited the properties.
    Ive renamed libdhtpi1.so to libdht.so and then overwrited the one already in .jar. Then zipped everything to jar.
    Then I copied everything to raspberry.

    I get error:

    Exception in thread “main” java.lang.UnsatisfiedLinkError: no dht in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at se.hirt.w1.impl.DHTSensor.(DHTSensor.java:51)
    at se.hirt.w1.Sensors.addDHTSensors(Sensors.java:115)
    at se.hirt.w1.Sensors.getSensors(Sensors.java:79)
    at se.hirt.w1.Sensors.main(Sensors.java:60)

  31. Marcus says:

    Did you set the library path properly? Read the readme carefully. 🙂

  32. Marvin says:

    Hello. I’m running the comment

    java -Djava.library.path=lib\ -jar w1.jar

    but i got the Error: Could not find or load main class ..w1.jar
    What should i do?

  33. Marvin says:

    When i try this

    java -Djava.library.path=/home/pi/w1/lib/libdhtpi.so -jar ./w1.jar

    i get the Error:
    Exception in thread “main” java.lang.UnsatisfiedLinkError: no dht in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at se.hirt.w1.impl.DHTSensor.(DHTSensor.java:51)
    at se.hirt.w1.Sensors.addDHTSensors(Sensors.java:115)
    at se.hirt.w1.Sensors.getSensors(Sensors.java:79)
    at se.hirt.w1.Sensors.main(Sensors.java:60)

  34. Marcus says:

    Read the readme carefully. You need to rename one of the provided libraries. 😉


    2. Under lib, take the native library for your platform. For Raspberry Pi 2, take libdhtpi2.so. For Raspberry Pi 1, take libdhtpi1.so.
    3. Rename the library you choose to libdht.so.

  35. sujit says:

    i am using raspberry pi 3 and dhtsensor 22
    getting checksum error or inaccurate value

    Temp: 0.000000 Humidity: 0.000000 Error code:-2.000000
    Temp: 0.000000 Humidity: 0.000000 Error code:-2.000000
    Temp: 13.800000 Humidity: 3301.399902 Error code:0.000000
    Temp: 0.000000 Humidity: 0.000000 Error code:-2.000000
    Temp: 0.000000 Humidity: 0.000000 Error code:-2.000000
    Temp: 0.000000 Humidity: 0.000000 Error code:-2.000000

  36. Marcus says:

    Not sure if something has changed for Raspberry Pi 3 again. Do you have a raspberry pi 2 you can try this on?

    I should probably move this all over to Robo4J at some point.

Leave a Reply

Your email address will not be published. Required fields are marked *