Ritardo tra 1 e 2 microsecondi

Buona sera,
devo generare una rampa con pendenza abbastanza precisa intervallata da una pausa da 1 secondo, ed ho ottenuto buoni risultati collegando un vecchio DAC (il DA1280), pilotato sugli 8 bit più significativi, connesso alla porta L di arduino MEGA, e scrivendo velocemente il portL con i 256 valori in sequenza.

Lo sketch è il seguente:

void setup() {

     DDRL=B11111111;
}


void loop() {

     for(int y=255;y>-1;y--){
         PORTL=y;  
         delayMicroseconds(1);  //ritardo tra un campione ed il successivo del DAC, ovvero durata della rampa
     }
     PORTL=255;
     delay(1000); 
}

La durata di questa rampa è il mio problema, perchè con:

  • delayMicroseconds(1); la rampa dura 100µsec
  • delayMicroseconds(2); la rampa dura 300µsec
  • delayMicroseconds(3); la rampa dura 520µsec
  • delayMicroseconds(4); la rampa dura 800µsec
  • delayMicroseconds(5); la rampa dura 1000µsec
  • delayMicroseconds(6); la rampa dura 1400µsec
    (tempi misurati con oscilloscopio).

Vorrei ottenere anche valori intermedi, tipo 150, 200, 250, 300, 350 e così via, a step di CIRCA 50µsec

Cosa mi cosigliate? Pensavo di perdere un pò di tempo con qualche "operazione inutile", tipo somme o altro, da mettere dopo il delayMicroseconds(), ma prima vorrei la vostra opinione.
Molte grazie.

Buongiorno e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (ogni sezione del forum può avere regole diverse), dopo di che, come da suddetto regolamento, fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte verrebbero temporaneamente nascoste), quindi ti consiglio di farla al più presto. :wink:

Io avrei un'idea...

Ciao Guglielmo, questa cosa della presentazione mi ricordo di averla fatta tanto tempo fa; forse non è più valida e la devo rifare? grazie

Ciao @pautax ... purtroppo, se vai nel tuo profilo e gaurdi la tua attività, vedi tutti i tuoi post e ... in Italiano non ho trovato altro che questi pochi, quindi, SI grazie :slight_smile:

Guglielmo

E se non usi nessun delay quanto dura la rampa?

Ciao, Ale.

98 microsecondi

fatto, grazie

Io userei un generatore di corrente costante che carica un condensatore... No?...

Se no, devi regolare finemente il clock... Che dice il 328p se gli si toglie un clock ogni 50 o qualcosa del genere? Si arrabbia parecchio o è tollerante? :slight_smile:

no, perche devo generare rampe da 125nsec fino a 1,25 sec , abbastanza precise

Ma la risoluzione minima di delayMicroseconds() non e' qualcosa tipo 3 o 4 microsecondi, per il 328P ?

Comunque una rampa da 125nS la vedo dura.

volevo dire 125 microsecondi :slight_smile: scusa

Non so che cosa tu intenda per "abbastanza precisa", ma con i monostabili RC e si facevano generatori di barre PAL ben stabili, in cui con un trimmer si regolava l'ampiezza orizzontale... Se devi fare uno strumento di misura preciso, naturalmente, è diverso. Senza conoscere i dettagli è difficile dire di più.

Pautax, per tempistiche precise usa l'assembler, puoi integrarlo facilmente nel C, non dovrebbe essere difficile per te visto che sei cresciuto come me con l'assembler degli albori dei microprocessori

Allora 98us si consumano per il for e per l'assegnamento. In teoria con AVR che lavora a 16MHz un ciclo di clock dura 62.5ns (0.0625us).

Ci sono 256 assegnamenti, allora 98us / 256 = 0,382 (382ns) per ogni assegnamento. Se fosse così aggiungendo una assegnazione dovresti avere 98us x 2 = 196us. Ma non sarà così poiché non conosciamo il tempo impiegato per il ciclo for. Consideriamo anche che la variabile y è grande 16-bit e quindi ci vuole più tempo rispetto ad una variabile byte.

Comunque aggiungendo assegnamenti e aggiungendo:

asm("nop);

nel ciclo puoi verificare con l'oscilloscopio. Ogni istruzione "nop" dovrebbe essere eseguita in un solo ciclo di clock cioè 62.5ns. C'è da vedere se il clock è 16MHz precisi e costanti. Quindi due "nop" all'interno del ciclo significa 62.5ns x 2 = 125ns e così via.

Riguardo alle funzioni delay considera anche quelle della libreria avrlibc, queste.

Un altra strada potrebbe essere quella del timer 1 hardware, ma non ho idea se è possibile farlo contare e sollevare una IRQ ogni 488ns.

Magari riesci in qualche modo con AVR, oppure dovrai ricorrere a qualche altra scheda questa volta basata su ARM.

Ciao.

Grazie dei consigli, con i NOP ho risolto.
Queste sono le funzioni (ancora da trimmare leggermente), ma mi generano le rampe con i valori desiderati su NANO, port D.


void Nano75usec(void){
  for(int y=255;y>-1;y--){
    PORTD=y;   
  }  
}


void Nano140usec(void){
  for(int y=255;y>-1;y--){
    PORTD=y;
    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   
  }
}

void Nano200usec(void){
  for(int y=255;y>-1;y--){
    PORTD=y;
    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   

    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   
  }  
}

void Nano260usec(void){
  for(int y=255;y>-1;y--){
    PORTD=y;
    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   

    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   

    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   
  }
}

void Nano300usec(void){
  for(int y=255;y>-1;y--){
    PORTD=y;
    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   

    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");   

    asm("nop");   
    asm("nop");   
    asm("nop");   
    asm("nop");
       
    asm("nop");   
    asm("nop");   
    asm("nop");   

  }
}

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