'IOError: [Errno 5] Ошибка ввода / вывода' при использовании SMBus для аналогового чтения через RPi
Я искал ответ для ошибки, упомянутой в названии, но впервые я еще не получил ответ. Мы попытаемся заставить мой Raspberry pi читать аналоговые данные, но когда я запускаю код в окне терминала, он выдает мне "IOError: [Errno 5] Ошибка ввода / вывода".
Код, который я использую для чтения аналоговых данных, показан ниже. Я использую PCF8591 АЦП.
from smbus import SMBus
bus = SMBus(0)
print "read a/d press ctrl + c to stop"
bus.write_byte(0x48, 0)
lastval = -1
while True:
reada = bus.read_byte(0x48)
if(abs(lastval-reada) > 2):
print(reada)
lastval=reada
Я понимаю, что это может быть из-за версии, измененной в Raspberry Pi, и я должен изменить SMBus(0) на SMBus(1). Для этого я проверил свою версию RPi, которая не является исправленной. Но все же я попытался запустить программу, изменив номер SMBus, но мне все равно не повезло.
Ошибка, которую я получаю, показана ниже:
Traceback (most recent call last):
File "analogread.py", line 7, in <module>
bus.write_byte(0x48, 0)
IOError: [Errno 5] Input/output error
Любая помощь приветствуется. Это основной блок в моем большом проекте, который я пытаюсь выполнить. Итак, чем быстрее я получу работу, тем лучше я смогу построить свое приложение. Спасибо
10 ответов
Причиной этого может быть то, что вы работаете удаленно (SSH). После отключения удаленного сеанса ваша программа все еще работает и может попытаться распечатать или взаимодействовать с консолью, которая больше не доступна. Это то, что случилось со мной.
Несмотря на то, что эта ветка старая, я хочу поделиться своим мнением, надеясь, что кому-то еще может помочь, поскольку во всех постах, с которыми я столкнулся, не упоминалось об этом потенциальном исправлении.
Я столкнулся с аналогичной проблемой, но с другим оборудованием (MCP23017 и ЖК-дисплей).
В течение некоторого времени я решил, что проблема не в программном, а в аппаратном обеспечении. В частности, подтягивающие резисторы на линиях SCL и SDA.
RPI (3 в моем случае) имеет резисторы 1,8 кОм, а на моем ЖК-дисплее также установлены некоторые подтягивающие резисторы (~2,2 кОм). Запуск ЖК-дисплея никогда не вызывал проблем, но MCP23017 случайным образом исчезал из шины и появлялся снова при запуске сканирования с помощью команды "i2cdetect -y 1".
Удаление дополнительных подтягивающих резисторов на ЖК-дисплее устранило проблему, и теперь все работает отлично.
Эти ошибки могут быть вне контроля программиста, вызванные случайным, но обычным событием.
Один из подходов состоит в том, чтобы попробовать пару раз, прежде чем следовать с ошибкой
def try_io(call, tries=10):
assert tries > 0
error = None
result = None
while tries:
try:
result = call()
except IOError as e:
error = e
tries -= 1
else:
break
if not tries:
raise error
return result
try_io(lambda: bus.write_byte(0x48, 0))
Причиной этого может быть то, что вы выталкиваете read/write
звонки быстрее, чем ваше оборудование может принять их. Поэтому добавьте небольшие задержки между операциями чтения / записи:
from time import sleep
from smbus import SMBus
bus = SMBus(0)
bus.write_byte(0x48, 0)
sleep(0.2) # Wait for device to actually settle down
lastval = -1
while True:
reada = bus.read_byte(0x48)
if(abs(lastval-reada) > 2):
print(reada)
lastval=reada
sleep(0.2) # This might be not needed.
Другая возможность состоит в том, что устройство фактически не присутствует в этом адресе. Поэтому, если таймауты не помогают, попробуйте i2c-tools (должен быть доступен через управление пакетами, если вы не используете дистрибутив программного обеспечения), чтобы проверить, действительно ли устройство доступно (иногда это может быть проблема с проводкой, например, забытая). GND):
i2cdetect -y [bus number]
Почему i2c? Потому что SMBus - это, по сути, модификация шины i2c с более строго определенными уровнями напряжения и таймингами.
Я столкнулся с этой проблемой при управлении 7-сегментным последовательным дисплеем по I2C с моделью b+ rpi. Я исправил проблему, настроив скорость передачи в соответствии с настройками устройства (9600). Я считаю, что по умолчанию 100000.
Чтобы изменить скорость передачи, я добавил следующую строку в /etc/modprobe.d/i2c.conf:
options i2c_bcm2708 baudrate=9600
После перезагрузки я убедился, что настройки вступили в силу:
prompt$ sudo cat /sys/module/i2c_bcm2708/parameters/baudrate
9600
С тех пор у меня не было проблем с прерывистыми ошибками ввода-вывода.
Я знаю, что эта тема довольно старая, но та же ошибка произошла с I2C и PCA9685, когда я поместил значения, которые не были в диапазоне. Я понял, что просто отключил и включил I2C:
sudo raspi-config
- "5. Варианты сопряжения
- 'P5 I2C'
- "Нет"
- 'ХОРОШО'
sudo reboot now
sudo raspi-config
- "5. Варианты сопряжения
- 'P5 I2C'
- 'Да'
- 'ХОРОШО'
sudo reboot now
После этого, sudo i2cdetect -y 1
снова обнаруживает мой ШИМ-модуль I2C.
У меня была аналогичная проблема при удаленном чтении файла csv большого объема (с сервера), когда я удаленно подключался к рабочей станции и пытался прочитать файл csv большого размера с сервера. Я скопировал файлы на рабочую станцию, и, следовательно, «IOError: [Errno 5] Ошибка ввода / вывода» была устранена. После этого у меня была ошибка MemoryError, которую я разрешил путем чтения фрагмента, а затем преобразовал его в фрейм данных с помощью
pd.concat
.
Код выглядит следующим образом:
chunk=pd.read_csv(CSV_File_Loc,chunksize=1000000,low_memory=False)
DF_CSV=pd.concat(chunk)
Выпуск старый, но на мой взгляд очень актуальный!
Решение (для RPi 3B+) - установить режим ALT0 для GPIO на контактах 3 и 5 (физических). Это можно сделать с помощью инструмента командной строки gpio:
gpio mode 8 alt0
gpio mode 9 alt0
8 и 9, так как это нумерация, используемая wiringpi для физических контактов 3 и 5. И это как раз проблема... он использует wiringpi.
http://wiringpi.com/wiringpi-deprecated/
В моем коде на Python я мог бы создать системный вызов этих двух команд (для меня это работает!)
Однако мне нужно решение, в котором не используются устаревшие библиотеки или инструменты.
Кто угодно?
В моем случае был оператор печати, который вызывал эту проблему, я просто удалил этот оператор печати, и теперь эта проблема для меня решена.
У меня была такая же проблема в связи RasPi -> ATMEGA, и я решил ее на подчиненном устройстве. Это сообщение об ошибке появляется, если ваш ведомый не отвечает.
Я попробовал следующий код на RasPi с ведомым устройством I2C, подключенным к шине I2C и настроенным с адресом 0x8:
от smbus импорт SMBus
I2C_Bus = SMBus (1)
SLAVE_ADD = 0x8
I2C_Bus.write_byte (SLAVE_ADD, 0xAA)
Если ведомый I2C хорошо настроен для подтверждения, он должен работать!