Wert aus Register lesen an einem bestimmten Pin

Hallo,

ich möchte gerne von einem Arduino einen Wert an einen anderen Arduino senden. Da es Werte zwischen 0 und 120 sind, habe ich mich für die ShiftOut Funktion entschieden.

Ich habe im Internet ein sehr gutes Beispiel gefunden:

Sender

void setup() {
  pinMode(2, OUTPUT); // data pin
  pinMode(3, OUTPUT); // clock pin
}

void loop() {
  delay(10);
  shiftOut(2, 3, MSBFIRST, (byte)70); // B01000110
}
Empfänger

volatile byte data;
volatile byte bitsRemaining = 7;

void setup() {
  pinMode(2, INPUT); // clock pin
  pinMode(8, INPUT); // data pin
  
  attachInterrupt(0, bitAvailable, RISING);
  Serial.begin(9600);
}

void loop() {
  if (bitsRemaining >= 8) {
    Serial.write(data);
    bitsRemaining = 7;
  }
}

void bitAvailable() {
  data = (data << 1) | (PINB & 1);
  bitsRemaining--;
}

Nun möchte ich den Datenpin beim Empfänger gerne ändern z.B auf Pin 9. Nur hier ist mein Problem, zu was muss ich "PINB" ändern? Ich habe schon gefunden das "B" das Register bedeutet und das dieses für die Digitalpins von 8 bis 13 zuständig ist. Eigentlich müsste ich mir doch das 2. Bit anschauen? Habe es mit "(PINB|= 1<<1 & 1)" versucht aber das funktioniert auch nicht. (Im Moment sendet ein Mega und der Uno empfängt)

Später möchte ich gerne einen Uno senden lassen und einen Nano empfangen lassen. Wie müsste ich den Ausdruck "PINB" dort ändern, um auf Digitalpin 8 zu kommen?

Danke für eure Hilfe.

Gruß

PINB ist das Input-Register. Das willst Du ja nur lesen. Ein '|=' macht da gar keinen Sinn, da würdest Du das Register ändern. Du musst den Registerwert lesen und soweit nach rechts schieben, dass das gewünscht Bit auf Bit0 steht, and dann wieder maskieren, und in data verodern:

data = (data << 1) | ((PINB>>1) & 1);

So sollte es funktionieren (ungetestet).

Vielen Dank!

So funktioniert es. Da habe ich wohl in die falsche Richtung verschoben..

Mit DigitalRead hat es auch funktioniert allerdings musste ich dann ein delay(5) beim senden bis zum nächsten Byte einsetzten. Wäre für meine Funktion auch ausreichend gewesen aber so ist es natürlich schöner und schneller :slight_smile:

Gruß
Daniel

Super! Klar, digitalRead() ist viel langsamer als das direkte Port-Lesen, da musst Du den Sender bremsen.

Hallo,

das du die Bits zukünftig schneller findest hier ein Paket der Pinoutübersichten gängiger Arduinoboards.
Leider ist der fleißige User der das alles erstellt hat schon länger nicht mehr erreichbar und seine Links sind auch tot. Das ist das was ich mir gesichert hatte. Hebt es euch gut auf.

Aufteilung ist wegen der Uploadgrößenbeschränkung bedingt.
(1) Uno, Mega2560

Pinoutpaket-1.zip (1.58 MB)

(2) Nano, Pro Mini

Pinoutpaket-2.zip (730 KB)

(3) Micro (32u4), Leonardo

Pinoutpaket-3.zip (1.14 MB)

Doc_Arduino:
das du die Bits zukünftig schneller findest hier ein Paket der Pinoutübersichten gängiger Arduinoboards.
Leider ist der fleißige User der das alles erstellt hat schon länger nicht mehr erreichbar und seine Links sind auch tot. Das ist das was ich mir gesichert hatte. Hebt es euch gut auf.

Ich hatte "damals" ein paar dieser wie ich finde sehr brauchbaren Pinout-Übersichten von der Seite runtergeladen, aber natürlich fehlte mir einiges, als alles offline ging.

Besten Dank für die Zurverfügungstellung!

dabr_178:
Hallo,

ich möchte gerne von einem Arduino einen Wert an einen anderen Arduino senden. Da es Werte zwischen 0 und 120 sind, habe ich mich für die ShiftOut Funktion entschieden.

Ich verstehe nicht wieso Du das so realisieren willst, wenn andere schon einen einfacheren und sichereren Weg gefunden haben: Serielle Schnittstelle.
Falls Du eine seriele Hardware-Schnittstelle frei hast nimm diese ansonsten die Emulation in Software.

Deine Lösung hat gar keine Synchronisation. Wenn mal ein Bit verlorengeht zB weil Die IF-bedingung zwischen 2 Bit empfangen nicht aufgrufen wird, dann mischt Du 2 Zahlen.

Grüße Uwe

Ich verstehe nicht wieso Du das so realisieren willst

Das war eben die Vorgabe in diesem Thread. Ebenso wie

dabr:
Ich habe im Internet ein sehr gutes Beispiel gefunden:

Was man auch generell anzweifeln, und für grundsätzlich Mist halten könnte: direkte hardwareabhängige Register-Adressierung mit Arduino Pin-Nummern mischen. Wenn man PIN - Register verwendet, sollte man auch DDR - Register verwenden und genau aufschreiben, für welche Hardware der Code gedacht ist.

Die shiftOut - Geschwindigkeit ist undefiniert und zum Glück relativ langsam, da sie von der Geschwindigkeit eines digitalWrite(dynamicPinVariable, constValue) abhängt.

Ohne ausreichend lange Idle-Zeiten ist übrigens auch bei Serial die Synchronisation auf ganze Bytes schwierig.

Hallo,

ich hatte mir noch keine wirklichen Gedanken gemacht, dass Bits bei der Übertragung verloren gehen können. Sobald aber ein Bit "übersehen" wird, dürften doch alle nachkommenden Zahlen falsch sein, da er bitsRemaining nicht runtergezählt hat?

Die Daten Seriell zu übertragen ist eine gute Idee. Ich habe das jetzt mal so gemacht:

//Seriell Read EMPFÄNGER

void setup() {

  Serial.begin(9600);
  Serial1.begin(9600);

}

void loop() {

  while (Serial1.available() <= 0);
  
    byte incomingByte= Serial1.read();
    Serial.print("Empfangen:  ");
    Serial.println(incomingByte, DEC);
  
  

}
//Serial Write SENDER

#include <SoftwareSerial.h>

SoftwareSerial nanoSerial (8,9); // Rx, Tx verkehrtherum am UNO anschließen (Rx auf Tx und Tx auf Rx)
void setup() {

  Serial.begin(9600);
  nanoSerial.begin(9600);

}

void loop() {

  nanoSerial.write((byte)45);
  delay(2000);

}

Später soll von einem Uno eine Position (zwischen 0 und 120 Grad) an einen Nano übergeben werden. Dieser soll einen Schrittmotor an diesen Punkt verfahren.
Was passiert jetzt, wenn er z.B. die Position 100 bekommt, den Motor anfängt zu verfahren und wärend der Zeit des Verfahrens eine neue Position Seriell gesendet wird? Wird diese dann "verschluckt"? Oder wird automatisch ein Interrupt durchgeführt bzw. muss man hier mit einem Interrupt arbeiten?

Dankeschön für eure vielen Antworten und Ideen :slight_smile:

Was passiert jetzt, wenn er z.B. die Position 100 bekommt, den Motor anfängt zu verfahren und wärend der Zeit des Verfahrens eine neue Position Seriell gesendet wird? Wird diese dann "verschluckt"? Oder wird automatisch ein Interrupt durchgeführt bzw. muss man hier mit einem Interrupt arbeiten?

Och...

Im Grunde liegt das an dir. (und an den vorgefertigten Libs, welche du verwendest)
Denn du bist der Programmierer deines Programms.
Du hast die Macht.

Übrigens:
Wenn ich die üblichen Arduinos miteinander quatschen lassen will, verwende ich (meist) I2C

Andererseits wenn die Datenübertragung nur in eine Richtung erfolgen soll kann man auch SPI verwenden, Die braucht auch nur 2 Signalleitungen. Seriell braucht nur eine. I2C funktioniert auch ist aber von der Kabellänge limitiert (ca 2-3m).
Der Vorteil der Hardwarelösung ist daß diese einen Buffer verwenden und so falls nicht zuviele Daten auf einmal kommen, Daten nicht verloren gehen.
Ob die Ansteuerung des Schrittmotors blockierend ist hängt vom Sketch ab.
Wie schnell muß der Motor sich drehen? Braucht es Anfahr bzw Bremsrampen?

Grüße Uwe

Ich werde das jetzt per Serieller Kommunikation lösen. Ich hoffe ich bekomme den Sketch so hin, dass keine Daten von der Seriellen Übertragung verloren gehen während der Schrittmotor verfahren wird. Ansonsten würde ich mich nochmal melden :slight_smile:
Bei den Schrittmotoren handelt es sich um die einfachen 28byj-48.