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

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

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

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


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Команда Encoder в Баскоме-вопрос


Команда Encoder в Баскоме-вопрос

Сообщений 31 страница 49 из 49

31

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

Код:
  $regfile = "m8def.dat"
$crystal = 12000000
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 57600


Dim I As Word
Dim W As Word
Dim N As Word

Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input
Config Portc.4 = Output

Config Timer0 = Timer , Prescale = 64
On Timer0 Tim0:
Enable Timer0

Config Int0 = Falling                                       ' прерывание INT0 по нисходящему фронту (c + на -)
On Int0 Encod

Enable Interrupts
Enable Int0


Do

If I <> W Then Print W
I = W


Loop

Encod:                                                      ' тут узнаем в каком направлении вращают ручку энкодера

                                                               ' ждем пока утихнет дребезг контактов


    If Pind.6 = 0 Then       ' если на ноге единица (импульс не пришел) тогда
        Incr W       ' инкременируем переменную (увеличиваем на 1)
  N = W
 If N = 1001 Then
 W = 0
 End If
      Else       ' в обратном случае
'--------------------------------------------------------------
  If W > 0 Then
            Decr W       ' декрементируем переменную (уменьшаем на 1)
  End If
'--------------------------------------------------------------
 N = W
 If N = 0 Then
 W = 1000
  End If
    End If

    Gifr = 64

  Return


 Tim0:

If Pind.5 = 0 Then W = 0

If Pind.5 = 0 Then Print W


Return

то в программе терминала Bascom и по графику в LabVIEW видны пропуски посылок:
123
124
127
129
...
Программа не успевает отправить посылки на СОМ порт?
НО программа работает стабильно(счет идет от 0 до 1000, нет "зацикливаний" ) как бы быстро ты не вращал энкодер от руки
фото:
http://sf.uploads.ru/t/Oi8aB.jpg

а если переписать код программы вот так:

Код:
  $regfile = "m8def.dat"
$crystal = 12000000
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 57600


Dim I As Word
Dim W As Word
Dim N As Word

Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input
Config Portc.4 = Output

Config Timer0 = Timer , Prescale = 64
On Timer0 Tim0:
Enable Timer0

Config Int0 = Falling                                       ' прерывание INT0 по нисходящему фронту (c + на -)
On Int0 Encod

Enable Interrupts
Enable Int0


Do


Loop

Encod:                                                      ' тут узнаем в каком направлении вращают ручку энкодера

 If I <> W Then Print W
I = W


                    ' ждем пока утихнет дребезг контактов


    If Pind.6 = 0 Then       ' если на ноге единица (импульс не пришел) тогда
        Incr W       ' инкременируем переменную (увеличиваем на 1)
  N = W
 If N = 1001 Then
 W = 0
 End If
      Else       ' в обратном случае
'--------------------------------------------------------------
  If W > 0 Then
            Decr W       ' декрементируем переменную (уменьшаем на 1)
  End If
'--------------------------------------------------------------
 N = W
 If N = 0 Then
 W = 1000
  End If
    End If


    Gifr = 64

  Return

 Tim0:

If Pind.5 = 0 Then W = 0

If Pind.5 = 0 Then Print W


Return

То по терминалу и на графике пропусков значений не наблюдается, НО вращать энкодер нужно медленно, иначе видны "зацикливания" фото:
         http://sf.uploads.ru/t/6RSXu.jpg
сначала идет медленное вращение, все норм, а затем быстрое (график).

вот такая ситуация...не могу понять куда копать.

0

32

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

Отредактировано Skull (2015-01-09 16:54:49)

0

33

Разбирается...-это,конечно, сильно сказанно, только начал осваивать...работаю по таймингу, но вопрос в другом. терминал в bascom либо  пропускает посылки(1 вариант кода), но не зацикливается, либо все видит(2вариант кода) но есть ограничение на скорость вращения... на графиках в LV в принципе получается  такая же фигня, просто нагляднее.

Вопросс...может что с кодом не так? уважаемые знатоки? в обоих областях (bascom и LV) я еще очень большой делетант...поэтому и прошу помощи... сам пока не победю=)

Отредактировано Евгений86 (2015-01-10 16:01:10)

0

34

А тупо вывести значение энкодера в UART (и смотреть по TTL to USB в терминале) - не? Далее уже смотреть, кто, где косячит.

0

35

RDW
а я в данном случае не это делаю? через uart-usb переходник посылаю значение переменной W на терминал Bascoma и вижу пропуски принятых посылок (код 1), либо при быстром вращени зацикливание (код 2). или я что то не так понял?
и в том и в другом случае косячет программа (как я понимаю) либо не успевает отправить значение переменной, либо ,по какойт о пока не понятной причине идет зацикливание при быстром(от руки) вращени энкодера.

если что не так-поправьте.

Отредактировано Евгений86 (2015-01-10 19:41:21)

0

36

Я не знаю какой в Баскоме терминал (да и судя из постов выше, вы используете вообще ЛабВьюв), но всегда юзал внешние (начиная от стандартного в винде и сторонних).

0

37

RDW

Я не знаю какой в Баскоме терминал (да и судя из постов выше, вы используете вообще Лабвью)

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

а по коду ни кто ни чего не подскажет? а то мы что то не о том...

уважаемые форумчане, как решить данный глюк?

0

38

Уважаемые форумчане,так и не смог победить этот глюк.при быстром вращении идет зацикливание счета

Код:
$regfile = "m8def.dat"
$crystal = 12000000
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 57600


Dim I As Word
Dim W As Word
Dim N As Word

Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input
Config Portc.4 = Output

Config Timer0 = Timer , Prescale = 64
On Timer0 Tim0:
Enable Timer0

Config Int0 = Falling                                       ' прерывание INT0 по нисходящему фронту (c + на -)
On Int0 Encod

Enable Interrupts
Enable Int0


Do




Loop

Encod:                                                      ' тут узнаем в каком направлении вращают ручку энкодера

If I <> W Then Print W
I = W

                    ' ждем пока утихнет дребезг контактов


    If Pind.6 = 0 Then                                      ' если на ноге единица (импульс не пришел) тогда
        Incr W                                              ' инкременируем переменную (увеличиваем на 1)
N = W
 If N = 1001 Then
 W = 0
 End If
      Else                                                  ' в обратном случае
'--------------------------------------------------------------
  If W > 0 Then
            Decr W                                          ' декрементируем переменную (уменьшаем на 1)
  End If
'--------------------------------------------------------------
 N = W
 If N = 0 Then
 W = 1000
  End If
    End If




    Gifr = 64

  Return

 Tim0:

If Pind.5 = 0 Then W = 0

If Pind.5 = 0 Then Print W


Return

0

39

Мутный алгоритм.

У вас это место:

Код:
 Tim0:

If Pind.5 = 0 Then W = 0

If Pind.5 = 0 Then Print W


Return

Срабатывает четко по таймеру.
Значит достаточно чтобы на Pind.5 был нуль и тогда "Print W" будет всё время, по циклу выплёвывать значения. Причем вам ещё повезло, что нет глюка с отдачей данных, т.к. двухбайтовая переменная, с преобразованием в текст, легко может прилететь прерывание в int0 (в котором кстати тоже находится ресурсоёмкий print)...
В общем, если хотите пилить свой алгоритм дальше, то просто разберитесь пошагово где происходит зацикливание. Просто раставьте легкие print с текстом, чтобы понять на чем циклится.

0

40

Добрый день. на pind.5 висит кнопка для сброса в ноль.так сказать 0-положение, сброс происходит когда энкодер не вращается.

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

может проблема в том что при быстром вращении происходит слишком быстрая смена лог уровней на выходах энкодера? хотя по осцилографу не больше 12 кГц, вроде как должен успевать...

и даже если взять код из сообщения №14 этой ветки г-на "uh9cae"

Код:
$regfile = "m128def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 38400 

Dim Conl As Byte
Dim Con As Byte
Dim I As Dword
Dim Con_n As Dword

Config Portb.6 = Input : Config Portb.7 = Input   
Config Timer0 = Timer , Prescale = 8  
On Timer0 Tim0:
Enable Timer0
Enable Interrupts 

Do
If I <> Con_n Then Print Con_n 
I = Con_n
Loop

Tim0:
If Pinb.6 = 0 And Pinb.7 = 0 Then : Conl = 0 : End If
If Pinb.6 = 1 And Pinb.7 = 0 Then : Conl = 1 : End If
If Pinb.6 = 1 And Pinb.7 = 1 Then : Conl = 2 : End If
If Pinb.6 = 0 And Pinb.7 = 1 Then : Conl = 3 : End If
If Con = 0 And Conl = 1 Then : Incr Con_n : End If
If Con = 1 And Conl = 2 Then : Incr Con_n : End If
If Con = 2 And Conl = 3 Then : Incr Con_n : End If
If Con = 3 And Conl = 0 Then : Incr Con_n : End If
If Con = 0 And Conl = 3 Then : Decr Con_n : End If
If Con = 1 And Conl = 0 Then : Decr Con_n : End If
If Con = 2 And Conl = 1 Then : Decr Con_n : End If
If Con = 3 And Conl = 2 Then : Decr Con_n : End If
Con = Conl 
Return

происходит так же пропуски выданных на терминал значений...
а если в этом коде условие вывода переменной поставить не в основной цикл а в прерывание по счетчику

Код:
$regfile = "m128def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 38400 

Dim Conl As Byte
Dim Con As Byte
Dim I As Dword
Dim Con_n As Dword

Config Portb.6 = Input : Config Portb.7 = Input   
Config Timer0 = Timer , Prescale = 8  
On Timer0 Tim0:
Enable Timer0
Enable Interrupts 

Do

Loop

Tim0:
f I <> Con_n Then Print Con_n 
I = Con_n
If Pinb.6 = 0 And Pinb.7 = 0 Then : Conl = 0 : End If
If Pinb.6 = 1 And Pinb.7 = 0 Then : Conl = 1 : End If
If Pinb.6 = 1 And Pinb.7 = 1 Then : Conl = 2 : End If
If Pinb.6 = 0 And Pinb.7 = 1 Then : Conl = 3 : End If
If Con = 0 And Conl = 1 Then : Incr Con_n : End If
If Con = 1 And Conl = 2 Then : Incr Con_n : End If
If Con = 2 And Conl = 3 Then : Incr Con_n : End If
If Con = 3 And Conl = 0 Then : Incr Con_n : End If
If Con = 0 And Conl = 3 Then : Decr Con_n : End If
If Con = 1 And Conl = 0 Then : Decr Con_n : End If
If Con = 2 And Conl = 1 Then : Decr Con_n : End If
If Con = 3 And Conl = 2 Then : Decr Con_n : End If
Con = Conl

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

Отредактировано Евгений86 (2015-01-17 22:41:34)

0

41

у вас энкодер в схеме обвязан?

0

42

Подтяжка резисторов? да есть, а в остольном выход с энкодера чистый прямоугольный импульс(по осцилогя3)%4у)энкодер промышленный оптический, дребезга не наблюдал.

может это функция print так тормозит систему? в Bascom больше нет другого метода отправки по UART?

0

43

в прерывание print не пихают, легко может тормозить
вывод делается в основном теле программы

0

44

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

в прерывание print не пихают, легко может тормозить

Тем более что стека под вызов не хватит.
Его размер всего 32 байта и он полностью тратится под сохранение регистров в прерывании.

0

45

избавился от пропусков значений в терминале и LabWiev введя в основной цикл задержку 1 мс

Код:
$regfile = "m8def.dat"
$crystal = 11059200
$hwstack = 32
$swstack = 32
$framesize = 32
$baud = 115200


Dim I As Word
Dim W As Word
Dim N As Word

Config Pind.5 = Input
Config Pind.6 = Input
Config Pind.7 = Input
Config Portc.4 = Output

Config Timer0 = Timer , Prescale = 1
On Timer0 Tim0:
Enable Timer0

Config Int0 = Falling                                       ' прерывание INT0 по нисходящему фронту (c + на -)
On Int0 Encod

Enable Interrupts
Enable Int0


Do

 Waitms 1                                                  '   задержка
 If I <> W Then Print W
I = W

 Loop

Encod:                                                      ' тут узнаем в каком направлении вращают ручку энкодера

 If Pind.6 = 0 Then                                      ' если на ноге ноль (импульс  пришел) тогда
    Incr W                                                  ' инкременируем переменную (увеличиваем на 1)
    N = W
 If N = 1001 Then
    W = 0
 End If
      Else                                                  ' в обратном случае
'--------------------------------------------------------------
  If W > 0 Then
            Decr W                                          ' декрементируем переменную (уменьшаем на 1)
  End If
'--------------------------------------------------------------
   N = W
 If N = 0 Then
   W = 1000
 End If
  End If

  Gifr = 64

  Return


 Tim0:

If Pind.5 = 0 Then W = 0                   'сброс по кнопке

If Pind.5 = 0 Then Print W


Return

немного не реал-тайм, но зато глюк пропал!
http://sf.uploads.ru/t/hi6db.jpg

Отредактировано Евгений86 (2015-01-19 15:59:26)

0

46

и снова здрассьте. борюсь с энкодером, нужна психологическая помощь.
пытаюсь использовать команду Encoder из самого баскома. в симуляции все работает... хорошо. решил проверить в железе и началось:
энкодер EC12D1564402 = показания скачут через 1 (2 - 4 - 6 и т.д.) списал все на особенности самого энкодера (30 положений 15 щелчков)
энкодер PEC11R-4215K-S0024 = просто тупая железяка. чувствительный - невыносимо. только вала коснешься и начинается чехарда. обвязку делал по даташиту на энкодер, пофик дым.
с горя попробовал на прерываниях по примеру Max-a из этого топика - но там чет еще хужей все.
в итоге для первого энкодера наваял код:

$Regfile="attiny2313a.dat"
$Crystal=8000000
$hwstack=32
$swstack=8
$framesize=8
$lib "mcsbyte.lbx"

Config PinA.0 = Input : Set PORTA.0
Config PinA.1 = Input : Set PORTA.1

  Dim Энкодер as Byte
  Dim X as Single , Z as byte

Config Lcd = 16 * 2     
Initlcd       
Cursor off

X = 10 ': Z = 1
cls
Do

Энкодер = Encoder(PINA.0 , PINA.1 , L , P , 1)
Z = X
Locate 1 , 1
Lcd Z ; " "
waitms 50

Loop

L:
X = X - 0.5
Return

P:
X = X+ 0.5
Return

но почему-то не отпускает ощущение общего извращения из-за использования дробных переменных. у коллеги Kip-а вроде получалось эту функцию забороть...

0

47

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

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

У Вас все получится! У Вас все получится! У Вас все получится!

0

48

Andrusha
спасибо, добрый человек! прям камень с души  :D
а вот подписи надо как-то отделять от текста. а то я сперва плохое подумал.

0

49

А я всё как-то так, единственное прерывание отнимает время:

Код:
$regfile = "m128def.dat"
$crystal = 14745600
$framesize = 228                                            ' Размер области используемой и необходимой для преобразований
$hwstack = 228                                              ' Размер аппаратного стека
$swstack = 228                                              ' Размер программного стека

'-------------------------------порты энкодера
En1 Alias Pine.6
En2 Alias Pine.5
Ensw Alias Pinb.4
Config En1 = Input
Config En2 = Input
Config Ensw = Input


'========================== Прерывание энкодера
'----- прерывания энкодера

Config Int6 = Falling                                       'Change

'переменные энкодера
Dim Ennpr As Byte 'Направление
Dim Enswvr As Byte 'Для антидребезга кнопки

On Int6 Encoder1
Enable Int6
Enable Interrupts

Do

If Ennpr > 0 Then Gosub ....                           'если были действия энкодера, перерисовываем курсор
   If Ensw = 0 Then Enswvr = 1                              'обработка нажатия кнопки энкодера
   If Enswvr = 1 And Ensw = 1 Then                          'если кнопка энкодера была нажата и отжата, делаем действия выбора
      Enswvr = 0                                            'сбрасываем статус кнопки
      ......
      ......
   End If

Loop
End


Encoder1:

If Ennpr = 0 Then
Waitus 300
   If En1 = 0 Then 'Реализация фильтра
    If En2 = 1 Then 'Определение направления вращения
      Ennpr = 2
      Else
        Ennpr = 1
    End If
  End If
End If
Eifr = 255 'Очистка срабатывания INT, чтоб от дребезга небыло повторного прерывания

Return





Просто сигнализирую перемещение энкодера в нужную сторону и отрабатываю его.

Отредактировано Ev3658 (2018-04-18 11:04:31)

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Команда Encoder в Баскоме-вопрос