Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > Python
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.09.2023, 17:16   #1
ZenBooster
Пользователь
 
Регистрация: 10.05.2018
Сообщений: 13
По умолчанию Опрос нескольких датчиков через modbus rtu

Опрашиваю датчики температуры и влажности через USB-RS485 конвертер. Если датчик один, всё прекрасно работает без sleep-ов. Но если надо два датчика опрашивать, без sleep-ов возникает ошибка:
Код:
[SENS_0] 41.8%; 26.4°C [SENS_1] 41.8%; 26.3°C
Traceback (most recent call last):
  File "/home/zenbooster/work/sht20/./sens.py", line 23, in <module>
    sens.read()
  File "/home/zenbooster/work/sht20/dev.py", line 19, in read
    self.t = res.registers[0] / 10
AttributeError: 'ModbusIOException' object has no attribute 'registers'
Почему так происходит, и есть ли более изящное решение чем использование задержек? Или хотя бы способ, как эти задержки рассчитать?

dev.py:

Код:
class csSensBase:
  def __init__(self, cli, id):
    self.cli = cli
    self.id = id

  def get_t(self):
    return self.t

  def get_h(self):
    return self.h

  def get_th(self):
    return (self.t, self.h)

class csSens_XY_MD01(csSensBase):
  def read(self):
    cli = self.cli
    res = cli.read_input_registers(1, 2, slave=self.id)
    self.t = res.registers[0] / 10
    self.h = res.registers[1] / 10
    return res

class csSens_CWT_THxxS(csSensBase):
  def read(self):
    cli = self.cli
    res = cli.read_input_registers(0, 2, slave=self.id)
    self.h = res.registers[0] / 10
    self.t = res.registers[1] / 10
    return res
sens.py:
Код:
#!/usr/bin/env python3
from pymodbus.client import ModbusSerialClient
import sys
from time import sleep
from dev import *

cli = ModbusSerialClient(port='/dev/ttyUSB0', baudrate=9600)

sens_list = [csSens_XY_MD01(cli, 2), csSens_CWT_THxxS(cli, 3)]

while(1):
  try:
    i = 0
    for sens in sens_list:
      sens.read()
      t, h = sens.get_th()
      print(f'[SENS_{i}] {h}%; {t}\u00B0C ', end='')
      sys.stdout.flush()
      i += 1
      sleep(0.15)

    print('')

  except KeyboardInterrupt:
    break

print('') # after ^C

print('end')
cli.close()
ZenBooster вне форума Ответить с цитированием
Старый 08.09.2023, 17:49   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,709
По умолчанию

Цитата:
Сообщение от ZenBooster Посмотреть сообщение
Но если надо два датчика опрашивать, без sleep-ов возникает ошибка:
Так проверяйте на ошибку и не используйте регистры ,если она была.
p51x вне форума Ответить с цитированием
Старый 08.09.2023, 18:12   #3
ZenBooster
Пользователь
 
Регистрация: 10.05.2018
Сообщений: 13
По умолчанию

Цитата:
Сообщение от p51x Посмотреть сообщение
Так проверяйте на ошибку и не используйте регистры ,если она была.
В dev.py сделал так:
Код:
class csSens_XY_MD01(csSensBase):
  def read(self):
    cli = self.cli
    cres = cli.read_input_registers(1, 2, slave=self.id)

    res = not cres.isError()
    if res:
      self.t = cres.registers[0] / 10
      self.h = cres.registers[1] / 10

    self.cres = cres

    return res

class csSens_CWT_THxxS(csSensBase):
  def read(self):
    cli = self.cli
    cres = cli.read_input_registers(0, 2, slave=self.id)

    res = not cres.isError()
    if res:
      self.t = cres.registers[0] / 10
      self.h = cres.registers[1] / 10

    self.cres = cres

    return res
В sens.py:
Код:
#!/usr/bin/env python3
from pymodbus.client import ModbusSerialClient
import sys
from time import sleep
from dev import *

cli = ModbusSerialClient(port='/dev/ttyUSB0', baudrate=9600)

sens_list = [csSens_XY_MD01(cli, 2), csSens_CWT_THxxS(cli, 3)]

while(1):
  try:
    i = 0
    for sens in sens_list:
      while not sens.read():
        #sleep(0.15)
        pass

      t, h = sens.get_th()
      print(f'[SENS_{i}] {h}%; {t}\u00B0C ', end='')
      sys.stdout.flush()
      i += 1
      #sleep(0.15)

    print('')

  except KeyboardInterrupt:
    break

print('') # after ^C

print('end')
cli.close()
- В итоге, каждый раз как возникает ошибка, он несколько секунд думает на read_input_registers, с помощью isError определяет, что была ошибка, потом всё же успешно читает их во время следующей попытки. В целом стало медленнее раз в 5 или около того...
ZenBooster вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
29 датчиков каждому футболисту Ципихович Эндрю Свободное общение 0 06.12.2022 11:14
Создание нескольких процессов через цикл Си WolfEater Помощь студентам 1 29.09.2015 17:29
Опрос датчиков. Не могу построить графики, постоянно появляются какие-то проблемы. IvanNaymov Помощь студентам 1 01.06.2015 20:50
Удаление нескольких записей через checkbox dmitruha PHP 1 23.07.2011 16:07
Отправка нескольких SMS через мобильник Spot Работа с сетью в Delphi 4 24.02.2011 03:18