Rotary encoder via Bluetooth

In the spirit of experimentation, I decided to attach a rotary encoder to an imp, and send the values via bluetooth to a phone. Obviously, it’s not using any of the wifi capabilities of the imp itself, but it demonstrates just how simple this kind of thing can be.

`
// Simple example to read a rotary encoder using “interrupts”, and write
// the value via a Bluetooth UART to a terminal program on a phone.

// Rotary encoder has detents, and outputs an entire cycle each detent, not just
// a single change of state. So to get direction, we only need to check one state,
// since we know the previous will be 11 (final state in the previous cycle).
// However, we still get “interrupts” for each state change within the cycle.

// sjm 20130328

counter <- 0;
OldCounter <- 0;
OldState <- 3; // binary 11

function Changed()
{
local ChA = hardware.pin5.read();
local ChB = hardware.pin7.read();

local CurrentState = (ChA << 1) | ChB;
local NewState = (CurrentState << 2) | OldState;

switch(NewState)
{
    case 11:    // 10 11 
            counter++; break;
    case 7:     // 01 11
            counter--; break;
}
OldState = CurrentState;
if (counter != OldCounter)
{
    hardware.uart12.write(format("%d\\r\

",counter));
OldCounter = counter;
}
}

// Encoder pins are pulled up by the imp, switched to ground
hardware.pin5.configure(DIGITAL_IN_PULLUP,Changed);
hardware.pin7.configure(DIGITAL_IN_PULLUP,Changed);
hardware.uart12.configure(9600,8,PARITY_NONE,1,NO_RX);

imp.configure(“Rotary Encoder via Bluetooth”,[],[]);
`

Neat, I’ve not seen combining quadrature encoder states into a single int for comparison before. Very elegant!

I am using pin 1&2 and the above example with my rotary, yet I am always only getting 10 11 as an input. Anyone any idea whats going on? hardware and software identical except the pins I am using.

I have an issue where the Imp does not respond to commands because the changed event is constantly being called. Any ideas how to get around this?

It is certainly possible to saturate the imp’s CPU if you set a changed event on a pin that’s actually toggling very rapidly. One way around this might be, in your change handler, to disable the changed event (reconfigure the pin), and set a short timer to re-enable it again.

Peter

You could use the sampler class and write a simple function to look for transitions. As long as you sample fast enough to see everything, keep you buffers small enough to get callbacks at a rate that meets your response requirement, and can get your transition detection function fast enough to not cause overruns, you should be on business.