Read output from MAX21105 and burst output to serial PC

Dependencies:   mbed

main.cpp

Committer:
visarute
Date:
2015-12-03
Revision:
0:27f71d402a3e

File content as of revision 0:27f71d402a3e:

/*============================================================================
 MBED_MAX21105_Burst01
 Read data from MAX21105 IMU included temperature 
 Data return by serial command in burst mode
 and control MCP4921 DAC
 Visarute Pinrod
 SonicMEMS Laboratory, ECE, Cornell University, Ithaca, NY, USA
 September 21, 2015 
============================================================================*/

// Import library
#include "mbed.h"
#include "SPI.h"
#include "DigitalOut.h"

// Define pinout
SPI spi1(p5, p6, p7);           //mosi, miso, sck
DigitalOut cs_MAX21105(p8);     //cs for MAX21105 6Dof IMU
DigitalOut cs_MCP4921(p9);      //cs for MCP4921 DAC for heater
DigitalOut cs_TSYS01st(p10);    //cs for TSYS01 Temperature sensor for stage

// Object
Serial pc(USBTX, USBRX); // tx, rx
Timer t;

// get value from command format
int getVal(char *cmd){
    int val=-1;
    char valC[4];
    valC[0]=cmd[3];
    valC[1]=cmd[4];
    valC[2]=cmd[5];
    valC[3]=cmd[6];
    sscanf(valC,"%4x",&val);
    return val;
}

// Start SPI connection
void startSPI(){
    spi1.format(8,3);
    spi1.frequency(1000000);
    cs_MAX21105 = 1;
    cs_MCP4921 = 1;
    cs_TSYS01st = 1;
}

// SPI write data to MAX21105
void writeMAX21105(char addr, char value){
    cs_MAX21105 = 0;
    spi1.write(addr); // MAX21100 Writing scheme
    spi1.write(value); // MAX21100 Writing scheme
    cs_MAX21105 = 1;
}

// SPI read and return 8 bits data to MBED
char readMAX21105(char addr){
    char buf_u8;
    cs_MAX21105 = 0;
    spi1.write(0x80|addr); // MAX21100 Reading scheme
    buf_u8 = spi1.write(0x0); // MAX21100 Reading scheme
    cs_MAX21105 = 1;
    return(buf_u8);
}

void startMAX21105(){
    // Check MAX21105 conditions
    char whoami = readMAX21105(0x20); // WHOAMI register
    char buf = readMAX21105(0x21); // SILICON_REV_OTP register
   
    // Set MAX21105 options
    writeMAX21105(0x00, 0x00);  // SET_PWR 0x00 - Power down,
    writeMAX21105(0x01, 0x03);  // SNS_CFG_1 0x03 - LPF = 2kHz, SNS_DOUT_FSC=125 dps
    writeMAX21105(0x02, 0x22);  // SNS_CFG_2 0x22 - sns_gyr_ois_lpf=on, sns_odr=2000Hz
 //   writeMAX21105(0x02, 0x25); // SNS_CFG_2 0x25 - sns_gyr_ois_lpf=on, sns_odr=200Hz
//    writeMAX21105(0x02, 0x06); // SNS_CFG_2 0x06 - sns_odr=100Hz
    writeMAX21105(0x03, 0x00); // SNS_CFG_3 0x00 - sns_hpf_co = 0.08 Hz
    writeMAX21105(0x04, 0xC0); // SET_ACC_PWR 0xC0 - sns_acc_fsc=2g
    writeMAX21105(0x05, 0x30); // ACC_CFG1 0x30 acc_odr = 2000 Hz
 //   writeMAX21105(0x05, 0x33); // ACC_CFG1 0x33 acc_odr = 200 Hz
 //   writeMAX21105(0x05, 0x01); // ACC_CFG1 0x01 - acc_odr = 800 Hz
    writeMAX21105(0x06, 0x01); // ACC_CFG2 0x01 Unfiltered
    writeMAX21105(0x00, 0x78); // POWER_CFG 0x78 - accelero,gyro low noise 
    
    writeMAX21105(0x13, 0x01); // SET_TEMP_DR 0x01 - enable temp, fine, dataready all
    writeMAX21105(0x00, 0x78); // POWER_CFG 0x78 - accelero,gyro low noise 
    
    pc.printf("[IMU_INITIAL_ST]");
    pc.printf("WHOAMI = 0x%X (MAX21105: B4)", whoami); //WhoAmI MAX21105 = B4
    pc.printf("REVISION_ID = 0x%X", buf); // Should be 0x00
    pc.printf("[IMU_INITIAL_ED]\n");
}

// Read 6 axis data
// See MAX21105 User guide for address and bit field description
void readMAX21105All(char *imuBuf,short imuCnt){
    // Variables for data from IMU
    char con; // IMU status
    short i;  // Data point measurement loop variable
    int time;
    // Wait for connection and return data
    t.start();
    t.reset();
    for(i=0;i<imuCnt;i++) {
        while ((con = readMAX21105(0x23))==0); // wait until DATA_READY
        imuBuf[0+18*i] = con;
        imuBuf[1+18*i] = readMAX21105(0x24); // wX_H MSB Angular speed  X
        imuBuf[2+18*i] = readMAX21105(0x25); // wX_L LSB Angular speed  X
        imuBuf[3+18*i] = readMAX21105(0x26); // wY_H MSB Angular speed  Y
        imuBuf[4+18*i] = readMAX21105(0x27); // wY_L LSB Angular speed  Y
        imuBuf[5+18*i] = readMAX21105(0x28); // wZ_H MSB Angular speed  Z
        imuBuf[6+18*i] = readMAX21105(0x29); // wZ_L LSB Angular speed  Z
        
        imuBuf[7+18*i] = readMAX21105(0x2A); // aX_H MSB Acceleration  X
        imuBuf[8+18*i] = readMAX21105(0x2B); // aX_L LSB Acceleration  X
        imuBuf[9+18*i] = readMAX21105(0x2C); //aY_H MSB Acceleration  Y
        imuBuf[10+18*i] = readMAX21105(0x2D); //aY_L LSB Acceleration  Y
        imuBuf[11+18*i] = readMAX21105(0x2E); //aZ_H MSB Acceleration  Z
        imuBuf[12+18*i] = readMAX21105(0x2F); //aZ_L LSB Acceleration  Z
        imuBuf[13+18*i] = readMAX21105(0x30); //TEMP_H MSB Temperature
        imuBuf[14+18*i] = readMAX21105(0x31); //TEMP_L LSB Temperature
        time=t.read_us();
        imuBuf[15+18*i] = (char)(time>>16&0xFF); //TEMP_L LSB Temperature
        imuBuf[16+18*i] = (char)(time>>8&0xFF); //TEMP_L LSB Temperature
        imuBuf[17+18*i] = (char)(time&0xFF); //TEMP_L LSB Temperature
    }
    t.stop();
}

// Send all axis data to PC
void sendPCAll(char *imuBuf,short imuCnt){
    pc.printf("[IMU_READALL_ST]");
    // Variables for data from IMU
    char con; // IMU status
    short i;  // Data point measurement loop variable
    
    uint8_t wX_H, wX_L, wY_H, wY_L, wZ_H, wZ_L; // Angular speed MSB&LSB x,y,z
    uint8_t aX_H, aX_L, aY_H, aY_L, aZ_H, aZ_L; // Acceleration  MSB&LSB x,y,z
    uint8_t temp_H, temp_L;
    uint8_t time_H, time_M, time_L;
    uint16_t wx, wy, wz, ax, ay, az, temp; // Full angular speed & acceleration
    int time;
    
    // Wait for connection and return data
    for(i=0;i<imuCnt;i++) {
        con=imuBuf[0+18*i];
        wX_H = imuBuf[1+18*i]; // MSB Angular speed  X
        wX_L = imuBuf[2+18*i]; // LSB Angular speed  X
        wY_H = imuBuf[3+18*i]; // MSB Angular speed  Y
        wY_L = imuBuf[4+18*i]; // LSB Angular speed  Y
        wZ_H = imuBuf[5+18*i]; // MSB Angular speed  Z
        wZ_L = imuBuf[6+18*i]; // LSB Angular speed  Z
        
        aX_H = imuBuf[7+18*i]; // MSB Acceleration  X
        aX_L = imuBuf[8+18*i]; // LSB Acceleration  X
        aY_H = imuBuf[9+18*i]; // MSB Acceleration  Y
        aY_L = imuBuf[10+18*i]; // LSB Acceleration  Y
        aZ_H = imuBuf[11+18*i]; // MSB Acceleration  Z
        aZ_L = imuBuf[12+18*i]; // LSB Acceleration  Z
        
        temp_H = imuBuf[13+18*i]; // MSB Temperature
        temp_L = imuBuf[14+18*i]; // LSB Temperature
        
        time_H = imuBuf[15+18*i]; // MSB Time
        time_M = imuBuf[16+18*i]; // middle Time
        time_L = imuBuf[17+18*i]; // LSB Time

        // Stack MSB and LSB together and send out thru serialPC
        wx = (uint16_t)((uint16_t)wX_H<<8|(wX_L));
        wy = (uint16_t)((uint16_t)wY_H<<8|(wY_L));
        wz = (uint16_t)((uint16_t)wZ_H<<8|(wZ_L));
        ax = (uint16_t)((uint16_t)aX_H<<8|(aX_L));
        ay = (uint16_t)((uint16_t)aY_H<<8|(aY_L));
        az = (uint16_t)((uint16_t)aZ_H<<8|(aZ_L));
        temp = (uint16_t)((uint16_t)temp_H<<8|(temp_L));
        time = (int)((int)time_H<<16|(int)time_M<<8|(time_L));
        pc.printf("ST%01X%04X%04X%04X%04X%04X%04X%04X%06XED",
            con, wx, wy, wz, ax, ay, az,temp,time); 
    }
    pc.printf("[IMU_READALL_ED]");
}

void burstGMAX21105(){
    writeMAX21105(0x02, 0x24);  // SNS_CFG_2 0x22 - sns_gyr_ois_lpf=on, sns_odr=2000Hz
    writeMAX21105(0x05, 0x32);  // SNS_CFG_2 0x22 - sns_gyr_ois_lpf=on, sns_odr=2000Hz
    char con; // IMU status
    char wX_H, wX_L, wY_H, wY_L, wZ_H, wZ_L; // Angular speed MSB&LSB x,y,z
    char aX_H, aX_L, aY_H, aY_L, aZ_H, aZ_L; // Accel MSB&LSB x,y,z
    int time;
    t.start();
    t.reset();
    while(1){
        while ((con = readMAX21105(0x23))==0); // wait until DATA_READY
        time=t.read_us();
        wX_H = readMAX21105(0x24); // wX_H MSB Angular speed  X
        wX_L = readMAX21105(0x25); // wX_L LSB Angular speed  X
        wY_H = readMAX21105(0x26); // wY_H MSB Angular speed  Y
        wY_L = readMAX21105(0x27); // wY_L LSB Angular speed  Y
        wZ_H = readMAX21105(0x28); // wZ_H MSB Angular speed  Z
        wZ_L = readMAX21105(0x29); // wZ_L LSB Angular speed  Z
        aX_H = readMAX21105(0x2A); // aX_H MSB Acceleration  X
        aX_L = readMAX21105(0x2B); // aX_L LSB Acceleration  X
        aY_H = readMAX21105(0x2C); //aY_H MSB Acceleration  Y
        aY_L = readMAX21105(0x2D); //aY_L LSB Acceleration  Y
        aZ_H = readMAX21105(0x2E); //aZ_H MSB Acceleration  Z
        aZ_L = readMAX21105(0x2F); //aZ_L LSB Acceleration  Z
        pc.printf("ST%01X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%08XED\n",con,wX_H,wX_L,wY_H,wY_L,wZ_H,wZ_L,aX_H,aX_L,aY_H,aY_L,aZ_H,aZ_L,time);
    }
    t.stop();
}

void setMCP4921(int val){
    cs_MCP4921 = 0;         // Select the device by seting chip select low
    spi1.write(0x70|(0xF&(val>>8)));// Set MCP4921 value. 0x7000 prefix
    spi1.write(0xFF&val);   // Set MCP4921 value. 0x7000 prefix
    cs_MCP4921 = 1;         // Deselect the device
}

void startTSYS01st(){
    // Select the device by seting chip select low
    cs_TSYS01st = 0;
    spi1.write(0x1E); // Reset
    cs_TSYS01st=1;
    wait(0.1); //2.8 ms reload
    
    uint8_t kH, kL, kA[8];
    char i;
    
    kA[0]=0xAA;
    kA[1]=0xA8;
    kA[2]=0xA6;
    kA[3]=0xA4;
    kA[4]=0xA2;
    kA[5]=0xAC;
    kA[6]=0xAE;
    kA[7]=0xA0;
    pc.printf("[TEMPS_COEFF_ST]");
    for(i=0;i<8;i++){
        cs_TSYS01st = 0;
        spi1.write(kA[i]); // k0 read
        kH=spi1.write(0x00); // k0_MSB
        kL=spi1.write(0x00); // k0_LSB
        pc.printf("%02X%02X",kH,kL);
        cs_TSYS01st = 1;
    }
    pc.printf("[TEMPS_COEFF_ED]");
}

void readTSYS01st(){
    uint8_t t[3];
    cs_TSYS01st = 0;
    spi1.write(0x48); // k0 read
    wait(0.1);
    cs_TSYS01st = 1;
    
    cs_TSYS01st = 0;
    spi1.write(0x00); // k0 read
    t[0]=spi1.write(0x00); // k0 read
    t[1]=spi1.write(0x00); // k0 read
    t[2]=spi1.write(0x00); // k0 read
    cs_TSYS01st = 1;
    pc.printf("[TEMPS_VALUE_ST]");
    pc.printf("%02X%02X%02X",t[0],t[1],t[2]);
    pc.printf("[TEMPS_VALUE_ED]");
}

// Start connection
void initialization(){
    //pc.baud(921600);
    pc.baud(460800);
    
    startSPI(); // Start SPI connection 
    startMAX21105();  // Connect to MAX21105
}

int main(){
    // Variable for main function
    char buf[16];       // Buffer for the command from PC
    char imuBuf[28800]; // Buffer for IMU output
    short imuCnt=1600;  // # of Point read from imu
    int val;          // Value from command
    
    // Start system
    initialization();
    // Infinite loop: listen to serial command
    while(1) {
        if (pc.readable()) {
            //Command format: Start Mode Submode VALUe enD   S F F FFFF D
            pc.gets(buf, 16);
            //pc.printf("Get buf: %s\n",buf);
            if ((buf[0] == 'S')&&(buf[7] == 'D')) {
                //Mode switch
                switch(buf[1]) { 
                //read all axis mode
                case 'r': 
                    // Submode switch
                    switch(buf[2]) { 
                    case 'a':
                        readMAX21105All(imuBuf,imuCnt);
                        sendPCAll(imuBuf,imuCnt);
                        pc.printf("\n");
                        break;
                    case 'm':
                        readMAX21105All(imuBuf,imuCnt);
                        sendPCAll(imuBuf,imuCnt);
                        readTSYS01st();
                        pc.printf("\n");
                        break;
                    case 'b':
                        burstGMAX21105();
                        break;
                    default:
                        break;
                    }
                //stage temperature
                case 's': 
                    // Submode switch
                    switch(buf[2]) { 
                    case 's':
                        startTSYS01st();
                        pc.printf("\n");
                        break;
                    case 'r':
                        readTSYS01st();
                        pc.printf("\n");
                        break;
                    default:
                        break;
                    }
                    break;
                //set heater
                case 'h': 
                    val = getVal(buf);
                    if(val!=-1){
                        setMCP4921(val);
                    }                  
                    break;
                default:
                    break;
                }
            }
        }     
    }
    return 0;
}