如何从文件中读取字符串,将其转换为 int,将值存储在内存中,然后访问该值并将其打印在屏幕上?

How can I read a string from a file, convert it to int, store the value in memory and then access the value and print it on screen?

我需要使用 Raspberry Pi 3 和 Python 从 DS18B20 传感器读取温度读数。 问题是传感器的刷新率(~1 秒) 我需要从 sys/bus/w1/devices/28-041670f43bff/w1_slave 读取并使用我得到的整数在直接连接到我的 GPIO 的 7 段显示器上显示温度(不使用任何硬件多路复用 - i2c ....等)

为了显示两位数的温度,我需要非常快地打开和关闭数字(比传感器刷新快)

这是用于获取整数温度的一小段代码:

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秒......等等。

非常感谢任何有关如何执行此操作的想法。

与其自行实现此功能,不如使用现有的库来解决代码中的这一特定部分。在这种情况下,我建议您使用 W1ThermSensor。您可以在以下位置找到文档:

https://github.com/timofurrer/w1thermsensor

您可以使用以下方式安装它:

pip install w1thermsensor

它确实支持 DS18B20,并在 README 中提供与您的用例完全类似的内容。

来自包的文档:

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
])

在许多情况下,特别是对于流行的硬件设备,您会发现 python 中已有可供使用的库,这将让您快速继续编写独特的代码位根据您自己的特殊需要。

Note: According to the technical discussion in the following link, if the DS18B20 is set to 12-bit temperature resolution, the temperature conversion will take 750 ms, or 3/4 of a second. If you set the hardware to do 9-bit resolution, the conversion time in hardware is 93.75 ms. I suspect this is the root of your once-per-second issue.

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

There is some discussion of this issue in this Question:

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

See the second Answer, regarding the configDS18B20 utility.

With the resolution set to 9-bit, you may be able to adjust the w1thermsensor RETRY_DELAY_SECONDS / RETRY_ATTEMPTS value combination in the source code and get what you need. It's unclear to me if the retry delay has any affect on the actual polling of the device. It looks like it is there for device finding. Though, as I said, that interval may impact polling a single device. I simply didn't read through the source code enough to see when and where it comes into play.


新年快乐!

我会将显示例程放到它自己的线程中,这样您就不必在主循环中考虑它。下面的代码应该演示这个概念。将 "testing" 设置为 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()

这是一个版本,每十次只读取一次温度,但每次都读取传输。我想您会看到如何轻松调整它以满足您的需求。

我会为每个 reader 创建单独的线程,但这会使线程管理变得相当复杂。

#!/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()