Go Down

Topic: "8-Bit" Eingang, Texte definieren und speichern (Read 13085 times) previous topic - next topic

michael_x


Quote
Über den Serial Monitor kann ich die Bits auch sehen. Jedoch wird immer 11111111 angezeigt, sofern kein INPUT auf Masse gelegt wurde. So wirklich verstehen tue ich das nicht
INPUT_PULLUP sorgt für die 1.

Bitweise negieren macht man mit ~

uxomm

#31
Nov 28, 2017, 02:18 am Last Edit: Nov 28, 2017, 02:23 am by uxomm
Wenn das Port als Ganzes eingelesen werden kann, bekommst Du Deine 8Bit direkt mit einem Mal Lesen, wenn Du die 8 Eingangssignale auf die 'Beinchen' legst, Die intern dieses eine Port darstellen.
Ob/Wie Das in C++ geht - bin ich der Falsche für (in Assembler geht Das)
Naja, wenn es um "komplette Ports" geht, ist beim Arduino (UNO - so einer wird hier wohl verwendet) die Luft ja eher dünn :)
siehe: http://www.pighixxx.com/test/portfolio-items/atmega328/?portfolioID=337
Port A ist nicht vorhanden
Port B wird teilweise vom Oscillator belegt (PB6, PB7)
Port C, da ist mit PC6 der Reset mitten drinnen (und PC7 gibt es gar nicht).
Bleibt Port D - der wäre als einziger vollständig vorhanden:
PD0 - Arduino Pin D0 (RX)
PD1 - D1 (TX)
PD2 - D2
PD3 - D3
PD4 - D4
PD5 - D5
PD6 - D6
PD7 - D7
Aber weil RX und TX belegt sind, ist das auch nur begrenzt nutzbar ...

Auf anderen Arduino-Boards (z.B. Mega) geht es natürlich weniger eng zu.

Einen kompletten Port einlesen geht natürlich mit C++:
Code: [Select]
byte meinPortD = PIND;
Always decouple electronic circuitry.

Serenifly

Man kann auch von zwei Ports einlesen und diese mit Schieben und Oder verknüpfen

agmue

#33
Nov 28, 2017, 07:34 am Last Edit: Nov 28, 2017, 12:17 pm by agmue
Ungetestete Anregung:

Code: [Select]
const int ledPin[8] = {10,11,12,13,A0,A1,A2,A3};
const int buttonPin[8] = {2,3,4,5,6,7,8,9};
const byte wertigkeit[] = {1,2,4,8,16,32,64,128};  // 2er-Potenz

void setup()
{
 Serial.begin(9600);
 for (byte i = 0; i < 8; i++)
 {
   pinMode(buttonPin[i], INPUT_PULLUP);
   pinMode(ledPin[i], OUTPUT);
 }
}

void loop()
{
 byte index = 0;
 static byte alt_index = 0;
 for (byte i = 0; i < 8; i++)
 {
   digitalWrite(ledPin[i], digitalRead(buttonPin[i]));
   if (digitalRead(buttonPin[i]))
   {
     index += wertigkeit[i];  // auch ohne Tabelle mit veroderten geschubsten Bits |= 1 << i
   }
 }
 if (index != alt_index)
 {
   Serial.print("index: ");
   Serial.println(index);  // Werte von 0 bis 255
   alt_index = index;
 }
}
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

michael_x

Quote
auch ohne Tabelle mit veroderten geschubsten Bits |= 1 << i
Guter Tip. Dafür gibt es den BV(i) Makro, wer's mag.
Der Compiler kennt guten Assembler-Code für 1 << i . Lohnt nicht, ihm da zu helfen.

Hast übrigens    alt_index = index;  vergessen.

Code: [Select]
void loop() {
  static byte alt_index;
  byte index=0;
  for (byte i = 0; i < 8; i++)
  {
    bool x = digitalRead(buttonPin[i]);
    digitalWrite(ledPin[i], x);
    if (x)   index |= 1 << i ;
  }
  if (index != alt_index) {
    Serial.print("index: ");
    Serial.println(alt_index = index, BIN);  // Werte von 0 bis 1111111
  }
}
Jetzt fehlen nur noch führende 0 in der Ausgabe

agmue

#35
Nov 28, 2017, 12:34 pm Last Edit: Nov 28, 2017, 12:47 pm by agmue
Hast übrigens   alt_index = index;  vergessen.
Danke, habe es in #33 ergänzt.

Du bist theoretisch eindeutig besser oder hast Du inzwischen einen Arduino-Notfallkoffer?

Mit der Tabelle der Wertigkeiten wollte ich es für den TO (Thread Opener) möglichst verständlich machen, da er eine wartungsfreundliche Lösung sucht, Lernen steht wohl eher nicht im Vordergrund.

Daher habe ich auch auf die binäre Ausgabe vom Index verzichtet, das machen schon die LEDs. Tatsächlich braucht er ja den Index, um einen Text aus dem Textfeld zu fischen. Dazu benötigt er eine Zahl.

Möglicherweise wäre es am anschaulichsten, den Index sowohl binär als auch dezimal anzuzeigen, um darzustellen, daß es sich um zwei unterschiedliche Darstellungen der selben Sache handelt.

Code: [Select]
if (index != alt_index)
 {
   Serial.print("index binaer: ");
   for (byte i = 7; i >= 0; i--)
   {
     Serial.print(index & (1 << i));
   }
   Serial.print("\tdezimal: ");
   Serial.println(index);  // Werte von 0 bis 255
   alt_index = index;
 }
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

michael_x

Mit der Tabelle der Wertigkeiten, und der Anzeige binär/dezimal hast du vom Verständnis her sicher recht.
Quote
Lernen steht wohl eher nicht im Vordergrund
Das nutzt ihm nix. ;)

Ausserdem lesen evtl. aus Versehen auch andere mit. Für die ist
Code: [Select]
void printBinary(byte value) {
   // 8 Bit Binärdarstellung auf Serial
   char output[9] = "00000000";
   char*cp = output;
   for (byte mask=0x80; mask;  mask >>= 1;) {
     if (mask & value) *cp |= 1; // '0' -> '1'
     cp++;
   }
   Serial.write(output);
}


Quote
hast Du inzwischen einen Arduino-Notfallkoffer
Als Ausgleich dazu, sonst nur noch 64-bit Systeme im Kopf zu haben, liebe ich 8-bit Arduinos, wo es evtl. noch auf einzelne Bytes ankommt.

agmue

Code: [Select]
*cp |= 1;
Warum "oder" anstelle "gleich", bringt das einen Vorteil?

Das nutzt ihm nix. ;)
Dann schmeiß ihn mit Pointern zu, bis er die Orientierung verliert ;)
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

michael_x

Quote
Warum "oder" anstelle "gleich", bringt das einen Vorteil?
Stimmt
   *cp = '1';
geht genausogut.

Ist also eher zur Verwirrung geeignet. (Dazu muss man nicht unbedingt mit Pointern um sich schmeißen)

Um den Unterschied, ob man ein ganzes Byte neu schreibt oder nur ein Bit zusätzlich setzt, hab ich mich nicht wirklich gekümmert.

Jannomag

#39
Nov 28, 2017, 05:02 pm Last Edit: Nov 28, 2017, 05:28 pm by Jannomag
@agmue:
Dein Programm:
Code: [Select]
const int ledPin[8] = {10,11,12,13,A0,A1,A2,A3};
const int buttonPin[8] = {2,3,4,5,6,7,8,9};
const byte wertigkeit[] = {1,2,4,8,16,32,64,128};  // 2er-Potenz

void setup()
{
 Serial.begin(9600);
 for (byte i = 0; i < 8; i++)
 {
   pinMode(buttonPin[i], INPUT_PULLUP);
   pinMode(ledPin[i], OUTPUT);
 }
}

void loop()
{
 byte index = 0;
 static byte alt_index = 0;
 for (byte i = 0; i < 8; i++)
 {
   digitalWrite(ledPin[i], digitalRead(buttonPin[i]));
   if (digitalRead(buttonPin[i]))
   {
     index += wertigkeit[i];  // auch ohne Tabelle mit veroderten geschubsten Bits |= 1 << i
   }
 }
 if (index != alt_index)
 {
   Serial.print("index: ");
   Serial.println(index);  // Werte von 0 bis 255
   alt_index = index;
 }
}


Funktioniert ganz gut...jedoch ist der Standardwert, wenn kein Eingang gegen Masse liegt, 255.
Ich versuche das ganze Teil zu verstehen, es fällt mir jedoch extrem schwer. Im Groben verstehe ich, was da passiert, wäre aber auch niemals auf diese Ideen gekommen.
Daher würde ich gerne zum Verständnis mal geklärt haben, wie ich die Ausgabe umdrehen kann, sodass standardmäßig 0 angezeigt und dann bis auf 255 hochgezählt werden kann.

Ich hab aktuell keine 8 Mikroschalter - hab meine letzten gerade erst verbaut und aus der Resteverwertung sind nur welche mit zu kurzen Beinchen fürs Breadboard rausgekommen.
Daher regel ich das gerade über Leitungen gegen Masse.
Der Pullup funktioniert ja an sich besser, wie der normale INPUT.

Wenn ich die Eingänge mit 5V ansteuere, dann gibt es extrem viele Störungen.

Nun werden ja von der SPS 24V ausgegeben, wenn ein Bit aktiv ist, mit denen ich dann die 5V für den Arduino über Optokoppler schalten will.
Wenn es da aber weiterhin diese Störungen gibt, dann funktionierts ja nicht wirklich...das kann ja aber nicht so richtig sein beim Arduino, oder?

5V   
  |
 \
  |---o Dn Arduino Uno
  |
 R
  |
GND

So schließe ich die Taster doch korrekt an, oder? R ist ein 4,7k Widerstand.
Wenn ich das so mache und dann die 5V auf einen Eingang lege, dann flimmert er teilweise extrem und die Serielle Ausgabe spielt verrückt und zählt da irgendein Mist.


Sorry, wenn ich da sogar die einfachsten Sachen scheinbar nicht kann, aber irgendwie fällt es mir extrem schwer das zu verstehen und zu merken.
Ich denke da immer etwas zu simpel, glaub ich...bin halt nur Elektriker :D

agmue

#40
Nov 28, 2017, 05:39 pm Last Edit: Nov 28, 2017, 05:42 pm by agmue
Was passiert bei pinMode(buttonPin[ i ], INPUT); zusammen mit Deiner Schaltung mit PullDown-Widerstand (R gegen GND)?

geht genausogut.
Gut, fürchtete schon, was nicht verstanden zu haben.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Jannomag

Was passiert bei pinMode(buttonPin[ i ], INPUT); zusammen mit Deiner Schaltung mit PullDown-Widerstand (R gegen GND)?

Der Arduino erkennt den Eingang nicht korrekt. Im Serial Monitor wechselt er schnell zwischen diversen Werten, wiederholt unzählige Male welche...als wenn er immer wieder neue Eingangssignale bekommt.
Fasse ich dann z.B. auf das Gehäuse vom Oszillator, bleibt das erstmal so stehen, bis ich wieder einen neuen Eingang anlege.

Ich weiss nicht, ob das mit Tastern besser wird, aber normal ist das doch nicht, oder?
Ich hab das bei anderen Projekten schon beobachtet und mich mit dem PULLUP abgefunden. Ich kann ja auch mit den Optokopplern die Masse durchschalten und somit den PULLUP verwenden.

Spannung beziehe ich übrigens via USB von meinem Desktop, falls das wichtig ist.

michael_x

Quote
Der Arduino erkennt den Eingang nicht korrekt.
Hast du denn externe Pulldown - Widerstände angeschlossen ?

Das ist der wesentliche Unterschied zwischen INPUT und INPUT_PULLUP : beim zweiten verwendest du im Controller intern vorhandene Pullup - Widerstände, beim ersten musst du die selber dranbauen.

agmue

Hast du denn externe Pulldown - Widerstände angeschlossen ?
Lt. #39 externe PullDown. Die Eingänge reagieren aber, als wenn keine dran wären. Es dürfte sich daher um einen Verdrahtungsfdehler handeln. In der systematischen Fehlersuche ist der TO (Thread Opener) aber ausgebildet, da bin ich ganz entspannt, das findet er alleine.

Mich hat mal ein Steckbrett genarrt, bei dem in der Mitte die roten und blauen Linien nicht verbunden waren. Die Kontakte waren es dann auch nicht. Oder ein Kabel für Steckbretter ohne Durchgang.
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Jannomag

Nehm ich die Widerstände raus und lege über die gleichen Pins des Boards die Masse an die Eingänge vom Uno dann klappt es einwandfrei mit PULLUP.
4,7k sind aber korrekt, oder?

Go Up