Mettere dati in array

Salve a tutti. Sto lavorando al mio primo progetto in Arduino, quindi chiedo scusa in anticipo se la domanda può risultare sciocca.

Sto cercando di mettere dei dati presi da un accelerometro (l’LSM303DLH) in un array. Quello che vorrei ottenere è che dopo un certo numero di dati salvati, Arduino mandi l’array di dati sulla porta seriale per mostrarli.

Questo è il codice di partenza.

/*
The sensor outputs provided by the library are the raw 16-bit values
obtained by concatenating the 8-bit high and low accelerometer and
magnetometer data registers. They can be converted to units of g and
gauss using the conversion factors specified in the datasheet for your
particular device and full scale setting (gain).

Example: An LSM303D gives a magnetometer X axis reading of 1982 with
its default full scale setting of +/- 4 gauss. The M_GN specification
in the LSM303D datasheet (page 10) states a conversion factor of 0.160
mgauss/LSB (least significant bit) at this FS setting, so the raw
reading of -1982 corresponds to 1982 * 0.160 = 317.1 mgauss =
0.3171 gauss.

In the LSM303DLHC, LSM303DLM, and LSM303DLH, the acceleration data
registers actually contain a left-aligned 12-bit number, so the lowest
4 bits are always 0, and the values should be shifted right by 4 bits
(divided by 16) to be consistent with the conversion factors specified
in the datasheets.

Example: An LSM303DLH gives an accelerometer Z axis reading of -16144
with its default full scale setting of +/- 2 g. Dropping the lowest 4
bits gives a 12-bit raw value of -1009. The LA_So specification in the
LSM303DLH datasheet (page 11) states a conversion factor of 1 mg/digit
at this FS setting, so the value of -1009 corresponds to -1009 * 1 =
1009 mg = 1.009 g.
*/

#include <Wire.h>
#include <LSM303.h>

LSM303 compass;

char report[80];

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  compass.init();
  compass.enableDefault();
}

void loop()
{
  compass.read();

  snprintf(report, sizeof(report), "A: %6d %6d %6d    M: %6d %6d %6d",
    compass.a.x, compass.a.y, compass.a.z,
    compass.m.x, compass.m.y, compass.m.z);
  Serial.println(report);

  delay(100);
}

Stavo pensando di mettere un contatore e un ciclo if (se la lettura è minore del numero di dati che voglio continua a prendere dati, altrimenti manda l’array di dati alla seriale per mostrarli.) Il problema è che non so davvero come fare visto che come ho già detto sono un novellino in materia.

Grazie in anticipo a tutti coloro che mi possono/vogliono aiutare.

Benvenuto. :) Ti invitiamo a presentarti qui: http://forum.arduino.cc/index.php?topic=113640.0 e a leggere il regolamento: http://forum.arduino.cc/index.php?topic=149082.0 Viene anche spiegato come postare le informazioni e il codice.

Per la domanda, io non ho capito quel che vuoi fare. In questo momento il tuo codice legge e spedisce sulla seriale la stringa che tu crei. Non capisco il problema. Troppi dati spediti su seriale? Tieni conto che i dati che ottieni sono 6 numeri (int, long ?) perciò hai bisogno di 6 array. E un contatore unico che inizializzi a 0. Dopo ogni compass.read() scrivi i 6 numeri nei 6 array e aumenti il contatore. Se il contatore (if) è maggiore di un certo numero allora spedisci e il contatore lo rimetti a 0. Logicamente il contatore deve andare da 0 a un numero uguale alla dimensione degli array. Ma ATTENZIONE a quanti elementi vuoi memorizzare. Ogni int = 2 byte se long addirittura 4 byte. Per 6 numeri !!! La SRAM di Arduino Uno è limitata a 2Kb

Grazie per la tua risposta, scusami se non mi sono presentato. =)

Ho letto anche il regolamento, mi pare che la domanda sia nella sezione giusta. Se ho toppato qualcosa nel porre la domanda o l'uso delle tag dimmelo pure e vedrò di correggere il tutto. ^^

Quel codice crea già una collezione di dati nella variabile report.

snprintf(report, sizeof(report), "A: %6d %6d %6d    M: %6d %6d %6d",
    compass.a.x, compass.a.y, compass.a.z,
    compass.m.x, compass.m.y, compass.m.z);

Questo codice converte i numeri a.x, a.y a.z, m.x, m.y, m.z in caratteri ASCII, in cui ogni rappresentazione ASCII a.x ecc è composta da massimo 6 caratteri. 6 caratteri x 6 dati = 36 caratteri, report è grande 80 caratteri, quindi basterebbe contare portare la dimenzione di report da 80 a 409 per poter collezionare 8 letture e poi spedirle.

char report[409];
// char *report_ptr;   // qui ho commesso l'errore di non inizializzare il puntatore, la riga seguente corregge il problema
char *report_ptr = report; // è un puntatore a carattere

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  compass.init();
  compass.enableDefault();
}

void loop()
{
  compass.read();
  for (byte i = 0; i<8; i++) {
    snprintf(report_ptr+(i*51), sizeof(report), "A: %6d %6d %6d    M: %6d %6d %6d\n",
    compass.a.x, compass.a.y, compass.a.z,
    compass.m.x, compass.m.y, compass.m.z);
  }
  Serial.println(report);

  delay(100);
}

Attenzione a report_ptr+(i*51), 51 si ricava da 6x6 + la lunghezza della stringa “A: %6d %6d %6d M: %6d %6d %6d\n” che equivale a 15 caratteri = 36 + 15 = 51.
Attenzione anche alla parte finale della stringa di formattazione in cui ho aggiunto un new line finale \n.

Stampera qualcosa di simile a:

A:     10     20     30    M:     40     50     60
A:     10     20     30    M:     40     50     60
A:     10     20     30    M:     40     50     60
A:     10     20     30    M:     40     50     60
A:     10     20     30    M:     40     50     60
A:     10     20     30    M:     40     50     60
A:     10     20     30    M:     40     50     60
A:     10     20     30    M:     40     50     60

Ovviamente con i numeri ricavati da compass.

Se modifichi la stringa di formattazione devi ricontare i caratteri e allora potrebbe essere utile:
const char ftmString = “A: %6d %6d %6d M: %6d %6d %6d\n”;
E ricavare la lunghezza della stringa con strlen(fmtString) che però ritorna 52, quindi al posto di 51
si scriverà report_ptr+(i*(strlen(fmtString) - 1))

Oppure si possono collezionare i dati in array di struct e spedirli raw, saranno meno comprensibili a noi umani
ma si impiegheranno minori risorse hardware.

Ciao.

nid69ita:
Benvenuto. :slight_smile:
Ti invitiamo a presentarti qui: http://forum.arduino.cc/index.php?topic=113640.0
e a leggere il regolamento: http://forum.arduino.cc/index.php?topic=149082.0
Viene anche spiegato come postare le informazioni e il codice.

Per la domanda, io non ho capito quel che vuoi fare. In questo momento il tuo codice legge e spedisce sulla seriale la stringa che tu crei. Non capisco il problema. Troppi dati spediti su seriale?
Tieni conto che i dati che ottieni sono 6 numeri (int, long ?) perciò hai bisogno di 6 array.
E un contatore unico che inizializzi a 0. Dopo ogni compass.read() scrivi i 6 numeri nei 6 array e aumenti il contatore.
Se il contatore (if) è maggiore di un certo numero allora spedisci e il contatore lo rimetti a 0.
Logicamente il contatore deve andare da 0 a un numero uguale alla dimensione degli array.

Quello che vorrei fare è inserire i dati letti in diversi array (uno per numero insomma), ad esempio di 500 elementi e poi visualizzarli sulla porta seriale.

MauroTec:
Quel codice crea già una collezione di dati nella variabile report.

snprintf(report, sizeof(report), "A: %6d %6d %6d    M: %6d %6d %6d",

compass.a.x, compass.a.y, compass.a.z,
    compass.m.x, compass.m.y, compass.m.z);



Questo codice converte i numeri a.x, a.y a.z, m.x, m.y, m.z in caratteri ASCII, in cui ogni rappresentazione ASCII a.x ecc è composta da massimo 6 caratteri. 6 caratteri x 6 dati = 36 caratteri, report è grande 80 caratteri, quindi basterebbe contare portare la dimenzione di report da 80 a 409 per poter collezionare 8 letture e poi spedirle.



char report[409];
char *report_ptr; // è un puntatore a carattere

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  compass.init();
  compass.enableDefault();
}

void loop()
{
  compass.read();
  for (byte i = 0; i<8; i++) {
    snprintf(report_ptr+(i*51), sizeof(report), “A: %6d %6d %6d    M: %6d %6d %6d\n”,
    compass.a.x, compass.a.y, compass.a.z,
    compass.m.x, compass.m.y, compass.m.z);
  }
  Serial.println(report);

delay(100);
}



Attenzione a report_ptr+(i*51), 51 si ricava da 6x6 + la lunghezza della stringa "A: %6d %6d %6d M: %6d %6d %6d\n" che equivale a 15 caratteri = 36 + 15 = 51.
Attenzione anche alla parte finale della stringa di formattazione in cui ho aggiunto un new line finale \n.

Stampera qualcosa di simile a:


A:    10    20    30    M:    40    50    60
A:    10    20    30    M:    40    50    60
A:    10    20    30    M:    40    50    60
A:    10    20    30    M:    40    50    60
A:    10    20    30    M:    40    50    60
A:    10    20    30    M:    40    50    60
A:    10    20    30    M:    40    50    60
A:    10    20    30    M:    40    50    60



Ovviamente con i numeri ricavati da compass.

Se modifichi la stringa di formattazione devi ricontare i caratteri e allora potrebbe essere utile:
const char ftmString[] = "A: %6d %6d %6d M: %6d %6d %6d\n";
E ricavare la lunghezza della stringa con strlen(fmtString) che però ritorna 52, quindi al posto di 51
si scriverà report_ptr+(i*(strlen(fmtString) - 1))

Oppure si possono collezionare i dati in array di struct e spedirli raw, saranno meno comprensibili a noi umani
ma si impiegheranno minori risorse hardware.

Ciao.

Il codice che hai postato penso sia proprio quel che mi serva. Il problema è che nella compilazione mi dice che report_ptr+(i*51) non è dichiarato e quindi non può procedere alla compilazione.

Intanto ringrazio entrambi per l’aiuto.

Ho commesso un errore, leggi il commento nel codice, e apporta le modifiche al tuo codice. PS: Ti consiglio da questo momento non fare più copia ed incolla, ma di scrivere di pugno.

Quando rilevi errori da parte del compilatore, copiali e postali, diversamente non c'è modo di sapere qual'e il problema, magari hai dimenticato di scrivere qualcosa, basta anche un ; in meno.

Ciao.

MauroTec: Ho commesso un errore, leggi il commento nel codice, e apporta le modifiche al tuo codice. PS: Ti consiglio da questo momento non fare più copia ed incolla, ma di scrivere di pugno.

Quando rilevi errori da parte del compilatore, copiali e postali, diversamente non c'è modo di sapere qual'e il problema, magari hai dimenticato di scrivere qualcosa, basta anche un ; in meno.

Ciao.

Grazie ancora una volta per l'aiuto e la pazienza. Seguirò i tuoi suggerimenti, devo ancora imparare molto in questo campo.