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);
}
}

Thanks for all
Thanks for all evden eve nakliyat
evden eve nakliyat comments evden eve nakliyat please go on
That's pretty awesome. I've
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