loading

DIY Android Ball Maze - An Introduction to the Android ADK

FeaturedContest Winner
Introduction
If you're reading this article you're probably like me: I go through phases where I get so engrossed in a project (which most others would see as trivial), so focused on the goal that sleep and food are afterthoughts, I put my body through a gauntlet to appease some primitive urge of mine to CREATE.

Such was the beginnings of this project. I attended Google I/O 2011 and managed to get my hands on an Android ADK demo board. ADK is the Accessory Development Kit , an Arduino-based interface board whereby you can connect your compatible Android device (2.3.4 and any device from 3.1 onwards) to virtually any hardware and use the phone to control a device, or vice-versa.  It's called the Android Open Accessory platform, and it's totally cool.

To introduce the concept to the Google’s keynote speech they produced a regular ball maze toy , familiar to many, which was controlled by a Motorola Xoom tablet.  This Instructable is kind of two instructables in one: first, I'll be illustrating the steps required to set up the ADK from scratch and then I'll be reproducing Google's ball maze on a Nexus One phone to demonstrate a simple use of the ADK board (I'll keep the massive bowling-ball version for another Instructable). 

So continuing with my story: I grew up with a ball maze, my parents had one as far back as I can remember. A little while after I got home from Google I/O I found the maze at my parents’ house and shortly thereafter I discovered I had everything I needed to make my very own Googley maze controlled by my Nexus One.

[Lights on, cue primitive one-tracked mind]

The goal was set: I had one night to make this from scratch, hardware and software. I'd never written a real-world Android app before (not that this is very real-world yet...), but I was convinced that it couldn't be too hard. I worked from 7pm to about 5am, though I probably could have done it in 2-4 hours if I had an Instructable like this to start with - being my first ever Android project, much of that time was reading!

Only the Nexus One (Gingerbread 2.3.4) has been tested with the code I'm supplying, but it should work with little to no modifications on a stock up-to-date Nexus S and possibly also Android 3.1 tablets.  As of writing, I am unaware of any other supported devices or Android versions.

So dig through grandma’s game closet for that old ball maze, grab your Nexus, break out your Google ADK board if you went to Google I/O (or get a compatible one from the suppliers listed here ) and start building!

Concept
The idea is relatively simple: monitor the phone’s accelerometer, and translate the three-dimensional acceleration vector (ie. which way is "down") into a coordinates on a two-dimensional plane - one dimension for each servo or axis of rotation on the maze.  This is mapped to two absolute positions between 0-255 for positioning the servo arms. These values are passed to the ADK board which acts as the servo controller and controls the tilt on the maze. 

In other words, you can now play the ball maze game by using your phone as a remote controller!
 
Remove these adsRemove these ads by Signing Up

Step 1: Materials and Tools

Picture of Materials and Tools
Materials
- A ball maze / labyrinth game
- Google’s ADK Demo board or compatible ADK board with 2 servo outputs
- Two small servos (eg. mini servos found in small RC cars/helicopters)
- Google Nexus One or Nexus S with Gingerbread 2.3.4 (not tested on Nexus S)
- Short cable with female 3x2 or larger box connector (an internal USB panel patch cable works well)
- Male box connector pins - either: one 3x2 or two 3x1 (for connecting to servo sockets)
- 0.5mm aluminium or other pliable sheet metal (for servo brackets)
- Small springs or springy metal (eg. I used stainless steel strips found in some wiper blades)
- A small block of wood (For mounting the "inner" servo to the ring)
- Thin stiff wire, eg. paperclip wire (for servo lever arm fixtures)
- Assorted small screws (to secure servo brackets)
- Small tacks, nails or a staplegun (to secure springs in place)
- Cable ties
- A few drops of oil or grease, particularly if your maze is 30+ years old like mine :)

Required tools:
- Drill and drill bits (I used 1mm, 6mm bits)
- 1-2 pairs of small needle-nosed pliers
- Wire clippers
- Screwdrivers
- Soldering iron
- Sharp knife / craft knife

Other useful tools:
- Drill press
- Small hand-held rotary drill/grinder tool (Dremel or similar)
- Diamond-tipped engraving bit or drill bit (for drilling holes in stainless steel spring strips)
- Bench grinder
- Small hammer / tack hammer

Note to the lazy
If you really don't want to compile and install the apps to your phone (which I highly recommend, you'll see why later), you can download the APK files from this Instructable.  You must ensure that the Settings > Applications > Unknown sources option is selected, copy the APK files to your device, then use a program like ApkInstaller to install them.  If you get an error, check your Android version is either 2.3.4 or 3.1 or greater.

Step 2: Setting up Android Development Software (Eclipse)

To compile the source code you'll need an Android development environment, and the easiest one to set up and use is probably Eclipse.  The entire installation process is well documented on this page, but here are the basic steps:

1. Download the appropriate installer for your operating system and install (choose the "Eclipse Classic" version).

2. Download the Android Software Development Kit (SDK) and install it.

3. Download and Configure the Android Development Tools (ADT) for Eclipse.

4. Add Platform support for the Platform APIs and Google APIs.  If installing on a Nexus One or Nexus S you will need the following:

    SDK Platform Android 2.3.3, API 10
    Google APIs by Google Inc., Android API 10

 ...whatever the latest revision is for each.  While the API is for version 2.3.3, the minimum Android version requirement on Gingerbread handsets is 2.3.4, which is currently only on stock Nexus One and Nexus S phones.   If you want to try this with an Android tablet running version 3.1 or later, you will need the following instead:

    SDK Platform Android 3.1, API 12
    Google APIs by Google Inc., Android API 12

Note that there is currently no support for Android version 3 devices prior to version 3.1, and I believe it is unlikely to be backported.

Step 3: Install ADK Components and setting up DemoKit

"That's a lot of software to set up", I hear you say...  But you want your maze, so press on!!

ADK Components
Now that you have a functional Eclipse environment, you are ready to set up the ADK components and test the board.  The process is well documented here so I'll only outline the three steps briefly here.  Once you've done this, you are ready to test:

1.  Install Arduino Software (contains libraries and an IDE for coding and installing firmware to the ADK board).
2.  Install the CapSense library (not strictly required for this project, but if you're going to be tinkering with the ADK - which I'm sure you will - you should install this now.  It contains the libraries to sense human capacitance. This is needed for the capacitive button that is located on the ADK shield) .
3. Install the ADK package (contains the firmware for the ADK board and hardware design files for the ADK board and shield) .

Setting up USB Debugging
While we're not going to actually use USB debugging, enabling it provides a quick, easy way to quickly compile, install and test apps on your device.  Follow steps 2 and 3 outlined here to enable USB debugging.

Compiling and Running the DemoKit app
Finally, follow the steps outlined here to get the DemoKit application working on your Android device (if you've followed my steps then you've already done the first step).  When it says "Install the application to your device" , do the following:

1.  On the device, go to the home screen, press MENU, select Applications > Development , and make sure USB debugging is enabled.  You may get a warning - that's fine, it just means that when connected via USB you will be able to install and run applications from Eclipse without any user interaction on the phone.  If you want to be super-protective you can disable this when you're done.
2.  Connect your device via USB
3.  With the DemoKit code open in Eclipse, select Run > Run or press Ctrl-F11.  If you see the Android Device Chooser , just select your Android device and click OK.  Eclipse will upload the compiled package and run it automatically.

Now finally you're ready for some fun!

Step 4: Setting up the ADK Board and Testing with DemoKit

Picture of Setting up the ADK Board and Testing with DemoKit
Maze 037.jpg
Testing with DemoKit
Without the ADK board the DemoKit application you've just compiled is a little pointless, so once it is running on your phone (you'll see an Android robot with a front panel open), disconnect the USB cord from the computer and (with the other end still attached to the phone) plug it into the ADK board's USB host port.

Plug the power into the ADK board and you should see a power indicator light up on the main Arduino board (under the demo "shield" board which is on top).

Now that DemoKit is installed on your phone you can run it as often as you like - you no longer need to recompile unless you want to make changes.  When connecting the phone to the ADK board, you should get a message like the one shown in the second image - be sure not to check the "Use by default for this USB accessory", because we also want to use the RealMaze program with the ADK board.  Simply click OK to start using it.

The initial screen has a number of hardware input indicators - showing the status of buttons, temperature, light sensors and more.  tap the "Out" tab at the top to show the controls for ADK outputs - relay switching, LED brightness controls and servo controls.

Connect the servos to the ADK board, taking care with the polarity - Black = Ground or -, Red = +, Grey = Signal.

Now you can control the servos using the sliders (second image).  If it's not working check the power light on the board, USB connection, and re-check the servo polarity.  Test the other outputs on the demo shield: lights and relays.

Step 5: Compiling and Running RealMaze

Picture of Compiling and Running RealMaze
Now for installing and compiling the RealMaze code.  RealMaze is just a severely and shamelessly ripped, hashed-up and duct-taped-together-again version of DemoKit with a bit of code from around the web (sources cited in the code).  It's called RealMaze because all the other accelerometer-based ball maze games are fakes onscreen :)  This one controls the real thing.

There are still many (most?) bits of code, entire classes and resources from DemoKit that I have not removed that are not used, you might want to tidy these up if you want to reuse the code for anything - being an Android amateur I'm worried that it might break if I remove too much!  Code patches and complete rewrites from more experienced programmers will be gratefully accepted, but the point is that it works for me as it is :) 

1.  Download the RealMaze.zip file attached to this Instructable and extract the files (with paths intact) in a suitable source code location.

2.  In Eclipse, select File > New Project , then choose Android > Android Project and click Next.

3.  Type the project name "RealMaze", choose "Create project from existing source"

4.  Check that the Build target is correct for your device (Using Google APIs version 2.3.3 for Nexus or 3.1 for tablets)

5.  Click Finish

6.  Reconnect your phone to the PC then in Eclipse under Package Explorer, right-click RealMaze and select  Run As > Android Application

Similar to the DemoKit installation, you should now have the RealMaze program installed on your phone.  Disconnect the phone from the PC and connect to the ADK board.  You'll see a message similar to the one you got with DemoKit, click OK and you should now be in control of the servos using the tilt on your phone.

(Note: one known bug is that RealMaze does not resume well if you start another activity then try to go back to it.  Simply start it again from the programs list)

Step 6: The Maze Hardware - Preparation

Picture of The Maze Hardware - Preparation
Maze 009.jpg
Maze 006.jpg
Basic preparation
If the maze you're using is anything like mine was, it might need a bit of thought.  I had to dust it out, oil up the pivot points, and remove hot glue that was used to stick the back on (after it had been dropped many years ago).

If you have better resources than I have, you can probably work out how to put the servos on the outside of the casing, so that they turn the rods just like the knobs usually do.  This may be a better/easier solution for you, but my servos were small, my workshop spares limited, and I kind of liked the old retro-knob look.

Remove the panel on the underside to get at the maze mechanics - this may require removal of screws, wood staples, or in my case an old hot glue repair job.  As you can see, mine had seen the odd repair or two over the years including a very tacky string repair job (that may have been mine at aged 10 after breaking it, I don't recall...).  Notice that I didn't remove any of the existing hardware inside, I've only added to it.  The two tiny servos were easily strong enough to move the tilting deck and the string, rods and knobs that were attached to it.  If your controls are still stiff after oiling you may have to disconnect the old mechanism for this to work more smoothly.

Important note: When referring to the connected wooden parts that make up the tilting maze I will hereafter refer to the outer box as the "casing", the slightly smaller square wooden ring inside the casing as the "ring", and the actual maze which sits inside the ring as the "table".

Servo location
You now need to identify where to put the servos (but we're not mounting them just yet!).  I decided to put mine both in one corner, but you may have to spread yours out.  Here's what I considered when looking for a good mounting spot:

 - You don't want the ball to hit a servo, spring or any wiring when it drops through a hole
 - You also don't want the ball to get stuck behind anything if it drops though a hole and starts rolling back to the exit
  - You need to have enough space for the table to swing through both axes, plus clearance for the servos.  Ideally you also need enough clearance to put the maze base back on, and remember that the base is not level - it slopes so the ball rolls back out the exit hole when it drops
  - You need to consider where to put your springs and how they will be attached.  Springs are not critical, but they are a very good idea if you want your servos to last.  Most cheap servos have nylon gears that are easily stripped by sudden external forces to the servo arm.
 - One servo will have to be mounted on the casing, this will control the ring in one axis.  The other servo will actually be attached to the "ring" (it moves when the other servo moves), and this controls the table top tilt in the other axis (which is always relative to the ring).
 - Consider what orientation works best - the servo arm can be adjusted, so you may want to flip or rotate them to find the best position.

For these reasons, I decided to put my servos on the opposite side of the maze to the exit hole as shown.  There's not quite enough clearance there to replace the sloping base panel, but I've decided not to for now.  If I did, only one servo screw would be in the way and a small cutout of the base panel would suffice.

Spring shape, size and placement
My springs came from wiper blades - some blades are reinforced with flat stainless steel rods and these make a perfect springy lever for attaching servos to the board.  You will have to experiment a bit with size and shape, and consider where they might be placed.  Here are some pointers:

-  Add a 90° twist near the top end of the spring, this increases the strength of the spring and ensures the servo linkage can be attached.
- The springs should be soft (ie. long) enough to provide the servos with some protection. With a servo arm screwed onto the servo pivot point, you can test this by cutting a length of metal and using it to (very gently) try and turn the servo arm at the furthest point from the pivot.  Ideally you should probably have about 10-15mm of flex in either direction without the servo arm moving.  Be careful when doing this, as some servos don't take external forces well and this could strip the gears.
- The springs should be stiff (ie. short) enough to move the table with very little flexing.  This probably comes down to adequate lubrication, but you can test this by taking the same piece of metal above and (with the maze the right way up) using it to tilt the the table in each axis.  There should be no more than a few mm of flexing - any more and your maze will be "sticky" and very hard to play.  You may need to cut the spring shorter, bearing in mind that it will provide less protection for the servos the shorter it gets.
- The springs also allow you to raise the pivot point away from the table - you need some separation to ensure the the spring has room to flex and the table has room to move through the full swing (or at least as much as the servos will allow).

Shape is less important, but with springs like this it is the total length from mounting point to lever arm pivot that gives it its "spring".  You may need to make the springs a little wavy as I have to get the springiness in the space you require.  You may want to try temporarily sticking the servos in place with a tiny dot of hot glue, double-sided tape, Blu-Tack or plasticine.  Watch how each spring moves in relation to the servo arm when the table is tilted in each axis, and look for a good place to mount the spring.  Mark it with pencil.

Each spring will need a small hole at the top end to connect the servo linkage to, plus it may need 2 more at the base as I did depending on how you decide to mount them.  Stainless steel does not drill well at small diameters, so I used a diamond-tipped engraving bit to slowly drill my holes (approx 1mm dia), a drill press will work best for this.  Be patient, you don't want to wear through the diamond coating by pushing too hard, and remember that you want to make the hole a snug fit for your linkage, so keep checking to make sure you don't make it too big.  Don't mount them just yet, but for mounting the springs to the board you could drill two more holes in the base of the spring and use small screws or miniature nails to attach it into the board. 

If you find drilling the stainless is too hard, you may wish to use epoxy glue or similar to mount them instead, and on the top end you could glue a small piece of plastic with the hole for the servo linkage instead.

Cable placement
Like the servos, you don't want the cables interfering with the ball or table movement.  Decide where you are going to locate the cables - if the servos are apart from each other you may need additional connectors or extensions.  Don't drill or cut anything just yet until you actually have your servos in place.

Step 7: The Maze Hardware - Putting it Together

Picture of The Maze Hardware - Putting it Together
ServoSwing.jpg
Maze 020.jpg
Maze 015.jpg
Maze 010.jpg
Mounting Servos
Using the sliders on the DemoKit app, move each servo as close as possible to the midpoint of its 180° rotation, then disconnect from the board.  Holding the first servo roughly in its mounting position, attach the plastic lever arm to the servo pivot so that it's roughly horizontal.  Screw the lever arm to the servo pivot.  Repeat with the other servo in its place.

Now mount the servos in place.  I used thin strips of sheet metal cut to size as straps around the servos and screwed them into the wood.  In my case the "outer" servo is mounted to the casing near the corner, and it is used to tilt the ring.  The "inner" servo is mounted on a block of wood which is mounted to the ring, close to the ring's pivot with the outside casing.  This servo is used to tilt the inner maze table.

If you are mounting a servo on a block of wood for clearance as I have done, make sure when this block and servo are mounted that there is enough clearance for the maze table to move full swing in both directions, as well as pivot on the opposite axis without hitting anything.

Once you've mounted the servos, you'll need to identify the relationship between servo arm swing and the displacement of the maze table (via the spring). Image 2 depicts the servo arm swing (most servos turn 180 degrees, I allow for slightly less). A full clockwise rotation pushes the spring "down" (at least from this perspective), while a full counter-clockwise rotation pulls the spring "up" approximately the same distance.

Remember the arm linkage (paperclip wire) remains the same length and the spring will only move in one dimension, up or down, so this linkage works a little like an engine crank.  An even up and down movement is now dependent on just the linkage length and position of the spring.

Mounting the springs
Now you can mount the springs.  If you didn't drill the holes in the springs, find the optimum position and glue in place.  If you managed to drill the holes in the base of the springs, you can now position them one at a time, mark and pre-drill the holes slightly undersize with a Dremel and perhaps 1mm drill bit.  You can then use small tacks or 1.5mm diameter nails which have been cut down to approximately 10mm long and re-sharpened on a bench grinder. A small tack hammer works well here.  If drilling/nailing make sure you're nailing into some wood on the other side, not just through the maze surface!

Adding linkage
Now that servos and springs are in place (and assuming servos are still center-swing), with the table level you can start preparing the linkage.  Put a small Z-shaped bend in the wire close to one end and feed this through the hole in the spring.  Measure or mark where on the wire the server arm hole is, then make another Z bend in the wire at that position and cut just marginally after the second bend, as shown in the third image.  You should now be able to feed the bottom Z-bend into the spring and with only slight bending you should be able to gently click the top into place on the servo arm.  Repeat with the other servo linkage.

Wiring it up
Finally, you need to add the wiring.  I used a USB cable that is often found inside PC's to connect the motherboard to a USB port panel (See Image 4).  This works well because at least one end is wired with a block connector which will fit onto the ADK board.  You can carefully trim the plug (usually 8-10 pin) down to 6 pins with a craft knife, and trim the unused wires back. 

Bring the servo plugs together and this is where you can drill a hole to feed the cable through.  Drill a hole the same diameter as the cable, cut any plug from the other end of the cable, and feed it through the hole, with the female box connector on the outside as shown in Image 5.

On the other end (the inside), we actually want a male 6-pin block connector to plug the servos into, that is if you don't fancy cutting off the servo plugs and soldering them to this cable.  These can be found on old computer parts, motherboards, all over the place - they are used for most jumper pins and many cable connectors..  I used one from an old sound card.  Solder it on, being very careful to get the wiring of the pins right so that they match the female plug on the other end.  Test with a multimeter if necessary.

I then used a couple of cable ties to hold the wires out of the way of the ball and stop the cable slipping and damaging things if it was tugged from the outside.  I plugged the servos into the male connectors, I then separated the servo plugs and bent the two sets of 3 pins apart so that there was minimal pulling on the relatively fragile servo wires (see Image 1).

Finally, check and double check the servo cable wiring and polarity, then plug the cable into the ADK board.  You should hear the servos move into place if they've been moved off center at all (and hopefully the maze table will move too), and that means you're good to move on to the next step.

Step 8: Fine tuning

Picture of Fine tuning
Wow - you now have a fully functional maze that you can control from your phone... but chances are that it's not quite playable yet.

Axis swapping
The first thing to adjust is if the axes are the wrong way around.  If your maze moves side-to-side when you tilt your phone forward and back then that's a simple fix - swap the servo plugs over.

(Note to the lazy)
If you've just got the RealMaze APK and skipped "roll your own" in steps 2-5 then the remainder of this step won't apply and unless your setup is exactly like mine you might find yourself with a maze that's difficult to control... You were warned.  It's not too late to go back and install the necessary bits :)

Inverting an axis
If, for example, you tilt your phone forward and the maze tilts back then you need to invert the movement on one axis (or both).  This is done by making a change in the RealMaze code in Ecplise.  Open RealMazeActivity.java from the Package Explorer > RealMaze > src > com.google.android.RealMaze .  Edit the lines highlighted in Image 1 (about line 110) by changing the (x*1.5) to (x*-1.5) if you believe the x axis needs flipping, or change the (y*1.0) to (1*-1.0) if the y axis needs flipping.

Changing sensitivity
If the servos are moving too wildly or not wildly enough for you, then you can change the multiplier on the commands sent to the servos.  For some reason the x axis needed multiplying by 1.5 for me(which is pretty significant - I still don't know why), but it may be dependent on hardware.  Simply adjust the 1.5 or 1.0 in those same two lines to adjust sensitivity.  You probably won't have to change either one lower than about 0.7 or higher than about 2.0.

Recompile, redeploy and retest.  Rinse, repeat.  When it's working better, move to the final (and most important) step....

Step 9: Play!

Picture of Play!
Fire up RealMaze again, connect to the ADK board, and enjoy the fruits of your hard work! 


And the original video that started it all...


Thanks to all those who encouraged me to post a video of this online, and then to write up this (my very first) Instructable.  It has been a great learning experience, and I hope I can impart some of what I've learned here.  The Android Open Accessories API and ADK demo board is among the coolest things to hit Android recently, and I hope this encourages more developers to check it out.

Cheers from NZ,
Paul
JUGG3R4 years ago
nice project,im just curious if there's a way that you could control it through wireless connection
pcdevltd (author)  JUGG3R4 years ago
AFAIK they are going to support bluetooth connections between phone and ADK board soon but it is not implemented yet. Not sure about wifi though.
Hi pcdevltd,

It is really Great project ,,,, I see you are appropriate one to tell me about good and small idea for subject on university,,, We can use on it jest Arduino and any sensor to built a nice application which wight 20% from final mark ,,, so please if you have an ides from your experience which smart and good tell me ,, it is really important ,,,

Than you,,,
pcdevltd (author)  MTechnology3 years ago
Coming up with ideas is one of the best parts of making any project - but I can't help you on that sorry - it depends on what hardware, software and other limitations you have, and also depends on what your university course expects you to do (When I was at university I learned that the "right" answer is most often the one that satisfies the lecturer/professor's expectations, not necessarily the one that you think is best, sadly). Good luck and post a link here when you are done!
JUGG3R pcdevltd3 years ago
BTW is there a code in here for the arduino or is it all the codes are for the android phone. Good day to you pcdev
pcdevltd (author)  JUGG3R3 years ago
I have not included the Arduino code, I was simply using the supplied DemoKit firmware (see this link, also posted in the instructable: http://developer.android.com/guide/topics/usb/adk.html#getting-started) The step titled "Installing the firmware to the ADK board" loads the ADK board with the demokit "sketch" (firmware). For this project I have not modified the firmware, but as I mentioned to Maheera if you are not using the Google ADK board then you will almost certainly have to update this code as well. I can't help with regular Arduino boards, I only have experience with the Google ADK board. Good luck!
JUGG3R pcdevltd3 years ago
i think arduino mega 2560 is compatible with the google adk board..thanks for this great project you have atleast i wont start from scratch..keep up the good work :)
pcdevltd (author)  JUGG3R3 years ago
Not directly compatible, see links I just posted above.
JUGG3R pcdevltd3 years ago
thanks for the links
JUGG3R3 years ago
too bad i cant install the demokit with my samsung galaxy s 2(2.3.5)..im currently working for the wired one to run successfully before going to a wireless one
pcdevltd (author) 4 years ago
Thanks for the comments everyone! Don't forget to come back and vote for me in the three competitions - Toy, Microcontroller and Make it Move - thanks for your support!
nagutron4 years ago
Here's a video of the massive one at Google I/O you mentioned, using a bowling ball! Great job.
pcdevltd (author)  nagutron4 years ago
Thanks, yes the article also links to a video of it - it was a very cool demonstration of the Android Open Accessory platform, and a very Googley thing to do. I really look forward to seeing what other people build with it, the possibilities really are endless.
micha3l874 years ago
awesome job!
john.graves4 years ago
I've seen Paul's setup in person and it does work--but you still need to have the reflexes needed to run the maze. I never made it past the first hole. The puzzle tilts in slightly jittery steps, but it is very responsive to tilting the phone.
pcdevltd (author)  john.graves4 years ago
Thanks John! Yes, it is a little jittery. Reasons include: springs may be a bit soft (could probably be shortened to firm them up), there is no software damping which would make a huge difference, and the maze surface is not completely flat particularly near the start, the most travelled part (from 30 years of use!). To be honest, it's not the type of game you play for an hour at a time like you might on the original, but I've made it to hole 12, so it is definitely playable.
wilgubeast4 years ago
Super-awesome. I've been waiting for the trickle of ADK projects to begin. You set the bar really, really high. Nice work.
zazenergy4 years ago
Paul, this is awesome! Thank you so much for sharing this wonderful project!