O-Ring Plug

Posted on June 26th, 2009

Use an material for the o-ring which is compatible for both water and the type of oil you’re using.

one design I just ran across this morning on one of our exhibits (designed to hold a vacuum, but that’s just the inverse of what you want to do ;) ):

A cap with a clearance fit into your tube, a plug with a gland for an o-ring, and use three screws to squeeze them together and expand the o-ring against the tube.
o-ring_end_plug.pdf

The 10 Commandments of Wireless Communications

Posted on February 18th, 2009

This is a repost from Mike Fahrion of BB-Electronics which has a great technical library.  I’m putting it up here because it’s so good, I’d hate for it to disappear off the web.

Follow these rules, and you’ll have happy Wireless.  Ignore them, and experience BER!

10 Commandments of Wireless Communications

(more…)

Some sample code to ignore!

Posted on February 13th, 2009

/*Pier Piling Pivot Arduino control program
by Earl Stirling for the explOratorium
installed on Fort Mason Piers
*/
/*
version 0.813
07/jan/2009
*/

/*This is a state machine.
This program counts on tight(ish) loops with no stalling.
I recommend using anything that stalls, the functions delay() or delayMicroseconds(),
they’re unnecessary, and you might miss a timeout
*/

/*

*/

//These are the states that the machine can be in.
//Entries in this enum should match the state_table pointer.
enum
{
WTG_FOR_BUTTONPRESS = 0,
ASCENDING,
UP,
DESCENDING,
DOWN,
ERROR,
curr_state_LIMIT
}
curr_state, prev_state = WTG_FOR_BUTTONPRESS;

//This table contains a pointer to the function to call in each state.
//These must match the enums for curr_state
void (*state_table[curr_state_LIMIT])() =
{
WtgForButtonpress,
Ascending,
Up,
Descending,
Down,
Error
};

//these constant defines are the correct place to change timeout values, pin values, etc.
#define KEEPUPTIME   120           //should be 120, change before deployment // timeout in seconds to keep the piling up
#define HOLDDOWNTIME 4         // time in seconds to keep the piling down before next ascent
#define MOVEMENTTIME 60        // time in seconds for maximum time to move the piling

#define BUTTONPINNUMBER     2  //the pin that the button is attached to
#define UPPERLIMITPINNUMBER 3  //the pin that the upper limit switch is attached to
#define LOWERLIMITPINNUMBER 4  //the pin that the lower limit switch is attached to
#define INSECTORPINNUMBER   5  //the pin for detecting that the mechanism is in normal operating range
#define RAISEMOTORPINNUMBER 6 //the pin for the relay to raise the piling
#define LOWERMOTORPINNUMBER 7 //the pin for the relay to lower the piling
//#define MOTORBRAKEPINNUMBER 8 //the pin for the relay to release the motor brake

#define ledPin  13  //the pin attached to the LED

long StartMovementTime;

int error_code, spinner = 0, thistime = 0;

//Limit switch values
enum {
MADE,
NOTMADE}
UpperLimitSwitch,
LowerLimitSwitch,
InSectorSensor;

//UI button value
enum {
PRESSED, NOTPRESSED}
Button;

//MOTOR CONTACTS!
//which motor contacts you’re calling
typedef enum {
RAISE, LOWER}
Motor_Contacts;

#define RAISE RAISEMOTORPINNUMBER
#define LOWER LOWERMOTORPINNUMBER
//#define brake MOTORBRAKEPINNUMBER

//motor actions you’re calling for
#define OFF  0
#define ON   1

//TIMERS!
//Timer values (should make this an array of type timertypes)
//int UpCountdownTimerValue, HOLDDOWNTIMERValue, ReversalCounterValue;
//TimerState UpCountdownTimer, HoldDownTimer;

//Actions you can call for the Timers
typedef enum {
START, RESET, EXPIRE, CHECK}
Timer_Actions;
#define START 0
#define RESET 1
#define EXPIRE 2
#define CHECK 3

//enumeration of the types of timers
typedef enum {
HOLDDOWN, KEEPUP, MOVEMENT, TIMERS_LIMIT}
Timers_new;
#define HOLDDOWN 0
#define KEEPUP 1
#define MOVEMENT 2

//states in which the timers can exist
typedef enum {
EXPIRED, CURRENT}
TimerState;
#define EXPIRED 0
#define CURRENT 1

void setup()
{
Serial.begin(9600); //setup serial output port
delay(3000);
//Send a string of CTRL-R’s to reset the LCD to 9600 baud
// for (int i=5000; i != 0 ; i–) {Serial.print(0×12,BYTE); };

// Initialize counters, flash LED’s, turn off outputs

//Initialize LCD display
//first set to 20 characters wide
Serial.print(0×7C,BYTE);
Serial.print(0×03,BYTE);
delay(128);

//then set to 4 lines long
Serial.print(0×7C,BYTE);
Serial.print(0×05,BYTE);
delay(128);

//clear display
Serial.print(0xFE,BYTE);
Serial.print(0×01,BYTE);
delay(128);

//turn display on
Serial.print(0xFE,BYTE);
Serial.print(0×0C,BYTE);
delay(128);

/*
//Set up splash screen for LCD
lcd_cursor(1,1);
Serial.print(”Pier Piling Pivot”);
Serial.print(”version 0.81″);
//delay(128);

//now save the current screen as the splash to the LCD’s NVRAM
Serial.print(0×7C,BYTE);
Serial.print(0×10,BYTE);
//delay(128);
*/
lcd_cursor(1,1);
Serial.print(”Starting setup     “);

pinMode(BUTTONPINNUMBER, INPUT);
pinMode(UPPERLIMITPINNUMBER, INPUT);
pinMode(LOWERLIMITPINNUMBER, INPUT);
pinMode(INSECTORPINNUMBER, INPUT);

pinMode(RAISEMOTORPINNUMBER, OUTPUT);
pinMode(LOWERMOTORPINNUMBER, OUTPUT);
//pinMode(MOTORBRAKEPINNUMBER, OUTPUT);

pinMode(ledPin, OUTPUT);

MotorContact (LOWER, OFF);
MotorContact (RAISE, OFF);

lcd_cursor(1,1);
Serial.print(”Done with setup    “);
};

// * * Begin State Functions * *

void Down()
{
/* Piling is down, wait for the hold down timeout, then
transition to waiting for someone to press the button.*/
poll();

for (int i=(HOLDDOWNTIME - 1); i != 0 ; i–)
{
//delay(128);
//move to 0,0
lcd_cursor(2,1);

Serial.print(”Hold Down: “);
Serial.print(i);
Serial.print(”      “);
}
curr_state = WTG_FOR_BUTTONPRESS;
}

void Error()
{
//digitalWrite (brake,LOW);

lcd_cursor(2,1);
Serial.print(”Error “);Serial.print(error_code);Serial.print(”             “);
switch (error_code)
{
case 2 :   lcd_cursor(4,1);Serial.print(”Movement Sector     “); break;
case 1 : lcd_cursor(4,1);Serial.print(”Movement Timeout    “); break;
};

MotorContact (LOWER, OFF);
MotorContact (RAISE, OFF);
for (int i=error_code; i != 0 ; i–)
{
digitalWrite(ledPin, HIGH);   // sets the LED on
delay(1000);                  // waits for a second
digitalWrite(ledPin, LOW);    // sets the LED off
delay(1000);                  // waits for a second
};
}

void WtgForButtonpress()
{
/* Hang around waiting for some curious kid to press the button. */
//Serial.print(”WtgForButtonpress”);
poll();

if ((InSectorSensor == MADE) and (Button == PRESSED))
{
MotorContact (RAISE,ON);
StartMovementTime = millis();
//lcd_cursor(2,1);Serial.print(”Start Movement Time (sec)”);Serial.print(StartMovementTime/1000);
curr_state = ASCENDING;
}
}

void Ascending()
{
// When the piling reaches the top, stop raising it.
//Serial.print(”Ascending”);
poll();

MovementErrorCheck();
if ((curr_state != ERROR) and (UpperLimitSwitch == MADE))
{
MotorContact(RAISE,OFF);
curr_state = UP;
}
}

void Descending()
{
// When the piling reaches the bottom, stop lowering it.
//Serial.print(”Descending”);
poll();

MovementErrorCheck();
if ((curr_state != ERROR) and (LowerLimitSwitch == MADE))
{
MotorContact(LOWER,OFF);
curr_state = DOWN;
}
}

void Up()
{
/* If the timer expires or the button is pressed, lower
the piling (check that lower switch isn’t hit) .*/
//Serial.print(”Up”);
poll();

for (int i=(KEEPUPTIME - 1); i != 0 ; i–)
{
//delay(128);
lcd_cursor(2,1);Serial.print(”Keep Up: “);
Serial.print(i);
}
if (InSectorSensor == MADE)
{
MotorContact (LOWER,ON);
StartMovementTime = millis();
//lcd_cursor(2,1);Serial.print(”Start Movement Time (sec)”);Serial.print(StartMovementTime/1000);
curr_state = DESCENDING;
}
}

// * * End of State Functions * *

void poll()
{
thistime = (millis()/1000) % 4;
if (spinner != thistime)
{
lcd_cursor(1,20);
spinner = thistime;
//Serial.println(spinner);
switch (spinner)
{
case 0:
//print
Serial.print(”>”);
break;
case 1:
//print an Up arrow
Serial.print(”v”);
break;
case 2:
Serial.print(”<”);
break;
case 3:
Serial.print(”^”);
break;
}
};

if (prev_state != curr_state)
{
lcd_cursor(1,1);
Serial.print(”                   “);
lcd_cursor(1,1);
Serial.print(curr_state);
prev_state = curr_state;
}

if (digitalRead(BUTTONPINNUMBER) == HIGH)
{
if (Button != PRESSED) {lcd_cursor(3,1);Serial.print(”Button is PRESSED   “);}
Button = PRESSED;
}
else
{
if (Button != NOTPRESSED) {lcd_cursor(3,1);Serial.print(”Button is NOT-PRESSED   “);}
Button = NOTPRESSED;
//Serial.print(”Button is NOTPRESSED”);
}

if (digitalRead(UPPERLIMITPINNUMBER) == HIGH)
{
if (UpperLimitSwitch != MADE) {lcd_cursor(3,1);Serial.print(”Upper Limit MADE    “);}
UpperLimitSwitch = MADE;
}
else {
if (UpperLimitSwitch != NOTMADE) {lcd_cursor(3,1);Serial.print(”Upper Limit NOT-MADE    “);}
UpperLimitSwitch = NOTMADE;
//Serial.print(”UpperLimitSwitch is NOTMADE”);
}

if (digitalRead(LOWERLIMITPINNUMBER) == HIGH)
{
if (LowerLimitSwitch != MADE) {lcd_cursor(3,1);Serial.print(”Lower Limit MADE    “);}
LowerLimitSwitch = MADE;
}
else {
if (LowerLimitSwitch != NOTMADE) {lcd_cursor(3,1);Serial.print(”Lower Limit NOT-MADE    “);}
LowerLimitSwitch = NOTMADE;
//Serial.print(”LowerLimitSwitch is NOTMADE”);
}

//Serial.print(”insectorpinnumber is “);Serial.print(digitalRead(INSECTORPINNUMBER));
if (digitalRead(INSECTORPINNUMBER) == HIGH)
{
if (InSectorSensor != MADE) {lcd_cursor(3,1);Serial.print(”In Sector MADE      “);}
InSectorSensor = MADE;
}
else
{
if (InSectorSensor != NOTMADE) {lcd_cursor(3,1);Serial.print(”In Sector NOTMADE   “);}
InSectorSensor = NOTMADE;
}
}

//** Begin Service Functions & Procedures**

//function call to twiddle the contacts
void MotorContact (int contact, int action)
{
//Serial.print(”Setting Motor Contact “); Serial.print(contact);
if (action == ON)
{//digitalWrite (brake,HIGH);
digitalWrite (contact,HIGH);
//Serial.print(” HIGH”);
}
else
{//digitalWrite (brake,LOW);
digitalWrite (contact,LOW);
//Serial.print(” LOW”);
}
};

void MovementErrorCheck()
/*function call to check for errors while moving
will change state to ERROR if there is a movement error,
and throw a code to serial output */
{
//Serial.print((millis()-StartMovementTime)/1000);
if (((millis()-StartMovementTime)/1000) > MOVEMENTTIME)
{
curr_state = ERROR;
error_code = 1;
lcd_cursor(2,1);Serial.print(”Err Movement Timeout”);
};
if (InSectorSensor == NOTMADE)
{
curr_state = ERROR;
error_code = 2;
lcd_cursor(2,1);Serial.print(”Err Out of Range    “);
}
};

void lcd_cursor(int row, int column)
{
int cursor_position, offset;

switch (row)
{
case 1:
offset = 0;
break;
case 2:
offset = 64;
break;
case 3:
offset = 20;
break;
case 4:
offset = 84;
break;
}

cursor_position=offset+column+127;

Serial.print(254,BYTE);
Serial.print(cursor_position,BYTE);
delay(128);
};

// * * Main Loop (”Booooorrrrring!!!!”) * *
void loop()
{
//lcd_cursor(1,1);Serial.print(”Starting loop       “);
/* The heart of the state machine is this one loop.  The function
corresponding to the current state is called once per iteration. */
while (1)
{
state_table[curr_state]();
}
};

Giant Vertical Turning Lathe

Posted on June 3rd, 2008

Schiess VTl

I’ve been working on a giant VTL with Peter Luka. It’s a pretty impressive machine. Made by Schiess in 1953 Germany, it weighs 45,000 pounds, has a 2 meter wide chuck and an 80 inch throw.

Since it’s a vertical lathe, everything is sideways. The chuck is actually a turntable, and the tail stock is above. The design is pretty impressive, typically German.

To be fixed: replace contactors, get the crossbeam clamp working again (it has it’s own motor and gearbox) rewind a bunch of the motors (they’re old, and a bit stressed running at 480V/60 Hz instead of the designed 380V/50 Hz). They might get new variable frequency drives so they can not only run at their intended voltage, frequency, but they you’d be able to control the motor speeds.

See it all here

The Electromagnetic Spectrum

Posted on June 6th, 2007

a handy reference:

Sometimes I try to picture what everything would look like if the whole spectrum were compressed into the visible spectrum.  Also sometimes I try to picture your sister naked.

Information and Entropy from MIT

Posted on June 4th, 2007

The Morse telegraph. (Image courtesy of the U.S. National Library of Medicine.)

I’ve been studying a lot of information and coding theory lately for work and personal research, especially computational thermodynamics, and its relationship to other sciences. I’ve been reading the coding and information theory and thermodynamics of computing sections of Feynman Lectures on Computation, a great intro. Another deep resource I recently found is an MIT Open Courseware class Information and Entropy. It’s a unique coverage of (what shouldn’t be such an) esoteric topic: (more…)

Redndant Engineeringing take 2 (and 2.50)

Posted on May 29th, 2007

To the optimist, the glass is half full. To the pessimist, the glass is half empty. To the engineer, the glass is twice as large as necessary.

Take 2.50: To the engineer, the capacity of the container has been over designed by a factor of approximately 1.905 assuming a 5% volume for the sloshing safety factor.

From Varmint Al’s Engineering Pages

Scott Adams chimed in on this in Take 1

TCMP: Trans-Consciousness Messaging Protocol

Posted on May 29th, 2007

A big obstacle in experimenting with the mind's dream-simulation-engine is holding onto the details as you wake up.  With TCMP you can bring back any information you want.

http://xkcd.com/c269.html

“It’s a good thing I put half my water in a redundant glass.”

Posted on May 29th, 2007

Engineers are neither optimists nor pessimists:
dilbert_optimist-pessimist-engineer.gif

(more…)

Information Theory, Inference, and Learning Algorithms

Posted on May 27th, 2007

© Bang ! Engineering • Powered by Wordpress • Using the Swiss Cool theme.