Decoding a Rotary Encoder

I recently acquired a rotary encoder to use as an input device for my hardware project. Knowing that such encoders make use of Gray code, I cracked open my Digital Design textbook and began coding a sketch for my Arduino. It wasn’t as straightforward as I had hoped.

This isn’t going to be a lesson in Gray code or rotary encoders — you can click the Wikipedia links above for that. This is intended to be a record of the lessons learned while trying to get a reliable, responsive read on the rotary encoder (herein simply “encoder” for brevity) that I have. Google turned up a lot of resources for reading an encoder with an Arduino, but there were a number of problems with them, including:

  • too complicated;
  • too much code (bytes of assembly);
  • too long (cycles); and
  • too unreliable.

Others were just flat out wrong.

From what I read, I decided that an Interrupt Service Routine (ISR) based on the changing levels from the 2 outputs from the encoder was the most reliable way of reading the encoder. Using basic Boolean algebra, I was able to come up with a simple expression to determine if the encoder was rotating clockwise. Where A and B are the previous state bits read from the encoder pins, and C and D are the current bits, the expression representing a clockwise movement can be represented in this truth table:

AB
00 01 10 11
00 0 0 1 0
C 01 1 0 0 0
D 10 0 0 0 1
11 0 1 0 0

The table can be reduced to the following boolean expression:
(A XOR D) AND NOT (B XOR C)

The Arduino code looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
volatile boolean rotating = false; 
static boolean rotating_cw = false; 
 
void rotEncoder() { 
  static byte old = 0; 
  byte in = PIND & B1100; 
  rotating_cw = (!!(old & B0100) ^ !!(in & B1000)) & ~(!!(old & B1000) ^ !!(in & B0100)); 
  rotating = true; 
  old = in; 
} 
 
void setup() { 
  DDRD |= B1100; 
  PORTD |= B1100; 
  attachInterrupt(0, rotEncoder, CHANGE); // ISR for rotary encoder 
  attachInterrupt(1, rotEncoder, CHANGE); // ISR for rotary encoder 
}

By way of a short explanation, the encoder is hooked up to digital pins 2 and 3 on the Arduino, and I’m using direct port manipulation for faster reads than digitalRead(). The bitwise math should be pretty easy to understand if you have done any real programming; the !! expression, however, is a little trick to normalize a truthy expression (non-zero) to 1 with minimal instructions.

Whenever you need to read the encoder, you just check the rotating variable, and, if true, then read the rotating_cw variable to see which direction the encoder is rotating. After reading, set rotating to false to get ready for the next read. It’s small, fast, simple, reliable, and usable in almost any programming application (save for those that require PD2 or PD3; but you can change the code to use any pin that can be used as an interrupt).

Here’s the problem: it’s too fast and too reliable! I was puzzled why my encoder was generating multiple rotations for each detent on the switch, even with fairly long delays between reads. I agonized over the math, the code, and my own sanity. Finally, by sending each read to serial output, I could see that, although the switch had 24 detents per rotation, each detent clocked a full 4 cycles of Gray code! What I really needed was to generate a rotating signal only once per detent.

It turns out the code for doing that is even faster, simpler, and smaller than the above code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
volatile boolean rotating = false; 
static boolean rotating_cw = false; 
 
void rotEncoder() { 
  byte in = PIND & B1100; 
  rotating_cw = in == B1100; 
  rotating = in & B100; 
} 
 
void setup() { 
  DDRD |= B1100; 
  PORTD |= B1100; 
  attachInterrupt(0, rotEncoder, CHANGE); // ISR for rotary encoder 
  rotating = false; // ignore the first reading, which will be false
}

Basically, I need only check for the ending state of the switch after landing on the detent. This requires checking only one of the lines for a signal change and ignoring all others when checking for rotation.

The moral of this story is that, despite using the same basic principles, different rotary encoders work differently, so check your data sheets or conduct signal tests like I ultimately ended up doing. If you’re interested in a function to handle the reading of the encoder without inspecting and manipulating the rotating and rotating_cw variables, here it is:

1
2
3
4
5
int readEncoder() { 
 int dir = rotating ? (rotating_cw ? 1 : -1) : 0; 
 rotating = false; 
 return dir; 
}

This will work with either of the two routines above. A call to readEncoder() will return 0 if the encoder hasn’t rotated, 1 for a clockwise direction, or -1 for a counter clockwise direction. This makes it really handy to keep a running counter based on the rotation of the encoder.

Sub’r Bowl Review: Jimmy John’s Gourmet Sandwiches

Although last week was technically half way through the Sub’r Bowl, due to the shop being in the “wrong” Division, I consider this week’s review of Jimmy John’s Gourmet Sandwiches to be the half way point. For some reason I was dreading a visit to the National Chain Over 1000 Locations Division, but sometimes it’s nice to be wrong.

We didn’t get to eat until really late this week, after 3:30pm. As such, the place was empty, and we got to order right away. Jimmy John’s serves “sub” and “club” sandwiches: while both varieties are served on 8 inch French bread rolls, the difference is that the club sandwiches have twice the meat. The staff told us that the most popular sandwiches were the Italian Night Club and the Beach Club sandwiches. Well, the Beach Club is some kind of California salad on a roll, but the Italian Night Club was right up our alley.

As is usual with most of the chains we’ve been to, there is a combo that includes chips and a drink. Greg made the comment that the most they can get on the sides was 3 points, and I jokingly said, not if they come in 12 ounce bags! The joke was on me, however, as the chips, while not sold in 12 ounce bags, were in fact 2.125 ounce bags, which are anywhere from one half to a full ounce bigger than the competition. That’s two servings per bag, if the nutritional information is to be believed. While it’s not enough to make them stand out in that category, it’s certainly worthy of some bonus points. Also, to Greg’s satisfaction, the soft drinks were Coca Cola products.

Jimmy John’s makes a monster sandwich. The French bread is freshly baked in the store, and it’s a really great tasting French roll. The problem for me is that I don’t really prefer French bread for a sub — it’s a little too crusty for me. Be that as it may, the sandwich itself is loaded with freshly sliced meat and cheese with the perfect amount of vegetables.

With the “club” sandwiches, there is double the meat of the “sub” sandwiches. Not only was there a lot of meat on the sandwich, but it was also very flavorful! It wasn’t just meat for meat’s sake, and it didn’t taste like a mishmash of cold cuts, like we’ve had in the past. You could really taste the different flavors of the meats on this thing, the mark of high quality cuts. For $5.49, this sandwich blows away the competition on taste, price and overall value.

As for the veggies, initially I thought there was too much lettuce, but when I opened it to remove some, I actually ended up taking off very little. There were ample roma tomato slices and just enough onion to be tasted without being overpowering. A welcome addition to the sandwich not present in the other’s we’ve tried was sliced red peppers. I also added hot peppers to my sandwich for a small fee, which were large and spicy but not overbearing.

A recurring theme for me is the complaint of too much mayonnaise on the sandwich, and Jimmy John’s is no exception. I understand the point of mayo — it keeps the bread from getting soggy by providing a fat layer. Heck, I put mayo on most of my own sandwiches at home where excess moisture is a concern. The problem is that I don’t like it oozing out of the sandwich when I bite into it. Nobody else in our group has ever expressed a concern about the mayo other than perhaps there being not enough, so maybe this is a personal preference, and I need to start asking them to go light on the mayo.

Another thing that was not really a problem for me but more of an observation was the amount of dressing on the sandwich. It had a really good flavor and didn’t really overpower the sandwich, but, my goodness, was there a lot of it! I had large puddles (plural) on my wrapper by the time I had finished eating the sandwich and had gone through half a dozen napkins trying to stay dry. This is definitely not a sandwich you’re going to eat on the go.

I rated the following categories:

  • Bread: 6
  • Sandwich Stuff: 6
  • Price/Value: 7
  • Non-sandwich Stuff: 3
  • Bonus points: 2
  • Total: 24 points

This past round saw some of the best and worst sandwiches we’ve had so far, with Jimmy John’s surprisingly topping the ratings for me to date. While we’ve still got almost half the contenders yet to review, it’s hard to see one of them topping these scores. I honestly never expected a large national chain to be at the top of the ratings chart, and it will be really interesting to see how things turn out in the playoffs!

See also:
Greg’s Review

Sub’r Bowl Review: Lenny’s Sub Shop

This week’s Sub’r Bowl review is for Lenny’s Sub Shop, which is actually in the same Division that we hit two weeks ago. We were supposed to be visiting a shop in the “National Chain Over 1000 Locations” Division, but this was actually my fault. I mistakenly thought Lenny’s was in that division (and I couldn’t be more wrong: only about 200 locations in 20 states), but in the grand scheme of things it’s not really that important, and we had a good lunch.

When we originally conceived the Sub’r Bowl, there was a convenient Lenny’s location right down the street from work, but they have since closed up shop. Whether they moved or closed the location entirely is unknown, but we found another location not too far away. When we got there it wasn’t crowded, but they were doing a pretty decent amount of business considering how late after lunch time it was. Their claim is that they serve Authentic Philly Cheesesteaks & the Deli Fresh Experience™. We weren’t there for the cheesesteak, so, true to form, we ordered the cold Italian sub.

You only have the choice of white or wheat bread, but it’s of the freshly baked variety. The rolls also quite large, what you might expect of a NY deli hero sandwich. I ordered my sandwich on white. The meat and cheese are sliced right in front of you, and there was plenty of both to balance out the bread. Of course I got everything on the sandwich, including hot peppers.

There is a combo that comes with chips and a drink, which I ordered with the sandwich. The chips are Lenny’s branded but otherwise standard deli chips, which include a salt and vinegar kettle chip, my standard choice. Their drinks are Coca Cola products, and, to my pleasant surprise, they had Cherry Coke on tap. Bonus points! The total came in a little over $8, about what we’ve been spending on average.

The bread was soft, a little chewy and a little crusty, but it tasted much like average white bread. Freshly baked, great tasting white bread, but not particularly a standout compared to other places with really great, freshly baked bread. In my opinion there was a little too much of it, but not so much as to detract from the overall sandwich — just a little too much for my personal preference. On the other hand, this is definitely the sort of bread that makes the perfect party sub, since it will hold up to smaller portions.

There was plenty of meat and vegetables, neither of which overwhelmed the other. The dressing had a nice vinegary bite to it, but there probably could have been a little more to offset the amount of bread. Conversely, there was a little too much mayonnaise for me, as white goop oozing out of a sandwich is a huge turnoff for me. The meat was better than average. Although it wasn’t the best we’ve had, there was a lot of it that you could really taste on the sandwich, and I felt it was a good value in terms of taste and price.

I rated the following categories:

  • Bread: 6
  • Sandwich Stuff: 6
  • Price/Value: 3
  • Non-sandwich Stuff: 3
  • Bonus points: 2
  • Total: 20 points

I don’t have a lot to say, good or bad, about Lenny’s other than they’re a pretty strong competitor in the sub game. One thing I will say, though, is that Lenny’s is the only place so far that I felt like I wanted to go back the next day. One of the other reviewers ordered the meatball sub, which he claimed must have been laced with crack because it was so good. That comment alone makes me want to go back to Lenny’s again to try it out for myself. That, and the Philly Cheesesteak. And the half pound hot dog. With a Cherry Coke.

See also:
Greg’s Review

Sub’r Bowl Review: Florio’s Pizza

For the second round in the Pizza Shops Division of the Sub’r Bowl we hit Florio’s Pizza. I’m a fan of their New York style pizza, but I’d never had any of their subs before. Greg had been going on since the beginning of the Sub’r Bowl about how he wanted to try Florio’s, not only because he loves the pizza, but also because he had heard the subs were good. Well, he finally got his wish.

We left a little earlier than usual for our lunchtime visit, and when we got there the parking lot was full. We had to park at the shopping center across the street, which wasn’t that far, but when we got to the shop the line to order extended outside the front door. Despite the appearance of the length of the line, it moved fairly quickly, and we were able to place our order within a couple of minutes. As usual, Greg and I split a sandwich, our standard Italian sub, and we each ordered the lunch special as a “side” — 2 slices of pizza and a drink.

I haven’t really written much about service since my first review, but the service at Florio’s was dichotomous. For starters, let’s just say the front office staff at Florio’s will not win any customer service awards. You’d better know what you’re ordering long before you get there, because, even before you get to the lady taking your order, an older gentleman will demand that you tell him what you’re going to drink. Right now. Hurry up, he hasn’t got all day. The lady taking your order isn’t much more patient or friendly, but fortunately you only have to deal with them on the front end of your visit.

On the other hand, the restaurant was quite busy and full, so they told our party of 5 to have a seat in the back room, which is normally closed and reserved for groups. That was pretty nice of them, and the room was nice and bright with plenty of room for us to sit. While it took a long time to fill the order (about 10 minutes), in fairness they were probably baking pizza to keep up with the lunch crowd. The lady who brought out the order, though, was all smiles and very friendly. The initial uneasiness from the front end rudeness was soon washed away.

Not learning a thing from my visit to Ray’s Pizzaria, I immediately went for the pizza. I’m not a connoisseur of NY style pizza, but I imagine that Florio’s must be the closest thing you can find in San Antonio. It was hands down delicious. Fortunately, unlike Ray’s, the following Italian sub was completely worthy.

The bread was a perfectly balanced, crusty and chewy sourdough roll. It was every bit as delicious as the bread from Boston Subworks, but with a completely different flavor. The inside of the sandwich was also quite good, but different in flavor from most of the other sandwiches we’ve eaten so far. The flavor reminded me of the western Pennsylvania hoagies I had eaten in my youth, so the good flavor mingled with a touch of nostalgia made the experience highly pleasurable.

The basic criticism I have about the sandwich is that, while it was very good, it did not taste like what I expected from an “Italian sub.” The meats were good and plentiful, but there wasn’t that salty meat flavor you expect from an Italian sub. While I personally prefer a sandwich dressed simply with vinegar and oil, as this one was, there wasn’t the usual flavor of the spices that make up an “Italian” dressing. Finally, I was missing the tang of peppers on the sandwich, which you usually find on an Italian sub, whether it’s from cherry, banana or sometimes sweet peppers.

Don’t get me wrong: the sandwich was outstanding, with the only real flaw being that there was too much lettuce, which is easily fixed with the flick of a finger. However, since I was expecting an “Italian” sub, and that’s not what I would say I got, I don’t feel I can give it full points. Based purely on taste, though, it was easily the best sandwich I’ve had so far in the Sub’r Bowl.

On a side note, Kelley ordered the meatball sub, which contained slices of a real, large, baked meatball. He said the meatball was not seasoned well enough, and it looked somewhat lacking in sauce, but I still want to give it a go someday. As for the rest of my meal, I had a regular fountain Coke to drink. I don’t know if refills were included in the drink price, but it turned out that I didn’t need one. I noticed that there weren’t any side items on the menu, though, save for a dinner salad, which I didn’t order.

I rated the following categories:

  • Bread: 7
  • Sandwich Stuff: 6
  • Price/Value: 6
  • Non-sandwich Stuff: 0
  • Bonus points: 2
  • Total: 21 points

If you can make it past the front counter, you’ll have a hard time finding better pizza and subs. Though not what I was expecting from an Italian sub, the sandwich was outstanding for what it was, and the pizza was excellent. Oddly, as we left, the attitudes of the front office staff seemed to take a 180, as they waved and told us thanks for coming and to come back soon. Though we have 2 more places to visit in this division, I think we’ll be visiting Florio’s again.

See Also:
Greg’s Review

Splitting a Path to a list in Python

At work today I needed to split a file path into it’s various directory and subdirectory components using Python. While the result of os.path.split can be inversed with os.path.join, they don’t do what you might intuitively think they do. A cursory search on Google, while turning up various and sometimes overbuilt solutions, didn’t give me a quick and dirty function to accomplish this task, so I wrote one myself.

In you look up the function definition, os.path.split works like this:

>>> os.path.split(filepath) == (os.path.dirname(filepath), os.path.basename(filepath))
True

The (not really) inverse function, os.path.join, could be more appropriately named os.path.concat, since it actually concatenates its path arguments into a combined path.

A coworker came up with this:

parts = filepath.split(os.path.sep)

However, calling os.path.join using the result will not return the original path if the path is absolute. You can get the original path back using:

 os.path.sep.join(parts)

But generally you want to manipulate the path in some way. A valid path like “/path/to//file” will return [ “”, “path”, “to”, “”, “file” ], which isn’t too helpful when you’re trying to deal with the different parts. Calling os.path.normpath first can help (generally a good idea when dealing with paths of unknown format), but you still end up with “” (an empty string) for the root directory.

Here’s my solution:

1
2
3
4
5
6
7
import os.path
 
def splitpath(path, maxdepth=20):
    ( head, tail ) = os.path.split(path)
    return splitpath(head, maxdepth - 1) + [ tail ] \
           if maxdepth and head and head != path \
           else [ head or tail ]

(code line split for easier reading)

Now “/path/to//file” will return [ “/”, “path”, “to”, “file” ]. You can also get the original path using os.path.join:

>>> os.path.normpath(filepath) == os.path.join(*splitpath(os.path.normpath(filepath)))
True

So there it is, mostly for my reference. Some other pedant might find it useful, too.

Sub’r Bowl Review: Firehouse Subs

The next visit in the Sub’r Bowl is Firehouse Subs. It’s the second shop we’ve hit in the National Chain, Under 1000 Locations Division. I had never been to one of these before, although I was aware of them, so I was interested to see what they had to offer.

When I first saw the menu, I saw a couple of choices that looked good, including the New York Steamer, which included corned beef brisket, pastrami, melted provolone, mustard, mayo, and Italian dressing; and the Italian, which contained the usual genoa salami, pepperoni, ham, melted provolone, Italian dressing, and seasonings. Since I had never been to Firehouse Subs before, I decided to depart from the usual and try something different, so I ordered the New York Steamer, plus the chips and drink that made it a combo meal.

This was the earliest we had ever gone to eat for the Sub’r Bowl, so we were in the thick of the lunch crowd. It took a good 5 minutes from the time of order to receiving the sandwich. Dave ordered an Italian, and Morteza, a newcomer to our office and guest participant, ordered the Smokehouse Cheese and Cheddar Brisket sandwich. Greg arrived a little later, after we had already received and eaten some of our subs. I offered him half of my sub in exchange for half an Italian that he would order. Kelley was absent from this outing.

Whether fairly or unfairly, I went there thinking I was going to get something a little better than Subway, because, in my thinking, if you’re going to go against the king in the national arena, you have to be better to keep people coming back. The sandwich was, to the contrary, quite disappointing on all levels. The bread was passable as something to keep the insides off your hands but was otherwise limp and flavorless. Unfortunately the insides fared no better.

First I ate half of the New York Steamer. I could barely distinguish that I was eating corned beef, and there was so much mayonnaise that I could hardly taste anything else. There was a lot of meat, but it was of really low quality with little flavor. The amount of mayo just turned it into a gross mess. Thank God Greg showed up by the time I was half finished so I could pawn off the other half of the sandwich!

I was really looking forward to trying the Italian, especially after the disappointment of the first sandwich. I looked at Dave’s Italian, and it looked really pretty and colorful, even though I already knew the bread was a throwaway. It’s served “Fully Involved,” which means it has mayo, mustard, lettuce, tomato and onion. However, when I finally bit into one, it was no improvement over the Steamer. It, too, was made of relatively flavorless, low quality meat, and the vegetables contributed almost nothing other than roughage. The Italian dressing was sickeningly sweet, with no tartness from vinegar that I could taste. And the seasonings? They must have been for show only, because they were seen but not tasted. Altogether it was pretty much a disaster, and only hunger permitted me to finish the sandwich. Greg left most of his uneaten.

What went wrong here? I estimate that the ingredients are no better or worse than those used by Earl of Sandwich or Subway, but both of those managed to turn out pretty decent sandwiches. In the case of Earl of Sandwich, they had a much superior bread, and they add different unique sauces to each sandwich to give them a distinctive flavor. At Subway, you pretty much have only yourself to blame if you don’t like the taste, because, other than the basic meats you’ve ordered as part of the sandwich, you tell them what you want on it. I left Firehouse Subs feeling like I had the submarine special from the school cafeteria, but even more disappointed because I at least expect cafeteria food to be pretty low grade.

You have pretty much your choice of chips just like at Subway — a selection of Frito-Lay products including Miss Vickie’s (which you may or may not know is also Frito-Lay). The drinks were fortunately Coca-Cola products and iced tea. So there isn’t anything special there, but for a total of about $8 for a medium sub, chips and a drink, it wasn’t a bad price to pay for lunch. However, because of the poor sandwich, I hesitate to say it was a good value for your money.

I rated the following categories:

  • Bread: 3
  • Sandwich Stuff: 0
  • Price/Value: 3
  • Non-sandwich Stuff: 3
  • Bonus points: 0
  • Total: 9 points

I didn’t feel like the bread should have rated so high, but there is nothing between 0 and 3, and I felt the sandwich deserved something other than 0. At least it reflects that the bread was better than the filling, and the sub wasn’t completely inedible, after all, just not enjoyable except by the truly starving. Personally, I hope I never have to go back to a Firehouse Subs ever again.

See also:
Greg’s Review

Sub’r Bowl Review: Boston Subworks

The naysayers of our group didn’t think it would last 2 weeks, but this week marks the beginning of round 2 of the Sub’r Bowl, bringing us back to Division C, local sandwich shops. We decided on Boston Subworks, my favorite place in town for a cheese steak sandwich.

Due to a high pressure deadline at work, we didn’t get to the restaurant until after 3:30pm, which we found out is near closing at 4pm. At one point I know there they were open later on week days, but apparently they decided it wasn’t worth extending past the lunch crowd. Luckily for us they were still open, because we were all really hungry after having worked through lunch.

Kelley had arrived ahead of us, and his cheese steak was coming out just as we arrived. Though I really love the cheese steak sandwiches at Boston Subworks, I decided to try something from the Specialty Subs portion of the menu since this is, after all, the Sub’r Bowl. Greg and I combined our order to get a large portion of The Supreme Italian, which we spit in half. We ordered it all the way, except for cherry peppers, which I put on my half alone. We also ordered a couple of sides, Mozzarella Cheese Sticks (which is technically an appetizer) and Seasoned French Fries.

Predictably, Kelley enjoyed his cheese steak. Though I don’t remember what Dave ordered, he seemed unimpressed with his sandwich. Greg declared the sandwich to be tasteless, complaining that there wasn’t enough meat, while envying that of Kelley’s cheese steak sandwich (insert off-color joke about meat envy here — we did). Though I had the exact same sandwich as Greg, albeit with the addition of cherry peppers, I couldn’t disagree more with him on the taste of the sandwich.

The bread was by far the best bread we’ve had. It was a delicious baked white roll, nice and crusty on the outside while perfectly soft and slightly chewy on the inside. The insides were a perfect balance between meat, veggies and dressing. Maybe it’s because I’m a supertaster, but I felt that because no single ingredient dominated, the sandwich had great depth of flavor. Every other sandwich I’ve had so far had some dominant flavor that pushed the others to the background; to me, this sandwich had just the right amount of each ingredient so that the flavors all played off each other to create a nearly perfect overall taste. My only criticism is that the quality of the meat was a mixed bag. Some cuts like the roast beef were really good, while others were fairly run of the mill.

Everyone agreed that the sides we ordered were top notch. The Mozzarella Cheese Sticks had a nicely flavored breading and plenty of gooey cheese inside. The dipping sauce was a very tasty marinara sauce, clearly not from a jar. The Seasoned French Fries were obviously cut and fried from non-frozen potatoes, and they had the perfect deep fry: golden brown and crispy on the outside, steamy and fluffy on the inside. The seasoning was excellent, so no ketchup was desired. To drink I had some iced tea, which was not notable in any way other than it tasted like tea.

I rated the following categories:

  • Bread: 7
  • Sandwich Stuff: 6
  • Price/Value: 3
  • Non-sandwich Stuff: 6
  • Bonus points: 0
  • Total: 22 points

If I had bought my meal separately instead of splitting a sandwich with Greg, I figure it would have cost me $10-11. While the food was really good, that’s a lot to spend regularly on lunch. Aside from that, I feel that the sandwich from Boston Subworks is easily the best I’ve had so far. The others in the group accused me of using hyperbole and artificially inflating my ratings. I respect that they didn’t enjoy their sandwiches, but for me Boston Subworks was a real winner.

See Also:
Greg’s Review