Pin provisioning

829 views
Skip to first unread message

l.sze...@gmail.com

unread,
Dec 21, 2012, 7:15:02 PM12/21/12
to pi...@googlegroups.com
Hi

I'm trying to handle my DS18B20 digital temperature sensor. The communication protocol is 1-Wire, so I though i could use pi4j to handle it.

With the ds18b20 reference sheet in my hand, I wrote something like this:


        private void setDQLow()
{
((GpioPinDigitalOutput) pin).low();
}
private boolean isDQHigh()
{
return ((GpioPinDigitalInput) pin).getState().isHigh();                                 
}
private void reset() throws InterruptedException
{
pin.export(PinMode.DIGITAL_OUTPUT);
setDQLow();
Thread.sleep(0, 500000);
pin.export(PinMode.DIGITAL_INPUT);
Thread.sleep(0, 70000);
if(isDQHigh()){ System.out.println("NOT PRESENT"); }else{ System.out.println("PRESENT"); }
Thread.sleep(0, 430000);
}

private void writeBit(int bit) throws InterruptedException
{
pin.export(PinMode.DIGITAL_OUTPUT);
setDQLow();

Thread.sleep(0, 10000);
if( (bit & 0x01) ==1){ pin.export(PinMode.DIGITAL_INPUT); }

Thread.sleep(0, 60000);
pin.export(PinMode.DIGITAL_INPUT);
Thread.sleep(0, 5000);
}
private int readBit() throws InterruptedException
{
pin.export(PinMode.DIGITAL_OUTPUT);
setDQLow();
Thread.sleep(0, 10000);
pin.export(PinMode.DIGITAL_INPUT);
Thread.sleep(0, 20000);
int bit; 
if(isDQHigh()){ bit= 0x01; }else{ bit= 0x00; }
Thread.sleep(0, 60000);
return bit;
}
private void writeByte(int b) throws InterruptedException
{
for(int i=0; i<8; i++){ writeBit( (b & (0x01<<i)) ); }
}

private int readByte() throws InterruptedException
{
int value= 0x00;
for(int i=0; i<8; i++)
{
if(readBit()>0x00){ value|= (1<<i); }
}
return value;
}
private void writeCmd_SKIP_ROM() throws NumberFormatException, InterruptedException
{
writeByte(0xCC);
}
private void writeCmd_CONVERT() throws NumberFormatException, InterruptedException
{
writeByte(0x44);
}
private void writeCmd_READ_SCRATCHPAD() throws NumberFormatException, InterruptedException
{
writeByte(0xBE);
}
public int getTemperature() throws InterruptedException
{
reset();
writeCmd_SKIP_ROM();
writeCmd_CONVERT();
Thread.sleep(800); //!!milis
reset();
writeCmd_SKIP_ROM();
writeCmd_READ_SCRATCHPAD();
int temp_LSB= readByte();
int temp_MSB= readByte();
reset();
System.out.println("temp_LSB is "+temp_LSB);
System.out.println("temp_MSB is "+temp_MSB);
return ((char)((temp_LSB+(temp_MSB*256))/16));
}


Unfortunately this doesn't seem to work, the readings float in wide ragnes, and make no sense. Is the above code even correct from the pi4j point of view? I'm mostly concerned about setting the input-output mode on the same pin, and timeouts (any lags caused by hardware access or such)

cheers,
Łukasz

Robert Savage

unread,
Dec 21, 2012, 8:29:04 PM12/21/12
to pi...@googlegroups.com
Hi Łukasz,

Try using the .setMode() method instead of the .export() method. The .export() may try to do more than we really need to change pin direction on the fly.

Robert Savage

unread,
Dec 21, 2012, 8:36:14 PM12/21/12
to pi...@googlegroups.com
Also, is the input pin (when input mode) connected to a circuit that will pull the state up or down at rest?  If the pin is not pulled up or down it will float wildly.  

The Raspberry PI can pull the pin state in either direction if configured to do so in software (via Pi4J)    
In this example you will see it pulled down to prevent floating.

It really depends on the circuit as to which direction to pull and if you need to do it in software or it is accomplished by the hardware circuit.

Robert Savage

unread,
Dec 22, 2012, 1:01:03 AM12/22/12
to pi...@googlegroups.com
FYI, I have added support for a new GpioPinDigitalMultipurpose interface to support cases like this where you need to work with a single pin in input and output modes.

See this new example:


Please note that you must manually manage the DIGITAL_INPUT or DIGITAL_OUTPUT modes using the setMode(mode) method.  Attempting to perform a control operation on an INPUT pin will result in an exception.   

This new feature is available in the latest 0.0.5-SNAPSHOT build:


l.sze...@gmail.com

unread,
Dec 22, 2012, 7:00:06 AM12/22/12
to pi...@googlegroups.com
Awesome!

Thank you very much for the swift reply. Just tried it out, but got an exception like this:

Exception in thread "main" java.lang.UnsupportedClassVersionError: com/pi4j/io/gpio/GpioFactory : Unsupported major.minor version 51.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:277)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:212)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
        at http.client.sensor.DS18B20Manager.<init>(DS18B20Manager.java:19)
        at http.client.sensor.DS18B20Manager.getInstance(DS18B20Manager.java:30)
        at Main.main(Main.java:29)

I googled it out and found a post on github: https://github.com/Pi4J/pi4j/issues/3

I''ll try to solve my problem in a similar way, by installing a newer (oracles) version of java jdk.

cheers

Robert Savage

unread,
Dec 22, 2012, 9:56:11 AM12/22/12
to pi...@googlegroups.com
The project was compiled with Java 7 (1.7.0_06).  Which JRE are you running on your Pi? 

Use this command to make sure you have the default system JRE on the correct version:

sudo update-alternatives --config java

More info:

l.sze...@gmail.com

unread,
Dec 22, 2012, 3:57:43 PM12/22/12
to pi...@googlegroups.com
Yep, looked like outdated java. Just got myself a brand new 1.7.0_10. Thanks!

Robert Savage

unread,
Dec 22, 2012, 4:02:28 PM12/22/12
to pi...@googlegroups.com
Glad to hear you are back up and running :-)

l.sze...@gmail.com

unread,
Dec 23, 2012, 4:09:50 PM12/23/12
to pi...@googlegroups.com
Well.. no luck here. All the connections seem to be ok. I have a 4,87KOhm resistor between ds18b20's Vcc and it's data line to create a weak external pullup. If i wan't to output data to the ds18b20 I configure gpio1 to output low or high, if I want to read data, i set it to input low and read the state. But the sensor doesn't respond. It's not broken, because i can read from it using Frank Buss's 

modprobe w1-gpio
modprobe w1-therm
cat /sys/bus/w1/devices/UID/w1_slave

Seems I can't get the timing right. Same thing with servo-motors. I use gpio1 to output 1 to 2 millisecond pulses on it, and than 18-19 ms to complete the cycle. That doesn't seem to work either. Is it possible, that it takes so much time for java to talk to peripherals through wiring-pi, that it changes the timing? Or maybe Thread.sleep() is not very accurate?

Just ordered a digital logic analyzer, shipping in probably after Christmas. We'll see what's going on with the pins..

cheers,
Łukasz

Robert Savage

unread,
Dec 26, 2012, 2:26:08 PM12/26/12
to pi...@googlegroups.com
I would also suspect the timing.  Linux is not a real time operating system and the overhead of the JVM may not be able to be very precise at these small intervals.  Please let us know how the reading turn out on the scope.  Thanks!  

l.sze...@gmail.com

unread,
Jan 5, 2013, 10:20:37 AM1/5/13
to pi...@googlegroups.com
Unfortunately it seems that it's all about the execution overhead.. I attached a screenshot showing the analyzer's readings. It was a simple test in which I toggled GPIO1's state every 100 ms. On each pulse width you get about 330 us of overhead, varying by 10-20 us. This overhead probably depends on OS load. I guess this means that it's not possible to communicate through protocols that require strict timing and are not clocked on separate signal line. Pitty.. Gonna try separate controller based on avr sending data to pi through SPI.
measurements.png

Alex Konshin

unread,
Aug 24, 2013, 11:34:01 AM8/24/13
to pi...@googlegroups.com
Actually there is no need to use Pi4J for this case. It can be done in plain Java without JNI and without root privileges.

    File w1devDir = new File("/sys/bus/w1/devices");

    if ( w1devDir.exists() && w1devDir.canRead() && w1devDir.isDirectory() ) {

      String[] dirnames = w1devDir.list();

      if ( dirnames!=null && dirnames.length>0 ) {

        List<File> dirs = null;

        for ( String dirname : dirnames ) {

          if ( !dirname.startsWith("28-") ) continue;

          File dir = new File( w1devDir, dirname );

          if ( dir.isDirectory() && dir.canRead() ) {

            if ( dirs==null ) dirs = new ArrayList<>(dirnames.length);

            dirs.add( dir );

          }

        }

        if ( dirs!=null ) {

         

          for ( File dir : dirs ) {

            Log.info( "Reading termosensor %s...", dir.getName() );

           

            File file = new File( dirs.get(0), "w1_slave" );

            // An example of file content:

            // 87 01 4b 46 7f ff 09 10 48 : crc=48 YES

            // 87 01 4b 46 7f ff 09 10 48 t=24437

           

            //BufferedReader reader = FileUtils.openReader( file, StringUtils.ASCII );

            BufferedReader reader = null;

            try {

              reader = new BufferedReader( new InputStreamReader(new FileInputStream(file),"US-ASCII") );

              String line = reader.readLine();

              if ( line==null ) break;

              Log.info( "%s", line );

              if ( line.endsWith(" YES") ) {

                line = reader.readLine();

                if ( line==null ) break;

                Log.info( "%s", line );

                if ( line.length()>29 && line.regionMatches(26," t=",0,3) ) {

                  int t = StringUtils.extractInteger( line, 29 );

                  int f = t*9/5+32000;

                  int k = t+273;

                  Log.info( "t = %d mC, %d mF, %d mK", t, f, k );

                }

              }

             

            } catch ( Throwable e ) {

              Log.error( e );

            } finally {

              try {

                reader.close();

              } catch ( Throwable e ) {

                // ignore

              }

            }

          } //for

        }

      }

But you have to execute the following before starting your java application (for example, you can put it into /etc/rc.local):

sudo modprobe w1-gpio
sudo modprobe w1-therm

 


Alex Konshin

unread,
Aug 24, 2013, 11:40:39 AM8/24/13
to pi...@googlegroups.com
Some corrections:

    File w1devDir = new File("/sys/bus/w1/devices");

    if ( w1devDir.exists() && w1devDir.canRead() && w1devDir.isDirectory() ) {

      String[] dirnames = w1devDir.list();

      if ( dirnames!=null && dirnames.length>0 ) {

        List<File> dirs = null;

        for ( String dirname : dirnames ) {

          if ( !dirname.startsWith("28-") ) continue;

          File dir = new File( w1devDir, dirname );

          if ( dir.isDirectory() && dir.canRead() ) {

            if ( dirs==null ) dirs = new ArrayList<>(dirnames.length);

            dirs.add( dir );

          }

        }

        if ( dirs!=null ) {

         

          for ( File dir : dirs ) {

            Log.info( "Reading termosensor %s...", dir.getName() );

           

            File file = new File( dirs.get(0), "w1_slave" );

            // An example of file content:

            // 87 01 4b 46 7f ff 09 10 48 : crc=48 YES

            // 87 01 4b 46 7f ff 09 10 48 t=24437

           

            //BufferedReader reader = FileUtils.openReader( file, StringUtils.ASCII );

            BufferedReader reader = null;

            try {

              reader = new BufferedReader( new InputStreamReader(new FileInputStream(file),"US-ASCII") );

              String line = reader.readLine();

              if ( line!=null ) {

                Log.info( "%s", line );

                if ( line.endsWith(" YES") ) {

                  line = reader.readLine();

                  if ( line!=null ) {

andre...@gmail.com

unread,
Oct 14, 2013, 7:22:41 PM10/14/13
to pi...@googlegroups.com
Hello Lukasz Szepiola,
I am currently working on RaspPi project with Dallas DS18B20 thermometers, using the standard w1-gpio & w1-therm modules (by reading file "/sys/bus/w1/devices/028-xxxxxxxx/w1_slave". I am also getting wide temperature reading variations. In addition, the 12bit precision is much higher than I need, and too slow (750ms per reading).

I would be interested to know if you got your Java code working and whether  you fixed the temperature variation issue.

Looking forward to your response (you can mail me directly if you prefer : andre.davis at bapjg.com)

Regards

Rene Figueroa

unread,
Jun 1, 2015, 4:59:13 PM6/1/15
to pi...@googlegroups.com
Hi, this is a Complete and compiled code:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author renefig
 */
public class ReadTemp {
    public static void main(String[] args) {
        ReadTemp rt = new ReadTemp();
        rt.ReadDS18B20();
    }
   
    public void ReadDS18B20(){

        File w1devDir = new File("/sys/bus/w1/devices");
        if ( w1devDir.exists() && w1devDir.canRead() && w1devDir.isDirectory() ) {
          String[] dirnames = w1devDir.list();
          if ( dirnames!=null && dirnames.length>0 ) {
            List<File> dirs = null;
            for ( String dirname : dirnames ) {
              if ( !dirname.startsWith("28-") ) continue;
              File dir = new File( w1devDir, dirname );
              if ( dir.isDirectory() && dir.canRead() ) {
                if ( dirs==null ) dirs = new ArrayList<>(dirnames.length);
                dirs.add( dir );
              }
            }
            if ( dirs!=null ) {
              for ( File dir : dirs ) {
                System.out.println("Reading termosensor "+dir.getName());

                File file = new File( dirs.get(0), "w1_slave" );

                // An example of file content:
                // 87 01 4b 46 7f ff 09 10 48 : crc=48 YES
                // 87 01 4b 46 7f ff 09 10 48 t=24437
                //BufferedReader reader = FileUtils.openReader( file, StringUtils.ASCII );

                BufferedReader reader = null;
                try {
                  reader = new BufferedReader( new InputStreamReader(new FileInputStream(file),"US-ASCII") );
                  String line = reader.readLine();
                  if ( line!=null ) {
                    System.out.println( "Line: "+ line );

                    if ( line.endsWith(" YES") ) {
                      line = reader.readLine();
                      if ( line!=null ) {
                        System.out.println("Line: "+line );

                        if ( line.length()>29 && line.regionMatches(26," t=",0,3) ) {
                          int t =Integer.parseInt(line.substring(29));


                          int f = t*9/5+32000;

                          int k = t+273;

                          System.out.println("t ="+t+"mC, "+f+"mF, "+k+"mK");

                        }

                      }

                    }

                  }
                } catch ( IOException | NumberFormatException e ) {
                  System.out.println(e.toString());

                } finally {
                  try {
                    reader.close();
                  } catch ( Throwable e ) {
                      System.out.println(e.toString());
                  }
                }

              } //for
...
Reply all
Reply to author
Forward
0 new messages