Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Examples of Quad Decode, PID, SD File IO & a basic Sched

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> Share your working BASCOM-AVR code here
View previous topic :: View next topic  
Author Message
glena
member
member


Joined: 25 Jul 2007
Posts: 265
Location: PA near Philly

usa.gif
PostPosted: Mon Jul 07, 2008 5:24 pm    Post subject: Examples of Quad Decode, PID, SD File IO & a basic Sched Reply with quote

I have decided to post my code for a line follower I made.
While there are lots of basic line followers out there this one has some
advanced features that you might find useful in other projects.

I wrote this to learn how to do Quadrature Decoding and PID motor control. I also wanted to write to an SD card to log the movement and to replay the movements.

Here are some of the features:

* Use of Pin Change Interrupts for fast Quadrature Decoding
* P.I.D. motor control using the quadrature feedback and PWM
* Fat File IO to SD card for logging movement
* Basic scheduler
* Auto adapts to light levels for line following
and more...

Let me know what you think and if you have any questions on operation.

You can see pics here: http://bah.net/gallery/main.php?g2_itemId=58

Sorry, no schematic at this time...

-Glen


Code:

'==============================================================================
' Project:  RoverX
' Created:  2007-08-05
' Edited:   2008-03-21
' By:       Glen Aidukas
' Description:
'   RoverX is a line Follower, Movement Logger.
'   RoverX uses two geared down motors with a hall effect shaft encoders for
'   feedback loop (PID).
'   It is controlled by an Atmel ATmega644 8bit micro controller.
'   It also has an SD/MMC attached for FAT16/32 file IO to read/write logs.
'   It uses a SN754410 Quad half bridge driver for motor drive control.
'==============================================================================


'=====[ Compiler Directives ]==================================================
$crystal    = 8000000       ' set via fuse bits to internal RC at 8megs
$regfile    = "m644def.dat"
$baud       = 38400
$hwstack    = 256
$swstack    = 256
$framesize  = 256
'------------------------------------------------------------------------------


'=====[ Includes ]=============================================================
$include "Config_MMC.bas"           ' Load SD/MMC code and config
$include "Config_AVR-DOS.BAS"       ' Load FAT File system code
'------------------------------------------------------------------------------


'=====[ Aliases... ]===========================================================
M1En Alias Portd.7      ' Motor-1 Drive Enable
M1Ha Alias Portc.2      ' Motor-1 H-Bridge-A
M1Hb Alias Portc.3      ' Motor-1 H-Bridge-B
M1Qa Alias Portb.0      ' Motor-1 Quadrature Phase-A
M1Qb Alias Portb.1      ' Motor-1 Quadrature Phase-B

M2En Alias Portd.6      ' Motor-2 Drive Enable
M2Ha Alias Portc.4      ' Motor-2 H-Bridge-A
M2Hb Alias Portc.5      ' Motor-2 H-Bridge-B
M2Qa Alias Portc.0      ' Motor-2 Quadrature Phase-A
M2Qb Alias PortC.1      ' Motor-2 Quadrature Phase-B

ButtonC7 Alias Pinc.7  ' Used to initiat line following
'------------------------------------------------------------------------------


'=====[ Global Vars ]==========================================================
Dim Btemp1           As Byte  ' Needed for Fat Drivers
Dim Filename   As String * 14 ' Fat Filename
Dim TmpStr     As String * 9  ' temp string

Dim Tick             as long  ' Clock tick counter
Dim Tick_Print       as long  ' Update Display
Dim Tick_FileIO      as long  ' FileIO timer
Dim Tick_UpDatePID   as long  ' PID Polling
Dim Tick_Movement    as long  ' Control Movement
Dim Tick_Look        as Long  ' Led sensor array update
Dim Tick_Button      as Long  ' Button timeout

'   Motor(1&2)
Dim Kp(2)            as long  ' Proportional gain
Dim Ki(2)            as long  ' Integral gain
Dim Kd(2)            as long  ' Derivative gain

DIM P(2)             as long  ' tmp value for Proportional
DIM I(2)             as long  ' tmp value for Integral
DIM D(2)             as long  ' tmp value for Derivative

DIM previous_err(2)  as long  ' used in PID

Dim Scale(2)         as long  ' used in PID
Dim PriorErr(2)      as long  '
Dim IntegralErr(2)   as long  '

Dim PIDerr(2)        as long  ' Vars used in PIDpoll
Dim PIDtmp(2)        as long  ' Vars used in PIDpoll
Dim PIDval(2)        as long  ' Vars used in PIDpoll

Dim MaxSpeed(2)   as integer  ' Max Speed for Travel
Dim SetSpeed(2)   as integer  ' SetSpeed requested

Dim TargetPos(2)     as Long  ' Target Postion to go to

Dim CurPos(2)        As Long  ' Curent possition
Dim Q_NewValue(2)    As Byte  ' Used in Quadrature ISR
Dim Q_OldValue(2)    As Byte  ' Used in Quadrature ISR
Dim Q_Direction(2)   As Byte  ' Used in Quadrature ISR


Dim fwrite           as byte  ' file open/closed flag
Dim ch               as byte  ' junk var used for uart input
Dim x             as integer  ' junk var
Dim z                as byte  ' junk var

Dim Eye(6)        as integer  ' Led sensor array
Dim EyeL(6)       as integer  ' Low value
Dim EyeF(6)       as integer  ' Factor

Dim LinePos       as integer  ' line position
Dim LineSpeed        as byte  ' following speed
Dim LineFollow       as Bit   ' 1= follow line, 0=dont follow.

Dim DebugFlag        as Bit   ' 1= print debug info
'------------------------------------------------------------------------------


'=====[ Constants ]============================================================
Const Next_Tick_Print      = 500
Const Next_Tick_FileIO     = 100
Const Next_Tick_UpDatePID  = 10
Const Next_Tick_Movement   = 50
Const Next_Tick_Look       = 50
Const Next_Tick_Button     = 500

Const LineSpeedMax = 25
'------------------------------------------------------------------------------


'=====[ Routine declarations ]=================================================
Declare Sub PIDPoll           ' This is the main PID code
Declare Sub PrintDebug        ' Print out the uart some of the current values
Declare Sub LogIt             ' Write log data to the SD/MMC card
Declare Sub ProcessCMD        ' Process commands from uart
Declare Sub MovenentControl   ' Process movement
Declare Sub Look              ' Read LED Sensor Array
Declare Sub LineFollowCMD     ' Turn on/off line following
Declare Sub OpenLogFile       ' Open file for logging
'------------------------------------------------------------------------------


'=====[ Set IO Pins ]==========================================================
''' set data direction registors for io pins
DDRa = &B00000000 ' bits 1-6 are used for LED sensors
                  ' bits 0&7 not used

DDRB = &B10110000
      ' bits 0 & 1 are for M1 quadrator(a&b) position ticks
      ' bits 2&3 not used
      ' bit 4 - SD/MMC CS     (DDIR is reset by Config_MMC.bas)
      ' bit 5 - SD/MMC MOSI   (DDIR is reset by Config_MMC.bas)
      ' bit 6 - SD/MMC MISO   (DDIR is reset by Config_MMC.bas)
      ' bit 7 - SD/MMC SCK    (DDIR is reset by Config_MMC.bas)

DDRC = &B00111100
      ' bits 0 & 1 are for M2 quadrator(a&b) position ticks
      ' bits 2-5 used for Motor (M1& M2) direction control
      ' bit 6 not used, bit 7 used for button

DDRD = &B11000000
      ' bits 0&1 used by uart0
      ' bits 2&3 not used (future uart1)
      ' bits 4&5 not used
      ' bit 6 M2 drive enable
      ' bit 7 M1 drive enable

PortC.7 = 1             ' turn on resistor pullup for button
'------------------------------------------------------------------------------


'=====[ Setup Timer1 for Tick isr ]============================================
''' Timer1 is used for Tick counter
Config Timer1 = Timer , Prescale = 8 , Compare A = Disconnect , Clear Timer = 1
' crystal / Prescale / CountWanted = reload value
' 8000000 / 8        / 1000        = 1000 (trigger ever 1000th sec)
Compare1a = 1000
On Compare1a T1_TickCounter_isr
Enable Timer1
Enable Compare1a
'------------------------------------------------------------------------------


'=====[ Config Timer2 for Motor PWM power Control ]============================
' Timer2 is used for motor power control on M1 & M2
' This is done by using the PWM out puts on Timer2 (OC2A and OC2B) and
' connecting them to the Enable inputs on the H-Bride that drives the motors.
Config Timer2 = Pwm , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
Pwm2a = 0       ' Set initial speed to 0
Pwm2b = 0       ' Set initial speed to 0
'------------------------------------------------------------------------------


'=====[ Enable Pin change interrupt ]==========================================
' The Pin Change Interupts are used for the quadrature imputs from the motors.
Pcmsk1 = &B0000011               ' Set mask for pcint1 (PortB.0&1)
Pcmsk2 = &B0000011               ' Set mask for pcint2 (PortC.0&1)
Pcicr.1 = 1                      ' Enable Pcint1 (Pin Change Interrupt)
Pcicr.2 = 1                      ' Enable Pcint2 (Pin Change Interrupt)
On Pcint1 M1Quad_count_isr       ' Set interrupt vector for PCINT1
On Pcint2 M2Quad_count_isr       ' Set interrupt vector for PCINT2
'------------------------------------------------------------------------------


'=====[ Setup ADC ]============================================================
''' ADC1-6 are used for LED sensors
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
'------------------------------------------------------------------------------


'=====[ Config misc stuff ]====================================================

Config Serialout = Buffered , Size = 254  ' Serial Buffering

' setup default gains for the PID rutine
Kp(1)     = 128 : Kp(2)   = Kp(1)
Ki(1)     = 30  : Ki(2)   = Ki(1)
Kd(1)     = 196 : Kd(2)   = Kd(1)
Scale(1)  = 8   : Scale(2)= Scale(1)

' setup timer off sets for the sub rutines.
' the lower the number the higher the priority
Tick_UpDatePID = 0
Tick_Movement  = 1
Tick_FileIO    = 2
Tick_Look      = 4
Tick_Print     = 3
Tick_Button    = 5

for z = 1 to 6  ' set the initial optic values...
   EyeL(z) = 1000
   EyeF(z) = 1
next z

Enable Interrupts
'------------------------------------------------------------------------------


print chr(27) ; "[2J";  ' ansi clear screen...
print "Starting..."
waitms 300


'******************************************************************************
'*****[ Start of main loop ]***************************************************
'******************************************************************************
do
   select case Tick
      case is > Tick_UpDatePID   : Gosub PIDPoll   ' update PID
      case is > Tick_FileIO      : Gosub LogIt
      case is > Tick_Print       : Gosub PrintDebug
      case is > Tick_Movement    : Gosub MovenentControl
      case is > Tick_Look        : Gosub Look
      case else                  :
         if ButtonC7 = 0         then Gosub LineFollowCMD
         if ISCHARWAITING() = 1  then Gosub ProcessCMD
      end select
Loop
End
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


'=====[ PrintIt routine ]======================================================
''' Send out the uart some curent internal values
Sub PrintDebug
portd.5 = 0
if DebugFlag = 1 then

   print chr(27) ; "[1;1H";            ' Move to top of page
   Print "Tick:  " ; Tick
   print
   print "TargetPos: "   ; TargetPos(1)   ; ", " ; TargetPos(2)   ; "    "
   print "CurPos   : "   ; CurPos(1)      ; ", " ; CurPos(2)      ; "    "
   print "PIDerr   : "   ; PIDerr(1)      ; ", " ; PIDerr(2)      ; "    "
   print "PriorErr : "   ; PriorErr(1)    ; ", " ; PriorErr(2)    ; "    "
   print "P        : "   ; P(1)           ; ", " ; P(2)           ; "    "
   print "I        : "   ; I(1)           ; ", " ; I(2)           ; "    "
   print "D        : "   ; D(1)           ; ", " ; D(2)           ; "    "


   print "PIDval(a&b): " ; PIDval(1)      ; ", " ; PIDval(2)      ; "   "
   print "Kp   : "       ; Kp(1)          ; "  "
   print "Kd   : "       ; Kd(1)          ; "  "
   print "Ki   : "       ; Ki(1)          ; "  "
   print "Scale: "       ; Scale(1)       ; "  "
   print "Speed: "       ; SetSpeed(1)    ; "  "
   print "write: "       ; fwrite

'   print "Eyes: " ;
'   print Eye(1);",";Eye(2);",";Eye(3);",";Eye(4);",";Eye(5);",";Eye(6);"      "
'   Print "LinePos: " ;     LinePos ;   "   "
'   Print "LineFollow: " ;  ButtonC7 ;  " , " ; LineFollow ; "  "
'   print "LineSpeed: " ;   LineSpeed ; " "
endif

Tick_Print = Tick_print + Next_Tick_Print
portd.5 = 1
end sub
'------------------------------------------------------------------------------


'=====[ Process Commands routine ]=============================================
''' Check for chars from uart and process them
Sub ProcessCMD
   ch = inkey()
   if ch <> 0 then
      SELECT CASE ch
         Case "P" :     ' incrament P factor
                  Incr Kp(1)               : Incr Kp(2)
         Case "p" :     ' decrament P factor
                  Decr Kp(1)               : Decr Kp(2)
         Case "I" :     ' incrament I factor
                  Incr Ki(1)               : Incr Ki(2)
         Case "i" :     ' decrament I factor
                  Decr Ki(1)               : Decr Ki(2)
         Case "D" :     ' incrament D factor
                  Incr Kd(1)               : Incr Kd(2)
         Case "d" :     ' decrament D factor
                  Decr Kd(1)               : Decr Kd(2)
         Case "S" :     ' increase scale
                  Incr Scale(1)            : Incr Scale(2)
         Case "s" :     ' decrease scale
                  Decr Scale(1)            : Decr Scale(2)
         Case ")" :     ' increase set speed
                  Incr SetSpeed(1)         : Incr SetSpeed(2)
         Case "(" :     ' decrease set speed
                  Decr SetSpeed(1)         : Decr SetSpeed(2)
         Case "o" :     ' Stop!
                  SetSpeed(1) = 0          : SetSpeed(2) = 0
         Case "+" :     ' move forward one tick position
                  Incr TargetPos(1)        : Incr TargetPos(2)
         Case "-" :     ' move back one tick position
                  Decr TargetPos(1)        : Decr TargetPos(2)
         Case "]" :  ' + 10
                  TargetPos(1) = TargetPos(1) + 10
                  TargetPos(2) = TargetPos(2) + 10
         Case "[" :  ' -10
                  TargetPos(1) = TargetPos(1) - 10
                  TargetPos(2) = TargetPos(2) - 10
         Case "}" :  ' +100
                  TargetPos(1) = TargetPos(1) + 100
                  TargetPos(2) = TargetPos(2) + 100
         Case "{" :  ' -100
                  TargetPos(1) = TargetPos(1) - 100
                  TargetPos(2) = TargetPos(2) - 100
         Case "." :  ' turn left (one tick)
                  TargetPos(1) = TargetPos(1) + 1
                  TargetPos(2) = TargetPos(2) - 1
         Case "," :  ' turn right (one tick)
                  TargetPos(1) = TargetPos(1) - 1
                  TargetPos(2) = TargetPos(2) + 1
         Case ">" :  ' turn right (5 ticks)
                  TargetPos(1) = TargetPos(1) + 5
                  TargetPos(2) = TargetPos(2) - 5
         Case "<" :  ' turn left (5 ticks)
                  TargetPos(1) = TargetPos(1) - 5
                  TargetPos(2) = TargetPos(2) + 5
         case "1" :
                  decr TargetPos(1)
         case "2" :
                  decr TargetPos(1)    : decr TargetPos(2)
         case "3" :
                  decr TargetPos(2)
         case "4" :
                  decr TargetPos(1)    : incr TargetPos(2)
         case "5" :
                  '
         case "6" :
                  incr TargetPos(1)    : decr TargetPos(2)
         case "7" :
                  incr TargetPos(1)
         case "8" :
                  incr TargetPos(1)    : incr TargetPos(2)
         case "9" :
                                         decr TargetPos(2)
         case "0" :
                  TargetPos(1) = 0         : TargetPos(2)  = 0
                  CurPos(1)    = 0         : CurPos(2)     = 0
         case " " :  ' reset positions to 0
                  TargetPos(1) = 0         : TargetPos(2)  = 0
                  CurPos(1)    = 0         : CurPos(2)     = 0
                  SetSpeed(1)  = 0         : SetSpeed(2)   = 0
                  print chr(27) ; "[2J";

         case "c" :  ' clear the screen
                  print chr(27) ; "[2J";

         Case "z" : DebugFlag = 1
         Case "Z" : DebugFlag = 0

         Case "W" :  ' open fie for writing...
                  Gosub OpenLogFile
         case "w" :  ' close file
                  print #10, "Closing..."
                  close #10
                  fwrite = 0
      End Select

   end if
end sub
'------------------------------------------------------------------------------


'=====[ LogIt routine ]========================================================
''' Write data to the SD/MMC card
Sub LogIt
   if fwrite = 1 then
      print #10, Tick;",";TargetPos(1);",";TargetPos(2);",";CurPos(1);",";CurPos(2)
   endif
   Tick_FileIO = Tick_FileIO + Next_Tick_FileIO
end sub
'------------------------------------------------------------------------------


'=====[ Timer ISR routine ]====================================================
T1_TickCounter_isr:
   Incr Tick
Return
'------------------------------------------------------------------------------


'=====[ M1 Quadrature ISR routine ]============================================
M1Quad_count_isr:
  Q_NewValue(1) = Pinb
  Q_Direction(1) = Q_OldValue(1).0 Xor Q_NewValue(1).1
  If Q_Direction(1) = 1 Then
    Incr CurPos(1)
  Else
    Decr CurPos(1)
  End If
  Q_OldValue(1) = Q_NewValue(1)
Return
'------------------------------------------------------------------------------


'=====[ M2 Quadrature ISR routine ]============================================
M2Quad_count_isr:
  Q_NewValue(2) = Pinc
  Q_Direction(2) = Q_OldValue(2).0 Xor Q_NewValue(2).1
  If Q_Direction(2) = 1 Then
    Incr CurPos(2)
  Else
    Decr CurPos(2)
  End If
  Q_OldValue(2) = Q_NewValue(2)
Return
'------------------------------------------------------------------------------


'=====[ PID polling routine]===================================================
''' Motor PID Control.........................................................
Sub PIDPoll

dim tmp as long
dim Itmp as long
For z = 1 to 2

''' set Proportional   P = (Target - CurPos) * Kp
   PIDerr(z) = TargetPos(z) - CurPos(z)
   P(z) = PIDerr(z) * Kp(z)

''' set Integral       I = I + (error * Ki)
   tmp = PIDerr(z) * Ki(z)
   I(z) = I(z) + tmp
   If I(z) >  10230 then I(z) =  10230   ' limit windup
   If I(z) < -10230 then I(z) = -10230

   if PidErr(z) = 0 then
      if I(z) > 0 then I(z) = I(z) - 1
      if I(z) < 0 then I(z) = I(z) + 1
   endif

   Itmp = I(z) / 10


''' set Derivative     D = (error - previous_error) * Kd
   tmp = PIDerr(z) - PriorErr(z)
   D(z) = tmp * Kd(z)

''' PIDval = P - I + D / scale
'   PIDval(z) = P(z) + I(z)
   PIDval(z) = P(z) + Itmp
   PIDval(z) = PIDval(z) + D(z)
   PIDval(z) = PIDval(z) / scale(z)

   PriorErr(z) = PIDerr(z)

''' Set Limits
   if PIDval(z) > 255 then
      PIDval(z) = 255
   elseif PIDval(z) < -255 then
      PIDval(z) = -255
   endif

Next z


''' Set Motor Direction and PWM for motor 1
   if PIDval(1) > 0 then
      M1Ha = 1 : M1Hb = 0        ' Set h-bridge to go farward
      PWM2a = PIDval(1)
   end if
   if PIDval(1) < 0 then
      M1Ha = 0 : M1Hb = 1        ' Set h-bridge to go backwards
      PWM2a = -PIDval(1)         ' invert pwm value
   end if
   if PIDval(1) = 0 then         ' Set h-bridge to Coast
      M1Ha = 0 : M1Hb = 0
      PWM2a = 0
   end if

''' Set Motor Direction and PWM for motor 2
   if PIDval(2) > 0 then
      M2Ha = 1 : M2Hb = 0        ' Set h-bridge to go farward
      PWM2b = PIDval(2)
   end if
   if PIDval(2) < 0 then
      M2Ha = 0 : M2Hb = 1        ' Set h-bridge to go backwards
      PWM2b = -PIDval(2)         ' invert pwm value
   end if
   if PIDval(2) = 0 then         ' Set h-bridge to Coast
      M2Ha = 0 : M2Hb = 0
      PWM2b = 0
   end if

Tick_UpDatePID = Tick_UpDatePID + Next_Tick_UpDatePID   ' next pid update
end sub
'------------------------------------------------------------------------------


'=====[ Control Movement routine ]=============================================
Sub MovenentControl

' line following..
   if LineFollow = 1 then

      TargetPos(1) = TargetPos(1) + LineSpeed
      TargetPos(2) = TargetPos(2) + LineSpeed

      x = abs(LinePos)
      if LinePos < 0 then  ' Turn left
         TargetPos(1) = TargetPos(1) - x
         TargetPos(2) = TargetPos(2) + x
      endif
      if LinePos > 0 then  'Turn right
         TargetPos(2) = TargetPos(2) - x
         TargetPos(1) = TargetPos(1) + x
      endif
   else
      TargetPos(1) = TargetPos(1) + SetSpeed(1)
      TargetPos(2) = TargetPos(2) + SetSpeed(2)
   endif

Tick_Movement  = Tick_Movement  + Next_Tick_Movement
end sub
'------------------------------------------------------------------------------


'=====[ Line Following routine ]===============================================
Sub LineFollowCMD
''' Toggle line following mode (on/off)
   if Tick < Tick_Button then return

   While ButtonC7 = 0
   Wend

   If LineFollow = 0 then
      SetSpeed(1) = 0
      SetSpeed(2) = 0
      LineFollow = 1
   else
      SetSpeed(1)  = 0 : SetSpeed(2)   = 0
      TargetPos(1) = 0 : TargetPos(2)  = 0
      CurPos(1)    = 0 : CurPos(2)     = 0
      M1Ha = 0 : M1Hb = 0 : PWM1b = 0
      M2Ha = 0 : M2Hb = 0 : PWM2b = 0
      LineFollow = 0
   endif

   Tick_Button = Tick + Next_Tick_Button  ' Don't listen until some time passes.

end sub
'------------------------------------------------------------------------------


'=====[ Look at LED array ]====================================================
Sub Look
   ''' get the LED(1-6) values and auto adjust for new lows and highs
   for z = 1 to 6
      Eye(z) = Getadc(z)

      if Eye(z) < EyeL(z) then   ' we have a new low....
         EyeL(z) = Eye(z)
      endif
      Eye(z) = Eye(z) - EyeL(z)  ' zero adjust for proper low.

      x = Eye(z) / EyeF(z)       ' ajust for the high value
      if x > 25 then             ' we have a new high...
         EyeF(z) = Eye(z) / 25
      endif
      Eye(z) = Eye(z) / EyeF(z)  ' ajust for the high value
   next z

   ''' Set speed based on quality and possition of line
   x =     Eye(3)
   x = x + Eye(4)
   x = x * 4
   x = x + Eye(2)
   x = x + Eye(5)
   x = x / 3
   x = x + 5
   LineSpeed = LineSpeed + x
   LineSpeed = LineSpeed / 3

   if LineSpeed > LineSpeedMax then LineSpeed = LineSpeedMax

   ''' get the line possition (left to right)
   ''' adjust weight based on how far from center the line is
   LinePos = 0
   x = Eye(1) * -2    : LinePos = LinePos + x
   x = Eye(2) * -1    : LinePos = LinePos + x
   x = Eye(3) * -1    : LinePos = LinePos + x
   x = Eye(4) *  1    : LinePos = LinePos + x
   x = Eye(5) *  1    : LinePos = LinePos + x
   x = Eye(6) *  2    : LinePos = LinePos + x
   LinePos = LinePos / 7

Tick_Look = Tick_Look + Next_Tick_Look
end sub
'------------------------------------------------------------------------------

'=====[ Open file for logging ]================================================
Sub OpenLogFile
   Btemp1 = Initfilesystem(1)       ' Init Partition 1
   If Btemp1 <> 0 Then
      Print "Error: " ; Btemp1 ; " at Init file system"
   Else

      ' look for an unused filename...
      z = 0 : x = 0
      while z = 0
         Filename = "000" + str(x)
         TmpStr = Right(Filename, 3)
         Filename = "RvrX-" + TmpStr + ".log"
         Open Filename For Input As #10
         if EOF(#10) <> 0 then z = 1
         close #10
         incr x
         if x > 999 then
            print "To many files!!!!!"
            return
         endif
      wend

      print "Filename: " ; Filename
      Open Filename For Output As #10
      print #10, "Tick,TargetPos(1),TargetPos(2),CurPos(1),CurPos(2)"
      fwrite = 1
   endif
end sub
'------------------------------------------------------------------------------
end
Back to top
View user's profile Visit poster's website AIM Address
WanaGo
member
member


Joined: 15 Aug 2008
Posts: 111

newzealand.gif
PostPosted: Wed Sep 10, 2008 9:57 am    Post subject: Reply with quote

Hello,

I am just trying to get my head around the code used for quadrature encoder inputs.

I have looked through your code and see this section, which appears to be the main setup for the quadrature input pins

'=====[ Enable Pin change interrupt ]==========================================
' The Pin Change Interupts are used for the quadrature imputs from the motors.
Pcmsk1 = &B0000011 ' Set mask for pcint1 (PortB.0&1)
Pcmsk2 = &B0000011 ' Set mask for pcint2 (PortC.0&1)
Pcicr.1 = 1 ' Enable Pcint1 (Pin Change Interrupt)
Pcicr.2 = 1 ' Enable Pcint2 (Pin Change Interrupt)
On Pcint1 M1Quad_count_isr ' Set interrupt vector for PCINT1
On Pcint2 M2Quad_count_isr ' Set interrupt vector for PCINT2
'------------------------------------------------------------------------------

I see above this there was setting up the pins as inputs etc.

Question, where abouts in the help is there about the PCMSK and PCINT and PCICR etc?
I cant seem to find much about it, or that it even existed.

Can you tell me what the PCICR is?
I read in the help on the READHITAG topic, this:
Quote:
When you use the PCINT interrupt it is important to realize that other pins must be masked off. The PCMSK register may have only 1 bit enabled. Otherwise there is no way to determine which pin was changed.


but that is about all I can find on the topic.

Basically I am wanting to find any help about setting pins up to work to read a quadrature input, and how you set them to read the 'pin change' style input.

What you have written in the ISR etc is all fine, its just the setting up of the actual pins and interrupt I am having problems with.

Thanks in advance
James
Back to top
View user's profile
pseddon
member
member


Joined: 20 Oct 2006
Posts: 75

uk.gif
PostPosted: Thu Sep 11, 2008 2:19 pm    Post subject: Reply with quote

The function of PCMSK etc. can be found in the chip data sheet.

regards Peter
Back to top
View user's profile
glena
member
member


Joined: 25 Jul 2007
Posts: 265
Location: PA near Philly

usa.gif
PostPosted: Sat Sep 13, 2008 4:27 am    Post subject: Reply with quote

James (WanaGo),

The main issue I had when first trying to understand how to use pin change interrupts is to first note that there is not one interrupt for each pin but rather there are only 4 separate interrupts (one per port). So you first need to select the pins on a given port (using the Pcmsk0, 1, 2 or 3) for the given pins you want to get an interrupt for.

In: Pcmsk1 = &B0000011 I am saying on PortB, pins 0 & 1 are going to trip the interrupt (Pcint1).

If you are using more then one pin on a given port then you will need to test for what pin actually changed on that port when you get the interrupt. Once the mask is set for all the pins you want to use you then need to turn on the interrupt for the port that the pins are connected to. You do this with the PCICR register. Bit 0 for porta, bit 1 for portb and so on. Lastly you need to setup the interrupt vector via the "On Pcint1 M1Quad_count_isr" statement.

In the example I have there are actually 4 pins total that I need to get an interrupt on. I could have put them all on one port but since I don't know when the the pulses are going to come in, I separated the two different AB signals from the first motor and AB from the second motor. Since A & B can not happen at the same moment they can share the interrupt. I then test use their state to determine the state (up or down).

Note that I only test for two possible states out of four. Up, Down, NoChange and ErrorState. As long as the encoder out put is clean and not so fast that the ISR cant keep up then the only states you should get interrupts for are Up or Down. I don't remember what speed I tested the code to but it was error free to the fasted speed I was able to push the motors too.

I hope this helps. Smile

Let me know if you have any other questions...

-Glen
Back to top
View user's profile Visit poster's website AIM Address
dbrother
member
member


Joined: 07 Jan 2007
Posts: 7

blank.gif
PostPosted: Thu Jan 22, 2009 3:38 am    Post subject: Reply with quote

thank u very much!
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> Share your working BASCOM-AVR code here 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