ADC performance check

Dependencies:  

Fork of GR-PEACH_test_wo_rtos by Kenji Arai

Revision:
7:c87a84872d85
Parent:
6:849caec97744
--- a/main.cpp	Fri Jan 09 22:50:07 2015 +0000
+++ b/main.cpp	Sun Jan 11 09:48:17 2015 +0000
@@ -6,7 +6,7 @@
  *  http://www.page.sannet.ne.jp/kenjia/index.html
  *  http://mbed.org/users/kenjiArai/
  *      Created: November  29th, 2014
- *      Revised: January   10th, 2015
+ *      Revised: January   11th, 2015
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
@@ -17,15 +17,10 @@
 
 //  Include ---------------------------------------------------------------------------------------
 #include    "mbed.h"
-#include    "L3GD20.h"
-#include    "LIS3DH.h"
-#include    "TextLCD.h"
 
 //  Definition ------------------------------------------------------------------------------------
 #define USE_COM         // use Communication with PC(UART)
-#define USE_I2C_LCD
-#define USE_I2C_SENSOR
- 
+
 // Com
 #ifdef  USE_COM
 #define BAUD(x)             pcx.baud(x)
@@ -41,114 +36,462 @@
 #define READABLE(x)         {;}
 #endif
 
+// Use TL431ACZ-AP
+//      Akizuki NJM431 (equivalent)
+//          http://akizukidenshi.com/catalog/g/gI-00431/
+#define VREF                (2.478f)    // measured data (not Typ. data)
+
+#if defined(TARGET_RZ_A1H)
+//#define ADC_BUF_SIZE        (4096 * 40)
+#define ADC_BUF_SIZE        (1024)
+#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
+#define ADC_BUF_SIZE        (1024)
+#elif defined(TARGET_K64F)
+#define ADC_BUF_SIZE        (1024)
+#endif
+
+
 //  Object ----------------------------------------------------------------------------------------
-// LED's
-DigitalOut LEDs[4] = {
-    DigitalOut(LED1), DigitalOut(LED2), DigitalOut(LED3), DigitalOut(LED4)
-};
-// Swiches
-DigitalIn   USER_SWITCH[2] = {
-    #if defined(TARGET_RZ_A1H)
-    DigitalIn(P6_0),  DigitalIn(P6_1)
-    #elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)\
-     || defined(TARGET_NUCLEO_L152RE)
-    DigitalIn(PC_13),  DigitalIn(A0)
-    #elif defined(TARGET_LPC1768)
-    DigitalIn(A0),  DigitalIn(A1)
-    #elif defined(TARGET_K64F)
-    DigitalIn(PTA4),  DigitalIn(PTC6)
-    #endif
-};
 // com
 #ifdef USE_COM
 Serial      pcx(USBTX, USBRX);      // Communication with Host
 #endif
-I2C i2c(D14,D15);
-// Gyro
-L3GX_GYRO   gyro(i2c, L3GD20_V_CHIP_ADDR, L3GX_DR_95HZ, L3GX_BW_HI, L3GX_FS_250DPS);
-// Acc
-LIS3DH      acc(i2c, LIS3DH_G_CHIP_ADDR, LIS3DH_DR_NR_LP_50HZ, LIS3DH_FS_8G);
-#ifdef USE_I2C_LCD
-// LCD
-TextLCD_I2C_N lcd0(&i2c, 0x7c, TextLCD::LCD16x2);  // LCD(Akizuki AQM0802A)
-#endif
+// Analog
+AnalogIn    adc0(A0);   // Connect TL431ACZ-AP
+AnalogIn    adc1(A1);
+AnalogIn    adc2(A2);
+AnalogIn    adc3(A3);
+AnalogIn    adc4(A4);
+AnalogIn    adc5(A5);
+// timer
+Timer       timer;
 
 //  RAM -------------------------------------------------------------------------------------------
-float fa[3];    // Acc  0:X, 1:Y, 2:Z
-float fg[3];    // Gyro 0:X, 1:Y, 2:Z
+static char linebuf[64];
+
+typedef struct {
+    float     adc0;
+    float     adc1;
+    float     adc2;
+    float     adc3;
+    float     adc4;
+    float     adc5;
+    int       a0_time;
+    int       a1_time;
+    int       a2_time;
+    int       a3_time;
+    int       a4_time;
+    int       a5_time;
+    uint32_t  n;
+} ADC_DataTypeDef;
 
-uint8_t show_flag;
-uint32_t count;
+ADC_DataTypeDef data_buffer[ADC_BUF_SIZE];
+
+// avarage & max.min
+uint32_t d_max_min[2];
+
+double ave_adc0;
+double ave_adc1;
+double ave_adc2;
+double ave_adc3;
+double ave_adc4;
+double ave_adc5;
+float d_max_min0[2];
+float d_max_min1[2];
+float d_max_min2[2];
+float d_max_min3[2];
+float d_max_min4[2];
+float d_max_min5[2];
 
 //  ROM / Constant data ---------------------------------------------------------------------------
+#if defined(TARGET_RZ_A1H)
+static char *const mon_msg = "ADC checking program for GR-PEACH mbed, created on "__DATE__"";
+#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
+static char *const mon_msg = "ADC checking program for Nucleo mbed, created on "__DATE__"";
+#elif defined(TARGET_K64F)
+static char *const mon_msg = "ADC checking program for K64F mbed, created on "__DATE__"";
+#endif
 
 //  Function prototypes ---------------------------------------------------------------------------
 
 //  Function prototypes ---------------------------------------------------------------------------
+void msg_hlp (void);
+void reset_max_min(uint32_t *bf);
+void check_max_min(uint32_t dt, uint32_t *bf);
+void reset_f_max_min(void);
+void check_f_max_min(float dt, float *bf);
+void get_line (char *buff, int len);
+void blink(void const *n);
+void put_rn ( void );
+void put_r ( void );
+int xatoi (char **str, int32_t *res);
 
 //-------------------------------------------------------------------------------------------------
 //  Control Program
 //-------------------------------------------------------------------------------------------------
-void blink(void const *n) {
-    LEDs[(int)n] = !LEDs[(int)n];
-}
+int main(void)
+{
+    char *ptr;
+    float dt;
+    uint32_t i;
+    uint32_t t;
+
+    BAUD(9600);
+    put_rn();
+    put_rn();
+    PRINTF("%s [Help:'?' key]", mon_msg);
+    put_rn();
+    for (;;) {
+        put_r();
+        PUTC('>');
+        ptr = linebuf;
+        get_line(ptr, sizeof(linebuf));
+        switch (*ptr++) {
+                //---------------------------------------------------------------------------------------------
+                //  Save ADC data into RAM
+                //---------------------------------------------------------------------------------------------
+            case 's' :
+                for (i = 0; i < ADC_BUF_SIZE; i++) {
+                    timer.reset();
+                    timer.start();
+                    dt = adc0.read();
+                    t = timer.read_us();
+                    data_buffer[i].adc0 = dt;
+                    data_buffer[i].a0_time = t;
 
-// Read switch status
-int read_sw(uint8_t n){
-    if (USER_SWITCH[n] == 0){   return 1;
-    } else {                    return 0;}
-}
+                    timer.reset();
+                    timer.start();
+                    dt = adc1.read();
+                    t = timer.read_us();
+                    data_buffer[i].adc1 = dt;
+                    data_buffer[i].a1_time = t;
+
+                    timer.reset();
+                    timer.start();
+                    dt = adc2.read();
+                    t = timer.read_us();
+                    data_buffer[i].adc2 = dt;
+                    data_buffer[i].a2_time = t;
+
+                    timer.reset();
+                    timer.start();
+                    dt = adc3.read();
+                    t = timer.read_us();
+                    data_buffer[i].adc3 =  dt;
+                    data_buffer[i].a3_time = t;
+
+                    timer.reset();
+                    timer.start();
+                    dt =adc4.read();
+                    t = timer.read_us();
+                    data_buffer[i].adc4 =  dt;
+                    data_buffer[i].a4_time = t;
+
+                    timer.reset();
+                    dt = adc5.read();
+                    t = timer.read_us();
+                    data_buffer[i].adc5 =  dt;
+                    data_buffer[i].a5_time = t;
 
-// Update sensor data
-void update_angle(void){
-#ifdef USE_I2C_SENSOR
-    // read acceleration data from sensor
-    acc.read_data(fa);
-    // read gyroscope data from sensor
-    gyro.read_data(fg);
-#else
-    fa[0] = fa[1] = fa[2] = 1.11f;
-    fg[0] = fg[1] = fg[2] = 1.11f;
-#endif
+                    data_buffer[i].n = i + 1;
+                    if (i%100 == 0) {
+                        put_rn();
+                        PRINTF("%d", i);
+                        put_rn();
+                    } else {
+                        PUTC('.');
+                    }
+                    if ( READABLE() ) {
+                        put_rn();
+                        GETC();
+                        break;
+                    }
+                }
+                data_buffer[i + 1].n = 0;
+                put_rn();
+                PRINTF("Finished at %d", i);
+                put_rn();
+                break;
+                //---------------------------------------------------------------------------------------------
+                //  Display saved ADC data
+                //---------------------------------------------------------------------------------------------
+            case 'd' :
+                put_rn();
+                PRINTF("Show all saved data");
+                put_rn();
+                for (i = 0; (i < ADC_BUF_SIZE) && (data_buffer[i].n != 0) ; i++) {
+                    PRINTF("No.%5d, ", i);
+                    PRINTF("A0= %4.4f , A1= %4.4f , ", data_buffer[i].adc0, data_buffer[i].adc1);
+                    PRINTF("A2= %4.4f , A3= %4.4f , ", data_buffer[i].adc2, data_buffer[i].adc3);
+                    PRINTF("A4= %4.4f , A5= %4.4f , ", data_buffer[i].adc4, data_buffer[i].adc5);
+                    PRINTF("Time/0= %d /1= %d /2= %d /3= %d /4= %d /5= %d [uS]",
+                           data_buffer[i].a0_time, data_buffer[i].a1_time, data_buffer[i].a2_time,
+                           data_buffer[i].a3_time, data_buffer[i].a4_time, data_buffer[i].a5_time);
+                    put_rn();
+                    if ( READABLE() ) {
+                        GETC();
+                        break;
+                    }
+                }
+                break;
+                //---------------------------------------------------------------------------------------------
+                //  Check convertion time
+                //---------------------------------------------------------------------------------------------
+            case 't' :
+                uint32_t time_all = 0;
+
+                put_r();
+                reset_max_min(d_max_min);
+                for (i = 0; (i < ADC_BUF_SIZE) && (data_buffer[i].n != 0) ; i++) {
+                    time_all += (data_buffer[i].a0_time + data_buffer[i].a1_time +data_buffer[i].a2_time
+                                 + data_buffer[i].a3_time + data_buffer[i].a4_time + data_buffer[i].a5_time);
+                    check_max_min(data_buffer[i].a0_time, d_max_min);
+                    check_max_min(data_buffer[i].a1_time, d_max_min);
+                    check_max_min(data_buffer[i].a2_time, d_max_min);
+                    check_max_min(data_buffer[i].a3_time, d_max_min);
+                    check_max_min(data_buffer[i].a4_time, d_max_min);
+                    check_max_min(data_buffer[i].a5_time, d_max_min);
+                }
+                PRINTF("Conversion time/ave =  %f [uS], Number of sample %d, Max %d [uS], Min %d [uS]",
+                       (double)time_all / (i * 6), i, d_max_min[1], d_max_min[0]);
+                put_rn();
+                break;
+                //---------------------------------------------------------------------------------------------
+                //  Analysis saved data
+                //---------------------------------------------------------------------------------------------
+            case 'a' :
+                put_r();
+                reset_f_max_min();
+                for (i = 0; (i < ADC_BUF_SIZE) && (data_buffer[i].n != 0) ; i++) {
+                    ave_adc0 += data_buffer[i].adc0;
+                    ave_adc1 += data_buffer[i].adc1;
+                    ave_adc2 += data_buffer[i].adc2;
+                    ave_adc3 += data_buffer[i].adc3;
+                    ave_adc4 += data_buffer[i].adc4;
+                    ave_adc5 += data_buffer[i].adc5;
+                    check_f_max_min(data_buffer[i].adc0, d_max_min0);
+                    check_f_max_min(data_buffer[i].adc1, d_max_min1);
+                    check_f_max_min(data_buffer[i].adc2, d_max_min2);
+                    check_f_max_min(data_buffer[i].adc3, d_max_min3);
+                    check_f_max_min(data_buffer[i].adc4, d_max_min4);
+                    check_f_max_min(data_buffer[i].adc5, d_max_min5);
+                }
+                PRINTF("Number of sample %d", i);
+                put_rn();                
+                PRINTF("ADC0/ave =  %f , Max %f , Min %f , Dif %f",
+                 ave_adc0 / i, d_max_min0[1], d_max_min0[0], d_max_min0[1] - d_max_min0[0]);
+                put_rn(); 
+                PRINTF("ADC1/ave =  %f , Max %f , Min %f , Dif %f",
+                 ave_adc1 / i, d_max_min1[1], d_max_min1[0], d_max_min1[1] - d_max_min1[0]);
+                put_rn(); 
+                PRINTF("ADC2/ave =  %f , Max %f , Min %f , Dif %f",
+                 ave_adc2 / i, d_max_min2[1], d_max_min2[0], d_max_min2[1] - d_max_min2[0]);
+                put_rn(); 
+                PRINTF("ADC3/ave =  %f , Max %f , Min %f , Dif %f",
+                 ave_adc3 / i, d_max_min3[1], d_max_min3[0], d_max_min3[1] - d_max_min3[0]);
+                put_rn(); 
+                PRINTF("ADC4/ave =  %f , Max %f , Min %f , Dif %f",
+                 ave_adc4 / i, d_max_min4[1], d_max_min4[0], d_max_min4[1] - d_max_min4[0]);
+                put_rn(); 
+                PRINTF("ADC5/ave =  %f , Max %f , Min %f , Dif %f",
+                 ave_adc5 / i, d_max_min5[1], d_max_min5[0], d_max_min5[1] - d_max_min5[0]);
+                put_rn();
+                break;
+                //---------------------------------------------------------------------------------------------
+                //  Buffer information
+                //---------------------------------------------------------------------------------------------
+            case 'b' :
+                put_r();
+                PRINTF("Buffer information", i);
+                put_rn();                
+                PRINTF("Start address: 0x%08x", &data_buffer[0]);
+                put_rn(); 
+                PRINTF("End address:   0x%08x", &data_buffer[ADC_BUF_SIZE - 1]);
+                put_rn();
+                PRINTF("Size of Buf:   %d (0x%x)", sizeof(data_buffer), sizeof(data_buffer));
+                put_rn();
+                break;
+                //---------------------------------------------------------------------------------------------
+                //  Check Vcc
+                //---------------------------------------------------------------------------------------------
+            case 'v' :
+                put_r();
+                PRINTF("This is special function only if A0 conneceted 2.5V Shunt reg. e.g. TL431, NJM431.");
+                put_rn();                
+                PRINTF("Please make sure #define VREF as your condition.");
+                put_rn(); 
+                while(true){
+                    PRINTF("Vcc= %4.4f [v]", VREF / adc0.read());
+                    put_rn();
+                    if ( READABLE() ) {
+                        GETC();
+                        break;
+                    }
+                    wait(0.5);
+                }
+                break;
+                //---------------------------------------------------------------------------------------------
+                //  help
+                //---------------------------------------------------------------------------------------------
+            case '?' :
+                put_r();
+                msg_hlp();
+                break;
+        }
+    }
 }
 
-// Update sensor data
-void display(void){
-#ifdef USE_I2C_LCD
-    lcd0.locate(0, 0);    // 1st line top
-    lcd0.printf(" G=%4.1f ", sqrt(fa[0]*fa[0] + fa[1]*fa[1] + fa[2]*fa[2]));
-    lcd0.locate(0, 1);    // 2nd line top
-    lcd0.printf("%8d",count++);
-#endif
+//  Help Massage
+void msg_hlp (void)
+{
+    PRINTF(mon_msg);
+    put_rn();
+    PRINTF("s - Save ADC data into RAM");
+    put_rn();
+    PRINTF("d - Display saved ADC data");
+    put_rn();
+    PRINTF("t - Check convertion time");
+    put_rn();
+    PRINTF("a - Analysis saved data");
+    put_rn();
+    PRINTF("b - Buffer information");
+    put_rn();
+    PRINTF("v - Check Vcc");
+    put_rn();
+}
+
+void reset_max_min(uint32_t *bf)
+{
+    *(bf + 1) = 0;
+    *bf = 0xffffffff;
 }
 
-void send_pc(void){
-    PRINTF("G:%+6.1f,%+6.1f,%+6.1f,  ", fg[0], fg[1], fg[2]);
-    PRINTF("A:%+6.1f,%+6.1f,%+6.1f \r\n", fa[0], fa[1], fa[2]);
+void check_max_min(uint32_t dt, uint32_t *bf)
+{
+    if (dt > *(bf + 1)){
+        *(bf + 1) = dt;
+    } else if (dt < *bf){
+        *bf = dt;
+    }
+}
+
+void reset_f_max_min(void)
+{
+    d_max_min0[0] = 1.0f;
+    d_max_min0[1] = 0.0f;
+    d_max_min1[0] = 1.0f;
+    d_max_min1[1] = 0.0f;
+    d_max_min2[0] = 1.0f;
+    d_max_min2[1] = 0.0f;
+    d_max_min3[0] = 1.0f;
+    d_max_min3[1] = 0.0f;
+    d_max_min4[0] = 1.0f;
+    d_max_min4[1] = 0.0f;
+    d_max_min5[0] = 1.0f;
+    d_max_min5[1] = 0.0f;
+}
+
+void check_f_max_min(float dt, float *bf)
+{
+    if (dt > *(bf + 1)){
+        *(bf + 1) = dt;
+    } else if (dt < *bf){
+        *bf = dt;
+    }
 }
 
-int main(void) {
-    // I2C LCD
-#ifdef USE_I2C_LCD
-    lcd0.locate(0, 0);    // 1st line top
-    lcd0.printf("I2C test");
-    lcd0.locate(0, 1);    // 2nd line top
-    lcd0.puts(" JH1PJL ");
-    lcd0.setContrast(0x14);
-#endif
-    count = 0; 
-    while (true) {
-        update_angle();
-        display();
-        send_pc();
-        //wait(0.2);
-        blink((void *)0);
-        //wait(0.2);
-        blink((void *)1);
-        //wait(0.2);
-        blink((void *)2);
-        //wait(0.2);
-        blink((void *)3);
-        //wait(0.2);
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//  Get key input data
+void get_line (char *buff, int len)
+{
+    char c;
+    int idx = 0;
+
+    for (;;) {
+        c = GETC();
+        //    Added by Kenji Arai / JH1PJL   May 9th, 2010
+        if (c == '\r') {
+            buff[idx++] = c;
+            break;
+        }
+        if ((c == '\b') && idx) {
+            idx--;
+            PUTC(c);
+            PUTC(' ');
+            PUTC(c);
+        }
+        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
+            buff[idx++] = c;
+            PUTC(c);
+        }
     }
+    buff[idx] = 0;
+    PUTC('\n');
 }
+
+//  Put \r\n
+void put_rn ( void )
+{
+    PUTC('\r');
+    PUTC('\n');
+}
+
+//  Put \r
+void put_r ( void )
+{
+    PUTC('\r');
+}
+
+int xatoi (char **str, int32_t *res)
+{
+    unsigned long val;
+    unsigned char c, radix, s = 0;
+
+    while ((c = **str) == ' ') (*str)++;
+    if (c == '-') {
+        s = 1;
+        c = *(++(*str));
+    }
+    if (c == '0') {
+        c = *(++(*str));
+        if (c <= ' ') {
+            *res = 0;
+            return 1;
+        }
+        if (c == 'x') {
+            radix = 16;
+            c = *(++(*str));
+        } else {
+            if (c == 'b') {
+                radix = 2;
+                c = *(++(*str));
+            } else {
+                if ((c >= '0')&&(c <= '9')) {
+                    radix = 8;
+                }   else {
+                    return 0;
+                }
+            }
+        }
+    } else {
+        if ((c < '1')||(c > '9')) {
+            return 0;
+        }
+        radix = 10;
+    }
+    val = 0;
+    while (c > ' ') {
+        if (c >= 'a') c -= 0x20;
+        c -= '0';
+        if (c >= 17) {
+            c -= 7;
+            if (c <= 9) return 0;
+        }
+        if (c >= radix) return 0;
+        val = val * radix + c;
+        c = *(++(*str));
+    }
+    if (s) val = -val;
+    *res = val;
+    return 1;
+}