Arduino reagiert nicht auf I2c Wire.onReceive()

Hallo

Ich habe zwei arduino über i2c verbunden. Aus irgend einem grund reagiert jedoch der eine Arduino nicht auf das senden von daten des anderen. Kann mir jemand sagen wo mein fehler liegt?

Empfänger

#include<Wire.h>
#include<DallasTemperature.h>
#include <TimeLib.h>

int cycle = 0 ;
int cycle_temp[5];
int cycle_time[5];

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial){
  }
  Wire.begin(9);
  Wire.onReceive(data);
}

void loop() {

 
 delay(2000);

}
void data(int howMany){
  Serial.print("test");
  while(Wire.available() > 0){
    cycle = Wire.read();
  } 
    Serial.print("I am in");
    Serial.print(cycle);
    Wire.beginTransmission(8);
    Wire.write("Temp");
    Wire.endTransmission();
    while(!Wire.available()){}
    for(int i = 0; i < 5 ;++i){
      cycle_temp[i] = Wire.read();
    }
    
    while(Wire.available()){
      Wire.beginTransmission(8);
      Wire.write("Time");
      Wire.endTransmission();
      }
    for(int i = 0; i < 5 ;++i){
      cycle_time[i] = Wire.read();
    }
  Serial.println("Zyklen:");
  Serial.println(cycle);
  Serial.println("Temp");
  for (int i = 0;i<5;++i){
    Serial.print(cycle_temp[i]);
    Serial.print(",");  
  }
  Serial.println("Zeit");
   for (int i = 0;i<5;++i){
    Serial.print(cycle_time[i]);
    Serial.print(",");  
  }
 }

Sender:

#include <Wire.h>
#include<DallasTemperature.h>
#include <TimeLib.h>
#include <SoftwareSerial.h>
int cycle = 5 ;
int cycle_temp[5] = {55,90,44,22,22};
int cycle_time[5] = {20,20,10,5,20};
int x = 1;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(19200);
  Wire.begin(8);
  Wire.onReceive(check);
}

void loop() {
  
  delay(200);
  Wire.beginTransmission(9);
  Wire.write(cycle);
  Wire.endTransmission();
  
  Serial.print(cycle);
  
  
}

void check(int howMany){

  if (Wire.read() == "Temp"){
    for(int i = 0; i < 5 ;++i){
      Wire.beginTransmission(9);
      Wire.write(cycle_temp[i]);
      Wire.endTransmission();  
    }
    
  
  }
  
  if (Wire.read() == "Time"){
    for(int i = 0; i < 5 ;++i){
      Wire.beginTransmission(9);
      Wire.write(cycle_time[i]);
      Wire.endTransmission();  
    }
    
  }

}

Wo rufst du denn deine Funktion die deine I2C-Daten einliest ?
void(data) sehe ich nicht in der loop.

void(data) sehe ich nicht in der loop.

Ich sehe schon, wo sie aufgerufen wird....
Aber ich sehe auch, dass diese Funktion total kaputt ist. Total.

Sowas tutman nicht!
Und schon gar nicht in einer ISR.

combie:
Ich sehe schon, wo sie aufgerufen wird....

Ja stimmt, ich jetzt auch. :wink:
Ist ja eine eigene Funktion.

Auch die Empfangsfunktion ist total kaputt. Erst werden alle Bytes gelesen und weg geworfen und dann wird blind irgendwas gesendet.

Schau Dir mal das als Beispiel an.

Gruß Tommy

Evtl. auch hier mal reinschauen.
Da sind viele Beispiel zum Übertragen von Daten per I2C drin.
Beispiele

Also ich habe ein wenig geändert und anfangs ging es auch zwei arrys zu senden. Aber ab dem Moment wo ich zwei weitere Variablen hinzugefügt habe ging es nicht mehr. Der Sender geht zwar noch in die Funtion send_data aber stockt dort?!. Er bringt auf dem Seriellen Monitor lediglich : Ic
und nicht den vollen Text:

Sender Code:

#include <Wire.h>
char cycle = 5;
char cycle_temp[5] = {1,2,3,4,5};
char cycle_time[5] = {55,66,77,33,33};
char repetition = 555;
void setup()
{
  Wire.begin(55); 
  Serial.begin(19200);
  Wire.onReceive(send_data);
}

void loop()
{
Serial.println("Warte auf Signal");
delay(1000);
}
void send_data(int howMany){
  
    Serial.println("Ich starte");
    delay(1000);
    Wire.beginTransmission(42);
    Wire.write(cycle);
    Wire.endTransmission();
    delay(1000);
    Wire.beginTransmission(42);
    Wire.write(repetition);
    Wire.endTransmission();
    delay(1000);
    Wire.beginTransmission(42);
    Wire.write(cycle_temp,5);  
    Wire.endTransmission();
    delay(1000);
    Wire.beginTransmission(42);
    Wire.write(cycle_time,5);
    Wire.endTransmission();

  delay(1000);

  }

Empfänger:

#include <Wire.h>
int cycle = 0;
int cycle_temp[5];
int cycle_time[5];
int repetition;
int i;
int check = 0;
void setup()
{
  
  Serial.begin(9600);
  Wire.begin(42); 
  Wire.onReceive(receiveEvent);
 
}

void loop()
{
  Wire.beginTransmission(55);
  Wire.write(1);
  Wire.endTransmission();
  Serial.println("Sende Signal");
  delay(1000);

      
}
void data(){
   Serial.println("TEMP");
      for(int i = 0;i <5;++i){
        Serial.print(cycle_temp[i]);
        Serial.print(",");  
      }
      Serial.println("TIME");
      for(int i = 0;i <5;++i){
        Serial.print(cycle_time[i]);
        Serial.print(",");  
      }
      Serial.println("Zyklen:");
      Serial.print(cycle);
      Serial.println("Wiederholungen");
      Serial.print(repetition);
      delay(1000);
  
}

void receiveEvent(int anzahl)
{
  Serial.println("Ich reagiere");
  switch (check){
    case 0:
      Serial.print("ich gehe hier rein");
      cycle = Wire.read();  
      ++cycle;
      break;
    case 1:
      repetition = Wire.read();
      ++cycle;
      break;
    case 2:
      while(Wire.available()){
        cycle_temp[i] = Wire.read(); 
        ++i;
      }
      ++cycle;
      break;
    case 3:
      while(Wire.available()){
        cycle_time[i] = Wire.read(); 
        ++i;
      }
      ++cycle;
      data();
      break;
    default:
      
      break;
    
  }
 
  
}

Du scheinst Dir die Beispiele nicht angeschaut zu haben. Dann kann das auch nichts werden.
Es ist besser von Master und Slave zu sprechen, als von Sender und Empfänger. Dann werden die Abläufe deutlicher.
Der Ablauf geht immer vom Master aus.
Dieser sendet dem Slave seinen Auftrag. Dafür hat der Slave die Routine an onRecive

void receiveEvent(int wieviel) {
  // bereite die Daten vor
}

Dann fordert der Master x Bytes vom Slave an: Wire.requestFrom(SLAVE_ADR, menge); Dieser verschickt sie in der Routine an onRequest

void requestEvent()
{
  Wire.write(antwort,laenge);
}

In die Routinen gehört kein Serial.print rein.

Gruß Tommy

Das Problem ist das ich die Länge der Arrays nicht im voraus weiß

Wieso weißt du das nicht?
Hast du das gar nicht selber programmiert?

DOCH, aber das ist nur ein TEST. Bei dem einem Arduino werden die Werte eingegeben. Und dadurch kann die länge des Arrys Varieren!

Dann fordere immer die Maximallänge an. Die überzählichen Bytes werden als 0xFF (-1) gesendet. Ist die Eingabe ein char-Array mit 0 Begrenzung oder sind es einfach Bytes?

Gruß Tommy

Also Obergrenze hab ich 10 gesetzt und es ist ein normaler char arry.
Ich hab es nun mit dem reqeust versuch und mir ist eingefallen das die länge der Arrys durch die Cycle Zahl gegebn ist. Wenn ich diese nun zurest rüberschicke kann ich entsprechend Die anderne Arrys anfordern;

Master

#include <Wire.h>
int cycle = 0;
int cycle_temp[5];
int cycle_time[5];
int repetition;
int i;
int check = 0;
void setup()
{
  
  Serial.begin(9600);
  Wire.begin(42); 
  Wire.onReceive(receiveEvent);
 
}

void loop()
{
  

  Serial.println("Sende Signal");
  delay(1000);
  Serial.print(check);
  switch (check){
     case 0:
      Serial.print("ich gehe rein");
        Wire.requestFrom(55,1);
        break;
     case 1:
        Wire.requestFrom(55,1);
        break;
     case 2:
        Wire.requestFrom(55,cycle);
        break;
     case 3:
        Wire.requestFrom(55,cycle);
        break;
     default:
        Serial.print("Finishe");
  }
      
}
void data(){
   Serial.println("TEMP");
      for(int i = 0;i <5;++i){
        Serial.print(cycle_temp[i]);
        Serial.print(",");  
      }
      Serial.println("TIME");
      for(int i = 0;i <5;++i){
        Serial.print(cycle_time[i]);
        Serial.print(",");  
      }
      Serial.println("Zyklen:");
      Serial.print(cycle);
      Serial.println("Wiederholungen");
      Serial.print(repetition);
      delay(1000);
  
}

void receiveEvent(int anzahl)
{
  Serial.println("Ich reagiere");
  switch (check){
    case 0:
      Serial.print("ich gehe hier rein");
      cycle = Wire.read();  
      ++cycle;
      break;
    case 1:
      repetition = Wire.read();
      ++cycle;
      break;
    case 2:
      while(Wire.available()){
        cycle_temp[i] = Wire.read(); 
        ++i;
      }
      ++cycle;
      break;
    case 3:
      while(Wire.available()){
        cycle_time[i] = Wire.read(); 
        ++i;
      }
      ++cycle;
      data();
      break;
    default:
      
      break;
    
  }
  ++check;
  
}

Slave

#include <Wire.h>
int cycle = 5;
char cycle_temp[5] = {1,2,3,4,5};
char cycle_time[5] = {55,66,77,33,33};
int repetition = 555;
int check = 0;
void setup()
{
  Wire.begin(55); 
  Serial.begin(19200);
  Wire.onRequest(send_data);
}

void loop()
{
Serial.println("Warte auf Signal");
delay(1000);
}
void send_data(int howMany){

    switch (check){
      
      case 0:
      Serial.print("Ich gehe rein");
        Wire.beginTransmission(42);
        Wire.write(cycle);
        Wire.endTransmission();
        break;
      case 1:
        Wire.beginTransmission(42);
        Wire.write(repetition);
        Wire.endTransmission();
        break;
      case 2:
        Wire.write(cycle_temp,cycle);
        break;
      case 3:
        Wire.write(cycle_time,cycle);
        break;
      default:
        Serial.println("Finished");
    }
    ++check;

  }

Was soll das mit beginTransmission() und endTransmission() im Request Handler? Das hat da nichts verloren. Nur write(). Diese zwei Methoden sind für Übertragungen vom Master zum Slave.

Solange Du die Datenübertragung mit I2C noch nicht verstanden hast, kann das nichts werden :frowning:

Jede Übertragung basiert auf einem Puffer, der die zu sendenden Daten enthält, bzw. in dem die empfangenen Daten abgelegt werden. Dafür stellt die Wire Bibliothek einen eigenen Puffer für den Slave bereit, beim Master kann der Benutzer einen eigenen Puffer in Wire.write() bzw. Wire.requestFrom() bereitstellen.

Nun mußt Du Dich erst einmal entscheiden, ob der Empfänger als Master die Daten direkt empfangen möchte (requestFrom), oder ob er als Slave auf eine Übertragung wartet (onReceive). Dann geht es entsprechend unterschiedlich weiter.

Wenn Du das slave_sender Beispiel angeschaut hättest, dann wüßtest Du, daß der Slave im requestEvent alle Daten mit Wire.write() abschicken muß, und keine neue Übertragung mit begin/endTransmission durchführen kann, weil der Bus derzeit dem Master gehört, der die Daten anfordert.

Also ein teil funktioniert jetzt.
Die Anzahl der Zyklen und die Temperatur werden richtig übertragen aber komischerweise nicht die Zeit und die repetitions

Master

#include <Wire.h>
int cycle = 0;
int cycle_temp[5];
int cycle_time[5];
int repetition;
int i;
int check = 0;
void setup()
{
  
  Serial.begin(9600);
  Wire.begin(42); 
 
 
}

void loop()
{
  int test = 0;

  delay(1000);
  Serial.print(check);
  
  switch (check){
     case 0:
        
        
        Wire.requestFrom(55,1);
        cycle = Wire.read();
        if(cycle != 0){
          ++check;
        }
        delay(100);
        Wire.flush();
        break;
     case 1:
     
        Wire.requestFrom(55,1);
        repetition = Wire.read();
        if (repetition != 0){
         ++check; 
         }
        
        
        break;
     case 2:
        Wire.requestFrom(55,cycle);
        while(Wire.available()){
        cycle_temp[i] = Wire.read(); 
        ++i;
      }
        if (cycle_temp[1] != 0){
         ++check; 
         }
         Wire.flush();
        break;
     case 3:
        Wire.requestFrom(55,cycle);
        while(Wire.available()){
        cycle_time[i] = Wire.read(); 
        ++i;
        }
        if (cycle_time[1] != 0){
         ++check; 
         }
        break;
     default:
        Serial.print("Finished");
        data();
  }
      
}
void data(){
   Serial.println("TEMP");
      for(int i = 0;i <5;++i){
        Serial.print(cycle_temp[i]);
        Serial.print(",");  
      }
      Serial.println("TIME");
      for(int i = 0;i <5;++i){
        Serial.print(cycle_time[i]);
        Serial.print(",");  
      }
      Serial.println("Zyklen:");
      Serial.print(cycle);
      Serial.println("Wiederholungen");
      Serial.print(repetition);
      delay(1000);
  
}

Slave:

#include <Wire.h>
int cycle = 5;
char cycle_temp[5] = {1,2,3,4,5};
char cycle_time[5] = {55,66,77,33,33};
int repetition = 555;
int check = 0;
void setup()
{
  Wire.begin(55); 
  Serial.begin(19200);
  Wire.onRequest(send_data);
}

void loop()
{
Serial.println("Warte auf Signal");
delay(1000);
}
void send_data(int howMany){
  Serial.print(check);
    switch (check){
      case 0:
      Serial.print("Ich gehe rein");
        
        Wire.write(cycle);
          ++check;
        delay(100);
        Wire.flush();
        break;
      case 1:
        
        Wire.write(repetition);
          ++check;
        break;
      case 2:
        Wire.write(cycle_temp,cycle);
         ++check;
        delay(100);
        Wire.flush();
        break;
         
      case 3:
        Wire.write(cycle_time,cycle);
         ++check;
        break;
       
      default:
        Serial.println("Finished");
        check = 0;
    }
  

  }

Hallo. Irgendwie bringt I2c den Arduino zum absturz.
Aktuell wollte ich den Testmouds einbinden.
Das Problem ist das sich der Arduino während bzw zum ende der Übertragung aufhängt kann mir jemand sagen wo der fehler ist?
Master Code:

// Project: DIY Thermocyler V2.0 Arduino
// Creator: Tobias and Torben
// Date of Creation: 10.12.16

#include "Nextion.h"
#include <SoftwareSerial.h>
#include <Wire.h>


SoftwareSerial HMISerial(10,11); //RX,TX
//SoftwareSerial ardserial(4,5); //RX,TX



int cycle = 0;
int repe  = 0;
int cycle_help = 0;
int cycle_help_temp = 0;
int cycle_temp[10];
int cycle_time[10]; 

//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
char buffer[100] = {0};

//Button Press abfrage
NexTouch *nex_listen_list[] = {
    
    
    &heat,
    &cool,
    &pwm_heat,
    &pwm_fan,
    &check,
    &check_rep,
    &check_t,
    &next_t,
    &back_t,
    &start,
    &c_time,
    &check_temp,
    &next_temp,
    &back_temp,
    &c_temp,
    NULL
  
};
//----------------------------------------------------------------------------------------------------------------------
//Arduino Inilisation
void setup() {
  Wire.begin(55);
  nexInit();
  Serial.begin(38400);
  //ardserial.begin();
  while (!Serial){
    
  }
 
 
  
  Serial.println("USB-to-PC Connection etablished");  
//----------------------------------------------------------------------------------------------------------------------
//Attach Button Funktions
//Home Screen BUttons
  start.attachPush(start_cycle, &start);
  c_time.attachPush(cycle_time_button,&c_time);
  c_temp.attachPush(cycle_temp_button,&c_temp);

//Attach Test Mode Buttons   
  heat.attachPush(heat_button, &heat);
  cool.attachPush(cool_button, &cool);
  pwm_heat.attachPop(pwm_heat_slider, &pwm_heat);
  pwm_fan.attachPop(pwm_fan_slider, &pwm_fan);

//Attach Cycle Buttons
  check.attachPush(check_cycle_button, &check);
//Attach Repetion Buttons
  check_rep.attachPush(check_repe_button,&check_rep);
//Attach Time Buttons
  check_t.attachPush(check_time_button,&check_t);
  next_t.attachPush(next_t_button,&next_t);
  back_t.attachPush(back_t_button,&back_t);
//Attach Temperatur Buttons
  check_temp.attachPush(check_temp_button,&check_temp);
  next_temp.attachPush(next_temp_button,&next_temp);
  back_temp.attachPush(back_temp_button,&back_temp);
  
  
//----------------------------------------------------------------------------------------------------------------------
Serial.println("Setup Complet");
}
//Main Loop waiting for actions
void loop() {

  nexLoop(nex_listen_list);

}

//----------------------------------------------------------------------------------------------------------------------
//start Cycle
void start_cycle(void *ptr){
  sendData();
   
}
//----------------------------------------------------------------------------------------------------------------------
//sending data funktio
void sendData(){
  int temp_ok = 0;
  int time_ok = 0;
  int cycle_ok = 0;
  int i = 0;
  while(!Serial){
    while(cycle_ok == 0){
      Serial.print('S'); 
      cycle_ok = Serial.read(); 
    } 
    Serial.print(cycle);
    while(temp_ok == 0){ 
      temp_ok  = Serial.read();
      
    }
    for (byte i = 0; i < (sizeof(cycle_temp)/sizeof(cycle_temp[0])); i++) {
    Serial.print(cycle_temp[i]);
    }
    i = 0;
    while(time_ok == 0){
      time_ok = Serial.read();  
    }

    for (byte i = 0; i < (sizeof(cycle_time)/sizeof(cycle_time[0])); i++) {
    Serial.print(cycle_time[i]);
    }
    i = 0;
    delay(100);
    Serial.print("Finished");
    
  }
  
  
}
//----------------------------------------------------------------------------------------------------------------------
//Read Data from Nextion
//Receving number of cycles
void check_cycle_button(void *ptr){
  uint32_t cycle_value_value = 0;
  n_cycle.getValue(&cycle_value_value);
  cycle = cycle_value_value;
 }
//Receving number of Repetions
void check_repe_button(void *ptr){
  uint32_t repe_value = 0;
  n_cycle_rep.getValue(&repe_value);
  repe = repe_value;
 }
//Cycle Temperature
//----------------------------------------------------------
void cycle_temp_button(void *ptr){
    //This is needed if you leave it and join it again 
    n_cycle_temp.setValue(cycle_temp[0]);
    Serial.print("test");
    
}
void check_temp_button(void *ptr){
  
  for (int h = 0; h < cycle+1;h++){
    Serial.print(cycle_temp[h]);  
  }
  
}
//Temp for each Cycle
void next_temp_button(void *ptr){
  uint32_t cycle_temp_value = 0;
  
//  cycle = EEPROM.read(200);
  
  if (cycle_help_temp == cycle){
    n_cycle_temp.getValue(&cycle_temp_value);
    cycle_temp[cycle_help_temp] = cycle_temp_value;
    cycle_help_temp = 0;
    n_cycle_temp.setValue(cycle_time[cycle_help_temp]);
    n_cycle_c_temp.setValue(cycle_help_temp);
  }else {
    n_cycle_temp.getValue(&cycle_temp_value);
    cycle_temp[cycle_help_temp] = cycle_temp_value;
    ++cycle_help_temp;  
    n_cycle_c_temp.setValue(cycle_help_temp);
    n_cycle_temp.setValue(cycle_temp[cycle_help_temp]);
 }

   
}
void back_temp_button(void *ptr){
  if (cycle_help_temp == 0){
    cycle_help_temp = cycle;
    n_cycle_temp.setValue(cycle_temp[cycle_help_temp]);
    n_cycle_c_temp.setValue(cycle_help_temp);
  }else {
    --cycle_help_temp;
    
    n_cycle_temp.setValue(cycle_temp[cycle_help_temp]);
    n_cycle_c_temp.setValue(cycle_help_temp);
  }
  
   
}

//----------------------------------------------------------
//Cycle Time
//Time of each Cycles
void cycle_time_button(void *ptr){
    //This is needed if you leave it and join it again 
    n_cycle_t.setValue(cycle_time[0]);
    Serial.print("test");
    
}
void check_time_button(void *ptr){
  
  for (int h = 0; h < cycle+1;h++){
    Serial.print(cycle_time[h]);  
  }
  
}
//Temp for each Cycle
void next_t_button(void *ptr){
  uint32_t cycle_t_value = 0;
  
//  cycle = EEPROM.read(200);
  Serial.print("Ich gehe hier rein");
  if (cycle_help == cycle){
    n_cycle_t.getValue(&cycle_t_value);
    cycle_time[cycle_help] = cycle_t_value;
    cycle_help = 0;
    n_cycle_t.setValue(cycle_time[cycle_help]);
    n_cycle_c.setValue(cycle_help);
  }else {
    n_cycle_t.getValue(&cycle_t_value);
    cycle_time[cycle_help] = cycle_t_value;
    ++cycle_help;  
    n_cycle_c.setValue(cycle_help);
    n_cycle_t.setValue(cycle_time[cycle_help]);
 }

 
  
   
}
void back_t_button(void *ptr){
  if (cycle_help == 0){
    cycle_help = cycle;
    n_cycle_t.setValue(cycle_time[cycle_help]);
    n_cycle_c.setValue(cycle_help);
  }else {
    --cycle_help;
    
    n_cycle_t.setValue(cycle_time[cycle_help]);
    n_cycle_c.setValue(cycle_help);
  }
  
   
}
//----------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
//Begin Test Mode

void heat_button (void *ptr){
  Serial.print("Test");
  Wire.beginTransmission(42);
  Wire.write('H');
  Wire.endTransmission();
  Wire.flush();

  
}  
void cool_button (void *ptr){
  Wire.beginTransmission(42);
  Wire.write('C');
  Wire.endTransmission();
  Wire.flush();
 Serial.print("Test2");
  
  
  
}
void pwm_heat_slider (void *ptr){
  uint32_t pwm_heat_value = 0;
  pwm_heat.getValue(&pwm_heat_value);
  Wire.beginTransmission(42);
  Wire.write('V');
  Wire.endTransmission();
  Wire.beginTransmission(42);
  Wire.write(pwm_heat_value);
 

  Serial.println(pwm_heat_value); 
  
}
void pwm_fan_slider (void *ptr){
  uint32_t pwm_fan_value = 0;
  pwm_fan.getValue(&pwm_fan_value);
  Wire.beginTransmission(42);
  Wire.write('F');
  Wire.endTransmission();
  Wire.beginTransmission(42);
  Wire.write(pwm_fan_value);
  Wire.endTransmission();
  Serial.println(pwm_fan_value); 
  
  
}

Slave: Da zu lang leider nur mit Pastebin:

Bild im Anhang mit Serial Monitor.
PS ich hab ein Teil des Codes wegen der länge rausnehmen müssen hat aber nichts mit der Verbindung zu tun der Teil