I’ve added a Darlington Array to my gearshift project, so that eventually it will drive 3 relays which in turn will drive 3 solenoids to change gear on the motorbike.

I love the way the ULN2803A works as its so simple – the inputs on the left go to the same outputs on the right, no code, no SPI, just feed it the outputs from the ATtiny.

If you look at the video you can see that’s I’ve also added a 7805 circuit to bring the 12V bike battery or 9V battery I’m using currently down to 5V for the Arduino and relays. Update: now moved to veroboard: video 2 layout.

The code below basically counts up a gear each time the (debounced) button is pressed and stops at 3 and will not do any higher or lower no matter how much you press it. If you hold down the button for 2 seconds it goes back to 0 or neutral. At the moment the 3 LED’s are showing how it works, but will eventually be replaced by relays.

// init vars
const int output1 = 2; // pin7
const int output2 = 1; // pin6
const int output3 = 0; // pin5
const int button  = 3; // pin2
int previous = 0;
int counter = 0;
unsigned long last_time = 0;

void changeGear(int one, int two, int three)
{
    // light led and solenoid
    digitalWrite(output1, one);
    digitalWrite(output2, two);
    digitalWrite(output3, three);
}

void setup()
{
    // set button to input with built-in pull-up
    pinMode(button, INPUT_PULLUP);

    // set led/solenoid pins to outputs
    pinMode(output1, OUTPUT);
    pinMode(output2, OUTPUT);
    pinMode(output3, OUTPUT);
}

void loop()
{
    // take a reading
    int reading = digitalRead(button);

    // changed state - debounce=250ms
    if (reading == LOW && previous == HIGH && millis() - last_time > 250)
    {
        // increment counter
        counter++;

        switch (counter)
        {
            case 1:
                changeGear(1,0,0);
                break;
            case 2:
                changeGear(0,1,0);
                break;
            case 3:
                changeGear(0,0,1);
                break;
        }

        // store the time the button was pressed
        last_time = millis();
    }

    // being held down in 3rd gear - holdtime=3s
    if (reading == LOW && previous == LOW)
    {
        if (millis() - last_time > 3000 && counter >= 3)
        {
            counter = 0;
            changeGear(0,0,0);
        }
    }

    // store previous reading
    previous = reading;
}