I2C data geoordend loggen

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

Re: I2C data geoordend loggen

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

ik heb nu mijn script aangepast en het schrijven van de file in de loop geplaatst. helaas werkt hij nog niet goed.
als ik de if (howMany ==3) gebruik stopt het script daar en zie ik in de serial monitor "niet genoeg bytes ontvangen"

als ik de if (howMany ==1) gebruik loopt het script wel door alleen leest hij bij Data1 een byte uit en Data2 en Data3 geeft hij een maximale byte weer (255)

hier onder mijn script wat doe ik fout?

Code: Alles selecteren

// Data Buffers.
volatile byte Data1;
volatile byte Data2;
volatile byte Data3;
volatile boolean dataReceived = false;



  // Functie die de data van de Master Arduino ontvangt
// this function is registered as an event, see setup()
  void receiveEvent(int howMany) {
  if (howMany == 1) // ontvang 3 bytes dan uitvoeren
  {
    Serial.println("byte ontvangen?");   
 // 3 bytes uitlezen.
    Data1 = Wire.read();
    Data2 = Wire.read();
    Data3 = Wire.read();

// raise the flag, to indicate that data was received.
    dataReceived = true;
   
  }
  else
  {
  Serial.println("niet genoeg bytes ontvangen"); 
    }
 }







Code: Alles selecteren
void loop() {

if ( dataReceived == true)
{
 
Serial.println("data to write");         
Serial.println(Data1);
Serial.println(Data2);
Serial.println(Data3);       

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

  // if the file is available, write to it:
  if (myFile) {
 
    Serial.println("Write to SD Card");
     myFile.print(Data1);
    myFile.print(",");
     myFile.print(Data2);
    myFile.print(",");
     myFile.print(Data3);
    myFile.println(" ");
    myFile.close();
    Serial.println("done.");
    // print to the serial port too:
  } 
  // if the file isn't open, pop up an error:
  else {
 
    Serial.println("error opening data.txt");
  }

}
}



Serial monitor : laat zien wat er in de data.txt file geschreven wordt.

219,255,255
219,255,255
203,255,255
219,255,255
220,255,255
220,255,255
220,255,255
220,255,255
220,255,255



moet ik bij de master trouwens een byte voorzien van een acknowledge?
een I2C byte kan maximaal het getal 255 aan toch zou ik graag ook grotere getallen willen ontvangen maar hoe...

Advertisement

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

Re: I2C data geoordend loggen

Berichtdoor Koepel » 19 Apr 2017, 23:09

De Wire library doet alle acknowledge en zo, dus dat gaat allemaal goed.

Ik schreef dat je eerst kunt beginnen zonder de howMany, maar dan is het wel nodig om te weten hoeveel bytes de Master verstuurd.
Wat is de code van de Master ? Als de Master maar één byte verstuurd, dan krijg je voor de rest een -1 van de Wire.read(), en dat is inderdaad 255 als die -1 in een byte gestopt wordt.
Je mag echt geen Serial functies in de receiveEvent zetten. Het gaat vaak goed, maar het kan zomaar opeens voor problemen zorgen.

In de loop() is het beter om even de interrupts uit te zetten en een kopie van de variabelen te maken.
In de loop() kun je de vlag weer terug zetten.

Code: Alles selecteren
if ( dataReceived == true)
{
  // Something was received, make copies
  noInterrupts();        // turn off interrupts
  byte Copy1 = Data1;
  byte Copy2 = Data2;
  byte Copy3 = Data3;
  dataReceived = false;   // reset the flag
  interrupts();             // enable interrupts

  Serial.println("Received:");         
  Serial.println(Copy1);
  Serial.println(Copy2);
  Serial.println(Copy3);
}


Dus de receiveEvent zet de vlag op true, en in de loop() wordt die vlag terug gezet op false. Dan werkt het goed samen.

Andere soorten variabelen oversturen kan later nog. Graag zou ik eerst werkende code zien (zonder Serial functies in de requestEvent).

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

Re: I2C data geoordend loggen

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

momenteel is hij nu zo. ik denk inderdaad dat het probleem dan in de Master zit. die zend volgens mij 3 x 1 byte in plaats van 1x 3 bytes.

mijn schrijftaal is duidelijk nog niet heel goed maar ik zal eerst eens zelf naar mijn master script kijken als ik nu al zie hoeveel ik anders moet doen. :oops:

Code: Alles selecteren
if ( dataReceived == true)
{
noInterrupts();        // turn off interrupts 

  byte Copy1 = Data1;
  byte Copy2 = Data2;
  byte Copy3 = Data3;
  dataReceived = false;   // reset the flag
 

Serial.println("data to write");         
Serial.println(Copy1);
Serial.println(Copy2);
Serial.println(Copy3);     
 
interrupts();             // enable interrupts

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


 // if the file is available, write to it:
  if (myFile) {
 
    Serial.println("Write to SD Card");
     myFile.print(Copy1);
    myFile.print(",");
     myFile.print(Copy2);
    myFile.print(",");
     myFile.print(Copy3);
    myFile.println(" ");
    myFile.close();
    Serial.println("done.");
    // print to the serial port too:
  } 
  // if the file isn't open, pop up an error:
  else {
 
    Serial.println("error opening data.txt");
  }



EDIT : jep dat probleem lag dus in mijn Master arduino nu stuurt hij wel de 3 bytes netjes ! TOP! :D

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

Re: I2C data geoordend loggen

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

Nu is de vraag nog hoe je een andere waarde verstuurd.

bijvoorbeeld een temperatuur van 30,456 graden.
een byte kan tot het getal 255 nu doe ik het met een vermenigvuldiging van 10 bijvoorbeeld dus kan ik maximaal tot 25,5 graden. daar na krijg je vreemde getallen te zien.

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

Re: I2C data geoordend loggen

Berichtdoor Koepel » 20 Apr 2017, 20:47

Je hebt iets verschoven...
De functie aanroep "interrupts()" om de interrupts weer aan te zetten staat nu ná de Serial.println(). Maar de Serial functies gebruiken interrupts. Dus als de output buffer in de Serial library vol komt te zitten, dan komt de sketch krakend tot stilstand.

Zodra je een Arduino als Slave wilt gebruiken, dan kom je nu eenmaal in dit soort dingen terecht. Het is helaas niet anders. Arduino had best iets eenvoudigers kunnen maken, bijvoorbeeld een WireEvent(), vergelijkbaar met SerialEvent().
Ik hoop dat mijn uitleg een beetje helpt.

Om alles soepel te laten lopen is het nodig dat de interrupt routines zo kort mogelijk zijn, en dat ook de interrupts zo kort mogelijk uitgezet worden.

Je laat de receiveEvent() niet zien, dus nu weet ik niet of daar nog een Serial.println in zit :?

Is de temperatuur een float ?
Tja, dan ga ik toch maar met tegenzin de Wire.readBytes() gebruiken, ook al is die functie niet voor I2C bedoelt. Het is beter om dat met aparte Wire.read's te doen. De Wire.readBytes() heeft namelijk ook een timeout ingebouwd, en dat is nu net wat de receiveEvent() functie niet kan gebruiken.

Dit is niet getest.
Code: Alles selecteren
// Master
  float temperatuur = 18.435;
  Wire.beginTransmission...
  Wire.write( &temperatuur, 4);     // voor later: sizeof(float) in plaats van 4
  Wire.endTransmission...

// Slave
volatile float ontvangen_temperatuur;

void receiveEvent( int howMany)
{
  if( howMany >= 4)   // toch maar extra check, speciaal voor Wire.readBytes.
  {
    Wire.readBytes( &ontvangen_temperatuur, 4);
    dataReceived = true;
  }
}


Kun je heel de Master sketch en heel de Slave sketch laten zien, dan ben ik weer bij ;)

Vorige

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 10 gasten