Show Posts
Pages: [1] 2
1  Products / Arduino Due / Re: Bridge USB Native port to Serial2 on: November 20, 2013, 08:49:26 am
OK. I am planning to get long 1038 bytes frames from Serial2 (sending them to the PC  via Native port), and send from the PC short 2byte frames, to Serial2 TX.

However, I have found some issues.
First the buffer data input for Serial2 uart is 64 bytes, so I need to read as fast as I can in roder to not get it full and lose data.

On the other hand, tried to read some bytes (6 bytes) at the same time to save accessing time. But I think, this way the processor is not able to get the job done in time.

Here is my code:

Code:
int led = 13;
boolean estado_led=HIGH;

void setup() {
 
    // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
 
 
  // initialize both serial ports: 
  Serial.begin(115200);


 Serial.println(" ARDUINO ON1!! #");
  Serial2.begin(3000000);
 
  SerialUSB.begin(3000000);//10 Megas
 // while(!SerialUSB);
 
  Serial.println(" ARDUINO ON!2! #");

  Serial.println(" ARDUINO ON2!! #");
}

#define buffer_mensaje 1038
char buf_msx[buffer_mensaje];   // 4 buffers of 256 readings
char buf_Rx[buffer_mensaje];   // 4 buffers of 256 readings




char lee_serie_of[2];
int breakpoint_1=0;
int breakpoint_2=0;
int cnt_loop=0;
int cnt_loop2=0;
int cnt_loop_total=0;
int cnt_rx2=0;
int cnt_tx2=0;
int cnt_s2rx2=0;




void loop() {
  cnt_loop++;
 
  if (cnt_loop>=100000){
  estado_led=!estado_led;
  cnt_loop=0;
    digitalWrite(led, estado_led);   // turn the LED on (HIGH is the voltage level)
   
  }


 
int incomingByte = 0;   // for incoming serial data

 
 if (SerialUSB.available() > 1)
 {
      incomingByte = SerialUSB.readBytes(lee_serie_of, 2);
      Serial2.write(lee_serie_of[0]);
      Serial2.write(lee_serie_of[1]);
      cnt_tx2++;
   
      para_en_TX=true;

 }
   
   
  // read from port 1, send to port 0:
  /*while (Serial2.available()>0) {
    int inByte = Serial2.read();
     SerialUSB.write(inByte);
  }/**/
//  if (Serial2.available()>1037) {

    if (Serial2.available()>6)
    {
//   int inByte = Serial2.readBytes(buf_msx, 1038);   
//    SerialUSB.write((uint8_t *)buf_msx,buffer_mensaje);

   int inByte = Serial2.readBytes(&buf_Rx[cnt_s2rx2*6], 6);   
   cnt_s2rx2++;
   cnt_rx2++;

  } 
 
 
  if (cnt_s2rx2>0)//1038/6
  {
   
     SerialUSB.write((uint8_t *)buf_Rx,cnt_s2rx2*6);
     cnt_s2rx2=0;
  }
 

}
2  Products / Arduino Due / Re: Bridge USB Native port to Serial2 on: November 19, 2013, 05:09:48 pm
I'll be curious to hear when speed you actually achieve?

My guess is it will fall short of 20 Mbit/sec.  Due's native port can transmit fast, I believe in the range of 40 to 50 Mbit/sec (about 10% of the theoretical bandwidth of 480 Mbit/sec USB).  But USB reception is slower, approx 1 Mbit/sec last time I measured.  I'm not sure what baud rates are supported for Serial2.  If do know transmit on Serial2 is polled with only the UART's 2 byte buffer, so you'll probably need to work around that somehow for the USB->Serial2 direction.

Good luck.  I hope you'll follow up with details on how it works?

Thank you for your answer Paul.

I have used Native port before with baudrates at 40Mbit/s with no problems.
What do you mean by USB reception? Is it using the programming port?

What do you mean Serial2 is polled with a byte buffer?

Actually, in my design the TTL device will send data continuosly and the PC will send some short frames of three bytes, for configuration in asynchronous mode (after a user request).

Do you know where I can find a script doing something similar to this?
Is it possible a dma mode?


Thank you again



3  Products / Arduino Due / Bridge USB Native port to Serial2 on: November 19, 2013, 01:26:37 pm
Hello all.
In a new project I need to connect a TTL device and my PC at a high rate communication. I thought the easiest way could be using the Native port of my Arduino Due.

So I need to reroute all the data traffic (at 20Mbps) between the Due Native port and Serial 2 port (TTL device).
I have implemeted all the data protocol, which is some HEX data, so I was planning to send every byte received from one port to the TX of the other port.

RX2    -------------------  Native Tx
Native Rx   --------------------  TX2

1.- Is there a simple/effective way to achieve this?
2.- Is there a way to not tie up the CPU of the due? (via dma or similar)
3.- Is it better to buffer the communication?

Thank you.

4  Products / Arduino Due / Re: speed of analogRead on: June 09, 2013, 07:07:22 am
It's not an interrupt, the ADC is internally wired to the timer and can use it to trigger a conversion. You can use it with DMA, it works just as you'd expect - for example if you set the timer to 1000Hz and ask the DMA to do 100 conversions you get 100 samples at a sample rate of 1000 samples/sec smiley

I used this technique in the DueVGA Waterfall example but I haven't properly tidied up the code and commented it yet so it is hard to follow.
https://github.com/stimmer/DueVGA/blob/master/extras/Waterfall/waterfall/waterfall.ino

Thank you again Stimmer. Nice piece of code.

 This is working as it should (I tested it at 50kHz). The nice thing about this way is that you don't need to worry about the sampling rate when using more than one channel....just multiply the buffer size by the number of them.

5  Products / Arduino Due / Re: speed of analogRead on: June 08, 2013, 07:36:52 pm
ADC_FREQ_MAX/MIN is the frequency of the ADC clock, not the sample rate. The ADC takes about 20 clocks to do a conversion (maybe exactly 20 clocks, I can't remember), so the conversion rate by this method is 50000-1000000 samples per second. To get a slower sample rate using free-running mode you could sample some channels you don't need to slow things down. But the proper way to do it is to use a timer triggered mode instead of free-running mode.

I see, but then is every analogread sampled in the timer interrupt? How does DMA Work with the timer?
I don't get it.

Thank you again.
6  Products / Arduino Due / Re: speed of analogRead on: June 08, 2013, 12:06:25 pm

The line   adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST); sets the prescal value - there is also ADC_FREQ_MIN and you can pass any value in between.



There is something I am missing.... if I want to set up an effective 20kHz or 50 KHz sampling rate using this method, what should I write?

The line   adc_init(ADC, SystemCoreClock, 50000, ADC_STARTUP_FAST); feels wrong since ADC_FREQ_MIN is 1000000


Thank you
7  Products / Arduino Due / Re: DUE's more advanced FFT capabilities on: March 04, 2013, 07:01:47 am
Nope, I was happy with whatever I could get to work, since I'm still at the
"thinking about it" phase of my project.
I have not really made an effort specifically for the Q31.
It might be hard, it could be simple ....
 



It is not hard, I have it for Q15, the problem is, if I use any Q31 array, arduino just freezes!!
8  Products / Arduino Due / Re: DUE's more advanced FFT capabilities on: March 03, 2013, 01:53:16 pm
lots of explaining can be found in hardware/arduino/sam/system/CMSIS/CMSIS/Documentation/DSP_Lib/html/index.html

as far as I can see now it is suposed to work , only not with hardware support (like in the M4).
it is even supposed to work on the M0 !

exciting !

... but on second thought, be aware that this stuff is covered by a licence.

I got the sketch to pass the errors mentioned above, but it seems to need to link with an .a file.
does anybody know how I should build these CMSIS files into a library and add that to the Arduino IDE ?

my sketch until now (based on one of the examples, but duly botched while trying to get it to compile) :
Code:
#define ARM_MATH_CM3 // this selects right environment for arm_math.h on DUE
#include <arm_math.h>

#define TEST_LENGTH_SAMPLES 2048
 
static q31_t testOutput[TEST_LENGTH_SAMPLES/2]; // all types changed from f32 to q31 just to see if it mattered
 
uint32_t M = 0;
 
/* ------------------------------------------------------------------
* Global variables for FFT Bin Example
* ------------------------------------------------------------------- */
uint32_t fftSize = 1024;
uint32_t ifftFlag = 0;
uint32_t doBitReverse = 1;
 
/* Reference index at which max energy of bin ocuurs */
uint32_t refIndex = 213, testIndex = 0;
 
/* ----------------------------------------------------------------------
Test Input signal contains 10KHz signal + Uniformly distributed white noise
** ------------------------------------------------------------------- */

q31_t testInput_f32_10khz[TEST_LENGTH_SAMPLES] =
{  
-0.865129623056441, 0.000000000000000, -2.655020678073846, 0.000000000000000, 0.600664612949661, 0.000000000000000, 0.080378093886515, 0.000000000000000,
-2.899160484012034, 0.000000000000000, 2.563004262857762, 0.000000000000000, 3.078328403304206, 0.000000000000000, 0.105906778385130, 0.000000000000000,
-1.620990298572947, 0.000000000000000, -1.085103073196045, 0.000000000000000, 0.738606361195386, 0.000000000000000,
-2.097831202853255, 0.000000000000000, 2.711952282071310, 0.000000000000000, 1.498539238246888, 0.000000000000000, 1.317457282535915, 0.000000000000000,
-0.302765938349717, 0.000000000000000, -0.044623707947201, 0.000000000000000, 2.337405215062395, 0.000000000000000, -3.980689173859100, 0.000000000000000,

};

void setup() {
  Serial.begin(19200);
}

void loop() {
      
    
       /** \example arm_fft_bin_example_f32.c
  */  

arm_status status;
arm_cfft_radix4_instance_q31 S;
q31_t maxValue;

status = ARM_MATH_SUCCESS;

/* Initialize the CFFT/CIFFT module */  
status = arm_cfft_radix4_init_q31(&S, fftSize, ifftFlag, doBitReverse);

/* Process the data through the CFFT/CIFFT module */
arm_cfft_radix4_q31(&S, testInput_f32_10khz);


/* Process the data through the Complex Magnitude Module for  
calculating the magnitude at each bin */
arm_cmplx_mag_q31(testInput_f32_10khz, testOutput, fftSize);  

/* Calculates maxValue and returns corresponding BIN value */
arm_max_q31(testOutput, fftSize, &maxValue, &testIndex);

if(testIndex !=  refIndex)
{
status = ARM_MATH_TEST_FAILURE;
}

/* ----------------------------------------------------------------------
** Loop here if the signals fail the PASS check.
** This denotes a test failure
** ------------------------------------------------------------------- */

if( status != ARM_MATH_SUCCESS)
{
while(1);
}

    while(1);                             /* main function does not return */
    
}


Could you finally get this library working under Q31? I can in Q15 and f32, but not under Q31!!!
Thank you
9  Products / Arduino Due / Re: linking with libarm_cortexM3l_math.a ? on: March 03, 2013, 10:04:15 am
I have seen that in the CMSIS library, those functions exist in radix2 format as well:

http://mazsola.iit.uni-miskolc.hu/DATA/segedletek/arm/cmsis/CMSIS/Documentation/DSP/html/group___radix2___c_f_f_t___c_i_f_f_t.html

But they are not included in the Arduino Due Libraries, why? Is it possible to add them? If it is, will they work with similar performance?

Thank you

10  Products / Arduino Due / Re: linking with libarm_cortexM3l_math.a ? on: March 02, 2013, 07:46:54 pm
Please turn on verbose mode in preferences and post the full output. I followed the instructions here and it worked fine.

Is there any reason not to include this modification in the next IDE release? It doesn't affect sketches which don't use the functions.

Ok, I have spotted the error.

First I restarted the Arduino IDE.  smiley-lol smiley-lol

Then I tried to change the points of the FFT to the half by using:
Code:
#define TEST_LENGTH_SAMPLES 1024
uint32_t fftSize = 512;

So I get the error at the call:
Code:
arm_cfft_radix4_f32(&S, testInput_f32_10khz);

after step 1.


Then I checked the file arm_cfft_radix4_init_f32.c, and there is not a 512 point fft!!!
Is there any way to introduce it?


11  Products / Arduino Due / Re: linking with libarm_cortexM3l_math.a ? on: March 02, 2013, 07:05:02 pm
running all 4 fft computations in the example 1000 times
(and assuming Millis() works correctly on the DUE)
takes about 35 seconds. 
hence 35 milliseconds per fft, for 1024 bins,

and 28 fft1024 calculations per second.   

Im falling in love with this beast...

Code:
start program
34939
69320


I followed all your steps, I edited the platforms.txt file, butno glory,  when my Arduino Due boots, it freezes.
It freezes whenever I call any of the functions of your example, i.e. arm_cfft_radix4_init_f32. If I comment ount that line, everything works.

When I compile I get the following errors:
Code:
EXTRACTOR_FFT_ARDUINO_DUE.cpp.o: In function `Ejecuta_FFT()':
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:131: warning: undefined reference to `arm_cfft_radix4_init_f32'
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:135: warning: undefined reference to `arm_cfft_radix4_f32'
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:140: warning: undefined reference to `arm_cmplx_mag_f32'
D:\Arduino\arduino-1.5.2/EXTRACTOR_FFT_ARDUINO_DUE.ino:143: warning: undefined reference to `arm_max_f32'
Binary sketch size: 23.212 bytes (of a 524.288 byte maximum) - 4% used

Any hint on this?
Thank you.
12  Products / Arduino Due / Re: speed of analogRead on: March 02, 2013, 06:55:08 am

Thank you Gericom.
Thank you stimmer.

13  Products / Arduino Due / Re: speed of analogRead on: March 01, 2013, 05:39:42 pm
The jitter you are measuring is not the same thing as the clock jitter that was mentioned earlier in the thread and will not affect the accuracy of the ADC readings. Clock jitter is caused by the accuracy of the timing and waveform of the master clock oscillator and there is nothing we can do about that.

The line   adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST); sets the prescal value - there is also ADC_FREQ_MIN and you can pass any value in between.

It isn't possible to get a buffer per channel as far as I know. There is a tagged mode where the highest 4 bits are written with the channel the sample came from, that is useful when you enable more than one channel.

SerialUSB works as fast as it can, the baud rate is ignored. Since it's USB2.0 the port is faster than the SAM3X can throw data down it. I've had it running at over 50Mbit/sec.



I'm sorry about the jitter misunderstanding, after thinking it I knew it was a different issue.

So, about the ADC sampling in both channels, then I suppose that the samples are alternated in the buffers, right?  Sorry to insist,but I am learning about the system...so, how could I set up a second channel?

Then, about the adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST) function.... Where could I find more information about this macros and functions? They are not the same as in the Arduino UNO, but pretty similar.
14  Products / Arduino Due / Re: speed of analogRead on: March 01, 2013, 12:22:54 pm
Quote
Code:
   while((ADC->ADC_ISR & 0xC0)==0);// wait for two conversions (pin A0[7]  and A1[6])

Well spotted - what it should actually be is this:
Code:
   while((ADC->ADC_ISR & 0xC0)!=0xC0);// wait for two conversions (pin A0[7]  and A1[6])

I'll go back and change my code in case anyone else copy/pastes it.

For reducing missed samples and allowing more processing time in the main loop, the biggest win comes through using peripheral DMA. This example uses DMA and interrupts - although if you are new to the Due, don't expect to understand it all at once smiley

Code:
#undef HID_ENABLED

// Arduino Due ADC->DMA->USB 1MSPS
// by stimmer
// Input: Analog in A0
// Output: Raw stream of uint16_t in range 0-4095 on Native USB Serial/ACM

// on linux, to stop the OS cooking your data:
// stty -F /dev/ttyACM0 raw -iexten -echo -echoe -echok -echoctl -echoke -onlcr

volatile int bufn,obufn;
uint16_t buf[4][256];   // 4 buffers of 256 readings

void ADC_Handler(){     // move DMA pointers to next buffer
  int f=ADC->ADC_ISR;
  if (f&(1<<27)){
   bufn=(bufn+1)&3;
   ADC->ADC_RNPR=(uint32_t)buf[bufn];
   ADC->ADC_RNCR=256;
  }
}

void setup(){
  SerialUSB.begin(0);
  while(!SerialUSB);
  pmc_enable_periph_clk(ID_ADC);
  adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);
  ADC->ADC_MR |=0x80; // free running

  ADC->ADC_CHER=0x80;

  NVIC_EnableIRQ(ADC_IRQn);
  ADC->ADC_IDR=~(1<<27);
  ADC->ADC_IER=1<<27;
  ADC->ADC_RPR=(uint32_t)buf[0];   // DMA buffer
  ADC->ADC_RCR=256;
  ADC->ADC_RNPR=(uint32_t)buf[1]; // next DMA buffer
  ADC->ADC_RNCR=256;
  bufn=obufn=1;
  ADC->ADC_PTCR=1;
  ADC->ADC_CR=2;
}

void loop(){
  while(obufn==bufn); // wait for buffer to be full
  SerialUSB.write((uint8_t *)buf[obufn],512); // send it - 512 bytes = 256 uint16_t
  obufn=(obufn+1)&3;    
}

It reads ADC data at 1 million samples/sec and outputs the data to SerialUSB. (I've only tested it on Linux and most of the time it works, sometimes it is unreliable, I don't know why). Using GNU Radio I was then able to analyse the data stream and receive a long-wave radio signal, with an LC tuned circuit into A0 as an aerial.





This code is running smoother and with less jitter.
I am measuring jitter, by setting HIGH and LOW one Digital pin with an oscilloscope and the inline function:
Code:
inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}




BTW, I am controlling the sample rate by using the PRESCAL register in:
Code:
ADC->ADC_MR |= 0x2680; // these lines set free running mode on adc 7 (pin A0)  [PRESCAL at  50kHz]
Is there any other (better) way to  do it?

Actually, depending on if I am using one channel or two an the ADC, I need to setup a different PRESCAL, since there is only one ADC for all input pins:
Code:
if (channels_2)
  {
    ADC->ADC_MR |= 0x1280; // these lines set free running mode on adc 7 (pin A0) and adc 6(pin A1) PRESCAL at 50kHz
  }
  else
  {
    ADC->ADC_MR |= 0x2680; // these lines set free running mode on adc 7 (pin A0) PRESCAL at 50kHz
  }



On the other hand, what would the changes for two channels and 4 buffers? Is it possible to get a buffer for each channel?


Finally, I'm trying to measure  performance (the same way as jitter) and for  50kHz sample rate and 512 points, the time in the interrupt is 1.8us and the free time in the loop is 10.23ms (99.98% free!!).
For 1MHz, it is still around 1.8us against 256us (it is still 99.29% free), however more jitter at the beggining of the loop is appreciated.

I think it is because of the
Code:
while(obufn==bufn);
instruction


It is interesting the
Code:
SerialUSB.begin(0);
 while(!SerialUSB);

Does the computer (or other device) set the speed of the port?



Your spectrogram app looks great, keep up the good work!! Congratulations.

15  Products / Arduino Due / Re: speed of analogRead on: February 28, 2013, 02:55:45 pm
It's similar. Basically in free running mode the SAM3X cycles through all enabled channels. So we just enable 2 channels and wait for 2 conversions each time:
Code:
void setup() {
  Serial.begin(9600);
  int t=analogRead(0);

  ADC->ADC_MR |= 0x80; // these lines set free running mode on adc 7 and adc 6 (pin A0 and A1 - see Due Pinout Diagram thread)
  ADC->ADC_CR=2;
  ADC->ADC_CHER=0xC0; // this is (1<<7) | (1<<6) for adc 7 and adc 6                                     
}

void loop() {
  int t=micros();
  int q0=0,q1=0;
  int a0,a1;
  for(int i=0;i<500000;i++){
    while((ADC->ADC_ISR & 0x80)==0);
    while((ADC->ADC_ISR & 0x80)==0);// wait for two conversions
    a0=ADC->ADC_CDR[7];              // read data on A0 pin
    a1=ADC->ADC_CDR[6];              // read data on A1 pin
    q0+=a0;
    q1+=a1;
  }
  t=micros()-t;
  Serial.print("500000 pairs of conversions in ");Serial.print(t);Serial.println(" micros");
  Serial.print("A0 total:");Serial.println(q0);
  Serial.print("A1 total:");Serial.println(q1);
}

Obviously there's only one ADC which is shared by the 2 channels so the effective sample rate halves. This means that you will lose some accuracy, because internally the chip is having to switch between two different input signals 1 million times per second, and that won't be as good as it tracking the same input all the time like in the 1-channel example.

This is also working.
But I have some doubts about it:

- Why on the 
Code:
while((ADC->ADC_ISR & 0x80)==0);
    while((ADC->ADC_ISR & 0x80)==0);// wait for two conversions
line, you use the same pin of the ADC to compare?

Wouldn't it be:
Code:
while((ADC->ADC_ISR & 0x80)==0);
    while((ADC->ADC_ISR & 0x40)==0);// wait for two conversions
or better:
Code:
    while((ADC->ADC_ISR & 0xC0)==0);// wait for two conversions (pin A0[7]  and A1[6])
??

On the other hand, to reduce Jitter and free more time for "processing" in the loop function, could it enabling ADC interrupts be a solution?
Do you know how to accomplish this? I have seen ADC_IER register in the datasheet, but I'm pretty new with Arduino Due (just a couple of days) and don't know how to start.  smiley-red smiley-red

Thank you again

Pages: [1] 2