Thursday, September 10, 2009

Brico Geek Contest Entry

Well guys I didn't win the Brico Geek Contest, but I had fun working with the idea. I did make up a board layout, and parts list. I will sell those to anyone interested, if nothing else to pay for my time invested. The code is included after the split. I will even make up kits for someone if they want to buy one. I may even be so inclined as to build the whole thing for the right price.

For my contest entry I decided to do a Whack-A-Mole style game. I made a 8 LED field that based on the random number generator made one LED light up for a predetermined time frame. Each LED has a corresponding button that should be pushed when the LED is lit. The successful "hit" will give an increment in the score, and a failure will decrement the score based on the level of play attained so far. The game play is simple, and becomes a simple hand eye coordination practice. I doubt that the way it is set up anyone could really beat it all the way through, as the higher your level the quicker the "mole LED" changes positions, and at the fastest it is less than 50ms.

The final version of this project will have illuminated buttons, and some form of speaker for 8 bit glorious mono sound. The code for the game is as follows...

/* incldes tlc5940 library for the TI 16 LED Driver IC, Library by Alex Leone , 2009-02-03
Basic Pin setup:
------------
ARDUINO |
(analog pin 3)17|-> failureLedPin
(analog pin 2)16|-> successLedPin
(analog pin 1)15|-> button8
(analog pin 0)14|-> RandomSeed /input ---u----
13|-> SCLK (pin 25) OUT1 |1 28| OUT channel 0
12|-> button1 OUT2 |2 27|-> GND (VPRG)
11|-> SIN (pin 26) OUT3 |3 26|-> SIN (pin 11)
10|-> BLANK (pin 23) OUT4 |4 25|-> SCLK (pin 13)
9|-> XLAT (pin 24) . |5 24|-> XLAT (pin 9)
8|-> button2 . |6 23|-> BLANK (pin 10)
7|-> button3 . |7 22|-> GND
6|-> button4 . |8 21|-> VCC (+5V)
5|-> button5 . |9 20|-> 2K Resistor -> GND
4|-> button6 . |10 19|-> +5V (DCPRG)
3|-> GSCLK (pin 18) . |11 18|-> GSCLK (pin 3)
2|-> button7 . |12 17|-> SOUT
1| . |13 16|-> XERR
0| OUT14|14 15| OUT channel 15
------------ --------

- Put the longer leg (anode) of the LEDs in the +5V and the shorter leg
(cathode) in OUT(0-15).
- +5V from Arduino -> TLC pin 21 and 19 (VCC and DCPRG)
- GND from Arduino -> TLC pin 22 and 27 (GND and VPRG)
- digital 3 -> TLC pin 18 (GSCLK)
- digital 9 -> TLC pin 24 (XLAT)
- digital 10 -> TLC pin 23 (BLANK)
- digital 11 -> TLC pin 26 (SIN)
- digital 13 -> TLC pin 25 (SCLK)
- The 2K resistor between TLC pin 20 and GND will let ~20mA through each
LED. To be precise, it's I = 39.06 / R (in ohms). This doesn't depend
on the LED driving voltage.
- (Optional): put a pull-up resistor (~10k) between +5V and BLANK so that
all the LEDs will turn off when the Arduino is reset.

If you are daisy-chaining more than one TLC, connect the SOUT of the first
TLC to the SIN of the next. All the other pins should just be connected
together:
BLANK on Arduino -> BLANK of TLC1 -> BLANK of TLC2 -> ...
XLAT on Arduino -> XLAT of TLC1 -> XLAT of TLC2 -> ...
The one exception is that each TLC needs it's own resistor between pin 20
and GND.

This library uses the PWM output ability of digital pins 3, 9, 10, and 11.
Do not use analogWrite(...) on these pins.

The buttons are 4 leg momentary buttons with a 1K ohm pull down resistor to ground, and +5V on the other side
The successLedPin and failureLedPin have 150 ohm resistors to limit the current draw, these should probably be 300 - 400 but these are what I had available.

The game is just like the original Whack-A-Mole you played at carnivals, and fairs, but the scoring mey be different. An LED Lights up and you hit the button that relates to it.
A successful hit will increment your score. for every 10 points you go up a level. For every 10 levels you go to the next level of difficulty.
for the first level of difficulty a miss-hit does not harm your score, but each level of difficulty added means more challenge, so a miss-hit on the 2nd difficulty makes your
score go down by 1, and on the 3rd level of difficulty your score goes down by 2 each miss-hit., and finally on the 4th level of difficulty you lose 3 points per miss-hit.

The speed increases as your levels go up, and each level of difficulty has a faster time delay as well, so at level 9 on the 3rd level of difficulty, your "moles" are screaming
fast.

The 5 LEDs attached to the IC that are not the moles are a score keeper for each hit. 4 yellow, and one green. If no LEDS for your score are on, then you have 0 points for
that level, if all 4 yellow LEDS are on you have 4 points, with the green one on you have 5 points plus the first ones (1 yellow and the green = 6, 2 yellow and the green = 7,
4 yellow and the green = 9). For any more score information that that use the Serial monitor from the arduino program on your computer.

The 2 LEDS attached to the analog i/o's are for success and failure on your button hits. A successful hit makes the orange LED on A2 light up, and a failure lights up a Red LED
on A3.

Game Interpretted to Arduino by Charles D. Stutzman Sr. 08/11/2009

*/

#include "Tlc5940.h"

#define button1 12
#define button2 8
#define button3 7
#define button4 6
#define button5 5
#define button6 4
#define button7 2
#define button8 15
#define statusLedPin 16
#define failureLedPin 17


int cheat = 0;

int buttonstate1;
int buttonstate2;
int buttonstate3;
int buttonstate4;
int buttonstate5;
int buttonstate6;
int buttonstate7;
int buttonstate8;

int ledPinstate1;
int ledPinstate2;
int ledPinstate3;
int ledPinstate4;
int ledPinstate5;
int ledPinstate6;
int ledPinstate7;
int ledPinstate8;

int mole;

int scoreCard = 0;
int level = 0;
int levelmultiplied;
int timesThrough = 0;
int timerMod = 20;

int buttonactive;
long randNumber;
long* sharerandNumber = &randNumber;

int statusLedState;
int* sharestatusLedState = &statusLedState;

int failureLedState;
int* sharedfailureLedState = &failureLedState;

int start = 0;


void setup()
{
/* Call Tlc.init() to setup the tlc.
You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
Tlc.init(4095);
Serial.begin(9600);
randomSeed(analogRead(0));
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
pinMode(button5, INPUT);
pinMode(button6, INPUT);
pinMode(button7, INPUT);
pinMode(button8, INPUT);
pinMode(statusLedPin, OUTPUT);
pinMode(failureLedPin, OUTPUT);
}

void loop()
{
if (start == 0){
Tlc.clear();
blinkAllMoleLEDs();
blinkAllMoleLEDs();
start++;
}
scoreCard = scoreCard + cheat;
randNumber = random(0, 8);
*sharerandNumber = randNumber;
switch (randNumber){
case 0:
mole = button1;
break;
case 1:
mole = button2;
break;
case 2:
mole = button3;
break;
case 3:
mole = button4;
break;
case 4:
mole = button5;
break;
case 5:
mole = button6;
break;
case 6:
mole = button7;
break;
case 7:
mole = button8;
break;
}
levelmultiplied = level * 5;
switch (timesThrough){
case 0:
timerMod = 10;
break;
case 1:
timerMod = 7;
break;
case 2:
timerMod = 4;
break;
case 3:
timerMod = 1;
break;
}

buttonstate1 = LOW;
buttonstate2 = LOW;
buttonstate3 = LOW;
buttonstate4 = LOW;
buttonstate5 = LOW;
buttonstate6 = LOW;
buttonstate7 = LOW;
buttonstate8 = LOW;
for (int delaycounter = 55; delaycounter > levelmultiplied; delaycounter--) {
Tlc.set(randNumber, 2095);
Tlc.update();
if (buttonstate1 == LOW){
buttonstate1 = digitalRead(button1);
if (mole == button1){
if (buttonstate1 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button1){
if (buttonstate1 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate1 = HIGH;
if (mole == button1){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}
}


if (buttonstate2 == LOW){
buttonstate2 = digitalRead(button2);
if (mole == button2){
if (buttonstate2 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button2){
if (button2 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate2 = HIGH;
if (mole == button2){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}
}

if (buttonstate3 == LOW){
buttonstate3 = digitalRead(button3);
if (mole == button3){
if (buttonstate3 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button3){
if (buttonstate3 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate3 = HIGH;
if (mole == button3){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate4 == LOW){
buttonstate4 = digitalRead(button4);
if (mole == button4){
if (button4 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button4){
if (buttonstate4 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate4 = HIGH;
if (mole == button4){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate5 == LOW){
buttonstate5 = digitalRead(button5);
if (mole == button5){
if (buttonstate5 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button5){
if (buttonstate5 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate5 = HIGH;
if (mole == button5){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate6 == LOW){
buttonstate6 = digitalRead(button6);
if (mole == button6){
if (buttonstate6 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button6){
if (buttonstate6 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate6 = HIGH;
if (mole == button6){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate7 == LOW){
buttonstate7 = digitalRead(button7);
if (mole == button7){
if (buttonstate7 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button7){
if (buttonstate7 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate7 = HIGH;
if (mole == button7){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate8 == LOW){
buttonstate8 = digitalRead(button8);
if (mole == button8){
if (buttonstate8 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button8){
if (buttonstate8 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate8 = HIGH;
if (mole == button8){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}
digitalWrite(statusLedPin, statusLedState);
digitalWrite(failureLedPin, failureLedState);
Tlc.set(randNumber, 00);
Tlc.update();
if (level < 0){ level = 0; scoreCard = 0; } else { switch(scoreCard){ case 0: Tlc.set(8, 00); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 00); break; case 1: Tlc.set(8, 1500); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 00); break; case 2: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 00); break; case 3: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 00); Tlc.set(12, 00); break; case 4: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 1500); Tlc.set(12, 00); break; case 5: Tlc.set(8, 00); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 6: Tlc.set(8, 1500); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 7: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 8: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 9: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 1500); Tlc.set(12, 2500); break; } } Tlc.update(); delay(timerMod); if (scoreCard > 9){
level ++;
scoreCard = 0;
}
if (scoreCard < 0){ level --; scoreCard = 9; } statusLedState = LOW; failureLedState = LOW; Tlc.set(14,0000); Tlc.set(15,0000); Tlc.update(); } Serial.print(timesThrough); Serial.println(" is the current amount of times you have gone through all 10 levels."); Serial.print(level); Serial.println(" is the current level."); Serial.print(level); Serial.print(scoreCard); Serial.println(" is the current score."); delay(50); if (level > 9){
Tlc.clear();

for (int delaycounter = 0; delaycounter < 13; delaycounter++) { Tlc.set(delaycounter, 1500); Tlc.update(); delay(100); } Tlc.clear(); Tlc.update(); level = 0; timesThrough ++; } if (timesThrough > 3 ){
Serial.println("You are a god!!!!! No one can move that fast, or you cheated.");
timesThrough = 0;
level = 0;
Tlc.clear();

for (int delaycounter = 0; delaycounter < 13; delaycounter++) { Tlc.set(delaycounter, 1500); Tlc.update(); delay(100); } for (int delaycounter = 13; delaycounter > 1; delaycounter--) {
Tlc.set(delaycounter, 00);
Tlc.update();
delay(100);

}
blinkAllMoleLEDs();
blinkAllMoleLEDs();

}
}
void blinkAllMoleLEDs(){
Tlc.set(0, 1000);
Tlc.set(1, 1000);
Tlc.set(2, 1000);
Tlc.set(3, 1000);
Tlc.set(4, 1000);
Tlc.set(5, 1000);
Tlc.set(6, 1000);
Tlc.set(7, 1000);
Tlc.update();
delay(100);
Tlc.set(0, 00);
Tlc.set(1, 00);
Tlc.set(2, 00);
Tlc.set(3, 00);
Tlc.set(4, 00);
Tlc.set(5, 00);
Tlc.set(6, 00);
Tlc.set(7, 00);
Tlc.update();
delay(100);
Tlc.set(0, 1000);
Tlc.set(1, 1000);
Tlc.set(2, 1000);
Tlc.set(3, 1000);
Tlc.set(4, 1000);
Tlc.set(5, 1000);
Tlc.set(6, 1000);
Tlc.set(7, 1000);
Tlc.update();
delay(100);
Tlc.set(0, 00);
Tlc.set(1, 00);
Tlc.set(2, 00);
Tlc.set(3, 00);
Tlc.set(4, 00);
Tlc.set(5, 00);
Tlc.set(6, 00);
Tlc.set(7, 00);
Tlc.update();
delay(100);
Tlc.set(0, 1000);
Tlc.set(1, 1000);
Tlc.set(2, 1000);
Tlc.set(3, 1000);
Tlc.set(4, 1000);
Tlc.set(5, 1000);
Tlc.set(6, 1000);
Tlc.set(7, 1000);
Tlc.update();
delay(100);
Tlc.set(0, 00);
Tlc.set(1, 00);
Tlc.set(2, 00);
Tlc.set(3, 00);
Tlc.set(4, 00);
Tlc.set(5, 00);
Tlc.set(6, 00);
Tlc.set(7, 00);
Tlc.update();
delay(100);
Tlc.clear();
}

The cheat variable is there so you can debug the platform, and make sure the code works through the full game. I have pictures and video of the prototype setup, and I will post them later.

Article continued after the jump...

Monday, August 24, 2009

Arduino Pointers and the Ping for Automated High Five

Here is the crosslinked article I wrote over at www.uchobby.com. This is a part of the giveaway program David is doing on the website.

Pointers, pointers to pointers, and reading information at the memory address pointed to by the pointers. These are topics that I haven’t seen addressed in the Arduino environment yet.

I was having a problem getting a variable to pass globally from one function to another. I declared the variables that I wanted to use in multiple functions globally outside all the functions and setup(). I tried declaring the variable in every function, and passing it using the return function, and putting the variable to be passed in the function call, i.e. function(variable). No success, I kept getting errors about scope, or the program will compile and upload, but the variable will be empty in the other function where I am trying to read the value.


I talked to David at uCHobby about the problem, and he pointed me to an article about using the volatile modifier on variables. It is a modifier that is rarely taught in depth but can make a difference in the programming especially when there is an optimizer in use (the Arduino uses an optimizer to make the code more efficient or take up less memory, I am not sure which, David could tell you). [David: the volatile modifier tells the compiler not to keep a local copy of a variable in a register. Its important when an interrupt could update the value making a saved copy invalid.]

I built a set of code from a few examples to try and quickly make something work. I was trying to use a PING sensor, some servos, some LEDs, and the serial monitor. I built the system I was working with one piece at a time, starting with the PING. Compile example, upload and voila. Simple. I can put my hand in front of the sensor and the serial monitor reads the distance my hand is from the sensor.

pingsensor servo

Next lets make the LEDs dim and brighten based on how far away the PING is from an object. Something like:

analogWrite(dimLED, inches);

where dimLED is a LED on a PWM pin that is dimming as the variable inches gets smaller. Success. I can make a sensor affect the LED.

Now let’s make the servo move. The Servo knob example works great for this. It lets us use an analog input to move a servo through its range. You will note that later in the actual example I put together, I did not use the servo library, or this example, but rather used an example from Robotgrrl.

Now lets make the ping sensor talk to the servo. Should be simple but the first attempt I had of this made things very jittery. The refresh rate on the servo and the PING sensor made it necessary for these to be set up as separate functions. Separate functions ended up meaning that we needed a timer to call them at timed intervals so that the refresh rates did not make the servo jittery. Separate functions and library calls eventually made it difficult to have the variables working correctly. The inches variable from the PING example was not passing to the servo function. Leaving me with a servo that did not move, but the PING was getting data. I moved the variable to make it global, and that didn’t fix the problem.

Scope errors, and undefined in this type messages drove me nuts. I consulted C++ tutorials on passing variables and global variables, and then tried the volatile modifier David at uC Hobby suggested. I talked to a computer programmer and he suggested I use pointers. Here is a good reference that helped me realize how to use pointers. I vaguely remember using pointers in my C programming class, but that was 8 years ago. I then set up the variable globalInches and a pointer to it *getInches:

int globalInches;

int* getInches=&globalInches;

To read the variables in and write the variables, as they are needed you have to reference them:

int inches1 = *getInches;

*getInches = inches;

The article about pointers goes into pointers to pointers, to pointers… and how to point to a memory address of a variable as opposed to a variable. The reason for pointing to the memory address instead of trying to pass the variable is that likely the program will try making a new variable rather than checking for the existence of a variable already. Whereas pointing to the memory address will get you the data that is in that position always. The last example they use is like this one:

int main()
{
int instruments(12);
int* p_instruments = &instruments;
int** p_p_instruments(&p_instruments);
int*** p_p_p_instruments = &p_p_instruments;
***p_p_p_instruments = 6;
}

Table for current information from above code

Variable Name Variable Type Memory Address Stored Value
instruments int 1279 6
p_instruments int* 1377 1279
p_p_instruments int** 1477 1377
p_p_p_instruments int*** 1000 1477

I put the last memory address lower than the first to show that a computer doesn’t care when a variable is declared, it will put it into memory at the first available location and during a program run, memory addresses can and will be emptied at any moment.

This makes instruments = 12, then points p_instruments to the address of instruments, then points p_p_instruments to the address of p_instruments, then points p_p_p_instruments to the address of p_p_instruments, then lastly dereferences p_p_p_instruments to put 6 in the instruments variable. Each * is a “dereference operator”, and takes the location that the variable has stored and uses it to look at the data in the memory location. The & symbol is “the address of operator”. It points the variable to the address of the variable it modifies. Reading the operators like they are called makes the line of code make more sense.

int* p_instruments = &instruments;

Reads like “int* p_instruments equals the address of instruments”.

*p_instruments = 6;

Reads like “dereferenced p_instruments equals 6”, meaning that the memory location that p_instruments is pointing to will now have 6 as it’s value. It just so happens that that memory location is the variable instruments, so now instruments = 6.

After getting it all working and tweaking the values I have a program that can make the servo with a flag on it move closer to the sensor till the servo is at or almost at the sensor, and then move it away as soon as it gets to an inch or so away. The action to start the servo to the sensor will be initiated by a button push. pushbutton

Note to programmers on keeping track of problem versions of code. In doing this example, and making it work from multiple source code parts and pieces, I ended up with many versions of the same file that all work in different fashions, or not at all. I apparently never saved any of the ones that had numerous errors in them, and I should have made a separate sketch folder for failed code, so that I could go back and see what didn’t work in doing this example. As it is I have only the memory of variable failures, and not the code to show and repeat the errors for this article. I wish I had a library of the bad code to be able to give the exact errors that came up.

highfive1The physical pin outs for the example is as follows using a Bare Bones Board kit:

Bare Bones Board Arduino in the breadboard

4 pin momentary on push-button with one pin at pin 2, one on the opposite side to 5+, and one to

ground with a pull down resistor

Servo with power and ground to the respective power lines, and the signal to pin 6

PING sensor with power and ground to the respective power lines, and the signal to pin 7

LED to pin 13 and ground

Here is the breadboard and Bare Bones Board with the sensor, servo, pushbutton and LED hooked up ready to go for this example.

/*
||
|| @file highfivePINGaervo.pde
|| @version 1.0
|| @author Charles Stutzman
|| @contact charlesd.stutzmansr@gmail.com
||
|| @description
|| | This sketch takes a button push and initiates a high five style motion from a servo to a PING
|| | sensor.
|| | based off of the TimedAction example ThreeExamplesAtOnce.pde by Alexander Brevig
|| | alexanderbrevig@gmail.com
|| | has three TimedActions, that interact and initiate a high five motion, and one that is a
|| | heartbeat to show activity on the board
|| | May contain parts and pieces from Ardiuno Examples Library (PING, Blink LED, Button
|| | digital Input, and http://robotics.learnhub.com/lesson/1766-arduino-and-servos
|| #
||
*/

#include 
//TimedAction initialization of the circuits heartbeat
TimedAction heartbeatAction = TimedAction(1000,heartbeat);

//TimedAction initialization of the Servo position function
TimedAction servoAction = TimedAction(20,servo);

//TimedAction initialization of the PING sensor read function
TimedAction pingAction = TimedAction(200,ping);

//TimedAction initialization of the button push for the start of a "high five" between the servo flag //and the PING sensor
TimedAction buttonAction = TimedAction(50,button);

// globalvariables for ping and servo functions
int globalInches;
int* getInches=&globalInches;

//heartbeat variables and pins
const int ledPin = 13;
boolean ledState = false;

//servo variables and pins
const int servo1 = 6;
int servoAngle1;
int pulseWidth1;

//ping variables and pins
const int pingPin = 7;

//button pins and variables
const int buttonPin= 2;
int buttonState = 0;

//set up for servo position setting
void servoPulse1 (int servo1, int servoAngle1) {
pulseWidth1 = (servoAngle1 * 11) + 500; // Converts angle to microseconds
digitalWrite(servo1, HIGH); // Set servo high (turns it on)
delayMicroseconds(pulseWidth1); // Wait a very very small amount
digitalWrite(servo1, LOW); // Set servo low (turns it off)
// Typical Refresh cycle of servo (20 ms) normally a delay would be here, but the delay is in the //TimedAction calls
}

void setup() {
pinMode(ledPin,OUTPUT);
digitalWrite(ledPin,ledState);
Serial.begin(9600);// there for debugging and watching the sensor values
pinMode(servo1, OUTPUT);
pinMode(buttonPin, INPUT);
}

void loop() {
heartbeatAction.check(); //trigger every second
servoAction.check(); //trigger every 20 millisecond
pingAction.check();//trigger every 200 millieconds
buttonAction.check();//trigger every 50 milliseconds
}

//checks for a button push to initiate the "high five"
void button() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH){
*getInches = 6;// makes globalInches go to a value that the servo will move when the servo checks //the value
}
}

//beats the LED at pin 13 at 1 beat per second as a heartbeat
void heartbeat() {
ledState ? ledState=false : ledState=true;
digitalWrite(ledPin,ledState);
}

//moves the servo according to data in *getInches
void servo() {
int inches1 = *getInches;
if (inches1 > 2) {
if (inches1 < 7) {
servoAngle1 = inches1*3;
}
}
else {
servoAngle1 = 60;
}
servoPulse1(servo1, servoAngle1);
Serial.print(inches1);
Serial.println(" inches from sensor."); //datalogging for debugging
}

//gets data from the ping sensor
void ping() {
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);

delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);

// convert the time into a distance
inches = microsecondsToInches(duration);
Serial.print(inches);
Serial.print(" inches is what the sensor just read.");//there to help identify the number
Serial.println();

*getInches = inches;
}

long microsecondsToInches(long microseconds) {
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf

return microseconds / 74 / 2;
}

Here is the sequenced pictures of the action:

highfive

Have fun and enjoy making the Arduino interact with others and its environment.

Charles Stutzman


Article continued after the jump...

Scrounging a Desk Phone

This is the first article I wrote over at www.UcHobby.com, cross listed over here so anyone finding me first here can see what I have done in the past.

Scrounging is a good way to get parts your your electronics workshop. Rather then throwing away that old piece of electronics, take it apart to salvage reusable parts. In this article an old Small Business 4 line Phone is salvaged for parts. This article was submitted by Charles Stutzman as part of the uCHobby giveaway program.


phoneuntouchedHow often do we see an office throw away good electronic components in the guise of slightly malfunctioning items, or doing a blanket upgrade to a new system. I work in a small business with 3 people in the office, and we have a 4 line phone system. Every time our boss decides we need to get a new phone, he buys one for every phone location, so that they interact with each other, allowing use of the intercom, and hold functions. This leaves anywhere from 4-8 good used phones being put to the curb. The need for a good alphanumeric LCD got me looking at that pile a little closer, and I decided to start scrounging. On opening the case I found more parts than I would ever have thought. Most of these are generic resistors, diodes, capacitors and the like, but there are a few items like headers, RJ11 and RJ14 connectors, a 12 volt power supply(wall wart), and that 16X2 LCD that happens to be a common interface type, with plenty of data to be able to use it, even one article showing how you can use dip switches, a breadboard, and a few other common items to manually drive it as if you were the software (I am thinking my daughter would love to play with that).

backwithleveleroffTools needed: small Phillips head screwdriver, Flathead screwdriver (for prying open the handset), de-soldering gun (or heat gun), and optionally a cordless drill (makes it all go quicker).

First flip the phone over so you can see its back, some of these have a plastic pop off piece that makes the phone sit at an angle. These usually are popped off with a release tab. There should be four to eight small Phillips head screws usually at the corners. Take those out. You don’t have to remove the battery cover screw unless you need a good nine volt battery contact set, but you might still want to check the charge on the nine volt, why throw a good project battery.

phonebackbatteryout

After the four to eight screws are removed, you can split the case and you will have two to three cables connecting the top to the bottom half. One to the LCD, and the other two go to the keypad. Unplug these from their headers on the bottom board carefully so you can reuse the headers and cables.

phonepulledapartcablesconnected

Now you have two separate halves of the phone, and you can see the goodies inside. As mentioned before the main things of interest will be RJ14 and RJ11 jacks, headers with matching cables (14, 10, and 9 pin), 16X2 alphanumeric LCD, Piezoelectric speaker, and microphones.

After looking at the boards and seeing if there are any obvious items you are interested, then you can make note, and start taking it apart. I first went to the LCD which is attached by four Phillips head screws.

LCD2

Most of these have a clear plastic guard that unless scratched can be reused in your projects as long as you don’t scratch it. Next attached by entirely too many screws is the keypad, which is useless unless you can figure out its logic processes for each button.

keypaduntouched

I look at it as too much to play with for now, but will keep the item in case I get a wild hair to tackle a challenge. I may take one of these and cut around the board to use each button as a single switch, by soldering wires to each trace and breaking the line beyond the wire splice in. Removing the board with all the goodies on it is simple, it has four screws holding it on. After it is removed you can put it in a vise, or clamp, and start removing components that you are interested in.

mainboarduntouched

The handset is really simple to pull apart, and get a mic, piezo-speaker, and RJ14 connector.

phonehandsetopenedI started with the through hole components since I can reuse them easily. There are capacitors, transformers, RJ14 and RJ11, headers, and more. The heat gun method makes this process quick if you are careful. I did a full pull apart of this board with the heat gun freeing only the surface mount parts, in 15 – 25 minutes. The total tear apart from fully intact phone to as far as I pulled it apart, in 30 – 45 minutes. Below are pictures of the items I have scrounged. Mainly it boils down to capacitors, capacitors, capacitors, with a sprinkling of other surface mount parts. Listed out the components are as follows: 1 16X2 alphanumeric LCD screen, 2 transformers, 4 reed relays, 4 fuses, 3 RJ14 jacks, 2 RJ11 jacks, 1 stereo headphone jack, 1 power port with matching 12 volt 500ma wall wart. 2 microphones, 1 piezoelectric speaker, 1 normal speaker, about 10 resistors of varying value, and about 40 varying size capacitors.

micsandspeakerfromhandsetRJconnectorsb

I decided not to remove surface mount parts, as I can’t use them currently, but they are still there to be used by anyone else who wants to go further with a tear down.
Here is the board empty of all the through hole components.

scroungedboardnothroughpinsleft

There is an article from Everyday Practical Electronics, February 1997, by Julyan Ilett, titled "How to Use an Intelligent LCD". It can be found here. With a breadboard, some resistors, a dip switch array (8 switches), two momentary on switches, a variable Potentiometer, and the scrounged LCD from the phone system, you can make up a small manual operated LCD screen. The article walks through manually operating an LCD based on the HD44780 controller. Searches for the HD44780 controller interface will yield info for you to integrate with many different microprocessors.
The parts can be identified fairly easily for the standard items using Google. A search for transistor part number KSP 44 214 pictured below right

0423091836

This search will get you many sites, and this is where I found information, fairchildsemi.com with information as to how the item is marked. We find out that the transistor is a three lead, with collector/emitter voltages of 400V and dissipation of 625 mW. The capacitors are easy to identify as they are marked for their size in most applications, usually. The blue and the white components shown are a little more difficult to determine. The harder to identify parts on the left of the picture are as follows: the blue items is a varistor, and the white is a capacitor.

unknowntransformers

These items I believe are 4 pin relays, but I am guessing on that, as the searches are coming up empty when I look by Cosmo and 4010 and c16 which are the markings on them.

The transformers are tricky, but some simple experimentation could give you some data on it.

assorted

The fuse is useful, the push button is potentially useful, and the reed relay (the 8 pin IC type chip).
There are a few really difficult items such as an item marked TECOM 561-100006 HJ66 0224 to find info about, and in reality looks like a component made up of many surface mount parts, in a heat shrink wrap with pins coming off in an inline fashion, with 17 pins.

I hope that this scrounge article helps others have ideas as to new places to scrounge. I plan to use the LCD soon, and the rest of the parts as needed. I may tear a few apart so I can have a few LCDs at least. You may notice that the phones changed in the pictures, because I already had one mostly scrounged when I realized that I didn’t have photos of the process that were usable, so I started scrounging a second one.
A list of the scrounged items is as follows:

  1. 42 capacitors from 1 microfarad to 220 microfarad
  2. 4 black 4 pin photo coupler anode cathode emitter collector
  3. 3 black 2 pin 682j inductors
  4. 2 102j 2 pin white inductors
  5. 4 8 pin reed switches D2A050002
  6. 4 ksp44 transistors epitaxial silicon transistors collector base 500v collector emitter 500v emitter base 6v
  7. 7 varied resistors
  8. 1 5.5v .47F Super capacitor useful as backup power for CMOS
  9. 1 121j – 120 uH inductor
  10. 5 varistors light blue flat discs brand _ _ _ varistor voltage – _ tolerance (k-10% l-15%,m -20%) – _ Type (disc or square) – _ _ element diameter
  11. 4 EPCOS tantalum chip capacitors
  12. 3 152j – 1.5 uH inductor
  13. many screws
  14. 2 transformers

The easiest way I have found with modern technology to identify parts is to type all of the markings on the part into a Google search, and refine your search from there. If you then find numerous instances of the same repeated part of the markings such as, the 4 reed switches made by KUAN HIS. A search for KUAN HSI D2A050002 C35 results in no matches, but drop the C35 and you get 2 results. If you go the first link you find that the part number is D2A050002 and the manufacturer is KUAN HSI. Drop the Manufacturer and you can obtain more manufactures of the common part, and then if you weed through the results you should be able to find a data sheet for the item in question. You may have to omit some numbers to get rid of date codes, or manufacturer’s plant codes, the last digit or three. I never found a data sheet for a D2A050002, but I did find one for a D2A050000, at alldatasheet.com.

More info on uses for the LCD can be found on uCHobby.com.

Charles Stutzman


Article continued after the jump...

Websites for the hobby electronics community

I recently started playing with hobby electronics, and so far I have found a few places to be absolutely invaluable, at least towards my current slant of projects. I got hooked looking at all the DIY Hack websites available, and currently look to see what others are doing on a regular basis at www.hacknmod.com, www.hackaday.com, and www.hackedgadgets.com. These website have plenty of ideas and examples of projects for hobby guys to play with. I eventually ran across www.UcHobby.com, where there are contests, and great giveaway programs to encourage the hobby community.

David Fowler of www.UcHobby.com is an excellent source of information and encouragement for the hobby electronics craft-person. I wrote my first article (also linked to here) for the electronics community for his giveaway program. What an encouragement to get free stuff for a little time investment that I was going to do anyway to learn more about the hobby I am getting into. The Bare Bones Board from www.moderndevice.com is a very capable arduino clone, aka freeduino, and is wonderful because it plugs into most breadboards fairly easily.

The open source nature of the item makes it very easy to learn and use if you have even the slightest knowledge of C or similar programming language. I am looking forward to the continued gain in knowledge that this hobby will bring me, and I hope to contribute back to the community as well.

Charles Stutzman

Article continued after the jump...

Article number 2 at UcHobby.com

Here is the link to the second article I wrote at www.uchobby.com, about integrating PING, Servos, and using Pointers in the Arduino IDE. Again I will post the whole article over here soon...

Charles Stutzman
Article continued after the jump...

Friday, August 21, 2009

Article 1 online

Here is a link to the first hobby electronics article I wrote for a website. The website www.uchobby.com is dedicated to serving the hobby electronics community. The owner of the site is a intelligent man and has giveaways and contests on a regular basis. Here is the link to the article. The article is about scrounging for parts on an old small business phone.

Later on I will post the article on my blog as well, as soon as I get more time to learn all the ins and outs of the software.

Charles
Article continued after the jump...

Thursday, August 20, 2009

Arduino Contests

I just finished my submission to the BricoGeek.com Let Arduino Play contest. A digital version of the Whack-A-Mole game from the carnivals. I submitted it last night, and am now waiting to see the outcome. This development platform is a fun and addictive hobby. I have been scrounging parts from old electronics, and trying ot learn as much about the small computer electronics platforms as I can. I have integrated PING))) sensors with motors, LEDS, and the Serial monitor. I am still baffled by interfacing with an HD44780 compatible LCD. I have yet to try just attaching it straight to the Arduino and sucking up all the available Pins on the board, but I may have to do that to figure any more out. I am still working on a few other projects related to this board, and hope to make more progress soon. Meanwhile the kids love to play with the random Electronics that I have for them to interact with routinely.

More later,

Charles Stutzman
Article continued after the jump...