Eric Ayars
Last modified 6/3/14

Servo shutter controller for Arduino or Arduino-compatible microcontroller.

STATE input (HIGH or LOW) selects between one of two servo POSITIONs.

LEARN button, when pressed, allows adjustment of servo POSITION for that
value of STATE. When the LEARN button is released, the servo POSITION 
is saved in EEPROM, so that regardless of power history the device
remembers the correct position for each STATE.

Set SERVO_ALWAYS_ACTIVE = true to make the servo actively hold position.
By default, the driver cuts power to the servo when it's not moving, in 
order to lower electronic noise and servo jitter mechanical noise.
This default works fine for things that don't move on their own, like my
vacuum system vapor deposition shutter or laser keyswitches; but if you
need to work to hold position, set SERVO_ALWAYS_ACTIVE = true.
const boolean SERVO_ALWAYS_ACTIVE=false;

#include <Servo8Bit.h>
#include <EEPROM.h>

const byte POSITION=1;  // position adjustment pot, analog input
const byte STATE=4;     // Logic level input to select servo position
const byte LEARN=1;     // Button pin for LEARN functionality
const byte SERVO=0;     // Servo is attached here
const byte SERVO_ON=3;  // Servo power 

Servo8Bit shutter;  // create servo object
byte state, oldState;
byte pHigh, pLow;   // Servo positions for high and low

void learn() {
    // Adjust position of servo according to potentiometer, save position
    // in EEPROM.
    byte position;
    state = digitalRead(STATE);

        digitalWrite(SERVO_ON, HIGH);

    while (!digitalRead(LEARN)) {
        // adjust until LEARN button is released
        position = map(analogRead(POSITION), 0, 1023, 0, 179);

        digitalWrite(SERVO_ON, LOW);

    EEPROM.write(state, position);  // state is either 0 or one, write
                                    // in corresponding address.
    // Remember NOW where we are, too! Not just EEPROM!
    if (state) pHigh = position;
    else pLow = position;

void setup() {
    // define pins
    pinMode(SERVO_ON, OUTPUT);      // Turns servo power on/off

    // Attach servo

    // read saved positions, if any
    pLow =;
    pHigh =;

    oldState = 2;                   // This is impossible, so it triggers 
                                    // an adjustment of position in loop().
        digitalWrite(SERVO_ON, HIGH);

void loop() {
    // Check STATE
    state = digitalRead(STATE);
    if (state != oldState) {
        // Hey, something changed!

        if (!SERVO_ALWAYS_ACTIVE) {
            digitalWrite(SERVO_ON, HIGH);

        if (state) shutter.write(pHigh);
        else shutter.write(pLow);
        delay(1000);                // Allow 1 second (plenty!) to arrive.

        if (!SERVO_ALWAYS_ACTIVE) {
            digitalWrite(SERVO_ON, LOW);

        // update that we got this one already.
        oldState = state;

    // Check for learning opportunity
    if (!digitalRead(LEARN)) learn();

    // Chill.

Generated by GNU Enscript 1.6.6.