doppiozero:
Provando a salvare 499 letture di accelerazioni in dati grezzi (2 byte) dell'asse z ho ottenuto:
Per scrivere un byte sulla EEPROM del 328 servono 3.4 ms in modo 0 (erase + write), oppure solo 1.8 ms in modo 2 (write only), se usi il modo 2 si presuppone che la EEEPROM sia stata preventivamente cancellata.
Facendo due conti se devi scrivere un totale di 1000 byte e usi il modo 2 ci vogliono almeno 3.4 secondi per completare l'operazione.
Tale tempo vale anche per le EEPROM I2C in quanto dovuto alla tecnologia usata, è risaputo che in scrittura le EEPROM sono lente.
Per capire il tempo minimo possibile serve sapere anche la frequenza di campionamento dei dati, 500 letture possono richiedere anche 5 secondi se ne fai 100 al secondo.
Se ti basta accumulare 500 letture non c'è problema a farlo in ram, non si rovina e non si consuma, basta che predefinisci un array composto da valori int di 500 celle, in questo modo ad ogni nuovo ciclo sovrascrivi le vecchie letture, meglio se le azzeri prima, e sei sicuro di non sforare mai la ram.
Se ti serve accumulare più di 500 letture, senza limitare la velocità di campionamento per via della lentezza della EEPROM, puoi benissimo usare una RAM SPI esterna.
La SPI è molto veloce come porta, come minimo riesci a trasferire più di 1000 letture al secondo senza interferire col campionamento, però non è semplicissima da gestire.
Ovvio che la vedi come un supporto esterno, come potrebbe essere una SD, solo molto più veloce e NON come parte della SRAM della MCU
ah ok, quindi dovrei in qualche modo dire all'atmega "scrivi sulla SRAM esterna" mentre se fosse un'estensione non avrei modifiche da fare allo sketch?
Allora teoricamente dovresti farcela.
Tutto dipende dalla velocità della SD e da come scrivi lo sketch.
allora vedo di reperire una sd da sacrificare (non ho la shield quindi utilizzerei metodi grezzi )
p.s. Con la SRAM se spegni perdi i dati, con la SD no.
si lo so ma mi servirebbe come buffer temporaneo, dopo salverei su eeprom o altro con calma
credo di usare il modo 0. Vi posto gli sketch che uso così magari se avete voglia li guardate.
Ho notato che scrivendo su SRAM le letture sono accoppiate a 2 a 2, cioè sembra che la velocità di lettura sia maggiore del refresh dei registri interni dell'accelerometro. Immagino che sia il limite dell'mpu
si si grazie comunque ho tagliato la testa al toro prendendo una scheda per le SD su ebay.
Nel frattempo che aspetto la consegna ho approfondito questo
3.4 ms in modo 0 (erase + write), oppure solo 1.8 ms in modo 2 (write only),
e ho modificato lo sketch che usavo per la eeprom interna.
Potreste darci un'occhiata? Non ho mai fatto prima modifiche ai registri e vorrei evitare danni. In pratica nel setup prima cancello la eeprom poi modifico il registro per scrivere solamente.
#include<Wire.h>
#include<EEPROM.h>
byte flag = LOW; // utilizzato per uscire dai cicli
int address = 0; // indirizzo della eeprom esterna
unsigned long int temposcrittura; // contiene il valore del tempo necessario a scrivere tot celle di eeprom
/////////////////// ACCELEROMETRO //////////////////////
const int MPU = 0x68; // I2C address of the MPU-6050
int AcZ; // contiene valori raw dell'accelerazione
void setup() {
Serial.begin(9600);
delay(1000);
Wire.begin();
///////////////////// EEPROM CLEAR ///////////////////////
Serial.println("eeprom clear - start");
for (int i = 0; i < 1024; i++) {
EEPROM.write(i, 0);
}
Serial.println("eeprom clear - stop");
///////////////////// EEPROM WRITE ONLY ///////////////////////
EECR |= (1<<EEPM1);
/////////////////// ACCELEROMETRO //////////////////////
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.println("Inizio campionamento");
}
void loop() {
temposcrittura = millis();
if (flag == LOW) {
/////////////////// ACCELEROMETRO //////////////////////
Wire.beginTransmission(MPU); //Begin a transmission to the I2C slave device with the given address. Subsequently, queue bytes for transmission with the write() function and transmit them by calling endTransmission().
Wire.write(0x3F); // starting with register 0x3F (ACCEL_ZOUT_H) /// Writes data from a slave device in response to a request from a master, or queues bytes for transmission from a master to slave device (in-between calls to beginTransmission() and endTransmission()).
Wire.endTransmission(false); //Ends a transmission to a slave device that was begun by beginTransmission() and transmits the bytes that were queued by write(). If true, endTransmission() sends a stop message after transmission, releasing the I2C bus.If false, endTransmission() sends a restart message after transmission. The bus will not be released, which prevents another master device from transmitting between messages. This allows one master device to send multiple transmissions while in control.The default value is true.
Wire.requestFrom(MPU, 2, true); // request a total of 2 registers // Used by the master to request bytes from a slave device. The bytes may then be retrieved with the available() and read() functions.
AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Wire.endTransmission(true);
// Serial.print(" | AcZ = "); Serial.println(AcZ);
}
//////////////////// EEPROM INTERNA - SCRITTURA /////////////////////
if (address <= 996 && flag == LOW ) {
EEPROM.put(address, AcZ );
address += sizeof(int);
}
//////////////////// EEPROM INTERNA - LETTURA /////////////////////
if (address > 996 && flag == LOW ) {
Serial.print("Tempo Scrittura = "); Serial.println(temposcrittura); // verifico tempo per scrivere tot valori sulla eeprom
delay(2000);
Serial.print("Valori campionati = "); Serial.println(address / 2);
delay(2000);
Serial.println("Inizio Lettura");
flag = HIGH;
address = 0;
delay(2000);
}
if (address <= 996 && flag == HIGH) {
EEPROM.get(address, AcZ);
Serial.print(address); Serial.print(" = "); Serial.println(AcZ);
address += sizeof(int);
delay(100);
}
}
Secondo me tenendo separati i due dati è di un nano secondo più veloce.
#include<Wire.h>
#include<EEPROM.h>
byte flag = LOW; // utilizzato per uscire dai cicli
int address = 0; // indirizzo della eeprom esterna
unsigned long int temposcrittura; // contiene il valore del tempo necessario a scrivere tot celle di eeprom
/////////////////// ACCELEROMETRO //////////////////////
const int MPU = 0x68; // I2C address of the MPU-6050
byte AcZH;
byte AcZL;
// int AcZ; // contiene valori raw dell'accelerazione
void setup() {
Serial.begin(9600);
delay(1000);
Wire.begin();
///////////////////// EEPROM CLEAR ///////////////////////
Serial.println("eeprom clear - start");
for (int i = 0; i < 1024; i++) {
EEPROM.write(i, 0);
}
Serial.println("eeprom clear - stop");
///////////////////// EEPROM WRITE ONLY ///////////////////////
EECR |= (1 << EEPM1);
/////////////////// ACCELEROMETRO //////////////////////
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.println("Inizio campionamento");
}
void loop() {
temposcrittura = millis();
if (flag == LOW) {
/////////////////// ACCELEROMETRO //////////////////////
Wire.beginTransmission(MPU); //Begin a transmission to the I2C slave device with the given address. Subsequently, queue bytes for transmission with the write() function and transmit them by calling endTransmission().
Wire.write(0x3F); // starting with register 0x3F (ACCEL_ZOUT_H) /// Writes data from a slave device in response to a request from a master, or queues bytes for transmission from a master to slave device (in-between calls to beginTransmission() and endTransmission()).
Wire.endTransmission(false); //Ends a transmission to a slave device that was begun by beginTransmission() and transmits the bytes that were queued by write(). If true, endTransmission() sends a stop message after transmission, releasing the I2C bus.If false, endTransmission() sends a restart message after transmission. The bus will not be released, which prevents another master device from transmitting between messages. This allows one master device to send multiple transmissions while in control.The default value is true.
Wire.requestFrom(MPU, 2, true); // request a total of 2 registers // Used by the master to request bytes from a slave device. The bytes may then be retrieved with the available() and read() functions.
// AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
AcZH = Wire.read();
AcZL = Wire.read();
Wire.endTransmission(true);
// Serial.print(" | AcZ = "); Serial.println(AcZ);
}
//////////////////// EEPROM INTERNA - SCRITTURA /////////////////////
if (address <= 996 && flag == LOW ) {
EEPROM.write(address, AcZH);
EEPROM.write(address + 1, AcZL);
// EEPROM.put(address, AcZ );
// address += sizeof(int);
address += 2;
}
//////////////////// EEPROM INTERNA - LETTURA /////////////////////
if (address > 996 && flag == LOW ) {
Serial.print("Tempo Scrittura = "); Serial.println(temposcrittura); // verifico tempo per scrivere tot valori sulla eeprom
delay(2000);
Serial.print("Valori campionati = "); Serial.println(address / 2);
delay(2000);
Serial.println("Inizio Lettura");
flag = HIGH;
address = 0;
delay(2000);
}
if (address <= 996 && flag == HIGH) {
AcZH = EEPROM.read(address);
AcZL = EEPROM.read(address + 1);
// EEPROM.get(address, AcZ);
Serial.print(address); Serial.print(" = "); // Serial.println(AcZ);
Serial.println(AcZH << 8 | AcZL);
// address += sizeof(int);
address += 2;
delay(100);
}
} // End Loop
voglio fare un po di misure su uno di questi il mio sarà mooolto più spartano.
comunque 500 letture** in 2 decimi di secondo mi bastano e avanzano, il mio problema era avere abbastanza memoria e abbastanza veloce da salvare dati per almeno 4 secondi.
Al di là del progetto che non è nulla di serio ero curioso di vedere il limite dell'atmega328 e di esercitarmi un po' su eeprom e memorie varie
** è il limite dell'mpu6050, non so se posso aumentarle, devo guardare meglio il datasheet
intanto volevo salvarle, un passo per volta certo sarebbe fico fare un sistema di telemetria real time che magari trasmetta direttamente su pc ma intanto vado con calma
@BaBBuino darò un'occhiata anche alle Winbond, grazie