I2C data geoordend loggen

algemene C code
Berichten: 17
Geregistreerd: 23 Mei 2014, 22:52

I2C data geoordend loggen

Berichtdoor -zuur- » 13 Apr 2017, 14:20

Hallo allemaal,

het is al weer een tijd geleden dat ik wat aan het stoeien ben geweest met een arduino.
nu heb ik weer een klein projectje een Arduino uno die data stuurt via de I2C bus naar een andere Arduino uno.
in totaal stuur in nu 3 waardes over de I2C bus en wil ik die bij Arduino 2 loggen in een data logger.

ook dit gaat prima en zet hij alle gegevens onder elkaar in een txt bestand.

nu om het overzichtelijk te maken wil ik eigenlijk dat de data in het text bestand gescheiden wordt opgeslagen met een comma.

bv :

Data1, Data2, Data3
Data1, Data2, Data3
Data1, Data2, Data3

hier kom ik niet uit. heel veel voorbeelden op het grote internet geven dit soort voorbeelden wel aan maar dan met harde contacten om te tellen.
bijvoorbeeld voor buttons If buttonPress == LOW
nu moet ik het dus niet van een pin hebben maar van de datagegevens van de I2C bus.
wie kan mij hier mee helpen?



Kort samengevat:

alle gegevens logt hij al.
gestructureerd loggen van I2C gegevens.

Advertisement

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: I2C data geoordend loggen

Berichtdoor nicoverduin » 13 Apr 2017, 14:35

Zet je sketch hier ff van die logger dat we weten wat voor soort data we krijgen. Zal wel sprintf() worden
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 17
Geregistreerd: 23 Mei 2014, 22:52

Re: I2C data geoordend loggen

Berichtdoor -zuur- » 14 Apr 2017, 14:23

Code: Alles selecteren
void receiveEvent(int howMany) {

  while (1 < Wire.available()) {
  }


 int x = Wire.read();   
 

Serial.println("data to write");         
Serial.println(x);         

  myFile = SD.open("data.txt", FILE_WRITE);

 
  if (myFile) {
 
    Serial.println("Write to SD Card");
    myFile.print(x);
    myFile.print(",");
    myFile.close();
    Serial.println("done.");
   
  } 
 
  else {
 
    Serial.println("error opening data.txt");
  }



  }



waarde X is een byte uit gelezen uit de I2C bus
deze formule moet hij dus 3x uitlezen voordat hij de volgende regel leest.

voorbeeld :

Temp1, Temp2, Temp3

Data1, Data2, Data3
X , X , X
X , X , X
enz

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: I2C data geoordend loggen

Berichtdoor nicoverduin » 14 Apr 2017, 15:42

Een hele sketch hier neer zetten blijft een uitdaging...... dus terug in de zon..... merk het wel.....
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 17
Geregistreerd: 23 Mei 2014, 22:52

Re: I2C data geoordend loggen

Berichtdoor -zuur- » 15 Apr 2017, 09:36

Je mag beste het hele script hebben hoor alleen is de rest niet relevant.
speciaal voor jouw hieronder het hele script.


cpp code
#include <Wire.h> //Communication I2C
#include <SPI.h>
#include <SD.h> // SD Kaart

/*------------------------------------------SD CARD INFO-----------------------------*/

File myFile;




// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4; //


/*---------------------------------------SETUP---------------------------------*/
/*---------------------------------------SETUP---------------------------------*/
/*---------------------------------------SETUP---------------------------------*/
/*---------------------------------------SETUP---------------------------------*/




void setup() {

Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output


Serial.print("Initializing SD card...");

if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");


// on startup Clear SD Card Data.txt file
myFile = SD.open("data.txt", O_WRITE | O_CREAT | O_TRUNC);
myFile.close();






}

/*-------------------------END --------------------- Setup------------*/


// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
}
int x = Wire.read();


Serial.println("data to write");
Serial.println(x);

myFile = SD.open("data.txt", FILE_WRITE);


if (myFile) {

Serial.println("Write to SD Card");
myFile.print(x);
myFile.print(",");
myFile.close();
Serial.println("done.");

}

else {

Serial.println("error opening data.txt");
}



}



/*---------------------------------------LOOP---------------------------------*/
/*---------------------------------------LOOP---------------------------------*/
/*---------------------------------------LOOP---------------------------------*/

void loop() {





/*
// re-open the file for reading:
myFile = SD.open("data.txt");
if (myFile) {
// Serial.println("Opening data.txt:");

// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error Re-opening data.txt");
} */
delay(5000);

}

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: I2C data geoordend loggen

Berichtdoor nicoverduin » 15 Apr 2017, 11:06

Krijg je altijd 3 waardes? Of is dat niet zeker?
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: I2C data geoordend loggen

Berichtdoor Koepel » 15 Apr 2017, 12:53

The receiveEvent() wordt aangeroepen vanuit een interrupt. Het is dus een interrupt routine. Hou die zo klein en zo snel mogelijk.

Je kunt de 'howMany' gebruiken, dat is het aantal bytes dat ontvangen is en die je kunt lezen met Wire.read().
Je mag geen Serial functies gebruiken, want de Serial library gebruikt zelf ook interrupts.
Schrijven naar een bestand hoort daar echt niet, doe dat in de loop().

Meestal gaat het op deze manier:
In receiveEvent kun je de ontvangen gegevens kopiëren naar een globale en 'volatile' buffer. Ik gebruik trouwens meestal een 'struct' voor een pakket van data dat ik over I2C verstuur. Vervolgens zet je ook nog een vlag dat gegevens zijn ontvangen.
In de loop() wordt dan gekeken naar de vlag, en als er iets is ontvangen dan worden de interrupts even uitgezet om een kopie van die gegevens te maken, en met die kopie wordt dan verder gegaan. Bijvoorbeeld naar een bestand schrijven.

Kun je nog eens vertellen hoe de data er uit ziet. Zijn het 3 bytes ? Dus drie variabelen met een waarde van 0 ... 255 ?

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: I2C data geoordend loggen

Berichtdoor nicoverduin » 15 Apr 2017, 14:55

Maar ook elke keer een bestand openen en sluiten is tijdrovend.... bestanden openen in de setup en flush() om de buffers weg te schrijven en de file pointer bij laten werken. Verder kun je gewoon een tabelletje maken en de 3 waardes daarin opslaan. Tabel vol eerst sprintf gebruiken om te formatteren en wegschrijven. En dat alles gewoon in de loop. Dan houdt je nog een beetje performance over.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 17
Geregistreerd: 23 Mei 2014, 22:52

Re: I2C data geoordend loggen

Berichtdoor -zuur- » 17 Apr 2017, 20:46

@nico ik krijg altijd 3x een byte binnen ja dit zijn 3 numerieke waardes.

Kan je mij uitleggen of een voorbeeld geven hoe je zo'n tabel maakt / vult

@koepel bedankt voor je duidelijke uitleg ik ga zorgen dat het schrijven van het bestand in de loop komt en de howmany functie even uit pluizen.
Het verhaal van een struct ken ik nog niet die ga ik even googlen en uit pluizen! Bedankt alvast ik laat me snel weer horen!

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: I2C data geoordend loggen

Berichtdoor Koepel » 18 Apr 2017, 07:03

De 'howMany' zit al in je sketch. Het is de parameter die binnen komt bij de requestEvent() functie.
Wanneer de Master twee bytes verstuurd, dan is de 'howMany' twee, dat zou je kunnen gebruiken als extra check of om een variabelen aantal bytes te lezen (als de Master soms twee en soms meer bytes verstuurd).
Ik noemde dat omdat ik de while-statement nogal raar vind. Het staat in dit voorbeeld: https://www.arduino.cc/en/Tutorial/MasterWriter, maar dat is dan ook een tenenkromend en haarpuntsplijtend slecht voorbeeld.

In dit voorbeeld ontvang ik twee bytes, ik ben vergeten of je inderdaad twee byte verstuurd.
Code: Alles selecteren
// global variables.
volatile byte received1;
volatile byte received2;
volatile boolean dataReceived = false;

void receiveEvent( int howMany)
{
  // We are expecting two bytes from the Master
  if( howMany == 2)
  {
    // Success ! we received two bytes.
    // Read the two bytes.
    received1 = Wire.read();
    received2 = Wire.read();
   
    // raise the flag, to indicate that data was received.
    dataReceived = true;
  }
}
Die 'howMany' is hier alleen maar een extra check. Dat mag je dus ook weglaten en meteen de twee bytes gaan lezen.

Je kunt beginnen met dit. Meer is niet nodig:
Code: Alles selecteren
// global variables.
volatile byte received1;
volatile byte received2;
volatile boolean dataReceived = false;

void receiveEvent( int howMany)
{
  // Read the two bytes from the Master
  received1 = Wire.read();
  received2 = Wire.read();
   
  // raise the flag, to indicate that data was received.
  dataReceived = true;
}
In de loop() ga je kijken naar de dataReceived flag en als die 'true' is, dan kun je ontvangen gegevens gaan gebruiken.

Een 'struct' kan nuttig zijn wanneer er verschillende soorten variabelen zijn. Bijvoorbeeld een byte voor het licht, een float voor de temperatuur en een integer voor de luchtvochtigheid. In dat geval kun je er één pakket van maken. Dat heet een 'struct'. Dat mag je vergeten hoor. Wanneer je een heel stel gegevens verstuurd die allemaal bytes of integers zijn, dan is het gemakkelijker om een array te gebruiken. Met slechts twee losse bytes speelt dit allemaal niet.

Volgende

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 7 gasten