2 x 24 Bit einlesen (Messschieber)

Hallo,

ich versuche vom Messschieber die 2x 24 Bit einzulesen. Als Vorlage diente ein Artikel aus der c’t Hardware Hacks 4-2013. Dort reichte aber 1x24Bit mit anderen Takt/Data Zyklen.

Jetzt habe ich mir die Logiklevel anzeigen lassen und versucht die Timings auszulesen. Hier bin ich bestimmt auf dem Holzweg bin. :~

// Messschieber mittels OPV LM393 angeschlossen, nicht invertierend
// Arduino Mega 2560

int i;
int LED = 7;
long value;
unsigned long FirstData;
unsigned long SecondData;
int clockpin = 24;  
int datapin = 25;
unsigned long Start_LOW;
unsigned long Ende_LOW;
unsigned long Dauer_LOW;
unsigned long Start_HIGH;
unsigned long Ende_HIGH;
unsigned long Dauer_HIGH;

void setup() {

  Serial.begin(9600);
  pinMode(clockpin, INPUT);
  pinMode(datapin, INPUT);
  pinMode(LED, OUTPUT);
  
}

 void loop () {

  while (digitalRead(clockpin)==LOW) {}    // wenn Clock HIGH warte bis er LOW ist
  Start_LOW = micros();                    // aktuellen Zeitpunkt einlesen
    
  while (digitalRead(clockpin)==HIGH) {}   // warten bis Clock wieder HIGH ist
  Ende_LOW = micros();    
  
  while (digitalRead(clockpin)==LOW) {}   // warten bis Clock wieder LOW ist
  Ende_HIGH = micros();    
  
  Dauer_LOW = Ende_LOW - Start_LOW;     // Länge LOW Pegel
  Dauer_HIGH = Ende_HIGH - Ende_LOW;    // Länge HIGH Pegel
  
  if ((Dauer_LOW > 30) && (Dauer_HIGH < 50))  // der Start 46µs HIGH-Pegel soll eingefangen werden
     {   
      decode();      //decode the bit sequence
     }
}  // Ende loop
 

void decode() {
  digitalWrite(LED, HIGH);
 
  FirstData=0;
  SecondData = 0;
  
  for (i=0;i<23;i++)    // die ersten 24 Bit einlesen
    {
     while (digitalRead(clockpin)==LOW) {}   // warten bis Clock wieder auf LOW ist

     while (digitalRead(clockpin)==HIGH) {}  // warten bis Clock wieder auf HIGH ist, dann Data einlesen

     if (digitalRead(datapin)==HIGH)
       {
        if (i<20) 
          {
           FirstData = FirstData | (1<<i);    // Bit einlesen mit ODER verknüpfen und eine Stelle nach links
          }                                   // Kurzform:  value|=1<<i;
       }
     }  // Ende 24 Bit einlesen


  for (i=0;i<23;i++)    // die zweiten 24 Bit einlesen
    {
     while (digitalRead(clockpin)==LOW) {}    // warten bis Clock wieder auf LOW ist

     while (digitalRead(clockpin)==HIGH) {}   // warten bis Clock wieder auf HIGH ist, dann Data einlesen

     if (digitalRead(datapin)==HIGH)
       {
        if (i<20) 
          {
           SecondData = SecondData | (1<<i);  // Bit einlesen mit ODER verknüpfen und eine Stelle nach links
          }                      
       }
     }  // Ende 24 Bit einlesen

  Serial.print("First  ");
  Serial.println(FirstData,BIN);  // die ersten 24 Bit
  Serial.print("Second ");
  Serial.println(SecondData,BIN); // die zweiten 24 Bit
  digitalWrite(LED, LOW);   

  //delay(1000);

}

Im Serialmonitor bekomme ich solchen Müll angezeigt, wenn ich oben versuche den 46µs High Pegel einzufangen. Bekomme also keine stabilen 32Bit Binärwerte.
Die Kontroll LED blinkt gut sichtbar im Takt. Wäre für mich aber eher ein Zeichen das etwas schief läuft. Denn der die müßte ca. im 2ms Takt leuchten, womit ich die LED nicht locker blinken sehen dürfte.

Am Anfang dachte ich, ich muß nur warten bis der Lowpegel länger als 900µs dauert. Dann passiert aber gar nichts. Möglicherweise täusche ich mich hier und der steht keine 964µs an.

Wie fängt man den Anfang richtig ein?

First  11111111111111111010000000000100
Second 10100000000000
First  11111111111111111111000000010011
Second 10011010111
First  11111111111111111101000000010011
Second 10011100111
First  11111111111111111010000000000011
Second 1001101011111
First  11111111111111111011000000010011
Second 100110001111
First  10000000000100
Second 10010000000000
First  11111111111111111000000000100100
Second 10110000000000
First  10000000000010
Second 101000000000000
First  11111111111111111100000000010011
Second 1010001111
First  11111111111111111010000000000101
Second 110001111
First  10010
Second 100110101111
First  1000000010011
Second 100101111
First  11111111111111111110000000000011
Second 100111001111
First  11111111111111111010000000000011
Second 10001001111
First  1000000010011
Second 1011000000000
First  100000000010010
Second 1110000000000
First  11
Second 100000000000000
First  110000000000010
Second 10000000000000
First  110000000000100
Second 10100000000000
First  110000000000010
Second 11111111111111111001010000000000
First  110000000100100
Second 1010000000000
First  10000000100100
Second 10010000000000
First  11111111111111111010000000000010
Second 10010000000000
First  110000000000010
Second 101010000000000
First  10010
Second 10010000000000
First  110000000000010
Second 11111111111111111001011000000000

Hallo, Doc!

Ich finde leider die entsprechende Webseite nicht mehr. Dort wurde gesagt, dass die ersten 24 bit eine absolute Position des Messschiebers anzeigen, die aber für Messzwecke nicht verwendbar sind ( warum, weiss ich nicht mehr ). Die zweiten 24 bit sollen ausgelesen und dann auch dargestellt werden können. Frag mich aber nicht, wie Du aus dem gesamten Datenpaket die ersten 24 bit ausfiltern kannst :-( . Hier sind aber so viele Menschen mit Ahnung unterwegs, die werden Dir schon helfen können.

Viele Grüße

Franjo

Hallo,

Du meinst vielleicht den Link hier. yadro.de - yadro Resources and Information.

Das filtern der ersten 24Bit wäre kein Problem. Ich möchte ja beide einlesen. Am Ende muß ich ja nur mit den letzten 24Bit arbeiten und die ersten gar nicht beachten. Sind ja jeweils in getrennten Variablen gespeichert. Ich muß jedoch erstmal den Anfang sicher erkennen können.

Jedoch kann ich deren Beschreibung laut meiner Auffassung nicht ganz folgen. Den beschriebene “Glitch” sehe ich auch, der signalisiert das die Position positiv ist. Bin ich im negativen ist der Glicht nicht da. Deswegen bin ich mir nicht sicher ob man wirklich nur bei Clock Low lesen soll.

Bin jedoch der Meinung das es erstmal egal ist ob ich bei H oder L lese, ich muß überhaupt erstmal beide 24Bit Werde überhaupt einlesen können. Ob nun H / L verdreht ist oder nicht. Denke ich jedenfalls.

Einen überall verwendeten Standard gibts eh nicht. Gibt scheinbar immer paar kleine Abweichungen. Das Prinzig ist jedoch gleich.

Hat wer Ideen?

Hallo,

durch weitere Eingrenzungen habe ich mir nur alle Zeiten der HIGH-Pegel anzeigen lassen und es kamen stabile Werte von 48, 112, 56 immer hintereinanderraus. Das stimmt mit dem Logic-Analyzerdiagramm überein.
Dann habe ich mir alle Zeiten der LOW Pegel größer 10µs anzeigen lassen. Hier war erstaunen. Es wurde immer konstant 319028 angezeigt. Bedeutet das, dass der letzte Low-Pegel immer 319ms dauert? Kann das sein?

Habe dann den Code erstmal eingekürzt und fange mir sicher die “mittleren 110µs” ein. Damit sollte ich immer das 2. 24Bit Signal holen. Allerdings bekomme ich immer nur 0 angezeigt.
Irgendwas stimmt mit dem digitalRead und bitshift nicht.

Wo liegt mein Denkfehler?

Edit: durch die UND Verknüpfung lösche ich mir alle vorherigen Bits. Stimmts? Nur wie macht man das dann?

// Digitalmessschieber auslesen
// http://www.heise.de/hardware-hacks/links/1304156
// c't Hardware Hacks 4/2013

// Messschieber mittels OPV LM393 angeschlossen, nicht invertierend
// Arduino Mega 2560

int i;
unsigned long Signal;
int LED = 7;
long value;
unsigned long FirstData;
unsigned long SecondData;
int clockpin = 24;  
int datapin = 25;
unsigned long Start_LOW;
unsigned long Ende_LOW;
unsigned long Dauer_LOW;
unsigned long Start_HIGH;
unsigned long Ende_HIGH;
unsigned long Dauer_HIGH;

void setup() {

  Serial.begin(9600);
  pinMode(clockpin, INPUT);
  pinMode(datapin, INPUT);
  pinMode(LED, OUTPUT);
  
}

 void loop () {
    
  while (digitalRead(clockpin)==LOW) {}    // wenn Clock LOW warte bis er HIGH ist
  Start_HIGH = micros();                   // aktuellen Zeitpunkt einlesen
    
  while (digitalRead(clockpin)==HIGH) {}   // Clock ist HIGH, warten bis Clock wieder LOW ist
  Ende_HIGH = micros();    

  Dauer_HIGH = Ende_HIGH - Start_HIGH;    // Länge HIGH Pegel
  
  if ((Dauer_HIGH > 60) && (Dauer_HIGH < 150))  // der 110µs HIGH-Pegel soll eingefangen werden
     {   
      decode();      //decode the bit sequence
     }
}  // Ende loop
 

void decode() {
  
  SecondData = 0;
  
  for (i=0;i<23;i++) {        // 24 Bit einlesen

    while (digitalRead(clockpin)==HIGH) {}  // warten bis Clock wieder LOW ist
    while (digitalRead(clockpin)==LOW) {}   // warten bis Clock wieder HIGH ist
    
    Signal = digitalRead(datapin);
    Signal = Signal << i;              // um n.Stelle verschieben
    SecondData = SecondData & Signal;  // UND verknüpfen
                                 
}  // Ende 24 Bit einlesen

   Serial.println(SecondData,BIN);  
   delay(1000);
   
}  // Ende decode

Hallo,

einzulesendes Datasignal sollte mit ODER verknüpft werden. Bin mir sicher das es richtig ist? Dennoch kommt Müll rein. Nach weiteren Versuchen habe ich mal die Zeit der for Einleseschleife gestoppt. Das dauert ca. 1ms. Das wäre aber viel zu langsam, wenn das Taktverhältnis High 6,2µs und Low 6,7µs beträgt. 24 mal 12,9µs sind 309,6µs für eine Übertragung.

Was nun machen?

// Digitalmessschieber auslesen
// http://www.heise.de/hardware-hacks/links/1304156
// c't Hardware Hacks 4/2013

// Messschieber mittels OPV LM393 angeschlossen, nicht invertierend
// Arduino Mega 2560

int i;
unsigned long Signal;
int LED = 7;
long value;
unsigned long FirstData;
unsigned long SecondData;
int clockpin = 24;  
int datapin = 25;
unsigned long Start_LOW;
unsigned long Ende_LOW;
unsigned long Dauer_LOW;
unsigned long Start_HIGH;
unsigned long Ende_HIGH;
unsigned long Dauer_HIGH;

void setup() {

  Serial.begin(9600);
  pinMode(clockpin, INPUT);
  pinMode(datapin, INPUT);
  pinMode(LED, OUTPUT);
  
}

 void loop () {
    
  while (digitalRead(clockpin)==LOW) {}    // wenn Clock LOW warte bis er HIGH ist
  Start_HIGH = micros();                   // aktuellen Zeitpunkt einlesen
    
  while (digitalRead(clockpin)==HIGH) {}   // Clock ist HIGH, warten bis Clock wieder LOW ist
  Ende_HIGH = micros();    

  Dauer_HIGH = Ende_HIGH - Start_HIGH;    // Länge HIGH Pegel
  
  if ((Dauer_HIGH > 60) && (Dauer_HIGH < 150))  // der 110µs HIGH-Pegel soll eingefangen werden
     {   
      decode();      //decode the bit sequence
     }
}  // Ende loop
 

void decode() {
  
  SecondData = 0;
  Serial.println(micros());  
  
  for (i=0;i<23;i++) {        // 24 Bit einlesen

    //while (digitalRead(clockpin)==LOW) {}    // warten bis Clock wieder HIGH ist
    while (digitalRead(clockpin)==HIGH) {}   // warten bis Clock wieder LOW ist
    
    Signal = digitalRead(datapin);
    Signal = Signal << i;              // um n.Stelle verschieben
    SecondData = SecondData | Signal;  // ODER verknüpfen
                                 
}  // Ende 24 Bit einlesen
   
   Serial.println(micros());  
   
   SecondData = SecondData >> 3;    // letzten 3 Stellen löschen
   //Serial.println(SecondData,BIN);  
   //Serial.println(SecondData);  
   delay(2000);
   
}  // Ende decode

Hallo, Doc!

Doc_Arduino: Jedoch kann ich deren Beschreibung laut meiner Auffassung nicht ganz folgen. Den beschriebene "Glitch" sehe ich auch, der signalisiert das die Position positiv ist. Bin ich im negativen ist der Glicht nicht da. Deswegen bin ich mir nicht sicher ob man wirklich nur bei Clock Low lesen soll.

Ein Glitch ist lt. Definition (http://de.wikipedia.org/wiki/Glitch_%28Elektronik%29) eine Störung. Er mag zufällig bei positiven Werten auftreten und nicht bei negativen. Der Glitch kann aber sicher nicht zum Erkennen von positiven und negativen Werten herangezogen werden.

Bei dem 1 x 24 bit-Protokoll ist es Bit Nr. 20, mit dem bei LOW ein negativer Wert dargestellt wird ( schaue dazu mal in meinen Thread http://forum.arduino.cc/index.php?topic=210741.msg1546665#msg1546665 )

Soweit ich mich erinnern kann, ist auch bei dem 2 x 24 Bit-Protokoll ein Bit dafür verantwortlich, möglicherweise Bit Nr. 23, aber ich weiß es nicht mehr genau.

Viele Grüße

Safran

So, eine der Seiten habe ich wiedergefunden:

http://www.pcbheaven.com/exppages/Digital_Caliper_Protocol/?topic=chinesebin

Vielleicht hilft sie Dir weiter.

Viele Grüße

safran

Hallo,

Danke für den Link. Meine Timings der Pausen sind etwas andere. Sollte nicht da Problem sein.

Ich habe erstmal alles verwurfen. Zurück zu den Basics. Sonst bekomme ich eine Macke.

Gehe ich richtig in der Annahme, dass folgender Code eine HIGH Pulselänge von länger wie 80µs einfängt und nur dann in die decode Funktion springt?

while (digitalRead(clockpin)==LOW) {}  // wenn Clock LOW, dann warten bis er wieder HIGH ist

  tempmicros=micros();                       // aktuelle Zeit nehmen

  while (digitalRead(clockpin)==HIGH) {} // wenn Clock HIGH, dann warten bis er wieder LOW ist

  if ((micros()-tempmicros)>80) {         // wenn HIGH Puls länger wie 80µs, dann starte dekodieren

    decode(); //decode the bit sequence
    {

Hallo,

kann es sein das die decode Funktion zu lange dauert?

Habe gerechnet. Ein Takt dauert doch nur 62,5ns bei 16MHz. Ein Takt vom Messschieber dauert 6,25µs. Würde doch bedeuten, er für alles 100 Takte Zeit hat. Ist das zu wenig?

Da ich mir nicht sicher war, habe ich in decode Funktion ein an/aus LED Taktsignal eingebaut für das Oszi. Ohne die Formeln und Serial Ausgaben. Hier sah ich das die LED nie am Ende der 24 Takte aus ging.

Dann habe ich mir 'ne Waffel gemacht wie man das schneller machen kann. Dazu mußte ich viel lesen und probieren ohne die schönen Arduino Befehle. Damit ist jetzt die “LED” zu 99% nur solange an wie die 24 Takte dauern. Dennoch habe ich eine Frage zu der for Schleifen.

Ich fange in der loop den 110µs mittleren High-Pegel ein. Bedeutet wenn ich in die decode Funktion springe ist der Takt noch im ersten Low-Pegel. Jetzt warte ich wieder einen High/Low Wechsel ab. Das würde aber bedeuten, dass ich das erste Datenbit verpasse. Wäre nicht weiter schlimm. Aber wenn die for Schleife von 0 bis 23 zählt, also 24x durchlaufen wird, dann müßte doch mein künstliches Überwachungssignal noch länger dauern. Also erst wieder die LED abschalten wenn der letzte 58µs lange High pegel vorbei ist. Wie auf dem letzten Bild zu sehen.

Genau das macht er aber nicht. Zu 99% haut das hin. Nur ganz selten ist er zu lang.

im Gesamtüberblick

so sieht das zu 99% passend aus, “LED ein/aus Takt” ist nur in den Taktpegel hinneingeschoben damit man das besser sieht

Und manchmal sieht das so, eine Taktphase zu lang, Zufallstreffer mit dem Fotoapparat.

Muß man damit leben, weil die Auswertung wirklich so Zeit kritisch ist oder gibts noch Möglichkeiten zur Optimierung? Denn wenn das passiert, würde es bedeuten das er mittendrin ein Taktsignal nicht erfassen konnte.

// Arduino Mega 2560

#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))   // setzt das angegebene Bit auf 1
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))  // setzt (löscht) das angegebene Bit auf 0
#endif

int sign = 1;

long value;

float result;

int clockpin = 24;  

int datapin = 25;

unsigned long tempmicros;


void setup() {

  Serial.begin(9600);

  DDRC  = 0b11111111;          // Port.C alles Ausgänge
  PORTC = 0b00000000;          // Port.C alles AUS  
  
  pinMode(clockpin, INPUT);
  pinMode(datapin, INPUT);

}


 void loop () {

  while (digitalRead(clockpin)==LOW) {}  // wenn CLOCK auf LOW, dann warten bis wieder HIGH

  tempmicros=micros();                   // aktuelle Zeitnahme

  while (digitalRead(clockpin)==HIGH) {} // wenn CLOCK auf HIGH, warten bis wieder LOW

  if ((micros()-tempmicros)>80)          // wenn High-Pegel länger wie 80µs war, springe in 'decode' Funktion
    {     
     decode();   // dekodiere das Datensignal
    }
}

void decode() {
    
  sbi (PORTC, 0);        // Pin 37 (Port.C Bit.0) einschalten
  
  for (int i=0;i<23;i++) {

    while ( !(PINA & (1 << PA2)))  { }  // solange warten bis Clock (Port.A Bit.2) wieder HIGH ist
    
    while ( PINA & ( 1 << PA2 ))  { }   // solange warten bis Clock (Port.A Bit.2) wieder LOW ist
     
    if ( PINA & ( 1 << PA3 )) 
      {
       value |= 1<<i;
      }
    
  }  // Schleifenende

 
  cbi (PORTC, 0);        // Pin 37 (Port.C Bit.0) ausschalten 
  
  value=0;
}

Hallo,

ich habe jetzt paar Meßwerte zum Test ausgelesen und habe festgestellt, dass die Schrittweite von 0mm weg, immer etwas weiter abdriftet. Sodass ich seltsamerweis nicht genau zurück auf die Werte im Display rechnen kann. Es ist auch egal ob ich die ersten 3 Bits mit zur Rechnung verwende oder nicht. Es ist demnach nicht zu 100% das Sylvac Protokoll.

Hat jemand einen Tipp zum umrechnen oder spinnt der Messschieber? Also könnte es sein das er andere Werte an der Schnittstelle ausgibt wie er selbst anzeigt?

Messschieber_Daten.xls (143 KB)

Hallo,

warum wird der einzulesende Wert ab mehr wie 16 Durchläufen in den höherwertigen Bits mit 1 aufgefüllt?
Die Variable value ist mit unsigned long deklariert und wird am Ende wieder auf 0 gesetzt.
Beim einlesen der maximal vorhandenen 24 Bits, ich lese nur 23 ein, müßten die oberen Bits Nullen sein. Sie sind aber 1.
Sobald ich die for Schleife mehr wie 16x durchlaufen lasse werden mir die höherwertigen Stellen mit 1 aufgefüllt statt mit 0. Warum das denn? Das ist für mich nicht nachvollziehbar.

// Arduino Mega 2560

int LED = 5;

unsigned long value = 0;

float result;

int clockpin = 24;  

int datapin = 25;

unsigned long tempmicros;

void setup() {

  Serial.begin(9600);
  
  pinMode(clockpin, INPUT);
  pinMode(datapin, INPUT);
  pinMode(LED, OUTPUT);

}


 void loop () {

  while (digitalRead(clockpin)==LOW) {}  // wenn CLOCK auf LOW, dann warten bis wieder HIGH

  tempmicros=micros();                   // aktuelle Zeitnahme

  while (digitalRead(clockpin)==HIGH) {} // wenn CLOCK auf HIGH, warten bis wieder LOW

  if ((micros()-tempmicros)>80)          // wenn High-Pegel länger wie 80µs war, springe in 'decode' Funktion
    {     
     decode();   // dekodiere das Datensignal
    }
}

void decode() {
     
  for (int i=0;i<23;i++) {

    while ( !(PINA & (1 << PA2)))  { }  // solange warten bis Clock (Port.A Bit.2) wieder HIGH ist
    
    while ( PINA & ( 1 << PA2 ))  { }   // solange warten bis Clock (Port.A Bit.2) wieder LOW ist
                                        // durch diese Abfrage geht Bit 0 bzw. der erste Takt verloren
     
    if ( PINA & ( 1 << PA3 )) 
      {
       value |= 1<<i;
      }
    
  }  // Schleifenende

  value = value >> 1;          // die erste Stelle rausschieben, wird nicht benötigt,
                               // damit wird das originale Bit 2 zu Bit 0
  Serial.println(value,BIN);   // 
  Serial.println(value);       // 
  
  delay(1000);
    
  value=0;
}

Elende default 16 bit int arithmetik !
statt

value |= 1<<i;

probier mal
[b]value |= 1UL << i; [/b]

sonst seh ich auch kein signed int in deinem code …

Jetzt wo du es sagst…

Genau das gleiche Problem hatte ich bei meiner Bitset Klasse

Hallo,

vielen Dank für den 1A Hinweis. Damit funktioniert es. :)

Steht das UL für unsigned long? Warum muß man das extra angeben? Die Variable ist doch schon so deklariert.

Ich hatte mich noch mit der Notlösung value = value & 0x3FFFFF beholfen, aber das funktionierte ab ca. 81mm nicht mehr. Entspricht einem eingelesenen Wert von 4177967. Ein Bitüberlauf konnte ich auch nicht nachvollziehen. Er springt dann auf Werte wie 16375 um. Womit natürlich am Ende Müll raus kommt.

Ich war die Tage so schon am verzweifeln. Jetzt funktioniert die Rechnung mit positiven Werten. Die negativen bekomme ich jetzt auch noch hin. ;)

Beim kompilieren des alten Codes erhalte ich manchmal, nicht immer, noch folgende Fehlermeldung im IDE.

C:\Portable Apps\Arduino IDE\hardware\tools\avr\bin\avr-ar: unable to rename 'core.a'; reason: File exists Binäre Sketchgröße: 6.810 Bytes (von einem Maximum von 258.048 Bytes)

“1” ist keine Variable, sondern ein Literal:

Integer-Literale sind standardmäßig int und damit hier 16 Bit. Auf dem PC wären es 32, bzw. 64 Bit, je nach Compiler Einstellung und Sprache. Wenn man mehr oder weniger braucht muss man das explizit angeben.

Hallo,

das Hauptgerüst vom Code ist jetzt fertig und dokumentiert. Ich stelle den Code dem Forum zur Verfügung. Danke an die Leute die geholfen haben.

Bevor Fragen kommen. Ich verwerfe bewußt die ersten beiden Bits der zweiten 24Bit, weil die mir viel zu sehr zappeln. :slight_smile: Wer alle 24 Bit verarbeiten möchte, hat dann statt einer Auflösung von 5120 Steps pro inch eben 20480 Steps pro inch.

/*

µC Arduino Mega 2560
Doc Arduino by http://forum.arduino.cc
auslesen eines Messschiebers mit Sylvac Protokoll (2 x 24Bit)
Takt an Pin 24
Data an Pin 25
Beide Signale vom Messschieber werden mittels OPV LM393 nicht invertierend auf 5V Pegel angehoben
Die zweiten 24 Bit werden eingelesen indem auf die mittlere Pause zwischen den beiden 24Bit Übertragrungen gewartet wird.
Diese Pause beträgt bei meinem Messschieber 110µs. Davor und danach sind ca. 60µs.
Am Ende der Verarbeitung werden die ersten beiden Bits verwurfen, sodass noch eine Auflösung von 5120 Steps pro Inch besteht.

*/

long value = 0;

float result;

int ClockPin = 24;  // in der decode Funktion ist Pin 24 das 2. Bit vom Port A (PINA PA2)

int DataPin = 25;   // in der decode Funktion ist Pin 25 das 3. Bit vom Port A (PINA PA3)
                    // der Arduino 'digitalRead' Befehl ist leider zu langsam, ein Clock High
                    // bzw. Low Pegel ist 6,7 bzw. 6,3µs lang

unsigned long tempmicros;

void setup() {

  Serial.begin(9600);
  
  pinMode(ClockPin, INPUT);
  pinMode(DataPin, INPUT);

}


 void loop () {

  while (digitalRead(ClockPin)==LOW) {}  // wenn CLOCK auf LOW, dann warten bis wieder HIGH

  tempmicros=micros();                   // aktuelle Zeitnahme

  while (digitalRead(ClockPin)==HIGH) {} // wenn CLOCK auf HIGH, warten bis wieder LOW

  if ((micros()-tempmicros)>80)          // wenn High-Pegel länger wie 80µs war, springe in 'decode' Funktion
    {     
     decode();                           // Anfang der zweiten 24 Bit erkannt, dekodiere das Datensignal
    }
}  // loop ENDE


void decode() {
      
  for (int i=0;i<23;i++)                 // 23 Durchläufe
    {
     while ( !(PINA & (1 << PA2)))  { }  // solange warten bis Clock (Port.A Bit.2) wieder HIGH ist
     while ( PINA & ( 1 << PA2 ))  { }   // solange warten bis Clock (Port.A Bit.2) wieder LOW ist
                                         // durch diese Abfrage am Anfang geht Bit 0 bzw. der erste Takt verloren
     
     if ( PINA & ( 1 << PA3 ))           // wenn Data (Port.A Bit.3) HIGH ist, dann schreibe 
       {                                 // eine 1 in die Variable 'value' an Bitnummer i
        value |= 1UL << i;               // Syntax Hinweis aus dem Forum, wegen default 16 bit int Arithmetik
       }
    
    }  // for Schleifenende

  value = value >> 1;          // die erste Stelle rausschieben, wird nicht benötigt,
                               // damit wird das originale Bit 2 zu Bit 0
 
  // Serial.println(value);       // der eingelesene und zurecht gerückte Rohwert (Schritte)
  
   if (value >= 0 & value < 32000)     // negative Meßwerte
     {
      result = (value/5120.0*(-25.4)); // Umrechnung in [mm] für negative Messwerte, 1 mm entspricht 201,5748 Schritte
      Serial.print(result,2);          // Anzeige in [mm]
      Serial.println(" mm"); 
      result = (value/ -5120.0);       // Umrechnung in [inch] für negative Messwerte, 1 inch entspricht 5120 Schritte
      Serial.print(result,3);          // Anzeige in [inch]
      Serial.println(" inch"); 
     }     
   
   if (value >= 4162000 & value < 4195000)  // positive Meßwerte, der Rest wird als Datenmüll verwurfen
     {  
      result = (4194303-value)/201.5748; // Umrechnung in [mm] für positive Messwerte, 1 mm entspricht 201,5748 Schritte
      Serial.print(result,2);            // Anzeige in [mm]
      Serial.println(" mm"); 
      result = (4194303-value)/5120.0;   // Umrechnung in [inch] für positive Messwerte, 1 inch entspricht 5120 Schritte
      Serial.print(result,3);            // Anzeige in [inch]
      Serial.println(" inch"); 
     }
   
   value=0;
   
   delay(1000);
   
}

Hallo,

das Messwert zappeln lag an etwas anderem. Habe nun die vollen 24 Bit genutzt.
Funktioniert nun auch. :slight_smile:

/*

µC Arduino Mega 2560
Doc Arduino by http://forum.arduino.cc
auslesen eines Messschiebers mit Sylvac Protokoll (2 x 24Bit)
Takt an Pin 24
Data an Pin 25
Beide Signale vom Messschieber werden mittels OPV LM393 nicht invertierend auf 5V Pegel angehoben
Die zweiten 24 Bit werden eingelesen indem auf die mittlere Pause zwischen den beiden 24Bit Übertragrungen gewartet wird.
Diese Pause beträgt bei meinem Messschieber 110µs. Davor und danach sind ca. 60µs.
Am Ende der Verarbeitung werden die ersten beiden Bits verwurfen, sodass noch eine Auflösung von 5120 Steps pro Inch besteht.

volle 24Bit Meßwertnutzung

*/

long value = 0;

float result;

int ClockPin = 24;  // in der decode Funktion ist Pin 24 das 2. Bit vom Port A (PINA PA2)

int DataPin = 25;   // in der decode Funktion ist Pin 25 das 3. Bit vom Port A (PINA PA3)
                    // der Arduino 'digitalRead' Befehl ist leider zu langsam, ein Clock High
                    // bzw. Low Pegel ist 6,7 bzw. 6,3µs lang

unsigned long tempmicros;

void setup() {

  Serial.begin(9600);
  
  pinMode(ClockPin, INPUT);
  pinMode(DataPin, INPUT);

}


 void loop () {

  while (digitalRead(ClockPin)==LOW) {}  // wenn CLOCK auf LOW, dann warten bis wieder HIGH

  tempmicros=micros();                   // aktuelle Zeitnahme

  while (digitalRead(ClockPin)==HIGH) {} // wenn CLOCK auf HIGH, warten bis wieder LOW

  if ((micros()-tempmicros)>80)          // wenn High-Pegel länger wie 80µs war, springe in 'decode' Funktion
    {     
     decode();                           // Anfang der zweiten 24 Bit erkannt, dekodiere das Datensignal
    }
}  // loop ENDE


void decode() {
      
  for (int i=0;i<24;i++)                 // 24 Durchläufe, 0 bis 23
    {
          
     if ( PINA & ( 1 << PA3 ))           // wenn Data (Port.A Bit.3) HIGH ist, dann schreibe 
       {                                 // eine 1 in die Variable 'value' an Bitnummer i
        value |= 1UL << i;               // Syntax Hinweis aus dem Forum, wegen default 16 bit int Arithmetik
       }
    
     while ( !(PINA & (1 << PA2)))  { }  // solange warten bis Clock (Port.A Bit.2) wieder HIGH ist
     while ( PINA & ( 1 << PA2 ))  { }   // solange warten bis Clock (Port.A Bit.2) wieder LOW ist
                                         // durch diese Abfrage am Anfang geht Bit 0 bzw. der erste Takt verloren
                                         
    }  // for Schleifenende

   // Serial.println(value);           // der eingelesene und zurecht gerückte Rohwert (Schritte)
  
   if (value >= 0 & value < 150000)    // negative Meßwerte
     {
      result = (value/ -806.3);        // Umrechnung in [mm] für negative Messwerte, 1 mm entspricht 201,5748 Schritte
      Serial.print(result,2);          // Anzeige in [mm]
      Serial.println(" mm"); 
      result = (value/ -20480.0);      // Umrechnung in [inch] für negative Messwerte, 1 inch entspricht 5120 Schritte
      Serial.print(result,2);          // Anzeige in [inch]
      Serial.println(" inch"); 
     }     
   
   if (value >= 16600000 & value < 16780000)  // positive Meßwerte, der Rest wird als Datenmüll verwurfen
     {  
      result = (16777215-value)/806.3;        // Umrechnung in [mm] für positive Messwerte, 1 mm entspricht 201,5748 Schritte
      Serial.print(result,2);                 // Anzeige in [mm]
      Serial.println(" mm"); 
      result = (16777215-value)/20480.0;      // Umrechnung in [inch] für positive Messwerte, 1 inch entspricht 5120 Schritte
      Serial.print(result,2);                 // Anzeige in [inch]
      Serial.println(" inch"); 
     }
   
   value=0;
   
   delay(1000);
   

}

Hallo, Doc !

Schön, das es bei Dir geklappt hat. Zur Signalaufbereitung nutzt Du einen OPV

Beide Signale vom Messschieber werden mittels OPV LM393 nicht invertierend auf 5V Pegel angehoben.

Könntest Du dazu den Schaltplan veröffentlichen? Ich muss 8 Signale aufbereiten und habe wenig Lust, dies diskret aufzubauen. Mit OPV kenne ich mich nun gar nicht aus.

Viele Grüße

Safran

http://www.mikrocontroller.net/articles/Operationsverst%C3%A4rker-Grundschaltungen

Hallo,

in sschultewolter seinem Link ist alles zum OPV schön beschrieben. Ich nutze den OPV als nichtinvertierenden Komparator. Quasi ein Schmittrigger ohne Hysterese. Mittels dem 10k Poti habe ich als Umschaltpunkt 0,8V eingestellt. 0,6 - 0,8V. Was ich jetzt vergessen habe einzuzeichnen ist ein 15k Widerstand am OPV Ausgang gegen +5V. Steht aber im Datenblatt drin.

LM393 deswegen, weil der mit 5V klar kommt. Ein alter 741 funktioniert leider nicht.

Edit: hab noch meine Exceltabelle rangehangen zum nachvollziehen zur Rechnung vom 24bit Messwert und Umrechnung

Messschieber_Daten.zip (36.4 KB)