BBB and OneWire

From Klaus' wiki
Jump to: navigation, search

OneWire is a simple, yet powerful, communication bus that allows us to connect several peripheral devices to a micro computer.

Enabling the DS18B20 thermometer

The version of Debian that my board was supplied with uses the Flattened Device Tree in order to ease the access to GPIO's and other hardware. This is so for the most modern Linux distributions for the ARM processors. The reason for this is mainly because Linus Thorvalds did not want to include the large amount of device drivers for the ARM processor family in the kernel. Se more about the Flattened Device Tree (FDT) on this site.

From this site I was inspired to set-up the correct dts file enabling the usage of GPIO pin 2 for the 1Wire interface.

Create a file name DS1820-00A0.dts with this content

/dts-v1/;
/plugin/;
 
/ {
    compatible = "ti,beaglebone", "ti,beaglebone-black";
    part-number = "DS1820";
    version = "00A0";
 
    exclusive-use = "P9.12";
 
    fragment@0 {
        target = <&am33xx_pinmux>;
        __overlay__ {
             ds1820_pins: pinmux_ds1820_pins {
                 pinctrl-single,pins =  <0x78 0x37>;
             };
        };
    };
 
    fragment@1 {
        target = <&ocp>;
        __overlay__ {
            onewire@0 {
                status          = "okay";
                compatible      = "w1-gpio";
                pinctrl-names   = "default";
                pinctrl-0       = <&ds1820_pins>;
                gpios           = <&gpio2 28 0>;
            };
        };
    };
};

Compile the specification into a dtbo binary file

dtc -O dtb -o /lib/firmware/DS1820-00A0.dtbo -b 0 -@ DS1820-00A0.dts

Finally in order to enable this part of the device tree perform at every boot this command

echo DS1820 > /sys/devices/bone_capemgr.*/slots

The thermometer should now show up in the /sys/bus/w1/devices folder

drwxr-xr-x 2 root root 0 Jan  1  2000 .
drwxr-xr-x 4 root root 0 Jan  1  2000 ..
lrwxrwxrwx 1 root root 0 Feb 21 10:49 28-000005a7ce64 -> ../../../devices/w1_bus_master1/28-000005a7ce64
lrwxrwxrwx 1 root root 0 Feb 21 10:49 w1_bus_master1 -> ../../../devices/w1_bus_master1

the 28-00000nnnnnnn is the thermometer - they are all uniquely identified, so the n's will vary.

Enabling@boot

Create a file called enable-DS18B20 in /etc/init.d wtih this content:

#! /bin/sh
 
### BEGIN INIT INFO
# Provides: enable-DS18B20
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Enables the DS18B20 1-wire on P9 pin 12
# Description: Conneting the 1-wire driver to the P9 pin 12
### END INIT INFO
case "$1" in
        start)
                echo "Enabling 1-Wire DS18B20 on P9 Pin 12"
		echo DS1820 > /sys/devices/bone_capemgr.9/slots
        ;;
        stop)
                #no-op
        ;;
        *)
                #no-op
        ;;
esac
 
exit 0

After creating the file execute

root@beaglebone $] chmod 755 enable-pwm
root@beaglebone $] update-rc.d enable-DS18B20 defaults

The first command set the file permissions and the second updates the init system to execute the file at a correct time depending on the information given in the first part of the script.

Testing the thermometer

Find below two tests that will verify that the thermometer work in your setup.

Test with Python

To check that the thermometer work correct prepare this short test program in a file named test.py where you of course will adjust the thermometer ID to suit your set-up:

import time
 
w1="/sys/bus/w1/devices/28-000005a7ce64/w1_slave"
 
while True:
    raw = open(w1, "r").read()
    print "Temperature is "+str(float(raw.split("t=")[-1])/1000)+" degrees"
    time.sleep(1)

Execute the program

python test.py

you should get something similar to this

root@klaus-BBB:~/ds18b20# python test.py 
Temperature is 24.0 degrees
Temperature is 24.0 degrees
Temperature is 24.062 degrees
Temperature is 24.062 degrees
^CTraceback (most recent call last):
  File "test.py", line 8, in <module>
    time.sleep(1)
KeyboardInterrupt
root@klaus-BBB:~/ds18b20#

Test using Bonescript

This source first locates the attached thermometer and then uses it for temperature reading.

This code is only able to handle one thermometer at a time, or in fact, only one 1-wire device at at time.

// 
// Interface for the thermometer
// Author   : Klaus Kolle
// Date     : 2015 02 22
// Revision : 0.0.3
 
var b = require('bonescript');
var f = require('fs');
 
//console.log('Hello, Thermostate.');
 
var temperature;
 
// Read from the 1-wire thermometer
// The 28-00000nnnnnnn will change depending of the device connected
// 
var oneWireDir;
 
locateThermometer();
 
function locateThermometer()
{
  var initialDir = '/sys/bus/w1/devices/';
  var regExpr = '28-00000';
  var dir = [];
  var i;
  // Get all files and directories in the dir
  var dirs = f.readdirSync(initialDir);
  // Did we gat anything - if not the cape manager is probably not initialised
  // with the dtbo compiled device tree
  if (dirs.length > 0)
  {
    for (i = 0; i < dirs.length; i++)
    {
      // Only select the directories matching the pattern
      if(dirs[i].match(regExpr))
      {
        dir.push (dirs[i]);
      }
    }
    // Currently the code only accepts one thermometer
    oneWireDir = initialDir + dir + "/w1_slave";
  }
}
 
function readTemp() 
{
  // Callback function for the timer
  b.readTextFile(oneWireDir, printTemp);
}
 
// The 1-wire returs this when reading the device
// klaus@klaus-BBB:~$ cat /sys/bus/w1/devices/28-000005a7ce64/w1_slave 
// a5 01 4b 46 7f ff 0b 10 f7 : crc=f7 YES
// a5 01 4b 46 7f ff 0b 10 f7 t=26312
// Therefore a split is needed. We need the string after the second =
 
function printTemp(x) 
{
  // We receive the data i x
  if (x.data != '')
  {
    var stringToSplit = x.data;
    // Split at = - three resulting strings are returned
    var arrayOfStrings = stringToSplit.split('=');
    // We are only interesd in the last
    temperature = (arrayOfStrings[2]) / 1000;
    console.log("Temp: " + temperature);
  }
}
 
setInterval(readTemp, 5000);

Expect a readout like this

Temp: 24.687
Temp: 24.75
Temp: 24.75
Temp: 24.687
Temp: 24.75
Temp: 24.75
Temp: 24.75
Temp: 24.687