encoder and tachometer class for EW3XX single board computer

EW305sbc.cpp

Committer:
lddevrie
Date:
2019-08-15
Revision:
0:1d5bf13d7dbb
Child:
1:b33d4964669b

File content as of revision 0:1d5bf13d7dbb:

//#include "mbed.h"
#include "EW305sbc.h"


EW305sbc::EW305sbc(int ch, int pulsesPerRev) 
    : ch_(ch), pulsesPerRev_(pulsesPerRev), spi(p5, p6, p7), ls7166_cs1(p19,1), ls7166_cs2(p20,1)
{
    init();
}

void EW305sbc::init()
{
    dt_ = 0.00625; // 125 Hz
    speed_ = 0.0; // initial distance
    countp_ = 0;
    count_ = 0;
    /** configure the rising edge to start the timer */
    updater.attach(callback(this, &EW305sbc::recalc), 0.00625); // 125 Hz, syntax from https://os.mbed.com/forum/mbed/topic/1964/?page=1
    wait(.2);   //delay at beginning for voltage settle purposes

    // initialize channel 1 encoder by 
    LS7366_reset_counter(ch_);
    LS7366_quad_mode_x4(ch_);
    LS7366_write_DTR(ch_,0);
}


void EW305sbc::recalc()
{
    // Read encoder
    count_ = -LS7366_read_counter(ch_); // input is the encoder channel

    // Estimate speed (counts/sec)
    speed_ = (count_-countp_)/0.00625*2.0*3.14159/(4.0*pulsesPerRev_);

    // Age variable
    countp_ = count_;
}


int EW305sbc::getCount(void)
{
    return count_;
}

float EW305sbc::getSpeed(void)
{
    return speed_;
}






//---- Function Listing -------------------------------

//----- LS7366 Encoder/Counter Routines --------------------
void EW305sbc::LS7366_cmd(int inst,  int reg)
{
    char cmd;
    spi.format(8, 0);
    spi.frequency(2000000);
    cmd = (inst << 6) | (reg << 3);
//    printf("\r\ncmd=0X%2X", cmd);
    spi.write(cmd);
}

long EW305sbc::LS7366_read_counter(int chan_num)
{
    union bytes {
        char byte_enc[4];
        long long_enc;
    } counter;

    counter.long_enc = 0;
    spi.format(8, 0);
    spi.frequency(2000000);

    if(chan_num!=2) {
        ls7166_cs1 = 0;
        wait_us(1);
        LS7366_cmd(LOAD,OTR);//cmd = 0xe8, LOAD to OTR
        ls7166_cs1 = 1;
        wait_us(1);
        ls7166_cs1 = 0;
    } else {
        ls7166_cs2 = 0;
        wait_us(1);
        LS7366_cmd(LOAD,OTR);//cmd = 0xe8, LOAD to OTR
        ls7166_cs2 = 1;
        wait_us(1);
        ls7166_cs2 = 0;
    }
    wait_us(1);
    LS7366_cmd(RD,CNTR);  //cmd = 0x60, READ from CNTR
    counter.byte_enc[3] = spi.write(0x00);
    counter.byte_enc[2] = spi.write(0x00);
    counter.byte_enc[1] = spi.write(0x00);
    counter.byte_enc[0] = spi.write(0x00);

    if(chan_num!=2) {
        ls7166_cs1 = 1;
    } else {
        ls7166_cs2 = 1;
    }

    return counter.long_enc;  //return count
}

void EW305sbc::LS7366_quad_mode_x4(int chan_num)
{

    spi.format(8, 0);
    spi.frequency(2000000);

    if(chan_num!=2) {
        ls7166_cs1 = 0;
    } else {
        ls7166_cs2 = 0;
    }
    wait_us(1);
    LS7366_cmd(WR,MDR0);// Write to the MDR0 register
    wait_us(1);
    spi.write(0x03); // X4 quadrature count mode
    if(chan_num!=2) {
        ls7166_cs1 = 1;
    } else {
        ls7166_cs2 = 1;
    }
}

void EW305sbc::LS7366_reset_counter(int chan_num)
{
    spi.format(8, 0);           // set up SPI for 8 data bits, mode 0
    spi.frequency(2000000);     // 2MHz SPI clock

    if(chan_num!=2) {           // activate chip select
        ls7166_cs1 = 0;
    } else {
        ls7166_cs2 = 0;
    }
    wait_us(1);                 // short delay
    LS7366_cmd(CLR,CNTR);       // Clear the counter register
    if(chan_num!=2) {           // de-activate chip select
        ls7166_cs1 = 1;
    } else {
        ls7166_cs2 = 1;
    }
    wait_us(1);                 // short delay

    if(chan_num!=2) {           // activate chip select
        ls7166_cs1 = 0;
    } else {
        ls7166_cs2 = 0;
    }
    wait_us(1);                 // short delay
    LS7366_cmd(LOAD,CNTR);      // load counter reg
    if(chan_num!=2) {           // de-activate chip select
        ls7166_cs1 = 1;
    } else {
        ls7166_cs2 = 1;
    }
}

void EW305sbc::LS7366_write_DTR(int chan_num, long enc_value)
{
    union bytes {              // Union to speed up byte writes
        char byte_enc[4];
        long long_enc;
    } counter;

    spi.format(8, 0);           // set up SPI for 8 data bits, mode 0
    spi.frequency(2000000);     // 2MHz SPI clock

    counter.long_enc = enc_value; // pass enc_value to Union

    if(chan_num!=2) {             // activate chip select
        ls7166_cs1 = 0;
    } else {
        ls7166_cs2 = 0;
    }
    wait_us(1);                 // short delay
    LS7366_cmd(WR,DTR);         // Write to the Data Transfer Register
    spi.write(counter.byte_enc[3]); // Write the 32-bit encoder value
    spi.write(counter.byte_enc[2]);
    spi.write(counter.byte_enc[1]);
    spi.write(counter.byte_enc[0]);
    if(chan_num!=2) {           // de-activate the chip select
        ls7166_cs1 = 1;
    } else {
        ls7166_cs2 = 1;
    }

    wait_us(1);                 // short delay
    if(chan_num!=2) {           // activate chip select
        ls7166_cs1 = 0;
    } else {
        ls7166_cs2 = 0;
    }
    wait_us(1);                 // short delay
    LS7366_cmd(LOAD,CNTR);      // load command to the counter register from DTR
    if(chan_num!=2) {           // de-activate chip select
        ls7166_cs1 = 1;
    } else {
        ls7166_cs2 = 1;
    }
}