2 x 24 Bit einlesen (Messschieber)

Super!

Dank an Euch beide.

Die Antwort wäre in einem anderen Forum nicht so ausgefallen ;) Ich glaub die hätten dich da jetzt schon gesteinigt oder einfach nur ignoriert.

sschultewolter: Die Antwort wäre in einem anderen Forum nicht so ausgefallen ;) Ich glaub die hätten dich da jetzt schon gesteinigt oder einfach nur ignoriert.

Ja, da hast Du vollkommen recht. Genau deshalb mag ich dieses Forum. Keiner vergibt sich etwas, dem anderen zu helfen statt ihn niederzumachen. Und in vielen Fällen ist es auch nicht so, dass der Ratsuchende nicht vorher selbst gesucht hat, aber vor der überwältigenden Fülle an Informationen ( die nicht immer richtig sein müssen ) im Web einfach kapituliert.

Viele Grüße

Safran

Hallo zusammen,

es tut mir leid, aber ich muss dieses Thema noch einmal ausgraben.

Verstehe ich es richtig, dass der clock und data Pin des Messschieber direkt und ohne Umwege beide gemeinsam mit dem positiven Eingang des OPVs verbunden werden? So wie es im Bild von Doc_Arduino zu sehen ist (siehe Anhang)?

Vielen Dank und Grüße,
Bratapfel

Du kannst Bilder direkt hier einstellen:

  1. Schritt: Bild als Attachment anhängen
  2. Schritt: den link auf dieses Attachment im IMG-Tag einbinden.

Gruß Tommy

Hi

  1. das Bild:
    0fc5687962f90a1548bf008a95c3ca6327a59f4c.png
    (man kann auch warten, bis Das ein Forum-Member macht :wink:

Ich verstehe den Plan so, daß SOWOHL clock wie auch data die gleiche Schaltung benütigen, man Diese deshalb auch nur 1x zeichnen muß.
Aber Beide brauchen eine EIGENE Schaltung - klingt auch logisch, da Clock und Data sich unabhängig von einander ändern können müssen.

Man könnte das Gezeigte Signalaufbereitung nennen.

MfG

Hallo,

postmaster-ino: Hi

Ich verstehe den Plan so, daß SOWOHL clock wie auch data die gleiche Schaltung benütigen, man Diese deshalb auch nur 1x zeichnen muß. Aber Beide brauchen eine EIGENE Schaltung - klingt auch logisch, da Clock und Data sich unabhängig von einander ändern können müssen. Man könnte das Gezeigte Signalaufbereitung nennen.

MfG

genauso ist das. Man könnte auch Levelshifter dazu sagen.

Super, vielen Dank für die Antworten. Das hat mir sehr weiter geholfen.
Die Sache mit dem Bild hat komischerweise nicht richtig funktioniert, es wurde immer unscharf. Deshalb habe ich es als Anhang rein gepackt.

Hallo,

da fühle ich mich gleich genötigt den Schaltplan zu erneuern. Konnte nicht ahnen das es nochmal Thema wird.
Detailierter ging es hier zur Sache. Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445

Hier ein überarbeiteter kompletter Schaltplan. In diesem Thread hier fehlte nämlich noch der Pullup, weil der OPV einen open collector Ausgang hat. LM393N (DIP8) musste nur einen kaufen, weil zwei OPV’s enthalten sind. Mit dem zusätzlichen Spannungsteiler im Potistrang kannste die ca. 0,8V besser einstellen. Oder baust einen Spannungsteiler aus Festwiderständen.

LM393N_Komparator.png

Pinout Übersichten:
Board Pinout Überblick
UNO Pinout
Mega Pinout

Hallo,

ich habe das Gefühl hier läuft gerade etwas mächtig schief. Laut Bild liefert dir der Adapter serielle Daten vom Messschieber auf Anforderung. Den OPV Aufbau benötigst du dafür nicht. Der Sketch wäre demzufolge dafür unbrauchbar. Jetzt sollte erstmal geklärt werden was du da wirklich wie machst. Zum Adapter sollte es doch noch andere Unterlagen geben?

Das Thema hier dreht sich darum die Daten direkt vom Messschieber abzugreifen. Kurzer Abschweif. Mein Messschieber arbeitet mit einer 1,5V Knopfzelle. Keine 3V. Die Kabel habe ich direkt am Messschieber angelötet. Ich kann den auch ohne Knopfzelle betreiben, die sowieso schnell leer ist.

PINA etc. (alles groß) sind Registernamen, die müssen angepaßt werden, je nach µC und verwendeten Pin. Aber wie gesagt, dass wird alles nicht mehr interessieren mit deinem Adapter.

Da brauchen wir ja neben dem Level-Shifter noch einen Step Down-Wandler https://www.eleccircuit.com/usb-battery-replacement-by-lm317/ ein LM1117 Adj tut sicher auch. Kannst du mal die Stromaufnahme des Messschiebers messen?

Hallo,

ich hatte es schon angedeutet. Mit dem Adapter, so verstehe ich das Bild, kannst du die Daten bestimmt direkt auf der seriellen Schnittstelle auslesen. Das wäre die einfachste Lösung. Ein Datenblatt oder ähnliches wirst du wohl sicherlich von Sylvac herunterladen oder anfragen können.

Wegen der Spannung. Wenn der Messschieber einen Spannungsanschluss hat und keine Batterie und es wirklich 3V sind, miss die Stromaufnahme und hoffe das sie unter 50mA liegt. Sollte deutlich drunter liegen. Aber ich kann es hier ja nicht garantieren. Logisch. Wenn dein Arduino Board, auch 3,3V zur Verfügung stellt, kannste die bis zu 50mA belasten, WENN !!! das Board dem originalen Arduino Schaltplan entspricht! Eine Diode in Flussrichtung dazwischen sollte für einen Test ausreichend sein. Ansonsten selbst schlau machen.

Falls doch anders. Zu 99,9% hat jeder billige digitale Meßschieber aus der Wühlkiste eine Schnittstelle. Die ist aber weder beschrieben noch herausgeführt. Hier ist immer etwas basteln angesagt. Dann benötigt man irgendein Oszi oder Datalogger um das Protokoll anzusehen wenn man nicht blinde Kuh spielen möchte.

Hallo,

damit du eine Vorstellung bekommst auf was du dich einlässen würdest. :slight_smile:
Die internen Anschlüsse sind unbeschriftet, zumindestens bei meinem Schieber.

Messschieber_01.jpg
Messschieber_02.jpg


Messschieber_04.jpg
Messschieber_05.jpg

Messschieber_01.jpg

Messschieber_02.jpg

Messschieber_04.jpg

Messschieber_05.jpg

Hallo,

den Sylvac würde ich auch nicht zerlegen wenn ich den Adapter habe. Die Bilder sollten zeigen was einem beim basteln mit einem billigen Meßschieber erwartet um an die Kontakte zugelangen.

Auch auf die Gefahr hin mich zu wiederholen. Du hast den optischen Adapter. Der hat eine serielle PC Schnittstelle. Ohne weiteren "seriellen Adapter" NICHT! an einen µC anschließen. Andere serielle Signalpegel. Mach dich hier schlau ob deiner dabei ist oder frage mit der Artikelnummer bei Sylvac nach Unterlagen dazu. https://www.sylvac.ch/de/download-de/gebrauchsanleitung/datenuebertragung-und-software Das könnte vielleicht deiner sein laut Bild. https://www.sylvac.ch/download-en/manuals/connections-and-softwares/sylvac-rs232-connectic-systems-for-hand-tools

Aus den mir lesbaren Informationen benötigen manche optische Adapter noch ein Netzteil, manche scheinbar auch nicht. Ich weiß es nicht genau. Woher auch. Wie gesagt, dazu musst du dich selbst schlau machen. Wenn das dann irgendwann am PC angeschlossen ist, kann man sicherlich mit einem Terminal schon paar Daten sehen. Oder die Sylvac Software ist frei verfügbar?

Um den Adapter am µC (Arduino) anschließen zu können wird ein erwähnter serieller Adapter benötigt. Der aus echten RS232 Signalen TTL Pegel konforme Signale erzeugt. Meistens mit MAX232 oder MAX3232. Es wird sicherlich auch fertige Adapter damit geben. Erst dann könnten wir weitermachen. Wenn ich das vermeintliche Manual überblicke, dann benötigt der optische Adapter zur Datenanforderung an DTR noch einen Impuls bzw. Pegel damit überhaupt etwas passiert. Ich weiß nicht ob es fertige TTL Pegel Wandler gibt die alle Pins der Schnittstelle "bedienen" oder immer nur TX und RX Leitung "behandeln". Vielleicht wissen das andere Leute aus dem Forum?

Hallo,

habe den Code überarbeitet. Hauptsächlich ging es darum die Blockierung rauszunehmen. Zusätzlich kann man einen zweiten relativen Meßwert nutzen indem per Taster ein Referenzwert gespeichert wird. Sporadische Aussetzer bzw. Meßfehler gibts keine mehr. Gegen das zappeln der letzten Kommastelle kann ich nichts machen. Mein Meßschieber gibt zappelnde Werte raus.
Statt direkten Port/Registerzugriff kann man auch digitalRead verwenden. Habs gestestet und funktioniert soweit.
Die Timings sind mir persönlich jedoch etwas zu knapp. Kann nicht garantieren ob es dauerhaft stabil bleibt.
Könnt ihr gern testen und rückmelden.

/*
  Doc_Arduino - german Arduino Forum
  IDE 1.8.5
  Arduino Mega2560

  26.06.2018

  auslesen eines Meßschiebers mit Sylvac Protokoll (2 x 24Bit)

  Takt an Pin A14
  Data an Pin A15
  
  Beide Signale vom Meßschieber werden mittels OPV LM393N nicht invertierend auf 5V Pegel angehoben.
  Der erste 24Bit Wert ist irgendein Absolutwert vom Meßschieber ohne konkreten Bezugspunkt.
  Der zweite 24Bit Wert ist der relative Meßwert wie auf dem Display.
  Es wird immer die ca. 320ms Pause zwischen den Werten erkannt und dann 2x24Bit in einer Interrupt Sperre eingelesen.
  Mittels Taster kann eine zweite relative Messung genutzt werden. Dabei wird der aktuelle Absolutwert zum neuen Referenzwert
  und dann verrechnet.
    
  Pinouts  >>> http://www.pighixxx.net/pinoutspg/boards/
  Uno      >>> http://www.pighixxx.net/portfolio-items/uno/?portfolioID=314
  Mega2560 >>> http://www.pighixxx.net/portfolio-items/mega/?portfolioID=314
*/

#include <util/atomic.h>
  
#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

#define PIN_TASTER_IN   cbi (DDRE,4)  // PE4 Eingang, Pin 2
#define PIN_TASTER_PULL sbi (PORTE,4) // Pullup aktiv
#define READ_TASTER    ( PINE & (1<<PE4) )

#define PIN_CLOCK_IN   cbi (DDRK,6)  // PK6 Eingang, Pin A14
#define PIN_CLOCK_PULL sbi (PORTK,6) // Pullup aktiv
#define READ_CLOCK    ( PINK & (1<<PK6) )

#define PIN_DATA_IN    cbi (DDRK,7)  // PK7 Eingang, Pin A15
#define PIN_DATA_PULL  sbi (PORTK,7) // Pullup aktiv
#define READ_DATA     ( PINK & (1<<PK7) )

struct t_data
{
  bool flag_detect = false;
  int32_t value_rel = 0;
  int32_t value_abs = 0;
  int32_t value_ref = 0;
  float result_m = 0.0;
  float result_i = 0.0;
  const float div_m = 806.34;     // Umrechnung in [mm]   >> 1 mm entspricht 806,339 Schritte
  const float div_i = 20481.0;    // Umrechnung in [inch] >> 1 inch entspricht 20481 Schritte
} mess;
 
                    
void setup() {
  
  Serial.begin(250000);

  PIN_TASTER_IN;
  PIN_TASTER_PULL;
  PIN_CLOCK_IN;
  PIN_CLOCK_PULL;
  PIN_DATA_IN;
  PIN_DATA_PULL;
}


 void loop () {

  mess.flag_detect = detect_pause();
 
  if (mess.flag_detect) {                     // Anfang erkannt, lese Daten ein ...
    mess.value_abs = read_data();             
    mess.value_rel = read_data();             
    
    int32_t diff = (mess.value_ref - mess.value_abs);
    
    //formatiere_daten(mess.value_rel); Serial.println(mess.value_rel); //Serial.print('\t');   // Debug
    //formatiere_daten(mess.value_abs); Serial.println(mess.value_abs); //Serial.print('\t');   // Debug
    //formatiere_daten(diff); Serial.println(diff);                                             // Debug
    
    convert_to_show(mess.value_rel);  Serial.print("\t\t");
    convert_to_show(diff);            Serial.println();
  }

  read_Taster();
  
}  // loop ENDE


int32_t read_data() {

  int32_t value = 0;
  uint32_t shift = 1;                       // Bit.0 mit "1" vorbelegen
  
  ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {  
    for (uint8_t i=0;i<24;i++) {            // 24 Durchläufe                                         
      while ( READ_CLOCK )  { }             // warten bis Clock wieder LOW ist
      if ( READ_DATA ) {                    // wenn Data HIGH ist, dann schreibe 
        value |= shift;                     // Bits ver_ODERN, shiften separat sonst wird es "hier" immer langsamer     
      }                                    
      while ( !READ_CLOCK )  { }            // warten bis Clock wieder HIGH ist  
      shift = (shift << 1);                                                           
    }  
  }
  
  return value;   
}


void convert_to_show (int32_t data)
{  
  switch (data) {
    // Gültigkeitsbereiche //
    case  -125000 ...   125000:  mess.result_m = (data/mess.div_m * -1);            // Umrechnung in [mm] für negative Werte
                                 mess.result_i = (data/mess.div_i * -1);            // Umrechnung in [inch] für negative Werte  
                                 show_measurement (mess.result_m, mess.result_i);   // und zusätzlich für Absolutwerte
                                 break;
                                                        
    case 16650000 ... 16777215:  mess.result_m = (16777215-data)/mess.div_m;        // Umrechnung in [mm] für positive Werte
                                 mess.result_i = (16777215-data)/mess.div_i;        // Umrechnung in [inch] für positive Werte 
                                 show_measurement (mess.result_m, mess.result_i);
                                 break;
                                 
    default:                     break;
  }
}


bool detect_pause ()
{  
  typedef enum {START, STOP} states;    // Steuerzustände
  static states detect = START;
  static uint32_t time_lowPhase = 0;
  bool valid = false;
  
  switch (detect) {
    case START:   
                 if ( !READ_CLOCK )  {            // prüft wann Clock auf Low wechselt  
                   time_lowPhase = millis();
                   detect = STOP;
                 }
                 break;
    case STOP:
                if ( READ_CLOCK )  {              // prüft wann Clock auf High wechselt 
                  if (millis() - time_lowPhase > 300) {
                    valid = true;
                  }    
                  detect = START;   
                }
                break;          
  }

  return valid;
}


void read_Taster ()
{
  static uint32_t last_ms = 0;

  if (millis() - last_ms < 50)  return;
  last_ms = millis();
    
  if ( !READ_TASTER )  {
    mess.value_ref = mess.value_abs;
  } 
}


void show_measurement (float &metric, float &inch)
{
  Serial.print(metric,3);        // Anzeige in [mm]
  Serial.print(F(" mm ")); 
  Serial.print('\t');
  Serial.print(inch,4);          // Anzeige in [inch]
  Serial.print(F(" inch")); 
}


void formatiere_daten (int32_t data)
{
  for (char i=23;i>=16;i--) {
    Serial.print(bitRead(data,i)); 
  }
  Serial.print('.');
  for (char i=15;i>=8;i--) {
    Serial.print(bitRead(data,i)); 
  }
  Serial.print('.');
  for (char i=7;i>=0;i--) {
    Serial.print(bitRead(data,i)); 
  }
  Serial.print('\t');
}

Hallo,

es folgt die Variante ohne define.

/*
  Doc_Arduino - german Arduino Forum
  IDE 1.8.5
  Arduino Mega2560

  27.06.2018

  auslesen eines Messschiebers mit Sylvac Protokoll (2 x 24Bit)

  Takt an Pin A14
  Data an Pin A15
  
  Beide Signale vom Messschieber werden mittels OPV LM393N nicht invertierend auf 5V Pegel angehoben.
  Der erste 24Bit Wert ist irgendein ein Absolutwert vom Meßschieber ohne konkreten Bezugspunkt.
  Der zweite 24Bit Wert ist der relative Meßwert wie auf dem Display.

  Es wird immer die ca. 320ms Pause zwischen den Werten erkannt und dann 2x24Bit in einer Interrupt
  Sperre eingelesen. Mittels Taster kann eine zweite relative Messung genutzt werden. Dabei wird
  der aktuelle Absolutwert zum neuen Referenzwert und dann verrechnet.
    
  Pinouts  >>> http://www.pighixxx.net/pinoutspg/boards/
  Uno      >>> http://www.pighixxx.net/portfolio-items/uno/?portfolioID=314
  Mega2560 >>> http://www.pighixxx.net/portfolio-items/mega/?portfolioID=314
*/


#include <util/atomic.h>
#include <CombiePin.h>

using namespace Combie::Pin;

InputPin<2>   TASTER_P2;   // zwischen Pin und GND
InputPin<A14> PIN_CLOCK;  
InputPin<A15> PIN_DATA;   

 
struct t_data
{
  bool flag_detect = false;
  int32_t value_rel = 0;
  int32_t value_abs = 0;
  int32_t value_ref = 0;
  float result_m = 0.0;
  float result_i = 0.0;
  const float div_m = 806.34;     // Umrechnung in [mm]   >> 1 mm entspricht 806,339 Schritte
  const float div_i = 20481.0;    // Umrechnung in [inch] >> 1 inch entspricht 20481 Schritte
} mess;
 
                    
void setup() {
  
  Serial.begin(250000);
  
  TASTER_P2.initPullup();
  PIN_CLOCK.initPullup();
  PIN_DATA.initPullup();
}


 void loop () {

  mess.flag_detect = detect_pause();
 
  if (mess.flag_detect) {                     // Anfang erkannt, lese Daten ein ...
    mess.value_abs = read_data();             
    mess.value_rel = read_data();             
    int32_t diff = (mess.value_ref - mess.value_abs);
    
    //formatiere_daten(mess.value_rel); Serial.println(mess.value_rel); //Serial.print('\t');   // Debug
    //formatiere_daten(mess.value_abs); Serial.println(mess.value_abs); //Serial.print('\t');   // Debug
    //formatiere_daten(diff); Serial.println(diff);                                             // Debug
    
    convert_to_show(mess.value_rel);  Serial.print("\t\t");
    convert_to_show(diff);            Serial.println();
    mess.flag_detect = false;
  }

  read_Taster();
  
}  // loop ENDE


int32_t read_data() {

  int32_t value = 0;
  uint32_t shift = 1;                       // Bit.0 mit "1" vorbelegen
  
  ATOMIC_BLOCK (ATOMIC_RESTORESTATE) {  
    for (uint8_t i=0;i<24;i++) {            // 24 Durchläufe                                         
      while ( PIN_CLOCK )  { }              // warten bis Clock wieder LOW ist
      if ( PIN_DATA ) {                     // wenn Data HIGH ist, dann schreibe 
        value |= shift;                     // Bits ver_ODERN, shiften separat sonst wird es "hier" immer langsamer     
      }                                    
      while ( !PIN_CLOCK )  { }             // warten bis Clock wieder HIGH ist  
      shift = (shift << 1);                                                           
    }  
  }
  
  return value;   
}


void convert_to_show (int32_t data)
{  
  switch (data) {
    // Gültigkeitsbereiche //
    case  -125000 ...   125000:  mess.result_m = (data/mess.div_m * -1);            // Umrechnung in [mm] für negative Werte
                                 mess.result_i = (data/mess.div_i * -1);            // Umrechnung in [inch] für negative Werte  
                                 show_measurement (mess.result_m, mess.result_i);   // und zusätzlich für Absolutwerte
                                 break;
                                                        
    case 16650000 ... 16777215:  mess.result_m = (16777215-data)/mess.div_m;        // Umrechnung in [mm] für positive Werte
                                 mess.result_i = (16777215-data)/mess.div_i;        // Umrechnung in [inch] für positive Werte 
                                 show_measurement (mess.result_m, mess.result_i);
                                 break;
                                 
    default:                     break;
  }
}


bool detect_pause ()
{  
  typedef enum {START, STOP} states;    // Steuerzustände
  static states detect = START;
  static uint32_t time_lowPhase = 0;
  bool valid = false;
  
  switch (detect) {
    case START:   
                 if ( !PIN_CLOCK )  {            // prüft wann Clock auf Low wechselt  
                   time_lowPhase = millis();
                   detect = STOP;
                 }
                 break;
    case STOP:
                if ( PIN_CLOCK )  {              // prüft wann Clock auf High wechselt 
                  if (millis() - time_lowPhase > 300) {
                    valid = true;
                  }    
                  detect = START;    
                }
                break;          
  }

  return valid;
}


void read_Taster ()
{
  static uint32_t last_ms = 0;

  if (millis() - last_ms < 50)  return;
  last_ms = millis();
    
  if ( !TASTER_P2 )  {
    mess.value_ref = mess.value_abs;
  } 
}


void show_measurement (float &metric, float &inch)
{
  Serial.print(metric,3);        // Anzeige in [mm]
  Serial.print(F(" mm ")); 
  Serial.print('\t');
  Serial.print(inch,4);          // Anzeige in [inch]
  Serial.print(F(" inch")); 
}


void formatiere_daten (int32_t data)
{
  for (char i=23;i>=16;i--) {
    Serial.print(bitRead(data,i)); 
  }
  Serial.print('.');
  for (char i=15;i>=8;i--) {
    Serial.print(bitRead(data,i)); 
  }
  Serial.print('.');
  for (char i=7;i>=0;i--) {
    Serial.print(bitRead(data,i)); 
  }
  Serial.print('\t');
}

CombiePin.zip (4.29 KB)