Friday, January 7, 2011

Arduino Hello World in Morse Code

Finally, it arrived! The Arduino kit and some additional hardware has just arrived today and as always, the all time favorite "Hello World" has to serve as a first experiment. I decided to spice it up a little bit though. I let the Arduino board "talk" in morse code through its onboard LED.

So here it goes. The first code snippet and a video of the Arduino board greeting all of you :).

/*
  Morse Code Hello World.
  One unit is equal to 250 ms in this example.
 */

void setup() {               
  // initialize the digital pin as an output.
  pinMode(13, OUTPUT);    
}

void loop() {
  //show H . . . .
  for(int x = 0; x < 4; x++) {
    dot();
  }

  //show E .
  dot();

  //show L . - . . (2 times)
  for(int x = 0; x < 2; x++) {
    dot();
    dot();
    dash();
    dot();
  }

  //show O - - -
  for(int x = 0; x < 3; x++) {
    dash();
  }
 
  //show space (waiting time between words is equal to seven units)
  digitalWrite(13, LOW);   
  delay(7 * 250);

  //show W . - -
  dot();
  dash();
  dash();

  //show O - - -
  for(int x = 0; x < 3; x++) {
    dash();
  }

  //show R . - .
  dot();
  dash();
  dot();
 
  //show L . - . .
  dot();
  dash();
  dot();
  dot();
 
  //show D - . .
  dash();
  dot();
  dot();
 
  //show space (waiting time between words is equal to seven units)
  digitalWrite(13, LOW);   
  delay(7 * 250);
}

//dot is equal to one unit
void dot() {
  digitalWrite(13, HIGH);  
  delay(250);             
  digitalWrite(13, LOW);
  //pause between next sign is one unit 
  delay(250);
}

//dash is equal to 3 units
void dash() {
  digitalWrite(13, HIGH);  
  delay(750);             
  digitalWrite(13, LOW);
  //pause between next sign is one unit   
  delay(250);
}

ServoSPOT

Today I wanted to connect my Modelcraft RS-2 servo to the SPOT. The setup was pretty simple.

The servo has three connections. Vin, which takes 4.8 to 6V to operate, GND to connect it to ground and most importantly the signal connection to send pulses to the servo to control the direction of movement.

The SunSPOT uses 4 connections. +5V is connected to the VH pin to power the high current output pins, GND is connected to ground and I used the H3 pin to send pulses to the servo.

I also used an external power source so I wouldn't drain the battery of the SPOT. I cut open an USB cable and cut off both of the data pins. The + pin of the USB cable had to be connected to the Vin connector of the servo and the - pin had to be connected to the GND connection of the SPOT and to the GND connection of the servo.

Here is a simplified schematic on how to connect everything:





The source code is pretty simple as well. The SDK contains classes to handle servo communication. The only thing I had to do was to determine the bounds of my servo. Most servos don't support a full 360 degree movement. They have physical boundaries. There is the possibility of removing those boundaries and kind of hack the servo to enable the full 360 degrees. I never tried it though. So you might need some test code to determine your servos boundaries.

ServoSPOT class:

import com.sun.spot.peripheral.Spot;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ISwitch;
import com.sun.spot.sensorboard.peripheral.ISwitchListener;
import com.sun.spot.sensorboard.peripheral.Servo;

public class ServoSPOT extends MIDlet implements ISwitchListener {

    private ISwitch sw1;
    private ISwitch sw2;
    private final float CENTER = 0.5F;
    private final float LEFT = 1.0F;
    private final float RIGHT = 0.0F;
    private Servo servo = new Servo(EDemoBoard.getInstance().getOutputPins()[EDemoBoard.H3]);

    protected void startApp() throws MIDletStateChangeException {
        new com.sun.spot.service.BootloaderListenerService().getInstance().start();
        Spot.getInstance().getSleepManager().disableDeepSleep();
        sw1 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW1];
        sw1.addISwitchListener(this);
        sw2 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW2];
        sw2.addISwitchListener(this);
        servo.setBounds(540, 2400);
        servo.setPosition(CENTER);
        LEDIndicator.showSPOTStarted();
    }

    protected void pauseApp() {
    }

    protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
    }

    public void switchPressed(ISwitch sw) {
       
    }

    public void switchReleased(ISwitch sw) {
        if (sw == sw1) {
            //move servo left
            LEDIndicator.showMoveLeft();
            servo.setPosition(LEFT);
        } else if (sw == sw2) {
            //move servo right
            LEDIndicator.showMoveRight();
            servo.setPosition(RIGHT);
        }
    }
}
LEDIndicator class:
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import com.sun.spot.sensorboard.peripheral.LEDColor;
import com.sun.spot.util.Utils;

public class LEDIndicator {

    public static void showSPOTStarted() {
        EDemoBoard board = EDemoBoard.getInstance();
        ITriColorLED[] leds = board.getLEDs();
        for (int x = 0; x < leds.length; x++) {
            leds[x].setColor(LEDColor.BLUE);
            leds[x].setOn();
            Utils.sleep(50);
            leds[x].setOff();
        }
    }

    public static void showMoveLeft() {
        EDemoBoard board = EDemoBoard.getInstance();
        ITriColorLED[] leds = board.getLEDs();
        for (int x = 7; x >= 0; x--) {
            leds[x].setColor(LEDColor.BLUE);
            leds[x].setOn();
            Utils.sleep(50);
            leds[x].setOff();
        }
    }

    public static void showMoveRight() {
        EDemoBoard board = EDemoBoard.getInstance();
        ITriColorLED[] leds = board.getLEDs();
        for (int x = 0; x <= 7; x++) {
            leds[x].setColor(LEDColor.BLUE);
            leds[x].setOn();
            Utils.sleep(50);
            leds[x].setOff();
        }
    }
}
Here you can see a small demonstration: