bitRead(PORTx,x)

Anyone care to give a brief "How-to" on this?

Need a replacement for the typical usage of:

if (digitalRead(2) == LOW) { stuff to do }

This takes too much time while I'm spinning an input Encoder... I'm seeing missed codes, resulting in unstable output decoding. I'm getting 80%+ accuracy, but I'd like it higher... and this looks to be a place for improvement.

The above code is right in the middle of reading the Quadrature codes... it's the encoder pushbutton monitor that will say "I'm done, you can save the existing value, and go away now"

My specific pin that I'm monitoring for this is named Pin2 (just after RX, TX, 2, 3, 4-7) on the ATmega 1280 I believe that to be PORTE, bit 4 (0-relative)

My questions is can I do this to replace the original "digitalRead": if (bitRead(PORTE,4) == LOW) { ...or do I need to break it down to multiple steps, which would still take less time that the interpreted "digitalRead"

Thanks in advance!!!

This takes too much time while I'm spinning an input Encoder... I'm seeing missed codes, resulting in unstable output decoding. I'm getting 80%+ accuracy, but I'd like it higher... and this looks to be a place for improvement.

Is there some reason to avoid interrupts? Encoders are generally read using interrupts.

My questions is can I do this to replace the original "digitalRead": if (bitRead(PORTE,4) == LOW) {

My question was what happened when you tried? Wouldn't that have been faster than posting here? No problems with posting here; I'm just curious why you chose that over trying the code.

Rotary encoders and interrupts:

http://www.gammon.com.au/forum/?id=11130

PaulS, yes, of course I tried… silly.

…and it does not work, where the original digitalRead does fine. It continues right on through it, as if it’s not there. I believe it may be due to “bit” versus “byte” comparisons, where I may need to some kind of bit compare… which I’ve not used before.

(I guess I’d ask why would I post a question if I didn’t need help?)

I have other timing and LCD-output issues going on, interrupts are not possible… been down that road.

(…which may be the root of my problems, not so much this single digitalRead… but I read it’s got a lot of overhead… so I was using it as a point to begin to optimize. What I learn here would apply to other places in my code)

My encoder reading function works, I’m just trying to improve its performance… as stated in my OP

Thanks

//------readEncoder-----------------------
                          /* returns only dir of encoder rotation click (-1,1) */
// original code (which works perfect as originally written and used with suitable encoder) from:
//    http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino 
                            
int8_t readEncoder()                           // "int" variable will be returned when all done
{  
int cw = 0;
int ccw = 0;
encOut = 0;
int temp;
  
int8_t tmpdata;

while (encOut == 0) {                              // while the decoder says "0" (not moving), keep trying

// THIS IS WHERE I'M TRYING TO IMPROVE THINGS  
  if (bitRead(PORTE, 4) == 0) ;                    // while encOut=0, loop until encoder knob is rotated/changed

// was  "if (digitalRead(enterPin) == LOW) {"      // digitalReads are slow, alternatives?


   tmpdata = read_encoderb();                      // calls the function, RAW from reader, not just +1 or -1

    if (tmpdata)  {                                // if tmpdata is non-zero, continue

      if (tmpdata == 1)  {                         // value of 1 is a CW encoder (half)click
        cw++;                                      // add 1 to my CW clicks counter, and
        if (cw == 2)  {                            // if we've had 2 (half)clicks...
          encOut = 1;                              // we can now set output 
          cw = 0;
          return(encOut);
        }
      }
        
      if (tmpdata == -1)  {                       // value of -1 means a CCW encoder (half)click
          ccw++;  
          if (ccw == 2)  {
            encOut = -1;
            ccw = 0;
            return(encOut);
          }
      }                     //close CCW detect    
    }                       // close "if (tmpdata)"
  }                            
   else {                   // exception to "if (digitalRead(enterPin) == LOW)", detected enterButton press=HIGH, do the following
     gotEnter = 1;          // set indicator that we HAVE seen the Enter button go HIGH
     return (0);            // return a +1 or -1 per encoder detent, except when "enter" button has been pressed
   }
}
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                       /* returns ANY change in encoder state (-1,0,1) */
int8_t read_encoderb()
{  
     static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
     static uint8_t old_AB = 0;

     old_AB <<= 2;                                 // remember previous state
     old_AB |= ( ENC_PORT & 0x03 );                // add current state
     return (enc_states[( old_AB & 0x0f )]);
}
//==========================

I guess I'd ask why would I post a question if I didn't need help?

My first thought is that you would have said that you tried it, if indeed you had. Since you didn't, I assumed that you hadn't.

My specific pin that I'm monitoring for this is named Pin2 (just after RX, TX, 2, 3, 4-7) on the ATmega 1280 I believe that to be PORTE, bit 4 (0-relative)

I'm curious how you got to 4. Pin 0 would be bit 0. Pin 1 would be bit 1. Pin 2 would be bit 2. At least, that's how I understand it.

Reading the PIN register is faster than a digitalRead.

ronbot: This takes too much time while I'm spinning an input Encoder... I'm seeing missed codes, resulting in unstable output decoding.

I think the problem is not how long the digitalRead() takes to execute, but how long a gap there is between calls i.e. the overall execution time of your polling loop. In order to read the encoder reliably you need to be certain of reading it at least once between each signal transition. From the physical characteristics of the encoder and the speed it's expected to move at you could estimate the shortest expected pulse width. Unless that is comfortably longer than your longest expected polling interval then the polling approach won't work. In that case interrupts would be the sensible option. Can you expand on why interrupts are not practical in this case? Maybe somebody can suggest a way around whatever-it-is that is stopping you from using them.

Kids these days…

I got my answer… in-house… from my 14 year old… all from memory… didn’t have to look up anything. :smiley:

replacing this: if (digitalRead(enterPin) == LOW) {

with this: if ((PINE & 1 << PE4) == 0) {

Works.

It’s incredible having a son who can not only “keep up with me” when I talk electronics, but has actually already surpassed me in some areas. I’ve got over 25 years in Electronics Design… had part in several start-ups that succeeded… one of them big (GARMIN - I was employee #11, got to see them grow to over 10,000 employees before I left)… and this boy picks things up so incredibly fast… even piano
http://www.youtube.com/user/beforebefore/videos (the oldest video was when he was 8(and NERVOUS), he started playing at age 6, and has now surpassed his teacher, who has a Masters, was a concert pianist… NOW WHAT??)

His first AVR project that he coded fully on his own used the ATtiny 6-pin version - put it in a 1000 lumen variable Li-Ion powered flashlight. I built the hardware, he coded it… it’s awesome, and fits in a regular 2-D cell ruggedness flashlight housing. We put a tiny sealed POT with its shaft extending through the rubber jacket, used it to tell the MCU what PWM to use for the MOSFET LED driver. We worked out the logarithmic scaling according to the human eye’s perception of brightness, etc.

His most recent code was for a hack board we made for my wife’s '08 Toyota Highlander Hybrid. The factory locks-out the Navigation user interface when you’re moving more than about 2MPH, and also blocks the DVD player from appearing on the dash screen… both limitations have been eliminated now, upon driver request. The Nav lockout can only be in “override” mode for a short time and still dead-reckon, or the GPS will get confused from lack of speedo input… so we have a timer which also flashes the LED in the pushbutton… blinking faster the closer you get to it timing-out and reverting to normal mode… so as to let you tap the button again if you need more time.

When he was young, he was FULL of questions… I’ve been in electronics since I was a child… so it’s all over my house. Whenever he’d ask some deep question… like how does electricity make a light bulb work? …or better… when he was 6-ish “how does a computer work?”… and I >NEVER< took the easy way out by saying “it’s too complicated”. I’d explain it, no matter if I doubted he’d understand or not… but usually he would not stop asking additional questions until he did.

Now he’s asking questions like “What kind of a receiver pre-amp design would be needed” for this 100kHz to 1GHz DSP FPGA multi-mode radio receiver he’s getting ready to build. He’s already got the VCO, PLL and Mixer designed (mostly in his head)… but he doesn’t like it when he askes me a question, and I have to tell him I’ve never done that kind of work… but he’s so hungry he’ll go and read ANYTHING it takes to find out.

The stuff that stops him is when it gets to the “art” of the design… the part where theory leaves off, and “doing” takes over… like when you get above a few hundred MHz, and things start mis-behavin! (like when a simple capacitor can turn into a series resonant LC tank due to it’s own length!)

This, my friends, what happens when you pray during pregnancy “God, make him someone who will glorify You”… and the God you pray to answers. God told me what to name him, well before birth… Samuel… “God has heard”.

(sorry if this offends, but I’m a pastor now, and not afraid to talk about my God, and his son, Jesus)

It's good that it is working, and very good you are encouraging your son to learn.

At faster speeds though, you will probably find that an interrupt will catch things reliably, especially if you are trying to do other stuff at the same time.

http://www.gammon.com.au/interrupts

Might be a good exercise for your son, interrupts are pretty cool. :)

The factory locks-out the Navigation user interface when you're moving more than about 2MPH, and also blocks the DVD player from appearing on the dash screen... both limitations have been eliminated now, upon driver request.

I trust your wife doesn't watch too many DVDs whilst driving. :P

She’d rather we didn’t mess with her vehicle… actually. She allowed it since it was just before a cross country trip we took… and since our older one (Sam) sits up front sometimes, we thought it might be useful… but as it turned out, the DVD hack it didn’t get used… but the Nav hack did. (the factory DVD player is roof-mounted, so it’d be hard for the driver to get at alone)

Our next hack on the HiHy might be to modify a couple of temp sensors… to allow for earlier ICE engine shut-down… more traction battery usage, higher mileage. It’s not too bad though… 4700 pounds, 7-seater, gets 26+MPG highway, 28MPG city. (real life) At times on our trip we got up to 29MPG at posted limits of 65-70MPH. The traction battery doesn’t help much on the level open highway though… mainly in-town or climbing hills.

back to the project at-hand… :slight_smile:

BTW... I'm a firm believer in interrupts... have used them in other projects, this one just didn't lend itself to it. :-)

Smart kid, congratulations!