Showing posts with label Library. Show all posts
Showing posts with label Library. Show all posts

Wednesday, 10 July 2013

A Multiple Encoder Library For Arduino

Here is an Arduino library which allows you to connect and decode up to 5 rotary encoders. It is basically an extension of my original encoder library, which can only decode one encoder.

You can download the library here: https://github.com/frodofski/Encoder_Polling_V2

Here is the example sketch:

#include <EncoderV2.h>

const int pin_A = 4;  // Encoder input pins
const int pin_B = 5;
const int pin_C = 6;
const int pin_D = 7;

void setup()
{
  Serial.begin(9600);
  encoder_begin();  // Start the library
  attach_encoder(0, pin_A, pin_B);  // Attach an encoder to pins A and B
  attach_encoder(1, pin_C, pin_D);  // Attach another encoder to pins C and D
}

void loop()
{
  int dir_0 = encoder_data(0);  // First encoder
  int dir_1 = encoder_data(1);  // Second
  
  if(millis() > 10000)
  {
    detach_encoder(1);  // After 10 seconds, detach encoder 1 
  }
  
  if(dir_0 != 0)  // Check for rotation
  {
    Serial.print("Encoder 0: ");
    Serial.println(dir_0);
  }
  
  if(dir_1 != 0)  // Check for rotation
  {
    Serial.print("Encoder 1: ");
    Serial.println(dir_1);
  }
}

The library is super easy to use, as it has only four functions:

  • encoder_begin() starts the library by setting up timer2 (note: this may conflict with the tone library)
  • attach_encoder(encNum, pin_A, pin_B) attaches an encoder to pin_A and pin_B, and sets these pins as inputs. encNum can equal 0, 1, 2, 3, or 4, allowing for up to five rotary encoders. The library will now start polling those two input pins.
  • detach_encoder(encNum) will detach the input pins corresponding to that encoder, and it will stop polling those two input pins. The pins can now be used as regular io again.
  • encoder_data(encNum) returns the state of the specified encoder. It returns a 1 or -1 if the encoder has turned, depending on the direction of rotation. It will return a 0 if the encoder has not turned, or if there is no encoder attached to that particular encNum.

The library will store that last known direction of the rotary encoder, until the encoder_data() function has been called for that encoder. This allows you to run the main sketch at any speed, without having to worry about missing a step.


Finally, you may need to use a hardware debouncer for each of the input pins if your're not using an optical encoder, or if your mechanical rotary encoder is particularly bouncy.

Tuesday, 9 July 2013

An Even Better IR Decoder Library


I improved my old IR decoder library by adding some new features, without making it any more complicated. What's nice it that this is all done in the interrupt routine, so the library is still non-blocking. Here are the new features:

  • It no longer records invalid IR codes, and automatically resets when an invalid code is received (who cares if the code is invalid anyway?).
  • It removes the start bits, and the toggle bit from the code, to make it easier to determine what button was pressed on the remote.
  • It can determine whether a code is a repeat, or a new button press by the user.


The library can be downloaded here: https://github.com/frodofski/RC5_Decoder_V2


As before, the ir_begin() function starts the decoder, but ir_data() is a little different:
  • If there is no valid code present, it will return a 0. 
  • If there is a new code, it will return the code. 
  • Finally, if it is receiving a string of codes with each one being a repeat of the previous one, it will return -1 until the string is broken.

Whats nice about the repeat detection, is that you don't have to worry about stuff happening more than once when you hold down a button on the remote. And if you do want something to happen for as long as the button is held down, like a volume control for example, you just need to look for the -1s.

Here is the example code:

#include "irDecoderV2.h"

const int IR_pin = 10;

int code = 0;

void setup()
{
  Serial.begin(9600);  
  ir_begin(IR_pin);  // Start the decoder
}

void loop()
{
  code = ir_data();  // Check for IR code
  
  if(code > 0)  // If a code is available...
  {
    Serial.print("Code: "); // Print it
    Serial.println(code);
  }
  
  else if(code == -1)  // If its a repeat
  {
    Serial.println("Repeat");  // Print it
  }
  
  delay(250);  // Prevent clogging up serial monitor
}




As before, the library configures timer2 in a way which might conflict with the Tone library, and also may cause problems when trying to use pwm on digital pins 9 and 10.

Sunday, 30 June 2013

Button Debouncing Library for Arduino



I decided to write a small library to handle polling and debouncing of a button for the Arduino. The library is really simple, and uses a timer interrupt to do the polling and debouncing, much the same as my IR decoder and rotary encoder libraries. This allows it to run in the background, without affecting your main sketch, a bit like the millis() function does.

The library can be downloaded here: https://github.com/frodofski/Debouncer

Here is the example sketch:

#include "Debounce.h"

const int buttonPin = 10;

int buttonState = 0;
int buttonStateOld = 0;

int ledState = 0;

void setup()
{
  pinMode(13, OUTPUT);
  debounce_begin(buttonPin); // State debouncing a button on buttonPin
}

void loop()
{
  buttonState = button_data(); // Check button state
  
  // Toggle pin 13 LED if the button's been pressed
  if(buttonState != buttonStateOld)
  {
    buttonStateOld = buttonState;
    if(buttonState == 1)
    {
      ledState = !ledState;
      digitalWrite(13, ledState);
    }
  }
}

The debounce_begin() function sets up the library and the input pin you enter, and button_data() returns the debounced state of the button.

Debouncing is done using a state machine with three states, standby, waiting, and delaying.
  • In the standby state, it reads in the value of the button pin, then moves on to the waiting state.
  • In the waiting state, it keeps checking the button pin, waiting for a change. If it sees one (ie. the button was pressed/released) it moves on to the delaying state.
  • When its in the delaying state, it just delays for a period of time set by DEBOUNCE_DELAY using a counter. When the time is up, it reads the value of the button pin into the data variable, which is now the debounced state of the button. It then goes back to the standby state.

The debounce delay can be set in the Debounce.h file by changing DEBOUNCE_DELAY. It is measured in multiples of 300 us, which the time between each interrupt. The default debounce delay is approximately 20 ms, but some experimentation may be needed to find a reliable time.

The library can only handle one button at the moment, but I hope to add support for multiple buttons in the future.

Just one more thing: the library configures timer2 in a way which might conflict with the Tone library, and also may cause problems when trying to use pwm on digital pins 9 and 10.

Rotary Encoder Library for Arduino



Here is a simple library for the Arduino which polls and decodes a rotary encoder. It is based on a timer interrupt, just like my IR decoder, so it runs in the background, and doesn't affect your main sketch.

If you're using a mechanical encoder, you'll need to use pull-up resistors, and a hardware debouncer for each of the two pins.

The library can be downloaded here: https://github.com/frodofski/Encoder_Polling

Here's an example sketch:

#include "RotaryEncoder.h"

const int encoderPin_A = 8;
const int encoderPin_B = 9;

void setup()
{
  Serial.begin(9600);
  encoder_begin(encoderPin_A, encoderPin_B); // Start the decoder
}

void loop()
{
  int dir = encoder_data(); // Check for rotation
  
  if(dir != 0)              // If it has rotated...
  {
    Serial.println(dir);    // Print the direction
  }  
}

The encoder_begin() function takes in the pins connected to your encoder, and sets them as inputs, then it sets up timer2 to trigger the ISR every 300 us.

The encoder_data() function will return a 1 or a -1 depending on the direction of rotation. If the encoder hasn't rotated at all since the last time the function was called, it will just return a 0.

The decoder is implemented by a state machine in the ISR. It has three states, standby, waiting, and idle.

  • In the standby state, it reads in the value of pin_A into a variable. It then moves on to the waiting state.
  • In the waiting state, it continually polls pin_A, looking for a change. If it sees a change, it then reads in the value of pin_B to determine the direction of rotation. It stores the direction in the data variable, then it moves on to the idle state.
  • Finally, in the idle state, it simply does nothing and waits for your sketch to read in the data, and reset the state machine with the encoder_data() function.

There are only two functions, encoder_begin() and encoder_data() so the library is very easy to use. One thing to note, is that the library configures timer2 in a way which might conflict with the Tone library, and also may cause problems when trying to use pwm on digital pins 9 and 10.

Saturday, 29 June 2013

IR Decoder Library for Arduino



In a previous post we looked at a method (or algorithm) for decoding the Philips RC-5 protocol with the Arduino. The code was very simple, but not very efficient as it was 'blocking code'.
As a follow up to this, I have written a simple library for the Arduino which can decode RC-5 codes in the background, whilst your main sketch runs un-encumbered in the foreground.

The library can be downloaded here: https://github.com/frodofski/RC5_Decoder

Here is an example of using the library:

#include "irDecoder.h"

const int IR_pin = 10;

int code = 0;

void setup()
{
  Serial.begin(9600);  
  ir_begin(IR_pin);      // Start the decoder
}

void loop()
{
  code = ir_data();      // Check for IR code
  
  if(code != 0)          // If a code is available...
  {
    Serial.print("Code: ");  // Print it
    Serial.println(code);
  }
}




The code is very efficient and only uses a small percentage of the Arduino's computing power. This leaves plenty of computing power left for the rest of your sketch to run. One thing to note, is that the library configures timer2 in a way which might conflict with the Tone library, and also may cause problems when trying to use pwm on digital pins 9 and 10.