domingo, 19 de mayo de 2013

Mejorando la lectura analógica | Improving analog reading

En la anterior versión del analizador lógico cometí un error, deshabilitaba las interrupciones mientras leía el puerto analógico, esto producía errores en el reloj encargado de calcular el tiempo total.
In the previous version of the logic analyzer I made a mistake, I disabled the interrupts while reading the analog port, it causes errors in the clock that calculates the total time.


...

Serial.end();
noInterrupts();  
BeginRead();
interrupts();
Serial.begin(115200);
Serial.write(_data, DATA);

...

void ReadAnalog()
{

  t = micros();
  for(i=0; i<DATA; i+=2) // 2 cycles
  {

    /*** From wiring_analog.c ***/

    // start the conversion
    sbi(ADCSRA, ADSC); // 2 Cycles

    // ADSC is cleared when the conversion finishes
    while (bit_is_set(ADCSRA, ADSC)); // 13 * 16 Cycles

    // we have to read ADCL first; doing so locks both ADCL
    // and ADCH until ADCH is read.  reading ADCL second would
    // cause the results of each conversion to be discarded,
    // as ADCL and ADCH would be locked when it completed.
    _data[i+1] = ADCL; // 2 cycles
    _data[i]   = ADCH; // 1 cycle

    /****************************/
    
  }
  
  t = micros() - t;
  _data[DATA-4] = (byte)(t >> 24);
  _data[DATA-3] = (byte)(t >> 16);
  _data[DATA-2] = (byte)(t >> 8);
  _data[DATA-1] = (byte)(t);


}


Se puede calcular el error de la siguiente manera:

Tiempo de cada iteración:

    for: 2 ciclos
    sbi: 2 ciclos
    leer analógico: 208 ciclos (13 ciclos ADC * 16 prescaler)
    leer ADCL : 2 ciclos (1 para incrementar el índice y 1 para asignar al array)
    leer ADCH: 1 ciclo
    Total: 215 ciclos

Teníamos 898 iteraciones:


    898 iteraciones * 215 ciclos = 193070 ciclos
    193070 ciclos * 62.5 ns = 12.07 ms


Al deshabilitar las interrupciones y calcular el tiempo con la función "micros()" obteníamos aproximadamente 1200 us, unas mil veces menos de lo esperado.

Así que al final, he decidido no calcular el tiempo y leer 900 veces (1800 bytes), y actuar de la misma forma que en la lectura digital.
Error can be calculated as follows:

Time per iteration:

    for: 2 cycles
    sbi: 2 cycles
    analog read: 208 cycles (13 ADC cycles * 16 prescaler)
    read ADCL: 2 cycles (1 for increasing index and 1 to assign the array)
    read ADCH: 1 cycle
    Total: 215 cycles


We had 898 iterations:

    898 iterations * 215 cycles = 193070 cycles
    193070 cycles * 62.5 ns = 12.07 ms


By disabling interrupts and calculate the time using "micros()" we're getting about 1200 us, a thousand times less than expected.

So in the end, I decided not calculate the time and read 900 times (1800 bytes), and act at the same way as digital reading.





Descargas:
Downloads:

LogicAnalyzer.zip



No hay comentarios:

Publicar un comentario