Friday, January 5, 2018

Configuring Google Home to play music with iTunes

Welcome


This post explains how I configured a Google Home (GH) to play music through iTunes on Windows.  This makes the GH handle requests like "Hey Google, play Pentatonix Christmas" by playing the closest appropriate material in iTunes over our airplay speaker system (it doesn't play the music on the GH itself).  Here's a video of the system working:



Motivation


My family is heavily ingrained in Airplay, Apples proprietary system used to play to and sync many different speakers / audio systems.  We've got several Airplay speakers, and several Apple Airport Express's that are plugged into some old speaker systems that my Dad built.  On top of that, I've got every album our family has ever bought loaded onto iTunes on the home computer (running Windows 7), and that computer perpetually plays music throughout the house via Airplay.  Anyone in the family can jump on the iOS remote App to play music / adjust volume as desired.  The system works great (as long no one is using the microwave), and has for years.

Over Christmas, we got a new Google Home (thanks Fritz!).  If you ask the GH to play music, it will try to play internet radio through itself (it's a tiny speaker too).  After doing this once, it was immediately obvious to my folks and I that the Google Home should play through our iTunes & Airplay setup, and not through itself.  I found no way to do this correctly, so I hacked together a working solution.

Application Pipeline


The most time consuming process was determining exactly how to get from point A (GH verbal cue) to point B (play respective material through iTunes).  My original goal was have the GH talk directly to the iTunes computer over LAN.  I couldn't find a way to do that, so my goal shifted to minimizing the number of services the data would need to move through in order to get the job done.  This is the pipeline I arrived at:


IFTTT

IFTTT is a popular glue application.  It allows you to glue different apps / services you already have together.  Google Assistant supports IFTTT, so it's the first step in our process.  We'll setup several IFTTT applets to steal the GH commands play, play X, loudersofter, next, etc, and send them where we want them.

Push Bullet

IFTTT is great, but the only 3rd party support they offer is through WebHooks.  I didn't want our home computer to be facing the internet, so the IFTTT actions are all PushBullet notifications.  PushBullet offers an API where you can connect and fetch the latest notifications (or if you keep the connection open, they can be pushed directly to you).

My Own Application

This application connects to a PushBullet server, waits for a new notification, parses it, uses a bit of NLP to figure out what to play with iTunes, and plays the material in iTunes.  The application is written in C#, configured to boot on machine startup in the background, and communicates with iTunes using the very dated iTunes COM SDK.  The application is able to fetch all song / album / artist data from iTunes directly using the COM SDK, however there is no clean way that I'm aware of with the SDK to "play songs by Third Eye Blind."  The workaround is a designated playlist, called Automated, that we fill with songs that match our query and then play.

Follow my Footsteps


Start by making accounts for your Google Home, for IFTTT and for PushBullet.  Open the Google Home application and make sure your device is setup and on the network.  Now, open the IFTTT website, and we'll setup several different IFTTT Applets.  You'll need to sign in to Google Assistant and PushBullet within the IFTTT App.

IFTTT

Here are my IFTTT Applets.  Note the inclusion of "please" in front of reserved phrases like "play" and "pause".  Google typically doesn't let you override the standard home commands, but if you include the keyword "please", the API will let you override them, and in practice, you don't need to say please:


All of these use the Say a simple phrase (Google Assistant) trigger and the Push a note (Push Bullet) action.  The triggers can be whatever you want them to be, but if you're trying to use the software I've developed the actions have to identical to what I have.  The last Applet takes in custom phrases with the Say a phrase with a text ingredient trigger.  It uses the same Push a note action as before, but this time it includes the ingredient as a message for the notification.



You can test these without anything else setup, and if you've done everything correctly, the GH should respond with the correct reply.

Push Bullet

Log on to the Push Bullet website, go to settings, and click Create Access Token.  PushBullet will show a long key that corresponds to your account.  Copy it (or save it to a text file).  You'll need to enter it into my custom C# Application.

My Custom Application

Here is the installer for the most recent Windows Application.

Here is source code for the Windows Application. 

The iTunes COM SDK should be installed when you installed iTunes.  If you're having difficulties, make sure that iTunes is installed in the default directory.  I don't know how long apple will continue to support the iTunes COM SDK, but it at least works with iTunes 12.7.2.60 on Windows 7, 8, & 10.

When you run my custom application for the first time, you'll have to copy the PushBullet access token from into the GUI.  It should remember it in the future.  I've gone ahead and set the application to run on startup on our machine.  If it has a valid PushBullet secret, it will minimize itself shortly after launch to the taskbar (where you can only exit by right clicking and selecting exit).

That's it!


Good luck!


EDIT 1:

Push bullet accounts periodically expire (around every 120 days).  If the system stops working, try logging into PushBullet on your browser and trying again.

Wednesday, March 16, 2016

Hacking Torqueedo Outboard Motors


Welcome

If you are the proud owner of a Torqeedo outboard motor and are unsatisfied with the standard Torqeedo  remote throttle, you've come to the right place!

In this post I'm going to cover using a micro controller to interface with the Torqeedo hardware by mimicking the digital signature of the magnetic encoder in the remote throttle used to read the handle position...  I'll be skipping a few of the trivial steps, but I'll cover in detail most of the software and share some code.

white

Why Mimic the Encoder? 

Lack of better options.  Alternatives we've tried:
  1. Use a servo to manually rotate the throttle, or a magnet placed where the throttle would normally sit.
  2. Splice into the data line between controller and handle, try to reverse engineer Torqeedo's messages, use those messages to directly communicate with the motor without remote throttle.
While the first method worked, it did not provide the fidelity or response times we needed.  The second method proved fruitless.  Mimicking the encoder is sort of a happy medium between the two, you can communicate digitally, but you're doing so with a protocol pulled off a data sheet.

white

What Encoder?

Start by taking apart your remote throttle.  Unplug it and remove the dead man switch for good measure.  Then you'll want to open it like a clam shell:


I've already spliced the encoder lines on mine, so the cable is really long.  Your's probably won't be, so it won't want to open all the way.  You can pop off both the white and red plugs on the right side to give yourself some wiggle room.  Next take a torque wrench and remove the screw that holds in the encoder.

white

AS5045

Now let's take a look at that encoder.  This is the part we're going to be mimicking, so it's crucial that anyone following this guide verbatim has the exact same chip as us.  A cell phone camera might do a better job reading those small letters than you and your naked eye (I don't know who decided to use dark dark gray font on a black background).

I've pulled out two AS5045's from both our Torqeedo outboard motors.  Make sure your chips are the same.  I don't know anything about Torqeedo's product line, or whether or not the same product is guaranteed to have the same chip, but if you have an AS5045, you should be golden.

You can download the data sheet for the AS5045 here.  It's a fairly generic "12 bit rotary position sensor."  It's configured to communicate with the main remote throttle control logic via serial interface.

white

AS5045 to Remote Throttle Communication

There is a 6 pin gray and red ribbon cable that connects the AS5045 with the main control logic.  The cable connects the following AS5045 Pins:
  • Power
  • Ground
  • Digital Out
  • Digital In
  • Clock
  • Chip Select
We ignore Power and Digital In, and reroute Chip Select, Ground, Digital Out, and Clock to some breakout wires.  You'll need to cut the ribbon cable in half to grab these connections.  The wires are pretty small, and soldering them isn't easy, but the wire is braided so if you give yourself lots of room to work with you should be fine.  You can see what I've done on the right.  The color code is:
  • White - Ground
  • Gray - Chip Select
  • Purple - Clock
  • Blue - Digital out
  • Green  - Digital In (you don't need this wire)
  • Yellow - Power (you don't need this wire)
In the picture, ribbon cable red side is on the right.

white

Sanity Check

To verify the reverse engineered pinouts, I attached an oscilloscope to the encoder output while everything is connected as it originally was:



Here a you can see a gif of the SCL (green) and SDA (blue) lines for two different handle positions:

If you compare this to the SSI interface outlined in the AS5045 data sheet:



You'll see that this is exactly what we'd expect from the system.  This is good!  However,  SOMETIMES THE CLK LINE (owned by the remote throttle) DOES NOT CYCLE 17 TIMES.  On occasion,  the CLK will only fire 12 times,  and essentially ignore the last few bits of the encoder message.  What's not shown in the oscilloscope (due to lack of channels) is the CSN line, which we will use later to clear the remaining 4 bits from the write buffer on our micro controller when the CLK line exhibits this behavior.

white

Remove the Dead Mans Switch

Do this if you haven't all ready.  We'll have to calibrate the remote throttle before it's reasonably safe to turn the motor back on.  After you've cut the ribbon cable connecting the AS5045 to the remote throttle, try turning on the remote throttle.  You should see a E22 error message.  This represents a non responsive encoder.  This is good!  Keep going.

white

Mimicking AS5045 Digital Signature

For this part, I use an Arduino Due micro controller.  You're welcome to try other flavors, but many other products on the Arduino line were not fast enough to match the timing of the AS5045.  I don't use the built in Arduino SPI interface because it appears to only have a master mode, and not a slave mode (master implies control of the clock, which the AS5045 does not have).   

Beware that the Arduino Due is a 3.3V micro controller, so plugging anything 5V into it is catastrophic.  

Upload this code to your Arduino Due.  Note the pinout's listed at the top of the file:

 const int PIN_DAT = 49;  
 const int PIN_CLK = 51;  
 const int PIN_CSN = 53;  

There is a ground pin right next to 53, which makes it all easy access.  Again, you don't need to connect the lines that would attach to Power or DI on the AS5045 to anything.  Here is my setup:


Note the remote throttle is not giving me the E22 error message.  You'll have to restart the remote throttle with the arduino plugged in to clear any prior error messages.

You'll need to replug the cables into the remote throttle if you haven't already.

If your remote throttle does not give you the E22 message, you're all set to continue!  If you see an E21 error message, this is alright as we'll address this in the next section.

white

Calibrating Remote Throttle

The remote throttle maps the rotation values from the encoder to power output.  That relationship is unique for each remote throttle.  On one of our remote throttles, 0 was full reverse, 900 was neutral, and 1300 was full forward.  Torqeedo has a built in calibration process to set this number line.  We'll be setting 0 to full reverse, 1000 to neutral, and 2000 to full forward.  This is the value range the arduino will be sending to command the motor when we're all finished.

Read through these instructions, taken from the torqueedo manual:

Re-calibrate: Press "cal" button for 10 seconds

  • The display shows "cal up": Press tiller forward to full gas then press the "cal" button
  • The display shows "cal stp": Return tiller to central postion then press the "cal" button
  • The display shows "cal dn": Press tiller backward to full gas then press the "acal" butto
The "cal" button they are referring to is the "setup" button (leftmost button on the remote throttle).  Other than that, these are great instructions.  We'll be doing something similar, except that we'll be pressing each button when the arduino is sending the right message, not when the handle is in the appropriate place.

Now, you'll need to upload this code to your arduino.  This code will continuously send either the value 0, 1000, or 2000 to the remote throttle.  Which value is sent is indicated by the speed of the on board blinking led on the arduino.

  • 1 Blink per second: tiller forward (2000) is being sent
  • 20 Blinks per second: neutral (1000) is being sent

  • 2.5 Blinks per second: tiller backward (0) is being sent
The arduino should progress like the manual suggests: Full Forward to Neutral to Full Backward to Neutral and so on.  The arduino will progress to the next output every 15 seconds, which leaves more than enough time to complete each calibration step.

white

Testing

Upload this code.  Reattach your dead mans switch, and let her rip!  If everything went well, the program should comamnd sinusoidal output.  The active code looks like this:


void loop()
{  
  int current_time = millis();
  float seconds = current_time / 1000.0;
  motorValue = 1000 + 1000 * sin(seconds);
} 

You'll notice that the motor won't go as fast in reverse as it will forward.  I think this is a function of the internal logic on the remote throttle, and isn't something we can fix here.

white

Sending Relevant Commands



This is a video of my lab mate controlling two Cruise R 2.0's with a remote control.  You won't want to spin the motors fast for long, as it heats up and eventually destroys the internal bearings.

We had to use two arduino due's, one for each Cruise R 2.0.  We found that a single arduino due was only fast enough to mimic one AS5045.  Trying to simulate two AS5045's at the same time caused us to miss interrupts, and poison our connection with the remote throttle (all it takes is one bad reading for the remote throttle to get stuck on a E23 or E22).

For the same reason, you can't open a serial line to a computer with the Arduino Due.  The serial interrupts mess with the timing of the arduino due, causing us to miss clock cycles.

What you can do is: use a second micro controller to read values from a computer or other device, and then use analogRead() or pulseIn() on the due to transfer the signal from the other micro controller to the due.  Neither analogRead or pulseIn throw off our interrupt timing.

That's it.

Happy Boating!


Friday, March 4, 2016

I do a lot of quirky projects.  When I get stuck, I often turn to the internet for guidance.  Sometimes the internet comes up short.  I've started this blog with high hopes that people working on projects similar to me don't repeat my mistakes.  Take my knowledge, make it your own!