MBED slow serial communication

Thread Starter

Dritech

Joined Sep 21, 2011
901
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?

C:
#include "mbed.h"

// Initialize a pins to perform analogue input fucntions
AnalogIn  ain1(p15);
AnalogIn  ain2(p16);
AnalogIn  ain3(p17);
AnalogIn  ain4(p19);

// USB serial (TX, RX)
Serial pc(USBTX, USBRX);

int main(void)
{
    // Declaring variables to be used for the ADC voltages
    float ADC1_voltage;
    float ADC2_voltage;
    float ADC3_voltage;
    float ADC4_voltage;

    while (1)
    {
    ADC1_voltage = ain1*3.3;
    ADC2_voltage = ain2*3.3;
    ADC3_voltage = ain3*3.3;
    ADC4_voltage = ain4*3.3;

    // Send the five ADC values to serial port
    pc.printf("%f,%f,%f,%f\n", ADC1_voltage, ADC2_voltage, ADC3_voltage, ADC4_voltage);
  }
}
Moderators note: used code tags for C
 
Last edited by a moderator:

jjw

Joined Dec 24, 2013
823
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.
 

Thread Starter

Dritech

Joined Sep 21, 2011
901
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?
Hi, I need to display a four 1kHz signals at reasonable quality. How can I determine the baud rate required?

Btw. in the printf function there are five %f parameters, but only four variables to be printed.
Sorry that was a typo.
 
Last edited:

jjw

Joined Dec 24, 2013
823
Mbed supports at least 112500 bd, maybe also higher speeds.
Thanks for the reply. Since the ADC result is a floating value, what can I use instead of a floating data type?
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?
 

Thread Starter

Dritech

Joined Sep 21, 2011
901
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:

jjw

Joined Dec 24, 2013
823
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.
 

jjw

Joined Dec 24, 2013
823
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.

C:
#include "mbed.h"

#define N_Samples 100

// Nucleo stm32F401re . Initialize 4 pins to perform analogue input functions.

AnalogIn  ain1(PA_0);
AnalogIn  ain2(PA_1);
AnalogIn  ain3(PA_2);
AnalogIn  ain4(PB_0);

// USB serial (TX, RX)
Serial pc(USBTX, USBRX);

Timer t;

int main(void)
{
  // Declaring variables to be used for the ADC voltages
  float ADC1_voltage[N_Samples];
  float ADC2_voltage[N_Samples];
  float ADC3_voltage[N_Samples];
  float ADC4_voltage[N_Samples];
  
  int i;

  t.reset();
  t.start();
  
  for ( i=0; i< N_Samples; i++ ){
  
      ADC1_voltage[i] = ain1*3.3f;
      ADC2_voltage[i] = ain2*3.3f;
      ADC3_voltage[i] = ain3*3.3f;
      ADC4_voltage[i] = ain4*3.3f;
  }

  t.stop();
  pc.printf("\nTime for one round= %f us\n", t.read()*1000000/N_Samples);

  // Send the ADC values to serial port
  // Values from the last round
  
  pc.printf("%f,%f,%f,%f\n", ADC1_voltage[i], ADC2_voltage[i], ADC3_voltage[i], ADC4_voltage[i]);

}

[\code]
 

Thread Starter

Dritech

Joined Sep 21, 2011
901
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)?
 

jjw

Joined Dec 24, 2013
823
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)?
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
 

Thread Starter

Dritech

Joined Sep 21, 2011
901
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:

C:
#include "mbed.h"
// Initialize a pins to perform analogue input fucntions
AnalogIn   ain1(p15);
AnalogIn   ain2(p16);
AnalogIn   ain3(p17);
AnalogIn   ain4(p19);
AnalogIn   ain5(p20);

// USB serial (TX, RX)
Serial pc(USBTX, USBRX);

int main(void)
{
    pc.baud(115200);
    short ADC1_voltage;

    while (1)
    {
        ADC1_voltage = ((ain1.read_u16()&0xFFF)*3300/4095);

        // Send the five ADC values to serial port
        pc.printf("%d\n", ADC1_voltage);

    }
}
and got this plot:


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

C:
#include "mbed.h"
// Initialize a pins to perform analogue input fucntions
AnalogIn   ain1(p15);
AnalogIn   ain2(p16);
AnalogIn   ain3(p17);
AnalogIn   ain4(p19);
AnalogIn   ain5(p20);

// USB serial (TX, RX)
Serial pc(USBTX, USBRX);

int main(void)
{
    pc.baud(115200);
    short ADC1_voltage;

    while (1)
    {
        ADC1_voltage = ((ain1.read_u16()&0xFFF)*3300/4095);

        // Send the five ADC values to serial port
        pc.printf("%d\t,%d\t,%d\t,%d\t,%d\n", ADC1_voltage, ADC2_voltage, ADC3_voltage, ADC4_voltage, ADC5_voltage);

    }
}
and got the following result:



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
 

jjw

Joined Dec 24, 2013
823
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;
 

djsfantasi

Joined Apr 11, 2010
9,156
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.
 
Top