Появилось немного свободного времени и я вновь вернулся к вопросу об управлении ШД при помощи простейшего, Китайского ПЛК.
В некоторых источниках видел релейные схемы, которые реализовывали на этих ПЛК для управление ШД. Мне как приверженцу традиционных инструментов (С/С++), трудно переключится на релейную логику и я делал несколько подходов к ПЛК использую язык ST. Это что-то очень похожее на Codesys, который в свою очередь похож на смесь Паскаля, Бейсика и Си. Хотя эта схожесть достаточно отдаленная.
В результате изучения документации набрел на раздел, посвященный управлению двигателями.
Это меня воодушевило. Далее стало понятно, что это обычные функции, а я все пытался найти функциональный блок.
Тут надо отметить, что описание на русском видимо с машинного перевода и довольно корявенькое. Пришлось сделать несколько тестов.
На выход ПЛК подцепил осцилограф и стал изучать возможности этих функций.
DRVA, DRVI в качестве параметров указываем кол-во импульсов, частоту, выход импульсов, выход направления.
Так же добавлю, что частота имеет разгон и торможение.
Экспериментируя я получил заявленные, стабильные 100 кГц на выходе.
В схему добавил резистор подтяжки, что бы на частотах более 20 кГц форма сигнала была похожа на полезный сигнал
В общем после того как я научился запускать пачку импульсов - принялся за прошивку.
Писал в среде GX Works2
(*******************************************************************************************
Входы/Выходы
X0 - Сигнал датчику нуля оси Z
Y0 - STEP. Выход на драйвер ШД
Y4 - DIR. Выход на драйвер ШД
Регистры
M0 Bit Запускает/останавливает движение по заданным координатам
M1 Bit Ручное движение вверх
M2 Bit Ручное движение вниз
M3 Bit Режим скорости ручного перемещения (0 - медленно S1, 1 - быстро S)
M4 Bit Корректировка высоты заготовки
M5 Bit Поимк нулевой точки
D9 DWORD Уставка Z в импульсах
D128 INT Высота стола (0.1 мм)
D132 INT Высота заготовки (0.1 мм)
D136 INT Количество импульсов на 1 мм перемещения по оси Z
D140 INT Скорость движения по оси Z (мм/сек). Автоматический режим
D142 INT Скорость движения по оси Z (мм/сек). Ручное управление
D144 INT Текущая координата Axis Z (0.1 мм)
D148 INT Текущая высота от заготовки до линзы Work Z (0.1 мм)
D152 INT Текущий номер линзы Lens (1..4)
D156 INT Фокусное расстояние линзы F1 (0.1 мм)
D160 INT Фокусное расстояние линзы F2 (0.1 мм)
D164 INT Фокусное расстояние линзы F3 (0.1 мм)
D168 INT Фокусное расстояние линзы F4 (0.1 мм)
D172 INT MaxZ. Максимальное значение Z
D176 INT Фокусное расстояние выбранной линзы
D8140 DWORD Текущее значение координаты Z в импульсах
M8029 Bit Сигнал завершения позиционирования (в одном цикле)
M8147 Bit 1 - происходит перемещение (Занято), 0 - ожидание команды
********************************************************************************************)
IF M8002 = 1 THEN (* Выполняется однократно при старте программы *)
M0 := FALSE;
M1 := FALSE;
M2 := FALSE;
M4 := FALSE;
END_IF;
(* Вычисляем чатсоту импульсов *)
dK := INT_TO_DINT(D136); (* K *)
HiSpeed := INT_TO_DINT(D140); (* Hi Speed *)
HiFreq := (dK * HiSpeed) / 10;
LoSpeed := INT_TO_DINT(D142); (* Lo Speed *)
LoFreq := (dK * LoSpeed) / 10;
CASE D152 OF
1: (* Линза 1 *)
D176 := D156;
FLeanse := INT_TO_DINT(D156);
2: (* Линза 2 *)
D176 := D160;
FLeanse := INT_TO_DINT(D160);
3: (* Линза 3 *)
D176 := D164;
FLeanse := INT_TO_DINT(D164);
4: (* Линза 4 *)
D176 := D168;
FLeanse := INT_TO_DINT(D168);
ELSE
D176 := 0;
FLeanse := 0;
END_CASE;
(* Вычисляем заданную координату Z в импульсах *)
TableH := INT_TO_DINT(D128); (* Высота стола *)
Mesure := INT_TO_DINT(D132); (* Высота заготовки *)
MaxZ := INT_TO_DINT(D172 ); (* MaxZ смещение*)
DestZ := MaxZ - (TableH + Mesure + FLeanse) ; (* Значение Z в 0,1 мм с учетом смещения MaxZ*)
DestPulsZ := DestZ * (dK/10); (* Вычисляем количество импульсов для смещения *)
DMOV( TRUE, DestPulsZ , D9);
(* Вычисляем текущую координату Z в 0,1 мм*)
DMOV( TRUE, D8140 , HardZ);
AxisZ := MaxZ - (HardZ * 10) / dK;
D144 := DINT_TO_INT(AxisZ);
(* Вычисляем текущее расстояние от заготовки до линзы Z1 в 0,1 мм*)
WorkZ := AxisZ - (TableH + Mesure);
D148 := DINT_TO_INT(WorkZ);
(* Soft Limit max *)
IF AxisZ > MaxZ THEN
M0 :=FALSE;
M1 := FALSE;
END_IF;
(* Soft Limit min *)
IF (AxisZ <= (TableH + Mesure)) THEN
M0 := FALSE;
M2 := FALSE;
END_IF;
(* По сигналам ручного управления отключить автоматическое M0 *)
IF M1 OR M2 THEN
M0 := FALSE;
M5 := FALSE;
END_IF;
DDRVA( M0 , DestPulsZ, HiFreq, Y0 , Y4);
(* Переключение скорости перемещения в ручном режиме *)
IF M3 THEN
HandSpeed := HiFreq;
ELSE
HandSpeed := LoFreq;
END_IF;
DDRVI( M1 , -80000 , HandSpeed , Y0 , Y4 );
DDRVI( M2 , 80000 , HandSpeed , Y0 , Y4 );
Y7 := M8147;
(* Поиск референтной точки/ мащинный 0 по датчику *)
DZRN( M5 , HiFreq, MaxZ * dK, X0 , Y0 );
(* Сброс M0 по оканчании позиционирования *)
IF M8029 THEN
M0 := FALSE;
M5 := FALSE;
END_IF;
Для управления режимами работы подключил текстовую панель оператора OP320A
На панели настроил несколько экранов для настройки, диагностики и главный для работы.
Уже в процессе отладки в голову пришла еще одна мысль по корректировки высоты заготовки. Дело в том, что порой поверхность гравировки как бы утоплена в деталь и не всегда есть возможность ее точного измерения. В таких случаях выкладываю на эту поверхность небольшой фрагмент алюминиевого листа (20*20мм) и уже визуально (по лазеру) определяю необходимую высоту сканаторной головы над заготовкой.
Все просто. Добавляю на панель оператора еще одну кнопку и дополняю код еще одним условием
IF m4 THEN
D0 := расчет;
END_IF;
Однако при старте почему-то это условие на первом цикле выполнения программы всегда выполнялось.
И даже в таком варианте:
m4 := FALSE;
IF m4 THEN
D0 := расчет;
END_IF;
Условие все равно выполнялось.
На этих 3-х строках кода потратил весь день, пытаясь понять причину. А причина оказалась банальной: Кривая прошивка ПЛК. И при компиляции из ST на первом цикле почему-то происходила не верная адресация как раз с условными операторами. Набрел на эту инфу на каком-то забугорном форуме. Не буду вдаваться в детали, но получается, что полноценно язык ST использовать для управления этими ПЛК не получится. По крайней мере это касается условных операторов IS/CASE/FOR
Тогда решил идти в обход
Этот фрагмент кода вынести в отдельную задачу и реализовать ее... , нет не на релейной логике, она по прежнему у меня вызывает взрыв мозга, на FBD. Это что-то похожее на электрическую схему
Набросав несколько блоков реализующих вычисление - алгоритм заработал верно.
И немного видео
https://youtu.be/BY-hvPyY9oI
Сегодня приехал драйвер, БП, шаговик и всякая мелочевка.
Собрал схему, подключил ПЛК и ... все заработало.
https://youtu.be/-HM8uyXW9VU
Сообщение отредактировал Smith2007: 24 Сентябрь 2021 - 01:30