Written by Adrian Kąkol
Software Engineer Gdańsk
Published April 13, 2022

Temperature sensor library for Raspberry Pi written in Go

Raspi config settings in console

Little cartoon hero sitting on a big Raspberry Pi device

This article explains how to build a simple Go library for the Ds18b20 temperature sensor without using any external repositories besides Go built-in libraries.

Project components

This small project comprises:
Devices and components:

  • Ds18b20 temperature sensor (more details: ​​https://bit.ly/3IWEhn0 )
  • 4.7k Ohm resistor
  • Raspberry Pi 2B (should also work fine with other versions)

Languages:

  • Go (basic level)
  • Bash (basic level)

System:

  • Linux (Raspberry OS)

Other:

  • GitHub account for publishing the library


Does Go language fit the Raspberry Pi?

Writing programs in Go to run them on Raspberry Pi might sound exotic, but the growing number of different Go libraries on GitHub dedicated to Raspberry Pi proves that the language works with Raspberry devices and people are interested in using it.
It is not as popular as Python though. GitHub shows that the number of Go based libraries makes up only 10% of the Python based libraries for the Raspberry Pi platform.

You may ask if it is worth using Go for writing programs to run on Raspberry Pi devices.
It is reasonable to use it for your projects because of the following reasons:

  1. Go has a small memory footprint in comparison to Python because the Go code is compiled to a binary file that can be run by the raspberry pi machine natively.
    For contrast, running Python scripts on the machine actually runs the additional interpreter which uses more memory to translate the Python code to the machine native language in the runtime.
    The whole translation of Go code and optimisation is done when you compile your Go program. It is a huge benefit due to a small amount of built-in memory in older Raspberry devices.
  2. The fact that the Go program can be compiled to the machine’s native language means that the program will be faster in comparison to programs run by interpreters.
  3. Go language enables you to run concurrent programs at the same time
    while Python does not support it.
  4. The huge benefit of using Go is the type safety check and the automatic code formatting during builds.
    The code is unified and verified before it is compiled.
    The Go compiler informs programmers when an assertion or a syntax error has occurred in the codebase.
  5. The most popular interfaces and sensors for Raspberry Pi already have Go libraries supporting them.
    The base on which programmers can build their own programs is already wide and is still growing.


Step 1: Configure Raspberry Pi to communicate with the sensor

The Ds18b20 sensor uses 1-wire communication protocol to exchange information with the Raspberry Pi device.
The sensor needs to be connected to the 1-wire GPIO pin of the Raspberry Pi device.
Under this link, you can verify which pin supports a 1-wire connection for the device of your choice: https://pinout.xyz/pinout/1_wire

By default, GPIO 4 is the 1-wire port.

To enable the default port, follow the steps listed below.

Enabling 1-wire port can be done in 2 ways:

Step 1.1:

Solution 1:

Enabling 1-wire using the raspi-config interface. Type in the terminal:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo raspi-config
sudo raspi-config
sudo raspi-config

In the open program select the interfaces option, find 1-wire option, and select enable as shown below.

Raspi config settings in the console

Confirm raspi-config changes

 

Solution 2 – alternative 1:

Alternatively, edit the /boot/config.txt file and add or uncomment the line as listed below:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo nano /boot/config.txt
sudo nano /boot/config.txt
sudo nano /boot/config.txt

Add or uncomment the following line:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
dtoverlay=w1-gpio
dtoverlay=w1-gpio
dtoverlay=w1-gpio

Solution 2 – alternative 2:

Alternatively, if you want to use a different GPIO pin than GPIO4, you can add the following line in the /boot/config.txt file. In this case, GPIO 21 is my custom 1-wire pin.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
dtoverlay=w1-gpio,gpiopin=21
dtoverlay=w1-gpio,gpiopin=21
dtoverlay=w1-gpio,gpiopin=21

Step 1.2:

Set the pull-up option for the pin and then restart the configuration using these commands (remember to change the PIN_NUMBER to the number that you chose – default: 4, in my case 21).

Type these commands in the terminal:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sudo dtoverlay w1-gpio gpiopin=PIN_NUMBER pullup=0
sudo modprobe w1-gpio
sudo dtoverlay w1-gpio gpiopin=PIN_NUMBER pullup=0 sudo modprobe w1-gpio
sudo dtoverlay w1-gpio gpiopin=PIN_NUMBER pullup=0
sudo modprobe w1-gpio

 

Step 2: Connect the temperature sensor to your Raspberry

Connect the temperature sensor as presented in the picture below.
Remember to use the correct resistor – 4.7k Ohm. The resistance is shown by the colours on the resistor. Remember to connect the data wire to the pin that you have chosen as your 1-wire pin in the configuration during step 1.
In the following example, the data pin is GPIO 21. You can connect the data pin to the GPIO4 by default or use another customised GPIO pin that you have chosen in step 1.

Sensor and Raspberry Pi connection scheme

 

Step 3: Verify the configuration and connection

Now, when the sensor is connected and Raspberry Pi is configured, you can check if the sensor is visible on the Raspberry. Type in the terminal of your Raspberry:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
ls /sys/bus/w1/devices/
ls /sys/bus/w1/devices/
ls /sys/bus/w1/devices/

You should see a list of files that represents the connected sensors. The temperature sensor will be visible as a file with an address similar to 28-01195240e3ff.
The example of an output from the command:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
pi@raspberrypi: $ ls /sys/bus/w1/devices/
28-01195240e3ff w1_bus_master1
pi@raspberrypi: $ ls /sys/bus/w1/devices/ 28-01195240e3ff w1_bus_master1
pi@raspberrypi: $ ls /sys/bus/w1/devices/
28-01195240e3ff w1_bus_master1

The file name represents the address of your temperature sensor.
The sensor address is important, so ensure to copy it for later use.

You can use less to display the file content:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
​​less /sys/bus/w1/devices/28-01195240e3ff/w1_slave
​​less /sys/bus/w1/devices/28-01195240e3ff/w1_slave
​​less /sys/bus/w1/devices/28-01195240e3ff/w1_slave

Or using cat:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cat /sys/bus/w1/devices/28-01195240e3ff/w1_slave
cat /sys/bus/w1/devices/28-01195240e3ff/w1_slave
cat /sys/bus/w1/devices/28-01195240e3ff/w1_slave

If you have set up the sensor and pin correctly, you should see a similar output:

Sensor file content

t=21312 is the temperature with 3 decimal places in Celsius degrees (21.3*C).

Step 4: Create an empty repository and push it to GitHub

Start from creating a directory on your computer (it is not needed to be on the Raspberry because we will compile the Go program to binary and upload the binary to the Raspberry Pi). Let’s name the directory ds18b20-go.
Open the directory. Add an empty file called main.go in this directory.
To create and publish the library, you need to have git installed.

Next, initialise the git repository. You can do all of these things in the terminal as follows:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mkdir ds18b20-go
cd ds18b20-go
touch main.go
git init
git add .
git commit -m “init repository”
mkdir ds18b20-go cd ds18b20-go touch main.go git init git add . git commit -m “init repository”
mkdir ds18b20-go
cd ds18b20-go
touch main.go
git init
git add .
git commit -m “init repository”

After those steps, you can create a GitHub repository which will be hosting your golang library.

Login to GitHub, create a public repository.

Github repository creation example

After creating the repository, you will be asked to push the code into it. Do this by following the instructions provided on the GitHub page:

Github explanation how to push repository

You will be asked to provide the username and password to your GitHub account.
After these steps, you will see the pushed changes in your repository.

Step 5: Let’s start coding!

Open the main.go in the ds18b20-go directory that has been created in the previous step.

If you are new to Go language, please notice that when the variable or method is named with an upper case letter,
it means that the method or variable is public and can be used outside of the module (package).
Lower case letter names are only visible in the scope of the package in which the name is defined.

Module and imports:

Firstly, we have to name the module. Add the first line of code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package DS18B20
package DS18B20
package DS18B20

Secondly, import the required dependencies.
We need os, regexp and bufio for reading files, errors for returning errors gracefully, math and strconv to round and parse the temperature.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import (
"bufio"
"errors"
"math"
"os"
"regexp"
"strconv"
"strings"
)
import ( "bufio" "errors" "math" "os" "regexp" "strconv" "strings" )
import (
	"bufio"
	"errors"
	"math"
	"os"
	"regexp"
	"strconv"
	"strings"
)

Sensor struct:

Now, let’s define the structure of our temperature sensor called DS18B20.
This struct stores the address of the device and the path to the file.
Notice that the address and filePath are private variables that are only used for internal operations that are only accessible in the package scope.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
type DS18B20 struct {
address string
filePath string
}
type DS18B20 struct { address string filePath string }
type DS18B20 struct {
	address  string
	filePath string
}

It is time to write the first function. This function is a public interface that enables you to initialise the instance of our temperature sensor struct.
As a result, it returns the new instance of the sensor. As a parameter, the programmer needs to pass an address of the sensor for his raspberry device.
We will add the method privately setSensorFilePath in the next step.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
func Init(address string) *DS18B20 {
ds := new(DS18B20)
ds.address = address
ds.setSensorFilePath()
return ds
}
func Init(address string) *DS18B20 { ds := new(DS18B20) ds.address = address ds.setSensorFilePath() return ds }
func Init(address string) *DS18B20 {
	ds := new(DS18B20)
	ds.address = address
	ds.setSensorFilePath()

	return ds
}

Sensor struct methods:

Now, we have to add a private method, which will prepare a filePath during the sensor struct initialisation.
We will use the *DS18B20 parameter type in this function to let Go know that this is a method added to the struct so it can be called on the sensor instance, for example sensor.setSensorFilePath().
This method combines the given address with the standard raspberry pi path to the file from which the measured temperature is accessible.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
func (ds *DS18B20) setSensorFilePath() {
ds.filePath = "/sys/bus/w1/devices/" + ds.address + "/w1_slave"
}
func (ds *DS18B20) setSensorFilePath() { ds.filePath = "/sys/bus/w1/devices/" + ds.address + "/w1_slave" }
func (ds *DS18B20) setSensorFilePath() {
	ds.filePath = "/sys/bus/w1/devices/" + ds.address + "/w1_slave"
}

Now, when we have the file path, we can start reading the temperature from the file.

Let’s add a new method to the DS18B20 struct.

This method uses the next getTemperatureFromFile() method that opens the file and reads a temperature from it.
Next, it tries to parse the temperature and, if parsing has failed, it returns an error.
If everything is fine, it returns a temperature as a float.
Method checks if the length of the temperature string is at least 3 characters long, and if converting string to float does not return an error.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
func (ds *DS18B20) GetTemperature() (float64, error) {
temperature, err := ds.getTemperatureFromFile()
if err != nil {
return 0, err
}
var comaIndex int = len(temperature) - 3
var temperatureFixed string = temperature[:comaIndex] + "." + temperature[comaIndex:]
parsed, err := strconv.ParseFloat(temperatureFixed, 64)
if err != nil {
return 0, errors.New("Unable to parse temperature.")
}
return math.Round(parsed*100) / 100, nil
}
func (ds *DS18B20) GetTemperature() (float64, error) { temperature, err := ds.getTemperatureFromFile() if err != nil { return 0, err } var comaIndex int = len(temperature) - 3 var temperatureFixed string = temperature[:comaIndex] + "." + temperature[comaIndex:] parsed, err := strconv.ParseFloat(temperatureFixed, 64) if err != nil { return 0, errors.New("Unable to parse temperature.") } return math.Round(parsed*100) / 100, nil }
func (ds *DS18B20) GetTemperature() (float64, error) {
	temperature, err := ds.getTemperatureFromFile()

	if err != nil {
		return 0, err
	}

	var comaIndex int = len(temperature) - 3
	var temperatureFixed string = temperature[:comaIndex] + "." + temperature[comaIndex:]

	parsed, err := strconv.ParseFloat(temperatureFixed, 64)

	if err != nil {
		return 0, errors.New("Unable to parse temperature.")
	}

	return math.Round(parsed*100) / 100, nil
}

Temperature reader function:

Last, we need to define the getTemperatureFromFile and implement the logic of reading the temperature from the file step by step.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
func (ds *DS18B20) getTemperatureFromFile() (string, error) {
}
func (ds *DS18B20) getTemperatureFromFile() (string, error) { }
func (ds *DS18B20) getTemperatureFromFile() (string, error) {
}

Firstly, we have to open the file. Add the following lines to the getTemperatureFromFile method. Notice that, in case of an error, we want to close the file using defer file.Close().

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
var measuredTemperature string
file, err := os.Open(ds.filePath)
if err != nil {
return "", errors.New("Failed to read the temperature. Cannot open the file.")
}
defer file.Close()
var measuredTemperature string file, err := os.Open(ds.filePath) if err != nil { return "", errors.New("Failed to read the temperature. Cannot open the file.") } defer file.Close()
    var measuredTemperature string

	file, err := os.Open(ds.filePath)

	if err != nil {
		return "", errors.New("Failed to read the temperature. Cannot open the file.")
	}
	defer file.Close()

Secondly, create a scanner and read the file line by line. Try to find a temperature string in each line using regexp.
The temperature is, for example, in the format t=20.000. “t=.*” is the matcher for it. If the temperature was found, remove t= from it and write it into the measuredTemperature variable.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
scanner := bufio.NewScanner(file)
for scanner.Scan() {
var line string = scanner.Text()
re := regexp.MustCompile("t=.*")
var temperature string = re.FindString(line)
if len(temperature) > 0 {
measuredTemperature = strings.Split(temperature, "=")[1]
}
}
scanner := bufio.NewScanner(file) for scanner.Scan() { var line string = scanner.Text() re := regexp.MustCompile("t=.*") var temperature string = re.FindString(line) if len(temperature) > 0 { measuredTemperature = strings.Split(temperature, "=")[1] } }
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		var line string = scanner.Text()

		re := regexp.MustCompile("t=.*")
		var temperature string = re.FindString(line)

		if len(temperature) > 0 {
			measuredTemperature = strings.Split(temperature, "=")[1]
		}
	}

The last thing to do is to check if the temperature was read correctly. If it was ok, the method returns it.
If an error occurred in the scanner or the temperature is an empty string, it will return an error.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if err := scanner.Err(); err != nil {
return "", errors.New("Failed to read the temperature. Cannot read the file.")
}
if len(measuredTemperature) < 1 {
return "", errors.New("Failed to read the temperature. Cannot parse the file.")
}
return measuredTemperature, nil
if err := scanner.Err(); err != nil { return "", errors.New("Failed to read the temperature. Cannot read the file.") } if len(measuredTemperature) < 1 { return "", errors.New("Failed to read the temperature. Cannot parse the file.") } return measuredTemperature, nil
	if err := scanner.Err(); err != nil {
		return "", errors.New("Failed to read the temperature. Cannot read the file.")
	}

	if len(measuredTemperature) < 1 {
		return "", errors.New("Failed to read the temperature. Cannot parse the file.")
	}
	return measuredTemperature, nil

 

This is how the file main.go looks after all of the changes:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package DS18B20
import (
"bufio"
"errors"
"math"
"os"
"regexp"
"strconv"
"strings"
)
type DS18B20 struct {
address string
filePath string
}
func Init(address string) *DS18B20 {
ds := new(DS18B20)
ds.address = address
ds.setSensorFilePath()
return ds
}
func (ds *DS18B20) setSensorFilePath() {
ds.filePath = "/sys/bus/w1/devices/" + ds.address + "/w1_slave"
}
func (ds *DS18B20) GetTemperature() (float64, error) {
temperature, err := ds.getTemperatureFromFile()
if err != nil {
return 0, err
}
var comaIndex int = len(temperature) - 3
var temperatureFixed string = temperature[:comaIndex] + "." + temperature[comaIndex:]
parsed, err := strconv.ParseFloat(temperatureFixed, 64)
if err != nil {
return 0, errors.New("Unable to parse temperature.")
}
return math.Round(parsed*100) / 100, nil
}
func (ds *DS18B20) getTemperatureFromFile() (string, error) {
var measuredTemperature string
file, err := os.Open(ds.filePath)
if err != nil {
return "", errors.New("Failed to read the temperature. Cannot open the file.")
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
var line string = scanner.Text()
re := regexp.MustCompile("t=.*")
var temperature string = re.FindString(line)
if len(temperature) > 0 {
measuredTemperature = strings.Split(temperature, "=")[1]
}
}
if err := scanner.Err(); err != nil {
return "", errors.New("Failed to read the temperature. Cannot read the file.")
}
if len(measuredTemperature) < 1 {
return "", errors.New("Failed to read the temperature. Cannot parse the file.")
}
return measuredTemperature, nil
}
package DS18B20 import ( "bufio" "errors" "math" "os" "regexp" "strconv" "strings" ) type DS18B20 struct { address string filePath string } func Init(address string) *DS18B20 { ds := new(DS18B20) ds.address = address ds.setSensorFilePath() return ds } func (ds *DS18B20) setSensorFilePath() { ds.filePath = "/sys/bus/w1/devices/" + ds.address + "/w1_slave" } func (ds *DS18B20) GetTemperature() (float64, error) { temperature, err := ds.getTemperatureFromFile() if err != nil { return 0, err } var comaIndex int = len(temperature) - 3 var temperatureFixed string = temperature[:comaIndex] + "." + temperature[comaIndex:] parsed, err := strconv.ParseFloat(temperatureFixed, 64) if err != nil { return 0, errors.New("Unable to parse temperature.") } return math.Round(parsed*100) / 100, nil } func (ds *DS18B20) getTemperatureFromFile() (string, error) { var measuredTemperature string file, err := os.Open(ds.filePath) if err != nil { return "", errors.New("Failed to read the temperature. Cannot open the file.") } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { var line string = scanner.Text() re := regexp.MustCompile("t=.*") var temperature string = re.FindString(line) if len(temperature) > 0 { measuredTemperature = strings.Split(temperature, "=")[1] } } if err := scanner.Err(); err != nil { return "", errors.New("Failed to read the temperature. Cannot read the file.") } if len(measuredTemperature) < 1 { return "", errors.New("Failed to read the temperature. Cannot parse the file.") } return measuredTemperature, nil }
package DS18B20

import (
	"bufio"
	"errors"
	"math"
	"os"
	"regexp"
	"strconv"
	"strings"
)

type DS18B20 struct {
	address  string
	filePath string
}

func Init(address string) *DS18B20 {
	ds := new(DS18B20)
	ds.address = address
	ds.setSensorFilePath()

	return ds
}

func (ds *DS18B20) setSensorFilePath() {
	ds.filePath = "/sys/bus/w1/devices/" + ds.address + "/w1_slave"
}

func (ds *DS18B20) GetTemperature() (float64, error) {
	temperature, err := ds.getTemperatureFromFile()

	if err != nil {
		return 0, err
	}

	var comaIndex int = len(temperature) - 3
	var temperatureFixed string = temperature[:comaIndex] + "." + temperature[comaIndex:]

	parsed, err := strconv.ParseFloat(temperatureFixed, 64)

	if err != nil {
		return 0, errors.New("Unable to parse temperature.")
	}

	return math.Round(parsed*100) / 100, nil
}

func (ds *DS18B20) getTemperatureFromFile() (string, error) {
	var measuredTemperature string

	file, err := os.Open(ds.filePath)

	if err != nil {
		return "", errors.New("Failed to read the temperature. Cannot open the file.")
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		var line string = scanner.Text()

		re := regexp.MustCompile("t=.*")
		var temperature string = re.FindString(line)

		if len(temperature) > 0 {
			measuredTemperature = strings.Split(temperature, "=")[1]
		}
	}

	if err := scanner.Err(); err != nil {
		return "", errors.New("Failed to read the temperature. Cannot read the file.")
	}

	if len(measuredTemperature) < 1 {
		return "", errors.New("Failed to read the temperature. Cannot parse the file.")
	}

	return measuredTemperature, nil
}

Step 6: Initialise the go modules and build the project

In order to properly set up the project as a library, we need to define the mod.go file. To do so, let’s use go lang built in cli.
Use this command to initialise the go.mod file. Change <your username> to the actual name that you use in GitHub.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
go init github.com/<your user name>/ds18b20-go
go init github.com/<your user name>/ds18b20-go
go init github.com/<your user name>/ds18b20-go

This results in a new file go.mod created in your project directory. This file should look similar to this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
module github.com/adrkakol/ds18b20_go
go 1.15
module github.com/adrkakol/ds18b20_go go 1.15
module github.com/adrkakol/ds18b20_go
go 1.15

Now, you should be able to build this project. You can try to build it using this command:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
go build -o ds18b20
go build -o ds18b20
go build -o ds18b20

As a result, you should see a new file called ds18b20 created. You can’t yet test if it works.

Step 7: Tag and push changes to GitHub

Now, let’s tag the current version of the codebase and push it to the remote repository on GitHub:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
git add .
git commit -m “feat(get-temperature): create temperature reader”
git push origin master
git tag -a v0.1.0 -m “version 0.1.0
git push origin —tags
git add . git commit -m “feat(get-temperature): create temperature reader” git push origin master git tag -a v0.1.0 -m “version 0.1.0” git push origin —tags
git add .
git commit -m “feat(get-temperature): create temperature reader”
git push origin master
git tag -a v0.1.0 -m “version 0.1.0”
git push origin —tags

After these steps you can use your library in other repository.

Step 8. Finally, use the library in another Go project

New repository:

As an example, create another directory, and in that directory, create the main.go file. Initialise the Go modules as well:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mkdir test_project
cd test_project
go mod init your-test-repository-name
mkdir test_project cd test_project go mod init your-test-repository-name
mkdir test_project
cd test_project
go mod init your-test-repository-name

Add your version of the created library as a dependency (change <your_user_name> and<your_library_name>):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
go mod edit -require github.com/<your_user_name>/<your_library_name>@v0.0.1
go mod edit -require github.com/<your_user_name>/<your_library_name>@v0.0.1
go mod edit -require github.com/<your_user_name>/<your_library_name>@v0.0.1

Add the following code to main.go

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package main
import (
"fmt"
dsSensor "github.com/<your_user_name>/<your_library_name>"
)
func main() {
sensorAddress := "YOUR_SENSOR_ADDRESS"
sensor := dsSensor.Init(sensorAddress)
temp, err := sensor.GetTemperature()
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("\nTemperature: %f \n", temp)
return
}
package main import ( "fmt" dsSensor "github.com/<your_user_name>/<your_library_name>" ) func main() { sensorAddress := "YOUR_SENSOR_ADDRESS" sensor := dsSensor.Init(sensorAddress) temp, err := sensor.GetTemperature() if err != nil { fmt.Print(err) return } fmt.Printf("\nTemperature: %f \n", temp) return }
package main

import (
	"fmt"
	dsSensor "github.com/<your_user_name>/<your_library_name>"
)

func main() {
	sensorAddress := "YOUR_SENSOR_ADDRESS"
	sensor := dsSensor.Init(sensorAddress)
	temp, err := sensor.GetTemperature()
	if err != nil {
		fmt.Print(err)
		return
	}
	fmt.Printf("\nTemperature: %f \n", temp)
	return
}

Change YOUR_SENSOR_ADDRESS to the actual address which you have obtained in step 3 during the configuration verification.

Installing dependencies:

Now, you have to install the remote modules. To install them, run them in the console:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
go get
go get
go get

After these steps, the two files go.mod and go.sum should be created. The file go.mod will be similar to this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
module your-test-repository-name
go 1.15
require github.com/adrkakol/ds18b20-go v0.1.0
module your-test-repository-name go 1.15 require github.com/adrkakol/ds18b20-go v0.1.0
module your-test-repository-name
go 1.15
require github.com/adrkakol/ds18b20-go v0.1.0

Compiling:

Now, you can compile your repository in order to use it on the raspberry.
Go allows you to compile programs for different machines. For raspberry PI, you need to use a proper configuration.
Run the following command to build the repo:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
GOOS=linux GOARCH=arm CC_FOR_TARGET=arm-linux-gnueabi-gcc go build -o measure-temperature
GOOS=linux GOARCH=arm CC_FOR_TARGET=arm-linux-gnueabi-gcc go build -o measure-temperature
GOOS=linux GOARCH=arm CC_FOR_TARGET=arm-linux-gnueabi-gcc go build -o measure-temperature

After that, copy the program file to your raspberry and run this command to make the file executable:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
chmod +x ./measure-temperature
chmod +x ./measure-temperature
chmod +x ./measure-temperature

Exporting program to the Raspberry device:

In order to copy the file from your computer to the raspberry pi, you can move it via pendrive or using scp (copying files via ssh) as follows (change <directory_in_the_home_directory> to your own directory name inside the home directory):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
scp measure-temperature pi@raspberrypi.local:~/<directory_in_the_home_directory>
scp measure-temperature pi@raspberrypi.local:~/<directory_in_the_home_directory>
scp measure-temperature pi@raspberrypi.local:~/<directory_in_the_home_directory>

For example, I have the dev directory inside the home directory:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
scp measure-temperature pi@raspberrypi.local:~/dev
scp measure-temperature pi@raspberrypi.local:~/dev
scp measure-temperature pi@raspberrypi.local:~/dev

Now, you can run the program in the Raspberry Pi terminal.

Perform these steps:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
chmod +x ./measure-temperature

./path/to/file/program/measure-temperature
chmod +x ./measure-temperature
 ./path/to/file/program/measure-temperature
chmod +x ./measure-temperature


./path/to/file/program/measure-temperature

As a result, you should see a print to the console with the current temperature read from the sensor.

Temperature displayed as a result of the program output

Temperature displayed as a result of the program output

Congratulations if you have reached the end of this article.
I have just helped you create your first library for Raspberry Pi!

In the next article, I will present how to run this program automatically when Raspberry Pi is turned on.
In that way, we will be able to collect the temperature measurements in the database or display it on the LCD screen.

You can find the library I published here:
https://github.com/adrkakol/ds18b20-go/ 

Written by Adrian Kąkol
Software Engineer Gdańsk
Published April 13, 2022