Us digital encoder code

I am a high school student working on a project for a science competition. I would like to implement an encoder from US digital to read how far a device has traveled. The only previous experience i have programming is going through the Boe Bot tutorial from parallax and programing a Basic atom pro to interface with 16 servos another micro and a radio. I was wondering what the best way to read the output is. All i really need is the micro(i have a basic atom pro or a BS2 that i could use) to count how many pulses and then jump to a subroute once a particular number has been reached. The count command would work but its not really ideal. Parallax has put some snipits of code out there for the BS2 and encoders but i am not sure they would work at the high resolution that i want and i dont particularly understand how the code works. I was wondering if anyone would be kind enough to share a bit of code for an Atom pro(or BS2 i guess) that counts encoder pulses.

Sorry I don’t have any code for the US digital encoder for the Basic Atom Pro. However I am currently working on the code for my 4WD rover that has two of the motors with encoders on it:lynxmotion.com/Product.aspx?productID=598&CategoryID=11. This encoder has two output channels(A,B), that are about 90 degrees out of phase with each other.

I have just starting working on this code. My first approach will be to try to have the BAP handle this by having Channel A of the encoder hooked up to a pin on the BAP that can trigger an interrupt. For example P18 which coorespondes with IRQ2. My code will set the trigger to the edge rising. When the interrupt happens, I will quickly try to capture the state of Channel B (in my case this will be connected to P16). If this IO pin has a high value, then I know that this motor is currently going forward (as to respect to my robot) and I will increment a distance value. If the value is low, I am going in reverse and will decrement the distance value. I will do the same with the second encoder, however since the motors are pointing opposit directions, the check for channell B being high or low indicating going forward will probably be reversed.

I have done similar code for the Wheel Watcher 02 encoders on a small workshop robot that used continuous rotation servos before on a Atmega16 chip and it was not always robust as the interrupt latency was to much and I had to resort to polling both channels. I am hoping that this won’t be the case here, but we shall see.

You might try implementing a similar approach for your encoder and see if it works for you.

Good Luck

if possible you want to trigger on both edges since the quadrature can move between two states just by moving that edge. you also want to be careful about how fast the pulses can arrive or you might spend ALL of your BAP time counting pulses. Ideally you would do this in assembly to minimize the time for the ISR to run.

Beat me to it. :slight_smile:

If you use an ONASMINTERRUPT you’ll be fine. I’m doing pretty much the same thing with a high density printer encoder wheel(amounts to 1200 dpi per inch of travel).

Yes, I will probably detect both edges of Channel A, if for no other reason to do some corrections. It will also up the resolution detection, although in the case of my Rover I am not sure how important that is, as the encoder is only so good as there is wheel slippage and the like. The fun with the pro will be that I am:

Processing WKP0-6 interrupts to intercept the hitec RC controller (on 0 both edges and on 1-5 only the falling edge). Plus I am also also handling the TimerA interrupt, plus HSERVO is active.

I am planning to implement this in ASM to minimize the overhead, like I did with TimerA. May need to enable interrupts in ASM?

Hopefully I will have the time to try it later today

Thanks for he responses. I looked over the manual provided with the basic atom pro and found that it does not really talk much about interrupts. From what i understand when something changes (in this case the state of an input pin) they force the program to go and execute another piece of code before they allow the program to go on. What i was wondering was how do i specify if i want the interrupt to trigger in the rising or falling edge? I looked at the manual for the H8/300 series micro and it went over interrupts in more detail; however, it did not do anything like providing code samples or something so i am kinda lost. I understand how to enable them, and how to use the ONASMINTERRUPT command. What is the best way to actually count the pulses? Should i just redefine a variable by adding one each time the interrupt triggers or is there a better/more efficient way to do this?

You are right that there is no one place in the manuals to find all of this information. However you can grab most of the information from a few different threads in this forum:Inline Assembly…, HSERVO Command…, External Interrupts on Atom Pro" Also in the Biped forum, you can grab a lot of information from the TV Brat thread.

There is a good example in the HSERVO Command, where AcidTech (Nathan), converted a WKP03 Interrupt that was written in Basic and gave the assembly language version. If you are new to interrupts and assembly language programming, I would recommend you first attempt to write this in Basic and if need be then later convert it to assembly language.

You have several choices on which pins you wish to connect the encoder to. But suppose you wisth to use the WKP0 interrupt which if you look at the table of interrupts is on P0. Then you would probably need something like (BASIC):

; in your data definition area...
lEncoder1Cnt var slong

; have this part at your code init area.
ONINTERRUPT WKPINT_0,handle_encoder1
PMR5.bit0 = 1  ;enables pin as WKP interrupt instead of normal I/O 
IEGR2.bit0 = 1 ;0 = Pin will interrupt on a falling edge, 1 to interrupt on a rising edge. 
ENABLE WKPINT_0

;
handle_encoder1
    enable        ; enable other interrupts as quickly as possible
    lEncoder1Cnt = lEncoder1Cnt + 1
    resume

This is a real simple version of the interrupt handler. If you were to do this as an assembly language version, you will find out that all 6 WKP interrupts are handled by one Interrupt, so if you are using multiple of these your function would need to determine which one it was. So for an assembly language version, I will show for IRQ2 instead, which is on P18 of the Atom Pro. The similar code would look something like:

[code]
lEncoder1Cnt var slong
…
ONASMINTERRUPT IRQ2INT, HANDLE_IRQ2
PMR1.bit6 = 1 ; enable pin to IRQ2 interrupt instead of normal I/O
IEGR1.bit2 = 1 ; Interrupt IRQ2 on risigin edge

…
; Handle IRQ2 interrupt - We will have the encoder Channel A on this interrupt.
; - First pass we will only handle the rising level
; - later we may try to handle the falling as well
BEGINASMSUB
HANDLE_IRQ2
push.l er1 ; first save away ER1 as we will mess with it.
bclr #2,@IRR1:8 ; clear the IRQ2 bit in the interrupt pending mask
andc #0x7f,ccr ; allow other interrupts to happen

mov.l @LENCODER1CNT:32,er1		; increment our count of encoders we have seen
inc.l #1,er1
mov.l er1, @LENCODER1CNT:32
pop.l er1

rte
ENDASMSUB[/code]

Now again once you have either type working like this, then you might want to process the other edge of the channel. You can do that by changing the appropriate bit in the right control register for example for IRQ2, you would change the value of IEGR1.bit2, which controls if the interrupt happens on the rising or falling edge. Then when this is working, you can then start working with the second channel of the encoder.

Good Luck