Hello Dexter-Users
TL;DR Error when using python2 and multiple sensors
I/O operation on closed file
or
argument must be an int, or have a fileno() method.
Background
I have a RaspberryPi 3 B+ and the grovePi Board
Connected to the grovePi are
- 2x SPDT 4 Channel Relay
- 2x Humidity and Temperature Sensor Pro
- 2x Buttons
- 2x Moisture Sesnsor
All the sample programs are working but as soon as I “connect” them or using more than one, i get one or both of the above error messages
My Code
import sys
import signal
import threading
import logging
import time
import datetime
import math
import grove
event_sigint = threading.Event()
event_button_pressed = threading.Event()
event_button1_pressed = threading.Event()
event_button2_pressed = threading.Event()
event_dht_reading = threading.Event()
LIGHT1_TIME_ON = datetime.time(16, 0, 0)
LIGHT1_TIME_OFF = datetime.time(20, 0, 0)
VENTILATOR1_TEMP_ON = 28
VENTILATOR1_CYCLE_MINUTE_ON = 10
VENTILATOR1_CYCLE_MINUTE_OFF = 20
BUTTON1_PIN = 2
BUTTON2_PIN = 3
DHT1_PIN = 4
DHT2_PIN = 8
temp1 = temp2 = 0
humi1 = humi2 = 0
def signal_handler(sig, frame):
print("CTRL + C received!")
event_sigint.set()
sys.exit(0)
def read_buttons():
while event_sigint.is_set() is False:
print('waiting for event btn press')
if grove.digitalRead(BUTTON1_PIN) > 0:
# print('btn {} pressed'.format(BUTTON1_PIN))
event_button1_pressed.set()
if grove.digitalRead(BUTTON2_PIN) > 0:
# print('btn {} pressed'.format(BUTTON2_PIN))
event_button2_pressed.set()
time.sleep(.1)
def main():
global temp1, temp2, humi1, humi2
signal.signal(signal.SIGINT, signal_handler)
""" mark 1 """
th_btn = threading.Thread(name='Read Buttons', target=read_buttons)
th_btn.start()
""" mark 2"""
read_dht = True
while event_sigint.is_set() is False:
time_now = datetime.datetime.now()
event_button_pressed.wait(.5)
if event_button1_pressed.is_set():
print('buttonX 1 pressed')
event_button1_pressed.clear()
if event_button2_pressed.is_set():
print('buttonX 2 pressed')
event_button2_pressed.clear()
""" mark 3"""
if time_now.second == 0:
if read_dht:
[temp1, humi1] = grove.dht(4, 1)
[temp2, humi2] = grove.dht(8, 1)
read_dht = False
if math.isnan(temp1) is False and math.isnan(humi1) is False:
print("temp1 = %.02f C humidity1 = %.02f%%" % (temp1, humi1))
if math.isnan(temp2) is False and math.isnan(humi2) is False:
print("temp2 = %.02f C humidity2 = %.02f%%" % (temp2, humi2))
else:
read_dht = True
""" mark 4"""
# time.sleep(.2)
if __name__ == '__main__':
main()
If I comment out the the button stuff (mark1 - mark 2) everything is working fine.
also, if I comment out the dht_reading (mark3 - mark 4) everything is working fine.
but if both readings are active, i get the I/O Error.
I already tried different aproaches to read the vars. my initial version had a thread for everything -> no luck
I then created an event, so that when the dht_reading is running, no button operations are done and vice-versa -> no luck
The OS and the firmware are up to date. my next approach would be using C but I’m not sure if that would help. Do you have any suggestions for me?
my /boot/config.txt
# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details
# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1
# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
#disable_overscan=1
# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16
# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720
# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1
# uncomment to force a specific HDMI mode (this will force VGA)
hdmi_group=2
hdmi_mode=16
# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2
# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4
# uncomment for composite PAL
#sdtv_mode=2
#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800
# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=i2s=on
# Uncomment this to enable the lirc-rpi module
#dtoverlay=lirc-rpi
# Additional overlays and parameters are documented /boot/overlays/README
# Enable audio (loads snd_bcm2835)
dtparam=audio=on
start_x=0
gpu_mem=128
dtparam=i2c1=on
dtparam=spi=off
dtparam=i2c_arm=on
dtparam=i2c_arm_baudrate=50000
enable_uart=0
My Goal
I have 8 relays
1 and 2 should be active every hour from minute 0 - 30
3 and 4 should be active from 16:00 - 20:00. If i press button 1, the relay 3 should toggle and for button 2 it’s the relay 4
Moisture sensore is not yet available but depending on the moisture, an LED, maybe a buzzer and relay 1-2 should be active
As soon as I get the I/O Error I cant abot the programm with CTRL + C. debugging showed me that I’m stuck in
# Write I2C block to the GrovePi
def write_i2c_block(block):
counter = 0
reg = block[0]
data = block[1:]
while counter < 3:
try:
i2c.write_reg_list(reg, data)
time.sleep(0.002 + additional_waiting)
return
except IOError:
counter += 1
time.sleep(0.003)
continue
except Exception as e:
logging.error('ERR: grove.py Line 90', exc_info=e)
counter += 1
time.sleep(0.003)
continue