Ardutester - Arduino Component Tester (INCOMPLETO)

pighixxx: Una richiesta agli esperti:

Quanto è da considerare affidabile il delay() di Arduino? (Idem per il delayMicroseconds())

Affidabile? Forse intendi "preciso". Quanto è preciso il risonatore ceramico esterno. Molto poco. In genere si parla di +/- 10%. Se però stai pensando allo standalone dell'ArduTester, devi senz'altro metterci un quarzo, ne guadagni tantissimo in precisione appunto.

Si volevo intendere "preciso". Cosa ne dici della soluzione di Markus Reschke?

void MilliSleep(uint16_t Time)
{
  uint32_t               Cycles;        /* timer cycles */
  uint8_t                Timeout;       /* compare value */
  uint8_t                Mode;          /* sleep mode */

  /*
   *  calculate stuff
   */

  /*
      Using timer prescaler of 1024 (maximum):
        MCU frequency  1MHz    8MHz   16MHz
        timer cycle    1024µs  128µs  64µs

      We don't compensate the binary to decimal offset and also not the time
      required for the processing loop, because it would make things much more
      complicated and we don't need exact timing here.
   */

  /* calculate required timer cycles (prescaler 1024) */
  Cycles = Time * (CPU_FREQ / 1000000);      /* timer cycles based on MCU frequency */


  /*
      After returning from the power down or power save sleep modes the
      main oscillator needs following start-up times to stabilize:
      - crystal oscillator:  16k cycles
      - ceramic resonator:   1k or 256 cycles
      - internal RC osc.:    6 cycles

      In power save mode the external oscillator should be turned off. But if
      timer2 is running in synchronous mode the oscillator keeps running. Even
      though we have to consider the start-up time, Weird, isn't it?
   */

  Mode = Config.SleepMode;              /* get requested sleep mode */

  /* compensate oscillator start-up */
  if (Mode == SLEEP_MODE_PWR_SAVE)
  {
    uint32_t        Value;

    Value = Cycles / 256;               /* calculate loop runs */
    Value++;                            /* fix offset by division */
    /* multiply with startup cycles equivalent to timer cycles */
    Value *= (OSC_STARTUP / 1024);      /* overhead cycles */

    if (Cycles > Value)            /* we are able to compensate */
    {
      Cycles -= Value;                  /* subtract overhead cycles */
    }
    else                           /* no way to compensate */
    {
      /* idle mode doesn't require oscillator start-up after wake-up */ 
      Mode = SLEEP_MODE_IDLE;           /* change sleep mode to Idle */
    }
  }


  /*
   *  setup timer
   */

  TCCR2B = 0;                      /* disable timer */
  TCCR2A = (1 << WGM21);           /* set CTC mode */
  TIMSK2 = (1 << OCIE2A);          /* enable interrupt for OCR0A match */

  set_sleep_mode(Mode);            /* set sleep mode */


  /*
   *  processing loop
   *  - sleep for several intervals until requested time is reached
   */

  while (Cycles > 0)
  {
    wdt_reset();              /* reset watchdog */

    /* get timeout */
    if (Cycles > 255) Timeout = 255;
    else Timeout = Cycles;
    Cycles -= Timeout;
    Timeout--;                     /* interrupt is triggered by cycle after match */
    /* todo: what happens if Timeout is 0? */

    /* update timer */
    TCNT2 = 0;                     /* set counter to 0 */
    OCR2A = Timeout;               /* set value to compare with (timeout) */

    /* sleep */
    /* enable timer by setting clock prescaler to 1024 */
    TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20);
    sei();                                   /* enable interrupts */
    sleep_mode();                            /* and sleep */    

    /* after wakeup */
    cli();                         /* disable interrupts */
  }
}

Il problema standalone sarà di Michele XD

Fermo restando che in questo algoritmo lui fa anche altre cose, tipo controlla se è appena uscito da sleep, si muove in base ai fuse, perche gestisce diverse vel clock, ed altro, alla fine USA cm un metodo bloccante e deve farlo perche non ha il magico delay a disposizione, resta cmq il discorso precisione perché c'è poco da fare. La domanda quindi è per cosa usi questo delay ? Influirà e di quanto sul risultato del valore dei componenti ? Il resto credo a noi non serva visto che si usa su un Arduino standard, quindi clock fisso.

In questo codice mi pare manchi il setup del watchdog. E poi non ho capito cosa stia facendo con il timer 2, il watchdog, e lo sleep. Sta cercando di fare un millis che vada anche con il chip in sleep?

Ma tu che necessità hai?

I Delay sono critici ed importanti per una buona lettura del componente. Non che adesso non sia preciso ma più i delay sono precisi più le letture sono accurate.

@Leo Da quello che ho capito fa un delay con il chip in sleep, utilizzando l'oscillatore interno. utilizzando in qualche maniera lo sleep.

edit Quasi quasi gli scrivo.

Pighi, non stare a preoccuparti molto di questa cosa. Con uno standalone con un quarzo esterno al posto del risonatore dell'Arduino avrai una precisione 10 volte maggiore nei tempi, e di conseguenza nei delay, che ti ricordo sono basati sul calcolo dell'overflow del timer 0. Quindi un qualcosa che prende la frequenza dal sistema. Ora, sull'Arduino, tale fonte di clock è appunto quel risonatore sulla schedina. Ma con un quarzo migliora molto.

E' perché mi avanzava un po' di tempo :D

A parte gli scherzi, sto rifinendo il tutto e ci tenevo a fare 'sti ritocchini. Nel frattempo ho sostituito i vari delay nel firmware con delle funzioni in modo da poterli aggiornare quando si vuole.

La presenza del quarzo era il motivo per cui volevo testare la 2009. Ma li c'è il problema del led e resistenza sul pin 13 che sballa le misure.

Promuoverò una campagna per rimuovere il led sul pin 13 dall’Arduino :grin:

http://www.instructables.com/id/Remove-LED-from-Arduino-Board/

Non ho capito come mai il Led pin 13 causa problemi O.o

Fino alla versione R2 della Uno e sulla precedente 2009 il led è alimentato direttamente dal pin con una resistenza. Quindi consuma corrente erogata dal pin. Sulla Uno R3 è invece pilotato da un op-amp per cui non disturba più

PaoloP: La presenza del quarzo era il motivo per cui volevo testare la 2009. Ma li c'è il problema del led e resistenza sul pin 13 che sballa le misure.

Non conosco bene come funziona l'Ardutester ma immagino che cambiare pin non si possa, vero? :-)

Come suggerito da Paolo ci sarebbe la possibilità di utilizzare la PORTD invece della PORTB ma sono in qualsiasi caso dolori. :D

La comodità della porta B è che i pin mappati sono quelli che vanno dall’8 al 13, mentre per la porta D sono quelli dall’1 al 7. Nel secondo caso, manipolando la porta si dovrebbe aggiustare sempre il tiro quando si usa la seriale. Quindi lettura dello stato dei pin della seriale e riscrittura dell’intera porta compresi due pin iniziali. Giusto? ma se cambia lo stato della seriale tra la lettura e la scrittura?
Insomma… dolori.

Sì ma con PORTB avete PB6 e PB7 occupati dal quarzo/risonatore, sull'Arduino. Per cui in teoria voi dovreste usare solo 6 pin di quella porta. Se usate PORTD e saltate PD0 e PD1 (i pin della seriale) avete sempre 6 pin liberi.

E sei ne servono. XD Tanti quanti le resistenze di precisione.

Beh, allora non vedo il problema a passare ai pin D2..D7 al posto di D9..D13.

Forse perchè mi ha fatto paura questa nota:

The resistors [u]must[/u] be connected to the lower 6 pins of the port

ma nulla vieta che si possa fare un tentativo. (Appena finito tutto) :D

Quella nota si riferirà al fatto che userà l'accesso diretto ai pin per pilotare le resistenze. Ma se è questo il problema, basta fare uno shift di 2 posizioni a sinistra del dato da inserire in PORTD prima di effettuare la scrittura. Esempio (premetto che non conosco il vostro codice): se prima avevate PORTB = valore dopo basta fare PORTD = (valore << 2)

leo72:
Pighi, non stare a preoccuparti molto di questa cosa.
Con uno standalone con un quarzo esterno al posto del risonatore dell’Arduino avrai una precisione 10 volte maggiore nei tempi, e di conseguenza nei delay, che ti ricordo sono basati sul calcolo dell’overflow del timer 0. Quindi un qualcosa che prende la frequenza dal sistema. Ora, sull’Arduino, tale fonte di clock è appunto quel risonatore sulla schedina. Ma con un quarzo migliora molto.

ovviamente andrò anche oltre il quarzo Leo XD devo tirare fuori qualcosa che non c’entri nulla con lo shield, altrimenti non vale la pena…

PaoloP: perché non mi hai risposto? la mia era una battuta ma anche la richiesta di “vedere” le tue R, non vorrei che avendo preso resistenze di precisione a 5-6 colori tu stia usando valori che non c’entrano nulla con quelliu richiesti, ciò spiegherebbe il fatto che non vanno nemmeno sui circuiti degli altri, non ti pare?