View previous topic :: View next topic |
Author |
Message |
medicb
Joined: 01 Aug 2009 Posts: 3
|
Posted: Thu Oct 25, 2018 10:35 am Post subject: Encoder - what is wrong |
|
|
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 |
|
|
MWS
Joined: 22 Aug 2009 Posts: 2262
|
Posted: Thu Oct 25, 2018 11:08 am Post subject: Re: Encoder - what is wrong |
|
|
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 |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
Posted: Thu Oct 25, 2018 11:34 am Post subject: |
|
|
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ś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
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 |
|
|
|
|
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
|
|