Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Encoder - what is wrong

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
medicb

Bascom Member



Joined: 01 Aug 2009
Posts: 3

blank.gif
PostPosted: Thu Oct 25, 2018 10:35 am    Post subject: Encoder - what is wrong Reply with quote

I want to get numbers between 0 and 4 but sometimes I get the number -1 or 5.
What is wrong?

Code:

$regfile = "m8adef.dat"
$crystal = 12000000
$hwstack = 64
$swstack = 32
$framesize = 128

Config Lcd = 40 * 2
Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.6 , Db6 = Portb.2 , Db7 = Portb.1 , E = Portb.0 , Rs = Portd.7

Config Portd.4 = Input
Set Portd.4
Guzik Alias Pind.4


Cursor Off
Cls

Lcd "Menu"

Const Intermediate = 0                                      ' impulsy plusowe czy minusowe?
Const Int_pcint = 0                                         ' korzystamy z INT czy PCINT



Encoder_a Alias Pind.2                                      'PCINT18
Encoder_b Alias Pind.3                                      'PCINT19

Portd = Portd And &B11110011                                'PINy PODRTD2 i PORTD.3 to wejścia

#if Intermediate = 0
   Portd = Portd Or &B00001100                              'podciąganie na PORTD.2 i PORTD.3
#endif


#if Int_pcint = 1
 Pcmsk2 = &B00001100
  Enable Pcint2
   On Pcint2 Encoder_isr Nosave
#else
 Config Int0 = Change                                       'ewentualnie INT0 = Change
 Config Int1 = Change                                       'eventualnie INT1 = Change
  Enable Int0 : On Int0 Encoder_isr Nosave
  Enable Int1 : On Int1 Encoder_isr Nosave
#endif


Dim State As Byte , Enc_new As Byte , Enc_old As Byte , Steps As Integer , Old_steps As Integer


 Enable Interrupts

Do

If Steps > 4 Then Steps = 4
If Steps < 0 Then Steps = 0
If Old_steps <> Steps Then
  Old_steps = Steps

  Locate 2 , 1
  Lcd Old_steps   ; "   "    ; "< "

End If

Loop
End



Encoder_isr:

  $asm
  !PUSH R16
  !PUSH R24
  !PUSH R26
  !PUSH R27
  !PUSH R30
  !PUSH R31
  !in R24, sreg
  !PUSH  R24
  $end Asm

   Enc_new.0 = Encoder_a
   Enc_new.1 = Encoder_b

      Select Case Enc_new

       Case 1
        Select Case State
         Case 0 : State = 1
         Case 3 : State = 1
         Case 4 : State = 5
        End Select

       Case 2
        Select Case State
         Case 0 : State = 2
         Case 4 : State = 2
         Case 3 : State = 6
        End Select

       #if Intermediate = 1
        Case 3
       #else
        Case 0
       #endif

        Select Case State
         Case 1 : State = 3
         Case 2 : State = 4

         Case 5 : State = 4
         Case 6 : State = 3
        End Select

       #if Intermediate = 1
        Case 0
       #else
        Case 3
       #endif

        Select Case State
         Case 5 : Incr Steps
         Case 6 : Decr Steps
        End Select
         State = 0

      End Select

  '          Tuned with NoSave Tool

  $asm
  !POP  R24
  !out sreg, r24
  !POP R31
  !POP R30
  !POP R27
  !POP R26
  !POP R24
  !POP R16
  $end Asm


Return
 


(BASCOM-AVR version : 2.0.8.0 , Latest : 2.0.8.1 )
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2262

blank.gif
PostPosted: Thu Oct 25, 2018 11:08 am    Post subject: Re: Encoder - what is wrong Reply with quote

medicb wrote:
What is wrong?

Assume the ISR is immediately executed with increase of Steps after this line when Steps is 4:
Code:
If Steps > 4 Then Steps = 4

After the ISR increased it, Steps is 5, at least the short moment until the main loop is executed again and sets it back to 4.
Limiting a variable against under- or overflow has to be done where it is altered and that is within the ISR at the incr/decr block.
Back to top
View user's profile
EDC

Bascom Expert



Joined: 26 Mar 2014
Posts: 971

poland.gif
PostPosted: Thu Oct 25, 2018 11:34 am    Post subject: Reply with quote

This code was written for one variable only. For driving some menus (I suppose that by line "Lcd "Menu") better is use it like that: Encoder can set value +1 or -1 and this you can use for increment/decrement any variable in the menu. At the end of "If Steps<>0" you simply make Steps=0.
Should work now...

Code:
$regfile = "m8adef.dat"
$crystal = 12000000
$hwstack = 64
$swstack = 32
$framesize = 128

Config Lcd = 40x2
Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.6 , Db6 = Portb.2 , Db7 = Portb.1 , E = Portb.0 , Rs = Portd.7

Config Portd.4 = Input
Set Portd.4
Guzik Alias Pind.4


Cursor Off
Cls

Lcd "Menu"

Const Intermediate = 0                                      ' impulsy plusowe czy minusowe?
Const Int_pcint = 0                                         ' korzystamy z INT czy PCINT



Encoder_a Alias Pind.2                                      'PCINT18
Encoder_b Alias Pind.3                                      'PCINT19

Portd = Portd And &B11110011                                'PINy PODRTD2 i PORTD.3 to wej&#347;cia

#if Intermediate = 0
   Portd = Portd Or &B00001100                              'podci&#261;ganie na PORTD.2 i PORTD.3
#endif


#if Int_pcint = 1
 Pcmsk2 = &B00001100
  Enable Pcint2
   On Pcint2 Encoder_isr Nosave
#else
 Config Int0 = Change                                       'ewentualnie INT0 = Change
 Config Int1 = Change                                       'eventualnie INT1 = Change
  Enable Int0 : On Int0 Encoder_isr Nosave
  Enable Int1 : On Int1 Encoder_isr Nosave
#endif


Dim State As Byte , Enc_new As Byte , Enc_old As Byte , Steps As Integer , Old_steps As Integer
Dim Your_value As Byte

 Enable Interrupts

Do

 If Steps <> 0 Then

  Select Case Steps

    Case Is < 0
      If Old_steps > 0 Then Decr Old_steps
    Case Is > 0
      If Old_steps < 4 Then Incr Old_steps
  End Select

  Locate 2 , 1 : Lcd Old_steps ; "   " ; "< "

  Steps = 0
 End If

Loop
End



Encoder_isr:

  $asm
  !PUSH R16
  !PUSH R24
  !PUSH R25
  !PUSH R26
  !PUSH R27
  !IN R24, SREG
  !PUSH  R24
  $end asm

   Enc_new.0 = Encoder_a
   Enc_new.1 = Encoder_b

      Select Case Enc_new

       Case 1
        Select Case State
         Case 0 : State = 1
         Case 3 : State = 1
         Case 4 : State = 5
        End Select

       Case 2
        Select Case State
         Case 0 : State = 2
         Case 4 : State = 2
         Case 3 : State = 6
        End Select

       #if Intermediate = 1
        Case 3
       #else
        Case 0
       #endif

        Select Case State
         Case 1 : State = 3
         Case 2 : State = 4

         Case 5 : State = 4
         Case 6 : State = 3
        End Select

       #if Intermediate = 1
        Case 0
       #else
        Case 3
       #endif

        Select Case State
         Case 5 : Steps = 1
         Case 6 : Steps = -1
        End Select
         State = 0

      End Select

    '          Tuned with NoSave Tool 1.10

  $asm
  !POP  R24
  !OUT SREG, R24
  !POP R27
  !POP R26
  !POP R25
  !POP R24
  !POP R16
  $end asm

Return

 
Back to top
View user's profile Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum