Category Archives: Small Project

3D Printed Cord Wrap Tool for Microsoft Surface Pro 4

If you owned any good laptops, you might have a charger that had a curved shape, and/or a strap to help you wrap the cord. Well… The Microsoft Surface Pro 4 is an amazing computer but it’s charger doesn’t even have a strap. So I’ve decided to solve this problem with 3D printing.

3dmodelchargetinbutnotwrapped (Large)printed (Large)wrapped (Large)

The filament I used is actually black 3mm polyurethane filament, which is both strong and flexible. Printed using my Ultimaker2, upgraded with a Flex3Drive, at 250 degrees C, layer height of 0.2mm, and 200% extrusion.

Funny that the strap would’ve been too long to be printed straight, that’s why I made it squiggly.

The model file is shared as a public model on Onshape here. Go ahead and download it, or even copy it to your own account to make modifications.

3D Printed Dust Skirt for Nomad 883 Pro

I got a new Nomad 883 Pro and it generates a lot of dust. This is going to be a big problem as I need to cut material that have hazardous fibers. I decided to make a dust skirt (aka vacuum skirt or vacuum shoe or vacuum head) so that a vacuum can suck up dust as the machine cuts. I 3D printed this thing, which is partly PLA plastic, and the skirt is 3D printed TPU (polyurethane) filament. The skirt is two layered and the cuts are made in a interleaved pattern so there’s a better seal. 3D printing makes this project really easy, just clean up the print, superglue, and tap the hole for the screw. The vacuum hose is 1.25 inch diameter and it just shoves right in with a perfect fit.

screenshotoverviewsideviewfrontviewbottomview

The CAD files can be downloaded here

3D Printed Battery Recharge Dock for Parrot Rolling Spider

20150902_222523 (Large)

I got a Parrot Rolling Spider for fun. The batteries are 570mAH and the life is under 10 minutes, plus the reviews often mention that the batteries will lose their capacity quickly. Further research into this problem indicated that charging them slowly will alleviate this problem.

I wanted a few spare batteries and a way to recharge them. I decided to DIY a dock for them. I had a handful of spare parts, such as the MCP73831 and plenty of small perfboards. All I needed to do was 3D print something to hold the batteries in place, and this is what I came up with.

More pictures if you continue reading.
Continue reading

Ultimaker2 Bearing Spool and Bearing Guide Upgrade

This is an upgrade to the Ultimaker2 3D printer for people who have spools that do not fit the original spool holder, and spools that are too tight and thus do not feed smoothly, causing under-extrusion.

It is composed of two assemblies: a replacement for the filament guide and a replacement for the spool holder. Both utilizes ordinary skateboard bearings to achieve smooth rotation. The conical shape of the spool holder allows for any sized spool to be used, easily swapped because it uses a wing nut.

um2 spool holder upgrade angleum2 spool holder upgrade sideum2 spool holder upgrade cross section

um2 filament guide upgrade angleum2 filament guide upgrade sideum2 filament guide upgrade cross section

Files are available on YouMagine. I want to emphasize that I am sharing the STEP files, not just STL, because STL are harder for people to import and modify than STEP files. SolidWorks files are also provided.

The cross section images shows you how to assemble the upgrade parts. The screw diameters are #6 for the filament guide and 5/16″ for the spool holder. Please figure everything else out from the cross section images.

Q-Bot Tx Module for Taranis

Most micro (palm sized) quadcopters are RTF and comes with a crappy cheap transmitter, and I really want to use my awesome expensive Taranis. I found out that Q-Bot comes with a tiny transmitter module that I can connect to my Taranis.

I didn’t want some ugly thing dangling off of my Taranis so I decided to 3D print a module that will contain the Q-Bot transmitter circuitry and plug into the Taranis’ module bay, which fits “JR” style transmitter modules.

20141115_110602 (Large)
3d
20141115_110254 (Large)

and here is what it looked like before:
original

The 3D files (SLDPRT, STEP, STL) Continue reading

FrSky X4R-SB Smart Port hack and Naze32

Continuing from my previous FrSky X4R-SB hack (read for some context), I really wanted Smart Port telemetry to work with Naze32. I forked the original baseflight firmware and added two key new functionalities:

  • implemented the Smart Port telemetry protocol
  • GPS can be assigned to any serial port (as opposed to only one port)
    • this is important because we are running out of ports
    • I made it possible for GPS to be connected to software/bitbang serial, to free up a hardware UART

please read my fork’s wiki, at this time, I can only test with my limited hardware, more help testing/coding would be appreciated.

Update 10/26/2014: I was asked to make the same contribution to Cleanflight, which I have done today.

The new forked firmware requires a circuit modification on both the X4R-SB and Naze32, see pictures: Continue reading

FrSky X4R-SB S.BUS anti-invert hack

I am building a quadcopter using a FrSky Taranis X9D radio. It came with a FrSky X8R receiver. I wanted to keep my wiring clean by using the S.BUS feature on the FrSky receivers, I purchased a smaller FrSky X4R-SB receiver. The X8R has 8 PWM channel pins and the X4R-SB has 3 PWM channel pins, but if I use S.BUS (which is serial, not PWM), I can access 16 channels using only 1 pin, on both X8R and X4R-SB. The X4R-SB is much smaller, making it more ideal. (do not confuse the X4R-SB with the D4R-II, this is important, D4R-II uses CPPM, not S.BUS)

(update 10/25/2014: a follow up hack for Smart Port)

I want to use a Naze32 flight controller, which is open source and does have code to interpret S.BUS protocol. S.BUS is UART communication but it is inverted and the Naze32’s UART cannot accept inverted input. Some flight controllers, such as the Pixhawk, has a dedicated inverter just to solve this problem, but the Naze32 does not.

The first option is to buy a “S.BUS to CPPM converter” but CPPM is not a serial bus like S.BUS and thus does not have the advantages of being a serial bus. CPPM uses timing, timing needs to be measured (measuring things = possible error) and the signal edges can be affected by capacitance, noise, etc. Also having such a converter means there will be a tiny bit more latency in the system. These two disadvantages are probably too insignificant to notice performance wise. But I still didn’t want to spend another $13 + tax + shipping just to solve a problem that shouldn’t have existed in the first place.

The second solution is to buy an “inverter cable” which is a cable that has a NOT gate inline and then shrink wrapped. Or I can just buy a NOT gate and make the cable myself. I still didn’t want to spend the money. I opted to hunt down the inverter on the X4R-SB circuit instead, and connect a wire to the input of the inverter (labelled as “A” in the datasheet). This provides me access to the un-inverted signal that I can directly connect to the Naze32.

See the pictures below to understand how this hack was done.

identify_r25indentify_inverterinstructions

And just in case I confused you even more, all you need to do is connect a wire to the “A” pin.

I have tested it with Naze32 Rev5 and firmware f4d556c68876ccd5902bddf1cade32f1bb382c9f. Works like a charm.

It is probably possible to perform the same hack on a X8R but the X8R is constructed using two PCBs and the inverter is covered up by one of them. Separating the two PCBs is very difficult and risky.

The Smart Port (I think it’s also called S.PORT) is another inverted serial bus available on the X4R-SB and X8R but it is bidirectional. Since whatever you want to connect to it will need a bidirectional circuit anyways, it is not worth it to perform another surgery on the Smart Port. Also, the Naze32 can use SoftSerial to transmit in an inverted fashion, so a dedicated inverter isn’t even required. (SoftSerial would not work well for taking inputs, but outputs is OK)

3D Printed Raspberry Pi Case + Camera Case + Server

There is a law of the universe which states that if you own a Raspberry Pi and a 3D printer, you must print a case for it.

3d_trans20141018_193540 (Large)20141018_193504 (Large)20141018_193521 (Large)20141018_193530 (Large)3d_exp_bot3d_exp_top20141018_005438 (Large)20141018_005336 (Large)3d.fw

There are plenty of case designs for the original R-Pi Model B, and some for the R-Pi Model B+, but there are a few minor annoyances I noticed about them. Plus I really like DIY my own designs, so I designed my own case to suit my own needs.

  • Designed specifically for 3D printing, meaning careful attention to how plastic is extruded, no weak spots, and no overhangs. Plenty of fillets and chamfers.
  • No screws required. The case is held together using latches that take advantage of the plastic’s natural flexibility. It is designed for just sitting on a desk, or attached via velcro/double-sided-tape.
  • I also designed a small case for the camera, which follows the same principles.

These parts are because I am going to set up a web server for my 3D printer, running OctoPrint and also serving live video through the camera. I also setup a cron job to take a picture periodically and upload it to this server. I can also stream video to my Ustream channel. (neither of these servers are 24/7)

I am sharing all of the source files for the models, not just STL files. It is very annoying when people only share STL files, because STL are not import or editing friendly. With my SLDPRT file, you can change one height dimension inside and it will re-adjust the entire case, maybe if you need more clearance on the bottom for screws.

files for R-Pi case

files for camera case

3D Printed Tripod Adapter for Smartphones

I got a new 3D printer, a Ultimaker 2. After testing it out with some small test prints, I printed my first own custom design on this printer. (I’ve only designed for SLT printing previously and not extrusion printing before, this is my first design for extrusion printing).

It’s an adapter that holds my smartphone (Samsung Galaxy Note 3 with a wireless charging S-View flip cover case) and has threads (a 1/4″-20 threaded nut) so it can be mounted to a standard camera tripod. This phone has 4K video recording so why not?

The design is very custom because I need to consider the fact that I have a S-View flip cover case.

(I know I could also use threaded metal inserts, but nuts are easier to buy at the local Home Depot)

Continue reading

PS4 Laser Cut Stand

Summer is coming so I was worried about cooling the PS4. This stand lifts the PS4 off the desk a bit to give it more airflow. I had this cut by Ponoko, using 9mm thick clear acrylic. If you want to make your own, click here to download the EPS file, follow Ponoko’s instructions.

Another way is to 3D print them using black ABS, but I don’t have a 3D printer. The acrylic is left over from another project, hence why I used it.

Simple 6X USB Charger with Current Monitor

This is a simple 6 port USB device charger with a individual current monitor on each port. The charging current is indicated using RGB LEDs. Blue means slow charge (under 250mA), green means 250mA to 750mA, red means over 750mA, and purple means over 1500mA (for tablets). This circuit involves an ATmega328P (if you do hobby electronics, I bet you have plenty spares of these), INA169 (check out this breakout board), and a OKR-T10-W12.

While this project is not as impressive as my other projects in terms of difficulty, I soldered and Continue reading

Improved “Third Hand” Using Coolant Hose

squidhand_2

I don’t really like my “third-hand” tool so I decided to build a better one using flexible ball-jointed coolant spraying pipe hoses. It’s not a totally new idea, SparkFun even sells some of these parts as a kit. But my way is slightly better, and I got the hoses from eBay (look for “Flexible Water Oil Coolant Pipe Hose for Lathe CNC”) instead because SparkFun’s prices were excessively expensive.
Continue reading

Reverse Engineering and Cloning a S-View Flip Cover

I got a Samsung Galaxy Note 3 as soon as it was released. I wanted a S-View flip cover for it. S-View basically means the screen will automatically turn on and off when you open and close the cover. It is also able to reformat the display to show important notifications through the square viewing window of the cover, etc. The phone knows if the flip cover is opened or closed because there’s a tiny magnet inside the cover.

But all of the official S-View flip covers available are very expensive at about $60 each. The cheap covers might look like S-View covers, but they do not support the actual S-View functionality. But the cheap covers are about $5. I wanted to hack a $5 to give it S-View functionality. Continue reading

Wiimote Extension Code

C Library to Make DIY Wiimote Extensions with AVR Microcontrollers

This is a library that gives an AVR microcontroller the ability to act as a Wiimote extension controller (Nunchuk, Classic Controller, Guitar Hero 3 controller, Guitar Hero World Tour guitar controller, Guitar Hero World Tour drum controller, etc). The library has two parts: the I2C slave device and Wiimote protocol handling. It can be used with AVR-GCC, and it is possible to adapt it to work with Arduino if you know how to include the files into your sketch properly.

Continue reading

Frank’s Open Source Code Snippets and Libraries Collection

I have many projects, but some of them are just short code libraries and snippets that I don’t want to allocate an entire blog post for. For more information on each, visit the link and read the “readme” provided.

LufaUsbAspLoader, a USB bootloader that combines LUFA and USBaspLoader, so it can be used in low-speed USB devices

Arduino-UsiSerial-Library, written mostly for Trinket, works for all ATtiny microcontrollers with a USI

Adafruit-Trinket-USB, a small collection of libraries that enable USB capabilities for Trinket, and other ATtiny V-USB projects

Bootloader for Adafruit’s Trinket and Gemma

Turnigy ESC Programming Card Reverse Engineered

I replicated the functionality of a Turnigy ESC programming card. These programming cards are meant to configure electronic speed controllers (ESC). I always wanted to know how they work. Eventually I purchased one since I need one for my quadrotor helicopter’s ESC, and then I started playing with it.

It should be very simple to adapt the code to any microcontroller.

Continue reading

Arduino library to bring USB serial to XMEGA

https://github.com/frank26080115/LufaXmegaSerial/

I’m working on a XMEGA-A3BU Xplained board, along with Arduino IDE. (normally I’d stay away from anything related to Arduino but this time I’m forced). I connecting a FT232 for debugging is a pain so I modified LUFA and turned it into an Arduino library, so I can use print and println for debugging.

Bioscience Business Card

I am a big fan of creative business cards that actually represent who you are and what you do. In 2012, I was a coop student working for a biotech company in Ottawa, Spartan Bioscience. I wanted a card that is relevant to biology, and that got me thinking about microscopes.

Side note: this card is mentioned on The Wall Street Journal (click for the article & video), but she only mentions it briefly, she interviewed me about my other USB business card and I told her a bit about this card as well. This took place literally on the day I finished making this card.

card_on_notebook_thumb[1]

It is supposed to look like a microscope slide with a drop of blood. It says “use a microscope to see my DNA” on it.
Under a microscope…

under_microscope_thumb[1]

Continue reading

GG Button USB Modification

The GG button (link to original website) is a button that yells “GG” when you press it. Similar to the Staples Easy Button.
I modified it so that it has a USB port and it becomes a USB keyboard when you plug it into a computer. When you press the button, it types out a certain key sequence. The key sequence is such that it chats “GG WP” to an opponent in Starcraft II, and then surrenders the game (by pressing F10, then ‘n’).

Continue reading

Wireless Alarm for “Gas Stove Left On”

My uncle tells me that my grandparents have a tendency of turning on the gas stove, and then forgetting about it, then even leaving their home unattended. This is obviously dangerous. He asked me to make something to hang on the door so they know that the gas stove is still on.

The door and the kitchen are too far apart for a wired solution so I went with a wireless solution. It wasn’t technically challenging, but I made it super fast due to time constraints. No time to wait for a PCB to be manufactured and shipped. All made with parts from a local store instead of online shopping.

It’s basically a ATtiny2313 and some dirt cheap 433 MHz radios. It’s a simple protocol that is somewhat immune to interference, low power, and low bandwidth.

See album:

VEX Radio PPM Decoder

This is a PPM signal splitter for use with the VEX radio transmitter/receiver kit sold at All Electronics (item is now gone from their web site, this article itself is extremely old and outdated because newer technology has arrived)

For $30 at All Electronics, you can buy a 6 channel radio transmitter and receiver. The transmitter is excellent for $30, trim, scaling, mixing are all programmable on the transmitter itself and it stores several configurations. The receiver only has one output pin, which outputs a PPM signal which needs to be split into individual channels in order to be able to control servos.

If you put the receiver right side up and with the socket facing you, the pin on the far left is the Vdd pin, connect this to a regulated 5 volt power supply, the middle left pin is the PPM output pin (it is open collector so a pull up resistor is needed), and the middle right pin is the Vss pin, connect this to your circuit’s ground, the far right pin is not connected to anything inside the receiver.

vexrx_connections

The 6 channel PPM signal has 7 periods of high and low pulses, each of these pulses all start with a high period of 500 microseconds, and a low period of varying lengths. The first low period is a sync pulse with a fixed low period of about 7 milliseconds, this exceptionally long low period indicates the next rising edge of the PPM signal will indicate the pulse start for channel 1. The period from the rising edge to rising edge of the a pulse is equal to the period of the high pulse that should be sent to the servo.

vexppmlogicsession

 

#include <avr/io.h>
#include <avr/interrupt.h>

#define BAUD 9600 // define baud rate here
#include <util/setbaud.h>

#define width_500 ((F_CPU * 5) / 10000) //  calculates ticks for 0.5ms

// pin and port renaming

#define in_port PORTD
#define in_pinin PIND
#define in_ddr DDRD
#define in_pin 6

#define LED_A_pin 4
#define LED_B_pin 5

#define out_port PORTB
#define out_ddr DDRB

// global variables

static volatile unsigned long ovf_cnt; // overflow counter
static volatile unsigned char chan_cnt; // channel counter
static volatile unsigned char mask_cnt; // used to determin next pin
static volatile unsigned int chan_width[8]; // stores pulse width in clock ticks
static volatile unsigned int chan_width_temp[8];
static volatile unsigned int last_capt; // time of last capture, used to find difference
static volatile unsigned char data_ready; // 1 if data is good, 0 if transmitter is off
static volatile unsigned char next_mask; // next port mask to apply
static volatile unsigned char busy_flag;

// input capture interrupt vector
ISR(TIMER1_CAPT_vect)
{
        out_port = next_mask; // apply port mask to pulse pin
        mask_cnt++; // next pin

        unsigned long t_ovf = ovf_cnt; // store overflow counter in case another overflow occurs during interrupt
        ovf_cnt = 0;

        unsigned long t_icr = ICR1; // convert to unsigned long

        // calculate total time using overflows and time difference
        unsigned long t = ((t_icr | 0x10000) - last_capt) & 0xFFFF;
        if(t_icr < last_capt)
        {
                t_ovf--;
        }
        t += 0x10000 * t_ovf;
        last_capt = ICR1;

        // if pulse is longer than 3ms, then it's a sync pulse
        if(t > width_500 * 6)
        {
                chan_cnt = 0;
                if(data_ready == 0)
                {
                        data_ready = 1;
                }
        }
        else // if pulse is shorter than 3ms, then it's a servo pulse
        {
                chan_width[chan_cnt] = t; // store time
                if(busy_flag == 0)
                {
                        chan_width_temp[0] = chan_width[0]; chan_width_temp[1] = chan_width[1]; chan_width_temp[2] = chan_width[2]; chan_width_temp[3] = chan_width[3];
                        chan_width_temp[4] = chan_width[4]; chan_width_temp[5] = chan_width[5]; chan_width_temp[6] = chan_width[6]; chan_width_temp[7] = chan_width[7];
                }
                chan_cnt++; // next channel
                if(chan_cnt >= 4 && data_ready != 0) // last channel, data is now good, reset to first pin
                {
                        data_ready = 2;
                        mask_cnt = 0;
                }
        }
        next_mask = _BV(mask_cnt); // prepare mask
}

// timer overflow interrupt vector
ISR(TIMER1_OVF_vect)
{
        ovf_cnt++;
        if(ovf_cnt >= 7) // if too many, then transmitter is missing
        {
                data_ready = 0;
        }
}

int main()
{
        // initialize variables

        ovf_cnt = 0;
        chan_cnt = 0;
        mask_cnt = 0;
        data_ready = 0;

        MCUCR |= _BV(PUD); // no pull-ups

        // initialize ports

        out_port = 0;
        out_ddr = 0;

        in_ddr |= _BV(LED_A_pin) | _BV(LED_B_pin);
        in_ddr &= 0xFF ^ _BV(in_pin);

        // initialize serial port

        UBRRH = UBRRH_VALUE; // set baud rate
        UBRRL = UBRRL_VALUE;
        UCSRB = _BV(RXEN) | _BV(TXEN); // enable port

        // initialize timer

        TCCR1B = 1 | _BV(ICES1); // start timer, input capture on rising edge
        TIMSK = _BV(TOIE1) | _BV(ICIE1); // enable interrupts

        sei(); // enable global interrupts

        while(1)
        {
                if(data_ready == 2)
                {
                        // enable output if data is good, light LED
                        out_ddr = 0xFF;
                        in_port |= _BV(LED_A_pin);
                }
                else
                {
                        // disable output if transmitter is missing, LED off
                        out_ddr = 0;
                        in_port &= 0xFF ^ _BV(LED_A_pin);
                }

                busy_flag = 0;
                if(bit_is_set(UCSRA, RXC)) // if command received
                {
                        unsigned char ch = UDR;
                        if(ch != 0) // if not null command
                        {
                                UDR = data_ready; // send status
                                busy_flag = 1;
                                unsigned int t = chan_width_temp[ch - 1]; // fetch from array
                                unsigned char h = (t & 0xFF00) >> 8; // get high byte
                                unsigned char l = t & 0xFF; // get low byte
                                loop_until_bit_is_set(UCSRA, TXC); // wait for finish
                                UCSRA |= _BV(TXC); // clear finished flag

                                // send two bytes, most significant byte first
                                UDR = h;
                                loop_until_bit_is_set(UCSRA, TXC); // wait for finish
                                UCSRA |= _BV(TXC); // clear finished flag
                                UDR = l;
                                loop_until_bit_is_set(UCSRA, TXC); // wait for finish
                                UCSRA |= _BV(TXC); // clear finished flag
                        }
                }
        }
        return 0;
}

I’ve recently rewrote the code from scratch, this is actually version 2. This new version eliminates any timing errors because everything is handled by the 16 bit timer’s input capture feature. Timer overflows help determine whether or not the transmitter is missing, and if it is missing, the port is disabled.

The serial port can be used to retrieve the pulse width of the channels. The baud rate is defined when you compile the code. First send the channel number, then wait for a three byte reply, the first byte will be 0x01 if the data is good, or 0x00 if the transmitter is missing, the next two bytes is the width of the channel pulse as a 16 bit integer, most significant byte being sent first. Pulse width is given in clock cycles and thus it varies based on the clock frequency you choose to use.