Rotary encoder displays

011
Rotary encoder display V1.0 - Build Instructions

Roary encoder display V1.0 - Build Instructions

1.0.0 - 8 September, 2015 477.07 KB

Sooner or later there will be a project wich uses rotary encoders and LEDs.

I created these two units to test out the possibilities. These are great circuits to be used on breadboard or as a building block in an enclosure.

Here are some demo videos of the working units: (It is up to your software how many steps are needed to switch to the next LED. This demo uses 256 steps for 100%)

 


 


 

 


// PIC Testboard - Rotary Encoder
// Version 0.2
// 12.12.2013
// (c) 2013 Thomas Hofmann
// TH custom effects
//
// PROCESSOR : PIC16F1827
// CLOCK     : INTERNAL 34Mhz

#include     <xc.h>

#pragma config FCMEN = OFF   // Fail Save Clock Monitor
#pragma config IESO  = OFF   // Internal/External Switchover mode
#pragma config WDTE  = OFF   // Watchdog Timer Enable
#pragma config MCLRE = OFF   // Reset Enable (see LVP)
#pragma config BOREN = OFF   // Brownn Out Ebable
#pragma config PWRTE = OFF   // Power up Timer enable
#pragma config LVP   = OFF   // Low Voltage Programming
#pragma config CLKOUTEN=OFF  // Clock Output Enable
#pragma config FOSC = INTOSC // Internal Oscillator
#pragma config CP    = ON    // Program Memory Code Protection
#pragma config CPD   = OFF   // Data Memory Code Protection
#pragma config STVREN= OFF   // Stack Overflow Reset


#define bit_set(var,bitno) ((var) |= 1 << (bitno))
#define bit_clr(var,bitno) ((var) &= ~(1 << (bitno)))
#define testbit_on(data,bitno) ((data>>bitno)&0x01)

unsigned int  e_max   = 256; // max encoder value
unsigned char e_last  = 0;  // encoder old value
unsigned char e_new   = 0;  // encoder new value
signed   char e_delta = 0;  // diff
signed   char e_temp  = 0;  // encoder temp
unsigned char e_count = 0;  // encoder counter

unsigned char b_temp  = 0;  // button temp
unsigned char b_pres  = 0;  // debouncing
unsigned char B_FLAG  = 0;  // Button toggle flag

unsigned char wait    = 0;

const static signed char table[16] = {0,0,-1,0,0,0,0,1,1,0,0,0,0,-1,0,0};

void interrupt isr(void) {
    if (TMR4IF) // timer4 interrupt (1ms interval)
    {
        // decode encoder
        e_new  = PORTA & 0b00011000;
        e_last = (e_last << 2)  & 0x0F;
        if (testbit_on(e_new,3)) e_last |=2;
        if (testbit_on(e_new,4)) e_last |=1;
        e_delta += table[e_last];

        // check for button pressed
        b_temp=PORTB & 0x01;                      // Read B0
        if ((b_temp==0x01) && (b_pres==0x01)) {   // Toggle Button Flag
            b_pres=0;
            B_FLAG^=0x01;
        }
        if (b_temp==0x00){b_pres=0x01;}           // indicate key pressed
        TMR4IF=0;
    }
}

signed char encoder_read( void )                   // Encoder auslesen
{
  signed char val;

  PEIE=0;
  val = e_delta;
  e_delta = 0;
  PEIE=1;
  return val;
}

//Just simple delay
void Delay(unsigned long cntr) {
    while (--cntr != 0);
}


// sending data word to controller 1x16
void out_LEDx16(unsigned int data){
    for (unsigned char l=0; l<=15; l++){  // output bit by bit
        if testbit_on(data,15-l) bit_set(LATB,1);  else bit_clr(LATB,1);  // Set data on RB1
        LATB^=0x04;  // Pulse SCK on RB2
        LATB^=0x04;
    }
    LATA^=0x04;      // Pulse LE on RA2
    LATA^=0x04;
}

// sending data word to controller 2x16
void out_LEDx32(unsigned int data, unsigned int data2){
    for (unsigned char l=0; l<=15; l++){  // output bit by bit
        if testbit_on(data2,15-l) bit_set(LATB,1);  else bit_clr(LATB,1);  // Set data on RB1
        LATB^=0x04;  // Pulse SCK on RB2
        LATB^=0x04;
    }
    for (unsigned char l=0; l<=15; l++){  // output bit by bit
        if testbit_on(data,15-l) bit_set(LATB,1);  else bit_clr(LATB,1);  // Set data on RB1
        LATB^=0x04;  // Pulse SCK on RB2
        LATB^=0x04;
    }
    LATA^=0x04;      // Pulse LE on RA2
    LATA^=0x04;
}

// converting char 0-16 to point/bar indicator
unsigned int value_to_graph(unsigned char data, unsigned char nvl_enable, unsigned char point_bar){
    unsigned int  buff = 0;
    unsigned char ctr  = 0;
    if ((data>0) || (nvl_enable>0)){
        buff=1;
        for (ctr=0; ctr<data; ctr++){  // shift left x times
            buff=buff<<1;
            if (point_bar>0){buff++;}
        }
    }
    return buff;
}

unsigned char calc_div(unsigned char val){
    unsigned char adjust = 0;
    adjust = e_max/16;
    return val/adjust;
}

// main function
void main(void) {
    OSCCON = 0b11110000; // 8Mhz  x PLL=4 = 32Mhz         // General
    OPTION_REG = 0x00;   // GPIO pull-ups are enabled
    INTCON = 0x00;       // Disable all Interrups

    TRISA  = 0b00111010; // PORTA 6,7 OUT - LED Bicolor, 2-OUT-LE, 3,4 - IN- Encoder, 0 - SDO2
    TRISB  = 0b00001001; // PORTB 4-6 OUT - LED RGB; 0- IN-Pushbutton;  1,4 = I2C

    ANSELA = 0x00;       // Disable Analog Port A
    ANSELB = 0x00;       // Disable Analog Port B

    LATA = 0x00;         // Set PORTA to defined State
    LATB = 0x00;         // Set PORTB to defined State

    TMR4 = 0x00; // reset counter 4                     // Encoder TIMER
    T4CON = 0b00001010; // 1:2 postscaler, 1:16x prescaler
    PR4 = 250; // interrupt is called 1/1000s
    TMR4IF = 0; // Clear Timer4 IF
    TMR4IE = 1; // Allow Timer4 Interrupts
    TMR4ON = 1; // Start Timer4
  
    PEIE = 1; // Enable Low Priority Interrupts          // INTERRUPS
    GIE = 1; //  Enable global interrupts

    LATA = 0b01000000;   // light bicolor LED to indicate RED

    unsigned int show   = 1;
    unsigned char i     = 0;
    unsigned char ack   = 0;


    while(1) {
        e_temp=encoder_read();   // read encoder changres since last read
        if ((e_count==0) && (e_temp==-1) || (e_count==e_max-1) && (e_temp==1)) {}
        else {                  // update new value only if no under/overrun will occour
            e_count+=e_temp;
            //out_LED(value_to_graph(calc_div(e_count),1,B_FLAG)); // output value with nulval_enabled and point
            out_LEDx32(value_to_graph(calc_div(e_count),1,B_FLAG),value_to_graph(calc_div(255-e_count),1,B_FLAG)); // output value with nulval_enabled and point
        }
    }
}

 

Leave a Comment

Your email address will not be published. Required fields are marked *