Ultrasonic Transducer Data collection

Hi does anyone know if this code is capable of being used for ultrasound data collection? If so, how would i go about increasing the sampling rate? I would like for it to be close to 2 samples per microsecond. I am also getting some noise in the data, but that may be because of the low sampling rate. Please let me know thanks

// adcdma
// analog A1
// could use DAC to provide input voltage A0
// http://www.atmel.com/Images/Atmel-42258-ASF-Manual-SAM-D21_AP-Note_AT07627.pdf pg 73

#define ADCPIN A1
#define HWORDS 1024
uint16_t adcbuf[HWORDS];

#include <SPI.h>
#include <SD.h>

const int chipSelect = SDCARD_SS_PIN;

typedef struct {
uint16_t btctrl;
uint16_t btcnt;
uint32_t srcaddr;
uint32_t dstaddr;
uint32_t descaddr;
} dmacdescriptor ;
volatile dmacdescriptor wrb[12] attribute ((aligned (16)));
dmacdescriptor descriptor_section[12] attribute ((aligned (16)));
dmacdescriptor descriptor attribute ((aligned (16)));

static uint32_t chnl = 0; // DMA channel
volatile uint32_t dmadone;

void DMAC_Handler() {
// interrupts DMAC_CHINTENCLR_TERR DMAC_CHINTENCLR_TCMPL DMAC_CHINTENCLR_SUSP
uint8_t active_channel;

// disable irqs ?
__disable_irq();
active_channel =  DMAC->INTPEND.reg & DMAC_INTPEND_ID_Msk; // get channel number
DMAC->CHID.reg = DMAC_CHID_ID(active_channel);
dmadone = DMAC->CHINTFLAG.reg;
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL; // clear
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP;
__enable_irq();

}

void dma_init() {
// probably on by default
PM->AHBMASK.reg |= PM_AHBMASK_DMAC ;
PM->APBBMASK.reg |= PM_APBBMASK_DMAC ;
NVIC_EnableIRQ( DMAC_IRQn ) ;

DMAC->BASEADDR.reg = (uint32_t)descriptor_section;
DMAC->WRBADDR.reg = (uint32_t)wrb;
DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf);

}

void adc_dma(void *rxdata, size_t hwords) {
uint32_t temp_CHCTRLB_reg;

DMAC->CHID.reg = DMAC_CHID_ID(chnl);
DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;
DMAC->SWTRIGCTRL.reg &= (uint32_t)(~(1 << chnl));
temp_CHCTRLB_reg = DMAC_CHCTRLB_LVL(0) |
  DMAC_CHCTRLB_TRIGSRC(ADC_DMAC_ID_RESRDY) | DMAC_CHCTRLB_TRIGACT_BEAT;
DMAC->CHCTRLB.reg = temp_CHCTRLB_reg;
DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK ; // enable all 3 interrupts
dmadone = 0;
descriptor.descaddr = 0;
descriptor.srcaddr = (uint32_t) &ADC->RESULT.reg;
descriptor.btcnt =  hwords;
descriptor.dstaddr = (uint32_t)rxdata + hwords*2;   // end address
descriptor.btctrl =  DMAC_BTCTRL_BEATSIZE_HWORD | DMAC_BTCTRL_DSTINC | DMAC_BTCTRL_VALID;
memcpy(&descriptor_section[chnl],&descriptor, sizeof(dmacdescriptor));

// start channel
DMAC->CHID.reg = DMAC_CHID_ID(chnl);
DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;

}

static inline void ADCsync() attribute((always_inline, unused));
static void ADCsync() {
while (ADC->STATUS.bit.SYNCBUSY == 1); //Just wait till the ADC is free
}

void adc_init(){
analogRead(ADCPIN); // do some pin init pinPeripheral()
ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC
ADCsync();
//ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 2.2297 V Supply VDDANA
//ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val; // Gain select as 1X
ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val; // default
ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val;
ADCsync(); // ref 31.6.16
ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ADCPIN].ulADCChannelNumber;
ADCsync();
ADC->AVGCTRL.reg = 0x00 ; //no averaging
ADC->SAMPCTRL.reg = 0x00; ; //sample length in 1/2 CLK_ADC cycles
ADCsync();
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV16 | ADC_CTRLB_FREERUN | ADC_CTRLB_RESSEL_10BIT;
ADCsync();
ADC->CTRLA.bit.ENABLE = 0x01;
ADCsync();
}

void setup(){
Serial.begin(9600);
analogWriteResolution(10);
analogWrite(A1,64); // test with DAC
adc_init();
dma_init();

while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
Serial.print("Initializing SD card...");

// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
while (1);
}
Serial.println("card initialized.");
}

}

void loop() {
uint32_t t;

t = micros();
adc_dma(adcbuf,HWORDS);
while(!dmadone); // await DMA done isr
t = micros() - t;

// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.txt", FILE_WRITE);

// if the file is available, write to it:
if (dataFile) {
dataFile.print(t);
dataFile.print(" us ");
dataFile.println(adcbuf[0]);
dataFile.close();
// print to the serial port too:
Serial.print(t);
Serial.print(" us ");
Serial.println(adcbuf[0]);
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}

}

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

Please edit your post to add code tags. It would help if you tell us about the ultrasonic transducer and amplifier (post a schematic).

I would like for it to be close to 2 samples per microsecond.

Why?

According to the datasheet, the ADC can only run up to 500k samples/sec which is 2 microseconds per sample and you want more than that.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.