Sparki sends his love

Sparki has been on a little trip (all the way back to the USA) to meet his namesake (my good friend Sparky) and to visit Boston, MA. As luck would have it, while I was out there with my new robot friend, it also happened to be Sparky's wedding. What a wonderful opportunity to spread some robot love!

The front of the card I'd made for Irina and Sparky's big day

The front of the card I'd made for Irina and Sparky's big day

Of course, a card isn't complete until you've signed it, so Sparki had to learn to write. This should be a little easier than it was for Hexy as Sparki can already roll around in a controlled manner, straight out of the box.

We could have just written a series of commands to let Sparki follow a path that spelled out his name, but I figured that it'd be a better exercise to write something that was a little more versatile. Getting Sparki to write just involves driving through a series of defined points (we'll call them waypoints from now on) with a pen installed in the marker holder. So it seemed logical to write a program that could take a bunch of waypoints as an input and command Sparki to follow that path as a result.

One of the most powerful features of programming is defining your own function to do something that you need to repeat a lot. Functions can take parameters as inputs and return values back to the code that called them. One important thing to remember about functions is that they only know information that you explicitly send them, so a function that looks like this will only know about the co-ordinates of the new waypoint that you want to go to:

That's not much good if we're trying to navigate between waypoints, so something a little more sensible would be to pass the function the co-ordinates of the current waypoint too:

We're still not quite there. Our function knows where the start and finish points are, but it doesn't know which direction Sparki is pointing in to start with, and we'd really like to return the new direction that Sparki will be pointing in after this movement. To do this we'll add a final parameter and a return value:

Now that we've got a function declaration that should do all that we want, it's time to pack it with some code to do the useful things that we need. The proper variable types are defined too:

The angle to the new point is calculated by the atan2 function, which returns an angle in radians (hence the "* 180 / PI"), everything else should be fairly obvious from the comments. So how do we call this function to get Sparki to draw something?

We'll need a set of waypoints (we'll store these in an array to make looping through them easier), and we'll need to set an angle that Sparki will be facing when we start the code. Stick all that in the setup() section of the Sparki sketch and we're set, here's an example:

The five waypoints are defined as a pair of arrays (five elements long) and the initial value of currentDirection is set as 90 (imagine Sparki pointing up along the y-axis on normal graph paper). Don't worry, there's a complete Sparkduino sketch to download at the end of this post.

But how to get a more complicated set of co-ordinates for something fancier than a square? It'd be exceptionally tedious to write them all in by hand (this whole exercise was meant to be about getting Sparki to do this easily!), so I'd produced some code (in Python, using the Pygame library) to do this for me. A few clicks later, the message is ready to be written (closing the window writes the co-ordinates to the console):

Using the Python code to capture a path

Using the Python code to capture a path


What gets written to the console looks like this:
[11.4, 9.1, 9.7, 12.2, 13.3, 11.2, 9.8, 13.2, 9.1, 12.2, 11.2]
[-3.8, -5.2, -7.2, -7.2, -5.4, -3.9, -7.2, -5.4, -5.1, -7.2, -3.8]
11

The first set of numbers in square brackets is the array of x-values, the second is the y-values and finally the integer at the bottom is the length of the arrays. In order to use this data in the code above:

  • Copy the x-values into the curly brackets on line 5
  • Copy the y-values into the curly brackets on line 6
  • Enter the length of the array into the square brackets in line 5 and 6
  • On line 10: the section that says (int i=1; i<5; i++) should have the length of the x and y arrays in the middle value (currently 5)

So that's it. Now you too have the power to make Sparki write whatever you want him to (or simply drive around a fixed set of points on a Cartesian grid). But for me, this all started with an unsigned wedding card, so here's his final effort:

Sparki signing his name for the first time in Irina and Sparky's wedding card

Sparki signing his name for the first time in Irina and Sparky's wedding card


What do you think?

NB Hexy sends his love to the happy couple too, but he's quite big and my luggage wasn't.

Code downloads:
Sparkduino sketch: write.ino
Python path capture: capture.py

2 thoughts on “Sparki sends his love

  1. Truly awesome Rob!
    Could you make Sparki read gcode? If you could do that maybe you could make single layer block letters in OpenSCAD, then slice them. Sparki could then not only draw the outline of the letters he could shade them in too (it might take longer than the age of the universe to complete though).
    I think your third code sample might be missing the return value

    • Thanks for the catch on my code.

      I think that Sparki could be made to understand G-Codes. Problem that I have with the above example is that you have to recompile Sparki's brain to get him to write new things. I think I'd like to integrate the Python GUI with the Bluetooth serial port to send movement commands live to him. Possibly update it to allow queuing of waypoints, or zooming to do larger scale movements. Could use that sort of interface to allow importing of G-Codes, might be quite a good interactive demo.

      Now do I do that before I start my "Pong" project?

Comments are closed.