PDA

Просмотр полной версии : Подбор оборудования для управления 3-мя силовыми шкафами и центральным пультом



sav13
29.08.2023, 09:33
Всем привет

Задача: создание системы управления 3-мя силовыми шкафами с центрального пульта
Все ручное управление в шкафах собрано на релейной логике без МК
Для удаленного управления планируется использовать MK либо модули ввода вывода по RS485

Шкаф 1
DI x 3, DO x 1 (СК), AI x 1 (датчик уровня 4-20), связь RS485

Шкаф 2
DI x 5, DO x 2 (СК), AI x 2 (датчик уровня 4-20), связь RS485

Шкаф 3
DI x 22, DO x 9 (СК), AI x 4 (датчик уровня 4-20), связь RS485

Центральный пульт
Панель управления 10" и МК (если нужен)

Сейчас пока планирую поставить след. оборудование:
Шкаф 1 и Шкаф 2
Модули в/в МВ110-224.2А + МК110-224.8Д.4Р
Шкаф 3
Модули в/в МВ110-224.8А + МК110-224.8Д.4Р x 3
Пульт:
Панель СП310-Р + ПЛК200/210

Вопросы:
Можно ли заменить модули в/в на программируемые реле (получается дешевле конфигурация)? Насколько сложно их подключать к ПЛК, выше ли затраты на конфигурирования по сравнению с модулями в/в ?
Можно ли панель СП310 использовать вместо ПЛК? И чем это чревато?
Может быть есть лучшие решения для данной конфигурации на оборудовании Овен?

EFrol
29.08.2023, 10:17
Конечно, можно заменить, например, на ПР100. ПР-ки можно подключить к СП3хх напрямую (без ПЛК).
Только в Шкаф 3 придется ставить пару ПР100 (входов/выходов не хватает).
Какое расстояние между шкафами, а так же между ними и центральным пультом?
Алгоритм управления какой? Наблюдение + ручное управление?

sav13
29.08.2023, 10:23
Конечно, можно заменить, например, на ПР100. ПР-ки можно подключить к СП3хх напрямую (без ПЛК).
Только в Шкаф 3 придется ставить пару ПР100 (входов/выходов не хватает).

А программирование у меня увеличится?

Я ведь три реле и СП3XX в один проект CodeSys не соберу?

EFrol
29.08.2023, 10:34
А программирование у меня увеличится?

Я ведь три реле и СП3XX в один проект CodeSys не соберу?

Если без ПЛК, то CodeSys не понадобится.
Что Вы собираетесь программировать?

melky
29.08.2023, 10:36
три реле не имеют ничего общего с CodeSys. Либо вы их включаете как модули ввода/вывода и забываете пор их программирование. Что при панели сделать сложновато будет. Либо логику пишите для них в Овен Лождик, а панель связываете с переменными для отображения.

Начните с того, что умеете.

petera
29.08.2023, 10:58
А программирование у меня увеличится?

Я ведь три реле и СП3XX в один проект CodeSys не соберу?

Как Вы собираетесь СП310 в CodeSys программировать?

sav13
29.08.2023, 11:26
Как Вы собираетесь СП310 в CodeSys программировать?

Имелось в виду ПЛК200 + СП310. Но похоже СПК110 мне больше подходит


три реле не имеют ничего общего с CodeSys. Либо вы их включаете как модули ввода/вывода и забываете пор их программирование. Что при панели сделать сложновато будет. Либо логику пишите для них в Овен Лождик, а панель связываете с переменными для отображения.

Подучаю два реле ПР100 и одно ПР102 с модулем ПРМ.1 и в качестве контроллера СПК110. Спасибо. Так значительно проще

EFrol
29.08.2023, 11:43
Если у Вас просто ручное дистанционное управление, то панель оператора СП3хх справится без ПЛК и СПК.
Если Ваш проект требует каких-то автоматических действий без участия человека в каждом шкафу отдельно, то ПР-ки справятся самостоятельно без ПЛК и СПК.
Даже если Вам в какой-то ПР-ке понадобятся данные из другой ПР-ки, то СП3xx умеет пересылать данные между своими ведомыми устройствами.
Не связывайтесь Вы с ПЛК и СПК! Ограничьтесь OWEN Logic'ом и конфигуратором СП3хх!

sav13
29.08.2023, 11:49
Если у Вас просто ручное дистанционное управление, то панель оператора СП3хх справится без ПЛК и СПК.
Если Ваш проект требует каких-то автоматических действий без участия человека в каждом шкафу отдельно, то ПР-ки справятся самостоятельно без ПЛК и СПК.
Даже если Вам в какой-то ПР-ке понадобятся данные из другой ПР-ки, то СП3xx умеет пересылать данные между своими ведомыми устройствами.
Не связывайтесь Вы с ПЛК и СПК! Ограничьтесь OWEN Logic'ом и конфигуратором СП3хх!

К сожалению, логика дополнительная есть.
Должны быть блокировки включения насосов в зависимости от уровней на аналоговых входах.
Ну и в далекой перспективе может быть автоматическое управления.

А чем так страшны ПЛК и МПК ?
Средой разработки CodeSys ?

EFrol
29.08.2023, 11:55
Лишнее оборудование в простой системе зачем?
Блокировку включения насосов в зависимости от уровня Вы легко реализуете на OWEN Logic.
В этом случае работа шкафов будет автономной (независимой) - каждый своей ПР-кой.
А через СП3хх Вы сможете наблюдать за всеми параметрами в каждой ПР-ке и задавать уставки,
которые напрямую будут записываться в ПР-ки и в них сохранятся.

sav13
29.08.2023, 13:00
Лишнее оборудование в простой системе зачем?
Блокировку включения насосов в зависимости от уровня Вы легко реализуете на OWEN Logic.
В этом случае работа шкафов будет автономной (независимой) - каждый своей ПР-кой.
А через СП3хх Вы сможете наблюдать за всеми параметрами в каждой ПР-ке и задавать уставки,
которые напрямую будут записываться в ПР-ки и в них сохранятся.

Хорошо у вас все получается, просто.
Но, к сожалению, все сложнее. Емкость рядом со шкафом 2 опорожняется насосом, подключенным к шкафу 2. А наполняется насосом, подключенным к шкафу 1 за 500м. И блокировка уровня, подключенная к шкафу 2, должна работать для обоих насосов. Есть и еще нюансы. Поэтому центральный контроллер, мне кажется проще, чем три отдельных, но с пересекающимся управлением.

Вопросик по ПР
Насколько они надежны?
Если всю логику кнопочного пульта управления организовать на ПР?
Напрягает, что в случае отказа ПР или блока питания не будет работать никакое управление насосами и это приведет к остановке производства, а ремонт получается сложный - замена ПР целиком с заливкой туда программы и коммутации всех разъемов.
Да и на форуме есть посты о локальных глюках ПР

melky
29.08.2023, 13:16
petera у СП3хх нет скриптов ? это просто панель?

melky
29.08.2023, 13:21
sav13 а если умрет модуль ввода/вывода в одном из шкафов? чем хрен слаще редьки тогда если контроллер в одном месте, а управление в другом не работает?
вот поднималась тема как с ПР контролировать обрыв связи, вот это организуйте лучше и получится нет связи, ниче не работает все остановлено...

А программу даже из СПК вы не считаете, если в ПЛК исходники не загрузите и опять же, толку от исходников, если ПЛК умер? Исходники в бекапах совсем в другом месте должны лежать...

EFrol
29.08.2023, 13:36
У меня уже несколько лет работают еще ПР110. Со съемными клеймами замена занимает минут 10.
В схемах шкафов предусмотрен ручной пуск насосов (все исполнительные механизмы подключены через переключатели "Авто-Стоп-Пуск").
Можно безопасно заменить как ПР, так и исполнительное устройство без отключения щита управления.
Мне, кажется, Вы боитесь чего-то другого или ищите сложное в простом.
А глюки бывают в любых устройствах. Вы только посмотрите, какое количество релизов выходит на тот же CoDeSys с различными исправлениями только найденных багов!!!

EFrol
29.08.2023, 13:46
petera у СП3хх нет скриптов ? это просто панель?

Если позволите ответить, то CП3xx имеет возможность писать макросы на C-подобном языке.
На нем я без проблем реализую поддержку любого протокола обмена, не говоря уже об дополнительной логике.

petera
29.08.2023, 13:51
petera у СП3хх нет скриптов ? это просто панель?

Скрипты на Си есть.

Гипертерминал в СП310 https://owen.ru/forum/showthread.php?t=26719

/*
Макрос "ТЕРМИНАЛ"

(с) petera для форума ОВЕН

*/

// Used PSW Adr ---------------------

#define SetupAdr 259
#define KbdStatusAdr 260
#define inAdr 300 // (DWord) !!!
#define bufAdr 500 // buffer uses (lTotal x cTotal) Regs.!!!
//-----------------------------------------------------------------------------------
#define KbdStatus PSW[KbdStatusAdr] /* В битах этог регистра - состояние управляющих кнопок клавиатуры (Shift, Ctrl, Repead),
индикаторов "Прием", "Передача" и бит разрешения работы макроса */
#define Setup PSW[SetupAdr] // Настройки режимов приема и передачи
#define Input PSW[inAdr] // Буфер для приема символов с клавиатуры
#define dwInput *(DWORD*)(PSW + inAdr) // -- // -- в формате DWord
#define buffer PSW[bufAdr] /*Начальный адрес области регистров PSW из которых сделано текстовое окно терминала
для окна терминала будет занято (lTotal x cTotal) регистров PSW */

//---Макро для чтения бит регистра Setup---------------------------------------------------------
#define GetSetupStatus(bitno) ((Setup) & (1 << (bitno)))
//---------------------------- назначение бит регистра Setup
#define CRLFreceive 0 //При вводе с клавиатуры дополнять символ CR символом LF(перевод строки)
#define CRLFsend 1 //Дополнять символ CR, полученный от удаленного терминала, символом LF(перевод строки)
#define BS_BSsend 3 //Передавать символ "backspace"(BS) как комбинацию из "BS"+"пробел"+"BS"
#define Echo 4 /*Включить режим "Эхо". В режиме "Эхо" все денные,принятые от удаленного терминала
тут же отправляются обратно, после чего обрабатываются и выводятся на экран */
#define Visible 5 /*"Показывать введенные символы". Символы, вводимые с клавиатуры, отправляются удаленному
терминалу и также отображаются в окне. Если Visible=FALSE, то символы, вводимые с клавиатуры,
отправляются удаленному терминалу, но на экран не выводятся.*/
//---Макро для инверсии бит -------------------------------------------------------------------
#define ReversPSB(PSB_No) PSB[(PSB_No) / 8] ^= (1 << ((PSB_No) % 8)) /* В дополнение к существующим SetPSB(PSB_No) и ResetPSB(PSB_No)
этот макро выполняет инверсию заданного PSB
Пример:
ReversPSB(256); */

#define ReversBit(reg, bitno) ((reg) ^= (1 << (bitno))) //
//---Макро для работы с битами регистра KbdStatus-----------------------------------------------
#define GetKbdStatus(bitno) ((KbdStatus) & (1 << (bitno)))
#define ResetKbdStatus(bitno) ((KbdStatus) &= ( ~ (1 << ((bitno)))))
#define SetKbdStatus(bitno) ((KbdStatus) |= ( 1 << ((bitno))))
//---------------------------- назначение бит регистра KbdStatus
#define Shift 0 // Нажата кнопка Shift
#define Ctrl 1 // Нажата кнопка Ctrl
#define Repead 2 // Нажата кнопка Rep - повторение символов при вводе
#define RunEnable 3 // Работа приема и передачи разешена
#define receiver 4 // Состояние индикатора "Прием"
#define sender 5 // Состояние индикатора "Передача"
#define ClrScreen 6 // Команда "Очистить экран"

//------------------------------------------------------------------
const int lTotal = 18; // Количество строк в окне терминала
const int cTotal = 80; // Количество символов в одной строке
const int tabs = 8; // Кратность (в символах) позиций табуляции

static int cCount, lCount; // Номер текущей позиции в строке и Номер текущей строки
static char savMark; /* Сохраненный код символа, который скрыт курсором
т.к. курсор может перемещаться на экране не только вперед, но и вверх,
вниз и назад, то перед перемещением курсора в другую позицию необходимо
сохранять код символа в том знакоместе, в котором окажется курсор после перемещения.
И при последующем перемещании курсора возвращать сохраненный символ в знакоместо
ранее занимаемое курсором */
/* Курсор - мигающий символ '_', указывает знакоместо в окне терминала,
в которое будет вводится очередной символ. Координаты курсора однозначно
определяются переменными cCount и lCount */
static BOOL init; // Флаг инициализации(устанавливается после первого вызова макроса)

BYTE byReceive[3] = {0x00}; /* Буфер приема для СОМ порта
буфер приема имеет и второе назначение. Т.к. все, что пришло в буфер приема
от удаленного терминала безусловно должно быть выведено на экран.
Чтобы использовать этот же фрагмент кода вывода на экран и для вывода символов,
вводимых с клавиатуры, буфер приема будет использован и при вводе данных с клавиатуры */
BYTE bySend[3] = {0x00}; // Буфер передачи для СОМ порта
BYTE *pBuff; // Указатель адреса символа в памяти регистров, отображаемых в окне терминала
int i, count, tmp;
BOOL flagSend, flagVisible; // флаги - требуется вывод в СОМ порт, требуется вывод на экран

//--------------------------------

if (GetKbdStatus(ClrScreen) || !init) { //Clr Screen
ResetKbdStatus(ClrScreen); //Сбросить бит команды
init = TRUE; [/COLOR]
memset(&buffer, ' ', cTotal * lTotal); //Во все байты всех регистров отображаемых в окне терминала
savMark = ' '; //будут записаны коды пробела - произойдет "очистка" окна терминала
lCount = cCount = 0; //курсор в правый верхний угол окна терминала
pBuff = (BYTE *)&buffer; //Установить указатель на начало буфера окна

}
else pBuff = (BYTE *)&buffer + lCount * cTotal + cCount; //Установить указатель в текущую позицию курсора

//-------------------------------
if (!GetKbdStatus(RunEnable)) { //Если работа макроса запрещена, то
ResetKbdStatus(Repead); //"отжать" кнопку "rep"
ResetKbdStatus(sender); //Выключить индикатор "Передача"
ResetKbdStatus(receiver); //Выключить индикатор "Прием"
dwInput = 0; //Очистить буфер клавиатуры
*pBuff = savMark; //Восстановить символ, скрытый курсором
return; //Завершить работу макроса
}
//-----------------------------
flagSend = GetSetupStatus(Echo); //Получить состояние настроек "Эхо" и "Показывать введенные символы"
flagVisible = GetSetupStatus(Visible);

Enter(PLC); //Открыть порт PLC
count = Receive(PLC, byReceive, 3, 100, 12);/*Читать 3 байта, TimeOut=100мс, TimeOutBytes=12мс(что это за зверь я не знаю)
значения тайм-аутов подбирал методом "научного тыка" на скорости 57600.
возможно, что при уменьшении скорости до 9600 TimeOut немного увеличить.
Макрос с TimeOut=100 будет работать и на скорости 115200,если в гипертерминале Windows
не зажимать клавиши до автоповтора, т.к. в редких случаях единичные символы
при приеме могут "проглатываться". Передедача из панели на 115200 без нареканий.*/
if (count == NULL) { //Если ничего не пришло, то проверить наличие символов в буфере клавиатуры
if (dwInput == 0) { //Если и в буфере клавиатуры пусто
flagSend = flagVisible = FALSE; //то ничего не отправлять и ничего не выводить на экран
count = 0;
}
else { //А если кто-то нажимал кнопки клавиатуры, то
SetKbdStatus(sender); //Включить индикатор "Передача"
ResetKbdStatus(receiver); //Выключить индикатор "Прием""
memcpy(&byReceive, &Input, 3); /*Копировать три байта из буфера клавиатуры в буфер передачи
последующие манипуляции будем проводить с содержимым буфера передачи
его же в дальнейшем будем отправлять через СОМ порт и выводить на экран */
//Проверить состояние управляющих кнопок
if (GetKbdStatus(Shift)) { //Если нажата кнопка Shift
if (((byReceive[0] >= 0x41) && (byReceive[0] <= 0x5A)) || //и введен код заглавной латинской буквы
((byReceive[0] >= 0x61) && (byReceive[0] <= 0x7A)) || // или строчной латинской буквы
(byReceive[0] >= 0xC0)) ReversBit(byReceive[0], 5); // или любой русской буквы, то поменять заглавную на строчную или наоборот
else if ((byReceive[0] == 0xA8) || // если введен код Ё или ё
(byReceive[0] == 0xB8)) ReversBit(byReceive[0], 4); // то и их поменять местами
}
if (GetKbdStatus(Ctrl)) { //Если нажата кнопка Ctrl, то заменить ЛАТИНСКИЕ БУКВЫ на управляющие коды
if (((byReceive[0] >= 0x41) && (byReceive[0] <= 0x5A)) ||
((byReceive[0] >= 0x61) && (byReceive[0] <= 0x7A))) byReceive[0] = byReceive[0] & 0x1F;
else byReceive[0] = 0; // Если это были не буквы, то ничего не отправлять и не выводить
}
//Возможно нужно изменить способ передачи символов CR(ctrl+M /Enter) или backspace - (ctrl+H /Delete)
if (GetSetupStatus(CRLFsend) && (byReceive[0] == 0x0D)) byReceive[1] = 0x0A; //Если нужно, то к CR добавить LF
else if (GetSetupStatus(BS_BSsend) && (byReceive[0] == 0x08)) { //Если нужно, то к BS
byReceive[1] = 0x20; //добавить ' '
byReceive[2] = 0x08; //и ещё один BS
}
count = strlen(byReceive); //Возможно длина посылки теперь будет другой
memcpy(&bySend, &byReceive, count); //Копировать то, что на вводили с клавиатуры в буфер передачи
flagSend = TRUE; //Разрешить передачу удаленному терминалу
if (! GetKbdStatus(Repead)) { //Если кнопка повтора не нажата, то
dwInput = 0; //очистить буфер клавиатуры
ResetKbdStatus(Ctrl); //"отжать" кнопку Ctrl
ResetKbdStatus(Shift); //"отжать" кнопку Shift
} /*А если кнопка повтора нажата, то код введенного символа и модификаторы Ctrl и Shift
запомнятся и будут заново отправлены в следующем цикле выполнения макроса */
}
}
//Сюда попали, минуя обработку буфера клавиатуры, если буфер чтения СОМ порта не пустой
else {
ResetKbdStatus(sender); //Выключить индикатор "Передача"
SetKbdStatus(receiver); //Включить индикатор "прием"
flagVisible = TRUE; //Выводить на экран содержимое буфера приема
memcpy(&bySend, &byReceive, count); //Копировать в буфер передачи из буфера приема все принятые символы
//в неизменном виде на случай необходимости Эха удаленному терминалу
if (GetSetupStatus(CRLFreceive) && (byReceive[0] == 0x0D)) {//Если нужно, то в буфере приема к полученным CR добавить LF
byReceive[Min(2, count)] = 0x0A;
count = Min(3, count+1);
}
}
//------------------------------------
// В эту точку можем попасть или после приема данных от удаленного терминала или после ввода символов с клавиатуры
// и всегда если буфер приема из СОМ порта был пуст и буфер клавиатуры тоже пуст
if ((count != NULL) && flagSend) { //отправка данных удаленному терминалу необходима если есть, что отправлять и
//если, например включен флаг Эхо
Send(PLC, bySend, count); //отправка даанных удаленному терминалу
}
Leave(PLC); //Закрыть СОМ порт
//------------------------------------
//Эта часть программы - вывод информации на экран
if ((count == 3) && (byReceive[0] == 0x1B) && flagVisible) { //Если в буфере приема три символа и код первого символа 0x1B
// то в буфере Escape последовательность
*pBuff = savMark; //восстановить в текущем знакоместе символ скрытый курсором
tmp = MAKEWORD(byReceive[2], byReceive[1]); //Собрать два оставшихся в буфере символа "в кучку"
switch (tmp) {
case 0x5B41: //Up //Это кнопка стрелка вверх
if (lCount != 0) { //Пока не достигнем верха окна терминала
lCount--; //переместим курсор в ту же позицию вышележащей строки
pBuff = pBuff - cTotal; //пересчитать адрес нового положения курсора
}
break;
case 0x5B42: //Down //Это кнопка стрелка вниз
if (lCount != lTotal -1) { //Пока не достигнем низа окна терминала
lCount++; //переместим курсор в ту же позицию нижележащей строки
pBuff = pBuff + cTotal; //пересчитать адрес нового положения курсора
}
break;
case 0x5B44: //Left //Это кнопка стрелка влево
if (cCount != 0) { //Пока не достигнем левого края окна терминала
cCount--; //переместим курсор на одну позицию влево в той же строке
pBuff --; //пересчитать адрес нового положения курсора
}
break;
case 0x5B43: //Right //Это кнопка стрелка вправо
if (cCount != cTotal - 1) { //Пока не достигнем правого края окна терминала
cCount++; //переместим курсор на одну позицию вправо в той же строке
pBuff++; //пересчитать адрес нового положения курсора
}
break;
case 0x5B48: //Home //Это кнопка Домой, т.е.
lCount = 0; //переместить курсор в левый верхний угол окна терминала
cCount = 0;
pBuff = (BYTE *)&buffer; //пересчитать адрес нового положения курсора (указатель на начало буфера)
break;
case 0x5B4B: //End //Кнопка End
*pBuff = ' '; //В позиции курсора записать пробел
memset(pBuff, ' ', cTotal - cCount); //Удалить все символы от текущего положения курсора до донца строки
break;
}
savMark = *pBuff; //Сохранить символ в знакоместе экрана, на которое теперь будет указывать курсор
}
else if ((count != NULL) && flagVisible) { //А если в буфере не оказалось Escape последовательность, а он не пустой
for (i=0; i<count; i++) { //то будем выводить по очереди все символы, которые обнаружим в буфере
*pBuff = savMark; //восстановить в текущем знакоместе символ скрытый курсором
switch (byReceive[i]) { //кроме печатных символов в буфере могут находится управляющие символы
//некоторые из управляющих символов используются для управления выводом
case 0x07: //Bell - (ctrl+G). Удаленный терминал может прислать звуковой сигнал
Beep(); //и если звук в панели не запрещен (PFW[2] == 0), то услышим короткий Бип
break;
case 0x8: //backspace - (ctrl+H /Delete)
if (cCount != 0) { //если курсор не в начале строки
cCount--; //то прееместить его на одно знакоместо влево
pBuff--; //пересчитать адрес нового положения курсора
}
break;
case 0x9: //Tab - (ctrl+I) Табуляция - перемещение курсора вправо до ближайшей позиции кратной "tabs"
if (cCount < (cTotal - tabs)) { //Если до конца строки осталось болше чем значение "tabs"
tmp = tabs - cCount % tabs; //то подсчитать сколько символов от текущего положения курсора до до ближайшей позиции кратной "tabs"
cCount = cCount + tmp; //переместить курсор в новую позицию
pBuff = pBuff + tmp; //пересчитать адрес нового положения курсора
}
else { //если до конца строки символов осталось меньше чем значение "tabs"
tmp = cTotal -1 - cCount; //то подсчитать сколько их осталось
cCount = cTotal-1; //и новое положение курсора, в этом случае, однозначно д.б. в конце строки
pBuff = pBuff + tmp; //пересчитать адрес нового положения курсора
}
break;
case 0xA: //LF - line feed (ctrl+J). Перевод строки
lCount++; //переместим курсор в ту же позицию нижележащей строки
pBuff = pBuff + cTotal; //пересчитать адрес нового положения курсора
break;
case 0xD: //CR - carriage return (ctrl+M /Enter). Возврат каретки
cCount = 0; //переместим курсор в начало текущей строки
pBuff = (BYTE *)&buffer + lCount * cTotal;//пересчитать адрес нового положения курсора
break;
//следующие три управляющих кода пока не используются
case 0x03: //ETX - end of text (ctrl+C)
case 0x04: //EOT - end of transmission (ctrl+D)
case 0x1A: //ctrl+Z (SUB -substitute)
//А теперь выводим печатные символы
default:
*pBuff = byReceive[i]; //очередной символ из буфера приема поместить по адресу курсора
pBuff++; //декремент указателя адреса
cCount++; //переместить курсор в следующую позицицию строки
break;
}
savMark = *pBuff; //Сохранить символ в знакоместе экрана, на которое теперь будет указывать курсор
}
}
//----------------------------------------------------------------------
if (cCount >= cTotal) { //если текущее(расчетное) положение курсора оказалось больше чем символов в одной строке
cCount =0; //то курсор переместить в начало следующей строки
lCount++;
}
if (lCount >= lTotal) { //если после этого нмер текущей строки стал больше чем есть строк в окне терминала
memmove(&buffer, &buffer+cTotal/2, ((lTotal-1)*cTotal)); //по переписать все содержимое строк начиная со второй и по последнюю в начало буфера окна
lCount=lTotal-1; //теперь номер текущей строки будет на 1 меньше, чем общее количество строк
memset(&buffer+(lTotal-1) * cTotal/2, ' ', cTotal); //освободившуюся последнюю строку очистить (заполнить пробелами)
savMark = ' '; //естественно новый смвол скрытый курсором будет - пробел
}
//---------------------------------------------------------------------
//Мигающий курсор
if (GetPSBStatus(4)) *pBuff = '_'; //0,5 сек показывать курсор '_'
else *pBuff = savMark; //0,5 сек показывать символ, скрытый курсором
//-----------------------------------------

https://www.youtube.com/watch?v=8ve0VrADULc

СП3хх не только панель
ТЕТРИС в панели СП3хх. https://owen.ru/forum/showthread.php?t=33784

https://youtu.be/-0o6NfBF4Ig
Игра написана на Си, секция "main" оформлена одноименным макросом
69870

Остальные функции находятся в Глобальном макросе
69871

sav13
29.08.2023, 13:55
sav13 а если умрет модуль ввода/вывода в одном из шкафов? чем хрен слаще редьки тогда если контроллер в одном месте, а управление в другом не работает?
вот поднималась тема как с ПР контролировать обрыв связи, вот это организуйте лучше и получится нет связи, ниче не работает все остановлено...

А программу даже из СПК вы не считаете, если в ПЛК исходники не загрузите и опять же, толку от исходников, если ПЛК умер? Исходники в бекапах совсем в другом месте должны лежать...
Если умрет модуль в/в, останется локальное управления на релейной логике. Поставят мужика, который палкой будет мерить уровень и включать/отключать насос. Если нужно поставят двух или трех мужиков со связью по телефону. Но производство будет работать. А вот если кнопка запуска двигателя сидит на ПР, то тут уже ничего не сделаешь.


У меня уже несколько лет работают еще ПР110. Со съемными клеймами замена занимает минут 10.
В схемах шкафов предусмотрен ручной пуск насосов (все исполнительные механизмы подключены через переключатели "Авто-Стоп-Пуск").
Можно безопасно заменить как ПР, так и исполнительное устройство без отключения щита управления.
Мне, кажется, Вы боитесь чего-то другого или ищите сложное в простом.
А глюки бывают в любых устройствах. Вы только посмотрите, какое количество релизов выходит на тот же CoDeSys с различными исправлениями только найденных багов!!!
Я про это и говорю. Что локальное управление должно работать на кнопках и реле минуя любой ПЛК. Тогда это более менее надежно. Ну а удаленное/автоматическое управление уже с ними

Собственно, я особо не боюсь ничего. Просто делаю проект на систему. А так как раньше работал только с S7, то многое для меня ново. Например, ПР я воспринимаю как Logo у Сименса. На котором промышленные распределенные системы никто не делает.

EFrol
29.08.2023, 14:09
Сейчас, когда в OWEN Logic добавили возможность создавать ФБ на языке ST, я про ПЛК и СПК начинаю вообще забывать.
Ну не попадаются мне такие сверх-задачи, чтобы можно было их эффективно использовать.
Это все равно что делать мигающий фонарик на Intel Pentium'е:o

sav13
29.08.2023, 14:30
Сейчас, когда в OWEN Logic добавили возможность создавать ФБ на языке ST, я про ПЛК и СПК начинаю вообще забывать.
Ну не попадаются мне такие сверх-задачи, чтобы можно было их эффективно использовать.
Это все равно что делать мигающий фонарик на Intel Pentium'е:o

А если распределенная система с несколькими узлами?
Получается мне каждый узел нужно программировать, а потом еще все вместе связывать на той же панели оператора?

EFrol
29.08.2023, 14:46
А если распределенная система с несколькими узлами?
Получается мне каждый узел нужно программировать, а потом еще все вместе связывать на той же панели оператора?

Допустим Вы сделаете все на МВ, МУ и ПЛК.

ПЛК умер - все шкафы стоят!
МВ или МУ умер - ПЛК будет притормаживать опрос, т.к. будет перезапрашивать не ответившее устройство (алгоритм должен учитывать такой сценарий),
при этом панель даже знать об этом ничего не будет!!! (а так сообщит с каким именно узлом у нее нет связи)
Будем менять модуль не выключая ПЛК? Вперед! Модуль сконфигурировать думаете быстрее, чем залить готовую прошивку в ПР?

Связывать все на панели Вам придется и в том и в том случае!

melky
29.08.2023, 15:20
Если умрет модуль в/в, останется локальное управления на релейной логике. Поставят мужика, который палкой будет мерить уровень и включать/отключать насос. Если нужно поставят двух или трех мужиков со связью по телефону. Но производство будет работать. А вот если кнопка запуска двигателя сидит на ПР, то тут уже ничего не сделаешь.

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

Правильно воспринимаете - ПР = Logo с теми или иными плюшками и недостатками

In_Da_Cher_A
29.08.2023, 16:21
смешно читать про страхи что плк/реле умрёт, ничего управляться не будет
да там три ящика с 10 сигналами, которые и так сейчас не управляются, чего там бояться
если бы там было хоть что-то , что требует надёжности, вы бы не сидели на форуме овен
а выбирали бы нормальные плк с резервированием как модулей, так и коммуникаций
но вы смотрите дешёвые железяки производителя эконом сегмента и пытаетесь не потратив денег добиться MBTF в 100 тыщ часов?
ну не будет работать - придёт Уася и воткнёт вручную