Go Down

Topic: "manuelle" Steuerung funktioniert nur sporadisch (Read 726 times) previous topic - next topic

Gundelputz

Hallo da draussen,
ich habe  einen Uno als Master und drei Nano als Slave mittels I2C verbunden. bei einem der Nanos soll nach Beendigung eines Counters(der unterschiedlich lang ist) ein Signal zum Master gesendet werden welches dem Master auffordert eine neue Aktion zu starten.
hierzu habe ich den Slave und den Master an Pin13 verbunden und sende vom Slave folgendes:
Code: [Select]
void RESET_TIME()
{
  digitalWrite(ende, HIGH);
  delay(50);
  digitalWrite(ende, LOW);
}


und werte am Master dieses aus:
Code: [Select]
void steuerung()
{
  weiter_so = digitalRead(weiter);

  if(weiter_so == HIGH)
  {// bei Signal vom Slave 4 (Anzeigetafel) das runde beendet
    delay(110);
    //sende_ton_1();
    Text_1 = "yes";
    tr_wk = tr_wk + 1;
    switch(tr_wk)
{
  case 1:
    Text_3 = "TW=1";
    runde_1();
  break;

  case 2:
    Text_3 = "TW=2";
    runde_2();
  break;

  case 3:
    Text_3 = "TW=3";
    runde_3();
  break;

  default:
    Text_3 = "TW=0";
    runde_4();
    tr_wk = 0;
  break;
}
   
  }
  else
  {
    Text_1 = " NO";
  }
 //ende weiter_so

}


die Massen sind verbunden und an den Pins ist ein Pull Up Widerstand.
das Problem ist nun das hier das Signal nur Sporadisch Empfangen wird.
die Aktion zum auslösen am Slave funktioniert definitiv.
Hat jemand ne Idee?

MicroBahner

Du arbeitest offensichtlich gern mit delay(). Der slave setzt das Signal für 50ms auf HIGH. Wenn auf dem Master - z.B. aufgrund von delays - nicht sichergestellt ist, dass das Signal schneller als alle 50ms abgefragt wird, wirst Du immer mal wieder welche verlieren.
Gruß, Franz-Peter

Gundelputz

habe die meisten delay's zu Testzwecken eingebaut
aktuell ist nur noch ein drin und dieses nur um zu verhindern das die Abfrage
Code: [Select]
  if(weiter_so == HIGH)
  {// bei Signal vom Slave 4 (Anzeigetafel) das runde beendet
    delay(110);

nicht zweimal durlaufen wird.
werde aber auch noch das ändern.

uwefed

Quote
hierzu habe ich den Slave und den Master an Pin13 verbunden und sende vom Slave folgendes:
Code: [Select]
void RESET_TIME()
{
  digitalWrite(ende, HIGH);
  delay(50);
  digitalWrite(ende, LOW);
}
Das geht so nicht Du kannst nicht 3 Ausgänge der Slave zusammenschalten und einen auf masse schalten und einen anderen auf HIGH.
Entweder Du wechselst das Pin zwischen Ausgang HIGH und Eingang und hast einen Pullupwiderstand geschaltet oder Du nimmst Dioden damit kein Kurzschluß passiert.
Grüße Uwe

HotSystems

....
ich habe  einen Uno als Master und drei Nano als Slave mittels I2C verbunden....

Hat jemand ne Idee?
Erkläre uns doch mal etwas genauer, was du mit dem Pin 13 erreichen möchtest.

Du hast doch schon eine Verbindung über I2C zwischen den Arduinos, wozu dann noch Pin13 ?
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

MicroBahner

Das geht so nicht Du kannst nicht 3 Ausgänge der Slave zusammenschalten und einen auf masse schalten und einen anderen auf HIGH.
Wenn ich seinen Startpost richtig gelesen habe, macht er das ja nur bei einem der Slaves.

Du hast doch schon eine Verbindung über I2C zwischen den Arduinos, wozu dann noch Pin13 ?
Ich denke, so spart er sich das pollen über I2C. Ist ja nicht so unüblich - viele I2C-Bausteine haben dafür einen eigenen Interrupt-Ausgang, wenn sie abgefragt werden wollen.

@Gundelputz: Wenn Du uns nicht den ganzen Sketch zeigst, werden wir zu deinem Problem nichts weiter sagen können.
Gruß, Franz-Peter

combie

Quote
Ich denke, so spart er sich das pollen über I2C. Ist ja nicht so unüblich - viele I2C-Bausteine haben dafür einen eigenen Interrupt-Ausgang, wenn sie abgefragt werden wollen.
Diese haben aber keine Push Pull Stufen.
Sondern Open Drain oder so..

Sollte man hier auch machen, da hat der Uwe ganz recht.

Alternativ:
Bei einem Programmierfehler möchte man, dass es raucht.
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

uwefed

#7
Nov 03, 2017, 04:08 pm Last Edit: Nov 03, 2017, 04:08 pm by uwefed
Alternativ:
Bei einem Programmierfehler möchte man, dass es raucht.
Im Moment sind die Rauchzeichen explizit im Sketch programmiert.

Gundelputz

Danke für die vielen Antworten.
Das geht so nicht Du kannst nicht 3 Ausgänge der Slave zusammenschalten und einen auf masse schalten und einen anderen auf HIGH.
Entweder Du wechselst das Pin zwischen Ausgang HIGH und Eingang und hast einen Pullupwiderstand geschaltet oder Du nimmst Dioden damit kein Kurzschluß passiert.
Grüße Uwe
Mach ich auch nicht. Natürlich sind alle GND mit einander verbunden aber Pin13 nur vom Slave 4 mit Pin 13 vom Master. Beim Slave Ausgang beim Master Eingang.

Erkläre uns doch mal etwas genauer, was du mit dem Pin 13 erreichen möchtest.

Du hast doch schon eine Verbindung über I2C zwischen den Arduinos, wozu dann noch Pin13 ?

beim I2C Bus ist es meines Wissens nach so das das senden vom Slave zum Master immer eine Anfrage des Masters an den jeweiligen Slave benötigt. Am Slave 4 läuft ein Counter der ein 4-stelliger Jumbo 7-Segmentdisplay und 5 Ampelsegmente Steuert. Es wird hier eine ausgewählte Zeit , z.B. 120sec., vom Master gestartet und auf Null gezählt. Es besteht aber auch die Möglichkeit das die Zeit, für eine unbestimmte Zeit lang, gestoppt werden muss. Um also eine permanente Abfrage zu vermeiden (mindesten alle hundertstel Sec.) habe ich mich für eine separate Leitung entschieden. Das Event wird immer ausgelöst wenn der Counter Null erreicht hat. Da die Ampel dann auch auf rot schaltet und der Impuls auch messbar ist kann ich mit Sicherheit sagen das am Slave alles funktioniert.
Wenn ich seinen Startpost richtig gelesen habe, macht er das ja nur bei einem der Slaves.
Ich denke, so spart er sich das pollen über I2C. Ist ja nicht so unüblich - viele I2C-Bausteine haben dafür einen eigenen Interrupt-Ausgang, wenn sie abgefragt werden wollen.

@Gundelputz: Wenn Du uns nicht den ganzen Sketch zeigst, werden wir zu deinem Problem nichts weiter sagen können.
der ganze Sketch währe vielleicht ein wenig zu umfangreich. hier noch mal die entsprechenden Stellen
Slave:
Code: [Select]
[///zählt die Zeit runter bis Null
void count_x()
{
 
while(zeit >= 0)//Schleife wird so lang ausgefürt bis zeit 0 beträgt
{
  if(start_count == 1)      //Start
  {
  number = zeit;
  zeit--;
  anzeige();
  delay(100);
 //Serial.println(zeit); 
 ///////////////////////////////
  //Ampel wärend des Countdown
   if(zeit >=300)
     {
       digitalWrite(rot, LOW);
       digitalWrite(gelb, LOW);
       digitalWrite(gruen, HIGH);
 
     }
     if((zeit<300)&&(zeit>0))
     {
      //unterscheide zwischen vorlaufzeit und Hauptzeit
      if(rot_oder_gelb == 0)//0 = Vorlaufzeit
     {
       digitalWrite(rot, LOW);
       digitalWrite(gelb, HIGH);
       digitalWrite(gruen, LOW);
     }
     else
     {
       digitalWrite(rot, HIGH);
       digitalWrite(gelb, LOW);
       digitalWrite(gruen, LOW); 
     }
   
     }
     if(zeit<=0)
     {
 
       digitalWrite(rot, HIGH);
       digitalWrite(gelb, LOW);
       digitalWrite(gruen, LOW);
       RESET_TIME();
     
     }

/////////////////////////////// 
  }
  else                      //Stop
  {
    zeit=zeit;
    Serial.println(zeit);
    delay(100);
    digitalWrite(rot, HIGH);
    digitalWrite(gelb, LOW);
    digitalWrite(gruen, LOW);
  }

///////////////////////////////// 
}
}


void RESET_TIME()
{
  digitalWrite(ende, HIGH);
  delay(100);
  digitalWrite(ende, LOW);
  delay(100);
}code]

Master:
[code][/void steuerung()
{
  weiter_so = digitalRead(weiter);

  if(weiter_so == HIGH)
  {// bei Signal vom Slave 4 (Anzeigetafel) das runde beendet
    delay(110);
    //sende_ton_1();
    Text_1 = "yes";
    tr_wk = tr_wk + 1;
    switch(tr_wk)
{
  case 1:
    runde_1();
  break;

  case 2:
    runde_2();
  break;

  case 3:
    runde_3();
  break;

  case 4:
    runde_4();
  break;

  default:
   
  break;
}
   
  }
  else
  {
    Text_1 = " NO";
  }
 //ende weiter_so

}

void runde_1()
{
  sende_ton_1();
  Text_3 = "TW=2";
  sende_4 = 6;
  senden_an();
}

void runde_2()
{
  sende_ton_3();
  Text_3 = "TW=3";
  AD_CD();
  sende_4 = 4;
  senden_an();
}

void runde_3()
{
  sende_ton_1();
  Text_3 = "TW=4";
  sende_4 = 6;
  senden_an();
 
}

void runde_4()
{
  Text_3 = "TW=0";
  sende_ton_3();
  tr_wk = 0;
  sende_4 = 2;//Stop Counter
  senden_an();
}

void AD_CD()
{
  switch(abcd)
  {
    case 1:
      sende_4 = 'b';
      senden_an();
      abcd = 2;
    break;
    case 2:
      sende_4 = 'c';
      senden_an();
      abcd = 1;
    break;
  }
}code]

HotSystems

Ich weiß zwar nicht, warum du das über Pin13 machst, aber das ist deine Sache.
Ich würde es über einen IRQ lösen.
Einen entsprechenden Pin am Slave ziehst du beim Event auf GND und am Master löst du einen IRQ aus.
In der entsprechenden IRQ-Serviceroutine fragst du den Slave ab.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Gundelputz

bin mir nicht ganz sicher was du meinst. Bei einem IRQ gehe ich von einer Unterbrechung aus. Im Prinzip mache ich ja nichts anderes nur das ich auf HIGH ziehe.
Kannst du mir für deinen Vorschlag ein einfaches Beispiel geben?
benötige ich dann eine Externe Beschaltung wie zB ein Pullup, Pulldown, Diode...?

postmaster-ino

Hi

Da Du schon via I²C mit den Slaves kommunizierst, wäre meine Wahl, Das So zu belassen.
Eine Art Interrupt-Leitung, Welche man entweder mit Dioden verodert (alle Slaves senden ein HIGH, wenn Diese was zu sagen haben, der Master sieht, daß mindestens Einer was von Ihm will, der Master fragt alle Slaves ab, Die, die fertig sind, nehmen das HIGH weg, irgend wann ist die Interrupt-Leitung wieder low) oder wie den I²C.Bus extern hoch zieht und von den Slaves auf LOW ziehen lässt.
Gleiches Prinzip, nur anders herum und ohne Dioden.

Diese Interruptleitung kann im Master auch nur gepollt werden.
Wenn Dieser eh die ganze Zeit läuft, spricht Nichts gegen ein Pollen und dem anschließendem Abfragen der Slaves.
Wenn der Master in der Zwischenzeit schlafen geschickt wird um Strom zu sparen, wäre ein Aufwecken per Interrupt meine Wahl, das Pollen kann dann trotzdem so im Code verbleiben.
Wenn die Interrupt-Leitung 'gesetzt' ist (also per Dioden auf HIGH oder per I²C-Schematik auf LOW) werden die Slaves abgeklappert, bis Keiner mehr was zu sagen hat - je nach Programmablauf kann Das auch pro Programmdurchlauf von Slave zu Slave wechseln und man muß nicht alle Slaves in einem Rutsch abfrühstücken.

MfG

Go Up