speeding up analogread() at the Arduino Zero


hello,

i use 0 , looking faster analog reading times. found articles due (link), nothing zero. since i'm not verry µc experienced, take me lot time transfer.

but, google found thread in japanese forum, , including code, come 436µs 21µs analog reading time. maybe use someone:


code: [select]
void adcbooster()
{
  adc->ctrla.bit.enable = 0;                     // disable adc
  while( adc->status.bit.syncbusy == 1 );        // wait synchronization
  adc->ctrlb.reg = adc_ctrlb_prescaler_div64 |   // divide clock 64.
                   adc_ctrlb_ressel_12bit;       // result on 12 bits
  adc->avgctrl.reg = adc_avgctrl_samplenum_1 |   // 1 sample
                     adc_avgctrl_adjres(0x00ul); // adjusting result 0
  adc->sampctrl.reg = 0x00;                      // sampling time length = 0
  adc->ctrla.bit.enable = 1;                     // enable adc
  while( adc->status.bit.syncbusy == 1 );        // wait synchronization
} // adcbooster


int analogpin = 1;

unsigned long start_times[100];
unsigned long stop_times[100];
unsigned long values[100];


void setup() {
   adcbooster();                              //uncomment reading time without 'boost'
 
  serial.begin(9600);
  pinmode(analogpin, input);
}

void loop() {
    analogreadresolution(12);                 //analog resolution 12bit
    unsigned int i;

    for(i=0;i<100;i++) {
    start_times[i] = micros();
    values[i] = analogread(analogpin);
    stop_times[i] = micros();
    }

    // print out results
    serial.println("\n\n--- results ---");
    for(i=0;i<100;i++) {
    serial.print(values[i]);
    serial.print(" elapse = ");
    serial.print(stop_times[i] - start_times[i]);
    serial.print(" us\n");
    }
   
    }



the datasheet of atmel sam d21e mentions readingspeed of 350ks, there might still room more optimisations reach ~3µs, making run in free running mode?

i found more code used example here.



 

hi,

you can use adc dma fill buffer adc samples. method, takes around 2us measure 1 sample. depending of needs, useful.

check thread more information : https://forum.arduino.cc/index.php?topic=346761.0

code: [select]
// adcdma
//  analog a1
//   could use dac 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];     

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; // 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() {
    // on 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 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 adc free
}


void adc_init(){
  analogread(adcpin);  // 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 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(a0,64);   // test dac
adc_init();
dma_init();
}

void loop() {
uint32_t t;

t = micros();
adc_dma(adcbuf,hwords);
while(!dmadone);  // await dma done isr
t = micros() - t;
serial.print(t);  serial.print(" us   ");
serial.println(adcbuf[0]);
delay(2000);
}


Arduino Forum > Products > Arduino Zero (Moderator: cmaglie) > speeding up analogread() at the Arduino Zero


arduino

Comments

Popular posts from this blog

DHT11 Time out error using v0.4.1library

Sketch upload fails with Java error (___REMOVE___/bin/avrdude)!

Arduino Uno + KTY81/210 temperature sensor