Detroit Makerfaire 2014

I apologize for the mismash of this post, I don’t have a good way to do a huge photodump like this.  Anyways, here are the pics and video I took from Makerfaire Detroit 2014

 

Homemade CS Go Swag

Ben Heck recently visited a friend from Valve.  He had promised me some cool CS Go swag as I’ve played Counterstrike off and on for many years (since 1.2).  Unfortunately they didn’t have any CS Go swag and we got Portal swag instead, still pretty cool.

 

Well this was our typical tinker-Saturday and I had some new NeoPixels that I got from Sparkfun.  Ben started playing around with them and his acrylics.  He decided to do an edge lit acrylic experiment.  I suggested the CS Go logo so I’d have something cool for my desk.  We found a couple of suitable logos and then Ben edited the best ones into one that would work well for our acrylic.

 

We cut the log on two pieces of acrylic, one clear that appeared to work great for edge lit, and one frosted, which works better to diffuse a backlight.  Ben then 3D printed a base to fit the NeoPixels and the acrylic.  We put them together for some testing and it worked great.  I then took the project home, hooked everything up to my Teensy 2.0 board and modified the code to have a little more functionality so I could switch between the different modes.

 

Here is a video of it in action

 

And here is the Arduino code

NeoPixel data line is Pin2, interrupt is Pin5

#include <Adafruit_NeoPixel.h>

#define PIN 2

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic ‘v1’ (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 – 500 Ohm resistor on first pixel’s data input
// and minimize distance between Arduino and first pixel. Avoid connecting
// on a live circuit…if you must, connect GND first.

volatile unsigned int mode;
volatile boolean superBreakout;

void setup() {
strip.begin();
mode = 0;
superBreakout = 0;
pinMode(5, INPUT);
digitalWrite(5, HIGH);
clearWipe();
strip.show(); // Initialize all pixels to ‘off’
delay(50);
attachInterrupt(0, changeMode, FALLING);
}

void loop() {

if ( digitalRead(5) == HIGH){
superBreakout = 0;
}

switch (mode){

case 0:
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
// Send a theater pixel chase in…
// Send a theater pixel chase in…
theaterChase(strip.Color(127, 127, 127), 50); // White
theaterChase(strip.Color(127, 0, 0), 50); // Red
theaterChase(strip.Color( 0, 127, 0), 50); // Green
theaterChase(strip.Color( 0, 0, 127), 50); // Blue
// Send rainbow code
rainbow(20);
rainbowCycle(20);
theaterChaseRainbow(50);
break;

case 1:
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
break;

case 2:
// Send a theater pixel chase in…
theaterChase(strip.Color(127, 127, 127), 50); // White
theaterChase(strip.Color(127, 0, 0), 50); // Red
theaterChase(strip.Color( 0, 127, 0), 50); // Green
theaterChase(strip.Color( 0, 0, 127), 50); // Blue
break;

case 3:
// Send rainbow code
rainbow(50);
rainbowCycle(25);
theaterChaseRainbow(50);
break;

case 4:
rainbow(50);
break;

case 5:
rainbowCycle(25);
break;

case 6:
theaterChaseRainbow(50);
break;

case 7:
clearWipe();
strip.show(); // Initialize all pixels to ‘off’
break;

case 8:
mode = 0;
break;
}

}

void changeMode(){
if (superBreakout == 0){
mode++;
clearWipe();
strip.show(); // Initialize all pixels to ‘off’
superBreakout = 1;
while(digitalRead(5) == LOW);
}
}

void clearWipe(){
for (int i = 0; i < 8; i++){
strip.setPixelColor(i,strip.Color(0,0,0));
}
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
if (superBreakout)
break;
delay(wait);
}
}

void rainbow(uint8_t wait) {
uint16_t i, j;

for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
if (superBreakout)
break;
delay(wait);
}
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;

for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
if (superBreakout)
break;
delay(wait);
}
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
for (int j=0; j<10; j++) { //do 10 cycles of chasing
for (int q=0; q < 3; q++) {
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, c); //turn every third pixel on
}
strip.show();
if (superBreakout)
break;
delay(wait);

for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
for (int j=0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q=0; q < 3; q++) {
for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, Wheel( (i+j) % 255)); //turn every third pixel on
}
strip.show();
if (superBreakout)
break;
delay(wait);

for (int i=0; i < strip.numPixels(); i=i+3) {
strip.setPixelColor(i+q, 0); //turn every third pixel off
}
}
}
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r – g – b – back to r.
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return strip.Color(WheelPos * 3, 255 – WheelPos * 3, 0);
} else if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(255 – WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return strip.Color(0, WheelPos * 3, 255 – WheelPos * 3);
}
}

Components

Teensy 2.0 – https://www.sparkfun.com/products/12765

NeoPixel – https://www.sparkfun.com/products/12661

Great Glue Gun Recap!

I recently helped out behind the scenes of the two part Ben Heck Great Glue episode. I did the electronics design, assembly, and firmware for Ben. He put that with the mechanical part of the extruder, changed out the trigger, and packaged it up real nice for the episode. As he rarely does write ups I thought I’d post the code (pre hall effect) and the parts I remember using for others to follow in the great glue gun foot steps.

Here is a partial working demo early in the process

 

Here are the two episodes-

 

Original Parts – Sparkfun

H-Bridge $2.35 https://www.sparkfun.com/products/315

Trigger Pot (retired) https://www.sparkfun.com/products/retired/10314

SSR $4.95 https://www.sparkfun.com/products/10636

Proto board $2.95 https://www.sparkfun.com/products/8811

Wall Wart 9V $5.95 https://www.sparkfun.com/products/298

Thermistor 10k $1.95 https://www.sparkfun.com/products/250 (I think I ruined one and ended up using a 100k though)

RGB LED $.95 https://www.sparkfun.com/products/11120

 

By request I cross referenced what I could for Newark http://www.newark.com , they should be available at http://canada.newark.com/ as well

BenDuino (Ben’s custom Arduino Uno, link is similar but larger) – http://www.newark.com/arduino/a000066/dev-brd-atmega328-arduino-uno/dp/78T1601

H-Bridge – http://www.newark.com/texas-instruments/sn754410ne/ic-peripheral-drivers-half-h-36v/dp/08F8145

Trigger Pot – Sorry no cross reference for this sweet product 🙁

SSR – http://www.newark.com/sharp/s202s02f/ssr-pc-board-8a-80vrms-to-240vrms/dp/14N9588

Proto board with ground plane – No cross reference

Wall Wart 9V – http://www.newark.com/triad-magnetics/wsu090-0800-r/ac-dc-conv-external-plug-in-1/dp/83T4327

Thermistor 10k – http://www.newark.com/epcos/b57891m0103k000/thermistor-ntc-radial-leaded/dp/63W2796

Make sure to change the code to use the 10k, I ruined my 10k’s after a few prototypes, jbweld is too strong.  Anyways I used 100k’s, it’s an easy code change and 10k is more often used

RGB LED we used 10mm not a 5mm – http://www.newark.com/kingbright/l-154a4sureqbfzgew/led-multicol-rgb-5mm-x-bright/dp/66W1972

Code

#include <math.h>
#define MotorENPIN  3
#define Motor1APIN  2
#define Motor2APIN  4
#define Light1PIN  5
#define Light2PIN  6
#define minSpeed 50
#define maxSpeedLow   90
#define maxSpeedHigh  160
#define meltTemp 235
#define speedTempOffset 25
//#define SSRPIN    7
#define ThermistorPIN A0                 // Analog Pin 0
#define TriggerPIN  A1
//#define TempSetPIN  A2
boolean extruding = false;
boolean atTemp = false;
int maxSpeed = maxSpeedLow;
int updateCount = 0;
int setTemp = 0;
int reqSpeed = 0;
int setSpeed = 0;
int temp;
int count = 0;
float pad = 100000;                       // balance/pad resistor value, set this to
                                        // the measured resistance of your pad resistor
float thermr = 100000;                   // thermistor nominal resistance
float Thermistor(int RawADC) {          //converts thermistor reading into a resistance and then temperature in C
  long Resistance;
  float logVal;
  float tempTemp;  // Dual-Purpose variable to save space.
  Resistance=((1024 * pad / RawADC) – pad);
  logVal = 3950/log((float)100000/Resistance);
  //T2= T1*B/ln(R1/R2)  /  ( B/ln(R1/R2) – T1 )
  tempTemp = (25+273.15)*logVal;
  tempTemp = tempTemp / (logVal-(25+273.15));
  tempTemp = tempTemp – 273.15;  // Convert Kelvin to Celsius
  tempTemp = (tempTemp * 9.0)/ 5.0 + 32.0;                  // converts to  Fahrenheit
  return tempTemp;              // Return the Temperature
}
void setup() {
  Serial.begin(115200);
  pinMode(MotorENPIN, OUTPUT);
  analogWrite(MotorENPIN, 0);
  pinMode(Motor1APIN, OUTPUT);
  digitalWrite(Motor1APIN, LOW);
  pinMode(Motor2APIN, OUTPUT);
  digitalWrite(Motor2APIN, LOW);
  pinMode(Light1PIN, OUTPUT);
  digitalWrite(Light1PIN, HIGH);
  pinMode(Light2PIN, OUTPUT);
  digitalWrite(Light2PIN, LOW);
  //pinMode(SSRPIN, OUTPUT);
  //digitalWrite(SSRPIN, LOW);
  analogRead(ThermistorPIN);
  analogRead(TriggerPIN);
  //analogRead(TempSetPIN);
}
void loop() {
  int readTemp = Thermistor(analogRead(ThermistorPIN)); // read ADC and  convert it to F
  if ((readTemp > 0) && (readTemp < 500))
    temp = readTemp;
  //setTemp = analogRead(TempSetPIN);
  //setTemp = map(setTemp,0,1023,50,350);            //analog reading 0-1023, temperature range 50 to 350F
  if (temp <= meltTemp){                            //if less than set temp, turn on SSR, set lights
    //digitalWrite(SSRPIN, HIGH);
    digitalWrite(Light1PIN, LOW);
    digitalWrite(Light2PIN, HIGH);
    maxSpeed = maxSpeedLow;
    atTemp = false;
  }
  if ((temp > (meltTemp + 5)) && (temp <= meltTemp + speedTempOffset)){  //if greater than set temp but less than set temp + 10, set lights
    digitalWrite(Light1PIN, HIGH);
    digitalWrite(Light2PIN, HIGH);
    maxSpeed = maxSpeedLow;
    atTemp = true;
  }
  if (temp > (meltTemp + speedTempOffset + 5)){                        //if greater than set temp + 10, turn off SSR, set lights
    //digitalWrite(SSRPIN, LOW);
    digitalWrite(Light2PIN, LOW);
    digitalWrite(Light1PIN, HIGH);
    maxSpeed = maxSpeedHigh;
    atTemp = true;
  }
  reqSpeed = 1023 – analogRead(TriggerPIN);
  if (reqSpeed < 3){                                 //if less than 3 (deadzone) and was extruding, reverse the motor to suck in the gluestick
    if (extruding == true && count >= 450){
      analogWrite(MotorENPIN, 0);
      delay(50);
      digitalWrite(Motor1APIN, LOW);
      digitalWrite(Motor2APIN, HIGH);
      analogWrite(MotorENPIN, 125);
      setSpeed = 0;
      delay(150);
      analogWrite(MotorENPIN, 0);
      delay(50);
      extruding = false;
      count = 0;
    }
    else{                                              //if less than 3 (deadzone) and was not extruding or reverse timed out, turn off motor
      count = 0;
      analogWrite(MotorENPIN, 0);
      setSpeed = 0;
    }
  }
  else if (reqSpeed > 5 && atTemp == true){                              //if greater than 5 (deadzone), turn on motor mapped to stick, 5-1023 reading 50-150 motor, set extruding
    if (count < 450)
      count++;
    setSpeed = map(reqSpeed,5,1023,minSpeed,maxSpeed);
    digitalWrite(Motor1APIN, HIGH);
    digitalWrite(Motor2APIN, LOW);
    analogWrite(MotorENPIN, setSpeed);
    extruding = true;
  }
  if (updateCount <= 250)
    updateCount++;
  else{
    writeUpdates();
    updateCount = 0;
  }
  //writeUpdates();                                      //for debugging
}
void writeUpdates(){
  Serial.print(“Temp: “);
  Serial.print(temp,1);
  Serial.println(“”);
  //Serial.print(“Req Speed: “);
  //Serial.print(reqSpeed,1);
  //Serial.println(“”);
  //Serial.print(“Set Speed: “);
  //Serial.print(setSpeed,1);
  //Serial.println(“”);
}
As always code and parts list offered without warranty and very little support but you can always shoot me an email and I’ll see what I can do 🙂

 

Also, if you have questions regarding this project, I did a little write up on Element14, any Ben Heck questions and suggestions should go there, it’s a helpful community with better knowledge base than just me (though I do contribute a lot there).

 

Oh, and look for a reflow write up in a few weeks.  Ben ended up doing a few episodes on the toaster reflow oven I was working on at his shop.