Umwandlung von digitalem Portinput

Ich habe vier Inputs die ich in eine Integerzahl umwandeln will: 1001 :slight_smile:
Ich habe die Formel gefunden:
int in = 0;
int D14_ = 1;//lowbit
int D15_ = 0;
int D16_ = 0;
int D17_ = 1;//highbit

in = ((D17_(2^3))+(D16_(2^2))+(D15_*(2^1))+D14_);

Bei der Formel schreibt der Arduino für in=2

Wenn ich die Formel so schreibe:

BTT = ((D17_(8))+(D16(4))+(D15_*(2))+D14_);

würde es stimmen, in=9

Habe ich das falsche Hochzeichen bzw.versteht der Arduino was anderes da drunter?

Verwenden Sie <CODE>-Tags, wenn Sie Computerbegriffe schreiben. HTML übersetzt Ihr Asterisk als „kursiv“
z.B.

in = ((D17_*(2^3))+(D16_*(2^2))+(D15_*(2^1))+D14_);
1 Like

Das ^ ist exklusive Oder.
Würde dir auch jedes C++ Buch sagen können.
Du suchst <<

:thinking: ok aber lt.dem Referenzbeispiel sollte es funktionieren:

Hallo
du suchst pow()
https://docs.arduino.cc/language-reference/de/funktionen/math/pow/

allerdings ist, für das was Du willst, << sinnvoller

Sehr nice ist mir aber schon wieder zu hochgegriffen, außerdem erlaubte Datentypen float, Ergebnis double.
Mit meiner gefundenen Formel bin ich eigentlich schon zufrieden, sie funktioniert und braucht nicht viel Speicherplatz. Mich hat nur gewundert daß der Ardu das Hochzeichen nicht versteht. :confused:

Kannst Du mal probieren:

#include <Streaming.h>      // https://github.com/janelia-arduino/Streaming

void setup()
{
  Serial.begin(9600);
  Serial << "\nStart\n";
  int in1 = 0, in2 = 0;
  int D14_ = 1;//lowbit
  int D15_ = 0;
  int D16_ = 0;
  int D17_ = 1;//highbit

  in1 = ((D17_ * pow(2, 3)) + (D16_ * pow(2, 2)) + (D15_ * pow(2, 1)) + D14_);
  Serial << "in1: " << in1 << endl;
  in2 = (D17_ << 3) + (D16_ << 2) + (D15_ << 1) + D14_;
  Serial << "in2: " << in2 << endl;
}

void loop() {}

Lesestoff: << (bitshift left)

2 Likes

@thmoe
also ich würde das auch einfach mit Bitshift machen (war aber langsamer als @agmue)

void setup() {
  Serial.begin(115200);

  int D14_ = 1;//lowbit
  int D15_ = 0;
  int D16_ = 0;
  int D17_ = 1;//highbit

  int in = (D17_ << 3) +  (D16_ << 2) + (D15_ << 1) + D14_;

  Serial.println(in, BIN);
  Serial.println(in, DEC);
}

void loop() {
}

aber besser wäre du beschreibst was du eigentlich machen willst, denn allein dein D14_ D17_ schaut schon verbesserungswürdig aus.

1 Like

Nur in deiner Fantasie!
Ich sehe da keinen Beispiel Code mit ^

Doch, das versteht der Compiler perfekt.

Verstehst Du das, was auf dem Seriellen Monitor ausgegegeben wird:

// Forensketch
// https://forum.arduino.cc/

int a;

void setup()
{
  Serial.begin(115200);
  Serial.print("a ist gleich ");
  Serial.println(a);
  if (a = 2)
  {
    Serial.println("a ist gleich 2");
  }
  else
  {
    Serial.println("Denkste");
  }
}

void  loop()
{
}

Bei dem Beispiel ist die Erklärung in Klammern gewesen und in "normalem" Mathe geschrieben nicht in Arduino-verständlichem Programmtext. Dort ist das ^-Zeichen tatsächlich ein bitweises XOR und kein Potenz-Hochzeichen. Das hatte ich übersehen. Also vielen Dank an alle Beteiligten für die Infos!

Abgesehen vom Linksshiften, was hier einfacher und effizienter ist aber für Anfänger weniger verständlich.

Wieso willst Du vom Programm Zahlen ausrechnen lassen, die Du beim programmieren bereits kennst?
Wieso willst Du 2^3 ausrechnen lassen, wenn es 8 ist?

Jemand der sich besser mit dem Kompiler aukennt sollte sagen ob dieses Herumgerechne sich im kompilierten Code überhaupt noch befindet oder ob das der Kompiler schon ausgerechnet hat und nicht in den Code Eingang findet.

Grüße Uwe

Wenn die Daten constexpr oder const sind, dann ist die Wahrscheinlichkeit groß, dass alles vorberechnet wird.
Aber wir dürfen ja nicht wissen wo die Daten her kommen.


Interessanter ist, ob der betreffende Rechner/µC einen Barrelshifter hat.
Wenn ja, dann ist sowas

int in = (D17_ << 3) + (D16_ << 2) + (D15_ << 1) + D14_;

völlig ok.
Ohne, z.B. bei den AVR, gibts bessere/schnellere Methoden.

Auch der µC muss leider geheim bleiben.

Nachtrag:

Dieses umgeht das "Barrelshifter Problem".
Zudem lassen sich die Pins leicht umsortieren bzw. weitere hinzufügen

/**
 * int in = 0;
 * int D14_ = 1;//lowbit
 * int D15_ = 0;
 * int D16_ = 0;
 * int D17_ = 1;//highbit
 * 
 */

const byte inputs[]
{ // Pins, anpassen
  2, // highbit D14?
  3,
  4, 
  5, // lowbit D17?
};

template<size_t N> unsigned readPins(const byte (&pins)[N])
{
  unsigned result {0};
  for(const byte pin:pins)
  {
    result <<= 1;
    result |= digitalRead(pin);
  }
  return result;
}
 
void setup()
{
  Serial.begin(9600);


  Serial.print("Result: ");
  Serial.println(readPins(inputs));
}

void loop() {}

Ja, ein Sketch von einem C++ Programmierer.
Wie soll sowas einem Amateur, wie mir das einfallen. Verstehe es ja fast nicht.

Danke für Dein Beispiel.

Grüße Uwe

Gerne geschehen, und Danke für die Blumen.

Eigentlich ist das gar nicht so kompliziert...

Durchnummerieren von Variablen ist immer böse, darum das Array.

Das Template stellt sicher, dass quasi jedes Byte Array übergeben werden kann.
Unabhängig von der Größe N.
Und dass der Compiler aufschreit, wenn man versucht irgendetwas anderes zu übergeben.
Das macht die Sache Wiederverwendbar.
for(const byte pin:pins) Der range based for loop, sollte mittlerweile bekannt sein.
Auch die kombinierten Operatoren finden sich im C++ Buch.

Natürlich könnte man das unsigned auch noch zu einem Template Parameter machen, damit man nicht auf die 16 oder 32 Bit beschränkt ist.

Noch Fragen?
Beantworte ich gerne!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.