Here is a quick hack to interface a temperature sensor to a BeagleBone Black unit.
I choose to use a Microship TCN75AVOA component. This SMS component is not really easy to use for prototyping but feasible. This component have a unit cost < 1€ and operate at 5V or 3.3V (as for BeagleBone). A Dip8 version exists. The communication with the CPU is numerical based on a two wire connection type I2C. It measures from -40°C to +125°C on 8b + 4b decimal with +/- 1°C precision.
Read next :
Here is how to look like … nice isn’t it ?!? ok … don’t comment !
So the connection is quite easy once you are able to connect some wire to the CMS component.
The circuit is the following :
GPIO1_28 (gpio60) is used for SDA (Data), GPIO1_16 (gpio48) is used for SCL (Clock).
A0, A1, A2 are used to indicate the sub address of the chip.
I used 10K Pull-up resistor and 3.3V VDD.
For implementation, we may have different way to interface an I2C component with Linux, really beautiful, integrated and so on. But … I prefer the basic way and will give you some peace of bash code to do it.
The principle is to generate the bus signals by manually changing the values on the SDA & SCL wires.
SCL use is simple, it is an output GPIO used for clock signal.
SDA use is different : it can be an input or an output and for each octet transmitted from the BBB, the sensors will send a ACK/NACK bit to be read.
Basically, each frame starts with a start message, then have the 7b I2C device address + 1 bit operation (read or write), confirmed by an ACK from this device. It can be followed by a 8b register address or a 16b read or write.
Let see an example, for details, you can check directly the component document :
Now, lets take a look to the source code I used :
To start, some really dirty code to have a tempo < 1s:
short_sleep() {
local i=0
while [ $i -lt 100 ] ; do
i=$(( $i + 1 ))
done
}
Some constant and configuration stuff:
gpio_base=/sys/class/gpio sda_pin=gpio60 sda_num=60 scl_pin=gpio48 scl_num=48 debug=1 #address ad6=1 ; ad5=0 ; ad4=0 ; ad3=1 ; ad2=0 ; ad1=0 ; ad0=0 #constant rd=1 wr=0 ack=0 nack=1
Then the gpio configuration:
init_gpio() {
# gpio 60 is SDA
# gpio 48 is SCL
if [ ! -r ${gpio_base}/${sda_pin} ] ; then
echo ${sda_num} >${gpio_base}/export
fi
if [ ! -r ${gpio_base}/${scl_pin} ] ; then
echo ${scl_num} >${gpio_base}/export
fi
if [ -r ${gpio_base}/${scl_pin} ] ; then
echo high > ${gpio_base}/${scl_pin}/direction
else
print_debug "${scl_pin} not correctly initialized"
exit 1
fi
if [ ! -r ${gpio_base}/${sda_pin} ] ; then
print_debug "${sda_pin} not correctly initialized"
exit 1
fi
}
set_sda_out() {
echo out > ${gpio_base}/${sda_pin}/direction
}
set_sda_in() {
echo in > ${gpio_base}/${sda_pin}/direction
}
Some code to read/write start / stop and bit:
send_start() {
# set sda high, scl low
echo high > ${gpio_base}/${sda_pin}/direction
echo 0 > ${gpio_base}/${scl_pin}/value
short_sleep
# set scl high
echo 1 > ${gpio_base}/${scl_pin}/value
short_sleep
# set sda low
echo 0 > ${gpio_base}/${sda_pin}/value
short_sleep
# set scl low
echo 0 > ${gpio_base}/${scl_pin}/value
short_sleep
}
send_stop() {
# set sda low, scl low
echo low > ${gpio_base}/${sda_pin}/direction
echo 0 > ${gpio_base}/${scl_pin}/value
short_sleep
# set scl high
echo 1 > ${gpio_base}/${scl_pin}/value
short_sleep
# set sda high
echo 1 > ${gpio_base}/${sda_pin}/value
short_sleep
# set sda low
echo 0 > ${gpio_base}/${sda_pin}/value
short_sleep
# set scl low
echo 0 > ${gpio_base}/${scl_pin}/value
short_sleep
}
send_bit() {
#set bit on sda
echo 0 > ${gpio_base}/${scl_pin}/value
echo $1 > ${gpio_base}/${sda_pin}/value
short_sleep
echo 1 > ${gpio_base}/${scl_pin}/value
short_sleep
echo 0 > ${gpio_base}/${scl_pin}/value
short_sleep
}
read_bit() {
# return bit
echo 1 > ${gpio_base}/${scl_pin}/value
short_sleep
ret=`cat ${gpio_base}/${sda_pin}/value`
echo 0 > ${gpio_base}/${scl_pin}/value
short_sleep
return $ret
}
Now, we can use all of this to create write address, read / write byte :
send_address() {
set_sda_out
send_bit $ad6
send_bit $ad5
send_bit $ad4
send_bit $ad3
send_bit $ad2
send_bit $ad1
send_bit $ad0
send_bit $1
set_sda_in
if read_bit ; then
print_debug Retour address : ACK
return 0
else
print_debug Retour address : NACK
return 1
fi
}
send_byte() {
set_sda_out
send_bit $1
send_bit $2
send_bit $3
send_bit $4
send_bit $5
send_bit $6
send_bit $7
send_bit $8
set_sda_in
if read_bit ; then
print_debug Retour address : ACK
return 0
else
print_debug Retour address : NACK
return 1
fi
}
read_byte() {
set_sda_in
read_bit
echo -n $?
read_bit
echo -n $?
read_bit
echo -n $?
read_bit
echo -n $?
read_bit
echo -n $?
read_bit
echo -n $?
read_bit
echo -n $?
read_bit
echo -n $?
#send ack
set_sda_out
send_bit $1
echo
}
And finally we just have to build frame and get the temperature :
main() {
init_gpio
# send a frame to select the register 0 (temperature)
send_start
send_address $wr
send_byte 0 0 0 0 0 0 0 0
send_stop
# now read the two byte of temperature
send_start
send_address $rd
read_byte $ack # read temperature, integer part
read_byte $nack # read temperature, decimal part
send_stop
}
main $*
The result is print as a binary string… some simple transformation are needed, but this is a simple proof of concept, easy to evolve.



maybe you can use the device tree which will make your code look better.