1

I try to use Sky mote (MSP430 F1611 + CC2420) to read the data from I2C sensor with 100Hz sampling frequency and write the data to serial port (USB). I tried a couple of tests and realized that the total output data have a sampling frequency of 78Hz. I used rtimer to profile my sampling and printing code and found the print function slows down the entire process. Here are some profiling outputs:

start 50628
15490,f074,20,3b8c,ffab,49,ffcf,fb70
end 51189
start 51293
15491,f0a8,fff4,3ba4,ffc6,24,ffd8,fb90
end 51880
start 51984
15492,f094,20,3b30,ffa7,5b,fff3,fb70
end 52544
start 52647
15493,f118,bc,3ce0,ffab,70,fffc,fb90
end 53207
start 53311
15494,f030,1b0,3b44,ffa9,1f7,1f,fb80
end 53871

The rtimer has 4098*8 ticks for one second. Here we can clearly see that the printing takes about 560 ticks (17ms). If the sampling frequency is 100Hz, the printing function should be completed within 10ms (327 ticks).

The embedded system I am using is Contiki OS and the baud rate is 115200 (maximum baud rate). The sensor sample contains 112bytes signed int.

Here is my code:

mpu_data_union samples;
int m=mpu_sample_all(&samples);
printf("start %u\n",RTIMER_NOW());
printf("%lu,%x,%x,%x,%x,%x,%x,%x\n",
  counterxx,samples.data.accel_x,samples.data.accel_y,
  samples.data.accel_z,samples.data.gyro_x,
  samples.data.gyro_y,samples.data.gyro_z,
  samples.data.temperature);
printf("end %u\n",RTIMER_NOW());

I hope some people with previous experience on optimizing printf or UART in general could provide some suggestions.

Thanks!

cloudfarm
  • 13
  • 3
  • Yes, printf is relatively slow. There's not a whole lot you can do about that, so you probably have to write your own conversion function - that can hopefully be more specialized and faster. – nos Jun 13 '14 at 08:03
  • If I remember good, you can stop the printf bufferize to reduce execution time. – Yann Jun 13 '14 at 08:08
  • @nos do you have some general guides on how to optimize the printf function for msp430? Thanks! – cloudfarm Jun 13 '14 at 08:22
  • Show some code. If you need printf only to display e.g. hex numbers you can write your own conversion function without `printf`'s overhead. – Jabberwocky Jun 13 '14 at 09:05
  • So as I supposed it's mainly about printing hex values. Do the conversion from int to string by yourself and then use the `puts` function. – Jabberwocky Jun 13 '14 at 09:37
  • Apart from the inefficiency in your program, keep in mind that your 112 bytes gets multiplied by 10 bit periods not 8, so at 100 Hz and 115200 baud the serial link is all but saturated, with no allowance for late writes to the UART. If your UART does not have enough of a hardware buffer to stay full while you are collecting the I2C data, the resulting failure to keep the UART 100% busy could alone be enough to miss your goal. – Chris Stratton Jun 13 '14 at 16:13

3 Answers3

1

I had a similar-ish problem with the printf function just being far too big for the MSP variant that I was using so I had to write my own version of the printf function as I did not need all of the baggage associated with the format string converters. I wrote a set of little functions that output a value in the required format and send the character output directly to the usart.

printf("%lu,%x,%x,%x,%x,%x,%x,%x\n", counterxx,samples.data.accel_x,samples.data.accel_y, samples.data.accel_z,samples.data.gyro_x, samples.data.gyro_y,samples.data.gyro_z, samples.data.temperature);

becomes

Send_Long_Decimal( counterxx ) ; 
Send_Hex( samples.data.accel_x ) ; 
Send_Hex( samples.data.accel_y ) ;
Send_Hex( samples.data.accel_z ) ;
Send_Hex( samples.data.gyro_x)  ;
Send_Hex( samples.data.gyro_y ) ;
Send_Hex( samples.data.gyro_z ) ;
Send_Hex( samples.data.temperature ) ;
Send_Newline() ;

The answer from Morty suggests using the non-blocking, interrupt driven serial port implementation. This is to be encouraged so that the time taken for the serial transfer does not come out of your available processing time.

Looking at the data sent out in your log, it would appear that the first record is around 64 characters long. Sending 100 of these at 115kbaud will take just over 0.5 seconds. You then have to read the data in from the I2C interface and perform some data processing/storage in the remaining less than 0.5 seconds.

Community
  • 1
  • 1
uɐɪ
  • 2,540
  • 1
  • 20
  • 23
0

While printf is slow, the serial is even slower (by far). By default Contiki uses a blocking serial for the MSP430 F1xx chips (See 1). By setting UART0_CONF_TX_WITH_INTERRUPT (Add -DUART0_CONF_TX_WITH_INTERRUPT to your CFLAGS) you can switch over to non-blocking buffered serial (128 Byte by default).

Morty
  • 2,889
  • 2
  • 19
  • 28
0

The C library printf wasn't designed for MSP430 16-bit microcontrollers. Instead, it was meant to be a general purpose solution to the problem of printing to a console.

If you need a more efficient solution, you should implement your own custom printing methods that write out a UART.

Here are a couple of solutions that are freely available:

  1. http://43oh.com/2011/10/tiny-printf-for-the-space-constrained-msp430/

  2. https://gist.github.com/nicholasjconn/2896369 (http://www.msp430launchpad.com/2012/06/using-printf.html)

bblincoe
  • 2,393
  • 2
  • 20
  • 34