Извини, но просто повторяюсь
https://ru.aliexpress.com/...2816412117.html
Это именно мини-UPS на одной плате.
Ненавязчивая автоматизация ректификационной установки
Dmi_D
Кандидат наук
Минск
393 138
Отв.1140 10 Февр. 18, 23:16
BogAD
Кандидат наук
Красногорск - Белово
403 184
Отв.1141 11 Февр. 18, 00:06, через 50 мин
Извини, но просто повторяюсьDmi_D, 10 Февр. 18, 23:16Пардон, не внимателен. Да, я видел.
Полезно почитать отзывы, прежде чем покупать.
к примеру нашел
"прежде всего это не UPS! продавцом, используя это слово в описании .. я тестировал его, и если Я отрезать власти в филиал выход всегда есть задержки и например оранжевый PI перезагрузки сам .. The consumption of Orange PI ~ 0.32A так очень малый ток, но даже с этой небольшой ток это устройство не может вести себя, как UPS!"
Т.е Orange PI на нем перегружается. Наша Малинка думаю тоже не вытерпит это...
Да и по отзывам, греется как печка.
На нетребовательную слаботочку может сгодится.
Dmi_D
Кандидат наук
Минск
393 138
Отв.1142 11 Февр. 18, 00:30, через 24 мин
Прости, не понял, о чем ты.
В смысле, это отзыв на твою или на мою ссылку?
В смысле, это отзыв на твою или на мою ссылку?
BogAD
Кандидат наук
Красногорск - Белово
403 184
Отв.1143 11 Февр. 18, 01:31
Dmi_D
Кандидат наук
Минск
393 138
Отв.1144 11 Февр. 18, 01:38, через 8 мин
Я уже после поста перерыл отзывы....
Давай так - я получаю модуль, тестирую, отчитываюсь.
А то делим шкуру, а медведя, может, и не было.
Тайм-аут до получения посылки.
Давай так - я получаю модуль, тестирую, отчитываюсь.
А то делим шкуру, а медведя, может, и не было.
Тайм-аут до получения посылки.
ZagAl
Доцент
Прибалтика
1.9K 916
Отв.1145 12 Февр. 18, 14:01
Всем, доброго дня.
В связи с тем, что у меня часто выбивает термодатчики (подключены к raspberry Pi Zero), решил поизучать этот вопрос.
Сделал программу на основе nna_02.py
import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#-----------------------------------------------------------------------
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = time.time()
#-----------------------------------------------------------------------
i=0
#-----------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#-----------------------------------------------------------------------
i+=1; ss = "% 5d" % (i) # Счетчик циклов
#-----------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#-----------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
Ts = sens.DS18B20.Ts() # Сначала их измерим
for id in tids: # Теперь добавим в строки для выдачи
if id == cid: # Подкрасим температуру в колонне для консоли
ss += "\x1b[32m% 6.2f\x1b[0m" % (Ts[id])
else: ss += "% 6.2f" % (Ts[id])
#-----------------------------------------------------------------------
print ss # и выводим на экран
time.sleep(5)
В результате, если в процессе работы программы отключить датчики, на экране будут отображаться нули. Если подключить датчики, то показания восстанавливаются. В первой строке, после восстановления показаний, может отображаться 85.0. Если не подключать датчики, то через 21 шаг происходит сбой программы. Первый вопрос: почему в течение 21 шага отображаются нули?
Изменил программу, добавив команду на завершение работы программы в случае если датчик отвалился.
import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
#import contrSTPR, sensWEIGHT
#--------------------------------------------------------------------------------
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#--------------------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#--------------------------------------------------------------------------------
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = time.time()
#--------------------------------------------------------------------------------
i=0
#--------------------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#--------------------------------------------------------------------------------
i+=1; ss = "% 5d" % (i) # Счетчик циклов
#--------------------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#--------------------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
Ts = sens.DS18B20.Ts() # Сначала их измерим
flag = False
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol)
else:
ss += "\x1b[31m %6.2f\x1b[0m" % (0.) # А если такого датчика нет - ставим нули.
flag = True
if flag:
print "Завершение работы"
sys.exit(1)
#--------------------------------------------------------------------------------
print ss # и выводим на экран
time.sleep(5)
Результат такой же как и прежде, за исключением того, что программа завершается по команде, но через те же 21 шаг, отображая при этом нули.
В следующей модификации программы, вместо команды завершения программы, дал команду на отображение нулей красным цветом.
import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
import contrSTPR, sensWEIGHT
#--------------------------------------------------------------------------------
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#--------------------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#--------------------------------------------------------------------------------
"""Параметр timeout задает время ожидания нажатия клавиши (он может быть
равен 0). В данном случае мы используем этот параметр для регулирования
длительности одного такта главного цикла приложения. При timeout = 3000
длительность такта составляет около 4 сек"""
#timeout = 3910 # В мс. Должно быть 5 сек.
#tt = kbh.TT(timeout)
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = New_time = time.time()
#--------------------------------------------------------------------------------
i=0
#--------------------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#--------------------------------------------------------------------------------
i+=1; ss = "% 5d" % (i) # Счетчик циклов
#--------------------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#--------------------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
Ts = sens.DS18B20.Ts() # Сначала их измерим
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol)
else: ss += "\x1b[31m %6.2f\x1b[0m" % (0.) # А если такого датчика нет - ставим нули.
#--------------------------------------------------------------------------------
time.sleep(5)
print ss # и выводим на экран
В результате после 21-го шага отображения нулей, начинают бесконечно отображаться нули красного цвета. Сама программа не завершается. То есть во всех этих трех вариантах, команда else:, непонятно почему выполняется только через 21 шаг после возникновения проблемы.
Новая модификация программы:
import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
import contrSTPR, sensWEIGHT
import RPi.GPIO as GPIO
ReadSensors = False
#-----------------------------------------------------------------------
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD) # Определяем пины по номерам
GPIO.setup(12, GPIO.OUT) # Пин 12 - вывод
GPIO.output(12,1) # Подаем высокое на пин 12
time.sleep(2)
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#-----------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#-----------------------------------------------------------------------
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = New_time = time.time()
#-----------------------------------------------------------------------
i=0 # Общий счетчик
error_counter = 0 # Счетчик ошибок
#-----------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#-----------------------------------------------------------------------
i+=1; ss = "% 5d" % (i)
"""Теперь довольно громоздкий блок в котором мы измеряем все доступные
текущие параметры процесса и формируем две строки. Одна (ss) краткая
и раскрашенная для вывода информации на консоль. Вторая (s)
"ненакрашенная" и (обычно) более подробная - для записи в журнал"""
#-----------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#-----------------------------------------------------------------------
while ReadSensors == False:
print "Считываю датчики"
Ts = sens.DS18B20.Ts() # Считаем датчики
if Ts.get(id) != None and Ts[id] != 0: # Соответствующий ключ (id) есть есть в словаре
ReadSensors = True
if Ts[id] == 85.:
ReadSensors = False
time.sleep(2)
print "Температура = %4.1f Возвращаюсь к считыванию датчиков." % (Ts[id])
continue
print "Датчики считаны"
else: # Увы...
print "Датчики отсутствуют или неисправны"
ReadSensors = False #
GPIO.output(12,0) # Отключаем 3.3V от DS18B20
print "Отключаю питание"
time.sleep(0.2)
GPIO.output(12,1) # Включаем 3.3V на DS18B20
print "Включаю питание"
error_counter += 1
time.sleep(2)
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol)
#-----------------------------------------------------------------------
ss += "% 5d" % (error_counter)
print ss # и выводим на экран
time.sleep(5)
ReadSensors = False
Так как после кратковременного отключения датчиков и последующего включения, показания восстанавливаются, пришла идея сделать так, чтобы при сбое датчика, автоматически отключалось и включалось питание. Для этого подключил питание датчиков к GPIO18 (pin 12).
Казалось бы, проблема разрешилась. Но при использовании этого блока в основной программе происходит следующее - после восстановления питания, не понятно от куда появляются нули. Четыре группы нулей - по количеству датчиков. И если датчики не подключать в течение более длительного времени, то и количество групп нулей возрастает кратно количеству сообщений о неисправности датчиков.
import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
import contrSTPR, sensWEIGHT
import RPi.GPIO as GPIO
ReadSensors = False
Tcol_list=[]
Tdef_list=[]
dWeight = 0
dWeight1 = 0
Column_stabilized = False
Tcol_max = False
Max_ekstremum = False
Temperature_grows = False
wght_new = 0
wght_correct = 0
Old_Weight = 0
Start_time = 0
Finish_time = 0
Sel_Speed = 0
dTime = 0
#--------------------------------------------------------------------------------
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#--------------------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20).
Подключаем питание датчиков на пин 12 (GPIO 18), определяем его как
пин вывода и подаем на него 1 (3.3V). """
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD) # Определяем пины по номерам
GPIO.setup(12, GPIO.OUT) # Пин 12 - вывод
GPIO.output(12,1) # Подаем высокое на пин 12
time.sleep(2)
"""Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#--------------------------------------------------------------------------------
"""С датчиками температуры разобрались. Теперь займемся датчиком
RMS (действующее напряжение сети)"""
vs = sens.RMS() # Создаем объект - датчик RMS
if vs != None: # Датчик в наличии и функционирует
V = vs.V
if V > 100: print "Действующее напряжение сети %d В" % (V)
else:
print "Слишком низкое напряжение сети. Завершение работы."
sys.exit(2)
else: pass # Ну на нет и суда нет. Можно работать и без датчика RMS
#--------------------------------------------------------------------------------
"""Датчик атмосферного давления - полезная вещь. Проверим его наличие
и работоспособность. Если его нет - не беда. Будем работать без него"""
ps = sens.BMP180() # Создаем объект - датчик атмосферного давления
if ps != None: # Датчик в наличии и функционирует
print "Атмосферное давление: \t%5.1f мм.рт.ст." % (ps.P)
print "Температура окружающей среды:\t%5.2f°C" % (ps.T)
#--------------------------------------------------------------------------------
"""Датчик веса."""
weight = sensWEIGHT.BALANCE()
if weight != None: #Датчик веса в наличии и функционирует
print "Вес: %5.1f грамм." % (weight.B)
else: None
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
"""Создаем объекты-контроллеры исполнительных устройств"""
#--------------------------------------------------------------------------------
teh = contr.TEH(vs) # Создадим объект "ТЭН"
if teh == None:
print "Контроллер ТЭНа отсутствует или неисправен. Завершение работы."
sys.exit(3)
#--------------------------------------------------------------------------------
#sd = contr.SD() # Создадим объект "устройство отбора"
"""В принципе можно работать и без клапана отбора. Например, с ручной
"пережимкой". Если ситуация именно такова, то закомментируйте следующие
три строчки"""
#if sd == None:
# print "Контроллер клапана отбора отсутствует или неисправен. Завершение работы."
# sys.exit(3)
#--------------------------------------------------------------------------------
Deflegmator=contrSTPR.STPR(addrSTPR=0x07)
if Deflegmator == None:
print "Контроллер Дефлегматора отсутствует или неисправен. Завершение работы."
sys.exit(4)
Holodilnik=contrSTPR.STPR(addrSTPR=0x08)
if Holodilnik == None:
print "Контроллер Холодильника отсутствует или неисправен. Завершение работы."
sys.exit(5)
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
"""Все. С датчиками и исполнительными устройствами мы разобрались.
Теперь переведем консоль в неблокирующий режим работы. Это нужно
для того, чтобы можно было бы в главном цикле приложения обрабатывать
нажатие клавиш клавиатуры. Необходимый для этого сервис организован
в виде класса TT, который находится в модуле kbh. При создании объекта
(экземпляра этого класса) как раз и происходит переход консоли
в неблокирующий режим. При уничтожении объекта (в деструкторе)
консоль возвращается к обычному режиму работы.
Параметр timeout задает время ожидания нажатия клавиши (он может быть
равен 0). В данном случае мы используем этот параметр для регулирования
длительности одного такта главного цикла приложения. При timeout = 3000
длительность такта составляет около 4 сек"""
timeout = 3910 # В мс. Должно быть 5 сек.
tt = kbh.TT(timeout)
"""Теперь сформируем карту режимов, доступных в данном приложении. Режимы
пронумерованы от 0 до 6. Карта режимов представляет собой список
именованных кортежей (т.е. к элементам кортежа можно обращаться
по имени). Это очень удобно. Имена элементов кортежа:
W - мощность нагрева ТЭНа, Вт (вещественное число)
stab - стабилизация мощности нагрева ТЭНа (True/False)
Q - скорость отбора, мл/час (вещественное число)
ststp - режим старт-стопа (True/Flase)"""
#-------------------------------------------------------------------------------
mrec = collections.namedtuple('mrec', 'W stab Q ststp')
modes = [] # Собственно список режимов
modes.append(mrec(0, False, 0, False)) # 0 - Только мониторинг
modes.append(mrec(2000, False, 0, False)) # 1 - Разгон
modes.append(mrec(650, True, 0, False)) # 2 - Стабилизация с выходом на отбор голов
modes.append(mrec(600, True, 40, False)) # 3 - Отбора голов
modes.append(mrec(600, True, 400, True)) # 4 - Отбора тела
modes.append(mrec(600, True, 400, False)) # 5 - Отбор хвостов
modes.append(mrec(2000, False, 1000, False)) # 6 - Пропарка колонны
#--------------------------------------------------------------------------------
mode = old_mode = 0 # Начинаем работать всегда с нулевого режима
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = New_time = time.time()
"""Теперь откроем файл журнала. Здесь возможны две ситуации. В первом
варианте мы продолжаем прерванный ранее процесс ректификации. В этом
случае нам удобно продолжить вести уже существующий файл журнала и
отсчет времени. Т.е. если файл журнала есть и он не слишком мал,
то мы так и поступим. Если же файла нет или он мал - то открываем
новый файл и вдем отсчет локального времени процесса с нуля."""
if os.path.exists("log") and os.path.getsize("log") > 127:
log = open("log", "r") # Нужно прочитать последнюю строку
log.seek(-127, 2) # Встанeм немного недоходя до конца файла
for line in open("log", "r"): # и считаем последнюю строку
last_line = line
prevStopTime = float(last_line.split()[1])
tst -= prevStopTime*60.0 # Локальное время будет продолжаться с конца
# предыдущей сессии
log.close()
log = open("log", "a") # А теперь откроем его уже для добавления
else: # В противном случае создаем новый файл журнала а нулевое
log = open("log", "w") # локальное время уже установлено выше
#--------------------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#--------------------------------------------------------------------------------
"""Сначала посмотрим на состояние клавиатуры"""
if tt.kbhit(): # Какая-то клавиша уже была нажата
ch = tt.getch() # Смотрим что было нажато....
if ch == 'q':
#GPIO.output(12,0) # Отключаем 3.3V
GPIO.cleanup()
break # Выходим из цикла - конец работы
elif ord(ch) >= 48 and ord(ch) <= 57: # Ввели номер режима
old_mode = mode; mode = int(ch)
#--------------------------------------------------------------------------------
"""Теперь довольно громоздкий блок в котором мы измеряем все доступные
текущие параметры процесса и формируем две строки. Одна (ss) краткая
и раскрашенная для вывода информации на консоль. Вторая (s)
"ненакрашенная" и (обычно) более подробная - для записи в журнал"""
#--------------------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0; dtrm = (now - rst)/60.0
ss = "% 7.2f % 7.2f\x1b[33m %d\x1b[0m" % (dtm, dtrm, mode)
"""Для журнала добавляем еще и глобальное время"""
s = time.strftime("%y.%m.%d.%H.%M.%S")
s += "% 7.2f % 7.2f %d" % (dtm, dtrm, mode)
"""Проверим и выведим информацию о продолжительности цикла.."""
Old_time = New_time
New_time = time.time()
Duration_of_cycle = New_time - Old_time
"""Выводим информацию о продолжительности цикла."""
ss += "% 2d" % (Duration_of_cycle)
#-----------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
while ReadSensors == False:
print "Считываю датчики"
Ts = sens.DS18B20.Ts() # Считаем датчики
if Ts.get(id) != None and Ts[id] != 0: # Соответствующий ключ (id) есть есть в словаре
ReadSensors = True
if Ts[id] == 85.:
ReadSensors = False
time.sleep(2)
print "Температура = %4.1f Возвращаюсь к считыванию датчиков." % (Ts[id])
continue
if Ts[id] == 0.:
ReadSensors = False
time.sleep(2)
print "Температура = %4.1f Возвращаюсь к считыванию датчиков." % (Ts[id])
continue
print "Датчики считаны"
else: # Увы...
print "Датчики отсутствуют или неисправны"
ReadSensors = False #
GPIO.output(12,0) # Отключаем 3.3V от DS18B20
print "Отключаю питание"
time.sleep(0.2)
GPIO.output(12,1) # Включаем 3.3V на DS18B20
print "Включаю питание"
#error_counter += 1
time.sleep(2)
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub); s += "% 7.3f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol); s += "% 7.3f" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef); s += "% 7.3f" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol); s += "% 7.3f" % (Thol)
#-----------------------------------------------------------------------
"""Измеряем и выводим текущую мощность нагрева"""
cW = teh.W
ss += "\x1b[31m %4d\x1b[0m" % (cW); s += " %5d" % (cW)
#-----------------------------------------------------------------------
"""Если есть датчик RMS, то в журнал выведем напряжение в сети"""
if vs != None:
V = vs.V; ss += " %3d" % (V); s += " %4d" % (V)
#-----------------------------------------------------------------------
"""Если есть датчик атмосферного давления - выводим давление"""
if ps != None:
P = ps.P; ss += "% 6.1f" % (P); s += "% 5.1f" % (P)
#-----------------------------------------------------------------------
"""Заполняем список и выводим информацию об изменении температуры в колонне"""
if len(Tcol_list) <= 4:
Tcol_list.append(Tcol)
# ss += "\x1b[32m% 6.2f\x1b[0m" % (0.)
else:
del Tcol_list[0]
Tcol_list.append(Tcol)
dTcol = Tcol_list[4] - Tcol_list[0]
# ss += "\x1b[32m% 6.2f\x1b[0m" % (dTcol)
#-----------------------------------------------------------------------
"""Заполняем список и выводим информацию об изменении температуры в дефлегматоре"""
if len(Tdef_list) <= 4:
Tdef_list.append(Tdef)
# ss += "\x1b[33m% 6.2f\x1b[0m" % (0.)
else:
del Tdef_list[0]
Tdef_list.append(Tdef)
dTdef = Tdef_list[4] - Tdef_list[3]
# ss += "\x1b[33m% 6.2f\x1b[0m" % (dTdef)
#-----------------------------------------------------------------------
"""Выводим информацию о положении кранов."""
ss += "% 4d" % (Deflegmator.N); s += "% 4d" % (Deflegmator.N)
ss += "% 4d" % (Holodilnik.N); s += "% 4d" % (Holodilnik.N)
#-----------------------------------------------------------------------
"""Выводим информацию с датчика веса."""
weight = sensWEIGHT.BALANCE()
if weight != None:
weight.B = 0 # Посылаем 0 чтобы считывать вес.
Nou_weight = weight.B # Получаем значение реального веса.
if Nou_weight == 0:
wght_new = 0.
#Nou_weight = 0.
wght_correct = 0.
else:
wght_old = wght_new
wght_new = weight.B
if wght_new < wght_old:
wght_correct += 200.
Nou_weight = wght_correct + wght_new
weight.B=1
Counter=weight.B/10. # Считывает значение счетчика капель
else: None
ss += "% 5d" % (Nou_weight); s += "% 5d" % (Nou_weight) # С Ардуинки принимаем целое число.
ss += "\x1b[32m %5.1f\x1b[0m" % (Counter); s += "% 5.1f" % (Counter)
#-----------------------------------------------------------------------
"""Выводим информацию о временном интервале, приросте веса и возможной скорости отбора."""
dWeight = Nou_weight - Old_Weight
if Old_Weight == 0: dWeight = 0
if dWeight > 0:
dWeight1 = dWeight
Finish_time = New_time
dTime = Finish_time - Start_time
if dTime > 1000: dTime = 0
Start_time = Finish_time
if dTime > 0:
Sel_Speed = dWeight/dTime*3600
ss += "\x1b[33m% 5.1f\x1b[0m" % (dTime)
ss += "% 5.1f" % (dWeight1)
ss += "% 4d" % (Sel_Speed)
Old_Weight = Nou_weight
#--------------------------------------------------------------------------------
"""Далее собственно и следует вся ненавязчивая автоматизация :)))
В данной задаче автоматическое переключение режимов нужно только
для стадии разгона. Т.е. в режиме разгона (режим 1) после закипания,
когда температура в 1/3 колонны превысит, скажем, 60°C, нужно
перейти в режим 2 (сбросить мощность на "штатный" уровень).
Ну так так и объясняем малинке."""
#--------------------------------------------------------------------------------
if mode == 1: # Текущий режим - разгон
if Tcol != 0: # Если датчики температуры исправны, то...
if Tcol >= 60: # Куб закипел - пора сбрасывать мощность
old__mode = mode; Deflegmator.N=130; Holodilnik.N=10; mode = 2
else: # Если датчик заглючил, то Tcol = 0. Завершаем работу.
print "Термодатчик неисправен. Завершение работы."
sys.exit(6)
#--------------------------------------------------------------------------------
if mode == 2: # Текущий режим - стабилизация с выходом на отбор голов
if Tdef != 0:
if Tdef_list[4] + 7 < Tcol_list[4]: # Регулируем кран дефлегматора только до заданной температуры.
if Column_stabilized == False: # Если колонна не стабилизирована
if Tcol_max == False and Tcol_list[2] > Tcol_list[4]: Tcol_max = True; print 'Максимум температуры колонны пройден.'
if Tcol_max == True and Tcol_list[2]-Tcol_list[4] < 0.1: Column_stabilized = True; print 'Начало стабилизации колонны.'
if Column_stabilized == True: # Началась стабилизация
if Temperature_grows == False and Tdef_list[4]>Tdef_list[2]>Tdef_list[0]: Temperature_grows = True
if Temperature_grows == True and Tdef_list[4] <= Tdef_list[2]:
Max_ekstremum = True; Temperature_grows = False;
if Tdef_list[4] < 50: oldDef = Deflegmator.N; Deflegmator.N = Deflegmator.N - 10
else: oldDef= Deflegmator.N; Deflegmator.N = Deflegmator.N - 7
if Deflegmator.N < 40: Deflegmator.N = oldDef
else: None # Если датчик температуры заглючил, то ничего не делаем.
#--------------------------------------------------------------------------------
""" if mode == 3: # Текущий режим - отбор голов.
if Tdef != 0:
# Написать инструкции анализа веса.
else: None # Если датчик температуры заглючил, то ничего не делаем.
"""
#--------------------------------------------------------------------------------
"""Теперь обработаем ситуацию, когда произошла смена режима работы
установки (автоматически, или по нажатию клавиши). Для обработки
используем карту режимов"""
if old_mode != mode:
"""Для режимов без стабилизации мощности (разгон, пропарка колонны и т.п.)
мощность устанавливается только один раз при смене режима"""
if not modes[mode].stab and mode != 0: teh.W = modes[mode].W
# sd.Q = modes[mode].Q # А вот для скорости отбора мы так делаем всегда
old_mode = mode
rst = now # Фиксируем момент начала нового режима
"""Для режимов со стабилизацией мощности (это написано в карте режимов),
мощность обновляем на каждом такте главного цикла приложения
(естественно, с учетом напряжения сети, если подключен датчик RMS)"""
if modes[mode].stab:
teh.W = modes[mode].W
# """Включаем счетчик циклов. И если step_number>steps_in_circle
# сбрасываем счетчик"""
# step_number=step_number+1
# if step_number>steps_in_circle:
# step_number=1
log.write(s + "\n"); log.flush() # Пишем данные в журнал
print ss # и выводим на экран
#-----------------------------------------------------------------------
ReadSensors = False
Прошу помочь разобраться в этом вопросе.
В связи с тем, что у меня часто выбивает термодатчики (подключены к raspberry Pi Zero), решил поизучать этот вопрос.
Сделал программу на основе nna_02.py
Скрытый текст
#coding:utf-8import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#-----------------------------------------------------------------------
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = time.time()
#-----------------------------------------------------------------------
i=0
#-----------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#-----------------------------------------------------------------------
i+=1; ss = "% 5d" % (i) # Счетчик циклов
#-----------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#-----------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
Ts = sens.DS18B20.Ts() # Сначала их измерим
for id in tids: # Теперь добавим в строки для выдачи
if id == cid: # Подкрасим температуру в колонне для консоли
ss += "\x1b[32m% 6.2f\x1b[0m" % (Ts[id])
else: ss += "% 6.2f" % (Ts[id])
#-----------------------------------------------------------------------
print ss # и выводим на экран
time.sleep(5)
Изменил программу, добавив команду на завершение работы программы в случае если датчик отвалился.
Скрытый текст
#coding:utf-8import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
#import contrSTPR, sensWEIGHT
#--------------------------------------------------------------------------------
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#--------------------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#--------------------------------------------------------------------------------
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = time.time()
#--------------------------------------------------------------------------------
i=0
#--------------------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#--------------------------------------------------------------------------------
i+=1; ss = "% 5d" % (i) # Счетчик циклов
#--------------------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#--------------------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
Ts = sens.DS18B20.Ts() # Сначала их измерим
flag = False
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol)
else:
ss += "\x1b[31m %6.2f\x1b[0m" % (0.) # А если такого датчика нет - ставим нули.
flag = True
if flag:
print "Завершение работы"
sys.exit(1)
#--------------------------------------------------------------------------------
print ss # и выводим на экран
time.sleep(5)
В следующей модификации программы, вместо команды завершения программы, дал команду на отображение нулей красным цветом.
Скрытый текст
#coding:utf-8import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
import contrSTPR, sensWEIGHT
#--------------------------------------------------------------------------------
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#--------------------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#--------------------------------------------------------------------------------
"""Параметр timeout задает время ожидания нажатия клавиши (он может быть
равен 0). В данном случае мы используем этот параметр для регулирования
длительности одного такта главного цикла приложения. При timeout = 3000
длительность такта составляет около 4 сек"""
#timeout = 3910 # В мс. Должно быть 5 сек.
#tt = kbh.TT(timeout)
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = New_time = time.time()
#--------------------------------------------------------------------------------
i=0
#--------------------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#--------------------------------------------------------------------------------
i+=1; ss = "% 5d" % (i) # Счетчик циклов
#--------------------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#--------------------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
Ts = sens.DS18B20.Ts() # Сначала их измерим
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol)
else: ss += "\x1b[31m %6.2f\x1b[0m" % (0.) # А если такого датчика нет - ставим нули.
#--------------------------------------------------------------------------------
time.sleep(5)
print ss # и выводим на экран
Новая модификация программы:
Скрытый текст
#coding:utf-8import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
import contrSTPR, sensWEIGHT
import RPi.GPIO as GPIO
ReadSensors = False
#-----------------------------------------------------------------------
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD) # Определяем пины по номерам
GPIO.setup(12, GPIO.OUT) # Пин 12 - вывод
GPIO.output(12,1) # Подаем высокое на пин 12
time.sleep(2)
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#-----------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20). Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#-----------------------------------------------------------------------
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = New_time = time.time()
#-----------------------------------------------------------------------
i=0 # Общий счетчик
error_counter = 0 # Счетчик ошибок
#-----------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#-----------------------------------------------------------------------
i+=1; ss = "% 5d" % (i)
"""Теперь довольно громоздкий блок в котором мы измеряем все доступные
текущие параметры процесса и формируем две строки. Одна (ss) краткая
и раскрашенная для вывода информации на консоль. Вторая (s)
"ненакрашенная" и (обычно) более подробная - для записи в журнал"""
#-----------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0
ss += "% 7.2f" % (dtm)
#-----------------------------------------------------------------------
while ReadSensors == False:
print "Считываю датчики"
Ts = sens.DS18B20.Ts() # Считаем датчики
if Ts.get(id) != None and Ts[id] != 0: # Соответствующий ключ (id) есть есть в словаре
ReadSensors = True
if Ts[id] == 85.:
ReadSensors = False
time.sleep(2)
print "Температура = %4.1f Возвращаюсь к считыванию датчиков." % (Ts[id])
continue
print "Датчики считаны"
else: # Увы...
print "Датчики отсутствуют или неисправны"
ReadSensors = False #
GPIO.output(12,0) # Отключаем 3.3V от DS18B20
print "Отключаю питание"
time.sleep(0.2)
GPIO.output(12,1) # Включаем 3.3V на DS18B20
print "Включаю питание"
error_counter += 1
time.sleep(2)
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol)
#-----------------------------------------------------------------------
ss += "% 5d" % (error_counter)
print ss # и выводим на экран
time.sleep(5)
ReadSensors = False
Казалось бы, проблема разрешилась. Но при использовании этого блока в основной программе происходит следующее - после восстановления питания, не понятно от куда появляются нули. Четыре группы нулей - по количеству датчиков. И если датчики не подключать в течение более длительного времени, то и количество групп нулей возрастает кратно количеству сообщений о неисправности датчиков.
Скрытый текст
#coding:utf-8import sys, os, time
import collections
"""Архив с модулями sens, contr и kbh находятся в приложении к
данному топику"""
import sens, contr, kbh
import contrSTPR, sensWEIGHT
import RPi.GPIO as GPIO
ReadSensors = False
Tcol_list=[]
Tdef_list=[]
dWeight = 0
dWeight1 = 0
Column_stabilized = False
Tcol_max = False
Max_ekstremum = False
Temperature_grows = False
wght_new = 0
wght_correct = 0
Old_Weight = 0
Start_time = 0
Finish_time = 0
Sel_Speed = 0
dTime = 0
#--------------------------------------------------------------------------------
"""Сначала создаем объекты, соответствующие датчикам и контроллерам.
Параллельно производится проверка их наличия и работоспособности.
#--------------------------------------------------------------------------------
Начнем с датчиков температуры (DS18B20).
Подключаем питание датчиков на пин 12 (GPIO 18), определяем его как
пин вывода и подаем на него 1 (3.3V). """
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD) # Определяем пины по номерам
GPIO.setup(12, GPIO.OUT) # Пин 12 - вывод
GPIO.output(12,1) # Подаем высокое на пин 12
time.sleep(2)
"""Идентификаторы датчиков,
установленных в системе известны. Определяем соответствующие
переменные"""
hid = 0x8000001ee27b # ID датчика температуры куба
cid = 0x8000001ef6e6 # ID датчика температуры колонны
did = 0x000006273720 # ID датчика температуры дефлегматора
wid = 0x8000000419af # ID датчика температуры выходящей воды
"""Создаем вспомогательный список tids, для удобства коллективной
работы со всеми датчиками"""
tids = (hid, cid, did, wid)
"""Статический метод Ts() класса DS18B20 возвращает словарь, содержащий
пары {идентификатор датчика : его температура} для всех датчиков,
подключенных к шине 1-Wire"""
Ts = sens.DS18B20.Ts()
"""Проверим, все ли датчики, с идентификаторами, перечисленными выше,
есть в этом словаре (т.е. висят на шине и исправны)"""
flag = False
for id in tids: # Пробегаем по списку нужных нам датчиков
if Ts.get(id) != None: # Соответствующий ключ (id) есть есть в словаре
print "0x%012x :% 7.3f°C" % (id, Ts[id]) # Доложим об этом...
else: # Увы...
print "Датчик с ID = 0x%012x отсутствует или неисправен" % (id)
flag = True # Выставляем флаг, что нужного датчика нет на шине
if flag:
print "Один или более датчиков DS18B20 отсутствуют или неисправны. Завершение работы."
sys.exit(1)
#--------------------------------------------------------------------------------
"""С датчиками температуры разобрались. Теперь займемся датчиком
RMS (действующее напряжение сети)"""
vs = sens.RMS() # Создаем объект - датчик RMS
if vs != None: # Датчик в наличии и функционирует
V = vs.V
if V > 100: print "Действующее напряжение сети %d В" % (V)
else:
print "Слишком низкое напряжение сети. Завершение работы."
sys.exit(2)
else: pass # Ну на нет и суда нет. Можно работать и без датчика RMS
#--------------------------------------------------------------------------------
"""Датчик атмосферного давления - полезная вещь. Проверим его наличие
и работоспособность. Если его нет - не беда. Будем работать без него"""
ps = sens.BMP180() # Создаем объект - датчик атмосферного давления
if ps != None: # Датчик в наличии и функционирует
print "Атмосферное давление: \t%5.1f мм.рт.ст." % (ps.P)
print "Температура окружающей среды:\t%5.2f°C" % (ps.T)
#--------------------------------------------------------------------------------
"""Датчик веса."""
weight = sensWEIGHT.BALANCE()
if weight != None: #Датчик веса в наличии и функционирует
print "Вес: %5.1f грамм." % (weight.B)
else: None
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
"""Создаем объекты-контроллеры исполнительных устройств"""
#--------------------------------------------------------------------------------
teh = contr.TEH(vs) # Создадим объект "ТЭН"
if teh == None:
print "Контроллер ТЭНа отсутствует или неисправен. Завершение работы."
sys.exit(3)
#--------------------------------------------------------------------------------
#sd = contr.SD() # Создадим объект "устройство отбора"
"""В принципе можно работать и без клапана отбора. Например, с ручной
"пережимкой". Если ситуация именно такова, то закомментируйте следующие
три строчки"""
#if sd == None:
# print "Контроллер клапана отбора отсутствует или неисправен. Завершение работы."
# sys.exit(3)
#--------------------------------------------------------------------------------
Deflegmator=contrSTPR.STPR(addrSTPR=0x07)
if Deflegmator == None:
print "Контроллер Дефлегматора отсутствует или неисправен. Завершение работы."
sys.exit(4)
Holodilnik=contrSTPR.STPR(addrSTPR=0x08)
if Holodilnik == None:
print "Контроллер Холодильника отсутствует или неисправен. Завершение работы."
sys.exit(5)
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
"""Все. С датчиками и исполнительными устройствами мы разобрались.
Теперь переведем консоль в неблокирующий режим работы. Это нужно
для того, чтобы можно было бы в главном цикле приложения обрабатывать
нажатие клавиш клавиатуры. Необходимый для этого сервис организован
в виде класса TT, который находится в модуле kbh. При создании объекта
(экземпляра этого класса) как раз и происходит переход консоли
в неблокирующий режим. При уничтожении объекта (в деструкторе)
консоль возвращается к обычному режиму работы.
Параметр timeout задает время ожидания нажатия клавиши (он может быть
равен 0). В данном случае мы используем этот параметр для регулирования
длительности одного такта главного цикла приложения. При timeout = 3000
длительность такта составляет около 4 сек"""
timeout = 3910 # В мс. Должно быть 5 сек.
tt = kbh.TT(timeout)
"""Теперь сформируем карту режимов, доступных в данном приложении. Режимы
пронумерованы от 0 до 6. Карта режимов представляет собой список
именованных кортежей (т.е. к элементам кортежа можно обращаться
по имени). Это очень удобно. Имена элементов кортежа:
W - мощность нагрева ТЭНа, Вт (вещественное число)
stab - стабилизация мощности нагрева ТЭНа (True/False)
Q - скорость отбора, мл/час (вещественное число)
ststp - режим старт-стопа (True/Flase)"""
#-------------------------------------------------------------------------------
mrec = collections.namedtuple('mrec', 'W stab Q ststp')
modes = [] # Собственно список режимов
modes.append(mrec(0, False, 0, False)) # 0 - Только мониторинг
modes.append(mrec(2000, False, 0, False)) # 1 - Разгон
modes.append(mrec(650, True, 0, False)) # 2 - Стабилизация с выходом на отбор голов
modes.append(mrec(600, True, 40, False)) # 3 - Отбора голов
modes.append(mrec(600, True, 400, True)) # 4 - Отбора тела
modes.append(mrec(600, True, 400, False)) # 5 - Отбор хвостов
modes.append(mrec(2000, False, 1000, False)) # 6 - Пропарка колонны
#--------------------------------------------------------------------------------
mode = old_mode = 0 # Начинаем работать всегда с нулевого режима
"""Это начало общего отсчета времени (относительное время программы)
и момент начала текущего режима работы"""
tst = rst = New_time = time.time()
"""Теперь откроем файл журнала. Здесь возможны две ситуации. В первом
варианте мы продолжаем прерванный ранее процесс ректификации. В этом
случае нам удобно продолжить вести уже существующий файл журнала и
отсчет времени. Т.е. если файл журнала есть и он не слишком мал,
то мы так и поступим. Если же файла нет или он мал - то открываем
новый файл и вдем отсчет локального времени процесса с нуля."""
if os.path.exists("log") and os.path.getsize("log") > 127:
log = open("log", "r") # Нужно прочитать последнюю строку
log.seek(-127, 2) # Встанeм немного недоходя до конца файла
for line in open("log", "r"): # и считаем последнюю строку
last_line = line
prevStopTime = float(last_line.split()[1])
tst -= prevStopTime*60.0 # Локальное время будет продолжаться с конца
# предыдущей сессии
log.close()
log = open("log", "a") # А теперь откроем его уже для добавления
else: # В противном случае создаем новый файл журнала а нулевое
log = open("log", "w") # локальное время уже установлено выше
#--------------------------------------------------------------------------------
"""Все. Все подготовительные операции закончены. Входим в главный
цикл приложения"""
while True:
#--------------------------------------------------------------------------------
"""Сначала посмотрим на состояние клавиатуры"""
if tt.kbhit(): # Какая-то клавиша уже была нажата
ch = tt.getch() # Смотрим что было нажато....
if ch == 'q':
#GPIO.output(12,0) # Отключаем 3.3V
GPIO.cleanup()
break # Выходим из цикла - конец работы
elif ord(ch) >= 48 and ord(ch) <= 57: # Ввели номер режима
old_mode = mode; mode = int(ch)
#--------------------------------------------------------------------------------
"""Теперь довольно громоздкий блок в котором мы измеряем все доступные
текущие параметры процесса и формируем две строки. Одна (ss) краткая
и раскрашенная для вывода информации на консоль. Вторая (s)
"ненакрашенная" и (обычно) более подробная - для записи в журнал"""
#--------------------------------------------------------------------------------
"""Сначала общая длительность процесса на данный момент и длительность
текущего режима"""
now = time.time(); dtm = (now - tst)/60.0; dtrm = (now - rst)/60.0
ss = "% 7.2f % 7.2f\x1b[33m %d\x1b[0m" % (dtm, dtrm, mode)
"""Для журнала добавляем еще и глобальное время"""
s = time.strftime("%y.%m.%d.%H.%M.%S")
s += "% 7.2f % 7.2f %d" % (dtm, dtrm, mode)
"""Проверим и выведим информацию о продолжительности цикла.."""
Old_time = New_time
New_time = time.time()
Duration_of_cycle = New_time - Old_time
"""Выводим информацию о продолжительности цикла."""
ss += "% 2d" % (Duration_of_cycle)
#-----------------------------------------------------------------------
"""Добавим для выдачи текущие значения температур с датчиков"""
while ReadSensors == False:
print "Считываю датчики"
Ts = sens.DS18B20.Ts() # Считаем датчики
if Ts.get(id) != None and Ts[id] != 0: # Соответствующий ключ (id) есть есть в словаре
ReadSensors = True
if Ts[id] == 85.:
ReadSensors = False
time.sleep(2)
print "Температура = %4.1f Возвращаюсь к считыванию датчиков." % (Ts[id])
continue
if Ts[id] == 0.:
ReadSensors = False
time.sleep(2)
print "Температура = %4.1f Возвращаюсь к считыванию датчиков." % (Ts[id])
continue
print "Датчики считаны"
else: # Увы...
print "Датчики отсутствуют или неисправны"
ReadSensors = False #
GPIO.output(12,0) # Отключаем 3.3V от DS18B20
print "Отключаю питание"
time.sleep(0.2)
GPIO.output(12,1) # Включаем 3.3V на DS18B20
print "Включаю питание"
#error_counter += 1
time.sleep(2)
for id in tids: # Теперь добавим в строки для выдачи
if id in Ts: # Если датчик с таким ID есть в словаре, то выведем его температуру
if id == hid: # Датчик в кубе Tcub
Tcub = Ts[id]
ss += "% 7.2f" % (Tcub); s += "% 7.3f" % (Tcub)
if id == cid: # Подкрасим температуру в колонне для консоли и определим переменную Tcol
Tcol = Ts[id]
ss += "\x1b[32m %7.2f\x1b[0m" % (Tcol); s += "% 7.3f" % (Tcol)
if id == did: # Подкрасим температуру в дефлегматоре для консоли и определим переменную Tdef
Tdef = Ts[id]
ss += "\x1b[33m %7.2f\x1b[0m" % (Tdef); s += "% 7.3f" % (Tdef)
if id == wid: # Датчик холодильника Thol
Thol = Ts[id]
ss += "% 7.2f" % (Thol); s += "% 7.3f" % (Thol)
#-----------------------------------------------------------------------
"""Измеряем и выводим текущую мощность нагрева"""
cW = teh.W
ss += "\x1b[31m %4d\x1b[0m" % (cW); s += " %5d" % (cW)
#-----------------------------------------------------------------------
"""Если есть датчик RMS, то в журнал выведем напряжение в сети"""
if vs != None:
V = vs.V; ss += " %3d" % (V); s += " %4d" % (V)
#-----------------------------------------------------------------------
"""Если есть датчик атмосферного давления - выводим давление"""
if ps != None:
P = ps.P; ss += "% 6.1f" % (P); s += "% 5.1f" % (P)
#-----------------------------------------------------------------------
"""Заполняем список и выводим информацию об изменении температуры в колонне"""
if len(Tcol_list) <= 4:
Tcol_list.append(Tcol)
# ss += "\x1b[32m% 6.2f\x1b[0m" % (0.)
else:
del Tcol_list[0]
Tcol_list.append(Tcol)
dTcol = Tcol_list[4] - Tcol_list[0]
# ss += "\x1b[32m% 6.2f\x1b[0m" % (dTcol)
#-----------------------------------------------------------------------
"""Заполняем список и выводим информацию об изменении температуры в дефлегматоре"""
if len(Tdef_list) <= 4:
Tdef_list.append(Tdef)
# ss += "\x1b[33m% 6.2f\x1b[0m" % (0.)
else:
del Tdef_list[0]
Tdef_list.append(Tdef)
dTdef = Tdef_list[4] - Tdef_list[3]
# ss += "\x1b[33m% 6.2f\x1b[0m" % (dTdef)
#-----------------------------------------------------------------------
"""Выводим информацию о положении кранов."""
ss += "% 4d" % (Deflegmator.N); s += "% 4d" % (Deflegmator.N)
ss += "% 4d" % (Holodilnik.N); s += "% 4d" % (Holodilnik.N)
#-----------------------------------------------------------------------
"""Выводим информацию с датчика веса."""
weight = sensWEIGHT.BALANCE()
if weight != None:
weight.B = 0 # Посылаем 0 чтобы считывать вес.
Nou_weight = weight.B # Получаем значение реального веса.
if Nou_weight == 0:
wght_new = 0.
#Nou_weight = 0.
wght_correct = 0.
else:
wght_old = wght_new
wght_new = weight.B
if wght_new < wght_old:
wght_correct += 200.
Nou_weight = wght_correct + wght_new
weight.B=1
Counter=weight.B/10. # Считывает значение счетчика капель
else: None
ss += "% 5d" % (Nou_weight); s += "% 5d" % (Nou_weight) # С Ардуинки принимаем целое число.
ss += "\x1b[32m %5.1f\x1b[0m" % (Counter); s += "% 5.1f" % (Counter)
#-----------------------------------------------------------------------
"""Выводим информацию о временном интервале, приросте веса и возможной скорости отбора."""
dWeight = Nou_weight - Old_Weight
if Old_Weight == 0: dWeight = 0
if dWeight > 0:
dWeight1 = dWeight
Finish_time = New_time
dTime = Finish_time - Start_time
if dTime > 1000: dTime = 0
Start_time = Finish_time
if dTime > 0:
Sel_Speed = dWeight/dTime*3600
ss += "\x1b[33m% 5.1f\x1b[0m" % (dTime)
ss += "% 5.1f" % (dWeight1)
ss += "% 4d" % (Sel_Speed)
Old_Weight = Nou_weight
#--------------------------------------------------------------------------------
"""Далее собственно и следует вся ненавязчивая автоматизация :)))
В данной задаче автоматическое переключение режимов нужно только
для стадии разгона. Т.е. в режиме разгона (режим 1) после закипания,
когда температура в 1/3 колонны превысит, скажем, 60°C, нужно
перейти в режим 2 (сбросить мощность на "штатный" уровень).
Ну так так и объясняем малинке."""
#--------------------------------------------------------------------------------
if mode == 1: # Текущий режим - разгон
if Tcol != 0: # Если датчики температуры исправны, то...
if Tcol >= 60: # Куб закипел - пора сбрасывать мощность
old__mode = mode; Deflegmator.N=130; Holodilnik.N=10; mode = 2
else: # Если датчик заглючил, то Tcol = 0. Завершаем работу.
print "Термодатчик неисправен. Завершение работы."
sys.exit(6)
#--------------------------------------------------------------------------------
if mode == 2: # Текущий режим - стабилизация с выходом на отбор голов
if Tdef != 0:
if Tdef_list[4] + 7 < Tcol_list[4]: # Регулируем кран дефлегматора только до заданной температуры.
if Column_stabilized == False: # Если колонна не стабилизирована
if Tcol_max == False and Tcol_list[2] > Tcol_list[4]: Tcol_max = True; print 'Максимум температуры колонны пройден.'
if Tcol_max == True and Tcol_list[2]-Tcol_list[4] < 0.1: Column_stabilized = True; print 'Начало стабилизации колонны.'
if Column_stabilized == True: # Началась стабилизация
if Temperature_grows == False and Tdef_list[4]>Tdef_list[2]>Tdef_list[0]: Temperature_grows = True
if Temperature_grows == True and Tdef_list[4] <= Tdef_list[2]:
Max_ekstremum = True; Temperature_grows = False;
if Tdef_list[4] < 50: oldDef = Deflegmator.N; Deflegmator.N = Deflegmator.N - 10
else: oldDef= Deflegmator.N; Deflegmator.N = Deflegmator.N - 7
if Deflegmator.N < 40: Deflegmator.N = oldDef
else: None # Если датчик температуры заглючил, то ничего не делаем.
#--------------------------------------------------------------------------------
""" if mode == 3: # Текущий режим - отбор голов.
if Tdef != 0:
# Написать инструкции анализа веса.
else: None # Если датчик температуры заглючил, то ничего не делаем.
"""
#--------------------------------------------------------------------------------
"""Теперь обработаем ситуацию, когда произошла смена режима работы
установки (автоматически, или по нажатию клавиши). Для обработки
используем карту режимов"""
if old_mode != mode:
"""Для режимов без стабилизации мощности (разгон, пропарка колонны и т.п.)
мощность устанавливается только один раз при смене режима"""
if not modes[mode].stab and mode != 0: teh.W = modes[mode].W
# sd.Q = modes[mode].Q # А вот для скорости отбора мы так делаем всегда
old_mode = mode
rst = now # Фиксируем момент начала нового режима
"""Для режимов со стабилизацией мощности (это написано в карте режимов),
мощность обновляем на каждом такте главного цикла приложения
(естественно, с учетом напряжения сети, если подключен датчик RMS)"""
if modes[mode].stab:
teh.W = modes[mode].W
# """Включаем счетчик циклов. И если step_number>steps_in_circle
# сбрасываем счетчик"""
# step_number=step_number+1
# if step_number>steps_in_circle:
# step_number=1
log.write(s + "\n"); log.flush() # Пишем данные в журнал
print ss # и выводим на экран
#-----------------------------------------------------------------------
ReadSensors = False
OldBean
Доцент
Красноярск
1K 1.4K
Отв.1146 13 Февр. 18, 06:29
2ZagAl Александр, положите пожалуйста текст модуля sens.py, который Вы используете в своих тестах. Их было несколько версий (в том числе с различными вариантами работы с потоками при запуске Ds-ок). Ну чтобы у нас была однозначность.
ZagAl
Доцент
Прибалтика
1.9K 916
Отв.1147 13 Февр. 18, 11:15
OldBean, да, конечно нужно было сразу об этом подумать. Вот sens.py которым я пользуюсь.
"""Модуль sens содержит классы-обертки для датчиков, подключенных
к шинам 1-Wire и I2C микрокомпьютера Raspberry Pi
История изменений - в конце файла
OldBean, 17.01.26"""
import os, time, thread
import smbus
import Adafruit_BMP.BMP085 as bmp
#-------------------------------------------------------------------------------
class DS18B20(object): # Класс датчика температуры DS18B20
""" Класс-обертка для датчиков DS18B20, подключенных к шине 1-Wire.
Температура каждого объекта класса DS18B20 представляется свойством T.
Цикл преобразования датчика запускается каждый раз, когда это
свойство используется в правой части выражения.
Класс DS18B20 также представляет средства для коллективной работы с
датчиками: список всех датчиков, подключенных к шине 1-Wire (стаический
метод IDs() и словарь, содержащий ключи - идентификаторы датчиков и
значения - температуры соответствующих датчиков (статический метод Ts())"""
path = "/sys/bus/w1/devices" # Директория с файлами датчиков
tsd = {} # Словарь для коллективной работы с датчиками {id датчика : температура}
def __new__(cls, id):
""" Перед созданием объекта В методе __new__ производится проверка
наличия датчика DS18B20 с заданным id"""
dn = cls.path + ("/28-%012x" % (id))
if os.path.isdir(dn):
return super(DS18B20, cls).__new__(cls)
else:
print "Датчик c id = 0x%012x отсутствует или неисправен" % (id)
return None
def __init__(self, id):
"""id - идентификатор датчика (число)"""
self._id = id
self._fn = DS18B20.path + ("/28-%012x/w1_slave" % (id))
@staticmethod
def temperature(fn, id = -1, lock = None):
""" Запускается цикл преобразования одного датчика DS18B20.
Если идентификатор датчика не установлен (по умолчанию),
то просто возвращается значение температуры.
Если же идентификатор датчика (параметр id) задан, то значение
температуры записывается в словарь tsd. Ключом является id датчика.
При таком режиме работы предполагается параллельная выполнение циклов
преобразований датчиков. Поэтому по окончанию преобразования
также освобождается и блокировка (параметр lock)."""
lines = ["NoNoNo", ""]
while not lines[0].strip().endswith("YES"): # Пока данные не будут готовы
f = open(fn, "r")
lines = f.readlines()
f.close()
pos = lines[1].find('t=') # Температура - после "t="
temp = -273.15 # :)
if pos != -1:
temp = float(lines[1][pos + 2:])/1000 # Температура в Цельсиях
if id < 0: return temp
DS18B20.tsd[id] = temp
lock.release()
@property
def T(self):
""" Свойство - температура датчика. Цикл преобразования
(около 750 мс) запускается при каждом использовании этого
свойства в правой части выражения."""
return DS18B20.temperature(self._fn)
@staticmethod
def IDs():
""" Возвращает список идентификаторов всех датчиков DS18B20,
подключенных к шине 1-Wire."""
fnl = os.listdir(DS18B20.path)
idl = []
for fn in fnl:
if fn.startswith("28-"): # Директория соответствует датчику DS18B20
idl.append(int(fn[-12:], 16))
return idl
@staticmethod
def Ts():
""" Возвращает словарь, содержащий идентификаторы всех датчиков
DS18B20, подключенных к шине 1-Wire (в качестве ключей словаря),
и температуры датчиков (соответствующие значения словаря). Обработка
каждого датчика производится параллельно в отдельном потоке, поэтому
суммарное время преобразования всех датчиков существенно меньше, чем
при последовательном опросе. Например для 4-х датчиков - 0.991 сек
вместо 3.349 сек."""
DS18B20.tsd.clear()
ids = []; fns = []; locks = []
dnl = os.listdir(DS18B20.path)
for dn in dnl:
if dn.startswith("28-"): # Директория соответствует датчику DS18B20
ids.append(int(dn[-12:], 16)) # Выделяем ID датчика и - в список
# Формируем полное имя файла с данными от датчика
fns.append(DS18B20.path + "/" + dn + "/w1_slave")
# Захватываем блокировки и заносим их в список блокировок
lock = thread.allocate_lock()
lock.acquire()
locks.append(lock)
nts = len(ids) # Количество датчиков DS18B20, подключенных к шине
# Запускаем параллельные потоки циклов преобразований датчиков
for i in range(nts):
thread.start_new_thread(DS18B20.temperature, (fns, ids, locks))
for i in range(nts): # Ждем завершения всех циклов преобразований датчиков
while locks.locked(): pass
return DS18B20.tsd
#-------------------------------------------------------------------------------
class BMP180(object):
""" Класс-обертка для датчика атмосферного давления и температуры BMP180.
Давления и температура представлены соответствущими свойствами (P и T)
экземпляра класса. Чтение датчиков происходит при каждом использовании
свойств в правой части выражения."""
sensor = None
def __new__(cls):
""" Перед созданием объекта В методе __new__ производится проверка
наличия и работоспособности датчика BMP180"""
try:
cls.sensor = bmp.BMP085()
cls.sensor.read_pressure()
cls.sensor.read_temperature()
return super(BMP180, cls).__new__(cls)
except:
print "Датчик BMP180 отсутствует или неисправен"
return None
def __init__(self):
self._sensor = BMP180.sensor
@property
def P(self):
"""Свойство - значение атмосферного давления в мм.рт.ст."""
return self._sensor.read_pressure()/133.322 # Паскали -> в мм.рт.ст.
@property
def T(self):
"""Свойство - значение температуры датчика в градусах Цельсия."""
return self._sensor.read_temperature()
#-------------------------------------------------------------------------------
class RMS(object):
""" Класс-обертка для датчика среднеквадратичного напряжения сети.
По умолчанию предполагается, что датчик подключен к 1-ой шине I2C
по адресу 5 (можно изменить при создании объекта)."""
def __new__(cls, addr = 0x05, bus = smbus.SMBus(1)):
"""Перед созданием объекта в методе __new__ производится
тестирование датчика (наличие и работоспособность).
addr - адрес датчика на шине I2C. По умолчанию - 5
bus - шина (объект SMBus). По умолчанию - SMBus(1)"""
try: # Проверим наличие и работоспособность датчика
bus.read_byte(addr)
# Все в порядке - создаем объект - датчик RMS
return super(RMS, cls).__new__(cls)
except:
print "Датчик RMS отсутствует или неисправен"
return None
def __init__(self, addr = 0x05, bus = smbus.SMBus(1)):
"""addr - адрес датчика на шине I2C. По умолчанию - 5
bus - шина (объект SMBus). По умолчанию - SMBus(1)"""
self._addr = addr
self._bus = bus
@property
def V(self):
"""Свойство - значение среднеквадратичного напряжения сети"""
return self._bus.read_byte(self._addr) + 100
#-------------------------------------------------------------------------------
if __name__ == "__main__": # Тестирование классов модуля sens
print "\nДатчики DS18B20"
tsIDs = DS18B20.IDs() # Список ID всех датчиков DS18B20 на шине 1 Wire
nts = len(tsIDs) # Количество датчиков DS18B20, обнаруженных на шине
if nts == 0:
print "Датчики DS18B20 не обнаружены"
else:
print "\nПоследовательный опрос %d датчиков" % (nts)
st = time.time()
for id in tsIDs:
ts = DS18B20(id) # Создаем объект (датчик DS18B20)
temperature = ts.T # Измеряем температуру этим датчиком
print "%5.3f сек" % (time.time() - st)
print "\nПараллельный запуск %d датчиков" % (nts)
st = time.time()
d = DS18B20.Ts() # Метод Ts() возвращает словарь с id датчиков (ключи) и
# температурой (значения)
for id in d.keys():
print "0x%012x :% 7.3f°C" % (id, d[id])
print "%5.3f сек" % (time.time() - st)
print "\nДатчик BMP180"
bmp = BMP180()
if bmp != None: # Датчик в наличии и функционирует
print "Давление: \t%5.1f мм.рт.ст." % (bmp.P)
print "Температура:\t%5.2f°C" % (bmp.T)
print "\nДатчик RMS"
vs = RMS()
if vs != None: # Датчик в наличии и функционируе
V = vs.V # Измеряем напряжение
if V > 100: print "Среднеквадратичное напряжение: %d V" % (V)
else: print "Слишком низкое напряжение в сети ( < 100B)"
print "\nТест на наличие датчика DS18B20 с id = 0x1888888 :)"
ts = DS18B20(0x1888888)
if ts != None: print "Есть такой датчик!!!"
#-------------------------------------------------------------------------------
"""История изменений
25.01.2017
----------
1. Написана документация модуля
2. Практически полностью переписан класс-обертка DS18B20 и расширен его
функционал - добавлена возможность выполнения цикла преобразования
каждого датчика в параллельных потоках
3. Перед созданием объектов-датчиков (RMS и BMP180) добавлено их тестирование
(наличие датчика и работоспособность интерфейса).
26.01.2017
----------
4. Перед созданием объект-датчика DS18B20 производится проверка его наличия
на шине 1-Wire
"""
Этот и остальные файлы из комплекта nna_02.
Скрытый текст
#coding:utf-8"""Модуль sens содержит классы-обертки для датчиков, подключенных
к шинам 1-Wire и I2C микрокомпьютера Raspberry Pi
История изменений - в конце файла
OldBean, 17.01.26"""
import os, time, thread
import smbus
import Adafruit_BMP.BMP085 as bmp
#-------------------------------------------------------------------------------
class DS18B20(object): # Класс датчика температуры DS18B20
""" Класс-обертка для датчиков DS18B20, подключенных к шине 1-Wire.
Температура каждого объекта класса DS18B20 представляется свойством T.
Цикл преобразования датчика запускается каждый раз, когда это
свойство используется в правой части выражения.
Класс DS18B20 также представляет средства для коллективной работы с
датчиками: список всех датчиков, подключенных к шине 1-Wire (стаический
метод IDs() и словарь, содержащий ключи - идентификаторы датчиков и
значения - температуры соответствующих датчиков (статический метод Ts())"""
path = "/sys/bus/w1/devices" # Директория с файлами датчиков
tsd = {} # Словарь для коллективной работы с датчиками {id датчика : температура}
def __new__(cls, id):
""" Перед созданием объекта В методе __new__ производится проверка
наличия датчика DS18B20 с заданным id"""
dn = cls.path + ("/28-%012x" % (id))
if os.path.isdir(dn):
return super(DS18B20, cls).__new__(cls)
else:
print "Датчик c id = 0x%012x отсутствует или неисправен" % (id)
return None
def __init__(self, id):
"""id - идентификатор датчика (число)"""
self._id = id
self._fn = DS18B20.path + ("/28-%012x/w1_slave" % (id))
@staticmethod
def temperature(fn, id = -1, lock = None):
""" Запускается цикл преобразования одного датчика DS18B20.
Если идентификатор датчика не установлен (по умолчанию),
то просто возвращается значение температуры.
Если же идентификатор датчика (параметр id) задан, то значение
температуры записывается в словарь tsd. Ключом является id датчика.
При таком режиме работы предполагается параллельная выполнение циклов
преобразований датчиков. Поэтому по окончанию преобразования
также освобождается и блокировка (параметр lock)."""
lines = ["NoNoNo", ""]
while not lines[0].strip().endswith("YES"): # Пока данные не будут готовы
f = open(fn, "r")
lines = f.readlines()
f.close()
pos = lines[1].find('t=') # Температура - после "t="
temp = -273.15 # :)
if pos != -1:
temp = float(lines[1][pos + 2:])/1000 # Температура в Цельсиях
if id < 0: return temp
DS18B20.tsd[id] = temp
lock.release()
@property
def T(self):
""" Свойство - температура датчика. Цикл преобразования
(около 750 мс) запускается при каждом использовании этого
свойства в правой части выражения."""
return DS18B20.temperature(self._fn)
@staticmethod
def IDs():
""" Возвращает список идентификаторов всех датчиков DS18B20,
подключенных к шине 1-Wire."""
fnl = os.listdir(DS18B20.path)
idl = []
for fn in fnl:
if fn.startswith("28-"): # Директория соответствует датчику DS18B20
idl.append(int(fn[-12:], 16))
return idl
@staticmethod
def Ts():
""" Возвращает словарь, содержащий идентификаторы всех датчиков
DS18B20, подключенных к шине 1-Wire (в качестве ключей словаря),
и температуры датчиков (соответствующие значения словаря). Обработка
каждого датчика производится параллельно в отдельном потоке, поэтому
суммарное время преобразования всех датчиков существенно меньше, чем
при последовательном опросе. Например для 4-х датчиков - 0.991 сек
вместо 3.349 сек."""
DS18B20.tsd.clear()
ids = []; fns = []; locks = []
dnl = os.listdir(DS18B20.path)
for dn in dnl:
if dn.startswith("28-"): # Директория соответствует датчику DS18B20
ids.append(int(dn[-12:], 16)) # Выделяем ID датчика и - в список
# Формируем полное имя файла с данными от датчика
fns.append(DS18B20.path + "/" + dn + "/w1_slave")
# Захватываем блокировки и заносим их в список блокировок
lock = thread.allocate_lock()
lock.acquire()
locks.append(lock)
nts = len(ids) # Количество датчиков DS18B20, подключенных к шине
# Запускаем параллельные потоки циклов преобразований датчиков
for i in range(nts):
thread.start_new_thread(DS18B20.temperature, (fns, ids, locks))
for i in range(nts): # Ждем завершения всех циклов преобразований датчиков
while locks.locked(): pass
return DS18B20.tsd
#-------------------------------------------------------------------------------
class BMP180(object):
""" Класс-обертка для датчика атмосферного давления и температуры BMP180.
Давления и температура представлены соответствущими свойствами (P и T)
экземпляра класса. Чтение датчиков происходит при каждом использовании
свойств в правой части выражения."""
sensor = None
def __new__(cls):
""" Перед созданием объекта В методе __new__ производится проверка
наличия и работоспособности датчика BMP180"""
try:
cls.sensor = bmp.BMP085()
cls.sensor.read_pressure()
cls.sensor.read_temperature()
return super(BMP180, cls).__new__(cls)
except:
print "Датчик BMP180 отсутствует или неисправен"
return None
def __init__(self):
self._sensor = BMP180.sensor
@property
def P(self):
"""Свойство - значение атмосферного давления в мм.рт.ст."""
return self._sensor.read_pressure()/133.322 # Паскали -> в мм.рт.ст.
@property
def T(self):
"""Свойство - значение температуры датчика в градусах Цельсия."""
return self._sensor.read_temperature()
#-------------------------------------------------------------------------------
class RMS(object):
""" Класс-обертка для датчика среднеквадратичного напряжения сети.
По умолчанию предполагается, что датчик подключен к 1-ой шине I2C
по адресу 5 (можно изменить при создании объекта)."""
def __new__(cls, addr = 0x05, bus = smbus.SMBus(1)):
"""Перед созданием объекта в методе __new__ производится
тестирование датчика (наличие и работоспособность).
addr - адрес датчика на шине I2C. По умолчанию - 5
bus - шина (объект SMBus). По умолчанию - SMBus(1)"""
try: # Проверим наличие и работоспособность датчика
bus.read_byte(addr)
# Все в порядке - создаем объект - датчик RMS
return super(RMS, cls).__new__(cls)
except:
print "Датчик RMS отсутствует или неисправен"
return None
def __init__(self, addr = 0x05, bus = smbus.SMBus(1)):
"""addr - адрес датчика на шине I2C. По умолчанию - 5
bus - шина (объект SMBus). По умолчанию - SMBus(1)"""
self._addr = addr
self._bus = bus
@property
def V(self):
"""Свойство - значение среднеквадратичного напряжения сети"""
return self._bus.read_byte(self._addr) + 100
#-------------------------------------------------------------------------------
if __name__ == "__main__": # Тестирование классов модуля sens
print "\nДатчики DS18B20"
tsIDs = DS18B20.IDs() # Список ID всех датчиков DS18B20 на шине 1 Wire
nts = len(tsIDs) # Количество датчиков DS18B20, обнаруженных на шине
if nts == 0:
print "Датчики DS18B20 не обнаружены"
else:
print "\nПоследовательный опрос %d датчиков" % (nts)
st = time.time()
for id in tsIDs:
ts = DS18B20(id) # Создаем объект (датчик DS18B20)
temperature = ts.T # Измеряем температуру этим датчиком
print "%5.3f сек" % (time.time() - st)
print "\nПараллельный запуск %d датчиков" % (nts)
st = time.time()
d = DS18B20.Ts() # Метод Ts() возвращает словарь с id датчиков (ключи) и
# температурой (значения)
for id in d.keys():
print "0x%012x :% 7.3f°C" % (id, d[id])
print "%5.3f сек" % (time.time() - st)
print "\nДатчик BMP180"
bmp = BMP180()
if bmp != None: # Датчик в наличии и функционирует
print "Давление: \t%5.1f мм.рт.ст." % (bmp.P)
print "Температура:\t%5.2f°C" % (bmp.T)
print "\nДатчик RMS"
vs = RMS()
if vs != None: # Датчик в наличии и функционируе
V = vs.V # Измеряем напряжение
if V > 100: print "Среднеквадратичное напряжение: %d V" % (V)
else: print "Слишком низкое напряжение в сети ( < 100B)"
print "\nТест на наличие датчика DS18B20 с id = 0x1888888 :)"
ts = DS18B20(0x1888888)
if ts != None: print "Есть такой датчик!!!"
#-------------------------------------------------------------------------------
"""История изменений
25.01.2017
----------
1. Написана документация модуля
2. Практически полностью переписан класс-обертка DS18B20 и расширен его
функционал - добавлена возможность выполнения цикла преобразования
каждого датчика в параллельных потоках
3. Перед созданием объектов-датчиков (RMS и BMP180) добавлено их тестирование
(наличие датчика и работоспособность интерфейса).
26.01.2017
----------
4. Перед созданием объект-датчика DS18B20 производится проверка его наличия
на шине 1-Wire
"""
OldBean
Доцент
Красноярск
1K 1.4K
Отв.1148 13 Февр. 18, 17:37
Спасибо, я понял какая у Вас версия. Но, похоже, у Вас проблемы с самими датчиками, а не со скриптами. Сами-то датчики система видит, но 3 из 4-х возвращают значение 85°C, которое присваивается при инициализации DS-ок. Это говорит о некорректной работе с датчиками. Наиболее вероятная причина - ошибки коммуникации малинки с этими тремя датчиками. Может быть помехи, а может - неисправности самих датчиков. Корректные значения иногда "прорываются".
Для фиксации проблемы проще воспользоваться средствами самой операционной системы для работы с датчиками, а не возиться со скриптами. В малинкиной директории /sys/bus/w1/devices/ должны быть четыре папки, названия которых совпадает с ID датчиков температуры (для DS-ок названия начинаются с "28-..."). Заходите в эти директории и ищите причину в файлах w1_slave. Это - тектовые файлы, в которых есть и диагностическая информация, и значения самих температур. Пока не добьетесь корректной работы датчиков (а именно - корректного содержимого файлов w1_slave) смысла возиться со скриптами нет. Так как методы класса-обертки DS18B20 (который описан в модуле sens) берут информацию как раз из этих файлов.
Смотрели? Что в этих файлах?
Для фиксации проблемы проще воспользоваться средствами самой операционной системы для работы с датчиками, а не возиться со скриптами. В малинкиной директории /sys/bus/w1/devices/ должны быть четыре папки, названия которых совпадает с ID датчиков температуры (для DS-ок названия начинаются с "28-..."). Заходите в эти директории и ищите причину в файлах w1_slave. Это - тектовые файлы, в которых есть и диагностическая информация, и значения самих температур. Пока не добьетесь корректной работы датчиков (а именно - корректного содержимого файлов w1_slave) смысла возиться со скриптами нет. Так как методы класса-обертки DS18B20 (который описан в модуле sens) берут информацию как раз из этих файлов.
Смотрели? Что в этих файлах?
ZagAl
Доцент
Прибалтика
1.9K 916
Отв.1149 13 Февр. 18, 22:38
OldBean, вот:
Или нужно запускать sens.py и если отображаются температуры 85.0 то тогда смотреть что в w1_slave?
На некоторое время отключил датчики и вновь подключил. Вот лог:
Что делать? Менять датчики?
Или нужно запускать sens.py и если отображаются температуры 85.0 то тогда смотреть что в w1_slave?
На некоторое время отключил датчики и вновь подключил. Вот лог:
Что делать? Менять датчики?
OldBean
Доцент
Красноярск
1K 1.4K
Отв.1150 14 Февр. 18, 03:05
Что делать? Менять датчики?ZagAl, 13 Февр. 18, 22:38Возможно, но я бы еще проверил. На всякий случай. Связь вроде нормальная, но, похоже, не запускается сам цикл преобразования. Если датчики без гильз, вытащите их и поставьте на питание (VCC-GND, подпаяйте прямо на ножки датчиков) керамические конденсаторы 0.1 мкФ. И потестируйте. Может быть им просто не хватает питания. Только запрашивайте не 1-2 раза, а много-много раз. Датчики должны работать безсбойно часами и сутками. Иначе никакая автоматизация толком работать не будет.
PS
Не покупайте дешевые датчики. "Левых" сейчас очень много. Не так давно взял (исключительно для пробы!) 4 недорогих датчика. Один всегда показывает 0, другой 127. Два других еще живы, но врут безбожно. Один показывает примерно градусов на 5 выше, второй - на 3. Вот так!
U-M
Магистр
MSK
210 39
Отв.1151 14 Февр. 18, 10:44
Не покупайте дешевые датчики. "Левых" сейчас очень много.OldBean, 14 Февр. 18, 03:05На этом фоне - нет мысли применить PT100 в связке с МАХ31865. Главный минус - каждому датчику свой шлейф и своя МАХ...
ZagAl
Доцент
Прибалтика
1.9K 916
Отв.1152 14 Февр. 18, 11:09, через 26 мин
Только запрашивайте не 1-2 раза, а много-много раз.OldBean, 14 Февр. 18, 03:05OldBean, Сергей, имеется ввиду цикл: включить, считать, выключить?
P.S. Всегда покупаю у продавцов с хорошим рейтингом, пусть даже подороже. В наличии имеются запасные. Поэтому для начала попробую сравнить их работоспособность. Но и ваш вариант тестирования тоже опробую.
m16
Модератор
Тамбов
1.9K 1K
Отв.1153 14 Февр. 18, 11:34, через 26 мин
На этом фоне - нет мысли применить PT100U-M, 14 Февр. 18, 10:44U-M, шестой год пользую менее сложную 8-ми канальную конфигурацию
OldBean
Доцент
Красноярск
1K 1.4K
Отв.1154 14 Февр. 18, 14:57
имеется ввиду цикл: включить, считать, выключить?ZagAl, 14 Февр. 18, 11:09Не обязательно. Любой из скриптов, которые Вы приводили чуть выше, где нет "костылей" (т.е. пересброса датчиков датчиков). Задача - добиться чтобы датчики работали без сбоев сколь угодно долго. Шина 1-Wire как у Вас устроена? Я имею в виду длину и топологию. Для начала сделайте все покороче и без ветвлений.
На этом фоне - нет мысли применить PT100 в связке с МАХ31865.U-M, 14 Февр. 18, 10:44У DS-ок хорошее соотношение цена/качество. Если использовать Брезенхема для регулировки мощности и нет серьезных помех тут же рядом (типа электросварки ;), то с ними вообще никаких проблем нет. И быть не должно. Надо просто разобраться в источнике проблем у коллеги ZagAl. А те дешевенькие я взял специально из любопытства. Посмотреть как они работают. Ну посмотрел... ;)
ZagAl
Доцент
Прибалтика
1.9K 916
Отв.1155 14 Февр. 18, 16:04
Любой из скриптов, которые Вы приводили чуть выше, где нет "костылей"OldBean, 14 Февр. 18, 14:57Сергей, так там и не было "костылей". Сбои я моделировал, отключая датчики вручную. На неработающей колонне, датчики работают без сбоев. Проверял. Почти сутки. Длина проводов 3 метра. Ну сейчас еще запущу четвертый вариант, тот, что сбои считает.
А вот на работающей колонне когда как. То выбивает датчики и довольно часто, то нет. В настоящее время экспериментирую на малых загрузках. Только для того чтобы посмотреть как колонна выходит на покапельный режим отбора голов и отбор голов с контролем веса и счетчика капель. Поэтому колонна в работе всего 2-3 часа.
P.S. Может какие электромагнитные наводки возникают от ТЭНа? Хотя куб заземлен. Может заземление плохое?
makh
Профессор
Sаmara
2.1K 1.1K
Отв.1156 14 Февр. 18, 16:29, через 26 мин
ZagAl, если где-то в схеме устройства, или рядом, фигурирует один или несколько неизвестного происхождения импульсных блоков питания, попробуй менять по одному, и смотреть на реакцию железа. У мну такое было -- собираешь установку, все как обычно вроде, но откисает вся гирлянда градусников каждые пару минут. Методом исключения нашол китайский БП, который это делал. Пара одинаковых была, один на электронику и насосы, второй на воздушный деф, так вот когда глючный кормил вентиляторы проблемы не было, а когда электронику -- непонятной природы горе..
ZagAl
Доцент
Прибалтика
1.9K 916
Отв.1157 14 Февр. 18, 17:30
makh, я пользуюсь блоком питания от настольного компьютера. С него беру и 5 вольт и 12 (для шаговых двигателей).
PavelSaratov
Доктор наук
Саратов
622 80
Отв.1158 14 Февр. 18, 17:59, через 30 мин
А те дешевенькие я взял специально из любопытства. Посмотреть как они работают. Ну посмотрел...Возникает вопрос - а где недешевенькие берете?
сообщение удалено
OldBean
Доцент
Красноярск
1K 1.4K
Отв.1159 14 Февр. 18, 19:21
так там и не было "костылей". Сбои я моделировал, отключая датчики вручную.ZagAl, 14 Февр. 18, 16:04А... А я-то думал, что Вы автоматизировали перезагрузку датчиков (тексты смотрел только у первых скриптов, но по скриншотам стало ясно, что проблема в датчиках, а не в скриптах).
На неработающей колонне, датчики работают без сбоев. Проверял. Почти сутки. ... А вот на работающей колонне когда как. То выбивает датчики и довольно часто, то нет.ZagAl, 14 Февр. 18, 16:04Тогда, с большой вероятностью, что наводки, а источник помех явно связан с установкой. Нужно искать. Про метод исключения коллега makh уже рассказал ;) Это действенный метод.
Кстати, отличная у Вас ложечка получилась! А я для аналогичной задачи (измерение расхода) хотел 100-грамовые тензовесы приспособить и сосуд с сифоном для периодического слива.
Возникает вопрос - а где недешевенькие берете?PavelSaratov, 14 Февр. 18, 17:59В том же магазине, что и дешевые. Только цена в два (с небольшим гаком) раза поболее. Они работают нормально и, кстати, очень хорошо коррелируют с датчиками из совсем старой партии, которую я брал еще лет 10 назад