А как в таком случае обнулять счет на ПЛК с буковками М02?
Вид для печати
А как в таком случае обнулять счет на ПЛК с буковками М02?
Никак. Это технически невозможно. "Обнуление" должно происходить в основной программе
Уважаемый Владислав, я понимаю, что краткость - сестра таланта, однако можно по подробнее пояснить про обнуление быстрого счетчика в 110М2? Если обнулять счетчик в принципе невозможно вообще никак и нигде, то какой смысл в этом счетчике?
Формат регистра счетчика - WORD, т. е. 0…65535 по абсолютному значению, т. е. придется программно учитывать переполнение аппаратного счетчика?
У вас установлен счётчик электричества?
Теперь примените к нему свои слова "Если обнулять счетчик в принципе невозможно вообще никак и нигде, то какой смысл в этом счетчике?"
И как? Нет смысла в "счётчике электричества" или есть?
Теперь вернёмся к "быстрому счётчику". Да, он просто считает, и когда достигает максимума, то сбрасывается.
"Учитывать переполнение" это пара строк кода:
total : DWORD;
newValue, prevValue : WORD;
newValue := counter;
total := total + WORD_TO_DWORD(newValue - prevValue);
prevValue := newValue;
Разумеется, и "total" тоже рано или поздно может переполниться.
Какая конечная задача требуется от этого счётчика?
В начале темы я описывал задачу. Но повторюсь:
1. На валу двигателя транспорта подачи материала установлен энкодер с разрешением 500 имп\об.
2. Частота вращения двигателя - максимум 3000 об\мин (обычно 2000 об\мин)
3. Двигатель работает от частотника.
4. Время, достаточное для подачи нужного количества материала ~0.4-0.6 сек за цикл.
5. Энкодер подключен к счетчику, который управляет частотником двигателя.
6. Двигатель низкоинерционный, остальная механика транспорта тоже. Останов происходит практически мгновенно, переезды есть, но они не критичны и их можно попытаться компенсировать программно.
От данного счетчика требуется отсчитать нужное количество импульсов и остановить двигатель. В следующем цикле счетчик должен быть обнулен до старта двигателя (переменная total в Вашем примере).
Т. е. счетчик должен уверенно и без пропусков считывать от одной фазы энкодера сигнал частотой до 30 кГц.
В принципе, я примерно так и сделал, как в предоставленном примере, но надеялся, что вдруг есть какая-нибудь другая возможность управления аппаратным счетчиком.
ЗЫ: Про сервопривода с функцией позиционера я знаю, однако задача стоит именно в таком способе позиционирования.
А какая точность/стабильность получилась?
Устраивает?
Объект сдан или ещё подобное планируется?
Раз вы написали "В продолжении темы быстрого счетчика и энкодера в одном флаконе", поэтому я подумал, что у вас какая-то новая задача, т.к. исходная тема обсуждалась в марте:
Попробую ещё разок:
Если видели тему по PRU программированию, то могли заметить, что я уже сделал ФБ для управления ШД с разгоном и поэтессами.
Можно сделать PRU ФБ и для вашей задачи. Пока ФБ делаю только я, но, возможно, скоро их смогут делать все желающие.
Например:
1) На вход "количество импульсов" -- длина пробега, и параметр "поехали"
2) По команде "поехали" блок будет активировать один из быстрых выходов
3) При достижении нужного количества импульсов, выход отключается
4) На выходе ФБ возвращается "пройденное расстояние" (на всякий случай) и "состояние" (ждём команды, едем, приехали)
5) В состоянии "приехали" счёт импульсов продолжается (чтобы можно было понять "какой перелёт оказался")
6) В состоянии "ждём команды" импульсы просто игнорируются. Или с ними что-то нужно делать?
Такой ФБ сможет без проблем отрабатывать на частотах порядка 100кГц, при этом 485, ethernet и прочее отваливаться не будет.
1. По сравнению с полноценными позиционерами - хуже.
2. Среднее расстояние подачи - 100-120мм, настоящий позиционер "гуляет" в пределах +-0,5 мм (возможно из за деформации материала и люфтов в механике), подобная реализация (не на ПЛК) "гуляет" на +-2мм, однако на %% брака это практически не сказывается, только немного увеличивается расход материала.
3. Данный проект находится в вялотекущей разработке, на реальной машине работает несколько другая система, но она морально и физически устарела, и просится на замену. Реализация этого счетчика средствами ПЛК позволит исключить один жутко импортный блок.
Это замечательно. Тему я просматривал, разработка нужная и полезная, но в моем случае. Т. к. имеющиеся привода не поддерживают принцип управления Step\Dir.
Это будет просто прекрасно.
Я даже прикидывал примерную схему тут
Параллельно с данным счетчиком должен работать ABZ энкодер с небольшой добавкой в виде детектора физического нуля после включения ПЛК.
Фото\видео - без проблем. Только не гарантирую когда это будет. В среднесрочной перспективе могу только провести эксперимент на реальной машине, если она встанет на долгий ремонт по железу. В условиях лаборатории проверить весь комплекс просто нет возможности.
Немного не так. ABZ-энкодер стоит на главном валу машины, это другой двигатель и другой частотник. Разрешение этого энкодера 360имп\об, По показаниям этого энкодера включаются и выключаются разные другие устройства, в том числе и транспорт. Детектор физического нуля необходим для того, что бы не включались устройства до тех пор, пока физический ноль не будет найден. Это связано с тем, что регистр энкодера в момент включения ПЛК равен нулю, а машина практически никогда не останавливается в 0 (обычно 150-190*), появляется "смещение", которое может привести к поломке оснастки и другой механики, если устройства включатся не в свое время. После определения физ.нуля детектор не оказывает никакого влияния на работу машины до следующего выключения.
В одном проекте я реализовал этот детектор программно ( на ПЛК110-60 старой модели), т. к. и модуль энкодера делал тоже программно, а показания энкодера сохранял а Retain.
1. Ненужно учитывать переполнение.
2. Зачем считать обязательно с нуля? Совершенно ни к чему обнулять регистр счетчика, нужно продолжать считать импульсы с того состояния, которое осталось в нем от предыдущего цикла.
Просто из текущего значения в счетчике нужно вычитать значение, которое было в нем перед стартом, т.к. WORD - без знаковое целое число, то результат арифметической операции "вычитание" всегда будет правильным, не смотря не то, что после 65535 счетчик начнет считать с 0.
Например
в счетчике было 65530
после старта значения в нем будут увеличиваться 65530, 65531, 65532, 65533, 65534, 65535, 0, 1, 2 ....
т.е. начальное значение в счетчике было 65530.
Теперь каждый раз при обращении в программе к регистру счетчика нужно вычитать начальное значение, в нашем случае получим
65530-65530=0
65531-65530=1
65532-65530=2
65533-65530=3
65534-65530=4
65535-65530=5
0 - 65530=6
1 - 65530=7
2 - 65530=8
3 - 65530=9
и т.д.
Т.е. никакое переполнение учитывать не надо.
Спасибо, проверим в реале.
petera всё правильно написал, но тут нужно не только счётчик получать, но и реагировать на него быстрее, чем ПЛК цикл.
Такой код работает в симуляторе: total := total + WORD_TO_DWORD(newValue - prevValue);
Но это не решает проблему "быстрого управления" -- эта проблема решится PRU программой.
A: WORD;
С: WORD := 65530;
A:=0-C;
Получится "6".
Простой пример
https://www.youtube.com/watch?v=bDNrHoHE73UКод:PROGRAM PLC_PRG
VAR
old: WORD;
curr_count: WORD := 65500;
NOTAL_count: WORD;
PUSK: BOOL;
TON1: TON;
state: INT;
END_VAR
TON1(IN:=NOT TON1.Q , PT:= t#100ms );
CASE state OF
0:
IF PUSK THEN
old:=curr_count;
state:=1;
END_IF
1:
curr_count:=curr_count + BOOL_TO_INT(TON1.Q);
NOTAL_count:=curr_count-old;
IF NOT PUSK THEN
NOTAL_count:=0;
state:=0;
END_IF
END_CASE
Да, в этом виде сломается.
Просто хотел ответить на частный вопрос
И показал, что обнулять счетчик не надо.Цитата:
Если обнулять счетчик в принципе невозможно вообще никак и нигде, то какой смысл в этом счетчике?
Формат регистра счетчика - WORD, т. е. 0…65535 по абсолютному значению, т. е. придется программно учитывать переполнение аппаратного счетчика?
Правильно будет так: total := total + WORD_TO_INT(newValue - prevValue);
Откуда такой вывод?
WORD_TO_DWORD нужно когда считаем "общее количество проделанных импульсов" (именно такая задача у автора темы) -- тут в prevValue/nextValue нужно брать счётчик.
WORD_TO_INT это когда пытаемся определить "абсолютное положение энкодера", но тогда и в prevValue/nextValue нужно брать не "счётчик", а реально "значение энкодера"
Вложение 26881
Зачем мне Ваши глупости повторят?
Я же сказал, что т.к. WORD - без знаковое целое число, то результат арифметической операции "вычитание" всегда будет правильным, не смотря не то, что после 65535 счетчик начнет считать с 0.
Т.е. именно для без знаковых целых переменных
0 - 65530=6
А Вы мне подсовываете КОНСТАНТЫ
Откуда компилятору знать, что эти константы надо рассматривать как без знаковые целые формата WORD, а не REAL или INT?
По этому только так
A: WORD;
С: WORD := 65530;
A:=0-C;
Получится "6"
Господа программисты, малость облегчу задачу для моего случая. Время работы двигателя транспорта программно ограничено по времени (1 сек) при любом состоянии счетчика и любой ситуации. Это сделано для предотвращения недопустимых ситуаций из за поломки энкодера и\или ошибки оператора станка при его настройке. По расчетам у меня получается примерно следующее: частота вращения двигателя транспорта 3000об\мин = 50 об\с, при разрешении энкодера 500 имп\об имеем 25000 импульсов. При среднем фактическом времени работы 0.4 сек имеем 10000 импульсов. Типы DWORD и DINT в моей задаче не актуальны.
Добрый день, немного оффтоп
Пришел плк110-220.60-K-М цвета корпуса такие же как на плк 160, это значит старая линейка?
М02 обновленный стиль корпуса ведь?
А кто вас спрашивает? Шутка.
Держите программу: Вложение 26911
Порядок пользования:
"online -> write file to plc -> PRU0.prg"
перезагружаем ПЛК
ФБ PRU_ABZ и PRU_CUTTER.
Через PRU_ABZ.ZERO_DETECTED можно узнать "обнаружен ли уже ноль"
Через PRU_CUTTER управляем мотором (указываем нужное количество импульсов и говорим "поехали!").
Энкодер подключать к 1-ым трём входам.
На какие именно фронты сигнала энкодера реагировать это, похоже, тот ещё вопрос, поэтому я сделал первое что пришло в голову: блок реагирует на вообще все фронты A и B сигналов. Фильтрации от дребезга нет. Возможно, стоит добавить.
Код:FUNCTION_BLOCK PRU_ABZ
VAR_INPUT
(*
A -- in1
B -- in2
Z -- in3
*)
END_VAR
VAR_OUTPUT
VALUE : WORD; (* increases or decreases depending on encoder direction *)
COUNTER : WORD; (* always increases *)
ZERO_DETECTED: BOOL; (* true when Z was detected at least once *)
END_VAR
FUNCTION_BLOCK PRU_CUTTER
(*
When ENABLE=TRUE, the block activates out1 until RUN_LENGTH encoder pulses observed.
RUN_LENGTH can be changed at any time.
*)
VAR_INPUT
ENABLE: BOOL;
RUN_LENGTH: DWORD; (* pulses *)
END_VAR
VAR_OUTPUT
STATE : PRU_CUTTER_STATE; (* INIT -> RUN -> STOP *)
OFFSET: DWORD; (* actual offset *)
END_VAR
TYPE PRU_CUTTER_STATE : (
INIT_CUTTER, (* CUTTER is waiting for new configuration and activation ENABLE=TRUE signal *)
RUN_CUTTER, (* CUTTER is moving *)
STOP_CUTTER (* CUTTER is stopped and it is waiting for ENABLE=FALSE to switch to INIT state *)
);
END_TYPE
Собственно, программа:
Вложение 26908
PRU_ABZ:
Вложение 26909
PRU_CUTTER:
Вложение 26910
Что значит "тот еще вопрос". Все должно быть однозначно.
Вложение 26912
http://www.owen.ru/forum/showthread....l=1#post187362
Сбрасывать, сбрасывать когда?
Если сбрасывать просто по фронту Z, то момент сброса будет зависеть от фактического направления вращения.
Как вариант, можно следить за направлением вращения и искать конкретный фронт в зависимости от направления вращения.
Ну или просто забить, и сбрасывать положение при любом фронте Z (что я и сделал)
Про Z метку. Привязка к фронтам А и В
Вложение 26915
Условно показан энкодер с одним "импульсом" на оборот.
Учтите, что один импульс - четыре такта изменения сигналов А и В.
Она всегда именно так выглядит?
Не будет ли того, что "длина Z" равна длине, скажем A?
Да даже если она привязана ко всем фронтам A и B, то всё равно "физический ноль" не может соответствовать сразу обоим фронтам Z метки.
Я и говорю: либо нужно эту погрешность проигнорировать, либо считать всегда один конкретный фронт Z метки (скажем, "левый"), который будет либо RTRIG, либо FTRIG в зависимости от направления вращения.
Указатель нулевой отметки / импульс полного оборота (выход N)
В энкодере, имеющем этот выход, импульс на этом выходе появляется в каждом обороте вала. Функция показателя нуля может использоваться для сброса внешне связанного счетчика или для регистрации начальной (нулевой) позиции.
Сброс счетчика ABZ-энкодера должен происходить при True на всех его трех входах - это будет самый точный "ноль". Фронт значения особого не имеет (во всяком случае для моего применения), но предпочтительнее передний.
За программу спасибо! Не ожидал, что будет так быстро готово. Постараюсь на следующей неделе воплотить всё это в железе, но правда на столе. Заодно проверю свой вариант решения "стандартными" средствами.
Не совсем понятно назначение выходной переменной counter в блоке PRU_ABZ_ENCODER. Если это просто счет импульсов, то оно без надобности. Вполне достаточно детектора истинного нуля и регистра показаний.
В самом энкодере всегда сбрасывают по обоим сторонам Z.
А в программе управления, зная направление вращения - учитывают это при расчёте положения
Привязана к фронтам А и Б, как на рисунке
Условно показан энкодер с одним "импульсом" на оборот.
Учтите, что один импульс энкодера - четыре такта изменения сигналов А и В.
Вложение 26917