Hallo, ich habe mir die Schaltung von Hans Borngraeber nachgebaut. http://www.roehrenkramladen.de/DRO/Projektmappe_MAS_V1_0.htm Zunächst habe ich es mit dem ~10 Euro Messschieber von Reichelt probiert. Nichts zu machen. Da war nur wirres Zeug auf dem Terminal zu sehen. Die Anzeige hat ständig von Inch nach mm umgeschaltet und die Zahlen passten überhaupt nicht. Zum testen habe ich dann noch die Firmware von Sven Hummel getestet. (http://www.svens-projekte.de/3.html) Die Version 6.0. Auch das hat nicht funktioniert. Dann habe ich mir Messschieber von Pollin gekauft. Angeblich soll die Schaltung von H.B. damit gestestet sein. Aber auch hier funktioniert es nicht. H.B. bietet ja zwei hex files an. Einmal für Pollin und einmal für Lidl. Die Pollin Vatriante zeigt ähnliches (unbrauchbares) Zeug an wie beim Reichelt Messschieber. Die Lidl Variante hingegen, zeigt immerhin Werte an, die linear steigen. Sie passen zwar ganz und gar nicht zum Display vom Messschieber, aber sie sind vom Wertebereich her "gültig". Das heißt: auf 150mm werden mir Werte von +0,00mm bis irgendwas um die 5,00mm angezeigt. Die Werte steigen jedoch linear zur Verschiebebewegung des Messschiebers. So langsam weiß ich nicht mehr was ich noch machen soll. Hat vielleicht der R22 (welcher auf 0,7-0,9V) eingestellt werden soll etwas damit zu tun? Wenn ich die Spannung ändere, passiert leider nichts sichtbares. Ich verwende 16Mhz Quarz und geschirmtes Kabel. Abgesehen von den Messwerten, wird im Terminal alles angezeigt wie es soll. Irgendwo muss da doch der Wurm drin sein, wer kann mir da helfen? Wo kann ich noch Fehler suchen? Ich habe also beide Messschieber mit allen drei Hex files getestet. (2X H.B. und 1X S.H.) Gruß, Andreas
Hallo Andreas Mit den Billig-Teilen von Lidl, Aldi, Pollin habe ich mich selber schon herumgeärgert. Bei diesen billigen China-Messschiebern gibt es mittlerweile mindestens drei völlig verschiedene Protokolle der Datenübertragung. Welches Protokoll deine Messlatte benützt ist leider Glückssache. Ich hatte auch schon welche, die zwar die Anschlüsse für den Stecker auf der Platine draufhatten, die Kontaktflächen waren aber nicht angeschlossen und völlig funktionslos. Anscheinend werden diese Dinger von immer mehr verschiedenen China-Firmen produziert, von denen jede ihr eigenes "geheimes" Protokoll verwendet. Eine Dokumentation dazu gibts vermutlich nur, wenn du die Dinger Containerweise bestellst. Einzige Abhilfe: Nicht bei Billig-Händlern wie Lidl oder Aldi oder Pollin kaufen. Was du dort bekommst, ist reiner Zufall und meistens nicht für das Auslesen per µC geeignet. Nur bei namhaften Werkzeughändlern bestellen und dir vorher schriftlich bestätigen lassen, welches Protokoll die Messschieber verwenden. Wenn's dann nicht klappt, hast du zumindest ein Rückgaberecht.
Hallo Andreas, ich habe dasselbe Problem mit meinen Messschiebern (von zujeddeloh).Die hatten auch ein komplett unschiedliches Protokoll als das von Pollin und Lidl (die hatte ich auch getestet). Um dem ganzen etwas näher zu kommen bin ich folgendermaßen vorgegangen: Auf das Umstellen der Modi (Fast, etc.) am besten erst einmal verzichten und aufs Lesen fokussieren. Wenn Werte kommen (auch wenn sie erst einmal falsch scheinen ist das auch schon ein gutes Zeichen;-) Dann bin ich wie folgt vorgegangen: 1. Festen Wert auf dem Meßschieber einstellen 2. Den eingestellten Wert in Binär umrechnen (z.B. mit http://www.arndt-bruenner.de/mathe/scripts/Zahlensysteme.htm) 3. Kleines Programm z.B in Bascom mit "Shiftin PINB.0 , Pinc.1 , <Wert> , 6 , 24" schreiben, welches den Messschieber im Loop ausliest und auf der seriellen Schnittstelle ausgibt. Dann nach dem Bitmuster in der Ausgabe suchen und den Schieber mal verstellen, schauen ob das neue Bitmuster an derselben Stelle dann dem eingestellten Wert entspricht. So hat es zumindest bei mir geklappt die Werte zu ermitteln. Aktuell kämpfe ich allerdings mit solchen Wiedrigkeiten wie Stromsparmodi der Messschieber, etc. Grüße Carsten
Ich habe mir vor nicht allzu langer Zeit selber eine Schaltung zum Auslesen von Schieblehren gebaut, welche die Werte von bis zu vier Schieblehren auf einem 16x4 LCD anzeigt. Zum Glück habe ich hier nur namhafte Schieblehren zur Verfügung, welche alle das gleiche Protokoll benutzen. Damit funktioniert das Auslesen und Umstellen der Modes völlig problemlos. Ich habe mich vorher aber vergewissert, dass das Protokoll auch korrekt ist, indem ich per Logikanalyzer die Ausgabe für drei verschiedene Messwerte gespeichert habe. Ich habe mal Screenshots der Ausgabe für -10mm, 0mm und 10mm mit angehängt. Dann habe ich die Software für den Controller geschrieben, welche heute noch problemlos funktioniert. Dazu habe ich mir auch eine Hilfsfunktion (signal.ini) erstellt, welche das Protokoll der Schieblehre emuliert und an mein Programm liefert. Damit konnte ich die Software testen ohne dauernd die Hardware anschliessen zu müssen. :) Falls es euch hilft, könnt ihr unter [1] das gesamte Programm von mir einsehen. Ciao, Rainer [1] https://quakeman.homelinux.net/viewvc/uVision/trunk/Schieblehre_Anzeige/
Hallo, ich bin, wie Carsten M. es vorgeschlagen hat vorgegangen. Nun bin ich soweit, dass mir der Messwert via Rs232 an den Pc gesendet wird. Wen es interessiert: Der Messwert liegt auf Bit 18 bis 31. Das Vorzeichen kann mit Bit 11 ermittelt werden. Maßeinheit habe ich nicht herausbekommen, ist für mich aber auch nicht wichtig, da ich nur mit mm arbeite. Jetzt würde mich interessieren, wie man nullen kann. Im Originalprogramm von H.B. wurde das mit Impulsen gemacht à la: Config Portd.3 = Output 'Schaltport Takt X-Achse .. .. Portd.3 = 1 Waitms 300 Portd.3 = 0 Meinen eingesetzten Messschieber interessiert das nicht sonderbar. Gibt es eine Chance herauszufinden was man da senden muss? Ich würde nur ungern mit Optokopplern die Hardkeys des Messschiebers anzapfen wollen... Gruß, Andreas
Hallo, freut mich dass es klappt. Das nullen habe ich auch nicht hinbekommen, da ich aber ohnehin nicht am Messschieber ablesen möchte mache ich das auch einfach in meinem Micrcontroller (aktuellen Wert als Nullwert merken und dann einfach immer die Differenz ausgeben). So habe ich zB. Auch vor die Radiusanzeige des Plansupportes zu realisieren, denn da muss man den Wert ja auch umrechnen. Grüße Carsten
Moin zusammen, schaut mal unter http://www.steamboating.de/caliper/cal-main.html nach. Dort gibt es eine Anzeige für die billig Messschieber. Habe diese mit den 10€ Messschieber von Alpha Tools (Bauhaus) ausprobiert. Funktioniert ganz gut. Gruß Sebastian
Bin nun etwas weiter. Ich habe die Firmware so umgeschrieben, das ich auf das HyperTerminal verzichten kann. Zum ersten Mal habe ich zwei Messschieber angeschlossen und festgestellt, das die Messwerte zwischendurch nicht ganz passen. D.h. er misst den richtigen Wert, z.B. 50.xx mm, macht einen Sprung nach 130.xx und dann zeigt er wieder den ursprünglichen (korrekten) Wert an. Das tritt aber nur auf, wenn ich einen zweiten Messschieber anschließe. Kann das Hardware-bedingt sein? Oder sieht jemand etwas "verdächtiges" in der Hauptschleife? Hier mal der Quellcode der Hauptschleife: Do Gosub Tastatur '****** X-Achse If Xflag = 0 Then Start Watchdog Shiftin Pinc.0 , Pinc.1 , L , 7 , 32 'Daten einlesen X-Achse Reset Watchdog Gosub Dekoder 'Daten dekodieren Ausgabe = "x" + Vz_text + Mw_text If Ausgabe <> Oldvalx Then Print Ausgabe End If Oldvalx = Ausgabe Waitms 10 End If '****** Y-Achse If Yflag = 0 Then Start Watchdog Shiftin Pinc.2 , Pinc.3 , L , 7 , 32 'Daten einlesen Y-Achse Reset Watchdog Gosub Dekoder 'Daten dekodieren Ausgabe = "y" + Vz_text + Mw_text If Ausgabe <> Oldvaly Then Print Ausgabe End If Oldvaly = Ausgabe Waitms 10 End If '****** Z-Achse If Zflag = 0 Then Start Watchdog Shiftin Pinc.4 , Pinc.5 , L , 7 , 32 'Daten einlesen Z-Achse Reset Watchdog Gosub Dekoder 'Daten dekodieren Ausgabe = "y" + Vz_text + Mw_text If Ausgabe <> Oldvalz Then Print Ausgabe End If Oldvalz = Ausgabe Waitms 10 End If Loop
Hallo, Soweit ich mich erinnere verwerfen die sonstigen Programme immer den ersten gelesenen Wert und nehmen dann den 2.. Für Dich würde das bedeuten die Shiftin Zeile einfach zu duplizieren. Du solltest noch bedenken, dass Shiftin den Prozessor blockiert. Sollte also einer Deiner Messchieber keine Daten mehr senden (ich hatte das bei meinem, der ging nämlich in den Standbymodus) bekommst Du auch keine Anzeige vom anderen mehr. Sollte das ein Problem sein melde Dich einfach, hatte da eine Shiftin mit Timeout Funktion geschrieben. Grüße Carsten
Carsten M. schrieb: > Soweit ich mich erinnere verwerfen die sonstigen Programme immer den > ersten gelesenen Wert und nehmen dann den 2.. Das wird genau das Problem sein. Du liest ja immer den ersten Wert ein, rechnest ihn um, gibst ihn aus und gehst zur nächsten Schieblehre. Dabei berücksichtigst du aber nicht, ob du beim Einlesen der nächsten Schieblehre unter Umständen gerade mitten in einem Datenpaket anfängst. Du liest dann unter Umständen nur noch die restlichen Bit des Datenpakets ein, was natürlich kein sinnvolles Ergebnis gibt. Ich habe in meinem Programm dafür extra eine Synchronisierungsmethode erstellt, welche immer als erstes nach dem Umschalten der Schieblehre aufgerufen wird. Diese stellt sicher, dass ich nicht mitten in einem Datenpaket anfange einzulesen. Ciao, Rainer
Hallo, ich hatte das damals wie folgt gemacht. Ich hatte nur kleine Probleme mit dem Beginn eines Datenpaketes,denn wenn man die komplette Bitlänge liesst bekommt man ja (ggf. mit Pause und nicht ganz so schön) trotzdem einen kompletten Wert. Das hat dann nur nicht mehr funktioniert, wenn man den Schieber bewegt (da ergibt sich tatsächlich das Problem, dass man das Ende des ersten und ggf. den Anfang des zweiten unterschiedlichen Wertes bekommt). Diese Routine funktionierte damals zumindest um das Timeout Problem zu lösen:
1 | Config Portc.0 = Input 'Takt-Eingang X-Achse |
2 | Config Portc.1 = Input 'Daten-Eingang X-Achse |
3 | |
4 | Config Timer1 = Timer , Prescale = 1024 |
5 | On Timer1 Overflow |
6 | Timer1 = 56000 ' Zeit bis Abbruch des Leseversuches |
7 | ' Die Zeit muss so gross sein, dass man ggf. die Pause zwischen zwei 'Signalen überbrücken kann und trotzdem noch mit der Geschwindigkeit 'zufrieden ist |
8 | |
9 | Dim Overflow_bit As Bit ' Glob Variable zur Anzeige, dass keine Daten geliefert werden |
10 | |
11 | |
12 | |
13 | ' hier kommt Dein Haupprogramm ... |
14 | ' |
15 | ' Ergebnis=Shiftintimeout(20) |
16 | 'if Overflow Bit=0 'Dann war alles Erfolgreich |
17 | ' then <Ergebnis umrechnen> |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | 'Interrupt Routine zum Abbruch falls keine Daten kommen |
24 | Overflow: |
25 | Overflow_bit = 1 |
26 | Return |
27 | |
28 | |
29 | |
30 | End |
31 | |
32 | Function Shiftintimeout(byval Timeout As Integer) As Long |
33 | Local P As Long |
34 | Local C As Byte |
35 | Dim X As Bit |
36 | P = 0 'Variable für den Wert |
37 | C = 0 'Dies Ist Der Bitzaehler |
38 | Overflow_bit = 0 ' Globale Variable zum Prüfen ob der Timer übergelaufen ist->abbruch, keine Daten |
39 | X = 0 |
40 | |
41 | Timer1 = 56000 |
42 | Enable Timer1 |
43 | Enable Interrupts |
44 | Do |
45 | Do |
46 | If Pinc.1 = 1 Then X = 1 |
47 | If Overflow_bit = 1 Then X = 1 |
48 | Loop Until X = 1 ' Auf steigende Flanke Warten |
49 | X = 0 |
50 | If Overflow_bit = 0 Then |
51 | Do |
52 | X = Pinc.1 |
53 | If Overflow_bit = 1 Then X = 0 |
54 | Loop Until X = 0 ' Auf fallende Flanke Warten |
55 | End If 'Platz machen für nächstes Bit in ZielVariable |
56 | Rotate P , Right |
57 | P = P + Pinc.0 ' Aktuellen Wert lesen |
58 | C = C + 1 |
59 | If Overflow_bit = 1 Then |
60 | C = 24 |
61 | End If |
62 | |
63 | Loop Until C = 24 |
64 | |
65 | If Overflow_bit = 0 Then |
66 | Shift P , Right , 9 |
67 | End If |
68 | |
69 | Disable Timer1 |
70 | Disable Interrupts |
71 | |
72 | Shiftintimeout = P |
73 | |
74 | End Function |
Ich habe mal Carsten`s Funktion in ein Testprogramm eingebaut. Das klappt irgendwie so ganz und gar nicht. Es werden keine Werte ausgelesen. Wenn ich z.B. die Waitms700 kleiner mache, stürzt der Controller sofort ab. Overflow_bit ist bei mir immer 1. Zum testen habe ich in der Hauptschleife mal den Timeout erhöht. Overflow_bit war immer 1 und bei 65xxx stürzt der Controller dann ab. $regfile = "m8def.dat" 'Atmega 8 CPU $crystal = 16000000 '16Mhz Quarztakt $baud = 38400 'RS232 38400,8,n,1 $hwstack = 32 $swstack = 16 $framesize = 24 '****** Variable definieren Dim L As Long 'Einlesevariable Dim Lng As Long Dim Ausgabe As String * 16 Dim Oldvalx As String * 16 Dim Oldvaly As String * 16 Dim Oldvalz As String * 16 Dim Keyinput As String * 16 Dim Tmp As Integer Dim Mw_text As String * 6 'Ausgabe Text Dim Xflag As Byte 'Einschalt Flag X-Achse Dim Yflag As Byte 'Einschalt Flag Y-Achse Dim Zflag As Byte 'Einschalt Flag Z-Achse Dim Exflag As Eram Byte 'Einschalt Flag Speicherwert X-Achse Dim Eyflag As Eram Byte 'Einschalt Flag Speicherwert Y-Achse Dim Ezflag As Eram Byte 'Einschalt Flag Speicherwert Z-Achse Declare Function Shiftintimeout(byval Timeout As Integer , Byval Achse As String) As Long 'Config Watchdog = 1024 'Watchdog Wert ca. 1sec Config Single = Scientific , Digits = 3 'Einstellen der Variable für den seriellen Messwert Config Portc.0 = Input 'Takt-Eingang X-Achse Config Portc.1 = Input 'Daten-Eingang X-Achse Config Portc.2 = Input 'Takt-Eingang Y-Achse Config Portc.3 = Input 'Daten-Eingang Y-Achse Config Portc.4 = Input 'Takt-Eingang Z-Achse Config Portc.5 = Input 'Daten-Eingang Z-Achse Config Portd.2 = Output 'Schaltport Daten X-Achse Config Portd.3 = Output 'Schaltport Takt X-Achse Config Portd.4 = Output 'Schaltport Takt Y-Achse Config Portd.5 = Output 'Schaltport Daten Y-Achse Config Portd.6 = Output 'Schaltport Takt Z-Achse Config Portd.7 = Output 'Schaltport Daten Z-Achse Config Timer1 = Timer , Prescale = 1024 On Timer1 Overflow Timer1 = 56000 ' Zeit bis Abbruch des Leseversuches ' Die Zeit muss so gross sein, dass man ggf. die Pause zwischen zwei 'Signalen überbrücken kann und trotzdem noch mit der Geschwindigkeit 'zufrieden ist Dim Overflow_bit As Bit ' Glob Variable zur Anzeige, dass keine Daten geliefert werden '**** Schaltausgänge zurücksetzen Portd.2 = 0 Portd.3 = 0 Portd.4 = 0 Portd.5 = 0 Portd.6 = 0 Portd.7 = 0 '****** Einlesen der Messschieber Konfiguration aus dem EERAM Xflag = Exflag Yflag = Eyflag Zflag = Ezflag If Xflag = 255 Then Exflag = 0 Xflag = 0 End If Print "rdy" Wait 1 Print "co:" ; Xflag ; ":" ; Yflag ; ":" ; Zflag Lng = 56000 Do '****** X-Achse If Xflag = 0 Then L = Shiftintimeout(20 , "x") If Overflow_bit = 0 Then Mw_text = Bin(l) Print "X" ; Mw_text End If End If Print Overflow_bit ; " L: " ; Lng 'If Overflow_bit = 1 Then ' Lng = Lng + 100 'End If Waitms 700 Loop 'Interrupt Routine zum Abbruch falls keine Daten kommen Overflow: Overflow_bit = 1 Return Function Shiftintimeout(byval Timeout As Integer , Byval Achse As String) As Long Local P As Long Local C As Byte Dim X As Bit P = 0 'Variable für den Wert C = 0 'Dies Ist Der Bitzaehler Overflow_bit = 0 ' Globale Variable zum Prüfen ob der Timer übergelaufen ist->abbruch, keine Daten X = 0 Timer1 = Lng Enable Timer1 Enable Interrupts If Achse = "x" Then Do Do If Pinc.1 = 1 Then X = 1 If Overflow_bit = 1 Then X = 1 Loop Until X = 1 ' Auf steigende Flanke Warten X = 0 If Overflow_bit = 0 Then Do X = Pinc.1 If Overflow_bit = 1 Then X = 0 Loop Until X = 0 ' Auf fallende Flanke Warten End If 'Platz machen für nächstes Bit in ZielVariable Rotate P , Right P = P + Pinc.0 ' Aktuellen Wert lesen C = C + 1 If Overflow_bit = 1 Then C = 24 End If Loop Until C = 24 End If If Overflow_bit = 0 Then Shift P , Right , 9 End If Disable Timer1 Disable Interrupts Shiftintimeout = P End Function End
Hallo,
ein paar Sachen an deen es liegen könnte sind mir aufgefallen:
Wenn ich Deine letzten Sources richtig verstanden habe, dann ist bei Dir
die Länge eines Wertes 32 Bit
> Shiftin Pinc.0 , Pinc.1 , L , 7 , 32 'Daten einlesen X-Achse
Damit müsstest Du die Zeilen
1 | If Overflow_bit = 1 Then |
2 | C = 24 '<-HIER 32 |
3 | End If |
4 | Loop Until C = 24 '<-HIER 32 |
entsprechend anpassen. Hier kommt glaube das eigendlich Wichtige! Wenn Deine Schaltung so ist:
1 | Config Portc.0 = Input |
2 | 'Takt-Eingang X-Achse |
3 | Config Portc.1 = Input |
4 | 'Daten-Eingang X-Achse |
Bei mir ist Takt und Daten genau umgekehrt, also entweder umstecken oder Du tauscht in der "ShiftInTimeout" alle Pinc.1 geben pinc.0 und andersrum. Dann sollte es zumindest schon mal etwas mehr ausgabe erzeugen. Viele Grüße Carsten ------------------- Der Code müsste dann in etwa so aussehen:
1 | Function Shiftintimeout(byval Timeout As Integer , Byval Achse As |
2 | String) As Long |
3 | Local P As Long |
4 | Local C As Byte |
5 | Dim X As Bit |
6 | P = 0 'Variable |
7 | für den Wert |
8 | C = 0 'Dies Ist |
9 | Der Bitzaehler |
10 | Overflow_bit = 0 ' Globale |
11 | Variable zum Prüfen ob der Timer übergelaufen ist->abbruch, keine Daten |
12 | X = 0 |
13 | |
14 | Timer1 = Lng |
15 | Enable Timer1 |
16 | Enable Interrupts |
17 | |
18 | If Achse = "x" Then |
19 | Do |
20 | Do |
21 | If Pinc.0 = 1 Then X = 1 |
22 | If Overflow_bit = 1 Then X = 1 |
23 | Loop Until X = 1 ' Auf |
24 | steigende Flanke Warten |
25 | X = 0 |
26 | If Overflow_bit = 0 Then |
27 | Do |
28 | X = Pinc.0 |
29 | If Overflow_bit = 1 Then X = 0 |
30 | Loop Until X = 0 ' Auf |
31 | fallende Flanke Warten |
32 | End If 'Platz |
33 | machen für nächstes Bit in ZielVariable |
34 | Rotate P , Right |
35 | P = P + Pinc.1 ' Aktuellen |
36 | Wert lesen |
37 | C = C + 1 |
38 | If Overflow_bit = 1 Then |
39 | C = 32 |
40 | End If |
41 | Loop Until C = 32 |
42 | End If |
43 | If Overflow_bit = 0 Then |
44 | Shift P , Right , 9 |
45 | End If |
46 | Disable Timer1 |
47 | Disable Interrupts |
48 | Shiftintimeout = P |
49 | End Function |
Hallo, die Pins 0 und 1 habe ich schon mal vertauscht. Die sind schon bei H.B. verkehrt herum. Zumindest, wenn ich der Doku von dem org. SHIFTIN Befehl glauben darf. Ob ich da 24 oder 32 eingebe bringt keinen Unterschied. Ich habe mal Versuche gemacht. Dazu habe ich am Anfang der Funktion Shiftintimeout ein print "read" eingebaut. In der Hauptschleife habe ich am Ende ein Waitms eingebaut. "Read" heißt nur das die Funktion aufgerufen wurde. Wenn es ein Messergebnis gab, steht es dabei. In der ersten Zeile die "Konfig" und ab dann die Ausgabe in meiner Konsole am PC. Timer 56000-65000 und WAITMS50 oder WAITMS700 rdy co:0:255:255 read read read read read usw. Timer 70000 und WAITMS700 rdy co:0:255:255 read read nichts mehr Timer 56000 und WAITMS10 oder keine Pause rdy co:0:255:255 zufällig, nicht reproduzierbare reads, manchmal ein (korrektes) messergebnis Timer 56000 und keine Pause und kein Print "read" rdy co:0:255:255 zufällig, selten ein (korrektes)Messergebnis nach ca. 6 sekunden. Meist resetet sich der Controller nach ca. 2-3 sekunden. Der Watchdog war bei allen Versuchen deaktiviert.
Hallo.... Komisch und wenn Du die Funktion zum Test mal direkt ins Hauptprogramm einbaust und nicht als Funktion aufrufst ? Grüße Carsten
Ich verstehe die Welt nicht mehr. Wenn ich in der Hauptschleife die Bedingung: "If Xflag = 0 Then" herausnehme, geht es ohne Probleme. Auszug aus der Definition: Xflag = Exflag Yflag = Eyflag Zflag = Ezflag If Xflag = 255 Then Exflag = 0 Xflag = 0 End If Hiernach ist Xflag (auch nach dem flashen) immer 0. Ein "Print Xflag" hat mir das bestätigt. Was hat der denn für ein Problem zu prüfen, ob das 0 oder was auch immer ist?
Hallo, ich werde das mit BASCOM dann sein lassen. Vielleicht klappt es mit c besser. Dazu habe ich leider noch weniger gefunden. Aus diversen Threads und älteren Programmen von mir habe ich folgendes zusammengebastelt (siehe unten). Die Ausgabe über USART funktioniert soweit. Dummerweise bekomme ich auf 10er Basis immer 61 und bei 2er Basis immer 111101 ausgegeben. Egal was ich am Messschieber einstelle. Das ist leider so gar nicht das was ich möchte. Auch ein vertauschen der beiden Pins Pc1 und Pc0 bringt das selbe Ergebnis: 61. Ich benötige "einfach nur" die Binärzahl als array of char, bzw. auf dem Pc als String. Dort pflücke ich das dann auseinander. Meine Frage ist, liegt das falsche Ergebnis an der Funktion read_caliper, oder an mir, da ich die Daten möglicherweise falsch aufbereite? Die Funktion read_caliper habe ich hier her: Beitrag "24 Bit über Pin auslesen Takt/Daten ohne Interrupt" #include <avr/io.h> #ifndef F_CPU #warning "F_CPU war noch nicht definiert, wird nun mit 16000000 definiert" #define F_CPU 16000000UL /* Quarz mit 16.0000 Mhz */ #endif #include <util/delay.h> #include <inttypes.h> #include <stdlib.h> #include <avr/interrupt.h> #include <string.h> #include <util/atomic.h> #include "sbit.h" #define UART_BAUD_RATE 38400L #define UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) ((F_CPU)/((UART_BAUD_RATE)*16L)-1L) #define CR "\r\n" uint32_t read_caliper( void ); uint32_t ermval; #define CLK_PIN SBIT( PINC, 1 ) #define DATA_PIN SBIT( PINC, 0 ) char wert[30]; //RS232------------------------------------------------------ void USART_putc(uint8_t byte) { while(bit_is_clear(UCSRA,UDRE)); //warten auf Datenregister empty UDR=byte; } void USART_puts(char *s) /* print string on USART (no auto linefeed) */ { while (*s!=0) { USART_putc(*s); s++; } } //RS232------------------------------------------------------ uint32_t read_caliper( void ) { uint32_t val = 0; ATOMIC_BLOCK(ATOMIC_FORCEON){ for( uint8_t i = 20; i; i-- ){ _delay_us( 4 ); if( CLK_PIN == 0 ) // if CLK = 1 for >80us i = 20; } for( uint8_t i = 24; i; i-- ){ while( CLK_PIN == 0 ); // wait until CLK = 1 val <<= 1; while( CLK_PIN == 1 ); // wait until CLK = 0 if( DATA_PIN ) // read data val |= 1; // lsb first } } return val; } int main(void) { UBRRH = (uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,16000000)>>8); UBRRL = (uint8_t) UART_BAUD_CALC(UART_BAUD_RATE,16000000); UCSRB = (1<<RXEN) | (1<<TXEN); UCSRC = (1<<URSEL)|(3<<UCSZ0); DDRD |= ( 1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7); // als Ausgang setzen DDRC &= ~( 1 << PC0) | (1 << PC1) | (1 << PC2) | (1 << PC3) | (1 << PC4) | (1 << PC5); // als Eingang setzen USART_puts("hallo"); USART_puts(CR); while (1) { ermval=read_caliper; itoa(ermval,wert,10); USART_puts(wert); USART_puts(CR); _delay_ms(900); } }
Andreas W. schrieb: > uint32_t read_caliper( void ) > { > uint32_t val = 0; > > ATOMIC_BLOCK(ATOMIC_FORCEON){ > for( uint8_t i = 20; i; i-- ){ > _delay_us( 4 ); > if( CLK_PIN == 0 ) // if CLK = 1 for >80us > i = 20; > } > for( uint8_t i = 24; i; i-- ){ > while( CLK_PIN == 0 ); // wait until CLK = 1 > val <<= 1; > while( CLK_PIN == 1 ); // wait until CLK = 0 > if( DATA_PIN ) // read data > val |= 1; // lsb first > } > } > return val; > } Ich denke, die Methode ist nicht ganz korrekt. Denn sie überspringt das erste Bit (welches das LSB im Protokoll ist). Wenn man die Methode durchgeht sieht man, dass als erstes nach einer CLK 1-Phase von >80µs gesucht wird. Ist diese aufgetreten wird nach der nächsten positiven Flanke val um eins nach links geschoben. Dann bei der nächsten negativen Flanke wird der Daten Pin eingelesen. Aber die erste negative Flanke nach der >80µs 1-Phase ist schon das erste Bit, welches nicht eingelesen wird. Dafür wird am Ende ein falsches 24. Bit eingelesen, welches nicht mehr zum Messwert gehört. Das Problem mit dem Versatz der Flanke kann man sich einfach an den Screenshots von mir weiter oben herleiten. In dem Screenshot für 10mm ist der zweite 24Bit Wert 010000010000011111111111 (LSB...MSB). In richtiger Reihenfolge also 111111111110000010000010 (MSB...LSB, anschließend negiert ist es 000000000001111101111101 und in dezimal 8061, noch normiert sind es dann 8061*25,4mm/2048 = 9,997529296875mm. Wenn man nun die Bits um eins verschiebt kommt unter Umständen nur noch Murks raus. :) Ciao, Rainer
Hallo, Zunächst zur BASCOM Version: Nachdem ich XFLAG als INTEGER definiert habe und komplett vom EEPROM getrennt habe, weise ich jetzt zwei Werte zu. Frei ausgedacht: 66=Lesen 99=Nicht lesen. Dabei habe ich herausgefunden, warum die IF-Abfrage dazu führt, das es nach dem ersten Durchlauf nicht mehr geht. Ganz einfach, weil die Variable XFLAG nach dem ersten Durchlauf nicht mehr gleich 66 ist. Auch nicht 99. Nein, sie hat den Wert 12336. Und das Beste: An keiner Stelle im Programm weise ich das zu. Und die Krönung ist, das der Controller leider nicht kaputt ist. Als PonyProg meinte "Verify successful" wußte ich nicht ob ich lachen oder weinen soll... Zur C Version: @Rainer Du glaubst gar nicht wie froh ich wäre, wenn ich wenigstens falsche Werte hätte. Dann gäbe es etwas wo ich ansetzen kann. Aber leider ist der Wert "61" immer "61". Völlig egal was ich am Messschieber einstelle. Ich habe mal testweise die BASCOM-Variante von Carsten, in c umgeschrieben. Der Bit-Zähler "C" ist nach dem einlesen auf 0. Der hat also gar nichts von dem Signal mitbekommen. Danach habe ich mal folgendes in die main geschrieben: ok=0; while(1){ if (PC0){ if (ok==0){ ok=1; USART_puts("1"); USART_puts(CR); } } else { if (ok==1){ ok=0; USART_puts("0"); USART_puts(CR); } } } Einmal mit PC0 und einmal mit PC1. Wildes 1,0 geflackere? Pustekuchen! Der eine Pin immer auf 1, der andere immer auf 0. Wenn da tatsächlich was empfangen wird, hätte wenigstens zufällig mal das Bit umspringen müssen, oder nicht? Natürlich habe ich während des "Versuchs" den Messschieber bewegt. Gibt es für all diese Sachen eine logische Erklärung? Ich weiß echt nicht wo ich jetzt noch Fehler suchen soll.
Zeichne dir die Impulszuege auf Papier auf. Wenn ich mich richtig erinnere gab es bei dem Protokoll eine Laengere Pause, dann die Messdaten, dann eine kuerzere Pause und nochmals Messdaten. Du musst also immer an der richtigen Flanke zB nach der langen Pause anfangen, sonst wird das nichts. Ich habe vor Jahren anfangs ohne Interrupt (mit 89C4051 ) immer die ersten Bits verpasst. Mit Int. ging es dann problemlos. Auch das Nullen ,das Umschalten von schnell auf langsam...kein Problem.
Rigi Taler schrieb: > Zeichne dir die Impulszuege auf Papier auf. > Wenn ich mich richtig erinnere gab es bei dem Protokoll eine Laengere > Pause, dann die Messdaten, dann eine kuerzere Pause und nochmals > Messdaten. > Du musst also immer an der richtigen Flanke zB nach der langen Pause > anfangen, sonst wird das nichts. > Ich habe vor Jahren anfangs ohne Interrupt (mit 89C4051 ) immer die > ersten Bits verpasst. > Mit Int. ging es dann problemlos. Auch das Nullen ,das Umschalten von > schnell auf langsam...kein Problem. Wieso aufzeichnen? Ich habe doch drei Screenshots meines Logikanalyzers weiter oben angehängt, auf denen man das Protokoll genau sehen kann. Ich habe in meiner Methode nicht extra nach der langen Pause zwischen dem relativen und absoluten Messwert gesucht, was schnell in die Hose gehen kann. Ich habe einfach beide Messwerte, den Relativen sowie den Absoluten direkt hintereinander eingelesen. Wichtig ist nur sicherzustellen, dass man nicht gerade mitten in einem Messwert drin ist, wenn man anfängt Werte einzulesen. Danach braucht man nur noch 48 negative Flanken auszuwerten, wovon die letzten 24 der absolute Messwert ist. Ich mache es übrigens auch mit einem 89C4051 per Interrupt Flag, aber ohne extra ISR. :) Andreas wenn du die Nase noch nicht voll hast von neuem Code, dann schau dir mal meine Methode bt_Scan() unter [1] an. Diese läuft stabil auf einem fertigen System in meiner Werkstatt und liest bis zu vier Schieblehren gleichzeitig ein. Die Aufteilung der 24 Bit in drei Schleifen mache ich nur deswegen, weil sich 8 Bit Variablen viel schneller schiften lassen als eine 32 Bit Variable. Man könnte auch die ersten 24 Flanken per Zähler einfach verfallen lassen und danach erst anfangen die Werte einzulesen. Ciao, Rainer [1] https://quakeman.homelinux.net/viewvc/uVision/trunk/Schieblehre_Anzeige/Schieblehre.c?view=markup
Hallo, habe heute mal mein Scope an den Messschieber angeschlossen, da ich die Pause zwischen den 2 Datenpaketen nicht erwische. Nun ja, wie soll ich sagen...Die Wellenform ist etwas abweichend von meiner Erwartung. Zum Bild: Davor und dahinter ist nichts mehr. Man erkennt aber kurze Pausen, welche alle 4 Bits erfolgen. Also das 24*2 wird es wohl nicht sein, 7 BCDs auch nicht. Es müsste ein 1*24 Protokoll sein. Das ganze Signal ist ca. 9ms lang. Habt ihr das schonmal gesehen?
So, habe nun den Fehler in dem BASCOM-Code gefunden. Man schaue sich die deklaration von Mw_text an. Ich habe es aber auch nur zufällig gesehen, da mir die "falschen" Werte von xflag und co. irgendwie bekannt vorgekommen sind :-) Das ermittelte Protokoll macht es mir sehr einfach den Anfang eines Paketes zu erkennen. Ich prüfe einfach, ob in einem Zeitinterval von 600µs (längste Pause in einem Paket=~400µs) Clock auf low bleibt und weiß dann ganz sicher, das ich in der recht langen Pause zwischen zwei Paketen bin. Hat funktioniert. Keine Aussetzer mehr.
Hallo Andreas, Kannst Du diese Prüfroutine (600us) evtl. Mal posten, würde mich auch interessieren. Danke Grüße Carsten
Hallo @Carsten Hier der Code-Snippet für die X-Achse. Ich habe es zu beginn in Deine Funktion zum einlesen gesetzt. In meiner Grafik vom Scope sieht man, das Clock (pos. 2) im "Ruhezustand" auf 1 ist. Die Schleife wird verlassen, wenn in einem Zeitraum von mind. 599µs Clock auf 1 ist. Gibt es währenddessen einen Takt, so beginnt das Warten erneut. If Achse = "x" Then While V < 599 If Pinc.1 = 1 Then V = V + 8 Else V = 0 End If Waitus 8 Wend End If
Hi, eventuell ist der selbst programmierte Analyzer für das 2x24 Bit Schieblehren Protokoll für den einen oder anderen hier hilfreich. :) Der Thread zu meinen Tools ist unter [1] zu finden. Ciao, Rainer [1] Beitrag "Tools für Logicport LA1034 und GTKwave"
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.