Monday, December 9, 2019

Sparkfun MP3 Shield

I have used a lot of these MP3 player shields in projects. They are super awesome and super simple to use, but I figured a small writeup was worthwhile as there are some details that aren't in the official documentation as well as some tips I have when using the shield.

The MP3 shield uses just about every pin on the Arduino. The documentation states you can use D5, D10 and A0-A5. However, I have found that for some reason when using the shield I have found neither D5 nor D10 to be usable. So typically what I do is setup a software serial using two of the analog pins:

#include <SPI.h>
#include <SdFat.h>
#include <SFEMP3Shield.h>
#include <SoftwareSerial.h>

SdFat sd;
SFEMP3Shield MP3player;

SoftwareSerial input(A0, A1); // RX, TX

void setup() {

  if(!sd.begin(9, SPI_HALF_SPEED)) {
  if (!sd.chdir("/")) {

  uint8_t result = MP3player.begin();

  if(result != 0) // check result, see readme for error codes.
    Serial.print(F("Error code: "));

  // Loudest volume for left and right
  MP3player.setVolume(0, 0);

void loop() {
  if (input.available()) {
    String action = readFromSerial();
    if (action == "play") {
      uint8_t result = MP3player.playMP3("awesome.mp3");
      Serial.println("Ready again"); 

String readFromSerial() {
  static char buffer[80];
  if (readline(, buffer, 80) > 0) 
  return buffer;

int readline(int readch, char *buffer, int len)
  static int pos = 0;
  int rpos;

  if (readch > 0) {
    switch (readch) {
      case '\n': // Ignore new-lines
      case '\r': // Return on CR
        rpos = pos;
        pos = 0;  // Reset position index ready for next time
        return rpos;
        if (pos < len-1) {
          buffer[pos++] = readch;
          buffer[pos] = 0;
  // No end of line has been found, so return -1.
  return -1;

Monday, November 18, 2019

Using Max Build Volume of Ultimaker 3D Printer

Sometimes you have to print at the max build volume of your 3D printer. I have an Ultimaker and the easiest slicer to use is Cura. If you set the "skirt link count" to zero, it won't print the line around the part so you can get the full x and/or y. As you may know the reason for the skirt is so that the printer gets a consistent extrusion of the filament, but I you need the full bed size, then you need the full bed size. Also turn off brim and set build plate adhesion to "none". Lastly set "travel avoid distance" to 0.

Tuesday, November 5, 2019

Raspberry Pi Super Computer STL Files Published on Thingiverse

Finally. I'm sorry it took so long. Here it is, the files to print your very own 2U rack mountable Raspberry Pi holder for 21 Raspberry Pi 3B+. Let me know if you have any questions or problems. Just because we made over 50 of these, doesn't mean it's easy.

Monday, September 2, 2019

Tuesday, August 20, 2019

Arduino Eithernet Shield 2 NTP Time

I'm trying to get an accurate time on an Arduino. I have an Ethernet Shield 2 attached to an Arduino Mega. There's also a couple current sensors and a barcode scanner. The main reason for this post is for those people that happen to have the Ethernet Shield 2 on any Arduino, and want to get the time. Every single example on the internet or in the Arduino IDE examples doesn't work, except for this one:

So as of the time of reading this, that tutorial will most likely be out of data, but let's say for the next 6 months it'll be the place to go.

So, here's a little insight into what I'm doing and my decisions along with some code at the end:

1. I have an Arduino. That means no clock.
2. I have an Ethernet Shield 2. That means there are an abundance of clocks on the internet.
3. I am not hooking up a clock to the Arduino. That means I need to use the Arduino to keep time.
4. So I'm going to do this by polling a clock on the internet, keeping that time around and adding the time since boot to that time. It isn't a clock you'd want to use as your morning alarm clock, but it'll be accurate enough for what I need.

So I hacked together two functions from that tutorial:

unsigned long getCurrentTime() {
  unsigned long result = 0;
  sendNTPpacket(timeServer); // send an NTP packet to a time server

  // wait to see if a reply is available
  if (Udp.parsePacket()) {
    // We've received a packet, read the data from it, NTP_PACKET_SIZE); // read the packet into the buffer

    // the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, extract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = ");

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
    // print Unix time:
    result = epoch;
  else {
    result = 2099414000; // Picked a date so we can test when not connected to the internet.

  return result;

String timeToString(unsigned long value) {
    String result = "";
    unsigned long epoch = value;
    // print the hour, minute and second:
    result += String((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    result += String('-');
    if (((epoch % 3600) / 60) < 10) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      result += String('0');
    result += String((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    result += String('-');
    if ((epoch % 60) < 10) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      result += String('0');
    result += String(epoch % 60); // print the second

    return result;

unsigned long startTime;

void setup() {
   // ...
   startTime = getCurrentTime();

And anytime you want the current time viola!

timeToString(startTime + millis() / 1000)

Thursday, July 25, 2019

Tormach 770M+

A Tormach 770M+ arrived last Friday and I've been getting it ready to use ever since while actually trying to get actual work done.

Just a piece of trivia, the Tormach machines have been known to use stepper motors rather than the more costly and arguably better servo motors. The 770M for example uses stepper motors. The 77M+ is an upgrade to the very recently released stepper motors. The advantage is servo motors are quieter and have built in encoders. A server motor for instance will run into something and not provide any feedback that it didn't actually move. But a servo motor has a feedback loop with the software to register problems when the motor didn't actually moved the distance it was asked to move.

Interesting trivia fact. The Apple II floppy drives had stepper motors instead of the more expensive servo motors and had no end stop switches. If you've ever been around an Apple II when it booted up you'd hear some loud bangs from he floppy drive. Sometimes it would go on for a long time sometimes for a short time. The reason is Woz knew the number of revolutions from the end stop if the head was in it's furthest position. So they ran it that number of revolutions to get it to the end stop and you'd hear the loud bang the number of times that the head was positioned from the length of travel minus it's current position. It simplified the disk drive and despite being loud had no ill effects.

Anyway, back to reality. The Tormach takes up a large amount of space in the garage, and not all the tooling showed up at the same time so there isn't much that I can do. The vice is in and reads zero deflection. That means it's nearly perfect, or fast least as perfect as my gauge. The vice itself has a 1/4 of 1,000 deflection in the middle however. NOTE that I'm not a machinist and still getting used to the jargon so that may be totally wrong.

The DIN connector for the electronic gauge isn't long enough, so I have an extension cable on order. I will 3D print a mount for it to go somewhere above the door. In fact I am currently 3D printing a lot of little parts to clean things up.

There are a couple parts I need to make for the Raspberry Pi Super Computer, but I don't think the tooling will get here in time so I'll have to take my part to a local machine shop.

Wednesday, July 24, 2019

Fusion 360 - Threads Not Exported to STL

There is one thing that I always have problems with, so hopefully by writing this short blog post I'll remember more often. That problem is creating threads properly. Usually I noticed after I have already printed the part. Always remember to choose the "Modeled" check box. I wish I could make this the default.

Also, if you need to remove part of the hole after the threads in the timeline, you'll have thread remnants, so move the threads to be later in the timeline, then "Cut" the hole.

Thursday, July 18, 2019

Very Large Raspberry Pi Cluster - Part VI

At this point I've shown how the all the Pi will be held in place to make a 2U rack, and next is the overall structure but that will have to wait until next week. So for this post I wanted to talk a little about the software and what we're going to run on all these Pi. A lot of data will be processed and sent to the cluster. So here's the high level of the software stack:

  • Each Pi will network boot from a central server running Oracle Linux
  • The boot image will be running Oracle Linux
  • It will be running Kubernetes and Docker
  • There will be a very large video wall run by a Windows server
  • Everything will be written in Java
  • Gluon is helping
What exactly it will do will remain a mystery until you come see it in person. So sign up for Code One and come see it!

Thursday, July 11, 2019

Very Large Raspberry Pi Cluster - Part V

Last week I said I'd talk more about this part. So here is what the main bracket of the Pi holder looks like and the two parts individually.

The print time for the Pi holder is 98 minutes. It's a lot but it's a lot of plastic too. I print 12 of them at time, at 15% infill, with a .8mm print head, no rafts or supports. I can print one rack in 24 hours. You can do the math from there how many days the printers will be running. I spent a few days optimizing the amount of filament and the print speed with the strength needed. It is over engineers and will not break when being shipped. It is easy to assembly and requires very few parts. The reason for the curves is because it prints faster since the print head doesn't have to slow down when it approaches a corner. I was going to make the front two exes that are square round but it only saved 30 seconds print time and looks better being square when fully assembled.

Here are some views of the models from different angles since these are two separate pieces. Here are two views with the two pieces combined. You will notice a square rod coming out of that slot.

That square rod is a piece of aluminum extrusion. Specifically it is 80/20 series 10 that is .5in x 1in x 18in. I had 16.35mm milled off the end and the ends tapped for 10-32 by a local machine shop (GSFAB in Santa Cruz).

So I print 21 of the Pi Holders and two of them end caps (mirror of one another). Bolt an end cap to one end. Add one plastic threaded insert to the top hole, bolt a Pi on (the bottom holes just sort of clip on), slide it on the 80/20, repeat. After 21 Pis, bolt the last end cap and it looks like this:

So, there's a 2U containing 21 Raspberry Pi in a 19in server rack. I've only got 48 more of these to print and assemble.

Wednesday, July 3, 2019

Very Large Raspberry Pi Cluster - Part IV

So I've had a couple weeks here without much of a progress update. A lot of work has gone on. So here's a quick update before the holiday. First some photos. The first one is of the original prototype 3D printed out with some Pi in it.

This is a very nice design. The Pi just snap in place, there's room in the back to get to the micro USB power plug. But there are three problems:

1. I can only print half a 2U, so things had to be designed in such a way that once side is put into place, slid over, the other side goes in and is slid over and bolted, the first one slide over bolted, then the two remaining Pi on the ends are put in. And it requires two people.

2. It takes 50 hours to print one 2U holding 21 Pi.

3. It requires access to the rear of the rack. Without those rear bolts it wouldn't survive shipping.

So back to the drawing board. And here is the new design.

It's difficult to see what's going on here but there are 23 individually 3D printed pieces; one for each Pi and one for each end cap. They connect together by sliding on a piece of series 10 80/20 1"x.5"x10" long that has had about 3/4" milled off and the ends tapped. These are at the machine shop now so I will show some photos when I get them back.

One thing that's really nice about 3D printing is the RepRap; or the ability to rapidly prototype and revision. 3D printing is slow, but it's faster enough to do this. Here are some of my tests.

The one in the middle is close to the final design. You can see that two of the bolt hols of the Pi have a post and the last one has a threaded insert for a bolt.

Next post I will go into these two parts in detail. They have been designed for strength, speed of 3D printing and ease of assembly.

Thursday, June 20, 2019

Very Large Raspberry Pi Cluster - Part III

I spent most of today fighting with Fusion 360 so I don't have much progress to report besides a serious complaint about Fusion 360. A new updated was released. If I didn't upgrade I couldn't save. If I upgraded I lost my changes. I had no choice but to upgrade, loose my changes and redo them. Then when I loaded up my models there were errors with unresolved imported components. The error states that if I save my model in this state I will loose my model. Personally I find this unacceptable and while I like Fusion 360, I like the disruption to the CAD world, many of the features, the price is reasonable and the fact that it runs on Mac and Windows, I also find it extremely buggy and a toy. I may be switching back to SolidWorks. Hopefully I get all of this resolved in the next few days and can report on the progress.

Update: After restarting Fusion 360 five times, and reloading the model after closing it with the error saying it will be destroyed, I finally got all the linked models and everything to load. So it was just a lot of ignoring errors and closing and reopening things and much ado about nothing, but extremely worrisome that just an update being pushed could cause such concern.

Wednesday, June 12, 2019

Very Large Raspberry Pi Cluster - Part II

Last week I posted about the very very large Raspberry Pi cluster that I'm building for Code One. Read that post here.

I realized after that post went live that I didn't give any backstory as to what we are actually building. When building something like this it's easy to document the entire process, it just takes 2-3 times as long to build. I figured I'd document the process in a fast and loose to blogs, YouTube and Twitter. So, before we go any further with the status of current progress let's backup.

Last year Stephen Chin and Gerald Venzl came to me with an idea. The conversation went something like this:

Stephen: "Gerald has an idea"
Gerald: "Let's build a HUGE biggest Raspberry Pi cluster for 2019 CodeOne. Like 1000 Raspberry Pis. The developers will love it. We will call it OSCAR!"
Me: "1000 is a lot, but 1024 is a better number"
Gerald, Stephen: "😃"

Back in the lab a few months later Jasper Potts and I did some math about how to pull off a cluster like this and we produced this rendering.

There will be 49 2U racks containing 21 Raspberry Pis (last weeks post was about this).
There will be 22 network switches.
There will be 18 USB power supplies.
There will be one server.
There will be 8 fans. This thing is going to get hot.
There will be 5 six foot server racks.
It will consume 120 amps of power.
It will require a fork lift to move.
It will network boot because can you imagine flashing 1024 SD cards?
In actuality, the server running the entire thing may be more powerful than all those Pis.
All of this barely fits in 5 racks.
This will travel to other Oracle events around the world next year.

WARNING: Actual numbers may vary, but the 1024 is the goal.