Making an FM radio-Part 2; the incremental encoder

Despite being a digital radio capable of doing a lot of stuff I wanted a simple design with a knob for volume and another one to change station. The volume is just a potentiometer and for the stations I wanted to use an encoder, unfortunately I didn’t have one. What I did have is a hard drive motor and as it turns out you can use them as rotary encoders. I found two ways to do this; one is to use the signals from the hall sensors and the other one is to use the back fem generated by the winding. The motor has all the electronics sealed making it difficult to figure out how to use the sensors so I used the second method. I found two projects that use brushless motors as encoders taking advantage of the back EMF. In one op-amps are used as amplifiers and the outputs are sampled with a microcontroller’s ADC, in the other the op-amps are used as comparators thus generating a couple of square waves. With the second approach I could use interruptions instead of sampling both ADC channels all the time so I went for the comparator setup.
For the first tests I used only a couple of led at the op-amp outputs to see if the circuit was doing something. Then I watched the outputs with a logic analyzer and let me tell you, it wasn’t pretty. Anyway, I searched for ways to read encoder signals with a microcontroller and I found this. I copied that code and add it a few lines to have a couple of pins generating pulses depending on the direction of rotation.

Unfortunately that code was made to be used with a real encoder with a much cleaner signal. In the picture I’m moving the motor in one direction but both outputs (channel 2 and 3) are generating pulses.

If you use an optical encoder all you have to do is detect a flank (either low->high or high->low) in one signal and check the value of the other one. With my “encoder” I have to detect both flanks and check the values of the other signal in those situations to see if an acceptable sequence has occurred.  And after a few changes I got this;

The first picture shows the signals generated when I move the motor fast first in one direction and then in the other. In the second picture I’m moving the motor slower (as if I’m looking for a station) in only one direction.  The signal is worst when I turn it slower but the microcontroller managed to detect a few pulses which I’ll be using to control the radio. Finally the code;

#include <msp430g2452>;
#include "stdint";
int aux=0;
int edge=1; //0=high-&gt;low, 1=low-&gt;high
int dir=0;
int accept=0;
void main( void )
 {
 // Stop watchdog timer to prevent time out reset
 WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // SMCLK = DCO = 16MHz
P1REN |= BIT1 + BIT2;  // select pullup resistors for pin 1.1 and 1.2
P1DIR |= BIT5 + BIT4;  // outputs for testing
P1OUT |= BIT1 + BIT2;  // need to set P1.1 and P1.2 to high so PULLUP resistor will be selected
P1IES &= ~ BIT2;  // select low to high transition for interrupts on all port pins (this actually the default)
P1IE  |= BIT2;  // enable interrupt for P1.2 to reader status of encoder every time Encoder sigal A goes high
P1IFG = 0x00;  // clear interrupt register
__bis_SR_register(LPM0_bits + GIE);
for (;;) {
}
}
#pragma vector = PORT1_VECTOR
 __interrupt void InterruptVectorPort1()
 {
 if( P1IFG &amp; BIT2 ) {
    switch(edge){
     case 1://always start with the 0-&gt;1 edge
      aux=( P1IN &amp; BIT1 );//save the other channel input
      P1IES =BIT2; //Edge sensitivity
      edge=0;//the next interruption will be in 1-&gt;0
      accept=0;//reset value
     break;
     case 0:
      if((P1IN & BIT1)==aux){accept=0;}//Not a good pulse sequence;
      else{accept=1;//Good pulse sequence
      P1IES &= ~BIT2 ; // Toggle Edge sensitivity
      edge=1;
      if(P1IN & BIT1){dir=2;}//save direction of movement
      else{dir=1;}
     break;
 } if(accept){//if a good sequence is detected...
    switch(dir){//output a short pulse in the correct direction
     case 2:
      P1OUT |= BIT4; // output P1.4
      __delay_cycles(1500);
      P1OUT &= ~BIT4;
     break;
    case 1:
      P1OUT |= BIT5; // output P1.5
     __delay_cycles(1500);
     P1OUT &= ~BIT5;
    break;
 }
 }
 P1IFG&= ~ BIT2;
 }
}
Advertisements

3 thoughts on “Making an FM radio-Part 2; the incremental encoder

    • I used the motor. I finished the radio but It was picking to much noise from the seven segment displays (those are multiplexed and shown the current FM station), it needs much better filtering and I need an oscilloscope for propper troubleshooting. Definitely on my to do list!

      • Good to hear that you used the motor. I am trying to use one to for my FM-Radio. The motor as rotary encoder is working like a charm after I introduced a very small hysteresis (50mV) in the comparators.
        And Yes, you do need an oscilloscope. Mine are (I have several) are all quite old analog scopes but I do not want to live without one.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s