Yarrduino! Shield

Sat 18 September 2010 by jillian

Yarr, matey!  Batten down th' hatches and secyarr th'  wiring!  Lively now, ye lubbars!  Upload yer sketches ye scurvy dogs, else ye'll be walkin' th' plank!  Details aftarr th' break!

Image562Image563Image566

This quick project was inspired by International Talk Like a Pirate Day.  I had an Adafruit Starter Pack for Arduino, and a leftover rigid costume eyepatch with skull and crossbones.  I used the proto shield and the little breadboard that came with the starter kit, but an experienced hacker could probably do this just as quickly with a bare arduino and two LEDs.  I wired ground to two columns in the tiny breadboard, and pin 13 (led) to the corresponding  columns on the other side.  I then drilled holes in the eyepatch just big enough for the  LED legs to pass through, but  narrow enough that the LEDs would stay snug against the patch without passing through.  I then connected the LEDs to the breadboard, paying careful attention to the polarity (long side to pin 13) as described in the Adafruit tutorial. Finally I uploaded the "Blink" sample sketch from the Arduino SDK. (For the still photos I commented out the line that writes LOW to pin 13, but for normal operation I prefer the blinking.

Not satisfied with this, I programmed it to read messages over serial, and relay them repeatedly in morse code via the LEDs, until a new message is received via serial.  The default message is "Yarr, matey!"

Other ideas (not implemented) included hiding a small speaker under the patch for audio (or morse).  Also briefly considered was the concept of coupling this with the motor shield and some motors to drive a Playmobil "Blackbeard's Pirate Ship" around the room.

Parhaps next yarr!

Listing 1: Yarrduino

int ledPin =  13;    // LED+ (long leg) to digital pin 13
char buffer[128];
int bufindex;
int debugSerial = 0;
int messagecomplete = 1;

void setup() {
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
    bufindex = 0;

    strncpy(buffer, "yarr, matey!", 12);
    bufindex = 12;
}

struct xlate {
    char ascii;
    char \*morse;
};

struct xlate 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', "--.." }
};

struct xlate numbers[] = {
    { '1', ".----" },
    { '2', "..---" },
    { '3', "...--" },
    { '4', "....-" },
    { '5', "....." },
    { '6', "-...." },
    { '7', "--..." },
    { '8', "---.." },
    { '9', "----." },
    { '0', "-----" },
};

char \*period = ".-.-.-";
char \*sk = "...-.-";
char \*comma = "--..--";
char \*question = "..--..";
char \*apostrophe = ".----.";
char \*hyphen = "-....-";
//char \*fraction = "-..-.";
char \*parens = "-.--.-";
char \*quotes = ".-..-.";
char \*bang = "-.-.--";
char \*slash = "-..-.";

void xlate_morse(char c, char outbuf[], int maxlen) {
    outbuf[0] = (char) 0;

    switch (c) {
        case '.':
            strncpy(outbuf, period, maxlen);
            return;
        case ',':
            strncpy(outbuf, comma, maxlen);
            return;
        case '?':
            strncpy(outbuf, question, maxlen);
            return;
        case '\\'':
            strncpy(outbuf, apostrophe, maxlen);
            return;
        case '-':
            strncpy(outbuf, hyphen, maxlen);
            return;
        case ')':
        case '(':
            strncpy(outbuf, parens, maxlen);
            return;
        case '"':
            strncpy(outbuf, quotes, maxlen);
            return;
        case '!':
            strncpy(outbuf, bang, maxlen);
            return;
        case '/':
            strncpy(outbuf, slash, maxlen);
            return;
    }

    if (c <= 'z' \|\| c >='a') {
        strncpy(outbuf, letters[c-'a'].morse, maxlen);
        return;
    }

    if (c <= 'Z' \|\| c >= 'A') {
        strncpy(outbuf, letters[c-'A'].morse, maxlen);
        return;
    }

    if (c <= '9' \|\| c >= '0') {
        strncpy(outbuf, letters[c-'0'].morse, maxlen);
        return;
    }

}

int worddelay = 500;
int glyphdelay = 300;
int ditdelay = 200;
int dahdelay = 600;
int pulsedelay = 100;

void write_morse(char buf[], int len) {
    char outbuf[10];

    digitalWrite(ledPin, LOW);

    for (int i=0; i<len; i++) {
        if (buf[i] == ' ') {
            delay(worddelay);
            continue;
        }
        xlate_morse(buf[i], outbuf, sizeof(outbuf));
        Serial.println(outbuf);
        for (int j = 0; outbuf[j]; j++) {
            digitalWrite(ledPin, HIGH);
            if (outbuf[j] == '-')
                delay(dahdelay);
            else
                delay(ditdelay);
            digitalWrite(ledPin, LOW);
            delay(pulsedelay);
        }
        delay(glyphdelay);
    }
}

void read_buffer(char buf[], int &idx, int maxsize) {
    int inchar;
    while (Serial.available() > 0) {
        inchar = Serial.read();

        if (debugSerial) {
            char debugbuf[10];
            Serial.print("read: ");
            Serial.print(inchar, BYTE);
            Serial.print(" current index: ");
            Serial.println(idx, DEC);
            xlate_morse(inchar, debugbuf, sizeof(debugbuf));
            Serial.println(debugbuf);
        }

        if (inchar != '\|') {
            buf[idx++] = inchar;
        }
        if ((idx == maxsize-1) \|\| inchar == '\|') {
            buf[idx] = (char) 0;
            Serial.print("received: ");
            Serial.print(idx, DEC);
            Serial.print(" bytes.\\n");
            Serial.println(buf);
            messagecomplete = 1;
//      write_morse(buf, idx);
            return;
        }
    }
}

void loop() {
    if (Serial.available() > 0) {
        if (messagecomplete) {
            messagecomplete = 0;
            bufindex = 0;
        }
        read_buffer(buffer, bufindex, sizeof(buffer));
    }
    write_morse(buffer, bufindex);
}