Speed and length measurement based on counting the rotational time of a roller

Dependencies:   USBDevice mbed

main.cpp

Committer:
BPPearson
Date:
2016-01-05
Revision:
0:0b32433dec5d

File content as of revision 0:0b32433dec5d:

#include "mbed.h"
#include "USBHID/USBHID.h"


#define  CMD_GET_ALL_VALUES         1
#define  CMD_GET_ROLLER_DIAMETER    2
#define  CMD_SET_ROLLER_DIAMETER    3
#define  CMD_SYS_CHECK              4
#define  CMD_SYS_RESET              5

#define COMMAND 0
#define DATA 1

#define VERSION 0x01

//We declare a USBHID device. By default input and output reports are 64 bytes long.
USBHID hid(64, 64);
HID_REPORT send_report __attribute__((aligned (4))); // Aligned for fast access
HID_REPORT recv_report __attribute__((aligned (4))); // Aligned for fast access

BusInOut databus(p8, p9, p10, p11, p12, p13, p14, p15);
DigitalOut registerSelect(p5);
DigitalOut readWriteClock(p7);
DigitalOut readWrite(p6);

Ticker updateLCD;
Ticker periodicTimer;

LocalFileSystem local("local");

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
Serial pc(USBTX, USBRX); // tx, rx
InterruptIn oneRotationPulse(p30);
InterruptIn reelChangeInput(p29);
 
//unsigned short timer_count;

unsigned int captureVal = 0;
unsigned int previousVal = 0;
unsigned int diff = 0;
bool newValToProcess = false;
bool newValToSend = false;
float rollerDiameter = 100.0;
double lengthFactor =  3.14159265359 * rollerDiameter;
double speedFactor =  lengthFactor * 1000000.0;
double speed = 0.0;
int rotationalCount = 0;
double reelLength = lengthFactor * (double)rotationalCount;
int displayMode = 0;
int noActivityCounter = 0;


void pin29ISR()
{
    
    rotationalCount = 0;

    reelLength = lengthFactor * (double)rotationalCount;
}


void pin30ISR()
{

    captureVal = LPC_TIM0->TC;

    rotationalCount++;

    diff = captureVal - previousVal;

    speed = speedFactor / (double)diff;

    reelLength = lengthFactor * (double)rotationalCount;

    previousVal = captureVal;
    
    newValToSend = true;
    
    noActivityCounter = 0;
        
    led2 = !led2;
}



void readConfigFile()
{
    
    FILE *fp = fopen("/local/config.dat", "r");

    if (fp != NULL)
    {
        fscanf(fp, "%f", &rollerDiameter); 
        fclose(fp);
    }
}



void writeConfigFile()
{
    FILE *fp = fopen("/local/config.dat", "w");

    if (fp != NULL)
    {
        fprintf(fp, "%5.1f\n", rollerDiameter);
        fclose(fp);
    }
}

void writeToLCD(bool rs, char data){

    // set register select pin 
    registerSelect = rs;
    
    // set read/write pin to write
    readWrite = 0;
    
    // set bus as output
    databus.output();
    
    // put data onto bus
    databus = data;
    
    // pulse read/write clock
    readWriteClock = 1;
    
    wait_us(1);
    
    readWriteClock = 0;

    wait_us(1);
    
    // clear data bus
    databus = 0;
    
    //pc.printf("%02x\n", data);
    
}


char readFromLCD(bool rs){

    char data;
    
    // set register select pin 
    registerSelect = rs;
    
    // set read/write pin to read
    readWrite = 1;
    
    // set bus as output
    databus.input();
    
    // put data onto bus
    data = databus;
    
    // pulse read/write clock
    readWriteClock = 1;
    
    wait_us(10);
    
    readWriteClock = 0;
    
    return data;
}


void resetLCD(){
}


void initLCD(){
    
    // wait 15 ms to allow LCD to initialise
    wait_ms(15);
    
    // set interface for 8 bit mode
    writeToLCD(COMMAND, 0x30);

    // give it time    
    wait_ms(5);

    // set interface for 8 bit mode again
    writeToLCD(COMMAND, 0x30);

    // give it time    
    wait_us(100);

    // set interface for 8 bit mode again, last one before we can configure the display
    writeToLCD(COMMAND, 0x30);

    // give it time    
    wait_us(500);
    
    // set interface for 8 bit mode, 2 display lines and 5 x 8 character font
    writeToLCD(COMMAND, 0x38);

    // give it time    
    wait_us(100);
    
    // display off
    writeToLCD(COMMAND, 0x08);

    // give it time    
    wait_us(100);
    
    // clear the screen
    writeToLCD(COMMAND, 0x01);

    // give it time to finish    
    wait_ms(2);

    // set entry mode to increment cursor position cursor on write
    writeToLCD(COMMAND, 0x03);
    
    // give it time to finish    
    wait_us(100);

    // position cursor at home
    writeToLCD(COMMAND, 0x02);
    
    // give it time to finish    
    wait_ms(2);

    // display on
    writeToLCD(COMMAND, 0x0F);
}




void positionCursor(uint8_t x, uint8_t y){

    if (x > 7) x = 0;
    
    if (y == 1)
        writeToLCD(COMMAND, 0x80 + 0x40 + x);
    else
        writeToLCD(COMMAND, 0x80 + 0x00 + x);
        
    wait_us(50);
}



void displayString(int x, int y, char *str){
    
    // position cursor
    positionCursor(x, y);    
    
    // write string to screen
    for (int i=0; i<strlen(str); i++)
    {
        writeToLCD(DATA, str[i]);
        
        wait_us(50);
    }
}
 

 
void updateDisplay(){
    char str[20];
    
    displayMode++;
    
    if (displayMode > 10)
        displayMode = 0;
        
    if (displayMode > 5)
    {
        sprintf( str, "%6.0f m", reelLength);
    }
    else
    {
        sprintf( str, "%4.1f m/s", speed);
    }

    displayString(0, 0, str);
}
 





void empty_report(HID_REPORT *data){
    register uint32_t *p = (uint32_t *)data->data;
    for( register int i=0; i<((sizeof(HID_REPORT)-1)/4); i++ ){
        *p = 0xFFFFFFFF;
        p++;
    }
}



void checkForUSBRequest()
{
    char *cptrR;
    char *cptrT;
    //float fTmp;
    //bool updatePIDValues = false;

    //try to read a msg
    if(hid.readNB(&recv_report)){
        
        // set character pointer to start of the parameter for set commands
        cptrR = (char *)&recv_report.data[1];
        cptrT = (char *)&send_report.data[1];

        led1 = 1;
        
        // Data packet received, start parsing
        int irx=0;
        int itx=0;

        send_report.data[itx++] = recv_report.data[0];

        switch (recv_report.data[irx++])
        {
            case    CMD_SYS_CHECK       :
                send_report.data[itx++] =  VERSION;
                break;
            
            case CMD_SYS_RESET       : 
                  // Soft reset
                    empty_report(&recv_report);
                break;

            case CMD_GET_ALL_VALUES:
                if (newValToSend)
                {
                    pc.printf("Capture val = %x, diff = %d, speed = %5.3f m/s, length = %5.1 m\n\r", captureVal, diff, speed, reelLength);
                
                    // return the speed, length and raw count values
                    sprintf((char *)send_report.data, "%c%c%10.1f %10.1f %10d", recv_report.data[0], 1, speed, reelLength, diff);
    
                    newValToSend = false;
                }
                else
                {
                    sprintf((char *)send_report.data, "%c%c", recv_report.data[0], 0);
    
                }
                break;
                
            case CMD_GET_ROLLER_DIAMETER:
                // return the roller diameter
                sprintf(cptrT, "%5.1f", rollerDiameter);
                pc.printf("roller diameter = %f\n", rollerDiameter );
                break;
                
            case CMD_SET_ROLLER_DIAMETER:
                // set roller diameter to value in packet
                sscanf(cptrR, "%f", &rollerDiameter);
                writeConfigFile();
                pc.printf("Set roller diameter to %f\n", rollerDiameter);
                break;
                
            case 0xEE   : {
                hid.sendNB(&send_report);  
                //WatchDog_us bello(100);
                }
            break;

            default:
                send_report.data[0] =   0xFF;   //Failure
            break;
        } // Switch 

        // Return command + optional new args
        hid.send(&send_report);

        // 0xFF unused bytes
        empty_report(&recv_report);         
        empty_report(&send_report);
        
        led1 = 0;
    }       // if packet
}


void periodicChecks()
{
    
    noActivityCounter++;
    
    if (noActivityCounter > 5)
    {
        speed = 0;
    }
}



int main (void) 
{
        
    pc.printf("initialise the LCD\n");
    
    initLCD();
    
    pc.printf("read the config file\n");

    readConfigFile();

    pc.printf("start updateLCD ticker\n");

    updateLCD.attach(&updateDisplay, 0.5);
    
    periodicTimer.attach(&periodicChecks, 1.0);
        
    pc.printf("initialise the USB interface\n");

    led1 = 0;
    led2 = 0;

    send_report.length = 64;
    recv_report.length = 64;

    pc.printf("initialise the timer_init\n\r");

    LPC_SC->PCONP |= 1 < 1;         //timer0 power on
    LPC_TIM0->TCR = 1;              //enable Timer2


    reelChangeInput.mode(PullUp);
    reelChangeInput.fall(&pin29ISR);  

    oneRotationPulse.mode(PullUp);
    oneRotationPulse.fall(&pin30ISR);  

    while(1)
    {
        
        checkForUSBRequest();
        
        wait(0.1);               // adjust to 0.01 when code working properly so we don't miss events
    }
}