Arduino Semaphor
I saw a Monty Python skit that used semaphore. It was interesting so I decided to built a robot semaphore system.
I bought two smaller steppers from recycledgoods.com. They are pretty low power so I was able to power them from USB. I used an LCD from fungizmos.com to show the letter that is being flagged.
The circuit to drive the stepper and lcd is pretty standard. There is a good stepper tutorial on the arduino site. Fungizmo has the circuit for the LCD.
My arduino code basically reads a number from serial input. The number must be in the range from 00 to 26. With 00 = space, 01 = A and so on. Once it reads the number, the arduino then drives the steppers to flag the letter. I wrote a little perl program that will read from standard input, then send the characters over serial to the arduino, one character at a time. That way I can just cat | any text file into the arduino.

My arduino code:
#include#include int lcd_addr = 0x50; //default I2C hex address from datasheet // change this to the number of steps on your motor // My stepper is 7.5 degrees per step, or 48 steps per revolution #define STEPS 48 // create an instance of the stepper class, specifying // the number of steps of the motor and the pins it's // attached to Stepper leftFlag = Stepper (STEPS, 8, 10, 9, 11); Stepper rightFlag = Stepper (STEPS, 7, 5, 6, 4); // Set stepper starting position int leftFlagStep = 48; int rightFlagStep = 0; int incomingByte1 = 0; // for incoming serial data int incomingByte2 = 0; // for incoming serial data int debug = 0; // LCD buffer char lcd[20] = "Ready "; // Letter array. we read a number over serial, then convert it to a letter char letters[] = { ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; // Create and array that has the flag positions. // 395 = 54 // 360 = 48 // 315 = 42 // 270 = 36 // 225 = 30 // 180 = 24 // 135 = 18 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 29 20 21 22 23 24 25 26 // '', A , B , C , D , E , F , G , H , I , J , K , L , M , N , O , P , Q , R , S , T , U , V , W , X , Y , Z int leftFlagPositions[] = { 48, 48, 48, 48, 48, 29, 36, 42, 54, 54, 36, 24, 30, 36, 42, 18, 24, 30, 36, 42, 24, 30, 42, 36, 42, 36, 36 }; // 225= 30 // 180= 24 // 135= 18 // 90 = 12 // 45 = 6 // 0 = 0 int rightFlagPositions[] = { 0, 6, 12, 18, 24, 0, 0, 0, 12, 18, 24, 6, 6, 6, 6, 12, 12, 12, 12, 12, 18, 18, 24, 30, 30, 18, -6 }; void setup () { delay (1000); //allow lcd to wake up. Wire.begin (); //initialize Wire library // Wire library expects 7-bit value for address and shifts left appending 0 or 1 for read/write // Lets adjust our address to match what Wire is expecting (shift it right one bit) lcd_addr = lcd_addr >> 1; //Send lcd clear command Wire.beginTransmission (lcd_addr); Wire.send (0xFE); //Cmd char Wire.send (0x51); //Home and clear Wire.send (lcd); // Put up the default message Wire.endTransmission (); // set the speed of the motor to 30 RPMs leftFlag.setSpeed (30); rightFlag.setSpeed (30); Serial.begin (19200); // opens serial port, set data rate } void loop () { // check for incoming data if (Serial.available () > 0) { if (Serial.available () == 2) { // read the incoming 2 bytes then convert them to an integer // convert from ascii // This number will correspond to the letter to semaphore. A = 01, B = 02 and so on incomingByte2 = Serial.read (); incomingByte1 = Serial.read (); setFlags ((incomingByte1 - 48) + 10 * (incomingByte2 - 48)); } else { } } } // Move the flags to make the letter void setFlags (int letter) { lcdPrint (letter); if (debug) { Serial.print ("letter = "); Serial.println (letter, DEC); } do { if (leftFlagStep > leftFlagPositions[letter]) { leftFlag.step (-1); leftFlagStep--; } if (rightFlagStep > rightFlagPositions[letter]) { rightFlag.step (-1); rightFlagStep--; } if (leftFlagStep < leftFlagPositions[letter]) { leftFlag.step (1); leftFlagStep++; } if (rightFlagStep < rightFlagPositions[letter]) { rightFlag.step (1); rightFlagStep++; } } // Loop as long as one of the flags needs to move while (leftFlagPositions[letter] != leftFlagStep || rightFlagPositions[letter] != rightFlagStep); // Send out a "Z" to signal we have finished this letter Serial.println ("Z"); } void lcdPrint (int letter) { // Shift everything in the LCD buffer to the left // Then print it to the LCD screen for (int cnt = 0; cnt < 16; cnt++) { lcd[cnt] = lcd[cnt + 1]; } lcd[15] = letters[letter]; Wire.beginTransmission (lcd_addr); Wire.send (0xFE); //Cmd char Wire.send (0x46); //Home and clear Wire.endTransmission (); Wire.beginTransmission (lcd_addr); Wire.send (lcd); Wire.endTransmission (); }
The perl code is pretty straightforward. It reads from standard input, converts the characters to numbers, then writes the numbers to the arduino over the serial port. The syntax is: cat rickroll.txt | perl ./semaphore.pl
Here is my perl code:
use Device::SerialPort;
# Set up the serial port
# 19200, 81N on the USB ftdi driver
my $port = Device::SerialPort->new("/dev/ttyUSB0");
$port->databits(8);
$port->baudrate(19200);
$port->parity("none");
$port->stopbits(1);
# hash of letters
# send the letter number to the arduino
%letter = (
' ' => '00',
'a' => '01',
'b' => '02',
'c' => '03',
'd' => '04',
'e' => '05',
'f' => '06',
'g' => '07',
'h' => '08',
'i' => '09',
'j' => '10',
'k' => '11',
'l' => '12',
'm' => '13',
'n' => '14',
'o' => '15',
'p' => '16',
'q' => '17',
'r' => '18',
's' => '19',
't' => '20',
'u' => '21',
'v' => '22',
'w' => '23',
'x' => '24',
'y' => '25',
'z' => '26',
);
# Read the characters from standard in
while () {
$_ =~ tr/A-Z/a-z/;
$_ =~ s/[^a-z ]+//gi;
@chars = split( //, $_ );
foreach $character (@chars) {
print $character;
print "Sending " . $letter{$character} . "\n";
$port->write( $letter{$character} );
# Poll to see if any data is coming in
# Wait for the arduino to tell us it is finished with the last letter
my $response = '';
while ( !$response ) {
$response = $port->lookfor();
}
# just wait for a second
sleep(1);
}
}
Comments
Anonymous:
I've only being experimenting with my Arduino for about a month now, but I hope to get this skilled in time.Dissertation Help | Essay Writing | Research Paper Help
Claudine:
vous êtes vraiment un génie! Tous inventé et réalisé par nous-mêmes!
Anonymous:
ovvvvv all right :)
ovvvvv all right :)
ovvvvv all right :)
film indir film indir film izle
film izle
SpooExi
dizi izle
mp3 indir
sex porno izle
Nate C.:
How are you getting a variable to display in the LCD screen? All I can get to display are strings.
I have int counter = 1; set at the top and I have tried everything below:
Wire.send("counter");
Wire.send('counter');
Wire.send(counter);
All with no luck. Any help would be appreciated
Eddy:
How did you figure that out dude?You must be a genius!
I am still doing the stepper tutorial.
----------
online drugs are addictive!
Joshua:
That's pretty awesome. I've only being experimenting with my Arduino for about a month now, but I hope to get this skilled in time.
Post new comment