This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2541 connect to optical encoder

Other Parts Discussed in Thread: CC2541

Hello,

I want to connect a mouse encoder, that is a LED light and a sensor to a CC2541 chip. Is this possible?

I have the reference design of CC2541 and I found a reference design of a mouse encoder. I want to join these two reference design. Again, is this possible?  I have the reference design below. Can anyone help?

Reference design for CC2541

0654.CC2541EM_Schematic.pdf

Reference design for the mouse encoder, with LED light and sensor. This diagram has a PIC chip, but I want to know whether if I can remove the PIC chip and connect it with CC2541. if yes, does anyone know how?

3058.reference design of mouse encoder.docx

thank you

  • The optical encoder outputs logic levels so this can absolutely be connected to the CC2541. You would of course need to create an encoder driver in SW.

    Cheers,
    Fredrik

  • Thank you for the reply, but what does SW means and how do I create an encoder driver in SW?

  • I want to code the CC2541, but below, I have the code for the PIC16F628A. Can anyone verify this code and help me to port and adapt these codes into CC2541.

    /******************************************************************************
    DC_motor_xtal.c - run a DC motor at xtal "clockwork" locked speed
    Started 8 Apr 2013 - Copyright www.RomanBlack.com, allowed for public use,
    you must mention me as the author and please provide
    a link to my web page where this system is described;
    www.RomanBlack.com/onesec/DCmotor_xtal.htm

    PIC16F628A - 20MHz HS xtal (see web page for schematic)
    Compiler - MikroC for PIC v8
    PIC pins;
    RA0 = digital ST input, quad encoder A
    RA1 = digital ST input, quad encoder B
    RB3 = CCP1 output, PWM to motor, HI = ON
    RB0 = echo encoder A output
    RB1 = echo encoder A output

    PIC configs; MCRLE off, BODEN off, BORES off, WDT off, LVP off, PWRT on
    ******************************************************************************/

    // This constant sets the motor speed. The value is in nanoSeconds per pulse,
    // as we are using a quadrature encoder there are 4 pulses per encoder slot.
    // My encoder had 36 slots, so that makes 36*4 or 144 pulses per revolution.
    // Example; 1 motor rev per second = 144 pulses /sec.
    // nS per pulse = 1 billion / 144 = 6944444
    //#define MOTOR_PULSE_PERIOD 1736111 // 4 RPS
    //#define MOTOR_PULSE_PERIOD 3472222 // 2 RPS
    #define MOTOR_PULSE_PERIOD 6944444 // 1 RPS
    //#define MOTOR_PULSE_PERIOD 13888889 // 0.5 RPS

    // This constant sets the proportional gain. Basically it sets how much
    // more PWM % is added for each pulse behind that the motor gets.
    // ie; if set to 10, the PWM is increased by 10% for each pulse behind.
    // Values must be within 1-50. Values of 10 or 16 worked well with
    // low motor RPMs, for higher RPMs a smaller value like 2 to 8 can be used.
    #define MOTOR_PROP_GAIN 10

    // global vars
    unsigned char rpos; // reference position of xtal based freq
    unsigned char mpos; // actual motor position
    unsigned char mlag; // amount the motor lags the reference
    unsigned char enc_new; // holds motor's quadrature encoder data for testing
    unsigned char enc_last;
    unsigned long bres; // bresenham accumulator used to make ref frequency
    unsigned char pins; // temporary var for echoing encoder signals


    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    void interrupt()
    {
    //-------------------------------------------------------
    // This is TMR0 int, prescaled at 2:1 so we get here every 512 instructions.
    // This int does the entire closed loop speed control;
    // 1. updates encoder to see if motor has moved, records it position
    // 2. updates reference freq generator, records its position
    // 3. compares the two, sets PWM if motor lags behind reference
    // 4. limit both counts, so they never roll, but still retain all error
    //-------------------------------------------------------
    // clear int flag straight away to give max safe time
    INTCON.T0IF = 0;

    // 1. updates encoder to see if motor has moved, records it position
    enc_new = (PORTA & 0b00000011); // get the 2 encoder bits
    if(enc_new != enc_last)
    {
    if(enc_new.F1 != enc_last.F0) mpos++; // record new motor position
    else mpos--;
    enc_last = enc_new;
    }

    // 2. updates reference freq generator, records its position
    bres += 102400; // add nS per interrupt period (512 insts * 200nS)
    if(bres >= MOTOR_PULSE_PERIOD) // if reached a new reference step
    {
    bres -= MOTOR_PULSE_PERIOD;
    rpos++; // record new xtal-locked reference position
    }

    // 3. compares the two, set PWM% if motor lags behind reference
    if(mpos < rpos) // if motor lagging behind
    {
    mlag = (rpos - mpos); // find how far it's lagging behind
    if(mlag >= (100/MOTOR_PROP_GAIN)) CCPR1L = 100; // full power if is too far behind
    else CCPR1L = (mlag * MOTOR_PROP_GAIN); // else adjust PWM if slightly behind
    }
    else // else if motor is fast, cut all power!
    {
    CCPR1L = 0;
    }

    // 4. limit both counts, so they never roll, but still retain all error
    if(rpos>250 || mpos>250)
    {
    rpos -= 50;
    mpos -= 50;
    }

    }
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


    //=============================================================================
    // MAIN
    //=============================================================================
    void main()
    {
    //-------------------------------------------------------
    // setup PIC 16F628A
    CMCON = 0b00000111; // comparators OFF, all pins digital

    PORTA = 0b00000000; //
    TRISA = 0b00000011; // RA0,RA1 used for digital ST encoder inputs

    PORTB = 0b00000000; //
    TRISB = 0b00000000; // RB3 is CCP1 PWM out, RB0,RB1 are encoder echo outputs

    // set TMR2 to roll every 100 ticks, PWM freq = 5mil/16/100 = 3125 Hz
    T2CON = 0b00000111; // TMR2 ON, 16:1 prescale
    PR2 = (100-1); // PWM total period of 100

    // set PWM out on CCP1
    CCPR1L = 0; // PWM range 0-100% = start with PWM of 0%
    CCP1CON = 0b00001100; // CCP1 on, set to PWM mode

    // TMR0 used for interrupt, makes interrupt every 512 insts
    OPTION_REG = 0b10000000; // PORTB pullups OFF, TMR0 on, 2:1 prescale

    //-------------------------------------------------------
    // setup before main loop
    Delay_mS(200); // allow PSU voltages time to stabilise

    // setup vars etc, will be used in interrupt
    bres = 0;
    rpos = 0;
    mpos = 0;

    // finally start TMR0 roll interrupt
    INTCON = 0b10100000; // GIE=on, TMR0IE=on

    //-------------------------------------------------------
    // main run loop
    while(1)
    {
    //-------------------------------------------------
    // We don't need to do anything in main loop as the motor speed
    // control is done entirely in the TMR0 interrupt.


    //-------------------------------------------------
    // For convenience in setting up the encoder trimpots,
    // echo the two encoder pins out two spare PORTB digital outputs!
    pins = 0;
    if(PORTA.F0) pins.F0 = 1;
    if(PORTA.F1) pins.F1 = 1;
    PORTB = pins; // output those two pins only (PWM output is not affected)
    }
    }
    //-----------------------------------------------------------------------------

    Thank you

  • Hello,

    I have attached the reference design of a  CC2541 to the encoder.  Can anyone check this and correct me if it is wrong.