Единственно чего ей не хватает, так это аналоговых входов (аналого-цифровые преобразователи отсутствуют).C-Bell, 13 Янв. 17, 16:31
И стоит Raspberry дешевле, даже если в него еще ардуину втыкнуть для наличия АЦП.makh, 16 Февр. 15, 23:47
makh, может поможет с решением.
C-Bell
Научный сотрудник
Улан-Удэ
1.8K 1.3K
Отв.121 13 Янв. 17, 17:07, через 6 мин
не, ПыХиПи не будет, будет сплошной python, я уже писал.
makh
Профессор
Sаmara
2.1K 1K
Отв.122 13 Янв. 17, 17:33, через 26 мин
Так че тут помогать-то. Есть в малине USB-порты, можно туда втыкнуть ардуинку и пообщаться с ней через серийный порт. Можно без ардуинки, более продвинутый АЦП на I2C или SPI интерфейс повесить. По конкретике смотреть надо -- что актуальней и проще для поставленной задачи в имеющихся условиях.
Судя по всему, малинковый драйвер посылает в градусник команду convert (0x44), ждет 700+ мс, потом читает измеренное, и так с каждым градусником. Долго. Ардуинку можно было бы по-быстрому попросить послать convert всем градусникам, а через 700+ мс так же скопом считать показания. Существенно быстрее, особенно если градусников десяток-другой.
сплошной pythonC-Bell, 13 Янв. 17, 16:07
Попытка стандартизировать обмен с ардуиной, если склероз не врет, называлась FirmATA; обязательно должон быть и для малины какой-то высокоуровневый API, с высочайшей вероятнойстью питоновый в т.ч.
capsolo
Профессор
Зелик
5.3K 1.6K
Отв.123 13 Янв. 17, 18:25, через 53 мин
C-Bell, Вот неплохая отправная точка для RasPI и прочих http://webiopi.trouch.com/ Сейчас ковыряю, однако получается на удивление быстро.
ys1797
Доцент
Санкт-Петербург
1K 339
Отв.124 13 Янв. 17, 19:37
Попытка стандартизировать обмен с ардуиной, если склероз не врет, называлась FirmATA; обязательно должон быть и для малины какой-то высокоуровневый API, с высочайшей вероятнойстью питоновый в т.ч.makh, 13 Янв. 17, 17:33
Для малины API - это gcc Там же полноценный линукс стоит. Даже гуй какой-никакой, да есть. Самое приятное это то, что можно писать на всем что угодно, хоть перл, хоть питон, хоть php. Да и на обычном Си никто не мешает написать что-нибудь.
Кстати, есть плата расширения для малинки с UNO на борту, которую можно использовать как АЦП/ЦАП. Правда тактовая частота снижена до 12 Mhz в силу питания в 3.3 вольта.
makh
Профессор
Sаmara
2.1K 1K
Отв.125 13 Янв. 17, 20:10, через 34 мин
можно писать на всем что угодноys1797, 13 Янв. 17, 19:37
Да, это сильная сторона железок с ОС, #!/bin/sh и понеслась. Пока не уперлось в риалтаймовую задачу. Тот же фазовый регулятор, например, категорически не хотелось бы писать для линупса, разбираясь со сборкой RT-ядра и прочая.
Добавлено через 35мин.:
На мой вкус, в "ненавязчивой автоматизации" описан (по-настоящему хорошо описан, не каждому судьба уметь так доходчиво выражаться) кошерный, массовый, экономически и трудозатратно целесообразный концепт -- однозадачные риалтайм исполнительные модули + мозги на базе железки с ОС. Как-то так и надо, гибко, с возможностью быстрой конфигурации под любую хотелку.
ys1797
Доцент
Санкт-Петербург
1K 339
Отв.126 13 Янв. 17, 22:50
Тот же фазовый регулятор, например, категорически не хотелось бы писать для линупса, разбираясь со сборкой RT-ядра и прочая.makh, 13 Янв. 17, 20:10
Я уже написал. high resolution timer вполне себе неплохо работает. И 100 прерываний в секунду - это не очень реалтайм. Вот с E1 потоком - там да все плотно. Надо будет тему оформить...
C-Bell
Научный сотрудник
Улан-Удэ
1.8K 1.3K
Отв.127 25 Янв. 17, 11:53
Подключение термометров DS18B20 к Raspberry PI 3 Model B
Хочу выразить свою глубокую признательность Виталию HBB Он буквально растолкал меня вернуться к данной теме, чуть не силком заставил убрать дорогой 1-wire/USB адаптер DS9490R и перейти на использование одноплатного компьютера Raspberry PI 3 Model B. Виталий и прислал мне этот Raspberry PI.
pcDuino, который уже четыре года исправно трудится, управляя самогонным аппаратом, показал себя с самой лучшей стороны. Увы, везде есть недостатки. pcDuino использует в качестве жесткого диска бортовую nand память (типа флэшки). Похоже, постоянное сохранение данных от термометров в огромном количестве ведут к деградации этой памяти. При очередном запуске перегона выяснилось отсутствие на диске пакета программ для перегона. Мало того, попытки запустить какие-то утилиты с правами суперпользователя также были безуспешны. Надо отдать должное линуксу, пользователей удалось восстановить несложным шаманством, пакет программ дистилляции восстановил с резерва. Так что pcDuino продолжает свою трудовую деятельность. И самое главное при почти равных характеристиках Raspberry PI 3 заметно дешевле pcDuino. Чего не хватает Raspberry PI 3, так это портов с аналого-цифровыми преобразователями.
Первоначальная настройка Raspberry PI - это отдельная тема, в этом посте только о том, как подключить цифровые термометры DS18B20 к Raspberry PI 3 Model B и как минимизировать время их опроса.
Для работы с шиной 1-wire нужно настроить конфигурацию Raspberry PI. Запускаем LXTerminal и набираем команду
sudo raspi-config
В появившемся меню конфигурации выбираем пункт 7 Advanced Options
Выбираем AA 1-Wire
Нажимаем Да и Ok, затем соглашаемся на перезагрузку. Таким образом при каждой загрузке Raspberry PI будут загружаться модули w1-gpio и w1-therm, обеспечивающие интерфейс с шиной 1-wire через GPIO и работу с цифровыми термометрами.
Подключение цифровых термометров DS18B20 к GPIO Raspberry PI осуществляется нехитрой схемой, дополнительно потребуется только один резистор на 4,7 kOm
Модули w1-gpio и w1-therm формируют отображение состава шины 1-wire в файловой системе '/sys/bus/w1/devices/'. В таком каталоге, при наличии на шине 1-wire цифровых термометров, будут папки вида 28-000000a88ca5. Имя этой папки совпадает с ID соответствующего термометра. В папке термометра находится файл с именем 'w1_slave', в этом файле можно обнаружить температуру в тысячных долях градусов Цельсия.
Несложная программа последовательного опроса цифровых термометров: Последовательный опрос цифровых термометров
#Функция чтения значения температуры с указанного термометра def read_temp_raw(device_file): '''Читает значение температуры с указанного термометра и возвращает его. device_file - папка (с полным путем), в которой находятся данные термометра ''' f = open(device_file, 'r') lines = f.readlines() f.close() equals_pos = lines[1].find('t=') temp_string = lines[1][equals_pos+2:] temp_c = float(temp_string) / 1000.0 return (temp_c)
#Возвращает кортеж из списка кортежей названий термометров с температурами #и времени измерения def Measure(): DS18B20list=[] while True: time_b=time.time() for device in device_folders: device_file = device + '/w1_slave' DS18B20list.append((os.path.basename(device), read_temp_raw(device_file))) return (DS18B20list, (time.time()-time_b))
def main(): while True: (DS18B20list, tMeasure)=Measure() for DS18B20 in DS18B20list: print(u"%s\t%3.1f градC" % DS18B20) print(u'Время измерения=%ssec' % tMeasure) print('')
if __name__ == '__main__': main()
После запуска программа будет циклично опрашивать термометры и выводить из показания. Дополнительно измеряется продолжительность опроса.
Как видно, продолжительность опроса пяти термометров никак не ниже 4 секунд. Это связано с тем что команду на измерение температуры модуль w1-therm выдает каждому термометру индивидуально. Процесс измерения одного термометра занимает примерно 0,75 сек и еще нужно время на передачу данных о свежеизмеренной температуре.
Строить управление с такой "оперативностью" не очень здоровая идея. Домашний дистиллятор, точнее его колонна, обладает малой инерционностью. За 4 секунды контролируемая температура может измениться значительно, что приведет к изменению распределения фракций по высоте колонны. Соответственно, на выходе можно получить вовсе не то, чего ожидали. Да и расход охлаждающей воды увеличится, что неизбежно увеличит затраты электроэнергии и времени перегона. К примеру, в моей колонне объем дефлегматора сменяется за 1 секунду, значит, за четыре секунды уйдёт четыре объема.
Система команд шины 1-wire позволяет запустить температурное преобразование одновременно на всех цифровых термометрах, и потом просто читать значения измеренных температур. Это позволило бы значительно сократить время опроса термометров. К сожалению, такая возможность в модуле w1-therm пока не реализована. Тем не менее, выход имеется - это запуск процедур чтения каждого из термометров в параллельных потоках. Первый проверил эту идею Сергей OldBean в своей теме Ненавязчивая автоматизация ректификационной установки. Он это сделал через с помощью скрипта bash. Я, соответственно, стал изучать параллелизм python, чтобы на нем реализовать параллельный запуск процессов температурного преобразования на каждом из термометров. Выяснилось, что параллелизм в питоне достигается многими средствами, первое средство распараллеливания процессов, с помощью которого удалось реализовать идею параллельного чтения температуры был питоновский модуль multiprocessing.dummy.
Ниже приведён соответствующий скрипт опроса термометров в параллельных процессах: Опрос термометров в параллельных процессах
#!/usr/bin/env python #coding=utf8 """ $Id: DS18B20mp.py, 2017/01/21 Copyright (c) 2017 C-Bell (VAGor). Чтение значений температур с цифровых термометров DS18B20 по шине 1-wire, подключенной к GPIO4 одноплатного компьютера Raspberry PI
Условия: - к GPIO4 подключена шина 1-wire с резистором 4,7 kOm, второй вывод резистора подключен к выводу 3,3V - в конфигураторе Raspberry PI должна быть включена шина 1-wire (установлены и запущены модули w1-gpio и w1-therm)
Использование: import DS18B20 (DS18B20list, tMeasure)=DS18B20.Measure() где DS18B20list - список кортежей (ID термометра, значение температуры) tMeasure - момент фиксации показаний термометров
Особенности: используется модуль multiprocessing.dummy для "одновременного" запуска измерения температыры всеми цифровыми термометрами DS18B20 что в большинстве случаев сокращает до минимума время опроса термометров """
import os #Модуль функций для работы с операционной системой import sys #Модуль доступа к некоторым системным переменным и функциям import glob #находит все пути, совпадающие с заданным шаблоном import time #Модуль для работы со временем from multiprocessing.dummy import Pool as ThreadPool
#Класс исключения отсутствия наличия шины 1-wire class NoOneWireError(Exception): pass
#Класс исключения при отсутствии цифровых термометров на шине 1-wire class NoDS18B20Error(Exception): pass
#Проверка наличия шины 1-wire if not os.path.isdir('/sys/bus/w1'): #Генерить исключение. raise NoOneWireError('No 1-wire bus') print("Включите поддержку 1-Wire в конфигурации Raspberry!") exit()
#Каталог, отражающий устройства на шине 1-wire base_dir = '/sys/bus/w1/devices/'
#Читает значение температуры с указанного термометра и возвращает его def read_temp_raw(device_folder): '''read_temp_raw читает значение температуры с указанного термометра и возвращает кортеж (ID термометра, температура в градусах цельсия)'''
#полное имя файла, из которого читается температура device_file = device_folder + '/w1_slave'
# создать объект-файл f = open(device_file, 'r')
#прочитать строки из файла lines = f.readlines()
#закрыть файл f.close()
#найти сочетание символов t= equals_pos = lines[1].find('t=')
#вычленить температуру из строки temp_string = lines[1][equals_pos+2:]
#преобразовать в число temp_c = float(temp_string) / 1000.0
#вернуть прочитанные данные return (os.path.basename(device_folder), temp_c)
#Возвращает кортеж из списка кортежей названий термометров #с температурами и временем измерения def Measure(): '''Функция Measure() ищет все цифровые термометры DS18B20 на шине 1-wire читает значения измеренных ими температур и возвращает в виде кортежа (список кортежей (ID термометра, температура), момент времени измерения)''' device_folders = glob.glob(base_dir + '28*')
#Если папки DS18B20 не обнаружены, сформировать исключение if len(device_folders)==0: raise NoDS18B20Error('Digital thermometers DS18B20 not found')
#задать количество процессов равным количеству DS18B20 pool = ThreadPool(len(device_folders))
#запустить параллельное измерение и получение температуры DS18B20list=pool.map(read_temp_raw, device_folders)
#закрыть мультипроцессинг pool.close()
#присоединить к основному потоку, чтобы он ждал завершение измерения pool.join() return (DS18B20list, time.time()) #выдать результаты измерения
def main(): '''Тестовая функция отображает результаты измерения подсчитывает среднее время измерения и отображает максимальное время измерения.''' t=0 #общее время измерения tMax=0 #максимальная продолжительность измерения for i in xrange(1, sys.maxsize): timeBegin=time.time() (DS18B20list, tMeasure)=Measure() os.system('clear') for DS18B20 in DS18B20list: print(u"%s\t%3.1f градC" % DS18B20) print(u'Время измерения=%ssec' % (tMeasure-timeBegin)) t+=(tMeasure-timeBegin) print(u'Среднее время измерения=%ssec' % (t/i)) if (tMax<(tMeasure-timeBegin)): tMax=(tMeasure-timeBegin) print(u'(mp)Максимальная продолжительность измерения=%ssec' % tMax) print('')
if __name__ == '__main__': main()
Результат работы скрипта:
Результат довольно впечатляющий, средняя продолжительность измерения температур около 1,2 секунды Хотя отдельные вызовы могут по прежнему достигать более чем 4 секунды, уже можно говорить о более-менее оперативном управлении. Как оказалось, эти достижения можно ещё немного улучшить, использовав другой модуль параллелизма питона, но об этом в следующем посте.
Ардуина с 328-й атмегой дешевле, однако. Без паяльника )
C-Bell
Научный сотрудник
Улан-Удэ
1.8K 1.3K
Отв.130 26 Янв. 17, 16:31, через 11 мин
Многопоточное измерение температуры в Rspberry PI
Продолжаем совершенствовать температурные измерения. Новый модуль измерения температур цифровыми термометрами DS18B20 использует пакет threading для параллельного запуска процессов измерения температуры. Снимок экрана модуля, отработавшего более 12 часов:
Можно заметить, что среднее время измерения немного ниже, чем в модуле, использующем многопроцессорный запуск. Правда, код нового модуля несколько покучерявее будет: Опрос термометров в параллельных потоках
#!/usr/bin/env python #coding=utf8 """ $Id: DS18B20mt.py, 2017/01/23 Copyright (c) 2017 C-Bell (VAGor). Чтение значений температур с цифровых термометров DS18B20 по шине 1-wire, подключенной к GPIO4 одноплатного компьютера Raspberry PI
Условия: - к GPIO4 подключена шина 1-wire с резистором 4,7 kOm, второй вывод резистора подключен к выводу 3,3V - в конфигураторе Raspberry PI должна быть включена шина 1-wire (установлены и запущены модули w1-gpio и w1-therm)
Использование: import DS18B20 (DS18B20list, tMeasure)=DS18B20.Measure() где DS18B20list - список кортежей (ID термометра, значение температуры) tMeasure - момент фиксации показаний термометров
Особенности: используется модуль multiprocessing.dummy для "одновременного" запуска измерения температыры всеми цифровыми термометрами DS18B20 что в большинстве случаев сокращает до минимума время опроса термометров """
import os #Модуль функций для работы с операционной системой import sys #Модуль доступа к некоторым системным переменным и функциям import glob #находит все пути, совпадающие с заданным шаблоном import time #Модуль для работы со временем import threading #Модуль для работы с потоками
#Класс исключения отсутствия наличия шины 1-wire class NoOneWireError(Exception): pass
#Класс исключения при отсутствии цифровых термометров на шине 1-wire class NoDS18B20Error(Exception): pass
#Проверка наличия шины 1-wire if not os.path.isdir('/sys/bus/w1'): #Генерить исключение. raise NoOneWireError('No 1-wire bus') print("Включите поддержку 1-Wire в конфигурации Raspberry!") exit()
#Каталог, отражающий устройства на шине 1-wire base_dir = '/sys/bus/w1/devices/'
#Читает и возвращает значение температуры с указанного термометра def read_temp_raw(device_folder): '''Читает и возвращает текущее значение температуры''' device_file = device_folder + '/w1_slave' f = open(device_file, 'r') lines = f.readlines() f.close() equals_pos = lines[1].find('t=') temp_string = lines[1][equals_pos+2:] temp_c = float(temp_string) / 1000.0 return (os.path.basename(device_folder), temp_c)
class T(threading.Thread): '''Класс для получения температуры от одного цифрового термометра''' def __init__(self, device_folder): '''Инициализация класса''' threading.Thread.__init__(self) self._device_folder = device_folder self._T = None def run(self): '''Функция, вызываемая при старте потока''' self._T = read_temp_raw(self._device_folder) @property def T(self): """Возвращает текущее значение температуры""" return self._T
#Возвращает кортеж из списка кортежей названий термометров с температурами #и временем измерения def Measure(): '''Функция Measure() ищет все цифровые термометры DS18B20 на шине 1-wire читает значения измеренных ими температур и возвращает в виде кортежа (список кортежей (ID термометра, температура), момент времени измерения)''' device_folders = glob.glob(base_dir + '28*') #Если термометры DS18B20 на шине не найдены, генерировать исключение if len(device_folders)==0: #Генерить исключение. raise NoDS18B20Error('DS18B20 not found on 1-wire bus')
#Список объектов-потоков Threads=[]
#Список термометров DS18B20list=[]
#Создание объектов-потоков для каждого термометра for device_folder in device_folders: Threads.append(T(device_folder))
#Запуск всех потоков for eashT in Threads: eashT.start()
#Присоединение потоков к текущему, чтобы ожидать завершение измерения for eashT in Threads: eashT.join()
#Сбор значений температур термометров for eashT in Threads: DS18B20list.append(eashT.T)
#Выдача результатов return (DS18B20list, time.time())
def main(): t=0 tMax=0 for i in xrange(1, sys.maxsize): timeBegin=time.time() (DS18B20list, tMeasure)=Measure() os.system('clear') for DS18B20 in DS18B20list: print(u"%s\t%3.1f градC" % DS18B20) print(u'Время измерения=%ssec' % (tMeasure-timeBegin)) t+=(tMeasure-timeBegin) print(u'Среднее время измерения=%ssec' % (t/i)) if (tMax<(tMeasure-timeBegin)): tMax=(tMeasure-timeBegin) print(u'(mt)Максимальная продолжительность измерения=%ssec' % tMax) print('')
Он буквально растолкал меня вернуться к данной теме, чуть не силком заставил убрать дорогой 1-wire/USB адаптер DS9490R и перейти на использование одноплатного компьютера Raspberry PI 3 Model B.
Очень рад, что Владимир продолжил тему. Да, пытки - это моё
Только вот как быть с этими мордами? При копипасте эти гады пропадают. Я однажды с этим попал. Может админу написать?
woddy
Доцент
Новосиб
1.3K 489
Отв.137 27 Янв. 17, 22:45, через 10 мин
прикладывать нужные файлы в виде аттачей, еще лучше архивами. А в тексте поста тоже надо, но для быстрого ознакомления.
m16Модератор
Тамбов
1.9K 1K
Отв.138 28 Янв. 17, 00:11
но работаетwoddy, 27 Янв. 17, 21:33
кто бы сомневался, мега с внешним клоком на 54мгц работает. НО, производитель не гарантирует нормальную работу камня в режимах отличных от рекомендуемых. woddy, ты ради интереса посмотри на фузы ардуины, китайские товарищи там свинью подложили.
C-Bell
Научный сотрудник
Улан-Удэ
1.8K 1.3K
Отв.139 28 Янв. 17, 09:11
прикладывать нужные файлы в виде аттачей, еще лучше архивами.woddy, 27 Янв. 17, 22:45
Архивы приложены.
Только вот как быть с этими мордами? При копипасте эти гады пропадают. Я однажды с этим попал. Может админу написать?HBB, 27 Янв. 17, 22:35