Python, в то время как l oop не прекращается через определенное количество времени - PullRequest
1 голос
/ 05 февраля 2020

Для этого проекта я создал устройство для измерения вибрации, которое отображает высокоскоростные вибрации, которые контролируются двигателем. Вот код ниже:

# Import the modules
from __future__ import division
import spidev, datetime, time
from sys import exit
import RPi.GPIO as GPIO

# Setup SPI
spi = spidev.SpiDev()
spi.open(0, 0)
spi.mode = 3

# Constants
accres, accrate = 1, 15

# Set GPIO chip select pins
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
cs1, cs2, motor = 23, 24, 18
GPIO.setup(cs1, GPIO.OUT)
GPIO.setup(cs2, GPIO.OUT)
GPIO.setup(motor, GPIO.OUT)

# Note: the duty cycle goes from 0.0 to 100.0, with 100.0 being no motor movement,
# and 0.0 being the maximum motor speed.
motor_output = GPIO.PWM(motor, 60)

# Initialize the ADXL345
def initadxl345():
    # Set data rate (accrate=15 -> 3200 Hz, 14=1600 Hz, 13=800 Hz, 12=400 Hz, 11=200 Hz, 10=100 Hz etc.)
    spi.xfer2([44, accrate])

    # Enable full range (10 bits resolution) and +/- 16g 4 LSB
    spi.xfer2([49, accres])

# Read the first ADXL x-y-z axes
def readadxl345_1():
    # Chip select pin ensures that the first sensor is being read by grounding its pin
    GPIO.output(cs1, 0)
    GPIO.output(cs2 ,1)

    rx = spi.xfer2([242, 0, 0, 0, 0, 0, 0])
    out = [rx[1] | (rx[2] << 8), rx[3] | (rx[4] << 8), rx[5] | (rx[6] << 8)]
    # Format x-axis
    if (out[0] & (1 << 16 - 1 )):
        out[0] = out[0] - (1 << 16)
    # Format y-axis
    if (out[1] & (1 << 16 - 1 )):
        out[1] = out[1] - (1<<16)
    # Format z-axis
    if (out[2] & (1 << 16 - 1 )):
        out[2] = out[2] - (1 << 16)
    # Return human readable values
    return out

# Read the second ADXL x-y-z axes
def readadxl345_2():
    # Chip select pin ensures that the first sensor is being read by grounding its pin
    GPIO.output(cs1, 1)
    GPIO.output(cs2 ,0)

    rx = spi.xfer2([242, 0, 0, 0, 0, 0, 0])
    out = [rx[1] | (rx[2] << 8), rx[3] | (rx[4] << 8), rx[5] | (rx[6] << 8)]
    # Format x-axis
    if (out[0] & (1 << 16 - 1 )):
        out[0] = out[0] - (1 << 16)
    # Format y-axis
    if (out[1] & (1 << 16 - 1 )):
        out[1] = out[1] - (1<<16)
    # Format z-axis
    if (out[2] & (1 << 16 - 1 )):
        out[2] = out[2] - (1 << 16)
    # Return human readable values
    return out

print("Vibration Reader Initializing...")
time.sleep(1)
print(GPIO.RPI_INFO)
time.sleep(1)

response = input("Proceed measurements? [Y, n] ")

if response == "Y" or "y":
    filename = input("Filename: ")
    pwm_speed = float(input("Motor PWM value: "))
    # Initialize the ADXL345 accelerometer
    print("Initializing ADXL345s...")
    initadxl345()
    motor_output.start(pwm_speed)
    print("Motor is up and running at {}".format(pwm_speed))
    time.sleep(1)

    timeout = 0.0003125 / 2 # timeout=1/samplerate=>not sufficient measurements. Half the time is sufficient (don't know why!)

    timetosend = 1

    while True:
       with open('/proc/uptime', 'r') as f: # get uptime
           uptime_start = float(f.readline().split()[0])
       uptime_last = uptime_start
       active_file_first = filename + '.csv'
       file = open('/var/log/sensor/' + active_file_first, 'w')
       while uptime_last < uptime_start + timetosend:

           time1 = str(datetime.datetime.now().strftime('%S.%f'))
           sensor1 = readadxl345_1()
           sensor2 = readadxl345_2()
           file.write(str(sensor1[0]) + ',' + str(sensor1[1]) + ',' + str(sensor1[2]) + ',' + str(sensor2[0]) + ',' + str(sensor2[1]) + ',' + str(sensor2[2]) + ',' + time1 + '\n')

           # Print data every "timeout" second
           elapsed = time.process_time()
           current = 0
           while(current < timeout):
               current = time.process_time() - elapsed

    motor_output.stop
    print("Motor shutting off and cleaning up GPIO.")
    GPIO.cleanup()

elif response == "N" or "n":
    print("Quitting...")
    time.sleep(1)
    quit()

Из-за этого у меня неприятности. Проблема в том, что, как только я решаю продолжить, выводится оператор печати Motor is up and running at 100.0, и ничего не происходит, пока я не нажму на клавиатуре случайную клавишу, на которой написано:

Traceback (most recent call last):
  File "accelerometer.py", line 116, in <module>
    current = time.process_time() - elapsed
KeyboardInterrupt

Это как если бы код, следующий за этим оператор print даже не существовал, или интерпретатор просто полностью его игнорировал. У кого-нибудь есть четкое объяснение этих проблем?

1 Ответ

1 голос
/ 05 февраля 2020

Давайте сделаем шаг назад и подумаем о том, что делает этот блок кода:

while True:

   ### Block 1 ###
   with open('/proc/uptime', 'r') as f: # get uptime
       uptime_start = float(f.readline().split()[0])
   uptime_last = uptime_start
   active_file_first = filename + '.csv'
   file = open('/var/log/sensor/' + active_file_first, 'w')

   ### Block 2 ###
   while uptime_last < uptime_start + timetosend:

       time1 = str(datetime.datetime.now().strftime('%S.%f'))
       sensor1 = readadxl345_1()
       sensor2 = readadxl345_2()
       file.write(str(sensor1[0]) + ',' + str(sensor1[1]) + ',' + str(sensor1[2]) + ',' + str(sensor2[0]) + ',' + str(sensor2[1]) + ',' + str(sensor2[2]) + ',' + time1 + '\n')
       # Print data every "timeout" second
       elapsed = time.process_time()
       current = 0

       ### Block 3 ###
       while(current < timeout):

           current = time.process_time() - elapsed

Блок 1 проверяет файл времени безотказной работы, считывает время и затем открывает file. Однако, если эта переменная uptime_start никогда не изменяется, то мы можем просто установить ее один раз за пределы (и вместо) верхней while l oop. Блок 2 затем проверяет uptime_last < uptime_start + x, но в предыдущих нескольких строках вы определили uptime_last = uptime_start. Это означает, что до тех пор, пока timetosend не будет отрицательным, этот l oop будет выполняться бесконечно, если не будет выполнено условие внутреннего прерывания. Блок 2 записывает данные датчика в файл. Блок 3 выполняет расчет времени до тех пор, пока не будет выполнено условие, но на самом деле ничего не делает с этой информацией.

Мне кажется, что хороший ответ может быть следующим:

### Block 1 ###
with open('/proc/uptime', 'r') as f: # get uptime
    uptime_start = float(f.readline().split()[0])
file = open('/var/log/sensor/' + filename + '.csv', 'w')
time_elapsed = 0
time_start = time.process_time()

### Block 2 ###
while time_elapsed < uptime_start:

   time1 = str(datetime.datetime.now().strftime('%S.%f'))
   sensor1 = readadxl345_1()
   sensor2 = readadxl345_2()
   file.write(str(sensor1[0]) + ',' + str(sensor1[1]) + ',' + str(sensor1[2]) + ',' + str(sensor2[0]) + ',' + str(sensor2[1]) + ',' + str(sensor2[2]) + ',' + time1 + '\n')

   time_elapsed = time.process_time() - time_start
...