digital_io.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. from io_module import IO_Module, SysUtils
  2. from modbus import Modbus, MBError, NoResponseError
  3. from log_reader import DigitalLogReader
  4. import colorama
  5. from colorama import Fore
  6. from time import sleep
  7. import time
  8. from datetime import datetime, timedelta, timezone
  9. from mb_registers import DIO_REGS, DioReg
  10. from serial import Serial
  11. class IO_Digital(IO_Module):
  12. def __init__(self, modbus: Modbus):
  13. self.modbus = modbus
  14. super().__init__(self.modbus)
  15. self.log = DigitalLogReader(self.modbus)
  16. '''Запрос параметров дискретных входов'''
  17. # 0x0100 - Состояние входов (вкл./выкл.)
  18. def get_inputs_state(self) -> str:
  19. data = self.modbus.read_holding_registers(DioReg.IN_STATE.value , 1)
  20. return format(data[0], '08b')
  21. # 0x0101 - текущее состояние входов
  22. def get_inputs_bit(self) -> str:
  23. data = self.modbus.read_holding_registers(DioReg.IN_BITS.value , 1)
  24. return format(data[0], '08b')
  25. # 0x0101 - 0x0110 Счетчики импульсов
  26. def get_inputs_counters(self):
  27. data = []
  28. first_reg = DioReg.IN_CNT.value
  29. for i in range(first_reg, first_reg + 16, 2):
  30. data.append(self.modbus.read_uint32_holding(i))
  31. return data
  32. # 0x0120 - режим работы входов
  33. def get_inputs_mode(self):
  34. data = self.modbus.read_holding_registers(DioReg.IN_MODE.value, 1)
  35. return format(data[0], '08b')
  36. # 0x0122 - нормальное состояние входов
  37. def get_inputs_norm_state(self):
  38. data = self.modbus.read_holding_registers(DioReg.IN_NORM.value, 1)
  39. return format(data[0], '08b')
  40. # 0x0124 - время антидребезга отдельного входа (ms)
  41. def get_debounce_channel(self, input):
  42. data = self.modbus.read_holding_registers(DioReg.IN_DEBOUNCE.value + input - 1, 1)
  43. return data[0]
  44. # 0x0124 - время антидребезга всех входов (ms)
  45. def get_debounce_channels(self):
  46. return self.modbus.read_holding_registers(DioReg.IN_DEBOUNCE.value, 8)
  47. '''Запрос датчиков обрыва нагрузки'''
  48. # 0x0130
  49. def get_loads_bit(self):
  50. data = self.modbus.read_holding_registers(DIO_REGS['load_bits'], 1)
  51. return format(data[0], '08b')
  52. # 0x0131
  53. def get_cred_bit(self):
  54. data = self.modbus.read_holding_registers(DIO_REGS['cred_bits'], 1)
  55. return format(data[0], '08b')
  56. '''Установка параметров дискретных входов'''
  57. # 0x0100 - Состояние входов (вкл./выкл.)
  58. def set_inputs_state(self, val):
  59. self.modbus.write_holding_register(DioReg.IN_STATE.value, val)
  60. # 0x0120 - Режим работы всех входов
  61. def set_inputs_mode(self, val):
  62. self.modbus.write_holding_register(DioReg.IN_MODE.value, val)
  63. # 0x0120 - Режим работы отдельного входа
  64. def set_input_mode(self, input, val):
  65. ret = self.modbus.read_holding_registers(DioReg.IN_MODE.value, 1)
  66. if val == 1:
  67. data = ret[0] | (0b1 << (input - 1))
  68. else:
  69. data = ret[0] & ~(0b1 << (input - 1))
  70. self.set_inputs_mode(data)
  71. def get_load_err(self):
  72. 'Состояние датчиков обрыва нагрузки'
  73. data = self.modbus.read_holding_registers(DioReg.LOAD_ERR.value, 1)
  74. return format(data[0], '08b')
  75. def get_outputs_err(self):
  76. 'Неисправность реле'
  77. data = self.modbus.read_holding_registers(DioReg.OUT_ERR.value, 1)
  78. return format(data[0], '08b')
  79. '''Запрос параметров дискретных входов'''
  80. def get_outputs_state(self):
  81. 'Состояние выходов (вкл./выкл.)'
  82. data = self.modbus.read_holding_registers(DioReg.OUT_STATE.value, 1)
  83. return format(data[0], '08b')
  84. def get_outputs_state_save(self):
  85. 'Состояние выходов в безопасном режиме (вкл./выкл.)'
  86. data = self.modbus.read_holding_registers(DioReg.OUT_STATE_SAVE.value, 1)
  87. return format(data[0], '08b')
  88. def get_outputs(self):
  89. 'Текущее состояние выходов'
  90. data = self.modbus.read_holding_registers(DioReg.OUT_BITS.value, 1)
  91. return format(data[0], '08b')
  92. def get_outputs_save(self):
  93. 'Текущее состояние выходов в безопасном режиме'
  94. data = self.modbus.read_holding_registers(DioReg.OUT_BITS_SAVE.value, 1)
  95. return format(data[0], '08b')
  96. def get_outputs_mode(self):
  97. 'Режим работы выходов'
  98. data = self.modbus.read_holding_registers(DioReg.OUT_MODE.value, 1)
  99. return format(data[0], '08b')
  100. def get_outputs_mode_save(self):
  101. 'Режим работы выходов в безопасном режиме'
  102. data = self.modbus.read_holding_registers(DioReg.OUT_MODE_SAVE.value, 1)
  103. return format(data[0], '08b')
  104. '''Установка параметров дискретных выходов'''
  105. def set_outputs_state(self, val):
  106. 'Состояние выходов вкл./выкл. (битовое поле)'
  107. self.modbus.write_holding_register(DioReg.OUT_STATE.value, val)
  108. def set_output_state(self, output, val):
  109. 'Состояние выхода вкл./выкл.'
  110. ret = self.modbus.read_holding_registers(DioReg.OUT_STATE.value, 1)[0]
  111. self.set_outputs_state(SysUtils.set_bit(ret, output - 1, val))
  112. def set_outputs_state_save(self, val):
  113. 'Состояние выходов вкл./выкл. в безопасном режиме (битовое поле)'
  114. self.modbus.write_holding_register(DioReg.OUT_STATE_SAVE.value, val)
  115. def set_outputs(self, val):
  116. 'Текущее состояние выходов в обычном режиме'
  117. self.modbus.write_holding_register(DioReg.OUT_BITS.value, val)
  118. def set_output(self, output, val):
  119. 'Установить значение на конкретном выходе [1..8]'
  120. ret = self.modbus.read_holding_registers(DioReg.OUT_BITS.value, 1)[0]
  121. self.set_outputs(SysUtils.set_bit(ret, output - 1, val))
  122. def set_outputs_save(self, val):
  123. 'Текущее состояние выходов в обычном режиме'
  124. self.modbus.write_holding_register(DioReg.OUT_BITS_SAVE.value, val)
  125. def set_output_save(self, output, val):
  126. 'Установить значение на конкретном выходе [1..8]'
  127. ret = self.modbus.read_holding_registers(DioReg.OUT_BITS_SAVE.value, 1)
  128. self.set_outputs_save(SysUtils.set_bit(ret, output - 1, val))
  129. def set_outputs_mode(self, val):
  130. 'Режим работы выходов (битовое поле)'
  131. self.modbus.write_holding_register(DioReg.OUT_MODE.value, val)
  132. def set_output_mode(self, output, val):
  133. 'Установить режим работы конкретного выхода [1..8]'
  134. ret = self.modbus.read_holding_registers(DioReg.OUT_MODE.value, 1)[0]
  135. self.set_outputs_mode(SysUtils.set_bit(ret, output - 1, val))
  136. def set_outputs_mode_save(self, val):
  137. 'Режим работы выходов в безопасном режиме (битовое поле)'
  138. self.modbus.write_holding_register(DioReg.OUT_MODE_SAVE.value, val)
  139. def set_output_mode_save(self, output, val):
  140. 'Установить режим работы конкретного выхода [1..8] в безопамном режиме'
  141. ret = self.modbus.read_holding_registers(DioReg.OUT_MODE_SAVE.value, 1)[0]
  142. self.set_outputs_mode_save(SysUtils.set_bit(ret, output - 1, val))
  143. def print_inputs(self):
  144. # Состояние входов (вкл./выкл.)
  145. print('Inputs state [bit field] :', Fore.GREEN + self.get_inputs_mode())
  146. # Значения входов (битовое поле)
  147. print('Inputs values [bit field] :', Fore.GREEN + self.get_inputs_bit())
  148. # Значение счетчиков
  149. data = self.get_inputs_counters()
  150. print('Inputs counters :', Fore.GREEN + ' | '.join(str(el) for el in data))
  151. # Режим работы входов (битовое поле)
  152. print('Inputs mode [bit field] :', Fore.GREEN + self.get_inputs_mode())
  153. # Нормальное состояние входов (битовое поле)
  154. print('Inputs norm [bit field] :', Fore.GREEN + self.get_inputs_norm_state())
  155. # Период антидребезга (ms)
  156. print('Debounce input (ms) :', Fore.GREEN + ' | '.join(str(el) for el in self.get_debounce_channels()))
  157. def print_loads(self):
  158. # Значения датчиков нагрузки (битовое поле)
  159. print('Loads values [bit field] :', Fore.GREEN + self.get_loads_bit())
  160. # Слово достоверности датчиков нагрузки (битовое поле)
  161. print('Credibility loads [bit field] :', Fore.GREEN + self.get_cred_bit())
  162. class IO_DigitalTester:
  163. def __init__(self, dev_tester: IO_Digital, dev_dut: IO_Digital):
  164. self.tester = dev_tester
  165. self.dut = dev_dut
  166. '''Управление DUT'''
  167. # Подать/снять питание на DUT
  168. def dut_switch(self, state: bool):
  169. self.tester.set_output(1, state)
  170. # Установить 1 на нечетных входах DUT
  171. def dut_set_odd_inputs(self):
  172. self.tester.set_output(2, False)
  173. # Установить 1 на четный входах DUT
  174. def dut_set_even_imputs(self):
  175. self.tester.set_output(2, True)
  176. '''Тест входов'''
  177. def test_inputs(self):
  178. self.dut_set_even_imputs()
  179. time.sleep(0.1)
  180. self.dut.print_inputs()
  181. time.sleep(1)
  182. self.dut_set_odd_inputs()
  183. time.sleep(0.1)
  184. self.dut.print_inputs()
  185. time.sleep(1)
  186. '''Тест выходов и датчика обрыва нагрузки'''
  187. def test_load(self):
  188. # Все выходы DUT разомкнуты
  189. print("Все выходы DUT разомкнуты...")
  190. self.dut.set_outputs(0)
  191. self.dut.print_loads()
  192. time.sleep(0.1)
  193. # Замкнуть все выходы DUT (лампочка должна гореть)
  194. print("Все выходы DUT замкнуты...")
  195. self.dut.set_outputs(0b11111111)
  196. time.sleep(0.1)
  197. for i in range(1, 9):
  198. # Разомкнуть i-ый выход DUT
  199. print(f"Разомкнуть выход {i}")
  200. self.dut.set_output(i, 0)
  201. time.sleep(1)
  202. self.dut.print_loads()
  203. self.dut.set_output(i, 1)
  204. time.sleep(1)
  205. def get_load(self):
  206. self.dut.set_outputs(0b11110111)
  207. # self.dut.set_outputs(0)
  208. time.sleep(1)
  209. self.dut.print_loads()
  210. def main():
  211. colorama.init(autoreset=True)
  212. serial_port = Serial('COM11', 115200, timeout=0.05, parity='N', xonxoff=False)
  213. modbus_tester = Modbus(serial_port, 1)
  214. modbus_tester.MB_DEBUG = False
  215. # dev_tester = IO_Digital(modbus_tester)
  216. dio = IO_Digital(modbus_tester)
  217. '''Тесты отдельного модуля DIO'''
  218. dio.sys.get_system_vars()
  219. # print(dio.sys.get_save_mode())
  220. # print(dio.sys.get_save_delay())
  221. '''Сохранить информацию о модуле'''
  222. # dio.sys.set_info('This is supe r DIO!')
  223. # dio.print_inputs()
  224. # dio.get_inputs_counters()
  225. # modbus_dut = Modbus(serial_port, 2)
  226. # dev_dut = IO_Digital(modbus_dut)
  227. # tester = IO_DigitalTester(dev_tester, dev_dut)
  228. '''Включить DUT'''
  229. # tester.dut_switch(True)
  230. '''Запросить системные настройки DUT'''
  231. # dio.sys.get_system_vars()
  232. '''Тест входов. Переключение значений на входах DUT'''
  233. # for i in range(10):
  234. # tester.test_inputs()
  235. '''Тестирование выходов и датчиков обрыва нагрузки'''
  236. # tester.test_load()
  237. # for i in range(100):
  238. # tester.get_load()
  239. '''Выходы'''
  240. # print(dio.get_outputs())
  241. '''~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'''
  242. ''' Выходы '''
  243. '''Выходы вкл/выкл'''
  244. # print(dio.get_outputs_state())
  245. # dio.set_outputs_state(0b1001_0000)
  246. # print(dio.get_outputs_state())
  247. # print(dio.get_outputs_state_save())
  248. # dio.set_outputs_state_save(0b0001_1001)
  249. # print(dio.get_outputs_state_save())
  250. '''Режим работы'''
  251. # print(dio.get_outputs_mode())
  252. # print(dio.get_outputs_mode_save())
  253. # dio.set_outputs_state(0b0000_0001)
  254. # dio.set_outputs_mode(0b0000_0000)
  255. # dio.set_outputs(0b0000_0001)
  256. # print(dio.get_outputs_mode())
  257. '''Текущие значения'''
  258. # print(dio.get_outputs())
  259. # print(dio.get_outputs_save())
  260. # dio.set_outputs_state(0b1000_0000)
  261. # dio.set_output_mode(8, 1)
  262. # dio.set_outputs(0b1000_0000)
  263. # dio.set_outputs_state_save(0b0000_0000)
  264. # dio.set_outputs_save(0b0000_0000)
  265. # dio.set_outputs_state_save(0b1000_0000)
  266. # dio.set_output_mode_save(8, 0)
  267. # dio.set_outputs_save(0b1000_0000)
  268. # print(dio.get_inputs_mode())
  269. # for i in range(100):
  270. # dio.set_outputs(0b00000001)
  271. # sleep(1)
  272. # dio.set_outputs(0b00000000)
  273. # sleep(1)
  274. '''Системные переменные и параметры'''
  275. # dio.sys.get_system_vars()
  276. # print(dio.sys.get_bat_votage())
  277. '''Безопасный режим'''
  278. # print(dio.sys.get_save_delay())
  279. # print(dio.sys.get_save_mode())
  280. # dio.sys.set_save_mode(0)
  281. # print(dio.sys.get_save_mode())
  282. # dio.sys.set_save_delay(5)
  283. ''' Установить текущее время с учетом часового пояса'''
  284. # print(dio.sys.get_rtc())
  285. # dio.sys.get_system_vars()
  286. '''Лог и архив. Настройки лога.'''
  287. # dev.log.get_log_info()
  288. # dev.log.get_random_entries()
  289. # for i in range(8):
  290. # dev.log.set_archive_period(5 + i*2, i)
  291. # dev.log.get_log_info()
  292. # dev.log.get_all_archive()
  293. # dev.log.get_all_log()
  294. # dev.log.log_clear()
  295. # dev.log.archive_clear()
  296. '''Лог'''
  297. # dev.log.get_all_log()
  298. '''Архив'''
  299. # dev.log.get_all_archive()
  300. # print(dev.log.get_archive_entry(0, 1))
  301. '''Сохранение настроек'''
  302. # dio.sys.save_sattings()
  303. '''Настройки'''
  304. '''Регистры модуля'''
  305. # dev.print_inputs()
  306. '''Аварии'''
  307. # print(dio.get_load_err())
  308. # print(dio.get_outputs_err())
  309. '''Настройи модуля'''
  310. # for i in range(1, 9):
  311. # dev.set_input_mode(i, 1)
  312. # print('Inputs mode [bit field] :', Fore.GREEN + dev.get_inputs_mode())
  313. # dev.set_input_mode(4, 1)
  314. # dev.print_inputs()
  315. '''Обновление'''
  316. # serial_port.timeout = 1
  317. # modbus_tester.MB_DEBUG = True
  318. # dio.updater.update('fw.bin', 'MDIO_88')
  319. if __name__ == '__main__':
  320. main()