Friction welding: Effective and Fun

Awhile ago I say this article on Hackaday http://hackaday.com/2014/12/30/3d-printing-technique-friction-welding/ on how to quickly and easily use friction welding on 3D prints.

I recently printed out a model of the Hubble Space Telescope to honor 25 years in space.  http://nasa3d.arc.nasa.gov/detail/HST

20150424_210407

The print was in several pieces and it need some assembly.

The technique is quite simple.  Put a piece of filament into a Dremel and push it into a joint.  You will need a smaller collet as the default one is too big.  I happened to have one from a set I purchased years ago.  Insert the filament with about 3/8″ sticking out.  Don’t worry if its not exactly straight it will fix itself with a little pressure.

20150503_151050I ran the speed on the Dremel at 3-4 which seemed to work fine for me.

Here is before: 20150503_151159And after:
20150503_151309Here are some more joints:

20150503_151210 20150503_150848

It works great it is quite easy and it seems to form a great bond.  Be ready to stop the Dremel and pull more filament out especially when you are filling a big joint.

Poor Mans Dual Color Prints (With one Print Head)

So what are you to do if you have only one print head like my replicator 2 has but you want to print two colors?  Some may give up and say “ya just can’t”.  I have already show that is not entirely true.  Remember my two color business cards?  http://www.3dprintmd.com/print/printed-business-cards/

Ok well some may say that this is cheating and this is not really two color printing.  It is merely using z-stop and changing colors.  Ok fine I get that, and I was not really satisfied with it either.

Lets take this concept one step farther.  How about printing around another object instead of on top of it?  Turns out, yep, you can do that that too.  It turns out to be relatively easy but with a ton of caveats.

First a word of warning.  If you do not pay close attention to what you are doing you could damage your printer.  Printing on top of another printer is not recommended for the inexperienced and it could cause your print head to crash into the first print or worse strip a belt or cause other damage.  I am not responsible for if you break your things.

Now with that mombo jumbo is out of the way…

Here is the goal:  I am printing a case for a usb adapter for the Old skool Sidewinder Joystick (http://www.descentbb.net/viewtopic.php?f=8&t=19061&sid=3da4f9e4089d6418b7a500aeab2aaa0c&start=160)

We didn’t want just any old case naw, that would be too easy.  How about one with a logo inlaid into the top.  Wells that’s easy enough if you have a two head printer.  But you only have one print head?  Well then challenge accepted!

Whats the problem you say with just printing one piece then printing another around it you may ask?  Well the problem comes when the second piece is printing the slicing engine does not know that it should not crash into the piece already printed.  Its needs to stay out of that area but there is no way for it to know how to do that.  It turns out that there is a happy accident awaiting to be discovered.

First prepare the model.  This is easy enough.

top

Top With .6mm deep hole in the shape of the logo

Justlogo

Logo .6mm Thick

logo

Top and Logo aligned

I have only done one of these and it is possible that I just simply got lucky with the design.  The design needs to be simple and should not have any holes in the middle of it.  Other design limitation may exist but I have not done enough of them to know for sure.  The design will play out in the next several step to see if its a viable option.  Please note that the inlay is exactly .6mm thick.  I will be printing with .3mm layer height and this will amount to exactly 2 layers being printed.  I would NOT go any higher than this.  The nozzle is an upside down cone shape and therefore gets bigger the farther away from the build pate you go limiting how close you can get to the first print.

Set up the slicer.

Here is what NOT TO DO and the reason why

Makerware is not an option for printing since the tool path algorithm likes to use any empty space round the object being printed.

If we slice with makerware there is nothing you can do to get the travel moves to not cross into what would already be printed.  Remember that we will be printing the logo first and the box around it must not cross into the logo area.  Otherwise, the print head will crash into it.

Makerware is a no go.  Travel moves cross into the logo area.

Makerware is a no go. Travel moves cross into the logo area.

So what can we do instead? ReplicatorG to the rescue.  I know what your are saying ugg not RepG that thing is so hard to understand and confusing.  Yea I get that too but in this case there is a happy accident in the slicing engine that is going to save the day.

It turns out that when RepG slices it tends to only follow the perimeter (in this case interior) of the object when doing travel moves.  Why it does this is somewhat of a mystery to me but, at least for this object it works out perfectly.

First edit your slicing profile to show the tool paths (or to make it easy you can copy mine. Replicator 2 – 340 micron)

In order to make sure that the travel moves don’t go where they should not go.  Go to the Craft tab and activate Skeinlayer

Activate Skeinlayer

Activate Skeinlayer

Then go to the Export tab and enable Analyze Gcode

Analyze Gcode

Analyze Gcode

Now when you slice you will get a Skeinlayer popup.

When you open you stl files make sure that if you change the location on the build platform you make the exact same changes to both the logo and the top.  These parts must be exactly aligned.

VERY IMPORTANT Pay very close attention to the grey lines.  These are travel moves and the MUST NOT cross into the Logo area.

Layer #0. Check All layers with the logo in it

Layer #0. Check All layers with the logo in it

Layer #1. Check All layers with the logo in it

Layer #1. Check All layers with the logo in it

Layer2.  The logo is gone since it was only 2 layers .6mm tall

Layer2. The logo is gone since it was only 2 layers .6mm tall

Now that we have the top sliced we can slice the logo with the same settings then print.

First load the logo color and print the logo as normal.  I am using the wipe in my profile so I need to peal that away before the next print.

Logo printed

Logo printed

wipe removed

wipe removedNow change filament colors and print the top.

20141222_211151

20141222_211157 20141222_211253 20141222_211259 20141222_211344 20141222_211517 20141222_211731 20141222_211804 20141222_211903 20141222_212116

Print complete and it looks great.  The bond is amazing.  It looks as of it was printed all in one piece.

20141222_212317

20141222_212345

Here is black on red

20141215_23032720141221_124028

Wow that was a long post.  Thanks for sticking with me.  Hopefully I have proved that you can do two color with a single print head.

LED lights – Auto off after 0-3 minutes – Update 1 of 2

I have a two year old and she likes to play inside one of the kitchen cabinets.  I would imagine that it gets dark in there when she closed the door, so I decided to puts some lights in there.  Being a 2 year old she likely to burn through some batteries so I though I could do a bit better than a simple on/off switch.

To be honest I have been wanting to do something with a 555 for a long time.  I picked one up from Radio Shack back in January 2003.  Now there is a need, so now is the time.

I basically used this article as a basis http://www.instructables.com/id/555-Timer/?ALLSTEPS.

I easily had all the parts so it was just a matter of assembly.

I will be using the 555 in the mono-stable mode circuit.

FSYCYIOH799760K

The only differences I made is that the control resistor shown here as a 10k ohms has been replaced with a 500k potentiometer/preset and the control capacitor shown here was replaced by a 330uF cap (since that’s the closest I had).  These values workout to a timeout of 0-181.5 seconds, right in the range that I was looking for.

In this case I also decided not to go all out and do a circuit diagram an etch a PCB.  This is a simple enough circuit I can just use some perfboard without the fuss.

Here is my result. 20141130_205152
It actually came out quite nice.  It has one button that starts the timer and turns on the 3 white LEDs.   The button does on nothing while the lights are on so in order to keep them on you have to hit the button every time they turn off.

LEDs stand off the board for max dissipation in a case I will make next.

LEDs stand off the board for max dissipation in a case I will make next.

Bottom side

Bottom side

Massive 330uF radial cap and an 805 10pF cap under it.

Massive 330uF radial cap and an 805 SMD 10pF cap under it.

This will be powered by a 9v battery which will hopefully last a while at 2min duty cycles.  I am not sure what the current draw is when idol (I may measure this later) but I think I will add an on off slider switch.

The next step is to make a case.  I have some ideas on what I want to do with the case but I do know that it is going to have to be rugged enough for a 2 year old to be pounding on it every 2 mins.  I was thinking that would be similar in design to the staples easy button but I will see how that pans out.

That’s all for now hopefully I can get the case done soon and I will post the second update to this post once it is done.

Fuse – Welding filament clamp for 3D printer

Back in July I back a project https://www.indiegogo.com/projects/fuse-welding-filament-clamp-for-3d-printers.  This looked like a neat idea.  Basically it has a heater in the center of a Teflon block and a 1.75mm hole in it.  20140707025312-Slide_1

You put one end of filament in one side and another piece in the other push it through and it welds the two pieces together.

I received my Fuse today.  Here is what I got.

20141114_211810 20141114_211819 20141114_211901 20141114_211913Overall construction is good, no issues there.  It looks well machined and assembled.  Of coarse the next step it to plug it in an give it a try.

This is my first attempt.  It looks  pretty ugly.  The filament squished out into the slit around the 1.75mm channel.  I had the screws tightened by hand the best I could.  I did not try tightening them with pliers since I did not want to damage the thumb screws.

20141114_222423

20141114_222451

Needless to say its not idiot proof as it take some getting used to.  Eventually after some practice I did start to get some usable joins.  This is one of the better ones that I was able to do.
20141114_222657

Same join as above compared to another one that is poor.  You can see that the white part is bulged out.  20141114_222733

Initial reaction based on 1 hr of use (yes I know that hardly makes me an expert).

The idea is solid;melt the ends and jam them together.  This is a bit more challenging to pull off than you might think.  To be fair I am using PLA which is probably the most difficult material to work with due to its low glass transition temperature.  I found that the melting was difficult at best to control.  PLA just loves to melt and deform as I learned from my experience with the http://www.filastruder.com/.   This does not mean that I don’t think it can work.  It does take some practice and lots of retries but with time I think that I can do much better.  Unfortunately, due to its difficulty of use (right out of the box with no experience) I don’t think that we will see  wade spread use of this product.

My next step will be to make some multicolored filament and do some printing with it.  I am somewhat concerned with how the printer will handle the transition, especially when the filament is not perfectly consistent in diameter.  From everything I know and read I dont think its going to be a big deal, assuming that there are not any bulges that make the filament jam in the hot-end.

More post on this topic to come.

Sensor Data – Troubleshooting 1

Status

Well that did not take long.  I got my fist failure with the LED status indicators and only the green light is lit which narrows it down to only one line; “DHT22.acquire();”  Now I need to dig deeper into this library.  Its been a while since I checked the code there may even be an updated version.

Sensor Data – Part 2

So I have been neglecting my temperature and humidity sensor.  I haven’t had it in my filament box because the battery does not last long enough and it occasionally hangs up.  I am attempting to address the latter first.  I added 4 more leds (total of 5) to try to find where in the code it is hanging.

Here is the new config:

20140901_140221

And the code:


// This #include statement was automatically added by the Spark IDE.
#include "idDHT22/idDHT22.h"
#include ;

// declaration for DHT11 handler
int idDHT22pin = D4; //Digital pin for comunications
void dht22_wrapper(); // must be declared before the lib initialization

// DHT instantiate
idDHT22 DHT22(idDHT22pin, dht22_wrapper);

char message[75]={0};
//char shortmessage[62] ={0}; //events have a limit of 63 bytes
String rmessage = "";
String smessage="";
double Humidity =0;
double degF = 0;
double degC = 0;
double DewPoint = 0;
double DewPointSlow = 0;
int result;
int greenled = 5;
int redled = 3;
int orangeled = 2;
int yellowled = 1;
int blueled = 0;

void setup()
{

	pinMode(greenled, OUTPUT);
	pinMode(redled, OUTPUT);
	pinMode(orangeled, OUTPUT);
	pinMode(yellowled, OUTPUT);
	pinMode(blueled, OUTPUT);
	
	Spark.variable("message", &message, STRING);
	//Spark.variable("Humidity", &Humidity, DOUBLE);
	//Spark.variable("degF", &degF, DOUBLE);
	//Spark.variable("degC", &degC, DOUBLE);
	//Spark.variable("DewPoint", &DewPoint, DOUBLE);
	//Spark.variable("DewPointSlow", &DewPointSlow, DOUBLE);
}
// This wrapper is in charge of calling
// mus be defined like this for the lib work
void dht22_wrapper() {
	DHT22.isrCallback();
}
void loop()
{

	digitalWrite(greenled, HIGH);   // turn the LED on (HIGH is the voltage level)
  
 
 
	//Serial.print("\nRetrieving information from sensor: ");
	//Serial.print("Read sensor: ");
	//delay(100);
	DHT22.acquire();
	digitalWrite(redled, HIGH);
	while (DHT22.acquiring());
	
	digitalWrite(orangeled, HIGH);
	result = DHT22.getStatus();
	switch (result)
	{
		case IDDHTLIB_OK:
			//Serial.println("OK");
			break;
		case IDDHTLIB_ERROR_CHECKSUM:
			//Serial.println("Error\n\r\tChecksum error");
			break;
 		case IDDHTLIB_ERROR_ISR_TIMEOUT:
			//Serial.println("Error\n\r\tISR Time out error");
			break;
		case IDDHTLIB_ERROR_RESPONSE_TIMEOUT:
			//Serial.println("Error\n\r\tResponse time out error");
			break;
		case IDDHTLIB_ERROR_DATA_TIMEOUT:
			//Serial.println("Error\n\r\tData time out error");
			break;
		case IDDHTLIB_ERROR_ACQUIRING:
			//Serial.println("Error\n\r\tAcquiring");
			break;
		case IDDHTLIB_ERROR_DELTA:
			//Serial.println("Error\n\r\tDelta time to small");
			break;
		case IDDHTLIB_ERROR_NOTSTARTED:
			//Serial.println("Error\n\r\tNot started");
			break;
		default:
			//Serial.println("Unknown error");
			break;
	}
    
    digitalWrite(yellowled, HIGH);
    Humidity = DHT22.getHumidity();
    degF = DHT22.getFahrenheit();
    degC = DHT22.getCelsius();
    DewPoint = DHT22.getDewPoint();
    DewPointSlow = DHT22.getDewPointSlow();
    
    rmessage = "";
    smessage = "";
    sprintf(message, "{\"Humidity\":%3.4f,\"degF\":%3.4f,\"degC\":%3.4f,\"DewPoint\":%3.4f,\"DewPointSlow\":%3.4f}", Humidity, degF,degC,DewPoint,DewPointSlow);
    //rmessage = "{\"Humidity\":" + doubleToString(Humidity,4) + ",\"degF\":"+ doubleToString(degF,4) + ",\"degC\":" + doubleToString(degC,4) + ",\"DewPoint\":" + doubleToString(DewPoint,4) +",\"DewPointSlow\":" + doubleToString(DewPointSlow,4) + "}";
    //message = doubleToString(Humidity,4) +","+ doubleToString(degF,4) +","+ doubleToString(degC,4) +","+ doubleToString(DewPoint,4) +","+ doubleToString(DewPointSlow,4);
    //rmessage = "I hate this sooooooo much";
    
    
    //smessage = doubleToString(Humidity,4) +","+ doubleToString(degF,4) +","+ doubleToString(degC,4) +","+ doubleToString(DewPoint,4) +","+ doubleToString(DewPointSlow,4);
    //Spark.publish("TempData",smessage);
    
    digitalWrite(blueled, HIGH);
    delay (2000);
    
    digitalWrite(greenled, LOW);
    digitalWrite(redled, LOW);
    digitalWrite(orangeled, LOW);
    digitalWrite(yellowled, LOW);
    digitalWrite(blueled, LOW);    // turn the LED off by making the voltage LOW
    
	//Spark.sleep(900);
	delay(30000);
}

//Rounds down (via intermediary integer conversion truncation)
String doubleToString(double input,int decimalPlaces){
    if(decimalPlaces!=0){
        String string = String((int)(input*pow(10,decimalPlaces)));
        if(abs(input)<1){             if(input>0)
            string = "0"+string;
            else if(input<0)
            string = string.substring(0,1)+"0"+string.substring(1);
        }
        return string.substring(0,string.length()-decimalPlaces)+"."+string.substring(string.length()-decimalPlaces);
    }
    else {
        return String((int)input);
    }
}

If you are interested here is a graph of the data:

All of the data
All of the data
Typical Day
Typical Day

Spark Core Data to Google Docs from Raspberry Pi

If you read my previous post you can see I was using powershell to write data to a CSV file locally on my PC.  This was not a great solution because my PC had to be running at all times in order to get the data.  I decided to use my Raspberry Pi as a server to collect the data and have it push the data to Google Docs.  Here is what I came up with:

#!/usr/bin/python
import time
import gdata.spreadsheet.service

import urllib2
import json
import time

##########Make Changes in this section
#the URL for your spark core
URL = 'xxxxxxx'
#Your gmail email to login to google docs with
email = 'xxxxxx'
#you gmail password
password = 'xxxxxxxx'

# Find this value in the url with 'key=XXX' and copy XXX below
spreadsheet_key = 'xxxxxxx'
# All spreadsheets have worksheets. I think worksheet #1 by default always
# has a value of 'od6'
worksheet_id = 'od6'

#########Done with the changes

while True:
 response = urllib2.urlopen(URL)
 response = response.read()
 response = json.loads(response)

 result = response["result"]
 result = json.loads(result)

 Humidity = result["Humidity"] 
 degF = result["degF"]
 degC = result["degC"]
 DewPoint = result["DewPoint"]
 DewPointSlow =result["DewPointSlow"]

 weight = '180'

 spr_client = gdata.spreadsheet.service.SpreadsheetsService()
 spr_client.email = email
 spr_client.password = password
 spr_client.source = 'Python runing on pi'
 spr_client.ProgrammaticLogin()

 # Prepare the dictionary to write
 dict = {}
 dict['date'] = time.strftime('%m/%d/%Y')
 dict['time'] = time.strftime('%H:%M:%S')
 dict['humidity'] = str(Humidity)
 dict['degf'] = str(degF)
 dict['degc'] = str(degC)
 dict['dewpoint'] = str(DewPoint)
 dict['dewpointslow'] = str(DewPointSlow)
 #print dict

 entry = spr_client.InsertRow(dict, spreadsheet_key, worksheet_id)
 if isinstance(entry, gdata.spreadsheet.SpreadsheetsList):
 print "Insert row succeeded."
 else:
 print "Insert row failed."
 time.sleep(300) # delays for 300 seconds 

You need to install the gdata python library here is how to do that (thanks to  http://www.mattcutts.com/blog/write-google-spreadsheet-from-python/)

mkdir ~/gdata
(download the latest Google data Python library into the ~/gdata directory)
unzip gdata.py-1.2.4.zip (or whatever version you downloaded)
sudo ./setup.py install

This script just loops forever and sends an update to the spreadsheet every 5 mins (this might be too often).

I might get fancy and make this a service but for now you can just run it in the background with &

This project is still not done for me.  Next I will be working to Reduce the power consumption by using sleep mode of the core Spark.sleep().  This puts the core in low power mode for a time.  In order to do this I need to change the core script to push data instead of updating all the time.  To do this I will use Spark.publish() to publish an event when it takes a reading.  Then the script can pull that event when ever it gets around to it.

Sensor Data

Here is a graph of the sensor data I collected with the sensor in the box.

Tempature Graph

The battery only lasted about 46 hours.  I would consider this the worst case for the battery usage since I was not doing anything to reduce consumption.  One simple thing to do is to use the Spark.sleep() instead of just delay() that I am using now.  This will put the core into sleep mode with low power consumption.  I am testing this now to see how much it helps.

The next big thing to do is to push the data instead of having the core serve the data.  This way the core can be sleeping and only wake up when a reading is needed.  This seem easy to do also using the Spark.publish() which generates an event that can be collected. There is a nice write up on on how to increase battery life https://learn.adafruit.com/low-power-wifi-datalogging/battery-life-and-current-consumption

I will post a follow-up once I get more data and do more tests.