Сбор показаний датчиков и их отображение



    Людям нравятся красивые презентации. Красивые картинки, немного текста, меняющиеся слайды. Красивая картинка позволяет быстро передать информацию человеку, сообщить самое важное. Мы все это знаем. Я вот думаю, как «скрестить ежа и ужа»?

    Как наглядно на мониторе компьютера представить процессы, происходящие внутри микроконтроллера или ПЛИС? Или как показать, что происходит внутри всей системы автоматики, реализованной на микроконтроллере или ПЛИС?

    Вообще-то правильный ответ я знаю – нужно использовать SCADA системы.
    SCADA – это supervisory control and data acquisition, диспетчерское управление и сбор данных. Но мы не ищем легких путей, мы хотим немножко изобрести своего велосипеда.

    Хочу поделиться своим простым методом отображения данных, получаемых от датчиков и сенсоров из платы управления.

    Тут, прежде всего, нужно разделить три компоненты:
    • протокол передачи данных. Нужно как-то кодировать передаваемую от контроллера к компьютеру информацию.
    • firmware в системе автоматики, в микроконтроллере или ПЛИС. Этот модуль должен собарать показания датчиков и передавать их на компьютер для отображения в «красивом виде»
    • программное обеспечение визуализации. Показывает состояние и значения датчиков. Может строит какие-то графики.


    Вот так, по порядку попробую рассказать.

    Протокол передачи данных.


    В настоящее время физических возможностей подключить какое-то устройство к компьютеру или ноутбуку фактически осталось только две: сетевое подключение через Ethernet/WiFi или USB. Практически ушли в прошлое «настоящие» параллельные и последовательные порты. С ними было просто. Конечно их еще можно найти, если поискать. Но лучше в эту сторону и не думать.

    Ethernet пока отставляю в сторону. Для передачи по сети нужно в контроллере иметь драйвера стека TCP/IP, как правило это тянет за собой наличие ОС, обычно Linux или ucLinux. Потом потребуется интерфейс настройки сети: а какой IP адрес? А статический или динамический? А какая маска и gateway? В общем не очень просто в реализации и настройке.

    USB кажется гораздо проще, хотя и тут много подводных камней: а какой класс/субкласс устройства? А нужно ли ему драйвера или используются стандартные драйвера той же Windows?
    И опять возвращаемся «на круги своя» — проще всего использовать последовательный порт через USB. В простейшем случае есть шнуры типа USB2Serial. Ну или как отличный вариант для разработчика плат и контроллеров – различные микросхемы FTDI.

    ОК, все же выбираем последовательный порт через USB. А раз так, то значит пересылка данных может быть в виде последовательности символов. Значит дальше еще проще: показания датчиков можно передавать в виде строк вида «НАЗВАНИЕ_ДАТЧИКА=ЗНАЧЕНИЕ»

    При таком подходе мы сможем легко увеличивать количество опрашиваемых сенсоров, и легко менять их тип. Состояние концевика или геркона будет передваться, например, в виде строк «but0=1» или «but1=0». Значение температуры можно передавать в виде строки «t0=36,6». Строки проще всего разделять символами «перевода каретки»: 0x0D 0x0A.

    Так, на первых порах даже и программа визуализации на компьютере не нужна. Можно просто запустить программу терминала вроде Putty и смотреть на показания датчиков из контроллера.

    Контроллер.


    Мой контроллер выполнен на базе ПЛИС Altera Cyclone III. На самом деле это известная разработчикам плата Марсоход2. Я уже писал про некоторые проекты, выполненные на ней. Например, когда-то мы сделали на этой плате на чистой ПЛИС FM радио передатчик. А еще мы сделали на ней USB Tracker. Есть и другие проекты.

    Вот такая плата:



    На плате уже есть 2 кнопочки – это первые два датчика для моих экспериментов.
    Еще я подключил микросхему термометра ds18b20 – это второй датчик.
    Можно еще использовать АЦП платы для измерения чего-то-пока-не-знаю-чего. Пока здесь просто переменный резистор вместо датчика.

    Важно, что на плате уже стоит микросхема FTDI FT2232HL, которая обеспечивает связь с компьютером через USB в виде виртуального последовательного порта. Скорость передачи аж 12Мбит/сек. Это условно 1,2 Мбайта/сек. Если, например, плата опрашивает датчики каждые 100 миллисекунд, то получается можно за каждый опрос передавать компьютеру более 100Кбайт данных. Вполне прилично.

    Сейчас не буду рассказывать о проекте для платы и ПЛИС Cyclone III. Для этого есть отдельная статья. В этой статье подробно рассказано, как опрашиваются данные и передаются результаты в компьютер через последовательный порт. Лучше перейдем к рассмотрению 3-ей компоненты – программы визуализации значений датчиков, которая работает на компьютере.

    Программа визуализации данных.


    Тут хотелось все сделать быстро и просто. На чем писать программу, чтоб было просто написать, менять, дополнять?

    Я выбираю Питон, хотя честно говоря опыта нет. Просто кажется, что это будет хорошо. Как сказал один из хабражителей (извините, не помню кто) – дополнительно хотелось бы «потреннировать своего питона».

    Итак, поскольку программа будет графическая, то попробую встроенный в питон Tkinter. Для работы с последовательным портом буду использовать pyserial.

    Хочется написать эдакий набор классов — для каждого типа датчиков свой класс.

    Самый простой класс – двоичный датчик. Это может быть кнопка, концевик, геркон. Его значения 0 или 1. Соответствующий этому датчику питоновский класс BinSensor отображает всего 2 состояния. Предлагаю каждому состоянию нарисовать свое изображение. Изображение прикрепляется к фиксированным координатам окна программы поверх фонового изображения.



    Как только пришло значение «0» показываем первую картинку. Если пришло значение «1», то показываем вторую картинку. Изображения могут быть любыми — все зависит от нашей фантазии.

    Вот этот класс:
    #!/usr/bin/env python
    
    import Tkinter
    from Tkinter import *
    
    root = Tk()
    
    class BinSensor:
      def __init__(self,name,img0,img1,x,y):
        self.name=name
        self.x=x
        self.y=y
        self.img0=PhotoImage(file=img0)
        self.img1=PhotoImage(file=img1)
        self.val=0
        self.label_img=Label(root,image=self.img0)
        self.label_img.place(x=self.x,y=self.y)
      def set(self,state):
        if(self.val==state): return
        self.val=state
        if( int(state)==0 ):
          self.label_img.configure(image=self.img0)
        else:
          self.label_img.configure(image=self.img1)
    

    В функцию __init__, которая вызывается при создании экземпляра класса, передаются параметры:
    Name – название датчика
    Img0 и img1 – имена файлов картинок, используемых для отображения состояния датчика.
    X и y – координаты окна, где будет отображаться датчик.

    При создании объекта датчика сразу создается Label с картинкой и размещается в окне Tkinter.

    Функция set принимает параметр строку – это новое состояние датчика «0» или «1». В зависимости от нового значения картинка внутри Label переконфигурируется, меняется на другую. В общем это и все.

    Аналогичным образом реализуется второй класс vBarSensor.
    class vBarSensor:
      def __init__(self,name,scale,min,max,x,y,w,h):
        self.name=name
        self.scale=scale
        self.x=x
        self.y=y
        self.h=h
        self.val=min
        self.min=min
        self.max=max
        self.delta=max-min
        h1=self.h*(self.val-self.min)/self.delta
        h0=self.h-h1
        self.canv0 = Canvas(root, width = w, height = h0, bg = "lightblue", bd=1, relief='ridge')
        self.canv1 = Canvas(root, width = w, height = h1, bg = "red", bd=1, relief='ridge')
        self.barLabel = Label(root, text = "0")
        self.canv0.place(x=self.x,y=self.y)
        self.canv1.place(x=self.x,y=self.y+h0)
        self.barLabel.place(x=self.x,y=self.y+h+5)
      def set(self,newval):
        #newval is signed hex string like "83A5"
        val=int(newval,16)
        if(val>0x7fff): val=-val
        val=val/self.scale
        if(self.val==val): return
        self.val=val
        h1=self.h*(self.val-self.min)/self.delta
        h0=self.h-h1
        self.barLabel.configure(text=str(self.val))
        self.canv0.configure(height = h0)
        self.canv1.configure(height = h1)
        self.canv1.place(y=self.y+h0)
    

    Этот класс графически представляет датчик типа термометра. Значения из датчика могут меняться в некотором диапазоне. Так же при создании экземпляра этого класса нужно указать имя датчика. Кроме этого у термометра есть возможное минимальное и максимальное значение, и еще указываем координаты столбика в окне визуализации, ширину и высоту столбика.

    Столбик термометра как бы состоит из двух частей нижняя красная и верхняя светлая.
    Можно было бы создать один Tkinter canvas и на нем нарисовать эти столбики, но почему-то я сделал не так. Сделал два canvas разного цвета и в функции set() меняю им вертикальный размер. В принципе это не важно. Работает. Кстати, если хочется видеть именно изображение термометра в окне визуализации, то его можно нарисовать на фоновом изображении окна, а поверх него разместить экземпляр vBarSensor.



    Наверное будет симпатично.

    Написал еще один класс GridDisplay для отображения показаний датчика и изменении их во времени. Его исходный код приводить здесь не буду, чтобы не перегружать статью излишними подробностями. Кому будет нужно скачает с сайта весь проект, вместе с исходниками для ПЛИС для Altera Quartus II.

    А вот главную программу alls.py пожалуй покажу. Здесь не очень много всего:
    #!/usr/bin/env python
    
    import sensor
    from sensor import *
    
    import serial
    from serial import *
    
    class AllSensors:
      def __init__(self):
        #open serial port
        self.s=serial.Serial("COM27",115200,timeout=10)
        #load background image
        self.bgnd=PhotoImage(file="bgnd.gif")
        self.label_bgnd=Label(root,image=self.bgnd)
        self.label_bgnd.place(x=0,y=0)
        #add all sensors and indicators
        self.all=[]
        self.all.append( BinSensor("b0","f0.gif","f1.gif",32,32) )
        self.all.append( BinSensor("b1","f0.gif","f1.gif",32,128) )
        self.all.append( vBarSensor("a0",1,0,255,128,32,32,160) ) 
        self.all.append( GridDisplay("t0",16,-55,125,10,16,180,32,256,160) ) 
      def set(self,name,val):
        for sens in self.all:
          if(sens.name==name):
            sens.set(val)
            return
      def setline(self,line):
        p=line.split("=")
        if(len(p)==2):
          self.set( p[0], p[1] )
      def run(self):
        while(1):
          line=self.s.readline()
          line=line.rstrip()
          #print(line)
          self.setline(line)
          root.update()
    
    a=AllSensors()
    a.run()
    

    В этой программе открываю последовательный порт для чтения. Загружаю фоновое изображение в окно. Создаю список всех имеющихся датчиков. Далее читаю строки з порта, разбираю их и по имени датчика передаю соответствующему экземпляру классов новое значение.

    Запустить программу из Python легко: «import alls», где alls — это имя главной программы файл alls.py. Вот так сейчас выглядит моя программа:



    Вот видео, которое показывает, как все это работает (только не пугайтесь, я там фен включаю для нагрева датчика температуры, так что звук лучше прикрутить):



    Теперь, когда «скелет» приложения работает, то можно приступать к детальному рисованию плана помещения и установленных в нем датчиков.
    Поделиться публикацией

    Комментарии 16

      +1
      «В настоящее время физических возможностей подключить какое-то устройство к компьютеру или ноутбуку фактически осталось только две: сетевое подключение через Ethernet/WiFi или USB.»


      В домашних условиях, либо очень ограниченных финансов — да, пожалуй. В промышленных же есть и продолжают жить Profibus, Can bus и иже с ними, (хотя сейчас наблюдаю тенденцию по переводу всего и вся на IE). Есть платы I/O чтобы сигналы в ПК напрямую завести. Видеокамеры могут на Camera Link висеть. Под особо специфические устройства разрабатывются свои PCI платы. Да и устройств с RS232 по-прежнему используется довольно много. В общем физических возможностей подключить какое-то устройство к компьютеру на самом деле — море.
        0
        (хотя сейчас наблюдаю тенденцию по переводу всего и вся на IE

        что вы имеете ввиду?
          0
          Я имею ввиду, что многие заказчики явно просят использовать Industrial Ethernet — вместо Profibus ставят Profinet, Modbus-RTU заменяют на Modbus-TCP, и так далее. Была пара заказов, когда уже установленное и проработавшее лет десять оборудование обновлялось в соответствии с общей идеологией предприятия. Ну и количество модулей и устройств с IE неуклонно растёт.
            0
            Ну Profibus/Profinet как и RIO сеть — это полевая шина и для подключения к компьютеру она не используется (используется для обмена данными между контроллером и модулями ввода-вывода). А для обмена данными компьютера с контроллером обычно используется Ethernet. А что там по верх ethernet`а, modbus или какой-то проприетарный протокол, зависит от производителя.
              0
              Ну не совсем так (впрочем это сильно зависит от сложившихся предпочтений отдела автоматизации). Мы долгое время ставили в ПК PCI карты Siemens СP5613 или 5614 — это как раз profibus, на компьютере крутился OPC сервер — ну и через него в SCADA вводились все данные. Были даже системы, в которых вообще обходились без ПЛК, поскольку его роль на себя брала SCADA — на Profibus висел только ПК да модули ввода вывода типа ET200. Теперь да — ставим ethernet, как вы написали и все контроллеры на IE висят.
          0
          интересно, а кому еще нужны PCI устройства? Раньше да, мы и сами их разрабатывали, а сейчас как-то все больше люди USB девайсы хотят… или я не прав?
            0
            Зависит от многих факторов — мне видится две области, где такое используется — промышленность да фундаментальные исследования типа CERN. И собственных примеров — есть плоскопанельный рентгеновский детектор, у которого интерфейс — оптоволокно — вот под него разработана своя PCI карта, и всё это продаётся комплектом. Либо — отдельно стоящий информационный киоск в цеху со своим ПК и кнопками (ну типа банкомата что ли) — чем городить там ПЛК — берётся PCI карта ввода вывода типа NI PCI-6518 и дело с концом. Плюс область автоматизации промышленности довольно инертна (особенно если речь идёт о кртичных к сбоям участках) — новомодные решения внедряются очень неспеша. Мы до сих пор очень много систем ставим с WinXP, и только-только начали переходить на Win7.
              0
              а есть ли у Вас реальная потребность в каких-то новых платах которых в природе пока нет? Или уже «давно все придумано», нужно брать готовые платы известных производителей?
              Просто хотелось бы понять есть ли здесь место для отечественных разработчиков…
                0
                Место есть. Зачастую все упирается в цену.
                С другой стороны, чтобы использовать плату в определенных отраслях промышленности необходима сертификация. А сертифицировать оборудование у нас не самый быстрый и дешевый процесс.
                  0
                  Нет, явной потребности честно говоря нет (но у нас есть свои внутренние возможности). Да и в промышленности стремятся использовать «проверенные» решения — так что собирается из готового. Впрочем у нас обычная автоматизация — роботы, конвейеры — тут готовых решений пруд пруди.
                0
                USB ненадежен
              0
              По поводу визуализации — было бы здорово, если бы визуализация была бы через web.
                +1
                Все бы ничего, но USB именно как шина, а при наличии нескольких датчиков топология point-to-point (ethernet тоже, в общем) проигрывает любой шине, крайне неудобно и в какой-то момент становится дорого. Нетривиально обеспечить расширяемость, например.

                Таким образом, возвращаемся к старым шинам, а USB остается лишь для совместимости с новым железом.

                Ну а раз мы все равно используем то, что используется уже несколько десятилетий, звучит не особенно разумным выдумывание своего протокола, когда есть проверенные «в бою» индустриальные протоколы, тот же Modbus. Который, помимо всего прочего, поддерживается как бы не всеми известными SCADA-системами и тонной контроллеров.
                • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    Опасная фраза, в зависимости от контекста даже неверная. Тут есть опасность сказать что-то типа «теплое синее мягкого». Похожее обычно разворачивается в дискуссиях, что лучше — WiFi или Bluetooth. Это разные вещи для разных областей применения. В то время как USB и Bluetooth — сиречь PAN, Ethernet и WiFi — уже уровень LAN, со всеми вытекающими.
                    • НЛО прилетело и опубликовало эту надпись здесь

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое