5 years, 8 months ago.

Transmit and Receive int array from and to Nucleo f4303re.

Hi im trying to write a code that takes data from pc using QT and receiving side nucleo f4303re will then be able to write it back to the pc serial for error checking. What i have done just is doing some part of the job as sometimes it transmits and receives and sometimes not. My mbed code is;

include the mbed library with this snippet

#include "mbed.h"

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);

int main() {
  pc.baud(115200);
char buffer[200];
// while (true){
//   char c = pc.getc();
// if(c=='H'){
//   myled = 1;
// }
//  if (c=='B'){
//   myled = 0;
//   wait(0.1);
// }
// }


for(int i=0;i<200;i++){


char c = pc.getc();
buffer[i] = c;
pc.putc(buffer[i]);


}
}

and my qt code function is;

qt code

void arduinoTest::writeArd(long samples[], int size_sample)
{
    char *samples32 = new char [size_sample];
    char *readData = new char [size_sample];


    for (int i =0;i<size_sample;i++){
        samples32[i] = samples[i];

        arduino->write(&samples32[i]);



        arduino->read(readData,size_sample);
        qDebug() << (int)readData[i] << "," ;




    }

1 Answer

5 years, 8 months ago.

Your current mbed code sends data back the first 200 bytes as they arrive and then stops doing anything until reset.

Is that what you want?

Other than stopping after 200 bytes there isn't any obvious reason why this shouldn't work.

There is one corner case possibility, you'd have to be unlucky to run into it but it is possible: While the port is at the same rate in both directions the PC and mbed are using different clocks so they could each be sending data at very slightly different rates (uarts can normally cope with up to a 5% error). This means that in some situations bytes can arrive faster than you can send them out. If you have the occasional gap in your data then this isn't an issue since that gives the slower side a chance to catch up but it looks like you send everything in one big block, theoretically if you were unlucky with the clock errors 200 bytes without a pause is enough to cause you to get buffer overflows.

There are two possible solutions to this: 1) Your current mbed code runs 1 byte at a time: receive, transmit,receive, transmit. Instead break the link between the two and let the mbed buffer data, a serial receive interrupt puts new data into a buffer, the background loop reads the buffer and outputs it.

2) Have the PC application add a small pause every 50 or so bytes. You may need to time that manually, the PC hardware will be buffering the writes so finding out when exactly it's finished sending everything you've given it can be tricky.

Accepted Answer

thank you so much. Actually the problem was with qt side. when i changed it it became better but now occasinnaly like in 200 bytes occasionally 3 consecutive bytes are becoming wrong. So im gonna try to do it with buffer. and then try with occasional pauses. I need to transmit these bytes to an external DAC and then play a sound so small pauses may endanger the necessary speed for the application. thanks!

posted by Bora Çelebi 17 Apr 2019

When data is coming from a DAC you shouldn't need to manually add pauses, you will need to send bytes to the DAC at a fixed rate which will be below the maximum rate of the serial port and so there will naturally be pauses. The issue is only because you are trying to drive the serial port at 100% utilization in both directions at the same time, even that wouldn't normally be an issue but you are asking both directions to be at exactly the same rate rather than roughly the same rate.

posted by Andy A 17 Apr 2019

Thank you so much actually with a baudrate of 57600 on both sides it worked. But to output it to the DAC can i just get 2 bytes from the serialport to Nucleo and then send it to a DAC of 16bits? or should i fill an array in nucleo first and then send every element to the DAC ?

posted by Bora Çelebi 17 Apr 2019

I assume that you have a fixed sample rate that you want to output the data from the DAC, if this is audio you need to play if back at the correct rate.

That means you need to pass the data to the DAC at the correct rate.

The way I'd structure this would be to have a circular buffer on the Nucleo that is large enough to hold say 250 ms worth of audio.

The PC sends the first 175 ms of data in one go and then every 100 ms after that it sends data in 100 ms blocks, the nucleo uses the receive interrupt to add the data to the buffer.

Once the buffer on the Nucleo gets to half full you kick off a Ticker interrupt which triggers at the required sample rate and reads a value from the buffer and outputs it to the DAC.

That way the PC can do bulk transfers which is what it's better at and can get its timing wrong by up to 25 ms each way without causing any issues. The nucleo handles the accurate timing but doesn't have to hold all the data at the same time.

Ideally the buffer on the nucleo should be as large as memory allows but larger buffers normally imply more latency if you need to get timing accurate or start the playback quickly.

posted by Andy A 18 Apr 2019

Thank you for your answer. As using qtserialport its documentation tells that it handles interrupts and can wait for byteswritten to the port. So can i send all of the data in one go from pc like kilobytes of data and on nucleo i just get first 100 bytes then pass it to dac and clear the 100bytes buffer and continue this in a loop till no data comes from pc? Otherwise there needs to be a really calibration between pc side and board.

posted by Bora Çelebi 21 Apr 2019

That would only work if you use flow control on the port. Without it the pc will send all the data as fast as possible and unless the nucleo buffer was large enough to hold everything in one go you'll over flow the buffer and lose data. A standard UART doesn't know it care of the other end is ready for data or not. If you tell the pc to send everything it will do it as fast as the baud rate allows.

posted by Andy A 21 Apr 2019

Thank you so mıch Andy. So like you said i will write bytes in some intervals. Then on board side on those intervals ill use getc and merge two chars into 16bit integers and save it in buffer and then will send to the DAC in the same interval before new data has been sent

posted by Bora Çelebi 22 Apr 2019

One more question sorry.. can i use usbaudio library on this project? As i ll pass audio package to dac from board

posted by Bora Çelebi 22 Apr 2019

I've never used USBAudio so I have no idea.

posted by Andy A 23 Apr 2019