Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Готовые конструкции » Датчик пройдённого пути


Датчик пройдённого пути

Сообщений 1 страница 26 из 26

1

Всем привет и с наступающим!
Для работы появилась необходимость собрать с нуля датчик длинны, по сигналу с которого будет нарезаться продукция.
Сейчас стоит шкив - диск с прорезями + индуктивный датчик + унифицированный счетчик который считает до нужной длинны и дает команду отрезному устройству.
Эта нехитрая приблуда дает погрешность, иногда шкив проскальзывае и на выходе получается неверная длинна.
Вместо шкива сделаю трак с прижимом что бы исключить проскальзывание, но сейчас не об этом.
Эту самоделку необходимо полностью воплотить в жизнь, поэтому создал тему в этом разделе так как вконце будет схема, фото механики, программа(с которой Вы поможете)
ну и все сопутствующее.

За основу взял промышленный энкодер 400 импульсов за оборот (заказал на али).
Допустим за 1 оборот ведущего шкива трака пройдет 100мм.
100/3,1415=31,8мм (диаметр шкива)
100/400=4 импульса за 1мм
1 импульс = 0,25мм

Вывод должен быть один импульс каждые 10мм, в идеале меандр.

получается, что на выходе МК должен быть импульс каждые 40 импульсов на входе.
Так же должен быть калибровка:
коэффициент и поправка.

Теперь вопросы по программе:
Нужен ли здесь кварц?
с коэффициентом понятно, а вот как ввести поправку?
Отмеряем иногда 50 и 100 метров, на такой длине может набежать нехилая погрешность.

Вижу эту программу примерно так:

Код

$regfile = "attiny13A.dat"
$crystal = 9600000
$hwstack = 16
$swstack = 16
$framesize = 16
Config Portb.2 = Output                                     'Выход на Счетчик
'         Portb.1 = Input                                      ' N-Coder
Portb.2 = 1
Const K = 20                                                '1=0.25mm
Dim A As Byte
'Dim F As Bit
A = 0
'F = 0
Config Int0 = Falling                                       'прерывание по нисходящему фронту
Enable Interrupts
Enable Int0
On Int0 Ncoder
Do

Loop
End
Ncoder:
Incr A
If A = K Then
Toggle Portb.2
A = 0
End If
Gifr = 64
Return

В протеусе работает как надо.
Может есть варианты получше?

И еще, так как диаметр прутка делаем разный нужно сделать регулируемый прижим, что б при любом диаметре прутка усилие было одинаковым.
Пока виду в качестве привода моторредуктор с винтом. Сделать измеритель силы тока в цепи двигателя и отключать его питание(прижим) при достижении определенного
порогового тока. Эту функцию можно реализовать на МК, добавить этот код в мк который будет измерять длинну или реализовать на отдельном?

так же вопрос по н-кодеру, как я понимаю чем больше будет импульсов за оборот тем точнее будет длинна но с увеличением точности будет падать максимальная скорость
измерений.

При внутреннем генераторе 9,6 Мегагерц как посчитать максимальную скорость счета исходя из энкодера 400 и 600 импульсов на 100мм?

0

2

Правильно ли я считаю частоту на входе МК?
Скорость протяжки
50 м за 5 минут.
5 м за 60 сек.
1м за 12 сек.
длинна окружности шкива 100 мм
400 импульсов за 100мм (1 имп - 0,25мм)
4000 импульсов за 12 сек
333 Гц

0

3

Да проще простого! Xmega  :rolleyes:

Сталкивался с автоматом по нарезке прутка, у одного стоял энкодер где-то 260 линий, у другого 800 линий.
Измерительная система (два валика) была отдельно от подачи, но стояла до механизма обработки.
Дело в том, что железный прут после раскручивания бабины надо было выравнивать, первое выравнивание было роликами, после них стоял ролик с энкодером, а дальше уже вращающийся барабан который гнул проволоку и тем самым убирал напряжение, после стояли ножницы.
Так вот, чтоб запустить механизм резки, проволока доводится до кусачем с запасом, отрезается чуток лишнее и начинается отсчёт длины, после нарезания нужного кол-ва кусков, проволока вытягивается назад из барабана (чтоб не завязало узлом внутри).

В Xmega длину можно считать аппаратно, код программы будет до безобразия простым.
Подключаем выходы энкодера A и B например в PinB.0 и PinB.1 - настраиваем их на срабатывание по спаду:

Код:
Config Pinb.0 = Input                                       'A
Config Pinb.1 = Input                                       'B
Config Xpin = Pinb.0 , Sense = Falling
Config Xpin = Pinb.1 , Sense = Falling

Берём канал события поддерживающий квадратурное событие, это новая штука в серии Xmega, номера каналов 0,2,4.
Возьмём №0, укажем событие по пину PortB.0, включим квадратурную дешифрацию и поставим фильтрацию на пропуск 2 такта процессора (1 не будет работать).

Код:
Config Event_system = Dummy , Mux0= Portb.0 , Qd0 = Enabled , Digflt0 = 2


Дальше если нужно считать только в одну сторону, то проще некуда! Сделаем аппаратный делитель энкодера, то-есть возможность подогнать значение энкодера к примеру к 1 миллиметру.
Возьмём свободный любой таймер, их к примеру в Xmega256A3 аж 7 штук, пусть он будет считать имульсы и как достигнет предела, мы от него получим переполнение по которому будем знать 1 миллиметр пройденного пути.
Взял таймер порта D - TccD0, E0 - это наше событие, заодно укажем ему, что он будет срабатывать от квадратурного события:

Код:
Config Tcd0 = Normal , Prescale = E0 , Event_source = E0, Event_action = Qdec   

Теперь в таймере мы будем видеть положение энкодера в обе стороны, но он у нас считает непойми чего и до 65535.
Чтоб довести значение к настоящему пройденному пути, мы ограничим его счёт до нужного параметра:
Tcd0_Per = нужное значение 1-65535 (к примеру энкодер 600 импульсов, в квадратуре это 2400, а миллиметр = 1200 квадратурных импульсов или 300 линий энкодера), то:

Код:
TCD0_Per=1200

Или

Код:
Delitel alias Tcd0_Per
...
...
...
Delitel=значение из энергонезависимой памяти


Теперь нам нужно подсчитать миллиметры и опять-же не напрягая контролер и прочее, всё это программе не мешает нисколько.
Берём другой любой свободный канал события и указываем ему на событие по переполнению нашего калибровочного таймера и берём свободный таймер, к примеру тогоже порта D таймер 1, и ограничим его счёт в метр:

Код:
Config Event_system = Dummy , Mux1 = Tcd0_ovf  
Config Tcd1 = Normal , Prescale = E1 , Event_source = E1 
Tcd1_Per=1000 '(мм)
Pozmm Alias Tcd1_CCA - используем выход осциллятора для задавания нужного значения реза.


Теперь нам нужно подсчитать метры, делаем так-же, только возьмём таймер порта C и свободное событие:

Код:
Config Event_system = Dummy , Mux2 = Tcd1_CCA 'Установим на срабатывание по CCA, нужно чтоб поймать нужный миллиметр, так-то таймер всё равно ограничили до 1000мм.  
Config Tcс0 = Normal , Prescale = E2 , Event_source = E2 
Pozmetr Alias Tcc0_PER- используем выход осциллятора для задавания нужного значения реза.


Вот теперь мы сконфигурировали аппаратную часть не зависимую от нагрузки на процессор, она живёт в контроллере сама по себе и может работать на очень диких скоростях, теперь переходим к программе:
Нам понадобится прерывание, которое укажет нам на срабатывание по выходу позиции, а так-же нам нужно задать начало измерения! Делается вот так:
Делаем прерывание по переполнению таймера метров:

Код:
On Tcc0_OVF Pozicia


Для начала счёта необходимо в наши алиасы забить значения нужной длины и т.п.:

Код:
Dlina=356432 'в миллиметрах
Pozmm=Dlina Mod 1000 'берём остаток в мм, нам нужно до 1000, всё, что после 1000 это метры и считаются отдельно
Pozmetr=Dlina/1000
TCD1_CNT=1 'Чистим cчётчик миллиметров, обязательно не 0, а 1, иначе на 1 миллиметр будет больше.
TCC0_CNT=0 'Чистим счётчик метров
Enable Tcc0_OVF
Enable Interrupts
...
Print #1,"Расстояние:";TCC0_CNT;TCD1,CNT;"мм. "
...
...
Pozicia:
-Стоп, резать, готово
Disable Tcc0_OVF
Return


Вот и вся программа измерения, которая может измерять очень быстро и выплёвывать на выходе чего-то там с бешеной скорость. :writing:
Сам процесс измерения не занимает процессор, единственное что может тормозить процесс резки и старта - это алгоритм запуска счёта с прерыванием.

Можно так-же задать скорость двигателя ШИМом:

Код:
Puls1 Alias Porte.4                                         'Выход импульсов
Config Tce1 = Pwm , Prescale = 0 , Comparea = Enabled 
Speed Alias Tce1_per
Speed = 20

Старт:
Speed = чем меньше, тем быстрей
Config Tce1 = Pwm , Prescale = 64 , Comparea = Enabled  '64 - это делитель тактов процессора, подбирается под нужды.
 
Стоп:
Tcf0_CTRLA=0

Думаю тут будет достаточно информации, чтоб не чудить чудеса с энкодером в Atmega, серия Xmega самое то, но нужен PDI программатор.
Xmega32A4 вполне подойдёт под эти нужды.
И версия Bascom 2.0.7.5 немного глючка с Xmega, 2.0.7.8 уже хорошо работает. Кварца под такие нужды не нужен, но если понадобится Uart запускать, то нужен соответствующий кварц под Uart.

Отредактировано Ev3658 (2018-01-01 03:19:28)

+2

4

Ev3658
Спасибо за развернутый ответ!
Зачем как сложно? У меня нет цели построить управление всей линией на одном камне.
Под мои конкретные нужды разве 13-ой тины не хватит?
Правильно ли я составил программу или можно оптимизировать еще?
Зачем исчислять второй выход н-кодера если он совсем не нужен?

0

5

boida написал(а):

Правильно ли я считаю частоту на входе МК?
Скорость протяжки
50 м за 5 минут.
5 м за 60 сек.
1м за 12 сек.
длинна окружности шкива 100 мм
400 импульсов за 100мм (1 имп - 0,25мм)
4000 импульсов за 12 сек
333 Гц


Все верно.

0

6

Yuriy.pv
Спасибо!

0

7

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

0

8

есть у кого пример где б использовались оба таймера как каунтер?

0

9

boida написал(а):

есть у кого пример где б использовались оба таймера как каунтер?

Всё-же гляньте в сторону Xmega, там проще  :glasses:
Вот, проще некуда, на два энкодера:

Код:
'Входы энкодера 1
Config Pinb.0 = Input                                       'A
Config Pinb.1 = Input                                       'B
Config Xpin = Pinb.0 , Sense = Falling
Config Xpin = Pinb.1 , Sense = Falling

'Входы энкодера 2
Config Pinb.2 = Input                                       'A
Config Pinb.3 = Input                                       'B
Config Xpin = Pinb.2 , Sense = Falling
Config Xpin = Pinb.3 , Sense = Falling

'Квадратурные события энкодеров:
Config Event_system = Dummy , Mux0= Portb.0 , Qd0 = Enabled , Digflt0 = 2
Config Event_system = Dummy , Mux2= Portb.2 , Qd2 = Enabled , Digflt2 = 2

Таймеры счёта пройденного пути:
Config Tcd0 = Normal , Prescale = E0 , Event_source = E0, Event_action = Qdec  
Config Tcd1 = Normal , Prescale = E2 , Event_source = E2 , Event_action = Qdec  

On Tcd0_OVF pozicia1 'Прерывание на выход по позиции по первому энкодеру
On Tcd1_OVF pozicia2 'Прерывание на выход по позиции по второму энкодеру
Enable Interrupts

Do
///// Условие старта счёта по по энкодеру 1
Tcd0_CNT=0 ' Сбрасываем счётчик
Tcd0_Per=Кол-во делений - нужное расстояние (1-65535)
Enable Tcd0_OVF
Старт двигателя
\\\\\\\\\\\

///// Условие старта счёта по по энкодеру 2
Tcd1_CNT=0 ' Сбрасываем счётчик
Tcd1_Per=Кол-во делений - нужное расстояние (1-65535)
Enable Tcd1_OVF
Старт двигателя
\\\\\\\\\\\

Значение счёта в Tcd0_CNT и Tcd1_CNT.

Loop
End

Pozicia1:
Disable Tcd0_OVF
.... Сигнал отрезать, остановка двигателя и т.п.
Return

Pozicia2:
Disable Tcd1_OVF
.... Сигнал отрезать, остановка двигателя и т.п.
Return


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

Отредактировано Ev3658 (2018-01-02 02:18:05)

+1

10

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

Если у меня получится аппаратно считать импульсы от двух датчиков то можно подумать о устройстве объединяющим в себе датчик и счетчик.
ЛСД 16х2 и матричную клавиатуру 3х4. Хороший будет опыт.

Не могу найти толковую информацию по использованию таймеров и прерываний в баскоме (((((

0

11

boida написал(а):

Не могу найти толковую информацию по использованию таймеров и прерываний в баскоме (((((

Вот тут attiny13 управление одной кнопкой с таймером пост 65 RDW очень доступно расписал про прерывания.

Вот здесь Примеры применения в среде Баском неплохо покопаться, только тут не про XMega.

0

12

boida написал(а):

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

Понимаю, всё-же если вдруг не вам, то кому нибудь пригодится  :rolleyes:
Аппаратный подсчёт импульсов таймером на Xmega:

Код:
Config Pinb.0 = Input                                       ' Вход импульса      
Config Xpin = Pinb.0 , Sense = Falling 'Считаем по спаду, можно и по нарастанию фронта или то и это, так-же можно подтянуть к плюсу или к минусу вход

'Канал события:
Config Event_system = Dummy , Mux0= Portb.0 

Таймер счёта:
Config Tcd0 = Normal , Prescale = E0 , Event_source = E0

Dim W As Word
W=TCD0_CNT 'Получение значения


В Xmega есть семь таймеров: TCD0 TCD1 TCC0 TCC1 TCE0 TCE1 TCF0 - это почти каждый порт имеет по два таймера, первые (0) имеют 4 выхода OCx, вторые по 2
Регистры управления:
TCxx_PER - ограничение счёта
TCxx_CNT - Значение таймера
TCxx_OVF - Флаг прерывания по переполнению счёта таймера
TCxx_ERR - тоже флаг переполнения, но может чего-то и другое выполнять
TCxx_CCx - Выход осциллятора (x=A,B,C,D) используется как источник прерывания а так-же запись значения, чтоб  выход таймера работал, нужно его просто сделать выходом и в таймере довабить строчку "CompareX = Enabled" (X - это для подставления значения)

В Atmega таймеры для меня сложней, да и мало их.
Друг радиолюбитель Руслан из города Орёл создал очень хорошую программу для рассчёта таймеров Atmega, генерирует код Bascom, пользуйтесь на здоровье - https://yadi.sk/d/eFS1QsW3jAbkf

+2

13

Вот неплохое описание, подробней этого не нашел
http://avr.ru/beginer/bascom/article15

0

14

Конфигурация таймера для счета внешних импульсов
Config Timer0 = Counter , Prescale = 1 , Edge = Falling
Stop Timer0 - остановить счет импульсов
Start Timer0 - запустить счет импульсов
Timer0 = Z - присвоить таймеру значение переменной (начать счет с этого числа)
Z = Timer0 -  присвоить переменной значение таймера.
1. какой оператор нужен что бы записать число до которого будет считать таймер?
2. Какие еще есть операторы для работы с таймером в режиме счета внешних импульсов?
мне нужно что бы счетчик насчитал 40 импульсов добавил к переменной 1 обнулил таймер и начал считать поновой.
3. Судя из примеров это делается в прерывании по переполнению но у меня задействованы оба таймера может получится так, что
они досчитают одновременно. как это правильно сделать?

0

15

Никак , второй оставит метку в регистре. Чем быстрее обработаете первый, тем меньше потеряете во втором. Ну или контролировать в первом и втором прерывании состояния таймеров. Ну или как предлогал Ev3658..

0

16

Блин, ну не ужели на меге ни как нельзя реализовать подсчет двух внешних импульсов аппаратно?

0

17

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

0

18

boida написал(а):

Блин, ну не ужели на меге ни как нельзя реализовать подсчет двух внешних импульсов аппаратно?

ИМХО, если разнести частоты импульсов, вероятность их совпадения будет гораздо меньше.

0

19

В том то и дело, что б считать одновременно.
А если попробовать реализовать это не на таймерах а по внешнему прерыванию.
На два пина посадить мои датчики и через диолы на инт0, как сделано в статье "несколько кнопок на одном прерывании"
Сможет ли нормально выполнятся основная программа если ее будут прерывать с частотой 400 Гц при кварце 16мГц?

0

20

смотря как загрузите прерывания, между прерываниями ~40т. тактов

0

21

boida написал(а):

В том то и дело, что б считать одновременно.

Ну так и считайте...

boida написал(а):

А если попробовать реализовать это не на таймерах а по внешнему прерыванию.

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

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

0

22

Yuriy.pv написал(а):

смотря как загрузите прерывания, между прерываниями ~40т. тактов

кварц 16 мгц частота счетных импульсов до 500 гц.

0

23

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

0

24

будет лсд 16х2, клавиатура и улнка для релейных выходов.
Приедут н-кодеры буду пробывать на макетке.

0

25

Ev3658
Вот эта плата пойдет для экспериментов?

https://ru.aliexpress.com/item/mini-ATX … autifyAB=1

0

26

boida написал(а):

Ev3658
Вот эта плата пойдет для экспериментов?

https://ru.aliexpress.com/item/mini-ATX … autifyAB=1

Должна, вроде как Qdec был в Xmega32A4, по крайней мере в чипах в этих точно есть - https://www.aliexpress.com/item/ATXMEGA … 0.0.bDWwfm

С загрузчиком в Xmega не работал, проще как-то через PDI, но это требует отдельного программатора, сперва собрал а после купил AVR ISP MKII
http://sd.uploads.ru/t/5FxgK.png

0


Вы здесь » Программирование ATMEL в BASCOM. » Готовые конструкции » Датчик пройдённого пути