BMS_T2

Dependencies:   INA226

Revision:
0:f06ed53310a3
Child:
2:3bbbe439ec11
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Feb 07 08:26:04 2018 +0000
@@ -0,0 +1,678 @@
+
+#include "mbed.h"
+#include "bms.h"
+#include "LTC681x.h"
+#include "LTC6811.h"
+
+#define UI_BUFFER_SIZE 64
+#define SERIAL_TERMINATOR '\n'
+
+#define ENABLED 1
+#define DISABLED 0
+
+#define DATALOG_ENABLED 1
+#define DATALOG_DISABLED 0
+DigitalOut led1(LED1);
+Serial pc(USBTX, USBRX);
+
+void run_command(uint32_t cmd);
+void measurement_loop(uint8_t datalog_en);
+void print_menu();
+void print_cells(uint8_t datalog_en);
+void print_open();
+void print_aux(uint8_t datalog_en);
+void print_stat();
+void print_config();
+void print_rxconfig();
+void print_pec(void);
+void serial_print_hex(uint8_t data);
+void check_error(int error);
+//char get_char();
+//void read_config_data(uint8_t cfg_data[][6], uint8_t nIC);
+
+/**********************************************************
+  Setup Variables
+  The following variables can be modified to
+  configure the software.
+
+***********************************************************/
+const uint8_t TOTAL_IC = 1;//!<number of ICs in the daisy chain
+char ui_buffer[UI_BUFFER_SIZE];
+
+
+//ADC Command Configurations
+//const uint8_t ADC_OPT = ADC_OPT_DISABLED; // See LTC6811_daisy.h for Options
+const uint8_t ADC_CONVERSION_MODE = MD_7KHZ_3KHZ;//MD_7KHZ_3KHZ; //MD_26HZ_2KHZ;//MD_7KHZ_3KHZ; // See LTC6811_daisy.h for Options
+const uint8_t ADC_DCP = DCP_DISABLED; // See LTC6811_daisy.h for Options
+const uint8_t CELL_CH_TO_CONVERT = CELL_CH_ALL; // See LTC6811_daisy.h for Options
+const uint8_t AUX_CH_TO_CONVERT = AUX_CH_ALL; // See LTC6811_daisy.h for Options
+const uint8_t STAT_CH_TO_CONVERT = STAT_CH_ALL; // See LTC6811_daisy.h for Options
+
+const uint16_t MEASUREMENT_LOOP_TIME = 500;//milliseconds(mS)
+
+//Under Voltage and Over Voltage Thresholds
+const uint16_t OV_THRESHOLD = 41000; // Over voltage threshold ADC Code. LSB = 0.0001
+const uint16_t UV_THRESHOLD = 30000; // Under voltage threshold ADC Code. LSB = 0.0001
+
+//Loop Measurement Setup These Variables are ENABLED or DISABLED Remember ALL CAPS
+const uint8_t WRITE_CONFIG = DISABLED; // This is ENABLED or DISABLED
+const uint8_t READ_CONFIG = DISABLED; // This is ENABLED or DISABLED
+const uint8_t MEASURE_CELL = ENABLED; // This is ENABLED or DISABLED
+const uint8_t MEASURE_AUX = DISABLED; // This is ENABLED or DISABLED
+const uint8_t MEASURE_STAT = DISABLED; //This is ENABLED or DISABLED
+const uint8_t PRINT_PEC = DISABLED; //This is ENABLED or DISABLED
+
+
+// Read data from the serial interface into the ui_buffer buffer
+uint8_t read_data();
+
+// Read a float value from the serial interface
+float read_float();
+
+// Read an integer from the serial interface.
+// The routine can recognize Hex, Decimal, Octal, or Binary
+// Example:
+// Hex:     0x11 (0x prefix)
+// Decimal: 17
+// Octal:   O21 (leading letter O prefix)
+// Binary:  B10001 (leading letter B prefix)
+int32_t read_int();
+
+// Read a string from the serial interface.  Returns a pointer to the ui_buffer.
+char *read_string();
+
+// Read a character from the serial interface
+int8_t read_char();
+
+/************************************
+  END SETUP
+*************************************/
+
+/******************************************************
+ *** Global Battery Variables received from 681x commands
+ These variables store the results from the LTC6811
+ register reads and the array lengths must be based
+ on the number of ICs on the stack
+ ******************************************************/
+
+cell_asic bms_ic[TOTAL_IC];
+
+/*!*********************************************************************
+  \brief main loop
+***********************************************************************/
+int main(void)
+{
+    uint32_t user_command;
+    
+    pc.baud(115200);
+    spi_enable();
+    LTC681x_init_cfg(TOTAL_IC, bms_ic);
+    LTC6811_reset_crc_count(TOTAL_IC,bms_ic);
+    LTC6811_init_reg_limits(TOTAL_IC,bms_ic);
+    print_menu();
+
+    while(1) {
+        //pc.printf("check 00\n");
+        //while(!pc.readable()) {
+        wait(0.3);
+        //    pc.printf("check 001\n");
+        //}         // Check for user input
+        //pc.printf("check 01\n");
+        user_command = read_int();      // Read the user commandi
+        pc.printf("command -> %d \n", user_command);
+        run_command(user_command);
+    }
+}
+
+/*!*****************************************
+  \brief executes the user command
+*******************************************/
+
+void run_command(uint32_t cmd)
+{
+    int8_t error = 0;
+    uint32_t conv_time = 0;
+//    uint32_t user_command;
+    int8_t readIC=0;
+    char input = 0;
+    switch (cmd) {
+
+        case 1: // Write Configuration Register
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_wrcfg(TOTAL_IC,bms_ic);
+            print_config();
+            break;
+
+        case 2: // Read Configuration Register
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_rdcfg(TOTAL_IC,bms_ic);
+            check_error(error);
+            print_rxconfig();
+            break;
+
+        case 3: // Start Cell ADC Measurement
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_adcv(ADC_CONVERSION_MODE,ADC_DCP,CELL_CH_TO_CONVERT);
+            conv_time = LTC6811_pollAdc();
+            pc.printf("cell conversion completed in:");
+            pc.printf("%.1f",((float)conv_time/1000));
+            pc.printf("mS\n");
+            break;
+
+        case 4: // Read Cell Voltage Registers
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_rdcv(0, TOTAL_IC,bms_ic); // Set to read back all cell voltage registers
+            check_error(error);
+            print_cells(DATALOG_DISABLED);
+            break;
+
+        case 5: // Start GPIO ADC Measurement
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_adax(ADC_CONVERSION_MODE , AUX_CH_TO_CONVERT);
+            LTC6811_pollAdc();
+            pc.printf("aux conversion completed\n");
+            pc.printf("\n");
+            break;
+
+        case 6: // Read AUX Voltage Registers
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_rdaux(0,TOTAL_IC,bms_ic); // Set to read back all aux registers
+            check_error(error);
+            print_aux(DATALOG_DISABLED);
+            break;
+
+        case 7: // Start Status ADC Measurement
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_adstat(ADC_CONVERSION_MODE, STAT_CH_TO_CONVERT);
+            LTC6811_pollAdc();
+            pc.printf("stat conversion completed\n");
+            pc.printf("\n");
+            break;
+
+        case 8: // Read Status registers
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_rdstat(0,TOTAL_IC,bms_ic); // Set to read back all aux registers
+            check_error(error);
+            print_stat();
+            break;
+
+        case 9: // Loop Measurements
+            pc.printf("transmit 'm' to quit\n");
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_wrcfg(TOTAL_IC,bms_ic);
+            while (input != 'm') {
+                //if (pc.readable()) {
+                    input = read_char();
+                //}
+
+                measurement_loop(DATALOG_DISABLED);
+
+                wait_ms(MEASUREMENT_LOOP_TIME);
+            }
+            //print_menu();
+            break;
+
+        case 10: // Run open wire self test
+            print_pec();
+
+            break;
+
+        case 11: // Read in raw configuration data
+            LTC6811_reset_crc_count(TOTAL_IC,bms_ic);
+            break;
+
+        case 12:  // Run the ADC/Memory Self Test
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_run_cell_adc_st(CELL,ADC_CONVERSION_MODE,bms_ic);
+            pc.printf("%d", error);
+            pc.printf(" : errors detected in Digital Filter and CELL Memory\n");
+
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_run_cell_adc_st(AUX,ADC_CONVERSION_MODE, bms_ic);
+            pc.printf("%d",error);
+            pc.printf(" : errors detected in Digital Filter and AUX Memory\n");
+
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_run_cell_adc_st(STAT,ADC_CONVERSION_MODE, bms_ic);
+            pc.printf("%d",error);
+            pc.printf(" : errors detected in Digital Filter and STAT Memory\n");
+            print_menu();
+            break;
+
+        case 13: // Enable a discharge transistor
+            pc.printf("Please enter the Spin number\n");
+            readIC = (int8_t)read_int();
+            LTC6811_set_discharge(readIC,TOTAL_IC,bms_ic);
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_wrcfg(TOTAL_IC,bms_ic);
+            print_config();
+            break;
+
+        case 14: // Clear all discharge transistors
+            clear_discharge(TOTAL_IC,bms_ic);
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_wrcfg(TOTAL_IC,bms_ic);
+            print_config();
+            break;
+
+        case 15: // Clear all ADC measurement registers
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_clrcell();
+            LTC6811_clraux();
+            LTC6811_clrstat();
+            pc.printf("All Registers Cleared\n");
+            break;
+
+        case 16: // Run the Mux Decoder Self Test
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_diagn();
+            wait_ms(5);
+            error = LTC6811_rdstat(0,TOTAL_IC,bms_ic); // Set to read back all aux registers
+            check_error(error);
+            error = 0;
+            for (int ic = 0;
+                    ic<TOTAL_IC;
+                    ic++) {
+                if (bms_ic[ic].stat.mux_fail[0] != 0) error++;
+            }
+            if (error==0) pc.printf("Mux Test: PASS\n");
+            else pc.printf("Mux Test: FAIL\n");
+
+            break;
+
+        case 17: // Run ADC Overlap self test
+            wakeup_sleep(TOTAL_IC);
+            error = (int8_t)LTC6811_run_adc_overlap(TOTAL_IC,bms_ic);
+            if (error==0) pc.printf("Overlap Test: PASS\n");
+            else pc.printf("Overlap Test: FAIL\n");
+            break;
+
+        case 18: // Run ADC Redundancy self test
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_run_adc_redundancy_st(ADC_CONVERSION_MODE,AUX,TOTAL_IC, bms_ic);
+            pc.printf("%d",error);
+            pc.printf(" : errors detected in AUX Measurement\n");
+
+            wakeup_sleep(TOTAL_IC);
+            error = LTC6811_run_adc_redundancy_st(ADC_CONVERSION_MODE,STAT,TOTAL_IC, bms_ic);
+            pc.printf("%d",error);
+            pc.printf(" : errors detected in STAT Measurement\n");
+            break;
+
+        case 19:
+            LTC6811_run_openwire(TOTAL_IC, bms_ic);
+            print_open();
+            break;
+
+        case 20: //Datalog print option Loop Measurements
+            pc.printf("transmit 'm' to quit\n");
+            wakeup_sleep(TOTAL_IC);
+            LTC6811_wrcfg(TOTAL_IC,bms_ic);
+            while (input != 'm') {
+                //if (pc.readable()) {
+                    input = read_char();
+                //}
+
+                measurement_loop(DATALOG_ENABLED);
+
+                wait_ms(MEASUREMENT_LOOP_TIME);
+            }
+            print_menu();
+            break;
+
+        case 'm': //prints menu
+            print_menu();
+            break;
+
+        default:
+            pc.printf("Incorrect Option\n");
+            break;
+    }
+}
+
+void measurement_loop(uint8_t datalog_en)
+{
+    int8_t error = 0;
+    if (WRITE_CONFIG == ENABLED) {
+        wakeup_sleep(TOTAL_IC);
+        LTC6811_wrcfg(TOTAL_IC,bms_ic);
+        print_config();
+    }
+
+    if (READ_CONFIG == ENABLED) {
+        wakeup_sleep(TOTAL_IC);
+        error = LTC6811_rdcfg(TOTAL_IC,bms_ic);
+        check_error(error);
+        print_rxconfig();
+    }
+
+    if (MEASURE_CELL == ENABLED) {
+        wakeup_idle(TOTAL_IC);
+        LTC6811_adcv(ADC_CONVERSION_MODE,ADC_DCP,CELL_CH_TO_CONVERT);
+        LTC6811_pollAdc();
+        wakeup_idle(TOTAL_IC);
+        error = LTC6811_rdcv(0, TOTAL_IC,bms_ic);
+        check_error(error);
+        print_cells(datalog_en);
+
+    }
+
+    if (MEASURE_AUX == ENABLED) {
+        wakeup_idle(TOTAL_IC);
+        LTC6811_adax(ADC_CONVERSION_MODE , AUX_CH_ALL);
+        LTC6811_pollAdc();
+        wakeup_idle(TOTAL_IC);
+        error = LTC6811_rdaux(0,TOTAL_IC,bms_ic); // Set to read back all aux registers
+        check_error(error);
+        print_aux(datalog_en);
+    }
+
+    if (MEASURE_STAT == ENABLED) {
+        wakeup_idle(TOTAL_IC);
+        LTC6811_adstat(ADC_CONVERSION_MODE, STAT_CH_ALL);
+        LTC6811_pollAdc();
+        wakeup_idle(TOTAL_IC);
+        error = LTC6811_rdstat(0,TOTAL_IC,bms_ic); // Set to read back all aux registers
+        check_error(error);
+        print_stat();
+    }
+
+    if (PRINT_PEC == ENABLED) {
+        print_pec();
+    }
+
+}
+
+
+/*!*********************************
+  \brief Prints the main menu
+***********************************/
+void print_menu()
+{
+    pc.printf("Please enter LTC6811 Command\n");
+    pc.printf("Write Configuration: 1            | Reset PEC Counter: 11\n");
+    pc.printf("Read Configuration: 2             | Run ADC Self Test: 12\n");
+    pc.printf("Start Cell Voltage Conversion: 3  | Set Discharge: 13\n");
+    pc.printf("Read Cell Voltages: 4             | Clear Discharge: 14\n");
+    pc.printf("Start Aux Voltage Conversion: 5   | Clear Registers: 15\n");
+    pc.printf("Read Aux Voltages: 6              | Run Mux Self Test: 16\n");
+    pc.printf("Start Stat Voltage Conversion: 7  | Run ADC overlap Test: 17\n");
+    pc.printf("Read Stat Voltages: 8             | Run Digital Redundancy Test: 18\n");
+    pc.printf("loop Measurements: 9              | Run Open Wire Test: 19\n");
+    pc.printf("Read PEC Errors: 10               |  Loop measurements with datalog output: 20\n");
+    pc.printf("\n");
+    pc.printf("Please enter command:\n");
+    pc.printf("\n");
+}
+
+/*!************************************************************
+  \brief Prints cell voltage codes to the serial port
+ *************************************************************/
+void print_cells(uint8_t datalog_en)
+{
+    for (int current_ic = 0 ; current_ic < TOTAL_IC; current_ic++) {
+
+        if (datalog_en == 0) {
+            pc.printf("IC%d, ", current_ic+1);
+            for (int i=0; i<bms_ic[0].ic_reg.cell_channels; i++) {
+                pc.printf("C%d:", i+1);
+                pc.printf("%.4f, ", bms_ic[current_ic].cells.c_codes[i]*0.0001);
+            }
+            pc.printf("\n");
+        } else {
+            pc.printf("Cells, ");
+            for (int i=0; i<bms_ic[0].ic_reg.cell_channels; i++) {
+                pc.printf("%.4f, ",bms_ic[current_ic].cells.c_codes[i]*0.0001);
+            }
+        }
+
+    }
+    pc.printf("\n");
+}
+
+/*!****************************************************************************
+  \brief Prints Open wire test results to the serial port
+ *****************************************************************************/
+void print_open()
+{
+    for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++) {
+        if (bms_ic[current_ic].system_open_wire == 0) {
+            pc.printf("No Opens Detected on IC%d\n", current_ic+1);
+        } else {
+            for (int cell=0; cell<bms_ic[0].ic_reg.cell_channels+1; cell++) {
+                if ((bms_ic[current_ic].system_open_wire &(1<<cell))>0) {
+                    pc.printf("There is an open wire on IC%d Channel: %d\n", current_ic + 1, cell);
+                }
+            }
+        }
+    }
+}
+
+/*!****************************************************************************
+  \brief Prints GPIO voltage codes and Vref2 voltage code onto the serial port
+ *****************************************************************************/
+void print_aux(uint8_t datalog_en)
+{
+
+    for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++) {
+        if (datalog_en == 0) {
+            pc.printf(" IC%d", current_ic+1);
+            for (int i=0; i < 5; i++) {
+                pc.printf(" GPIO-%d:%.4f,", i+1, bms_ic[current_ic].aux.a_codes[i]*0.0001);
+            }
+            pc.printf("Vref2:%.4f\n", bms_ic[current_ic].aux.a_codes[5]*0.0001);
+        } else {
+            pc.printf("AUX, ");
+            for (int i=0; i < 6; i++) {
+                pc.printf("%.4f,", bms_ic[current_ic].aux.a_codes[i]*0.0001);
+            }
+        }
+    }
+    pc.printf("\n");
+}
+
+/*!****************************************************************************
+  \brief Prints Status voltage codes and Vref2 voltage code onto the serial port
+ *****************************************************************************/
+void print_stat()
+{
+
+    for (int current_ic =0 ; current_ic < TOTAL_IC; current_ic++) {
+        pc.printf("IC%d", current_ic+1);
+        pc.printf(" SOC:%.4f,", bms_ic[current_ic].stat.stat_codes[0]*0.0001*20);
+        pc.printf(" Itemp:%.4f,", bms_ic[current_ic].stat.stat_codes[1]*0.0001);
+        pc.printf(" VregA:%.4f,", bms_ic[current_ic].stat.stat_codes[2]*0.0001);
+        pc.printf(" VregD:%.4f\n", bms_ic[current_ic].stat.stat_codes[3]*0.0001);
+    }
+
+    pc.printf("\n");
+}
+
+/*!******************************************************************************
+ \brief Prints the configuration data that is going to be written to the LTC6811
+ to the serial port.
+ ********************************************************************************/
+void print_config()
+{
+    int cfg_pec;
+
+    pc.printf("Written Configuration: \n");
+    for (int current_ic = 0; current_ic<TOTAL_IC; current_ic++) {
+        pc.printf(" IC ");
+        pc.printf("%d", current_ic+1);
+        pc.printf(": ");
+        pc.printf("0x");
+        serial_print_hex(bms_ic[current_ic].config.tx_data[0]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.tx_data[1]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.tx_data[2]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.tx_data[3]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.tx_data[4]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.tx_data[5]);
+        pc.printf(", Calculated PEC: 0x");
+        cfg_pec = pec15_calc(6,&bms_ic[current_ic].config.tx_data[0]);
+        serial_print_hex((uint8_t)(cfg_pec>>8));
+        pc.printf(", 0x");
+        serial_print_hex((uint8_t)(cfg_pec));
+        pc.printf("\n");
+    }
+    pc.printf("\n");
+}
+
+/*!*****************************************************************
+ \brief Prints the configuration data that was read back from the
+ LTC6811 to the serial port.
+ *******************************************************************/
+void print_rxconfig()
+{
+    pc.printf("Received Configuration ");
+    for (int current_ic=0; current_ic<TOTAL_IC; current_ic++) {
+        pc.printf(" IC ");
+        pc.printf("%d", current_ic+1);
+        pc.printf(": 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[0]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[1]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[2]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[3]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[4]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[5]);
+        pc.printf(", Received PEC: 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[6]);
+        pc.printf(", 0x");
+        serial_print_hex(bms_ic[current_ic].config.rx_data[7]);
+        pc.printf("\n");
+    }
+    pc.printf("\n");
+}
+
+void print_pec()
+{
+    for (int current_ic=0; current_ic<TOTAL_IC; current_ic++) {
+        pc.printf("\n%d", bms_ic[current_ic].crc_count.pec_count);
+        pc.printf(" : PEC Errors Detected on IC");
+        pc.printf("%d\n", current_ic+1);
+    }
+}
+
+
+void serial_print_hex(uint8_t data)
+{
+    if (data < 16) {
+        pc.printf("0x0%X", data);
+    } else
+        pc.printf("0x%X", data);
+}
+
+//Function to check error flag and print PEC error message
+void check_error(int error)
+{
+    if (error == -1) {
+        pc.printf("A PEC error was detected in the received data");
+    }
+}
+
+
+// hex conversion constants
+char hex_digits[16]= {
+    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+// global variables
+
+char hex_to_byte_buffer[5]= {
+    '0', 'x', '0', '0', '\0'
+};               // buffer for ASCII hex to byte conversion
+char byte_to_hex_buffer[3]= {
+    '\0','\0','\0'
+};
+
+// Read data from the serial interface into the ui_buffer
+uint8_t read_data()
+{
+    uint8_t index = 0; //index to hold current location in ui_buffer
+    int c; // single character used to store incoming keystrokes
+    //pc.printf("check 1\n");
+    while (index < UI_BUFFER_SIZE-1) {
+        //pc.printf("check 2\n");
+        c = pc.getc(); //read one character
+        //return c;
+        //pc.printf("check 3\n");
+        
+        if (((char) c == '\r') || ((char) c == '\n')) break; // if carriage return or linefeed, stop and return data
+        if ( ((char) c == '\x7F') || ((char) c == '\x08') ) { // remove previous character (decrement index) if Backspace/Delete key pressed      index--;
+            if (index > 0) index--;
+        } else if (c >= 0) {
+            ui_buffer[index++]=(char) c; // put character into ui_buffer
+        }
+        //pc.printf("check 4\n");
+        
+    }
+    ui_buffer[index]='\0';  // terminate string with NULL
+
+    if ((char) c == '\r') {  // if the "last" character was a carriage return, also clear linefeed if it is next character
+        wait_ms(1);
+        //pc.printf("check 5\n");
+        
+        if (pc.readable()==1) {
+            //pc.printf("check 6\n");
+            pc.getc(); // if linefeed appears, read it and throw it away
+        }
+        //pc.printf("check 7\n");
+        
+    }
+    //pc.printf("check 8\n");
+        
+    return index; // return number of characters, not including null terminator
+}
+
+// Read a float value from the serial interface
+float read_float()
+{
+    float data;
+    read_data();
+    data = atof(ui_buffer);
+    return(data);
+}
+
+// Read an integer from the serial interface.
+// The routine can recognize Hex, Decimal, Octal, or Binary
+// Example:
+// Hex:     0x11 (0x prefix)
+// Decimal: 17
+// Octal:   021 (leading zero prefix)
+// Binary:  B10001 (leading B prefix)
+int32_t read_int()
+{
+    int32_t data;
+    read_data();
+    if (ui_buffer[0] == 'm')
+        return('m');
+    if ((ui_buffer[0] == 'B') || (ui_buffer[0] == 'b')) {
+        data = strtol(ui_buffer+1, NULL, 2);
+    } else
+        data = strtol(ui_buffer, NULL, 0);
+    return(data);
+}
+
+// Read a string from the serial interface.  Returns a pointer to the ui_buffer.
+char *read_string()
+{
+    read_data();
+    return(ui_buffer);
+}
+
+// Read a character from the serial interface
+int8_t read_char()
+{
+    read_data();
+    return(ui_buffer[0]);
+}