# How to use the 1-WIRE bus on Acqua SOM

<abstract>
This article illustrates how to enable a bit banging 1-wire bus on any Acqua GPIO pin
</abstract>

<div class="alert alert-success" role="alert" markdown="1">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
This article was written using Linux Kernel 4.19.x
</div>

1-Wire is a device communications bus system designed by Dallas Semiconductor 
that provides low-speed data, signaling, and power over a single signal. 1-Wire is similar in concept to I2C, 
but with lower data rates and longer range. 

1-Wire is typically used to communicate with small inexpensive devices 
such as digital thermometers and weather instruments. This article illustrates how to 
read a popular DS18B20 thermal sensor.

## The Dallas/Maxim DS18B20 thermal sensor

<a href="http://www.maxim-ic.com/datasheet/index.mvp/id/2812"><img src="DS18B20.jpg" width="640px"/></a>

The DS18B20 digital thermometer provides 9-bit to 12-bit Celsius temperature measurements. 
It communicates over a 1-Wire bus that by definition requires only one data line (and ground) 
for communication with a central microprocessor. 

It has an operating temperature range of -55&deg;C to +125&deg;C and is accurate to &plusmn;0.5&deg;C over 
the range of &deg;10&deg;C to +85&deg;C. ([read more on datasheet](https://datasheets.maximintegrated.com/en/ds/DS18B20-PAR.pdf)).

## Wiring

| DS18B20  | Berta D2 Board |
|----------|----------------|
| 1 - GND  | GND            |
| 2 . Data | PB5            |
| 3 - Vcc  | 3V3            |

A 4.7kOhm is requested between the DS18B20 pins Vcc and Data

## Kernel drivers

The 1-wire bus is managed in bit banging mode by the Kernel driver called w1-gpio. 

* [Master: w1-gpio.c Kernel driver source](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/w1/masters/w1-gpio.c?h=v4.19.227)
* [Slave: w1_therm.c Kernel driver source](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/w1/slaves/w1_therm.c?h=v4.19.227)


To enable the Kernel drivers (master and slave) follow this tutorial: @h1='compile_linux_kernel_4_19'. 
When using this command:

	make arch=ARM menuconfig

use this configuration.

Enable the <b>Dallas's 1-wire support</b> and the <b> Thermal family implementation</b> as shown below:

	Device Drivers  --->
	    <*>   Dallas's 1-wire support
	    	1-wire Bus Masters  --->
	    		<*> GPIO 1-wire busmaster
	    	1-wire Slaves  --->
	    		<*> Thermal family implementation

Any GPIO can be used as 1-wire bus. The pin used depends by
the device tree definition

## Configuring the device tree

Edit the device tree source of your board and add in __apb__section these lines (change PB5 with the GPIO you intend to use):

	onewire@0 {
		compatible = "w1-gpio";
		gpios = <&pioB 5 GPIO_ACTIVE_HIGH>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_w1_0>;
		status = "okay";
	};
		
then add also these lines in the section __pinctrl@fffff200__: 

	pinctrl_w1_0: w1_0 {
		atmel,pins =
			<AT91_PIOB 5 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
	};

Changing the gpio parameter you can change the GPIO to use as 1-wire bus	

## Read the temperature

The 1-wire driver automatically scans every 10 seconds if new sensors are plugged on the 1-wire bus.

For each 1-wire device detected a new directory is created on /sys/bus/w1/devices/w1 bus master.

Type:

	ls /sys/bus/w1/devices/*/w1_slave
	
if everything is ok you should obtain this reply:

	/sys/bus/w1/devices/28-000006c52e56/w1_slave

these lines indicates that a thermal sensors is probed on the bus (28 is the family ID) and their 
unique ID are 000006c52e56.

To read the temperature from each sensor type:

	cat /sys/bus/w1/devices/28-000006c52e56/w1_slave
	58 01 4b 46 7f ff 08 10 f9 : crc=f9 YES
	58 01 4b 46 7f ff 08 10 f9 t=21500

t=21500 indicates that the temperature read is 21.5 &deg;C 

## Read the temperature each seconds in Python3

	#!/usr/bin/python3
	
	import os
	import time
	
	w1path = "/sys/bus/w1/devices/w1_bus_master1"
	
	# Extract the sensor id
	
	if not os.path.exists(w1path): 
		print ("1-wire bus not found")
		print ("Check if the 1-wire bus is installed")
		exit(1)
	
	deviceList = os.listdir(w1path)
	
	# for deviceId in deviceList:
	#	print(deviceId)
	
	onewire_id=[deviceId for deviceId in deviceList if deviceId[0:2]=="28"]
	
	# print(onewire_id[0])
	
	
	# Read temp
	
	
	while True:
		f = open("/sys/bus/w1/devices/" + onewire_id[0] + "/w1_slave","r")
		tString=f.read()
		f.close()
	
		if tString.find("NO")>=0:
			print ("Wrong CRC")
			exit(1)
						
		p=tString.find("t=")
		value =float(tString[p+2:-1])/1000
		formatted_value = "{:.2f}".format(value)
		print(formatted_value)
	
		time.sleep(1)

##Links

* [DS18B20 datasheet](https://datasheets.maximintegrated.com/en/ds/DS18B20-PAR.pdf)
* [Wikipedia 1-Wire definition](http://en.wikipedia.org/wiki/1-Wire)

@include='bio_tanzilli'

