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

Итак, ранней весной 2014 года я поднялся на третий этаж бетоносмесительного узла одного завода. В моём распоряжении были два планетарных бетоносмесителя фирмы Wiggert, линия адресной подачи Kubat на два монорельса и полностью разбомбленный цех внизу, в который надо было выдавать бетон. В перспективе.

В чём заключался хитрый план? Мы должны были с нуля наладить производство пустотного настила в одном пролёте цеха и стеновых панелей — в другом.

Вот так выглядит пустотный настил в разрезе:

image
Фото с сайта echo.co.za

Итак, для опробования бетоносмесителя нужно куда-то девать удачно (или не очень) произведённый бетон. Вариант с десятью джамшутами не рассматривался, поэтому нужно подключать адресную подачу (АП). Механическая часть АП включает в себя пару специально обученных шаттлов (кюбелей), катающихся по монорельсу, и бетонораздатчик, управляющийся в полуавтоматическом режиме:



Начинаем вкуривать документацию на Kubat: электрическая часть состоит из центрального шкафа управления на 314-2DP, двух станций ET200S (шаттлы) и CPU 313-2DP IFM (раздатчик), общающихся по Powercom (аналог сименсовского PowerRail, т.е. RS-485 по троллеям 220/380В).



Упс, а вот и первые грабли: исходников ПО нет и не предвидится. Ладно, вскрываем пароли контроллеров специальной утилитой. С раздатчиком всё более-менее нормально, а вот центральный рэк декомпилируется в ядрёную кашу на STL, т.к. большая часть программы написана на SFC непонятно какой версии.

Ладно, не вопрос. Для начала отправляю монтажников прокидывать коммуникации вдоль монорельсов, подключать питание и ставить датчики, сам в это время смотрю схему:



Итак, инвертор фирмы Nord, управляемый по Profibus. В нашем случае используется для питания приводов движения и вращения. Скачиваем документацию, раскуриваем регистры управления и пишем код:

FUNCTION_BLOCK nord_control

VAR_INPUT
    cmd:INT;    //0 - fast stop
                //1 - smooth stop
                //2 - run to setpoint
                //3 - get info;
    setpoint:REAL;
    hw_addr:INT;    
END_VAR

VAR_OUTPUT
    state:TNordInfo;
END_VAR

VAR_TEMP
    // Temporary Variables
    d: ARRAY [0..5] OF WORD;
    setpoint1:REAL;

END_VAR

VAR
    t:INT;
    c: WORD;
    s: WORD; 
    cw AT c: TNord_CW;
    sw AT s: TNOrd_SW;
    st:WORD;       
END_VAR

    s:=IW[hw_addr]; //256 257 state word *
    state.sw:=sw;
    state.act_value1:=INT_TO_REAL(WORD_TO_INT(IW[hw_addr+2]))*50/16384;//258 259
    state.act_value2:=INT_TO_REAL(WORD_TO_INT(IW[hw_addr+4]))*50/16384;//260 261
    state.act_value3:=INT_TO_REAL(WORD_TO_INT(IW[hw_addr+6]))*50/16384;//262 263 
    state.w0:=IW[hw_addr+8];//264 265
    state.w1:=IW[hw_addr+10];//266 267

    // Statement Section
    CASE cmd OF
    0:  c:=0;
        cw.ack_err:=TRUE;   //SWITCH OFF;
        cw.enable_op:=FALSE;
        cw.on1:=FALSE;        
        cw.on2:=FALSE;
        cw.on3:=FALSE;
        cw.enable_op:=FALSE;            
        cw.enable_ramp:=FALSE;
        cw.unfreeze_ramp:=FALSE;
        cw.en_setpoint:=FALSE;            
        cw.pzd_valid:=FALSE;
        setpoint1:=0;
        t:=0;
        
    1:  cw.on1:=FALSE;
            
    2:  setpoint1:=setpoint;
        CASE t OF //run to setpoint
        0:  IF (sw.start_disabled=TRUE) THEN //wait for mains voltage
                t:=1;
            END_IF;
        1:  cw.on2:=TRUE;  //switch to standby
            cw.on3:=TRUE;
            cw.enable_op:=TRUE;            
            cw.enable_ramp:=TRUE;
            cw.unfreeze_ramp:=TRUE;
            cw.en_setpoint:=TRUE;            
            cw.pzd_valid:=TRUE;
            cw.ack_err:=FALSE;        
            IF (sw.ready=TRUE) AND //Wait for standby
               (sw.no_off2=TRUE) AND
               (sw.no_off2=TRUE) THEN //change to no_off3
                t:=2;
            END_IF;          
        2:  cw.on1:=TRUE;
            t:=3;
        END_CASE;        
    END_CASE;
    
    IF cmd<3 THEN   //Write data
        QW[hw_addr]:=c;
        st:=INT_TO_WORD(REAL_TO_INT((setpoint1*16384.0/50.0)));
        QW[hw_addr+2]:=INT_TO_WORD(REAL_TO_INT((setpoint1*16384.0/50.0)));       
    END_IF;
END_FUNCTION_BLOCK

О, кажется шаттл поехал, но, вроде бы, снизу слышны какие-то радостные крики. С матерными воплями монтажники пытаются убежать по подкрановым путям от мчащейся пятитонной железки. Аварийно выключаем питание и делаем перерыв на подсчёт личного состава.
Уже было бы неплохо иметь хоть какую-то визуализацию. ОК, делаем небольшой проектик для тач-панели.



В течении пары недель допиливаю остальную часть программы (тут должна быть картинка про сову), что бы можно было развозить бетон… которого ещё нет.

Тем временем внизу заканчивается бетонирование термостендов и можно расконсервировать линию Echo. Тут всё просто. Или почти просто. Машины простояли под дождём и голубиными фекалиями с 2008 года, вагонетка и слип-формер после заправки маслом и очистки начинают работать нормально, а вот пила накидывает полный экран ошибок и говорит, что никуда не поедет.



Добрые товарищи из дойчланда горят желание помочь, но исключительно за несколько десятков тысяч евро. Рубли не принимают.
Хорошо, скачиваем программу из контроллера, пытаемся понять что ей надо. Всё выглядит так, как будто две оси позиционирования заклинило. В принципе, это не удивительно: силовые модули в двух инверторах выгорели полностью. Хорошо, заказываем новые Emerson Unidrive и, чтобы не терять время, возвращаемся на БСУ для секаса с планетарными бетоносмесителями.

Один Wiggert уже смонтирован, подключён и вроде бы даже опробован. Однако, как всегда, дьявол кроется в мелочах (ну, это, конечно, если не считать крайне кривого подключения воздуха и разводки электрики).



Дозирование инертных идёт хорошо, весело, с погрешность килограмм в 500. Регулирую датчики открытия дозаторов, выставляю величину дозагруза, погрешность уменьшается до 2-10 кг.

Через пару недель приезжают частотники. Ставим их в шкаф, выполняем перенос настроек (да, там ещё есть модули SM-Applications Plus со своими программами) и референцирование осей.



Profit! Можно начинать выпускать продукцию. Конечно, если сначала подобрать состав бетона.

В общем, всё закончилось хэппи эндом и линия благополучно работает по сей день.

Комментарии (4)


  1. grossws
    11.01.2016 16:07
    +1

    Странная бага. При нажатии стрелки указывается «недостаточное количество слова-которое-нельзя-называть», а за пост голосовать даёт. И автора показывает в ro.


    1. GlukKazan
      11.01.2016 22:38

      Исправлено


  1. redmanmale
    12.01.2016 12:08

    Спасибо за статью! Программирование контроллеров бетоносмесителей поинтереснее, чем очередная поделка на ардуино.


    1. firez
      12.01.2016 12:23
      +1

      И, что самое характерное, намного опаснее. К сожалению, был момент, когда формовщики откатили корзину раздатчика в сторону и 3,5 тонны бетона выгрузились с шестиметровой высоты на пол цеха. К счастью, все умело отпрыгнули в сторону.
      Потом этот баг успешно пофиксили (вместо одного датчика стали проверять 3, причём несколько раз).
      Кстати, про промавтоматику интересно пишет fixik-papus в ЖЖ.