String mit binären Inhalt in Integer konvertieren

Moin,
ich verzweifel bald.
Ich möchte mit den Werten einer elektonischen Schieblehre weiterarbeiten. Die Hardware steht, bekomme die Daten auch angezeigt. Ich bekomme es aber nicht hin eine float Variable zu generieren.

Vielleicht kann mir jemand eine Richtung zeigen wie es weiter gehen könnte??

Gruß Stefan

//Simple Digital Calliper Reader
//See http://j44industries.blogspot.com/

// Pin Declarations
int dataIn = 11;
int clockIn = 12;

// Variables
int clock = 1;
int lastClock = 1;
unsigned long time = 0;
unsigned long timeStart = 0;
int out = 0;






void setup() 
{
  // Pin Set Up
  pinMode(dataIn, INPUT);     
  pinMode(clockIn, INPUT);  

  Serial.begin(115200);
  Serial.println("Ready: ");
}




void loop(){

  lastClock = clock;
  clock = digitalRead(clockIn);

  if (lastClock == 1 && clock == 0){
    out = digitalRead(dataIn)+digitalRead(dataIn)+digitalRead(dataIn); // Tripple sampling to remove glitches
    if((micros() - time) > 800){
      Serial.println(" ");
    }
    else if((micros() - time) > 400){
//      Serial.print("  ");
    }

    if (out > 1){
      Serial.print("1");
    }
    else{
      Serial.print("0");
    }
//    Serial.print(",");
    time = micros();
  }
}

float floatVariable = 3.14; 
Serial.println(floatVariable, 4); // mit 4 Dezimalstellen nach dem Dezimalpunkt

// Sie können mathematische Operationen durchführen.
floatVariable = 22.357 / 42.45;

:man_shrugging: ??

Zeige doch die Daten, und wie werden die auf dem Messschieber angezeigt wen zu groß dann Dividieren durch 10 oder 100.

Ich hab den oben genannten original Code versucht zu erweitern , bekomme aber nur Fehler oder falsche Ergebnisse.

Vielleicht noch zum Verständnis
Ausgabe auf dem Bildschirm mit Original Code

19:43:58.948 -> 100110110110000000000000
19:43:59.089 -> 100110110110000000000000
19:43:59.183 -> 100110110110000000000000
19:43:59.277 -> 100110110110000000000000
19:43:59.418 -> 100110110110000000000000
19:43:59.527 -> 100110110110000000000000
19:43:59.621 -> 100110110110000000000000
19:43:59.700 -> 100110110110000000000000
19:43:59.841 -> 100110110110000000000000
19:43:59.935 -> 100110110110000000000000
19:44:00.029 -> 100110110110000000000000
19:44:00.170 -> 100110110110000000000000
19:44:00.264 -> 100110110110000000000000
19:44:00.374 -> 100110110110000000000000
19:44:00.468 -> 100110110110000000000000

Die Daten müssen dann noch aufgearbeitet werden

Interpretation of data:

?,X,X,X, X,X,X,X, X,X,X,X, X,X,X,X, ?,?,?,?, ?,Y,?,?
? = Not sure
X's for a binary number with least significant bit at the start of the string. The binary number is the distance in mm times 100.
Y = Sign bit if Y = 1 number is negative if Y = 0 number is positive.

Reihenfolge ändern hab ich, erste Bit ist weg, Vorzeichen hab ich. Aber den String bekomme ich nicht als Integer oder Float

//Simple Digital Calliper Reader
//See http://j44industries.blogspot.com/

// Pin Declarations
int dataIn = 11;
int clockIn = 12;

// Variables
int clock = 1;
int lastClock = 1;
unsigned long time = 0;
unsigned long timeStart = 0;
int out = 0;

String Ausgabe ;
String A;
String Vorzeichen;
String Binar;
int Dezimal;
int Ausgabezahler = 0;
int Ende = 0;


void setup() {
  // Pin Set Up
  pinMode(dataIn, INPUT);     
  pinMode(clockIn, INPUT);  

  Serial.begin(115200);
  Serial.println("Ready: ");
}



void loop()
{
 




  lastClock = clock;
  clock = digitalRead(clockIn);

  if (lastClock == 1 && clock == 0)
    {
          
            
      out = digitalRead(dataIn)+digitalRead(dataIn)+digitalRead(dataIn); // Tripple sampling to remove glitches
     
      if((micros() - time) > 800)
        {
          
          A =  Ausgabe.substring(2, 21);
          
          if (A.endsWith("0"))
            {
              Vorzeichen = "+"; 
            }
            else
            {
              Vorzeichen = "-";
            }    

          // Bitreihenfolge taschen


          //************************************************************
          String Satz= A;
          char SatzArray[Satz.length()];
          Satz.toCharArray(SatzArray, Satz.length() + 1);

          for (int i = sizeof(SatzArray) - 1; i >= 0; i--)
            {
              Binar = Binar + (SatzArray[i]);
            }
           
          //**********************************************************
          Serial.println(Ausgabe);  // original aber falsche Reihenfolge
          Serial.println (A);       // gekürzte original Reihenfolge
          Serial.println (Binar);   // richtige Reihenfolge

          
//          Dezimal = (Binar.toi());
//          uint32_t Dezimal = strtoul(Binar, NULL, 2);
//          Dezimal= (Binar.toInt());
//          Serial.println(Dezimal);

          
 //         Serial.println(" ");
          Ausgabe = " ";
          Binar = " ";
          A = " ";
         
        }
    
    if (out > 1)
    {
      Ausgabezahler = Ausgabezahler + 1;
      
      Serial.print("1");
      Ausgabe = Ausgabe + "1";
    }
    else
    {
      Ausgabezahler = Ausgabezahler + 1;
      Serial.print("0");
      Ausgabe = Ausgabe + "0";
    }
 
    time = micros();
  

  }
}

Habe den Rest gefunden ob tut was soll ist gute frage.
Jedoch der Jenninger nutzt Analog Pins, testen kostet nix :wink:

int dataIn = 11 //A0;
int clockIn = 12 //A2;
// Variables
int clock = 1;
int lastClock = 1;
unsigned long time = 0;
unsigned long timeStart = 0;
int out = 0;
long longout=0;
float finalout;
void setup() {
// Pin Set Up
pinMode(dataIn, INPUT);
pinMode(clockIn, INPUT);
Serial.begin(115200);
Serial.println("Ready: ");
}
void loop(){
lastClock = clock;
clock = digitalRead(clockIn);
if (lastClock == 1 && clock == 0){
out = digitalRead(dataIn)+digitalRead(dataIn)+digitalRead(dataIn); // Tripple sampling to remove glitches
if((micros() - time) > 1200){
longout=longout>>8;
//%negative numbers switch to 2s complement
if (longout & 0b00000000000010000000000000000000){
longout=longout & 0b11111111111101111111111111111111;
longout=~longout + 1;
}
finalout=(float(longout)-1)/100;
Serial.print("data:");
Serial.println(finalout);
longout=0;
}
else if((micros() - time) > 400){
}
if (out > 1){
longout=longout|0b01000000000000000000000000000000;
longout=longout>>1;
}
else{
longout=longout>>1;
}
time = micros();
}
}

Ach ja die Seite

Ich bin nicht glücklich mit diesem Code - zu viele Strings, die auf kleinen Rechnern gerne mal Probleme machen. Character-Arrays wären da zu bevorzugen.
Aber sei's drum - Du hast alles beisammen, um den Meßwert ausgeben zu können.

            Serial.println(Ausgabe);    // original aber falsche Reihenfolge
            Serial.println(A);          // gekürzte original Reihenfolge
            Serial.println(Binar);      // richtige Reihenfolge

An dieser Stelle kannst Du ansetzen.

Ausgabe enthält die empfangenen Zeichen, deren Interpretation ist bekannt.
Um den Sketch nicht allzusehr durcheinader zu würfeln, basteln wir daraus mal einen Character-Array (kannst Du später mal global oder statisch machen und gleich bei der Datenaufnahme befüllen).

            //                       1                      2
            // 0 1 2 3  4 5 6 7  8 9 0 1  2 3 4 5  6 7 8 9  0 1 2 3
            // ?,X,X,X, X,X,X,X, X,X,X,X, X,X,X,X, ?,?,?,?, ?,Y,?,?
            char dataSet[25];
            strcpy(dataSet, Ausgabe.c_str());

Jetzt müssen wir die "verkehrten" Bytes (least significant bit at the start) in eine richtige Zahl wandeln - zunächst ganzzahlig. Die Wertigkeit jedes Bits (jeder Ziffer) steigt ja von 1 auf 2 auf 4 usw.

            int16_t ivalue = 0;   // integer value to be calculated
            int16_t avalue = 1;   // add value for each bit
            // X's for a binary number with least significant bit at the start of the string
            for (byte i = 1; i < 16; i++)   // klappere alle 15 'X'e ab
            {
                ivalue += (dataSet[i] == '1' ? 1 : 0) * avalue;
                avalue <<= 1;   // Wertigkeit erhöhen
            }

Am Ende noch schnell das Vorzeichen korrigieren:

            // Y = Sign bit if Y = 1 number is negative if Y = 0 number is positive
            if (dataSet[21] == '1')
                ivalue = -ivalue;

Und weil der übermittelte Wert das 100fache des Meßwerts ist müssen wir einmal dividieren:

            // The binary number is the distance in mm times 100.
            float fvalue = (float)ivalue / 100.;
            Serial.println(fvalue, 2);

Es kompiliert, ob es das richtige tut kann ich mangels Hardware nicht beurteilen.

1 Like

Wenn ich dein

richtig interpretiere (LSB first) empfängst du 0b1101101100 (0x36C = 876 = 8,76 mm ) ?

Falls ja, kannst du doch einfach das Bitmuster zusammen schiften (muss eine Schieblehre negative Werte können?) und und dann durch 100.0 dividieren?

@wno158 war schneller.

Moin,
so, Frühstück ist vorbei. Ich habe getestet ohne den Code von "foni" wirklich zu verstehen.
Er funktioniert . Bei der Ausgabe stimmt das Ergebnis zwar nur wenn ich Inch wähle an der Schieblehre. Aber das zu ändern (Umrechnen ) ist ja kein Hexenwerk.

Allerdings kommt jetzt das nächste Problem:
ich möchte die Ergebnisse nicht permanent auslesen sondern nur z.B. alle 5 Sekunden. Dazu hab ich eine Variable "fertig" eingesetzt die nach der Ausgabe des Ergebnisses auf 1 gesetzt wird und wiederum in der Loop zurückgesetzt wird. Funktioniert nicht.
Dann hab ich zusätzlich einen Zähler eingesetzt der nach dem Lesen von einem Bit jeweils um eins erhöht wird. Funktioniert auch nicht.
Wo ist der Gedankenfehler oder wie geht ihr das Problemchen an ???

Gruß Stefan

int dataIn = A0;
int clockIn = A2;
// Variables
int clock = 1;
int lastClock = 1;
unsigned long time = 0;
unsigned long Abfrage = 0;
//unsigned long timeStart = 0;
int out = 0;
long longout=0;
float finalout;

unsigned long Timer = 0;                    // Zeitintervall
unsigned long Timeout = 1000;               // Ausgabe Ergebnis im Sekundentakt
int fertig = 0;                             // while Schleife ,Start einer Messperiode
int zahler = 0;                             // 24 Bit gesammelt



void setup() 
{
  // Pin Set Up
  pinMode(dataIn, INPUT);
  pinMode(clockIn, INPUT);
  Serial.begin(115200);
  Serial.println("Ready: ");
}



void loop()
{
  if(millis() > Timeout + Timer ) 
    {  
      fertig = 0;
      zahler = 0;
      SchieberMessen();
      Timer = millis();
    }

}


void SchieberMessen()
{
  while (fertig == 0 && zahler < 25)
    {
      lastClock = clock;
      clock = digitalRead(clockIn);
      if (lastClock == 1 && clock == 0)
        {
          out = digitalRead(dataIn)+digitalRead(dataIn)+digitalRead(dataIn); // Tripple sampling to remove glitches
          if((micros() - time) > 1200)
            {
              longout=longout>>8;
              //%negative numbers switch to 2s complement
              if (longout & 0b00000000000010000000000000000000)
                {
                  longout=longout & 0b11111111111101111111111111111111;
                  longout=~longout + 1;
                }
              finalout=(float(longout)-1)/1000;
              Serial.print("data:");
              Serial.println(finalout,5);
              longout=0;

              Serial.print("Zähler ");
              Serial.println(zahler);
              if (zahler = 24) 
                {
                  fertig = 1;
                }  
              zahler = 0;  
            }
          else if((micros() - time) > 400)
            {
            }
          if (out > 1)
            {
              longout=longout|0b01000000000000000000000000000000;
              longout=longout>>1;
              zahler = zahler +1;
            }
          else
            {
              longout=longout>>1;
              zahler = zahler +1;
            }
          time = micros();
        }
    }  
}

Ich habe es mal ein bisschen umgestellt. Kann sein, dass es so nicht funktioniert, weil ich den Code selber etwas missverstanden habe. Aber probieren kannst Du ja mal:

constexpr byte DATA_IN_PIN {11};    // A0;
constexpr byte CLOCK_IN_PIN {12};   // A2;
constexpr unsigned long DELAY_MS {5000}; // time in milliseconds
// Variables
unsigned long delayTimer {0};

float readScale() {
  static byte clock {1};
  static byte lastClock {1};
  static unsigned long time;
  static unsigned long longout;

  while (true) {
    lastClock = clock;
    clock = digitalRead(CLOCK_IN_PIN);
    if (HIGH == lastClock && LOW == clock) {
      byte out = digitalRead(DATA_IN_PIN) + digitalRead(DATA_IN_PIN) +
                 digitalRead(DATA_IN_PIN);   // Tripple sampling to remove glitches
      if ((micros() - time) > 1200) {
        longout = longout >> 8;
        //%negative numbers switch to 2s complement
        if (longout & 0b00000000000010000000000000000000) {
          longout = longout & 0b11111111111101111111111111111111;
          longout = ~longout + 1;
        }
        float finalout = (float(longout) - 1) / 100;
        longout = 0;
        return finalout;   // Result determined. Exit the function.
      } else if ((micros() - time) > 400) {
      }

      if (out > 1) {
        longout = longout | 0b01000000000000000000000000000000;
        longout = longout >> 1;
      } else {
        longout = longout >> 1;
      }
      time = micros();
    }
  }
}

void setup() {
  // Pin Set Up
  pinMode(DATA_IN_PIN, INPUT);
  pinMode(CLOCK_IN_PIN, INPUT);
  Serial.begin(115200);
  Serial.println("Ready: ");
}

void loop() {
  if (millis() - delayTimer > DELAY_MS) {
    delayTimer = millis();
    Serial.print("data:");
    Serial.println(readScale());
  }
}

                if (longout & 0b00000000000010000000000000000000) {
          longout = longout & 0b11111111111101111111111111111111;
     
          longout = longout | 0b01000000000000000000000000000000;

ich finde mit bit(19) bzw. ~bit(19) und bit(30) würde das lesbarer werden

Hallo Kai-R,
so, 1:1 übernommen funktioniert es nicht.
Ergebnis =>

-> Ready:
10:54:44.206 -> data:-0.01
10:54:49.241 -> data:Ready:
10:54:55.265 -> data:-0.01
10:55:00.251 -> data:Ready:
10:55:06.133 -> data:-0.01
10:55:11.120 -> data:Ready:
10:55:16.958 -> data:-0.01
10:55:21.993 -> data:Ready:

Egal was ich am Messschieber eingestellt habe

Das sieht ja so aus, als würde der Controller permanent neu starten ?!

ich hab mich vielleicht missverständlich ausgedrückt.

Dieser Code funktioniert.

int dataIn = A0;
int clockIn = A2;
// Variables
int clock = 1;
int lastClock = 1;
unsigned long time = 0;
unsigned long Abfrage = 0;
//unsigned long timeStart = 0;
int out = 0;
long longout=0;
float finalout;



void setup() 
{
  // Pin Set Up
  pinMode(dataIn, INPUT);
  pinMode(clockIn, INPUT);
  Serial.begin(115200);
  Serial.println("Ready: ");
}



void loop()
{
  if ((millis() - Abfrage) > 5000)  
    {  
      SchieberMessen();
      Abfrage = millis;
    }

}


void SchieberMessen()
{
  lastClock = clock;
  clock = digitalRead(clockIn);
  if (lastClock == 1 && clock == 0)
    {
      out = digitalRead(dataIn)+digitalRead(dataIn)+digitalRead(dataIn); // Tripple sampling to remove glitches
      if((micros() - time) > 1200)
        {
          longout=longout>>8;
          //%negative numbers switch to 2s complement
          if (longout & 0b00000000000010000000000000000000)
            {
              longout=longout & 0b11111111111101111111111111111111;
              longout=~longout + 1;
            }
          finalout=(float(longout)-1)/1000;
          Serial.print("data:");
          Serial.println(finalout,5);
          longout=0;
        }
      else if((micros() - time) > 400)
        {
        }
      if (out > 1)
        {
          longout=longout|0b01000000000000000000000000000000;
          longout=longout>>1;
        }
      else
        {
          longout=longout>>1;
        }
      time = micros();
    }
}

Sobald ich auch nur einen Taster abfragen möchte kommt es zeitlich nicht mehr hin.
Jetzt war meine Idee nur einmal alles was in der Loop steht abzuarbeiten. Also separate void. AAAber es funktioniert nicht. Ich dachte ich spring in eine while Schleife und komme erst wieder raus wenn Variable "fertig" auf 1 gesetzt wird und 24 Bit gezählt wurden. Funktioniert bei nicht.

??????

Kai R so ist es

Hm, vielleicht bin ich ja gedanklich völlig auf dem Holzweg. Aber mich wundert, dass der Code in #13 funktioniert. Es müssen mindestens 24Bit eingelesen werden. Dafür sind 24 Durchläufe von SchieberMessen() notwendig. So wie ich das verstehe, müsste das Einlesen eines Wertes dann mal 24*5 Sekunden dauern...

nein alle 5 sek. 24 Bil einlesen. 24 Bit = ein Messergebnis

Also der Code den Du in #13 gepostet hast macht das nicht...

nein, es kommt kein Ergebnis

Da hast Du aber geschrieben, der würde funktionieren. Das ist etwas verwirrend.

Er funktioniert, aaaaaber

Sobald ich auch nur einen Taster abfragen möchte kommt es zeitlich nicht mehr hin.

Also sobald auch nur eine kleine Erweiterung in der Loop hinzu kommt, ist es beim messen mit dem Timing veorbei.

Gruß