¿ªÔÆÌåÓý

Re: uBit Encoder


Jack Purdum
 

Not really. Pin interrupts use the attachInterrupt() function which simply puts a wrapper around the messy details that requires using bit masks. External interrupts have their own interrupt vectors. This means that the Interrupt Service Routine immediately knows which pin caused the interrupt. Pin interrupts share an interrupt vector, which is the reason bit masks are used. Bit masking is necessary to figure out which pin caused the interrupt. I suppose external interrupts are a couple of micro instructions faster, but rarely would it be noticed.

Jack, W8TEE



From: K5ESS <k5ess.nothdurft@...>
To: [email protected]
Sent: Saturday, March 3, 2018 7:00 PM
Subject: Re: [BITX20] uBit Encoder

Jack,
Is there a reason to avoid using pin change interrupts with an encoder?? It seems no one uses this method in lieu of polling.
Mike
K5ESS
?
From: [email protected] [mailto:[email protected]] On Behalf Of Jack Purdum via Groups.Io
Sent: Saturday, March 3, 2018 4:38 PM
To: [email protected]
Subject: Re: [BITX20] uBit Encoder
?
Mike:
?
I'm currently working on a project for the ?BITX and I need quite a few of the I/O pins and I'm already at about 50K of code space and not done yet. It also uses two encoders, both driven by external interrupts. As you know, the Nano only has two external interrupts, the Mega has five. Anyway, I couldn't attempt what I'm doing without the Mega.
?
With the Arduino IDE, the default integral data type is a 2-byte int. If you are using a variable for frequency, you need numbers that would overflow the default int data type. (The max number for an unsigned int is 2^16, or 65,536. A regular signed int is half that. Neither is big enough for any HF band.) You need a 4-byte long data type. Since frequencies are never negative, most programmers would used an unsigned long data type for frequency. So you would see something like this in the code:


?? unsigned long frequency;
?? // ...insert several hundreds of lines of code here...

?? frequency = 7000UL;??????????? // Tell the compiler this is an Unsigned Long data type, just to make sure


Quite honestly, the compiler is smart enough to make it the correct data type anyway, but the trailing "UL" type specifier documents for anyone who is reading the code that frequency is an unsigned long data type. Otherwise, since the definition of frequency is several hundred lines earlier in the program, the programmer couldn't be sure if it is an int or a long, or unsigned long.
?
Inheritance and polymorphism are words designed to scare people away from programming so wages remain high for the fearless. Inheritance allows you to extend the definition of an existing object. For example, an investor came to me several years ago to write software for their real estate investing. I define an object named building, which had variables for property taxes, mortgage, square feet, type of utilities (e.g., gas or electric heat), etc. Every property he owned had those building characteristics. However, he had commercial buildings, residential buildings, and vacation rentals. Commercial buildings have unique characteristics: parking spaces per square foot, bathrooms per square foot, handicapped parking, etc. Residential had bedrooms, pool, enclosed garage, air, lot size, etc. Vacation rentals were bedrooms, but also beds per room, waterfront, water view, etc. What I created were three property objects (commercial, residential, vacation) that inherited all of the characteristics of the building object. This allows me to "reuse" information from one object by allowing new objects to inherit its characteristics.
?
Polymorphism allows me to use a common function name for two different tasks. It derives from the Greek for "many shapes". Consider, for example, that I have a function named ReadEncoder() and that one encoder can be used to either read frequency values or it can read several other types of data. The first line two of them might be:
?
? ?? int ReadEncoder(int dir)
?? {
????? // code that details what this function does...
?? }
?
?? unsigned long ReadEncoder(int dir)
?? {
????? // code that details what this function does...
?? }
?
Note that the first function definition returns an int data type from its use. The second one returns an unsigned long from its use. Whatever comes before the function's name (e.g., ReadEncoder) is called the function type specifier. That is always followed by the function name. The third part is call the function parameter list. Both versions of the ReadEncoder() function have the same parameter list; an int named dir. Collectively, these three things form what's called the function's signature. Polymorphism simply means I can have two (or more) functions sharing the same name as long as either the function type specifier, the parameter list, or both are different. Once the compiler knows each function's signature, it can always generate code so the proper function is called even when they have the same name
?
??? frequency = ReadEncoder(myDir);
??? wpm = ReadEncoder(myDir);
?
Because the compiler knows that frequency is defined as an unsigned long, the first line above cases the compiler to invoke the second flavor of ReadEncoder(). Likewise, if I'm changing the word per minute in the program, the compiler knows that wpm is an int, so it will call the first flavor of ReadEncoder().
?
Read this email several hundred times and it will make sense...
?
Jack, W8TEE

From: Michael Hagen <motdog@...>
To: [email protected]
Sent: Saturday, March 3, 2018 4:30 PM
Subject: Re: [BITX20] uBit Encoder
?
About running out of memory..
I built a super Raduio PCB with an Mega 2560 Pro.? It has 256K and 14 connectors.? I had it in my uBit radio.
But it is overkill, seems like these radios don't need more memory than Nano if there are good coders like you out there?
The CEC code seems to do more than I would ever want and still fits Nano.
With about 70 pins of I/O connectors with nearly none hooked up, my RaduinoXP is just overkill.
It would make a nice controller for something.? I have over 40 pcbs left.
I have not looked why uBit did not use interrupts on the encoder.? They must have needed more pins?
I have a new uBit Raduino now with 16 more I/O bits (I just announced it today), so maybe I will look at moving
some functions around free up the interrupts?? I have not looked at the encoder code in uBit,
I have a hard time figuring out the CEC code, so much stuff just dealing with eeprom.
My C skills are limited, the extended stuff in + is past me.? Terms like Polymorphism and Inheritance gag me.
So I am going to work on understanding the CEC code, since I need the education, it seems to work, and he will keep it updated.
I followed some of your links on encoders.? I used several of them before.

Your commented on Libraries.?? I wish they would explain things better in a text file.? Sometimes I don't even know
the input and output parameters of their functions.? They use C++ terms I don't know about.? Guys like Jack taught C at college level and is a PHD, he has tried to explain a few things to me, I gave up.?? I still don't know why, when I make a variable a UL, when I declare it, I still have to use UL at the end of a value when I move it to the variable.? The compiler should know what to do, since I declared it that way?? I was presented an example where it would error?
Well off to more Ubitting!


Thanks for the help,
Mike
?
On 3/3/2018 12:41 PM, Arv Evans wrote:
Mike
My simple LED fixture for evaluating encoders is built on a socket strip and
powered by a 9V battery lead.? It does not get used very often so keeping it
simple and inexpensive was the objective.
Writing my own encoder decoding routine was mandated when I purchased
some encoders from an Ebay supplier and found they did strange things.?
This is when I built the LED based evaluator and learned about using interrupts
to track state changes.?
I am not a C++ expert but sometimes it feels like the pre-coded libraries do
not get optimized as much as they should during the compile process, resulting
in code that is larger than when I write my own function calls to do the same
thing.? This is only a problem when working with an almost full AVR or Arduino
but it just feels right to know that executables are as compact as could be.?
Arv
_._
?
On Sat, Mar 3, 2018 at 11:21 AM, Michael Hagen <motdog@...> wrote:
Thanks Arv,
I have always used interrupts, and use it on BitX40.? I can't use some of the features of Allards software, because I only
re-wrote the code changing frequency.
I like the interrupt method because I can change the frequency in the interrupt or set a flag.
Not much delay and missing action.? I made a couple of signal generators too using interrupts.
I used the Rotary Library that is out there.? Used the 2 interrupt pins.
But why they did not use them on uBit?
But now I want to run the great software KD8CEC for uBit.? He a code Wizard!
So not wanting to change CEC, I want to find the correct encoder the works with his code.?
So far out of a dozen encoders I have of 3 types, only the stock encoder seems to function correctly.
I knew I had ones the pulse per step is different.
I did look at the signals with a scope, but will go through you supplied information.
Maybe I can come up with a test fixture to sort out my assortment of encoders.
Thanks, Mike
?
?
On 3/3/2018 10:00 AM, Arv Evans wrote:
Mike? WA6ISP
Rotary encoders can be a pain to work with, but in reality are quite simple.
If we assign the two outputs as out-A and out-B then rotation in either direction
will show phase offset between them depending on direction of rotation.?
But of course you already know that.?
It is relatively easy to write your own encoder decoding software for Arduino/AVR
systems.? Problem comes when we try to handle an encoder and do other things
at the same time.? Capturing an encoder output in real-time is difficult to do because
it blocks the performance of other activity.? This is why we usually use an interrupt
routine to watch for encoder steps while letting the software do other things at
the same time.?
This URL provides examples of reading encoders in real-time.? It works if you
do not need to have other tasks running in parallel with encoder sensing.
The URL shown below talks about using either real-time or interrupt based
reading of encoder outputs.?

To evaluate mechanical encoders you can usually devise a way to connect LEDs
to the out-A and out-B pins and observe the output states as you slowly rotate
the shaft.? This allowed me to determine that some of the Ebay sourced encoders
have one state change per mechanical detent and others have two state changes
per detent.?
FYI:? A code addition to swallow one state change allowed me to use the
two state change devices as one-state change devices.?
?
Once you have a good understanding of both real-time and interrupt methods for
reading rotary encoder outputs it is easy to include your own decoding routine
as a function call and avoid having to use libraries like encoder.h which may, or
may not, have unexpected results.? This also solves the problem of having a
profusion of encoder libraries with the same or similar names but different operating
methodology.?
Arv? K7HKL

_._
?
On Sat, Mar 3, 2018 at 10:37 AM, Michael Hagen <motdog@...> wrote:
I have experimented with several Encoders on uBit.
A few types on their own PCB with the pullups (10K) and a 5 Pin Header connector.
I get strange results with all of them.?? Takes more steps, like it is missing pulses.? In the interrupt routine in the Rotary Library I know there is a #define to fix the difference between models.? But uBit has its own routine using 3 analog ports (as digital).
I think someone supplied the one that comes with uBit.? It might be an Alps from Mouser??
Anyone remember that post or had experience with uBit and Encoders?
TNX & 73's
Mike, WA6ISP

?
-- 
Mike Hagen, WA6ISP
10917 Bryant Street
Yucaipa, Ca. 92399
(909) 918-0058
PayPal ID ?"MotDog@..."
Mike@...
?
?
-- 
Mike Hagen, WA6ISP
10917 Bryant Street
Yucaipa, Ca. 92399
(909) 918-0058
PayPal ID ?"MotDog@..."
Mike@...
?
?
-- 
Mike Hagen, WA6ISP
10917 Bryant Street
Yucaipa, Ca. 92399
(909) 918-0058
PayPal ID ?"MotDog@..."
Mike@...
?


Join [email protected] to automatically receive all group messages.