3D printing adventures

I recently shelled out around $900 and bought myself a Prusa i3 3D printer kit for rapid prototyping. Unfortunately, I spent quite some time getting the ‘calibration’ working.

The RepRap wiki was very helpful in helping to calibrate. However, I was quite lucky and the supplier where I got my kit from actually provided me with some pre-calculated numbers so I cut down on about one third of calibration needed.

After some tweaking with acceleration and steps/mm adjustments for the Z-axis, I finally got my test cubes to print properly.

However, after a while, I noticed a lot of my prints were falling apart. Eventually, the print quality just dropped to downright unacceptable.

IMG_20140723_121508 IMG_20140721_132558

 

Notice how the layers don’t seem to stick together? The infill didn’t seem to be ‘infilling’ either. The whole thing seemed like a delicate honeycomb. Most of the time, I was able to crush and rip it apart fairly easily.

Let’s take a look at what the printer is actually doing.

IMG_20140721_113938

 

As you can see, the extruder isn’t providing enough material.

At this point, I suspected a few things. Firstly, it’s obvious that there’s not enough material or that material is being extruded unevenly.

Of course, the first thing I did was head to the Print Troubleshooting page of the RepRap wiki and to the Google-mobile. Both suggested that my prints are turning out badly due to material contamination but I ruled this out initially since the rolls of filament were close to brand new.

Next, I suspected the Z-axis steps/mm calibration may be out of whack. Could it be that the Z-axis is moving up faster in reality than slic3r is expecting it to? Maybe not enough material is being deposited due to this discrepancy.

Something told me at the back of my head that this was unlikely since for a day or two, I was getting pretty good prints before this started happening and I didn’t touch the calibration settings at all. Nevertheless, I did waste a few days attempting to ‘recalibrate’ the Z-axis to no avail.

Maybe it was just a PLA thing? I took out a roll of ABS and fed it to the machine and printed a test object. Hey, presto! Apart from some dragging and oozing, the test object turned out okay! Unfortunately, the second print showed the same symptoms as PLA so I ruled material out.

Now, I started suspecting the extruder. Perhaps the plastic isn’t being heated to the correct temperature making it hard to extrude (and hence, the rest of the printer moves too fast for the extruder to keep up). I wasted a day heating up PLA to different temperatures with very little difference.

At this point, I was pretty frustrated and took a break from it for a few days.

When I finally decided to give it another crack, I suspected the extruder again. Maybe the E-steps/mm calibration was out (again, unlikely since the first few prints worked). No matter how I measured, the calibration was spot on (the supplier had it calibrated pretty precisely).

This whole time, I was on Google searching and reading about similar problems – none which matched mine exactly.

Alright, at this point, I decided it was time to take the material contamination possibility seriously. The room where I’m printing in can get quite humid so I suspect the filament may have gone dud quicker than expected. Baked both rolls of filament in the oven at 60 degrees and monitored the oven temperature very closely to make sure I didn’t deform the PLA plastic. I left them to bake for about 4 hours.

When I tried another print with the baked filament, I had the same problem. With both materials. Dammit. I then, took another break and came back a couple days later to have a look again.

Anyway, I still suspected the extruder. I tried a test print while gently pushing the filament into the feeder. And, what do you know? The layers started giving me clean lines for the first time in about two weeks!

So finally, I figured for some reason, it wasn’t extruding enough material. I didn’t think I made any build mistakes.

Although the extruder design appeared to be a custom one, it was simple enough to work out how it worked and I couldn’t see any problems.

My next suspect was the hot end. Could it be clogged? I tried to clean it out by heating the PLA to 190 degrees, letting it cool to about 40 degrees, then heating it to about 80 degrees and sharply pulling the filament out. That was supposed to pull out any bits of gunk. I actually did this a couple of times before trying another test print.

Again, no cigar. Dammit.

It wasn’t until I was casually browsing the supplier’s documentation for the printer that I had an epiphany. I noticed that the cog for pushing the filament through always needed cleaning. What if it wasn’t meant to be like that?

A quick Google told me that if the cogs needed constant cleaning, there was something wrong.

I looked at the extruder design again.

IMG_20140723_121558

 

Maybe the ball bearing wasn’t pushing the filament hard enough onto the cog? Maybe that’s why the filament wasn’t being pushed though.

I added an extra bolt before the spring so the bearing pushes harder against the filament and fired another test print.

IMG_20140724_220012

 

Hey, success!

Now, it’s definitely not a perfect print, there’s still inconsistencies to be fixed and fine tuning to do but it was over 9000 times better than the craptastic prints I was getting before!

At the very least now, I have the option of printing out and trying other, more standard extruder designs now.

The Success Box

This box was made with a button to press after a major achievement to boost your morale. It plays a song of your choice (or a random song) from a USB drive plugged into the side of the box. Personally, I prefer the Final Fantasy victory fanfares. With a little tweaking, you could easily make it stream over wifi or bluetooth.

The Components

IMG_20140718_225840

The components used in this project are readily available. You should be able to build this machine in well under $100.

The main controller is a Raspberry Pi which is configured with the usbmount package. This will automatically mount USB drives under /media. I used a python script (run at boot time via /etc/rc.local – included at bottom of the post) that scans all the files ending in .mp3 in the /media directory and plays it when the GPIO goes high (i.e. an open circuit). I could have gotten an MP3 and DAC chip somewhere to output the audio and read music off an SD Card using a microcontroller but I couldn’t find a cheap solution.

The button was from a $10 emergency stop button I bought off eBay. Using an emergency stop button means I can stop the music any time by releasing the stop button. I took the button out of its enclosure and chucked it into my own. Be careful when you’re writing the software that the button is active high on the GPIO pull-up inputs (when the button is pressed, it is an open circuit – not a closed circuit unlike conventional buttons). I wired mine up to GPIO1 on the original Raspberry Pi B model since there’s a ground pin immediately to the left of it.

The PC speaker can be scavenged from any old computer and soldered to jumper wires to connect to an amplifier (or just a straight audio jack – see below).

Furthermore, I included an amplifier circuit to boost the audio. The is optional if you feel the power outputted by the Raspberry Pi is enough but it’s cheap enough to throw in even just as volume control.  However, the amplifier did make the speaker more susceptible to noise, possibly from fluctuations in the power supply or electromagnetic interference from the cables – it even picked up blips from my wifi dongle. I chose an LM386 circuit since it’s small, easy to use and inexpensive (~$5-$10). Don’t bother wiring up your own circuit, eBay and websites like DealExtreme sell premade LM386 modules that take 5V nicely. For the amplifier, I also had to solder an old pair of earphone wires to jumper pins for easy connection.

The Enclosure

enclosure

I’ve included the design for the enclosure at the bottom of the post but be warned, the specs have changed slightly and I haven’t bothered to reflect the changes in the SCAD files.

Originally, I was going to 3D print the enclosure but felt it would look better made from wood. I was lucky enough to have a neighbour who had a CNC router in his garage and was nice enough to help me cut out the walls and build the enclosure (thanks Marco!).

The enclosure is designed to lock the Raspberry Pi in place via the SD card. Removing the SD Card lets the Raspberry Pi fall out nicely. Otherwise, it’s held in place by the USB connectors and SD Card. Nothing else was used to fix the board down.

The emergency stop button just needed screwing onto the top.

The speakers were fixed on with a plastic ring that came with the speaker. It was secured using nuts and bolts. I put a mesh on it too since it also came with the speaker.

The Software

The Raspberry Pi runs the default Raspbian Linux distro with a LOT of things cut out to reduce boot time. You may find minimal distros made for the Raspberry Pi that has a ~120MB footprint on the SD Card and fast boot times.

Next, I installed usbmount and pygame to automount USB drives as they are plugged in and for outputting sound in Python respectively.

Then, it’s just a matter of uploading the script that polls GPIO for changes and plays music at the right time. I have included the script I hacked up at the end of the post.

Don’t forget to add this script to your /etc/rc.local file along with code to export the GPIO interface and set it to input pull-up mode. You could use the horrible /dev/mem trick used in earlier tutorial Python code for the Raspberry Pi, but coming from a kernel developer background, I’d avoid messing directly with memory mapped I/O and just use the standard kernel interfaces for manipulating GPIO.

You may also want to configure your network interface to auto grab an address and install an SSH server so if you need to debug the box, you just have to plug in a wireless dongle instead of taking it all apart and hooking it up to a monitor.

Then, reboot your Pi and check everything works!

Files needed for this project

Idea for TI-Nspire serial adapter

The TI-Nspire has a serial interface in the dock connector at the bottom of the calculator. The easiest way to access this reliably is to simply solder a wire onto it but that’s obviously not an option for some people. A few people in the community have come up with some interesting designs for a home made adapter.

Here’s a simple and reliable adapter that I made out of tape, cardboard and some wires to replace my old, ugly, unreliable adapter.

IMG_20130615_171001

IMG_20130615_170922

IMG_20130615_170927

File:/// crash in Mountain Lion workaround

Update: For a much more in-depth analysis of the problem, head over to Naked Security where Paul Ducklin explains the bug in much more detail.

Gizmodo recently published an article about OS X Mountain Lion crashing when the text File:/// is typed into TextEdit, Spotlight, Mail or some other OS X apps. It’s also reported that Safari and Chrome also crash though I haven’t personally tested them.

I did some sniffing around with gdb and the problem seems to come down to an Apple framework called DataDetector. A bit of Googling shows that this private framework is responsible for looking in text for text that might be ‘special’ such as dates and giving them special options.

It seems that the data detector for URLs is broken and will crash when called upon. The workaround is to remove it from being run. Open Finder, open the Go menu, click Go to Folder and put in /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/Resources/ then rename the file called com.apple.datadetectorscore.cache.urlifier.system to com.apple.datadetectorscore.cache.urlifier.system.backup

You can also do all of this in one handy terminal command:

sudo mv -v /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/Resources/com.apple.datadetectorscore.cache.urlifier.system /System/Library/PrivateFrameworks/DataDetectorsCore.framework/Versions/A/Resources/com.apple.datadetectorscore.cache.urlifier.system.backup

You may need to reboot afterwards. This was tested to be working on OS X 10.8.1.

Linux Kernel port to TI-Nspire CX

I’ve just begun a port of Linux to the TI-Nspire CX and I’m happy to say I have a minimal kernel booting successfully on the calculator!

Here’s the UART bootlog and you can see we actually make it to userland without crashing!

The minimal port has support for the interrupt controller and the timer. UART support is on its way (at the moment, it’s just using the early printk console) and I’m hoping to get the framebuffer working soon so I don’t have to rely on the dodgy serial adapter I made.

I’ll also be needing a lot of help so if you’re familiar with Linux kernel development, I’d appreciate your help immensely. Contact me if you’re interested.

Edit: For updates and downloads, visit the Omnimaga thread here.

GameBoy Advance development

I found my old GameBoy Advance consoles and found that I’ve never done any development work on it and decided to play around with it.

Unfortunately, I don’t have a flashcart and it’s difficult to find decent ones to buy on the internet anymore. The only option to actually upload code was to use the multiboot protocol in the GBA BIOS to run the code.

If you don’t know, the GBA has a feature where it’s possible to multiplayer link multiple consoles even if the other consoles did not have the game cartridges. The master console can download 256K worth of game code to each of the slave units so they can each run a copy of the game without a game cartridge.

The first obstacle to bypass was to actually able to communicate with the console. There are actually many ways to communicate with the GBA. With a bit of searching around and debugging, I found that the GBA can actually use 3 different serial protocols to download code. There’s the normal serial mode that is really just 32bit SPI. Then you have your proprietary Joybus mode and 16bit multiplayer serial interface.

After reading through a lot of diagrams and code, I managed to set up a Teensy AVR to bitbang the multiplayer serial protocol and bridge it to USB serial. (Hint: don’t ever use digitalWrite for bitbanging. It’s too slow!).

Second obstacle is actually working out the protocol. I had to read through lots of reverse engineered code to work it out. It seems the GBA uses this weird as encryption and checksumming scheme which I cannot work out. I have managed to complete all the handshaking except encryption and checksum verification though.

I will post source code and documentation once I finish it completely. In the meantime, here’s a video.

bFLT format – implementation notes

One of the biggest show-stoppers in writing a bFLT file loader for Ndless was the lack of documentation with the bFLT file format. Information was scattered everywhere and it was hard to find how to implement some specific feature. I decided to write a simple description of all the features in bFLT and how to implement them.

The first thing I should mention is that there are two versions of bFLT out there. I will be describing the simpler, version 4 format.

First, we have the file header structure:

#define	FLAT_VERSION			0x00000004L

struct flat_hdr {
	char magic[4];
	unsigned long rev;          /* version (as above) */
	unsigned long entry;        /* Offset of first executable instruction
	                               with text segment from beginning of file */
	unsigned long data_start;   /* Offset of data segment from beginning of
	                               file */
	unsigned long data_end;     /* Offset of end of data segment
	                               from beginning of file */
	unsigned long bss_end;      /* Offset of end of bss segment from beginning
	                               of file */

	/* (It is assumed that data_end through bss_end forms the bss segment.) */

	unsigned long stack_size;   /* Size of stack, in bytes */
	unsigned long reloc_start;  /* Offset of relocation records from
	                               beginning of file */
	unsigned long reloc_count;  /* Number of relocation records */
	unsigned long flags;
	unsigned long build_date;   /* When the program/library was built */
	unsigned long filler[5];    /* Reservered, set to zero */
};

#define FLAT_FLAG_RAM    0x0001 /* load program entirely into RAM */
#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
#define FLAT_FLAG_GZIP   0x0004 /* all but the header is compressed */
#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */

For simplicity, all fields are in network byte order (i.e. big endian) and are 32 bits wide. When you write your loader, make sure you correctly convert the endian appropriate for your machine.

Loading Executables

The magic field should be the bytes “bFLT”. The rev field should be set to FLAT_VERSION. It’s advisable to check these fields before loading the binary.

The next 3 fields are all file offsets. If your system doesn’t differentiate between code and data, you can load the text and data sections all in one reading since the sections are one after the other in the file. It is assumed that text_start = entry, text_end = data_start, data_end = bss_start.

Although the bss_end field implies that a bss section exists in a file, it actually doesn’t. You need to make sure that (bss_end – data_end) bytes are available and zero’d at the end of the executable image.

The total executable image size can be calculated by (bss_end – entry).

The stack_size field is pretty much self-explanatory.

The flags field is a bitfield of flags. The FLAT_FLAG_* definition comments describe the meaning of the flags.

Relocations

There are two kinds of relocation you may need to do. The first is relocating global and static pointers and the other being fixing up the GOT.

Relocating global and static pointers

If reloc_count is more than 0, it means that there are pointers that needs to be fixed up.

The reloc_start field is a file offset to a list of pointers (note, they are still big endian!). These pointers point to pointers in the executable image. These pointers are zero-based offsets into the executable image (exceptions being shared library references – explained later).

If you’re implementing XIP and you’re keeping code and data separate, you can work out which section the offsets are pointing to by taking the pointer and comparing it to the sizes of each section. I.e.

if (offset < (data_start - entry)) {
    //pointing to code section
} else if (offset < (data_end - entry)) {
    //pointing to data section
} else if (offset < (bss_end - entry)) {
    //pointing to bss section
}

In most cases, you can derive the real address of the offsets by adding the executable image base address to the offset (obviously a little more work is required for XIP executables).

Deference the pointer and you get another offset (this time, it’s the native endian for the target). This is an offset you need to fix up. In most cases you can add the executable image base image to it and store it back. With XIP, you will need to work out how you can get the absolute address for the offset (not very difficult).

After you’ve gone through all reloc_count offsets, you’re done for this part.

GOT relocation

If your flags indicate that your program is PIC with GOT, you need to do some additional fixups.

At the start of your data section is a list of pointers terminated by a pointer value of -1. They need to be fixed up in the same way you fixed up relocation above.

Entry point

After all the relocation has taken place, you can simply jump to the base of the code section to run the executable.

Shared libraries

Shared libraries are equivalent to executables in bFLT. The executable linkage to the shared library is determined at compile-time rather than runtime.

Shared libraries are identified by numbers between 0-255. 0 and 255 are reserved.

During relocation, the high byte of the offset determines the library needed to complete the linkage.

For example, if the offset needed fixing during relocation was 0x030003a0, the fix up for that offset would be a pointer pointing to the offset 0x03a0 into the library identified by the number 0×03.

You would find the library associated with the number in the high byte, load it into memory, find the absolute address of the offset into the library and replace the fixup with that.

Using the same example, if I had a executable loaded into memory at 0×1000 and a library with an ID of 3, loaded into memory at 0×2000, the fix up for 0x030003a0 would be 0x23a0.

When a shared library is loaded, I believe you also need to enter its entry point to initialize the library before the main binary runs.

Shared libraries are, otherwise, loaded and treated exactly the same as a normal executable.

A movie player for NSpire. Finally.

I’ve been struggling for quite a while now on the best way to implement a movie player for the NSpire calculator. nPlayer was also born around the same time and I realised there were other’s trying to do the same thing as I. I had to gain an edge over them. I immediately identified a few things I could improve in nPlayer. First, nPlayer was closed source and secondly, it didn’t have decent video compression. From there, I set out on my journey to create a good movie player for the NSpire.

The first version I made was a failure. It worked but took way too much storage. I recall it was in the tens of megabytes for just over a minute.

Since then, I have been looking for ways to reduce the amount of storage needed for a video file. I looked at using run length encoding but I realised that if the video didn’t have simply the same data repeated all the time (which is basically all the time), run length encoding would actually take more storage than if I hadn’t used it.

At one point, I looked at porting libmpeg to the NSpire. After several failed attempts, I finally had something that ‘probably’ works. But I realised the converting process is too complicated. The library needs a pure mpeg2 stream and thats not so easy to produce. Eventually I gave up on that.

Next, I took a look at using zLib to compress the frames. This, however, only reduced sizes by around 10 percent maximum and that’s still not good enough.

After a long break, I realised that with videos, a lossy compression was needed or else the size wouldn’t reduce by much. And so, I decided to look at motion jpeg. However, I wasn’t successful to get it working on the NSpire.

Finally, I compromised. I decided to give up on porting a real video codec while still using lossy compression. I remembered that jpeg files compress extremely well and I decided I could concatenate a whole series of jpeg files together into a single file and have them uncompress on the spot as it was being played.

All that’s left was to find a library that would decode jpeg files. I found a one-shot C library that did exactly that. I would feed it jpeg data and it would spit out a decoded frame.

All that’s left is to process the buffer and convert the colors and draw them out.

And voila, that is how Nspire Movie Player was born!