Arduino, How-To comments edit

It’s been a while since I’ve worked on my Arduino project to create a Bluetooth keyboard. In that time I have been using my keyboard a little bit, but it needs some work, ranging from small tweaks to major overhauls. This post is to remind me how to do the small tweaks. Some of it will be very specific to my current setup.

The first thing I’m remembering, and this sounds really dumb but I had to relearn it, was that the Arduino needs to be on. I had assumed that merely plugging it into my laptop would have been enough, but nope. Fully powered on. Check. ✔

Now that the board is on, we can verify all of the settings in Arduino IDE, including making sure the correct board is selected and the correct com port is being used. For my setup Adafruit Feather 32u4 and COM3 are the expected values.

Select Board

Select Board

Select COM Port

Select COM Port

Now that the board is connected, to view debug output while it’s running you can open up the Serial Monitor with Ctrl-Shift-M.

My board has an guid of d7:63:b2:85:c4:24

Travel, Food comments edit

Thirteen days in France: ten based in Aix-en-Provence, then three in Paris. We ate a lot of duck, foie gras, crêpes, and pastries; tasted wine around Bandol, Cassis, and Aix; and packed in Roman ruins, Van Gogh, Cézanne, Picasso, and one very stubborn induction stove.

Where We Ate

Aix-en-Provence and Provence

Place My rating What I thought
Les Deux Garçons ★★★★☆ My pork with morels was a perfect “Josh” meal, and the white wine was very good. Ksenia’s duck was overcooked. Day 1.
Colde ★★☆☆☆ Underwhelming sandwiches. Day 2.
Jacquou le Croquant ★★★★★ Perfect duck confit. We went back for more, and everything was just as good the second time. Days 2 and 10.
Le Coquet — Grilled octopus for me; foie gras for Ksenia. They had run out of mussels and lemonade. Day 3.
Jardin Mazarin — Foie gras and kangaroo for me; truffle eggs and duck in cherry sauce for Ksenia. Day 3.
Crêpes Cidre et Compagnie ★★★★★ Tender crêpes, heavenly caramel, and a nice woman behind the counter. Day 4.
Le Petit Verdot — Artichoke and slow-cooked baby pork for me; foie gras and sea bass for Ksenia. We drank the 2018 Bodin white. Day 4.
Café le Verdun ★★☆☆☆ Mussels were OK, but kind of dry. Day 5.
Le Bistrot des Philosophes — Sea bream with crispy marrow bone for me; duck in fig sauce for Ksenia. Day 6.
Marie-Georgette ★★☆☆☆ Bland burger, lightly cooked and kind of cold. Day 9.

We also ate at market stalls in Aix and Avignon, made dinner at the Airbnb twice, and had a crêpe in Les Baux-de-Provence. The apartment’s induction stove put up quite a fight.

Paris

Place My rating What I thought
Paul — Quiche Lorraine, croissant, fruit tarts, and orange juice after landing. No complaints. Day 1.
Au Rendez-vous des Amis — A quick late lunch: foie gras for Ksenia, escargot for me. Day 11.
Auberge Nicolas Flamel ★★★★★ A fantastic tasting menu, a waiter with personality, and a chocolate ball that melted open when the hot chocolate hit it. Day 11.
Square Gardette — Onglet of beef and wine for me; white fish and Orangina for Ksenia. Day 12.
Au Bourguignon du Marais — Foie gras and beef bourguignon for me; escargot and cod for Ksenia. Day 12.
Mariage Frères — Soba salad and tea for me; salmon and smoky Earl Grey for Ksenia. Day 13.
Qui Plume la Lune ★★★★☆ Great five-course dinner and wine pairing. I loved the chocolate-and-chestnut dessert, though I wish we hadn’t ended with sweetbreads. Day 13.

The unnamed boulangerie breakfasts in Paris were a bargain: two of us ate for less than one hotel breakfast.

Where We Stayed

We made an Airbnb in Aix-en-Provence our home base for Provence. It had odd art, a terrace, and an induction stove I never want to cook meat on again. In Paris, we stayed at a hotel; breakfast down the street was a much better deal than eating there.

Wine and Tours

Fabien took us through Domaines Bunan in Bandol and Cassis Bodin on Day 4. The Bodin white was mineral and flinty. We tasted wines at Château Henri Bonnaud during a market-and-cooking tour on Day 5; the 2016 red Palette was really good. Pierre took us through Saint-Rémy, Les Baux, and Arles on Day 9.

Other Places We Saw

Around Aix, we explored Saint-Sauveur Cathedral, Hôtel de Caumont, Musée Granet, and Cézanne’s grave at Saint-Pierre Cemetery. In Avignon, we toured the Palais des Papes and the Pont d’Avignon, which I still think is the least bridge I’ve ever seen. Saint-Paul-de-Mausole, Les Baux-de-Provence, and Arles’s Roman sites filled our day trip.

In Paris, the stained glass of Sainte-Chapelle was magnificent. We also visited Atelier des Lumières, Père Lachaise, and the Picasso Museum. We walked around Notre-Dame after the fire, and finished with the Eiffel Tower and Louvre courtyard.

Day by Day

Ratings are out of five stars; a dash means I didn’t have a clear verdict.

Travel, Food comments edit

Breakfast from a boulangerie again: croissants, éclairs, and apple juice. Two mornings in a row, breakfast for both of us cost less than one breakfast at the hotel.

We finally made it to the Picasso Museum after ten years of waiting. Half the floors were closed, and the tickets were still full price. The half we saw was good, but that was disappointing. We walked through the Marais afterward and found plenty of very expensive boutiques. Ksenia found two shirts. At the museum shop, the cashier switched from English to French when talking with her.

Lunch was at Mariage Frères. I had a soba salad and King Chai; Ksenia had a salmon plate and smoky Earl Grey.

For dinner we went to Qui Plume la Lune, Jacky Ribault’s restaurant, for a five-course dinner with wine pairing. The amuse-bouches included a soft-boiled egg, a marinated cherry tomato in cucumber sauce with a little cuttlefish on top, and focaccia with sugar, thyme, and olive oil. The first course brought mussels with oyster sauce, cuttlefish, octopus, and a crisp kale leaf. Dessert seemed to go on forever: figs with vanilla mousse, meringue and blackberry sauce; a roasted whole fig with black-currant sauce; and chocolate with chestnut, which I loved. Then came little post-dessert sweets, including a passion-fruit pastry, chocolate square, and apricot jelly cube. Overall, the meal was great. We just wished we didn’t end with sweetbreads.

After dinner, we took the Métro to the Eiffel Tower. I was sad to see the whole area fenced off; we had to pass through security just to get close. Then we went over to the Louvre courtyard. Ksenia got yelled at by security when she started to cut through the empty security-rope area. They calmed down once I explained that we were just walking through, not trying to enter the museum.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 54, 2019-09-06

Notebook page 55, 2019-09-06

Notebook page 56, 2019-09-06

Notebook page 58, 2019-09-06

Notebook page 59, 2019-09-06

Notebook page 60, 2019-09-06

Notebook page 61, 2019-09-06

Travel, Food comments edit

Atelier des Lumières is a huge space where images are projected onto every wall. We saw Dreamed Japan, Verse, and Van Gogh. Very cool; I would recommend it.

Lunch was at Square Gardette. I had onglet of beef and wine; Ksenia had white fish and an Orangina. We walked around Père Lachaise Cemetery and saw the graves of Jim Morrison, Abélard and Héloïse, Chopin, Pissarro, and others.

For dinner at Au Bourguignon du Marais, Ksenia had escargot and cod. I had foie gras and beef bourguignon.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 52, 2019-09-05

Notebook page 53, 2019-09-05

Travel, Food comments edit

We woke up early for our last morning in Provence, ate everything left in the fridge, and headed to the train station. We picked up a croissant and quiche Lorraine for the ride. In Paris, we dropped our bags at the hotel and went down the street to Au Rendez-vous des Amis for a quick late lunch: foie gras for Ksenia and escargot for me.

We spent the afternoon wandering. At Mariage Frères we bought tea for gifts and ourselves. The stained glass at Sainte-Chapelle was magnificent. I had somehow forgotten all that stained glass. We walked around Notre-Dame but couldn’t get near it after the fire earlier that year. At Shakespeare and Company I found a Stephen Fry book called Heroes. Ksenia looked for a favorite Parisian boutique, but it seems to be gone.

Dinner at Auberge Nicolas Flamel was fantastic. The waiter had personality, and we both had the tasting menu; I added wine pairings. The amuse-bouches were a tiny chicken burger, gazpacho with melon foam, and a crisp rice flake with cheese. Then came duck liver foie gras with passion-fruit aspic, salmon tartare with mango and avocado, half a lobster over quinoa, and beef with mushrooms and pureed carrot. Dessert was a hollow chocolate ball filled with strawberries, whipped cream, and basil shaved ice. Hot chocolate poured over the shell melted it open to reveal the surprise inside.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 48, 2019-09-04

Notebook page 49, 2019-09-04

Notebook page 50, 2019-09-04

Notebook page 51, 2019-09-04

Travel, Food comments edit

We wandered the markets again. I found more Boney M records, but didn’t buy any. Several stalls had Birkenstocks, but none in my size. Lunch was leftovers—steak and eggs, then some pasta—and we had macarons before dinner.

We went back to Jacquou le Croquant for one more duck confit. We essentially repeated our first meal there: split foie gras, duck confit, and tarte Tatin. Everything was as good as the first time. An excellent last dinner in Aix.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 46, 2019-09-03

Notebook page 47, 2019-09-03

Travel, Food comments edit

We took a day trip with Pierre to Saint-Rémy-de-Provence, Les Baux, and Arles. Saint-Rémy was small and cute, with two main streets to wander. We grabbed a baguette and a croissant, then visited Saint-Paul-de-Mausole, the hospital where Van Gogh stayed and worked. Across the road stood a Roman mausoleum and triumphal arch built about 2,000 years ago.

We stopped for crêpes and a walk in Les Baux-de-Provence. I had La Savoyarde, with bacon, cheese, potatoes, and onions; Ksenia had an andouille crêpe. The village was a fortified town perched above some very nice views.

In Arles, the Roman amphitheater and theater are both still used. Arles has French bull races, where competitors try to snatch a ribbon from the bull’s horns—kind of like a golden finch, but less stabby than the Spanish version. I liked the maze of masonry in the town hall’s ceiling. We also saw Saint-Trophime, Le Café Van Gogh, and the site where Van Gogh painted another garden.

Dinner back in Aix was at Marie-Georgette, a fancy hamburger place. It was rather bland. My burger was lightly cooked and kind of cold; I should have ordered it medium-well instead of medium-rare. There just wasn’t much flavor.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 40, 2019-09-02

Notebook page 41, 2019-09-02

Notebook page 42, 2019-09-02

Notebook page 43, 2019-09-02

Notebook page 44, 2019-09-02

Notebook page 45, 2019-09-02

Travel, Food comments edit

After breakfast from the leftovers—potatoes, eggs, and fruit—we went to Musée Granet. The main museum had mostly Renaissance-era art, some Picassos, and a few Cézannes. I liked the extension better: late-19th- and early-20th-century works in an old church. Its layout reminded me of the Musée d’Orsay.

I got mango-and-lemon ice cream on the walk home; next time I’ll stick with lemon. A festival on the main drag was celebrating calissons, Aix’s almond candies, with bands, displays, and free little cookies. The military even came out to secure the sweets.

I took on the apartment kitchen again and think I won, despite banging my head on the low doorway while retrieving potatoes from the toaster oven. We ate foie gras de canard, roast rib eye, tomato and lettuce salad with garlic vinaigrette, roast fingerling potatoes, green beans, candied carrots, and mustard sauce. It was our first day in France without a single restaurant, bistro, or brasserie meal.

We also visited Saint-Pierre Cemetery to find Cézanne’s grave. The aisle markers weren’t particularly logical, but we found it on the right side of Allée 6, fourteen graves in, across from a distinctive grave marked François Labiński. From the grave we could see Mont Sainte-Victoire, a mountain Cézanne painted again and again.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 33, 2019-09-01

Notebook page 34, 2019-09-01

Notebook page 35, 2019-09-01

Notebook page 36, 2019-09-01

Notebook page 37, 2019-09-01

Notebook page 38, 2019-09-01

Notebook page 39, 2019-09-01

Travel, Food comments edit

We had breakfast at the market stalls. Ksenia got an apple-caramel crêpe; I got a savory one with egg, cheese, and sausage. I learned that I do not like andouillette. It’s the guts.

At Hôtel de Caumont, an old mansion was showing the Guggenheim’s Thannhauser collection of Impressionist art. Afterward Ksenia went wandering and shopping while I went home to make dinner.

The meal was OK. The two-burner induction stove was not. The burners were so close together that I could only fit one pan at a time, and each had small hot spots that made searing meat impossible. A pan overhung the controls, so the buttons were hard to reach and got nearly too hot to touch. There weren’t even knobs. To turn a burner off, I had to select it and then press through the settings. I wouldn’t cook meat on that stove again. Dinner was tuna steak with white-wine gravy, fingerling potatoes with garlic and herbs de Provence, and garlic green beans.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 27, 2019-08-31

Notebook page 28, 2019-08-31

Notebook page 29, 2019-08-31

Notebook page 31, 2019-08-31

Notebook page 32, 2019-08-31

Travel, Food comments edit

We took the train to Avignon for the day, browsed the indoor market, bought more salt, and wandered around. Lunch at a market stall was a ham omelet for Ksenia and sausage for me.

At the Palais des Papes, the tour handed us tablets that recognized where we were and showed the rooms as they once looked. They even knew when we’d entered the little side rooms. Pretty neat technology, and the castle itself was cool. I went into the small treasury room—about 15 feet square—with hidden floor compartments for storing valuables. From there we walked to the Pont d’Avignon, the least bridge I’ve ever seen. It stops halfway across the river. Great engineers! After the “bridge to nowhere,” the city started to stink. We wandered in the heat, stopped at Notre Dame for air conditioning, grabbed a street crêpe, and found some French children’s DVDs before the train home.

Dinner at Le Bistrot des Philosophes in Aix: Ksenia had gazpacho and duck in fig sauce. I had the sea-bream special topped with marrow bone—the marrow was crispy. We finished with lemon sorbet and Żubrówka bison-grass vodka.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 22, 2019-08-30

Notebook page 23, 2019-08-30

Notebook page 24, 2019-08-30

Notebook page 25, 2019-08-30

Notebook page 26, 2019-08-30

Travel, Food comments edit

Today’s cooking tour began at the market and Château Henri Bonnaud. We tasted the dry white Terre Promise, a 2018 white Palette that had spent time in oak, a 2018 Palette rosé, and a 2016 red Palette. The red was really good; Ksenia would like it.

Then we cooked. Ksenia chopped orange potatoes, carrots, basil, beets, and parsley. We made a beet salad, charred red peppers, tapenade, and rocket salad, with soup as the main course.

Dinner at Café le Verdun was mussels. They were OK, but kind of dry.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 20, 2019-08-29

Notebook page 21, 2019-08-29

Travel, Food comments edit

Breakfast at Crêpes Cidre et Compagnie was worth getting up for. Ksenia had apple and caramel; I had pear and caramel. The crêpes were tender, the caramel heavenly, and the woman behind the counter was nice. Lunch was bread, ham, cheese, butter, fruit, and wine from the market.

Our wine-tour guide Fabien took us first to Domaines Bunan in Bandol. I learned how they check sugar levels before picking the best grapes by hand, cool them immediately, and gently press them. Rosé gets a short time in contact with red-grape skins; reds stay with the skins for weeks and have to be stirred as the skins rise. The older vines have deeper roots. We also got the barrel lesson: smaller barrels exchange more tannins with the wine, while larger barrels slow that down as the wine ages.

At Cassis Bodin, white wine was the main event. It was mineral and flinty. We had about 45 minutes to walk around Cassis before heading back for dinner at Le Petit Verdot in Aix. Ksenia had foie gras and sea bass. I had the house-specialty artichoke followed by slow-cooked baby pork. We drank a 2018 Bodin white; the one we had tasted earlier was sold out.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 14, August 28, 2019

Notebook page 15, August 28, 2019

Notebook page 16, August 28, 2019

Notebook page 17, August 28, 2019

Notebook page 18, August 28, 2019

Notebook page 19, August 28, 2019

Travel, Food comments edit

We had sausage and cheese at the apartment before going out in search of morning crêpes and a walking tour. Our guide, Jérôme, took us along Cours Mirabeau and through the “city of a thousand fountains”—more like 130, he said. We saw the Four Dolphins fountain, Hôtel Maurel de Pontevès, the warm moss-covered fountain, Place d’Albertas, City Hall, and the buildings around Saint-Sauveur Cathedral. The courtyard at Place d’Albertas was made a little deeper to make it look nicer. Back at the cathedral, we could see how it had absorbed an older church, which in turn had incorporated a Roman temple.

Le Coquet was out of mussels and lemonade at lunch. Ksenia had foie gras and a mojito; I had grilled octopus. We bought soap, candy, and wine, returned to the cathedral, then took a classic French siesta at the apartment.

After another wander, dinner was at Jardin Mazarin by the Four Dolphins fountain. Ksenia ordered truffle scrambled eggs and duck breast in cherry sauce. I had foie gras and kangaroo. We shared white wine and a peach dessert.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 10, August 27, 2019

Notebook page 11, August 27, 2019

Notebook page 12, August 27, 2019

Notebook page 13, August 27, 2019

Travel, Food comments edit

We went straight to the market at Place Richelme for ham, cheese, cassis, strawberries, figs, tomatoes, duck-heart sausage, and herbs de Provence. A supermarket stop supplied the less glamorous essentials: tea, toilet paper, water, butter, sugar, and pepper. Back at the apartment, Ksenia fell asleep on the sofa. Not to be outdone, I lay down on the bed.

An hour later we went out for lunch. The sandwiches at Colde were underwhelming. Ksenia had the salmon; I had the ham. We spent the afternoon wandering the streets and shops, eating ice cream, and visiting the public library. Its front had three tall sheet-metal books: The Little Prince, The Stranger, and one I can’t remember. At a café, I had a Negroni and Ksenia had a cassis mocktail.

Dinner at Jacquou le Croquant made up for lunch. We split foie gras, both ordered duck confit—perfect—and shared a seasonal fruit tart. I didn’t expect the pear-and-coconut combination. Ksenia liked it, and I enjoyed the pear parts. We also split a 50-centiliter carafe of local rosé. Delicious. I highly recommend the place.

We walked home and had another drink on the terrace while planning the next day. We’d forgotten to buy wine, so we had Fanta. C’est la vie.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 6, August 26, 2019

Notebook page 7, August 26, 2019

Notebook page 8, August 26, 2019

Notebook page 9, August 26, 2019

Travel, Food comments edit

We landed at Charles de Gaulle at 7:37 a.m. local time, after an hour’s delay taking off because of some problem with an auxiliary power unit. Somehow we still landed on time. The line for customs was long, so we had breakfast at Paul in the train station around 10. I had a quiche Lorraine, a croissant, and fresh orange juice. Ksenia had two fruit tarts, cherry and apple, plus orange juice. No complaints.

Our train to Aix was the only car without air conditioning. The seats had two numbers apiece, depending on which way the car was facing. Seat 17 became seat 62 when the train changed direction, and the numbers were printed together as “6217.” We eventually sorted it out. Three hours on the hot train and a 20-minute Uber ride later, we reached our Airbnb. It was cute, with odd art on the walls. After nearly 20 hours of travel, all I cared about was a shower.

Dinner was at Les Deux Garçons. Ksenia had orange Fanta, good foie gras, duck magret that was overcooked, and a giant tarte Tatin. We split the appetizer and dessert. My pluma de porc noir aux morilles was excellent: tender, flavorful pork that wasn’t overcooked, a tasty sauce, and both button mushrooms and morels. It was a perfect “Josh” meal. The white Coteaux d’Aix wine was very good too.

Part of our August–September 2019 trip through Provence and Paris. Trip summary.

From the Notebook

Notebook page 1, August 25, 2019

Notebook page 2, August 25, 2019

Notebook page 3, August 25, 2019

Notebook page 4, August 25, 2019

Notebook page 5, August 25, 2019

Evolution

Today I was able to complete the first fully working prototype of my keyboard. It has 6 16mm arcade buttons – two each of green, yellow, and red – runs on a 350mAh lithium ion battery, and is completly wireless. It doesn’t even have a wire to charge it since I didn’t have enough space to mount the port in the case.

Build It

Mostly today was a build day. I had most of the code in place, so all that was left was to assemble everything. First I made a template on paper to figure out the placement of the buttons. I wanted to make sure that the arcade buttons were placed far enough apart so that I could fit the power button on the side. After a lot of measuring and some fiddling I settled on the below layout.

Step 1: Create a template

To be sure the spacing worked, I placed the buttons directly on the paper. This was the third layout I tried. Also, I originally planned on blue, green, and red buttons. After seeing them lined up, the blue and the green were too similar in color, so I swapped in the yellow buttons for some contrast.

Step 2: Check the layout

To be absolutely certain, I created a quick mock up a cardboard box. The layout was just right.

Step 3: Check the placement

To transfer the layout to the case, I taped the pattern to the top and drilled 1/16th holes in the center.

Step 4: Place the template

Forstner bits were used to drill out the 16mm holes for the buttons. It took me a little bit to get the hang of drilling the holes. Sometimes the drill caught on the plastic and scratched the surface of the case.

Step 5: Drill holes

The wires took up more space than I expected. It would have been helpful to daisy chain all of the grounds across a common wire, removing half of the wires needed. Also, the rest of the wires could have been cut much shorter or routed around the edge of the enclosuer, taking up less room.

All of the wires terminate in a breakout FeatherWing.

Step 6: Wiring

The fit was tight enough that I didn’t need to mount the feather to the case. The wires held it in place with little to no movement when the bottom was screwed on.

Front View

You can see the power button on the side.

Side View

Code

With everything assembled it was time to test it out. And it didn’t work. After a little trial and error, I realized that the keyboard would only work if my laptop was plugged into it via USB and I had the Arduino serial monitor plugged in. Looking over my code a bit, I see that I still had a line of code at the very beginning telling the board not to start up unless it detected a serial console. Removing that fixed the first problem.

Next, whenever I pressed the volume down or up buttons for a brief moment, the volume would go all the way to 0 or 100. No in between. It registered as way too many key presses. Adding a small delay at the end of the loop solved this problem.

Here’s the useful command I used to create the thumbnails for this post: magick mogrify -resize 33% -path ./thumbnails *.jpg.

Feather

Today’s progress is a bit misplaced in the “Pi Project” folder. I wound up using my Adafruit Feather 32u4 Bluefruit LE to emulate a keyboard. Since this is exactly what it was designed to do, it really wasn’t that hard. Which means it took me a long time. My goal was to use a Bluefruit LE UART Friend connected to my Raspberry Pi. That was beyond my current skills so I decided to take smaller steps. The Feather has lots of samples doing exactly what I want to do, so I went that route.

The plan is still to go back to the Pi though since my end goal is to make a keyboard that gets updates from the computer it’s connected to and I assume it’d be easiest to do that with a restful API. But that’s for Future Josh to work through.

Working with several tutorials and code samples I was able to create a simple app that sends custom strings of keyboard codes to whatever device is paired.

Code

Below are the highlights of the application. First it declares the commands to send as constants, and then polls for button state and sends corresponding messages.

BLE Commands

Two types of BLE commands are supported, keyboard codes, and control commands. Keyboard codes are sequences of key downs (key ups are inferred by sending either the next code, or by sending a message with no codes). Keyboard codes are sent in a message that is up to 8 bytes long.

  • The first byte is a bit mask of any modifiers (shift, alt, etc)
  • The second byte is always 00
  • Bytes 3 through 8 are the keys to send

For example 08-00-07 is the command for pressing the Windows Key + D. 08 is the left Windows key, and 07 is the letter D (it’s case insensitive, if you want to have an upper case D, then also send shift).

As stated above, up to 6 keys can be sent at once. So to send abc, that would be 00-00-04-05-06. But then this would continue to send c repeatedly since we never sent the key up signal. To do that, just send an empty message with 00-00.

A complete listing of the keys can be found in section 12 here.

The other type of message that I’m sending is a control command. This is used to emulate media buttons like play, stop, and volume control. In my example I use it just for play (which will also pause). Adafruit’s sample code has a listing of some available commands.

Code Logic

Each loop of the main method polls the state of the buttons to determine which messages to send. It also records its state so the next iteration can either send the key up signal in the case of the keyboard codes, or to simply not resend the play command a second time (thereby pausing the music if the button is held down for more than a fraction of a second).

It’s all pretty hard coded now, but the idea is to have it evolve to be more configurable over time.

char CMD_MISSION_CONTROL[] = "01-00-52"; // (Left) Control + Arrow Up
char CMD_APP_WINDOWS[]     = "01-00-51"; // (Left) Control + Arrow Down
char CMD_SHOW_DESKTOP[]    = "08-00-07"; // (Left) Window + D
char CMD_VOLUME_UP[]       = "00-00-80"; // Volume Up
char CMD_VOLUME_DOWN[]     = "00-00-81"; // Volume Down
char CMD_VOLUME_MUTE[]     = "00-00-7F"; // Volume Mute
char CMD_F14[]             = "00-00-69"; // F14
char CMD_KEYS_UP[]         = "00-00";    // No keys held

void loop(void)
{
  int pressed = 0;
  int playPressed = false;
  if ( digitalRead(5) == LOW )
  {
    pressed++;
    printKeyboardCode(CMD_MISSION_CONTROL);
  }
  if ( digitalRead(6) == LOW )
  {
    pressed++;
    printKeyboardCode(CMD_APP_WINDOWS);
  }
  if ( digitalRead(9) == LOW )
  {
    pressed++;
    printKeyboardCode(CMD_SHOW_DESKTOP);
  }
  if ( digitalRead(10) == LOW )
  {
    playPressed = true;
    if (!playButtonPressedLastTime)
    {
      printControlKey("PLAY");
    }
  }
  if ( digitalRead(11) == LOW )
  {
    pressed++;
    printKeyboardCode(CMD_VOLUME_UP);
  }
  if ( digitalRead(12) == LOW )
  {
    pressed++;
    printKeyboardCode(CMD_VOLUME_DOWN);
  }

   if (pressed < 1 && buttonsPressedLastTime > 0){
    // send the key-up command
    printKeyboardCode(CMD_KEYS_UP);
  }

   buttonsPressedLastTime = pressed;
  playButtonPressedLastTime = playPressed;
}

 void printKeyboardCode(char keys[])
{
    ble.print("AT+BleKeyboardCode=");
    ble.println(keys);
}

 void printControlKey(char keys[])
{
    ble.print("AT+BleHidControlKey=");
    ble.println(keys);
}

Wiring

Close Up

Wiring is pretty simple for this device since it’s essentially made for this use case. I strung together 5 buttons with a common ground, and plugged each of the buttons into the pins 5, 6, 9, 10, 11, and 12. I have a Battery on order, and will wire up that and a power switch once they arrive.


I followed a mix of instructions, including Adafruit, and ElectronicWings to start playing with talking to and from my Raspberry Pi over a serial connection from my Windows Surface. I used a TTL cable from Adafruit.

Following are instructions for setting up communication between a Raspberry Pi 3 (not a zero) and a Windows laptop.

Setting up the Pi

First thing to do on the Pi is to turn of shell login via serial port.

  1. sudo raspi-config
  2. Select “Interfacing Options”
  3. Select “Serial”
  4. When asked “Would you like a login shell to be accessible over serial?” select no
  5. When asked “Would you like the serial port hardware to be enabled?” select yes
  6. Reboot the device

Next is to connect the cable to my Pi. My Pi was powered by USB already, so I didn’t connect the red (5v) wire to the Pi. Just hook up the wires up as follows, (or see the picture below).

  • Black -> Ground
  • White -> TXD
  • Green -> RXD

Wiring the Pi

Setting up the Windows Laptop

First step is to install the drivers on my laptop for the cable. I had the older version of the cable, so I needed the Prolific Drivers. There’s also a link to this from the Adafruit tutorial.

Now once the the USB cable is plugged into the laptop it will show up as a new COM port. To figure out which one it is either find it in the Device Manager or use the mode command.

Device Manager

>mode

Status for device COM5:
-----------------------
    Baud:            9600
    Parity:          None
    Data Bits:       8
    Stop Bits:       1
    Timeout:         OFF
    XON/XOFF:        ON
    CTS handshaking: OFF
    DSR handshaking: OFF
    DSR sensitivity: OFF
    DTR circuit:     ON
    RTS circuit:     ON


Status for device CON:
----------------------
    Lines:          32766
    Columns:        112
    Keyboard rate:  31
    Keyboard delay: 1
    Code page:      437

Notice that the mode command will also conveniently print out the baud rate (you’ll need this in the next step). This information is also available from device manager too by going in to the port’s properties.

Open up the serial port in PuTTY, using the COM5 port found above.

PuTTY

Connecting

Back on the Pi find the correct serial port. As I understand it (which is 90% likely to be wrong), on the Raspberry Pi 3, the UART port is going to be ttyS0 and the Bluetooth port (also serial) will be ttyAMA0. ls -l /dev will give you information about the ports.

$ ls -l /dev/serial*
lrwxrwxrwx 1 root root 5 Jun 22 15:12 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 7 Jun 22 15:12 /dev/serial1 -> ttyAMA0

From here echoing out a string in the Pi to /dev/serial0 will have it show up in PuTTY.

$ echo "hello world" > /dev/serial0

PuTTY

Travel, Food comments edit

Portland gave us books, doughnuts, beer, and a garden. Then we went down the Oregon coast and into wine country before driving north through Mount St. Helens, Olympia, Tenino, Tacoma, Gig Harbor, and Seattle. Nine days, two states, four wineries, and three wildlife stops: the Oregon Zoo, Wolf Haven, and Point Defiance Zoo & Aquarium. I saw many wolves at Wolf Haven, but I didn’t keep an animal count.

Where We Ate and Drank

Portland

Place What I thought Rating
Lardo Brisket grilled cheese for me; pork meatball bánh mì for Ksenia. —
Blue Star Donuts Raspberry-rosemary for me, an O.G. for Ksenia. —
Deschutes Brewery Portland Public House Lunch, mussels, pretzel, and a six-beer flight. —
The Tao of Tea Lavender tea for me, Assam for Ksenia, with a view over Lan Su Chinese Garden. —
Clyde Common My burger with duck confit was wicked good, even if the truffle got lost. ★★★★☆
St. Jack Oysters, pasta, foie gras, and bone marrow; the marrow was too oily. —
Salt & Straw Lavender-honey for Ksenia, “Berries, Beans, and BBQ Sauce” for me. —
Schilling Cider House Cider flight for Ksenia and tots for me. —
Breakside Brewery A final round after St. Jack. —

Oregon coast and wine country

Place What I thought Rating
The Wayfarer, Cannon Beach Fish and chips for Ksenia; local salmon and chowder for me. The beer was OK. —
The Dundee Bistro, Dundee Anniversary Pinot and shrimp pasta. —
Thistle, McMinnville Farm-to-table dinner after a full day of tasting; rabbit for me. —

Washington

Place What I thought Rating
La Petite Maison, Olympia French onion soup was a favorite. —
Wendy’s, en route to Seattle A quick lunch stop. —
Reckless Noodle House, Seattle We enjoyed the five-spice duck confit, though it was not spicy. ★★★★☆
Super Six, Seattle Hawaiian breakfast and Spam. —
Gertie and the Giant Octopus, Gig Harbor Tapas: good for a mall restaurant. ★★★☆☆
Smith, Seattle Brunch on our last day. —

We also had fried papas verdes at the Oregon Zoo, breakfast at our Olympia B&B, pizza on our last night, and snacks from Safeway.

Wine Tasting

We visited four wineries on June 5. There was a lot of Pinot.

Winery Wines and impressions
Erath 2015 Willakia Chardonnay, fruity and dry; 2018 Oregon Pinot Noir Rosé; 2014 Pinot Noir, very fruity, with blackberry notes; 2012 Pinot Noir.
Archery Summit 2017 Renegade Ridge, toasted marshmallow; 2017 Archer’s Edge Vineyard, a little like French Burgundy; 2016 Looney Vineyard; 2016 Arcus Vineyard; 2016 Red Hills Vineyard; 2016 Summit Vineyard.
Colene Clemens 2018 Rosé of Pinot, clean, crisp, tart; 2017 Chardonnay, clean and very nice; 2015 Margo Pinot; 2015 Adriane Pinot; 2015 Victoria Pinot; 2012 Adriane Pinot.
Fairsing Vineyard 2018 Rosé, floral and “strawberry lemonade for adults”; 2016 Chardonnay; 2017 Chardonnay; 2016 Pinot Noir, nicely balanced.

We bought two bottles of rosé for friends and a 2016 Chardonnay for Danielle.

Where We Stayed

In Portland: The Inn at Northrup Station, with a rooftop deck where we drank our first-night cider and beer. In wine country: Le Puy, a Wine Valley Inn, near Newberg (now The Setting Inn Willamette Valley). In Olympia: a B&B. We stayed with family and friends in Seattle.

Places That Stuck With Me

Powell’s City of Books, Portland Art Museum, and Lan Su Chinese Garden made for a very Portland beginning. I liked the calm garden tea break, and the repeated trips to Powell’s were inevitable.

Haystack Rock and the green drive down the coast led us to wine country. Mount St. Helens was cold, clouded over, and then suddenly clear enough for great views. Wolf Haven International was a highlight: many wolves. We also visited the Oregon Zoo and Point Defiance Zoo & Aquarium, then finished in Seattle at Ada’s Technical Books and Volunteer Park.

Day by Day