Sensors
Introduction
In this chapter, you will learn how to sense the physical world with BeagleBone Black. Various types of electronic sensors, such as cameras and microphones, can be connected to the Bone using one or more interfaces provided by the standard USB 2.0 host port, as shown in The USB 2.0 host port.
Note
|
All the examples in the book assume you have cloned the Cookbook repository on www.github.com. Go here [basics_repo] for instructions. |

The two 46-pin cape headers (called P8 and P9) along the long edges of the board (The P8 and P9 cape headers) provide connections for cape add-on boards, digital and analog sensors, and more.

The simplest kind of sensor provides a single digital status, such as off or on, and can be handled by an input mode of one of the Bone’s 65 general-purpose input/output (GPIO) pins. More complex sensors can be connected by using one of the Bone’s seven analog-to-digital converter (ADC) inputs or several I2C buses.
[displays] discusses some of the output mode usages of the GPIO pins.
All these examples assume that you know how to edit a file ([basics_vsc]) and run it, either within the Visual Studio Code (VSC) integrated development environment (IDE) or from the command line ([tips_shell]).
Choosing a Method to Connect Your Sensor
Problem
You want to acquire and attach a sensor and need to understand your basic options.
Solution
Some of the many sensor connection options on the Bone shows many of the possibilities for connecting a sensor.

Choosing the simplest solution available enables you to move on quickly to addressing other system aspects. By exploring each connection type, you can make more informed decisions as you seek to optimize and troubleshoot your design.
Input and Run a Python or JavaScript Application for Talking to Sensors
Problem
You have your sensors all wired up and your Bone booted up, and you need to know how to enter and run your code.
Solution
You are just a few simple steps from running any of the recipes in this book.
-
Plug your Bone into a host computer via the USB cable ([basics_out_of_the_box]).
-
Start Visual Studio Code ([basics_vsc]).
-
In the bash tab (as shown in Entering commands in the VSC bash tab), run the following commands:
bone$ cd bone$ cd BoneCookbook/docs/02sensors/code

Here, we issued the change directory (cd) command without specifying a target directory. By default, it takes you to your home directory. Notice that the prompt has changed to reflect the change.
Note
|
If you log in as debian, your home is /home/debian. If you were to create a new user called newuser, that user’s home would be /home/newuser. By default, all non-root (non-superuser) users have their home directories in /home. |
Note
|
All the examples in the book assume you have cloned the Cookbook repository on www.github.com. Go here [basics_repo] for instructions. |
-
Double-click the pushbutton.py file to open it.
-
Press ^S (Ctrl-S) to save the file. (You can also go to the File menu in VSC and select Save to save the file, but Ctrl-S is easier.) Even easier, VSC can be configured to autosave every so many seconds.
-
In the bash tab, enter the following commands:
root@beaglebone:~/boneSensors# ./pushbutton.js data= 0 data= 0 data= 1 data= 1 ^C
This process will work for any script in this book.
Reading the Status of a Pushbutton or Magnetic Switch (Passive On/Off Sensor)
Problem
You want to read a pushbutton, a magnetic switch, or other sensor that is electrically open or closed.
Solution
Connect the switch to a GPIO pin and read from the proper place in /sys/class/gpio".
To make this recipe, you will need:
-
Breadboard and jumper wires
-
Pushbutton switch
-
Magnetic reed switch (optional)
You can wire up either a pushbutton, a magnetic reed switch, or both on the Bone, as shown in Diagram for wiring a pushbutton and magnetic reed switch input.
The code in Monitoring a pushbutton (pushbutton.js) reads GPIO port P9_42, which is attached to the pushbutton.
Put this code in a file called pushbutton.js following the steps in Input and Run a Python or JavaScript Application for Talking to Sensors. In the VSC bash tab, run it by using the following commands:
bone$ ./pushbutton.js data = 0 data = 0 data = 1 data = 1 ^C
The command runs it. Try pushing the button. The code reads the pin and prints its current value.
You will have to press ^C (Ctrl-C) to stop the code.
If you want to use the magnetic reed switch wired as shown in Diagram for wiring a pushbutton and magnetic reed switch input, change P9_42 to P9_26 which is gpio 14.
Mapping Header Numbers to gpio Numbers
Problem
You have a sensor attached to the P8 or P9 header and need to know which gpio pin it’s using.
Solution
The gpioinfo command displays information about all the P8 and P9 header pins. To see the info for just one pin, use grep.
bone$ gpioinfo | grep -e chip -e P9.42 gpiochip0 - 32 lines: line 7: "P8_42A [ecappwm0]" "P9_42" input active-high [used] gpiochip1 - 32 lines: gpiochip2 - 32 lines: gpiochip3 - 32 lines:
This shows P9_42 is on chip 0 and pin 7. To find the gpio number multiply the chip number by 32 and add it to the pin number. This gives 0*32+7=7.
For P9_26 you get:
bone$ gpioinfo | grep -e chip -e P9.26 gpiochip0 - 32 lines: line 14: "P9_26 [uart1_rxd]" "P9_26" input active-high [used] gpiochip1 - 32 lines: gpiochip2 - 32 lines: gpiochip3 - 32 lines:0*32+14=14, so the P9_26 pin is gpio 14.
Reading a Position, Light, or Force Sensor (Variable Resistance Sensor)
Problem
You have a variable resistor, force-sensitive resistor, flex sensor, or any of a number of other sensors that output their value as a variable resistance, and you want to read their value with the Bone.
Solution
Use the Bone’s analog-to-digital converters (ADCs) and a resistor divider circuit to detect the resistance in the sensor.
The Bone has seven built-in analog inputs that can easily read a resistive value. Seven analog inputs on the P9 header shows them on the lower part of the P9 header.

To make this recipe, you will need:
-
Breadboard and jumper wires
-
10 kΩ trimpot or
-
Flex resistor (optional)
-
22 kΩ resistor
A variable resistor with three terminals
Wiring a 10kΩ variable resistor (trimpot) to an ADC port shows a simple variable resistor (trimpot) wired to the Bone. One end terminal is wired to the ADC 1.8 V power supply on pin P9_32, and the other end terminal is attached to the ADC ground (P9_34). The middle terminal is wired to one of the seven analog-in ports (P9_36).

Reading an analog voltage (analogIn.py) shows the Python code used to read the variable resistor. Add the code to a file called analogIn.py and run it; then change the resistor and run it again. The voltage read will change.
#!/usr/bin/env python3
#//////////////////////////////////////
# analogin.py
# Reads the analog value of the light sensor.
#//////////////////////////////////////
import time
import os
pin = "2" # light sensor, A2, P9_37
IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw'
print('Hit ^C to stop')
f = open(IIOPATH, "r")
while True:
f.seek(0)
x = float(f.read())/4096
print('{}: {:.1f}%, {:.3f} V'.format(pin, 100*x, 1.8*x), end = '\r')
time.sleep(0.1)
# // Bone | Pocket | AIN
# // ----- | ------ | ---
# // P9_39 | P1_19 | 0
# // P9_40 | P1_21 | 1
# // P9_37 | P1_23 | 2
# // P9_38 | P1_25 | 3
# // P9_33 | P1_27 | 4
# // P9_36 | P2_35 | 5
# // P9_35 | P1_02 | 6
#!/usr/bin/env node
//////////////////////////////////////
// analogin.js
// Reads the analog value of the light sensor.
//////////////////////////////////////
const fs = require("fs");
const ms = 500; // Time in milliseconds
const pin = "2"; // light sensor, A2, P9_37
const IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw';
console.log('Hit ^C to stop');
// Read every 500ms
setInterval(readPin, ms);
function readPin() {
var data = fs.readFileSync(IIOPATH).slice(0, -1);
console.log('data = ' + data);
}
// Bone | Pocket | AIN
// ----- | ------ | ---
// P9_39 | P1_19 | 0
// P9_40 | P1_21 | 1
// P9_37 | P1_23 | 2
// P9_38 | P1_25 | 3
// P9_33 | P1_27 | 4
// P9_36 | P2_35 | 5
// P9_35 | P1_02 | 6
Note
|
The code in Reading an analog voltage (analogIn.js) outputs a value between 0 and 4096. |
A variable resistor with two terminals
Some resistive sensors have only two terminals, such as the flex sensor in Reading a two-terminal flex resistor. The resistance between its two terminals changes when it is flexed. In this case, we need to add a fixed resistor in series with the flex sensor. Reading a two-terminal flex resistor shows how to wire in a 22 kΩ resistor to give a voltage to measure across the flex sensor.

The code in Reading an analog voltage (analogIn.py) and Reading an analog voltage (analogIn.js) also works for this setup.
Reading a Distance Sensor (Analog or Variable Voltage Sensor)
Problem
You want to measure distance with a LV-MaxSonar-EZ1 Sonar Range Finder, which outputs a voltage in proportion to the distance.
Solution
To make this recipe, you will need:
-
Breadboard and jumper wires
-
LV-MaxSonar-EZ1 Sonar Range Finder
All you have to do is wire the EZ1 to one of the Bone’s analog-in pins, as shown in Wiring the LV-MaxSonar-EZ1 Sonar Range Finder to the P9_33 analog-in port. The device outputs ~6.4 mV/in when powered from 3.3 V.
Warning
|
Make sure not to apply more than 1.8 V to the Bone’s analog-in pins, or you will likely damage them. In practice, this circuit should follow that rule. |

Reading an analog voltage (ultrasonicRange.js) shows the code that reads the sensor at a fixed interval.
#!/usr/bin/env python
# //////////////////////////////////////
# // ultrasonicRange.js
# // Reads the analog value of the sensor.
# //////////////////////////////////////
import time
ms = 250; # Time in milliseconds
pin = "0" # sensor, A0, P9_39
IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw'
print('Hit ^C to stop');
f = open(IIOPATH, "r")
while True:
f.seek(0)
data = f.read()[:-1]
print('data= ' + data)
time.sleep(ms/1000)
# // Bone | Pocket | AIN
# // ----- | ------ | ---
# // P9_39 | P1_19 | 0
# // P9_40 | P1_21 | 1
# // P9_37 | P1_23 | 2
# // P9_38 | P1_25 | 3
# // P9_33 | P1_27 | 4
# // P9_36 | P2_35 | 5
# // P9_35 | P1_02 | 6
#!/usr/bin/env node
//////////////////////////////////////
// ultrasonicRange.js
// Reads the analog value of the sensor.
//////////////////////////////////////
const fs = require("fs");
const ms = 250; // Time in milliseconds
const pin = "0"; // sensor, A0, P9_39
const IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw';
console.log('Hit ^C to stop');
// Read every ms
setInterval(readPin, ms);
function readPin() {
var data = fs.readFileSync(IIOPATH);
console.log('data= ' + data);
}
// Bone | Pocket | AIN
// ----- | ------ | ---
// P9_39 | P1_19 | 0
// P9_40 | P1_21 | 1
// P9_37 | P1_23 | 2
// P9_38 | P1_25 | 3
// P9_33 | P1_27 | 4
// P9_36 | P2_35 | 5
// P9_35 | P1_02 | 6
Accurately Reading the Position of a Motor or Dial
Problem
You have a motor or dial and want to detect rotation using a rotary encoder.
Solution
Use a rotary encoder (also called a quadrature encoder) connected to one of the Bone’s eQEP ports, as shown in Wiring a rotary encoder using eQEP2.

On the BeagleBone and PocketBeage the three encoders are:
eQEP0 |
P9.27 and P9.42 OR P1_33 and P2_34 |
eQEP1 |
P9.33 and P9.35 |
eQEP2 |
P8.11 and P8.12 OR P2_24 and P2_33 |
On the AI it’s:
eQEP1 |
P8.33 and P8.35 |
eQEP2 |
P8.11 and P8.12 or P9.19 and P9.41 |
eQEP3 |
P8.24 and P8.25 or P9.27 and P9.42 |
To make this recipe, you will need:
-
Breadboard and jumper wires
-
Rotary encoder
We are using a quadrature rotary encoder, which has two switches inside that open and close in such a manner that you can tell which way the shaft is turning. In this particular encoder, the two switches have a common lead, which is wired to ground. It also has a pushbutton switch wired to the other side of the device, which we aren’t using.
Wire the encoder to P8_11 and P8_12, as shown in Wiring a rotary encoder using eQEP2.
BeagleBone Black has built-in hardware for reading up to three encoders. Here, we’ll use the eQEP2 encoder via the Linux count subsystem.
Then run the following commands:
bone$ config-pin P8_11 qep bone$ config-pin P8_12 qep bone$ show-pins | grep qep P8.12 12 fast rx up 4 qep 2 in A ocp/P8_12_pinmux (pinmux_P8_12_qep_pin) P8.11 13 fast rx up 4 qep 2 in B ocp/P8_11_pinmux (pinmux_P8_11_qep_pin)
This will enable eQEP2 on pins P8_11 and P8_12. The 2 after the qep returned by show-pins shows it’s eQEP2.
Finally, add the code in Reading a rotary encoder (rotaryEncoder.js) to a file named rotaryEncoder.js and run it.
#!/usr/bin/env python
# // This uses the eQEP hardware to read a rotary encoder
# // bone$ config-pin P8_11 eqep
# // bone$ config-pin P8_12 eqep
import time
eQEP = '2'
COUNTERPATH = '/dev/bone/counter/counter'+eQEP+'/count0'
ms = 100 # Time between samples in ms
maxCount = '1000000'
# Set the eEQP maximum count
f = open(COUNTERPATH+'/ceiling', 'w')
f.write(maxCount)
f.close()
# Enable
f = open(COUNTERPATH+'/enable', 'w')
f.write('1')
f.close()
f = open(COUNTERPATH+'/count', 'r')
olddata = -1
while True:
f.seek(0)
data = f.read()[:-1]
# Print only if data changes
if data != olddata:
olddata = data
print("data = " + data)
time.sleep(ms/1000)
# Black OR Pocket
# eQEP0: P9.27 and P9.42 OR P1_33 and P2_34
# eQEP1: P9.33 and P9.35
# eQEP2: P8.11 and P8.12 OR P2_24 and P2_33
# AI
# eQEP1: P8.33 and P8.35
# eQEP2: P8.11 and P8.12 or P9.19 and P9.41
# eQEP3: P8.24 abd P8.25 or P9.27 and P9.42
#!/usr/bin/env node
// This uses the eQEP hardware to read a rotary encoder
// bone$ config-pin P8_11 eqep
// bone$ config-pin P8_12 eqep
const fs = require("fs");
const eQEP = "2";
const COUNTERPATH = '/dev/bone/counter/counter'+eQEP+'/count0';
const ms = 100; // Time between samples in ms
const maxCount = '1000000';
// Set the eEQP maximum count
fs.writeFileSync(COUNTERPATH+'/ceiling', maxCount);
// Enable
fs.writeFileSync(COUNTERPATH+'/enable', '1');
setInterval(readEncoder, ms); // Check state every ms
var olddata = -1;
function readEncoder() {
var data = parseInt(fs.readFileSync(COUNTERPATH+'/count'));
if(data != olddata) {
// Print only if data changes
console.log('data = ' + data);
olddata = data;
}
}
// Black OR Pocket
// eQEP0: P9.27 and P9.42 OR P1_33 and P2_34
// eQEP1: P9.33 and P9.35
// eQEP2: P8.11 and P8.12 OR P2_24 and P2_33
// AI
// eQEP1: P8.33 and P8.35
// eQEP2: P8.11 and P8.12 or P9.19 and P9.41
// eQEP3: P8.24 abd P8.25 or P9.27 and P9.42
Try rotating the encoder clockwise and counter-clockwise. You’ll see an output like this:
data = 32
data = 40
data = 44
data = 48
data = 39
data = 22
data = 0
data = 999989
data = 999973
data = 999972
^C
The values you get for data will depend on which way you are turning the device and how quickly. You will need to press ^C (Ctrl-C) to end.
See Also
You can also measure rotation by using a variable resistor (see Wiring a 10kΩ variable resistor (trimpot) to an ADC port).
Measuring a Temperature
Problem
You want to measure a temperature using a digital temperature sensor.
Solution
The TMP101 sensor is a common digital temperature sensor that uses a standard I2C-based serial protocol.
To make this recipe, you will need:
-
Breadboard and jumper wires
-
Two 4.7 kΩ resistors
-
TMP101 temperature sensor
Wire the TMP101, as shown in Wiring an I2C TMP101 temperature sensor.

There are two I2C buses brought out to the headers. Table of I2C outputs shows that you have wired your device to I2C bus 2.

Once the I2C device is wired up, you can use a couple handy I2C tools to test the device. Because these are Linux command-line tools, you have to use 2 as the bus number. i2cdetect, shown in I2C tools, shows which I2C devices are on the bus. The -r flag indicates which bus to use. Our TMP101 is appearing at address 0x49. You can use the i2cget command to read the value. It returns the temperature in hexidecimal and degrees C. In this example, 0x18 = 24°C, which is 75.2°F. (Hmmm, the office is a bit warm today.) Try warming up the TMP101 with your finger and running i2cget again.
bone$ i2cdetect -y -r 2 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- 49 -- -- -- -- -- -- 50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- bone$ i2cget -y 2 0x49 0x18
Reading the temperature via the kernel driver
The cleanest way to read the temperature from at TMP101 sensor is to use the kernel drive.
Assuming the TMP101 is on bus 2 (the last digit is the bus number)
bone$ cd /sys/class/i2c-adapter/ bone$ ls i2c-0 i2c-1 i2c-2 # Three i2c busses (bus 0 is internal) bone$ cd i2c-2 # Pick bus 2 bone$ ls -ls 0 --w--w---- 1 root gpio 4096 Jul 1 09:24 delete_device 0 lrwxrwxrwx 1 root gpio 0 Jun 30 16:25 device -> ../../4819c000.i2c 0 drwxrwxr-x 3 root gpio 0 Dec 31 1999 i2c-dev 0 -r--r--r-- 1 root gpio 4096 Dec 31 1999 name 0 --w--w---- 1 root gpio 4096 Jul 1 09:24 new_device 0 lrwxrwxrwx 1 root gpio 0 Jun 30 16:25 of_node -> ../../../../../../../../firmware/devicetree/base/ocp/interconnect@48000000/segment@100000/target-module@9c000/i2c@0 0 drwxrwxr-x 2 root gpio 0 Dec 31 1999 power 0 lrwxrwxrwx 1 root gpio 0 Jun 30 16:25 subsystem -> ../../../../../../../../bus/i2c 0 -rw-rw-r-- 1 root gpio 4096 Dec 31 1999 uevent
Assuming the TMP101 is at address 0x48:
bone$ echo tmp101 0x49 > new_device
This tells the kernel you have a TMP101 sensor at address 0x49. Check the log to be sure.
bone$ dmesg -H | tail -3 [ +13.571823] i2c i2c-2: new_device: Instantiated device tmp101 at 0x49 [ +0.043362] lm75 2-0049: supply vs not found, using dummy regulator [ +0.009976] lm75 2-0049: hwmon0: sensor 'tmp101'
Yes, it’s there, now see what happened.
bone$ ls 2-0049 delete_device device i2c-dev name new_device of_node power subsystem uevent
Notice a new directory has appeared. It’s for i2c bus 2, address 0x49. Look into it.
bone$ cd 2-0048/hwmon/hwmon0 bone$ ls -F device@ name power/ subsystem@ temp1_input temp1_max temp1_max_hyst uevent update_interval bone$ cat temp1_input 24250
There is the temperature in milli-degrees C.
Other i2c devices are supported by the kernel. You can try the Linux Kernel Driver Database, https://cateee.net/lkddb/ to see them.
Once the driver is in place, you can read it via code. Reading an I2C device (i2cTemp.py) shows how to read the TMP101 from BoneScript.
#!/usr/bin/env python
# ////////////////////////////////////////
# // i2cTemp.py
# // Read a TMP101 sensor on i2c bus 2, address 0x49
# // Wiring: Attach to i2c as shown in text.
# // Setup: echo tmp101 0x49 > /sys/class/i2c-adapter/i2c-2/new_device
# // See:
# ////////////////////////////////////////
import time
ms = 1000 # Read time in ms
bus = '2'
addr = '49'
I2CPATH='/sys/class/i2c-adapter/i2c-'+bus+'/'+bus+'-00'+addr+'/hwmon/hwmon0';
f = open(I2CPATH+"/temp1_input", "r")
while True:
f.seek(0)
data = f.read()[:-1] # returns mili-degrees C
print("data (C) = " + str(int(data)/1000))
time.sleep(ms/1000)
#!/usr/bin/env node
////////////////////////////////////////
// i2cTemp.js
// Read at TMP101 sensor on i2c bus 2, address 0x49
// Wiring: Attach to i2c as shown in text.
// Setup: echo tmp101 0x49 > /sys/class/i2c-adapter/i2c-2/new_device
// See:
////////////////////////////////////////
const fs = require("fs");
const ms = 1000; // Read time in ms
const bus = '2';
const addr = '49';
I2CPATH='/sys/class/i2c-adapter/i2c-'+bus+'/'+bus+'-00'+addr+'/hwmon/hwmon0';
// Read every ms
setInterval(readTMP, ms);
function readTMP() {
var data = fs.readFileSync(I2CPATH+"/temp1_input").slice(0, -1);
console.log('data (C) = ' + data/1000);
}
Run the code by using the following command:
bone$ ./i2cTemp.js data (C) = 25.625 data (C) = 27.312 data (C) = 28.187 data (C) = 28.375 ^C
Notice using the kernel interface gets you more digits of accuracy.
Reading i2c device directly
The TMP102 sensor can be read directly with i2c commands rather than using the kernel driver. First you need to install the i2c module.
bone$ pip install smbus
#!/usr/bin/env python
# ////////////////////////////////////////
# // i2ctmp101.py
# // Read at TMP101 sensor on i2c bus 2, address 0x49
# // Wiring: Attach to i2c as shown in text.
# // Setup: pip install smbus
# // See:
# ////////////////////////////////////////
import smbus
import time
ms = 1000 # Read time in ms
bus = smbus.SMBus(2) # Using i2c bus 2
addr = 0x49 # TMP101 is at address 0x49
while True:
data = bus.read_byte_data(addr, 0)
print("temp (C) = " + str(data))
time.sleep(ms/1000)
This gets only 8 bits for the temperature. See the TMP101 datasheet for details on how to get up to 12 bits.
Reading Temperature via a Dallas 1-Wire Device
Problem
You want to measure a temperature using a Dallas Semiconductor DS18B20 temperature sensor.
Solution
The DS18B20 is an interesting temperature sensor that uses Dallas Semiconductor’s 1-wire interface. The data communication requires only one wire! (However, you still need wires from ground and 3.3 V.) You can wire it to any GPIO port.
To make this recipe, you will need:
-
Breadboard and jumper wires
-
4.7 kΩ resistor
-
DS18B20 1-wire temperature sensor
Wire up as shown in Wiring a Dallas 1-Wire temperature sensor [1].

Edit the file /boot/uEnt.txt. Go to about line 19 and edit as shown:
17 ### 18 ###Additional custom capes 19 uboot_overlay_addr4=BB-W1-P9.12-00A0.dtbo 20 #uboot_overlay_addr5=.dtbo
Be sure to remove the # at the beginning of the line.
Reboot the bone:
bone$ reboot
Now run the following command to discover the serial number on your device:
bone$ ls /sys/bus/w1/devices/ 28-00000114ef1b 28-00000128197d w1_bus_master1
I have two devices wired in parallel on the same P9_12 input. This shows the serial numbers for all the devices.
Finally, add the code in Reading a temperature with a DS18B20 (w1.js) in to a file named w1.py, edit the path assigned to w1 so that the path points to your device, and then run it.
#!/usr/bin/env python
# ////////////////////////////////////////
# // w1.js
# // Read a Dallas 1-wire device on P9_12
# // Wiring: Attach gnd and 3.3V and data to P9_12
# // Setup: Edit /boot/uEnv.txt to include:
# // uboot_overlay_addr4=BB-W1-P9.12-00A0.dtbo
# // See:
# ////////////////////////////////////////
import time
ms = 500 # Read time in ms
# Do ls /sys/bus/w1/devices and find the address of your device
addr = '28-00000d459c2c' # Must be changed for your device.
W1PATH ='/sys/bus/w1/devices/' + addr
f = open(W1PATH+'/temperature')
while True:
f.seek(0)
data = f.read()[:-1]
print("temp (C) = " + str(int(data)/1000))
time.sleep(ms/1000)
#!/usr/bin/env node
////////////////////////////////////////
// w1.js
// Read a Dallas 1-wire device on P9_12
// Wiring: Attach gnd and 3.3V and data to P9_12
// Setup: Edit /boot/uEnv.txt to include:
// uboot_overlay_addr4=BB-W1-P9.12-00A0.dtbo
// See:
////////////////////////////////////////
const fs = require("fs");
const ms = 500 // Read time in ms
// Do ls /sys/bus/w1/devices and find the address of your device
const addr = '28-00000d459c2c'; // Must be changed for your device.
const W1PATH ='/sys/bus/w1/devices/' + addr;
// Read every ms
setInterval(readW1, ms);
function readW1() {
var data = fs.readFileSync(W1PATH+'/temperature').slice(0, -1);
console.log('temp (C) = ' + data/1000);
}
bone$ ./w1.js temp (C) = 28.625 temp (C) = 29.625 temp (C) = 30.5 temp (C) = 31.0 ^C
Discussion
Each temperature sensor has a unique serial number, so you can have several all sharing the same data line.
Playing and Recording Audio
Problem
BeagleBone doesn’t have audio built in, but you want to play and record files.
Solution
One approach is to buy an audio cape ([app_capes]), but another, possibly cheaper approach is to buy a USB audio adapter, such as the one shown in A USB audio dongle. Some adapters that I’ve tested are provided in [app_misc].

Drivers for the Advanced Linux Sound Architecture (ALSA) are already installed on the Bone. You can list the recording and playing devices on your Bone by using aplay and arecord, as shown in Listing the ALSA audio output and input devices on the Bone. BeagleBone Black has audio-out on the HDMI interface. It’s listed as card 0 in Listing the ALSA audio output and input devices on the Bone. card 1 is my USB audio adapter’s audio out.
bone$ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: Black [TI BeagleBone Black], device 0: HDMI nxp-hdmi-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: Device [C-Media USB Audio Device], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0 bone$ arecord -l **** List of CAPTURE Hardware Devices **** card 1: Device [C-Media USB Audio Device], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0
In the aplay output shown in Listing the ALSA audio output and input devices on the Bone, you can see the USB adapter’s audio out. By default, the Bone will send audio to the HDMI. You can change that default by creating a file in your home directory called ~/.asoundrc and adding the code in Change the default audio out by putting this in ~/.asoundrc (audio.asoundrc) to it.
pcm.!default {
type plug
slave {
pcm "hw:1,0"
}
}
ctl.!default {
type hw
card 1
}
You can easily play .wav files with aplay:
bone$ aplay test.wav
You can play other files in other formats by installing mplayer:
bone$ sudo apt update bone$ sudo apt install mplayer bone$ mplayer test.mp3
Discussion
Adding the simple USB audio adapter opens up a world of audio I/O on the Bone.