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 Zeilen1 | 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.




