zondag 24 januari 2010

AdvButton, a button library for the Arduino platform

I've decided to create a library for using buttons on the Arduino platform. See also http://www.arduino.cc/playground/Code/AdvButton.

Features

  1. Event based implementation
  2. Recording the time a button is pressed
  3. Adjustable repeat delay, start delay for the keypressed event
  4. requires only a single call in the main loop

Download, install and import

Download here: Attach:AdvButton.zip
 
Extract the folder AdvButton under /hardware/libraries/. (Re)start the Arduino application and select from the menu bar: "Sketch->Import Library->AdvButton". The following lines should be added: 


#include < AdvButton.h >
#include < ButtonManager.h >
 
See the file buttondemo.pde, included in the zip, for an example.

Usage

After importing the header files, declare the buttons:


#define PINBUTTON1 2
#define PINBUTTON2 3

#define PINLIGHT1 8
#define PINLIGHT2 9

AdvButton but1 = AdvButton(PINBUTTON1,OnKeyPressBut1,100,1000);
AdvButton but2 = AdvButton(PINBUTTON2,NULL,OnKeyDownBut2,OnKeyUpBut2);
 
Button 1 will generate a keypress event upon pressing the button at pin 2. After a short delay (1000 milliseconds), every 100 milliseconds the keypress event is raise again. Until the button is released.
Button 2 will generate a keydown event upon pressing the button at pin 3. After releasing the button a keyup event is raised.
Next we need to define the event functions. The triggering button is passed as parameter.


void OnKeyPressBut1(AdvButton* but)
{
  digitalWrite(PINLIGHT1,HIGH);
  delay(5);
  digitalWrite(PINLIGHT1,LOW);
}


void OnKeyDownBut2(AdvButton* but)
{
  digitalWrite(PINLIGHT2,HIGH);

}

void OnKeyUpBut2(AdvButton* but)
{
  digitalWrite(PINLIGHT2,LOW);
}
 
Last is the adding a call to the buttonmanager to update the button states:



void loop()
{
  ButtonManager::instance()->checkButtons();
}

woensdag 20 januari 2010

Arduino: Controlling a DC motor

It's been a while, but I've been busy with an interesting project. I will blog about it later on. Totally unrelated is today's topic: controlling an DC motor with an Arduino. At first you might say that it is easy to power an DC motor with an Arduino. Put it on a digital pin and enable or disable the motor. But if we want different speeds you will need a different voltage. As a digital pin is only high (5v) or low (0v), the motor can either go very fast or stop. How do we fix this problem?

The short answer is quite simple actually: use pulses. By sending a pulse every x milliseconds the motor will rotate faster or slower depending on the pulse length. The longer answer, however, is a bit harder. We will need something to flat out the pulses a bit. As the pulse top is 5v and the pulse bottom is 0v, the engine will actually be turned off and on very fast. By using an capacitator we can flat out the pulse to, for example, top 3v and bottom 2.5v.

To build the following circuit we will need:
1 x An Arduino board
1 x C547B transistor
2 x 10KOhm resistors
1 x 5v DC Motor
1 x 100 MicroF Elco
2 x push-to-make buttons

This circuit will send a pulse every x milliseconds. You can control the pulse length by pressing the buttons.






Upload the following sketch to the Arduino, you will need the Metro library:


#include

#define PINBUTTON1 2
#define PINBUTTON2 3
#define PINMOTOR 8


signed int pulseTime=50;
unsigned long prevPulse = millis();

boolean inPulse = false;

Metro MotorPulse = Metro(250);


void setup ()
{
  pinMode(PINMOTOR, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  if (millis() %500 ==0)
 {
  int curbut1 = digitalRead(PINBUTTON1);
  if (curbut1==HIGH)
  {
    if (pulseTime + 5 <=100)
   pulseTime +=5;
   else
     pulseTime=100;
 Serial.print(pulseTime);
 Serial.print("\n");


  }
 
  int curbut2 = digitalRead(PINBUTTON2);
  if ( (curbut2==HIGH))
  {
    if (pulseTime - 5 >=0)
      pulseTime -=5;
    else
      pulseTime = 0;
     
 Serial.print(pulseTime);
 Serial.print("\n");


  }
 }

 
  if (!inPulse)
  {
    if (MotorPulse.check() == 1)
    {
      MotorPulse.interval(5);
      inPulse = true;
      digitalWrite(PINMOTOR , HIGH);
    }
  }
  else
  {
    if (MotorPulse.check() == 1)
    {
      MotorPulse.interval(pulseTime);
      inPulse = false;
      digitalWrite(PINMOTOR , LOW);
    }
  }
 
}