22

I have seen plenty of examples for using one temperature sensor with the Raspberry Pi, however, how can I multiplex 5-6 temperature sensors to a Raspberry Pi? I want to read the temperature from several sources simultaneously.

Can I simply assign the GPIO pins on the Raspberry Pi to read from each sensor, essentially replicating the same configuration for one sensor, or do I need some kind of multiplexor that all the sensors would plug into then in turn that would send data in parallel to the Raspberry Pi?

asked Aug 6, 2013 at 17:40
1
  • 1
    From the datasheet: "Each DS18B20 has a unique 64-bit serial code, which allows multiple DS18B20s to function on the same 1-Wire bus.". Try reading the datasheet (don't worry if you don't understand everything). Commented Aug 6, 2013 at 19:57

7 Answers 7

20

Given that your sensor is a DS18B20, which uses the 1-wire protocol, and that the 1-wire driver on the latest RPi Linux kernel can do as many as 64 different addresses on the same 1-wire bus:

If you just connect all of your sensors to the same 3 pins (3v3, GND and GPIO4 - pin number 4 on the connector), you will read their outputs from /sys/bus/w1/devices/28*/w1_slave where the 28* is the individual unique 1-wire address. Check adafruit's tutorial.

Don't forget that you need the 4K7 resistor pulling up on GPIO4, as the internal pull up of the Pi gives you roughly 50K, and that is too much for the sensor, so you will need this extra component. Use only one 4K7 resistor between 3V3 and GPIO4 for any number of sensors connected to the 1-wire bus.

The 1-wire bus receives its name for the ability to supply the needed power through only 1 wire, in some conditions. This is called "parasitic power". Using this "feature" of the protocol will not work with multiple connected sensors. So be sure that you have all 3 pins connected to the array of 18x20s.

answered Aug 6, 2013 at 19:50
4
  • Hey there, I'm currently in the design process of making a 10-sensor temperature logger with some DS18B20s, I've pretty much got what you're saying above except for the parasitic power bit: You should just make sure you are not trying to use parasitic power. What do you mean by this? Do I need to use an external power supply instead of the 3.3V from pin1 on the Pi's GPIO? Or is parasitic power if I only use GND+Data and not the 3V3? - it refused to hot-link to your username :-( Commented Dec 12, 2016 at 14:35
  • 2
    @Jim Parasitic power is a feature of the DS18B20 whereby you connect only GND and IO pins to the bus, not VCC. Marco Poli is saying that you shouldn't run it in this mode, instead connecting all 3 wires from the DS18B20s to the Pi. You won't need an external power supply. Commented Feb 20, 2018 at 16:08
  • Hi regarding you comment, this is hardcoded in the driver does that mean that connecting temperature sensors to a different GPIO pin (or multiple GPIO pins) will not work? Commented Mar 5, 2018 at 18:47
  • Bprodz "hardcoded" means that you cannot change it after it has been compiled. To change it you would need to alter the source code and compile it again. So, given that the GPIO pin and the number of sensors are both hardcoded (for the 1-wire bus, I mean), so changing the pin would require you to edit the source code and recompile it. I don't know if it is at all possible to have multiple pins for this bus type and this driver. Commented May 9, 2020 at 21:01
4

For reference, here is a short snippet of Python to bitbang the 1-wire GPIO and return the the temperature reading for the first sensor. It should be straightforward enough to modify to return temps for all connected sensors as a list or something similar.

import subprocess, time
def read_onewire_temp():
 '''
 Read in the output of /sys/bus/w1/devices/28-*/w1_slave
 If the CRC check is bad, wait and try again (up to 20 times).
 Return the temp as a float, or None if reading failed.
 '''
 crc_ok = False
 tries = 0
 temp = None
 while not crc_ok and tries < 20:
 # Bitbang the 1-wire interface.
 s = subprocess.check_output('cat /sys/bus/w1/devices/28-*/w1_slave', shell=True).strip()
 lines = s.split('\n')
 line0 = lines[0].split()
 if line0[-1] == 'YES': # CRC check was good.
 crc_ok = True
 line1 = lines[1].split()
 temp = float(line1[-1][2:])/1000
 # Sleep approx 20ms between attempts.
 time.sleep(0.02)
 tries += 1
 return temp
answered Oct 30, 2013 at 3:19
1
  • needs import subprocess import time to run Commented May 20, 2014 at 4:24
2

Talking over a 1-wire bus can be painful. Whether you're talking to 1 sensor or 100, you'll need to think about timing. I wrote some code for the DS18B20 a few years ago, but it's in Assembly. If it's of any use, here:

;***************************************************************
;Title: Temperature Logger
;Description: Polls temperature every two seconds and returns a value
; in degC as well as the slope (rising, falling, steady)
;***************************************************************
Screen EQU $F684
;System Equates
PortA EQU 0000ドル
DDRA EQU 0002ドル
;Program Equates
TxPin EQU %00000001
RxPin EQU %00000010
IntPin EQU %10000000
;Commands
SkipROM EQU $CC
Convert EQU 44ドル
ReadPad EQU $BE
;Constants
ASCII_0 EQU 48
Poll_D EQU 2000
;Macros
TxOn macro ; Send the 1-wire line Low
 MOVB #TxPin,DDRA
 MOVB #00,ドルPortA
 endm
TxOff macro ;Releases the 1-wire line letting it return to High.
 MOVB #00,ドルDDRA
 endm
;-------------------------------------
;Main 
;-------------------------------------
 ORG 0ドルD00
 ; Clear registers and initialise ports
Start: MOVB #00,ドル DDRA
Main: LDD #00ドル
 JSR Init
 LDAA #SkipROM
 JSR Write
 LDAA #Convert
 JSR Write
 JSR Wait
 JSR Init
 LDAA #SkipROM
 JSR Write
 LDAA #ReadPad
 JSR Write
 JSR Read ; read first 8 bits
 TFR A, B
 JSR Read ; read second 8 bits
 ; Convert bytes to BCD
 LSRB
 LSRB
 LSRB
 LSRB
 STD TempNew
 PSHA
 PSHB
 LDAB #6
 MUL
 TBA
 PULB
 ABA
 CLRB
Conv_Lp:SUBA #10
 BMI Conv_Dn
 INCB
 BRA Conv_Lp
Conv_Dn:ADDA #10
 TFR A, Y
 PULA
 ABA
 TFR Y, B
 ; convert BCD bytes to ASCII and store in temp register
 LDX #Temp
 ADDA #ASCII_0
 STAA 0, X
 INX
 ADDB #ASCII_0
 STAB 0, X
 LDX #OutUp ; print 'The current temp is '
 JSR Echo
 LDX #Temp ; print ASCII bytes
 JSR Echo
 ; compare stored temp with previously stored and print 'rising', 'falling' or 'steady'
 LDD TempNew
 SUBD TempOld
 BGT Rising
 BEQ Same
 LDX #Fall
 BRA EchDir
Rising: LDX #Rise
 BRA EchDir
Same: LDX #Steady
EchDir: JSR Echo
 ; wait 2 seconds
 LDX #Poll_D
Bla_Lp: JSR Del1ms
 DBNE X, Bla_Lp
 ; set new temp as old temp and loop
 LDD TempNew
 STD TempOld
 JMP Main
 SWI
;-------------------------------------
;Subroutines
;-------------------------------------
Init: TxOn ; turn pin on
 uDelay 500 ; for 480us
 TxOff ; turn pin off
 uDelay 70 ; wait 100us before reading presence pulse
 JSR Wait
 RTS
Wait: LDX #120
Wait_Lp:JSR Del1ms
 DBNE X, Wait_Lp
 RTS
Write: PSHX
 PSHA
 LDX #8 ; 8 bits in a byte
Wr_Loop:BITA #%00000001
 BNE Wr_S1 ; bit is set, send a 1
 BEQ Wr_S0 ; bit is clear, send a 0
Wr_Cont:LSRA ; shift input byte
 uDelay 100
 DBNE X, Wr_Loop ; shifted < 8 times? loop else end
 BRA Wr_End
Wr_S1: TxOn ; on for 6, off for 64
 uDelay 6
 TxOff
 uDelay 64
 BRA Wr_Cont
Wr_S0: TxOn ; on for 60, off for 10
 uDelay 60
 TxOff
 uDelay 10
 BRA Wr_Cont
Wr_End: PULA
 PULX
 RTS
Read: PSHB
 LDAB #%00000001
 CLRA
Rd_Loop:TxOn ; on for 6, off for 10
 uDelay 6
 TxOff
 uDelay 10
 BRSET PortA, #RxPin, Rd_Sub1 ; high? add current bit to output byte
Rd_Cont:uDelay 155 ; delay and shift.. 0? shifted 8 times, end
 LSLB
 BNE Rd_Loop
 BRA Rd_End
Rd_Sub1:ABA 
 BRA Rd_Cont
Rd_End: PULB
 RTS
uDelay macro ;Delay a mutliple of 1us (works exactly for elays > 1us)
 PSHD
 LDD #1円
 SUBD #1
 LSLD
\@LOOP NOP
 DBNE D, \@LOOP
 PULD
 endm
;-------------------------------------
;General Functions
;-------------------------------------
; delays
Del1us: RTS
Del1ms: PSHA
 LDAA #252
Del_ms: JSR Del1us
 JSR Del1us
 JSR Del1us
 CMPA 0000ドル
 CMPA 0000ドル
 NOP
 DECA
 BNE Del_ms
 CMPA 0000ドル
 NOP
 PULA
 RTS
; display text from address of X to 0円
Echo: PSHY
 PSHB
 LDAB 0, X
Ech_Lp: LDY Screen
 JSR 0, Y
 INX
 LDAB 0, X
 CMPB #0
 BNE Ech_Lp
 PULB
 PULY
 RTS
Interrupt:
 SWI
 RTI
;-------------------------------------
;Variables
;-------------------------------------
 ORG 0800ドル
OutUp: DC.B 'The current temperature is ', 0
Rise: DC.B ' and Rising', 0ドルD, 0ドルA, 0
Steady: DC.B ' and Steady', 0ドルD, 0ドルA, 0
Fall: DC.B ' and Falling', 0ドルD, 0ドルA, 0
Temp: DS 2
 DC.B 0
TempOld:DS 2
TempNew:DS 2
answered Aug 7, 2013 at 14:24
1
  • 3
    The Raspberry pi already has a kernel module for 1-wire and another specifically for 1-wire temperature sensors (that includes de DS18B20). Just load the modules and the temperatature is read from a file, with a reagular file read command. You don't need to manually implement the protocol, if you choose to use the ready-modules. Commented Aug 7, 2013 at 14:41
2

If interested, here's a guide I wrote for using a DS18B20 temp sensor (which as stated above can be chained with as many as you want using the same GPIO pin on the Pi) with a Raspberry Pi and some Pyhton code that posts it to a RESTful service that aggregates and displays the temperatures in charts and diagrams on a web site. All code public on the specified GitHub account. http://macgyverdev.blogspot.se/2014/01/weather-station-using-raspberry-pi.html

answered Jan 1, 2014 at 22:10
1

What kind of temperature sensor are you using? If you have something like a DS18B20 then you can chain up to 18446744073709551615 sensors, if you had that many.

answered Aug 6, 2013 at 18:09
2
  • The sensor is a DS18B20 type indeed, however can you please elaborate what is meant by chaining, and if possible, point to a source for the implementation of such a technique. How would one differentiate between the sensor inputs if they were chained? I need to acquire and the output of graph temperature sensor 1, temperature sensor 2....temperature sensor n. Commented Aug 6, 2013 at 18:16
  • 2
    @JadCooper each ds18b20 sensor has a 16-bit serial number in it.nwhen you address a sensor with that, it returns data from only that sensor. See (this tutorial)[learn.adafruit.com/… for using them on the pi Commented Aug 11, 2013 at 1:48
0

To answer:

how can I multiplex 5-6 temperature sensors to a Raspberry Pi?

There are add on modules you can get that have several buses to connect to the pi.
This video compares their speeds: https://www.youtube.com/watch?v=YbWidNBycls He ends up using a recompiled kernel to achieve multiple GPIO communicating with multiple sensors. He hasn't posted his results on how he got it. But it is possible to multiplex it instead of using just one pin.

Update. He has posted now. He connected 81 sensors to 9 separate GPIO and was able to get all the temperatures in under 3 seconds: https://www.youtube.com/watch?v=JW9wzbp35w8

answered Mar 18, 2016 at 21:21
0

the ideal way to read multiple sensor is use I2C sensors.

this is the only way you can chain multiple sensors together or you can use analog sensors but they will take lot of analog pins but i2c will use only 2 lines. lets say you are using Pi2/3, then i will suggest get a raspberry Pi hat which has I2C port so that you can connect all your i2c devices with Pi within seconds and it will make sure your hardware is correct.

now you have the Pi with an I2C adpter let move on the sensor part. TI,AD,NXP,freescale and lot of other companies make temp sensor with I2C but you want to connect more then one sensor so there are two options.

  1. get 6 different different I2C sensors with different different I2C address, if you have two sensors with same address it wont work.

  2. you can get sensors with address line and just change address and you can connect them with Pi without any address conflict. i will suggest use this TMP 100 sensor i prefer this one because it has 2 address line with floating address line support so you can hookup 6 sensor with one i2c line.

there are advantage of using same sensors are that you dont have to read 6 datasheet to write your code you will need to study one datasheet and write the code its way easy. if your all sensors are same then you will have better results to compare.

answered Apr 28, 2016 at 15:47

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.