Arduino FAST DAC

Ciao a tutti,

avrei bisogno di aiuto o chiarimenti sull'uso degli interrupt nel mio caso; sono giorni che ci sto sbattendo la testa senza venirne fuori;
il problema è questo; ho 2 arduino ( Arduino DuemilaNove e Mega 2560 ) in collegamento Master e Slave;
il primo il Duemilanove manda al Mega un valore int a blocchi di 4 bit ogni 20micro secondi e segnala al Mega che i bit sono caricati tramite un altro PIN che fa scattare;
l'interrupt sullo Slave ossia il Mega2560;
nella routine dello Slave recupero i 4 bit sul registro di porta PINA e dopo 4 interrupt ho la WORD ricostruita;
questa WORD la metto poi in un buffer circolare e sarà poi scritta dalla funzione di loop arduino appena ne avrà la possibilità:
funzione di interrupt:
void ISR_Nibble()
{
//questo shift è necessario per dare il peso giusto ai bit che arrivano
value+=((PINA >> 4)<<state);

if((state+=4)==16) //se state=16 cioè siamo all’ultimo blocco di 4 bit la WORD è ricostruita e viene scritta nel Buffer circolare
{
raw_data[(writeIdx++) % BLOCK_BUFFER]=value; //incrementa indice di scrittura e scrive valore su buffer circolare
value=state=0;
}
}

funzione loop:
void loop()
{

if(writeIdx>readIdx) //se l'indice di scrittura è maggiore di quello di scrittura si può scrivere il dato su file
{
readIdx++;
sprintf(buffer,"%ld %ld", readIdx, raw_data[ readIdx % BLOCK_BUFFER ]);
client.println(buffer);
}

}

il problema che ho è che le chiamate alla funzione di interrupt sembra che si accavallino in quanto nel file che esce leggo:

1 1
2 2
3 3
4 4
5 5
6 6
7 10
8 11
9 12
10 100 !! salto enorme
11 30 // qui ritorna a decrescere !! come è possibile? interrupt che si accavallano?

questo è il mio problema;
potete aiutarmi?

ciao,
ale

Secondo mè hai messo troppa roba nell'isr ed i tempi di esecuzione dei comandi poi danno l'effetto accavallamento..

Ciao grazie per la risposta!
ho visto con l oscilloscopio che la routine di servizio impiega
circa 50 microsecondi ma sta ancora nei tempi stabiliti;
il collo di bottiglia e' nel loop dove scrivo su rete; la scrittura
impiega 1.5 ms ossia 4kb al sec; come posso fare per ovviare?
il dac deve acquisire per 1 ora e non so come scaricare questi dati.

L' unica cosa che mi viene in mente é un FRAM. Per esempio il FM25256B

Si usa come un EEprom seriale esterno, ma si riesce a scrivere senza pause di programmazione.
Usa l' esempio http://www.arduino.cc/en/Tutorial/SPIEEPROM

programma con cui l' ho scritto:

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO 
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

byte eeprom_output_data;
byte eeprom_input_data=0;
byte clr;
unsigned int address=0;
byte daten=0; 

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

void setup()
{
  Serial.begin(9600);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  // SPCR = 01010000
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 rate (fastest)
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);    
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WREN); //write enable
  digitalWrite(SLAVESELECT,HIGH);
  delay(10);  
  Serial.print("starttime: ");
  Serial.println(micros());
  digitalWrite(SLAVESELECT,LOW);      // write 32kByte in sequence
  spi_transfer(WRITE);                      //write instruction
  address=0;
  spi_transfer((char)(address>>8));   //send MSByte address first
  spi_transfer((char)(address));        //send LSByte address
  // write 32KByte
  for (unsigned int I=0;I<32768;I++)
  {
    spi_transfer(I/256); //write data byte
  }  
  digitalWrite(SLAVESELECT,HIGH); //release chip  
  Serial.print("endtime: ");
  Serial.println(micros()); Serial.println();
  Serial.println("FRAM Write finish");
}

void loop()
{
  delay(5000); //pause for readability
}

riempie i 32kByte in ca 100mSec e percui ca 4µSecondi per Byte.
ciaso Uwe

e qua il programma per leggere il contenuto della FRAM:
ciao Uwe

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO 
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

byte eeprom_output_data;
byte eeprom_input_data=0;
byte clr;
unsigned int address=0;

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

byte read_eeprom(int EEPROM_address)
{
  //READ EEPROM
  int data;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(READ);                        //transmit read opcode
  spi_transfer((char)(EEPROM_address>>8));   //send MSByte address first
  spi_transfer((char)(EEPROM_address));      //send LSByte address
  data = spi_transfer(0xFF);                 //get data byte
  digitalWrite(SLAVESELECT,HIGH);            //release chip, signal end transfer
  return data;
}

void setup()
{
  Serial.begin(9600);
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH);         //disable device
  // SPCR = 01010000
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 rate (fastest)
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);  
}

void loop()
{
  Serial.print('\n',BYTE);
  for (unsigned int I=0;I<32768;I++)
  {
    eeprom_output_data = read_eeprom(I);
  Serial.print(eeprom_output_data,DEC);
  address++;
  if (address == 64)
  {Serial.print('\n',BYTE);
  address = 0;
  }
}  
delay(5000); //pause for readability
}

ciao!

scusa il ritardo! ti ringrazio per il suggerimento e soprattutto per il codice che mi hai postato, ma 32Kb non sono sufficienti
per acquisire 1 ora di seguito; una volta saturata la memoria avrei comunque il problema
di come scaricarla prima che arrivino nuovi dati;

di nuovo grazie mille!

ciao,
ale