MBED slow serial communication

Discussion in 'Embedded Systems and Microcontrollers' started by Dritech, Mar 21, 2016.

  1. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Hi all,

    I was using the code below to display four analog inputs on the computer through serial communication.The MCU that I am using is the LPC1768.
    From the plots I noticed that the MBED code is slow since I was getting a very low quality graph.
    After I commented the serial command line pc.printf("%f,%f,%f,%f,%f\n", ADC1_voltage, ADC2_voltage, ADC3_voltage, ADC4_voltage); I noticed that the code functioned correctly.
    Can someone please guide me on what I am doing wrong?

    Code (C):
    1. #include "mbed.h"
    2.  
    3. // Initialize a pins to perform analogue input fucntions
    4. AnalogIn  ain1(p15);
    5. AnalogIn  ain2(p16);
    6. AnalogIn  ain3(p17);
    7. AnalogIn  ain4(p19);
    8.  
    9. // USB serial (TX, RX)
    10. Serial pc(USBTX, USBRX);
    11.  
    12. int main(void)
    13. {
    14.     // Declaring variables to be used for the ADC voltages
    15.     float ADC1_voltage;
    16.     float ADC2_voltage;
    17.     float ADC3_voltage;
    18.     float ADC4_voltage;
    19.  
    20.     while (1)
    21.     {
    22.     ADC1_voltage = ain1*3.3;
    23.     ADC2_voltage = ain2*3.3;
    24.     ADC3_voltage = ain3*3.3;
    25.     ADC4_voltage = ain4*3.3;
    26.  
    27.     // Send the five ADC values to serial port
    28.     pc.printf("%f,%f,%f,%f\n", ADC1_voltage, ADC2_voltage, ADC3_voltage, ADC4_voltage);
    29.   }
    30. }
    Moderators note: used code tags for C
     
    Last edited by a moderator: Mar 26, 2016
  2. MrChips

    Moderator

    Oct 2, 2009
    12,441
    3,361
    Stop using floating point and you will regain a lot of speed and memory space.
     
    JWHassler likes this.
  3. jjw

    Member

    Dec 24, 2013
    173
    31
    How fast it should be?
    The default serial speed is 9600bd, so printing about 4*8 characters takes ~ 4ms + the time used by the printf function.
    I think you can use faster serial speed?

    Btw. in the printf function there are five %f parameters, but only four variables to be printed.
     
  4. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Thanks for the reply. Since the ADC result is a floating value, what can I use instead of a floating data type?
     
  5. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Hi, I need to display a four 1kHz signals at reasonable quality. How can I determine the baud rate required?

    Sorry that was a typo.
     
    Last edited: Mar 22, 2016
  6. jjw

    Member

    Dec 24, 2013
    173
    31
    Mbed supports at least 112500 bd, maybe also higher speeds.
    You can have the ADC result with 16bit unsigned integer value.
    https://developer.mbed.org/users/boseji/notebook/adc-processing-/
    Serial interfacing etc. is explained in mbed.org
    What is at the receiving end?
    PC terminal or some graphical display?
    Can you do some processing at the receiving end?
     
  7. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    The receiving end is a computer and I am using MATLAB to display the plots, but I need to do the processing on the MCU since it will be used as a standalone device. I am only using MATLAB to confirm that the processing of the signals is correct and for better visualisation of the processed signals.
     
    Last edited: Mar 22, 2016
  8. jjw

    Member

    Dec 24, 2013
    173
    31
    You can do adc at full speed, save the data into arrays and at the end send the arrays to pc.
    If the conversion with floats is too slow, use 16bit unsigned integers.
    The adc sampling speed is at least 200kHz and is more than enough for four 1kHz channels.
     
  9. jjw

    Member

    Dec 24, 2013
    173
    31
    I tested this on Nucleo board ( stm32F401RE / 84MHz )
    ADC for 4 channels takes 15us / round, so 66 samples / 1kHz period / channel.
    STM32F401 has a floating point unit, but with integer values you should get about the same speed.

    Code (C):
    1.  
    2. #include "mbed.h"
    3.  
    4. #define N_Samples 100
    5.  
    6. // Nucleo stm32F401re . Initialize 4 pins to perform analogue input functions.
    7.  
    8. AnalogIn  ain1(PA_0);
    9. AnalogIn  ain2(PA_1);
    10. AnalogIn  ain3(PA_2);
    11. AnalogIn  ain4(PB_0);
    12.  
    13. // USB serial (TX, RX)
    14. Serial pc(USBTX, USBRX);
    15.  
    16. Timer t;
    17.  
    18. int main(void)
    19. {
    20.   // Declaring variables to be used for the ADC voltages
    21.   float ADC1_voltage[N_Samples];
    22.   float ADC2_voltage[N_Samples];
    23.   float ADC3_voltage[N_Samples];
    24.   float ADC4_voltage[N_Samples];
    25.  
    26.   int i;
    27.  
    28.   t.reset();
    29.   t.start();
    30.  
    31.   for ( i=0; i< N_Samples; i++ ){
    32.  
    33.       ADC1_voltage[i] = ain1*3.3f;
    34.       ADC2_voltage[i] = ain2*3.3f;
    35.       ADC3_voltage[i] = ain3*3.3f;
    36.       ADC4_voltage[i] = ain4*3.3f;
    37.   }
    38.  
    39.   t.stop();
    40.   pc.printf("\nTime for one round= %f us\n", t.read()*1000000/N_Samples);
    41.  
    42.   // Send the ADC values to serial port
    43.   // Values from the last round
    44.  
    45.   pc.printf("%f,%f,%f,%f\n", ADC1_voltage[i], ADC2_voltage[i], ADC3_voltage[i], ADC4_voltage[i]);
    46.  
    47. }
    48.  
    49. [\code]
     
    Dritech likes this.
  10. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Thanks for the reply. I tried using the ADC in integer data type by following the link you mentioned previously.
    I did as follows:

    ADC_int = ((ain1.read_u16()&amp;0xFFF)*3.3/4095);

    This did not work. What am I doing wrong? Is "int ADC_int" the way to declare the variable (since it is a 16-bit integer)?
     
  11. jjw

    Member

    Dec 24, 2013
    173
    31
    First, you can't multiply an integer with 3.3.
    read_u16() returns unsigned short integer, normalized from 0 to 65535. With 12 bit ADC you can get the real value ( 0-4095 ) by dividing with 16

    If you need to scale the values to real voltages ( 0 to 3.3V) you could multiply the values by 3300 and then divide by 65535 to get the results in millivolts.
    I have not yet connected anything to ADC pins, so have not tested this.
    The speed in stm32f401 is the same with integers and floats.

    In mbed the default sizes are:
    short = 16bit
    int = 32b
    long = 32b
    long long = 64b
     
  12. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Hi again,

    I connected a potentiometer to the ADC and turned it both directions for eight times to monitor the output through Putty.
    I tried the following code:

    Code (C):
    1.  
    2. #include "mbed.h"
    3. // Initialize a pins to perform analogue input fucntions
    4. AnalogIn   ain1(p15);
    5. AnalogIn   ain2(p16);
    6. AnalogIn   ain3(p17);
    7. AnalogIn   ain4(p19);
    8. AnalogIn   ain5(p20);
    9.  
    10. // USB serial (TX, RX)
    11. Serial pc(USBTX, USBRX);
    12.  
    13. int main(void)
    14. {
    15.     pc.baud(115200);
    16.     short ADC1_voltage;
    17.  
    18.     while (1)
    19.     {
    20.         ADC1_voltage = ((ain1.read_u16()&0xFFF)*3300/4095);
    21.  
    22.         // Send the five ADC values to serial port
    23.         pc.printf("%d\n", ADC1_voltage);
    24.  
    25.     }
    26. }
    and got this plot:
    [​IMG]

    Then I replaced the the same code, but this time using a floating variable:

    Code (C):
    1. #include "mbed.h"
    2. // Initialize a pins to perform analogue input fucntions
    3. AnalogIn   ain1(p15);
    4. AnalogIn   ain2(p16);
    5. AnalogIn   ain3(p17);
    6. AnalogIn   ain4(p19);
    7. AnalogIn   ain5(p20);
    8.  
    9. // USB serial (TX, RX)
    10. Serial pc(USBTX, USBRX);
    11.  
    12. int main(void)
    13. {
    14.     pc.baud(115200);
    15.     short ADC1_voltage;
    16.  
    17.     while (1)
    18.     {
    19.         ADC1_voltage = ((ain1.read_u16()&0xFFF)*3300/4095);
    20.  
    21.         // Send the five ADC values to serial port
    22.         pc.printf("%d\t,%d\t,%d\t,%d\t,%d\n", ADC1_voltage, ADC2_voltage, ADC3_voltage, ADC4_voltage, ADC5_voltage);
    23.  
    24.     }
    25. }
    and got the following result:

    [​IMG]

    As can be seen, the results are not correct when using integers. Any suggestions of what can be wrong?
    In the code ADC_int = ((ain1.read_u16()&amp;0xFFF)*3.3/4095); , do I have to keep the "amp;" ? because the program was not compiling with it included in the code.

    Thanks in advance.

    Moderators note: used code tags for C
     
  13. jjw

    Member

    Dec 24, 2013
    173
    31
    What is amp?

    Don't mask the result with 0xfff, 0xffff is ok, if needed.

    This should be ok:
    ADC1_voltage= (ain1.read_u16()×3300)/65535;
     
    Dritech likes this.
  14. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    2,805
    833
    An unsigned integer type has a maximum value of 65535. Since you are multiplying the ADC value by 3300, the ADC value cannot be greater than 19! Otherwise you will have overflow errors. Cast your input to an unsigned long and multiply by an unsigned long (3300ul, or however it is represented in your language). Divide by an unsigned long and then cast the entire calculation back to an unsigned integer.

    You can even use integer arithmetic to get the result, and use this technique to obtain a floating point value in volts.

    Calculating with mixed types and using division with integers can often be problematic. You have to consider the range of intermediate results. The technique I explained is an example of how I code to get around these limitations.
     
    Dritech likes this.
  15. Dritech

    Thread Starter Well-Known Member

    Sep 21, 2011
    756
    5
    Thanks for the help. I managed to make it work by following your suggestions :)
     
    djsfantasi likes this.
Loading...