2017-01-01 42 views
0

我需要使用Raspberry Pi 3和Python从DS18B20传感器读取温度读数。 问题是传感器(〜1秒) 我需要从sys/bus/w1/devices/28-041670f43bff/w1_slave阅读和使用整数i得到显示直接连接到我的GPIO(不使用任何硬件复用的7段显示器上的温度的刷新速率 - I2C ....等)如何从文件中读取字符串,将其转换为int,将值存储在内存中,然后访问该值并将其打印在屏幕上?

为了显示一个两位数温度,我需要打开和关闭位真快(小于传感器刷新更快)

这用于小片的代码得到整数温度:

def temperature(): 
    with open ("/sys/bus/w1/devices/28-041670f43bff/w1_slave") as q: 
     r=q.read() 
     temp=r[69:71] 
     t=int (temp) 
     return t 

但我需要调用此为了在7段显示器上获得良好的显示效果,每秒多次执行一次功能。

这是我怎么想这样做的:

#the temperature() function returns a two digit int 
while True: 
    GPIO.output(31,0) 
    GPIO.output(temp[temperature()/10], 1) # temp is a dictionary used to know which segments to light up to show numbers 
    time.sleep(0.0005) 
    GPIO.output(31,1) 
    GPIO.output(37,0) 
    GPIO.output(temp[temperature()%10], 1) 
    time.sleep(0.0005) 
    GPIO.output(37,1) 

但这代码只是让一个数字补光灯,等待1秒〜,点亮了其他数字,等待1秒〜.....等等上。

的如何做到这一点任何想法非常赞赏。

+0

这是关于读取温度或运行GPIO的问题吗?关于读取温度FAST以运行GPIO的 –

+0

。 –

+0

我怀疑它是如此缓慢。你有计时吗?如果速度慢,你可以在每次读取前保持文件打开并寻找(0),但如果速度更快,我会感到惊讶。我问你是否有时间吗? –

回答

0

我会把显示程序放到它自己的线程中,这样你就不必在主循环中考虑它了。下面的代码应该证明这个概念。将“测试”设置为False以查看它是否适用于您的硬件。

#!/usr/bin/python 

import time 
import threading 
import Queue 
import random 

# Set this to False to read the temperature from a real sensor and display it on a 7-digit display. 
testing = True 

def temperature_read(q): 
    # Read the temperature at one second intervals. 
    while True: 
     if testing: 
      r = '-' * 69 + '%02d' % (random.randrange(100)) + 'blahblah' * 4 
     else: 
      r = open('/sys/bus/w1/devices/28-041670f43bff/w1_slave', 'r').read() 

     print r 

     # The temperature is represented as two digits in a long string. 
     # Push the digits into the queue as a tuple of integers (one per digit). 
     q.put((int(r[69]), int(r[70]))) 

     # Wait for next reading. 
     # (Will w1_slave block until the next reading? If so, this could be eliminated.) 
     time.sleep(1.0) 

def temperature_display(q): 
    # Display the temperature. 

    # Temperature is two digits, stored separately (high/low) for more efficient handling. 
    temperature_h = temperature_l = 0 


    while True: 
     # Is there a new temperature reading waiting for us? 
     if not q.empty(): 
      temperature = q.get() 

      # If it's None, we're done. 
      if temperature is None: 
       break 

      # Load the two digits (high and low) representing the temperature. 
      (temperature_h, temperature_l) = temperature 

     if testing: 
      print 'displayH', temperature_h 
      time.sleep(0.05) 
      print 'displayL', temperature_l 
      time.sleep(0.05) 

     else: 
      GPIO.output(31,0) 
      GPIO.output(temperature_h, 1) # temp is a dictionary used to know which segments to light up to show numbers 
      time.sleep(0.0005) 
      GPIO.output(31,1) 
      GPIO.output(37,0) 
      GPIO.output(temperature_l, 1) 
      time.sleep(0.0005) 
      GPIO.output(37,1) 

    # Clean up here. Turn off all pins? 




# Make a queue to communicate with the display thread. 
temperature_queue = Queue.Queue() 

# Run the display in a separate thread. 
temperature_display_thread = threading.Thread(target=temperature_display, args=(temperature_queue,)) 
temperature_display_thread.start() 

# Run the reader. 
try: 
     temperature_read(temperature_queue) 
except: 
     # An uncaught exception happened. (It could be a keyboard interrupt.) 
     None 

# Tell the display thread to stop. 
temperature_queue.put(None) 

# Wait for the thread to end. 
temperature_display_thread.join() 

再支持读取(传输),我只是把它在读取循环,而不是增加另一个线程它。我改变了队列,以便你可以轻松地将它移动到另一个线程,但是我怀疑你会添加更多的输入,所以这可能是一种合理的方式来做到这一点,除非一个人的阅读频率需要大不相同。 (即使是这样,你可以做的事情,在该循环计数器。)

#!/usr/bin/python 

import time 
import threading 
import Queue 
import random 

# Set this to False to read the temperature from a real sensor and display it on a 7-digit display. 
testing = True 

def observe(q): 
    while True: 

     # Make a temperature reading. 
     if testing: 
      r = '-' * 69 + '%02d' % (random.randrange(100)) + 'blahblah' * 4 
     else: 
      r = open('/sys/bus/w1/devices/28-041670f43bff/w1_slave', 'r').read() 

     print 'temperature ->', r 

     # The temperature is represented as two digits in a long string. 
     # Push the digits into the queue as a tuple of integers (one per digit). 
     q.put(('temperature', int(r[69]), int(r[70]))) 

     # Make a transmission reading. 
     if testing: 
      r = random.randrange(1,6) 
     else: 
      r = 0 # Put your transmission reading code here. 

     print 'transmission ->', r 

     q.put(('transmission', r)) 

     # Wait for next reading. 
     # (Will w1_slave block until the next reading? If so, this could be eliminated.) 
     time.sleep(1.0) 


def display(q): 
    # Display the temperature. 

    # Temperature is two digits, stored separately (high/low) for more efficient handling. 
    temperature_h = temperature_l = transmission = 0 


    while True: 
     # Is there a new temperature reading waiting for us? 
     if not q.empty(): 
      reading = q.get() 

      # If it's None, we're done. 
      if reading is None: 
       break 
      elif reading[0] == 'temperature': 
       # Load the two digits (high and low) representing the temperature. 
       (x, temperature_h, temperature_l) = reading 
      elif reading[0] == 'transmission': 
       (x, transmission) = reading 

     if testing: 
      print 'displayH', temperature_h 
      time.sleep(0.05) 
      print 'displayL', temperature_l 
      time.sleep(0.05) 
      print 'transmission', transmission 
      time.sleep(0.05) 

     else: 
      GPIO.output(31,0) 
      GPIO.output(temperature_h, 1) # temp is a dictionary used to know which segments to light up to show numbers 
      time.sleep(0.0005) 
      GPIO.output(31,1) 
      GPIO.output(37,0) 
      GPIO.output(temperature_l, 1) 
      time.sleep(0.0005) 
      GPIO.output(37,1) 

    # Clean up here. Turn off all pins? 

# Make a queue to communicate with the display thread. 
readings_queue = Queue.Queue() 

# Run the display in a separate thread. 
display_thread = threading.Thread(target=display, args=(readings_queue,)) 
display_thread.start() 

# Observe the inputs. 
try: 
    observe(readings_queue) 
except: 
    # An uncaught exception happened. (It could be a keyboard interrupt.) 
    None 

# Tell the display thread to stop. 
readings_queue.put(None) 

# Wait for the thread to end. 
display_thread.join() 

这里有一个版本,只读取温度每第十次,但每一次读取传输。我想你会看到如何轻松调整这个来满足你的需求。

我会为每个读者制作单独的线程,但它会使线程管理变得复杂一些。

#!/usr/bin/python 

import time 
import threading 
import Queue 
import random 

# Set this to False to read the temperature from a real sensor and display it on a 7-digit display. 
testing = True 

def observe(q): 
    count = 0 

    while True: 
     # Only read the temperature every tenth time. 
     if (count % 10 == 0): 
      # Make a temperature reading. 
      if testing: 
       r = '-' * 69 + '%02d' % (random.randrange(100)) + 'blahblah' * 4 
      else: 
       r = open('/sys/bus/w1/devices/28-041670f43bff/w1_slave', 'r').read() 

      print 'temperature ->', r 

      # The temperature is represented as two digits in a long string. 
      # Push the digits into the queue as a tuple of integers (one per digit). 
      q.put(('temperature', int(r[69]), int(r[70]))) 

     # Make a transmission reading. 
     if testing: 
      r = random.randrange(1,6) 
     else: 
      r = 0 # Put your transmission reading code here. 

     print 'transmission ->', r 

     q.put(('transmission', r)) 

     # Wait for next reading. 
     if testing: 
      time.sleep(0.5) 
     else: 
      time.sleep(0.1) 

     count += 1 

def display(q): 
    # Display the temperature. 

    # Temperature is two digits, stored separately (high/low) for more efficient handling. 
    temperature_h = temperature_l = transmission = 0 


    while True: 
     # Is there a new temperature reading waiting for us? 
     if not q.empty(): 
      reading = q.get() 

      # If it's None, we're done. 
      if reading is None: 
       break 
      elif reading[0] == 'temperature': 
       # Load the two digits (high and low) representing the temperature. 
       (x, temperature_h, temperature_l) = reading 
      elif reading[0] == 'transmission': 
       (x, transmission) = reading 

     if testing: 
      print 'displayH', temperature_h 
      time.sleep(0.05) 
      print 'displayL', temperature_l 
      time.sleep(0.05) 
      print 'transmission', transmission 
      time.sleep(0.05) 

     else: 
      GPIO.output(31,0) 
      GPIO.output(temperature_h, 1) # temp is a dictionary used to know which segments to light up to show numbers 
      time.sleep(0.0005) 
      GPIO.output(31,1) 
      GPIO.output(37,0) 
      GPIO.output(temperature_l, 1) 
      time.sleep(0.0005) 
      GPIO.output(37,1) 

    # Clean up here. Turn off all pins? 

# Make a queue to communicate with the display thread. 
readings_queue = Queue.Queue() 

# Run the display in a separate thread. 
display_thread = threading.Thread(target=display, args=(readings_queue,)) 
display_thread.start() 

# Observe the inputs. 
try: 
    observe(readings_queue) 
except: 
    # An uncaught exception happened. (It could be a keyboard interrupt.) 
    None 

# Tell the display thread to stop. 
readings_queue.put(None) 

# Wait for the thread to end. 
display_thread.join() 
+0

是的。这正是我所需要的。温度更新并正确显示。谢谢 –

+0

你能告诉我如何添加另一个线程?我有另一段代码,就像一个齿轮(卡丁车换档)指示器(1 ... 2 ... 3 ... 4 ... 5 ... 4..3..etc),我想要与此同时在相同的4位7段显示器上运行。再次感谢你。 –

+0

我在这里新来的,所以我不知道如果我这样做的权利... 我添加了传输到我的答案的代码。那样有用吗? –

2

而不是实现你自己的这个功能,你应该使用的库,在那里,地址代码的特定位本身。在这种情况下,我建议你使用W1ThermSensor。你可以找到的文档:

https://github.com/timofurrer/w1thermsensor

,您可以使用安装它:

pip install w1thermsensor 

它支持的DS18B20,并提供精确的模拟,以你的使用情况自述文件。

从文档的包:

from w1thermsensor import W1ThermSensor 

sensor = W1ThermSensor() 
temperature_in_celsius = sensor.get_temperature() 
temperature_in_fahrenheit = sensor.get_temperature(W1ThermSensor.DEGREES_F) 
temperature_in_all_units = sensor.get_temperatures([ 
    W1ThermSensor.DEGREES_C, 
    W1ThermSensor.DEGREES_F, 
    W1ThermSensor.KELVIN 
]) 

在许多情况下,特别是对于流行的硬件设备,你会发现,目前已经提供给蟒蛇内使用库,并且将所有你快速继续写下你自己特定需求的独特代码。

注:根据以下链接的技术讨论,如果DS18B20设置为12位温度分辨率,温度转换将花费750毫秒或3/4秒。如果您将硬件设置为9位分辨率,则硬件中的转换时间为93.75毫秒。我怀疑这是你每秒一次的问题的根源。

https://www.maximintegrated.com/en/app-notes/index.mvp/id/4377

没有在这个问题上这个问题的一些讨论:

https://raspberrypi.stackexchange.com/questions/14278/how-to-change-ds18b20-reading-resolution

见第二个答案,关于configDS18B20效用。

设置为9位分辨率,你可以能够调整在源代码中的w1thermsensorRETRY_DELAY_SECONDS/RETRY_ATTEMPTS值组合,并得到你所需要的。我不清楚重试延迟是否会影响设备的实际轮询。它看起来像是在那里寻找设备。虽然,正如我所说的那样,间隔可能会影响轮询单个设备的。我只是没有仔细阅读源代码,看看它在什么时间和地点发挥作用。


新年快乐!

+0

非常感谢你的这个想法。我将使用这个包。但是这个功能每秒钟左右只能显示一次温度。 –

+0

@PinteaMihaita查看我更新的答案。你可以通过改变硬件本身的温度分辨率来解决这个问题,但是通过在你的软件中进行任何操作,不会改变硬件配置,你看起来不会比1秒更新好得多。即使如此,目前还不清楚这是否会有所帮助,根据我上面提到的来自raspberrypi.stackexchange.com的回答。不过,这是你最好的选择。祝你好运! –

+0

谢谢。也会试图做到这一点。也许我可以更好地提高速度。谢谢 –

相关问题