Hallo zusammen. Da ich selber nicht weiter komme, frage ich mal die Profis. Ich habe drei verkettete 12bit Asynchronzähler mit 32768Hz getaktet, deren Zustände über 3 schieberegister par2ser abgefragt werden. Der Zähler läuft problemlos. Beim Einlesen in den μC bekomme ich allerdings Zufallszahlen. Kann mir jemand einen Tip geben wo ich mir hier Störungen einfangen könnte? Überlegungen: 1. Pulldown Widerstände an den Ausgängen der Zähler 2. Entstörkondensator an Vcc der Schieberegister 3. Pullup an der Datenleitung der Schieberegister Leider fehlt mir ein Oszi mit dem ich der Sache auf die Schliche kommen könnte. Würde mich über den ein oder anderen Hinweis freuen.
:
Verschoben durch Admin
Chris schrieb: > Würde mich über den ein oder anderen Hinweis freuen. Hallo! Faulheit, Bequemlichkeit oder "Ich weis was, das Du nicht weist"? Schaltung und Software sind ja wohl nicht zu viel verlangt? Du erhältst sonst nur "Super"-Hinheise zu Zeile 42 und R42.
asynchrone Zähler kannst du nicht zu jedem beliebigen Zeitpunkt auslesen. Jede Stufe hat eine gewisse Verzögerung gegenüber der vorigen, so dass im schlechtesten Fall erst nach Durchlaufen aller Stufen der richtige Zählerstand an den Ausgängen anliegt. In der Zwischenzeit liegen deine "Zufallszahlen" an.
1 / 32768 Hz sind ca. 30.5 us. Wenn Du schlau bist, startest Du das Einlesen mit einer Flanke die die Zaehler weiterschaltet. Um die Durchlaufzeit durch die Zaehlerkette zu beruecksichtigen, solltest Du noch ca. 1 us warten. Dann hast Du noch rund 29 us Zeit die Schieberegister in den Controller zu schieben.
Gebe zu, ich war ein wenig voreilig. Hier als Ergänzung der Schaltplan und der Code. Alles zusammen befindet sich im Moment auf nem Breadboard. Danke schon mal für die vorherigen Antworten. Der aktuelle Zählerstand wird beim Setzen von PL in das Schieberegister geladen. Der Zähler zählt doch weiter ohne das Register zu beeinflussen so viel ich weiß. Schaut euch mal mein Gebastel an. Danke schon mal für eure Mühe !
1 | int PLOADPIN = 8; |
2 | int CLOCKPIN = 7; |
3 | int DATAPIN = 9; |
4 | int CEPIN = 6; |
5 | |
6 | byte bitarray[24]; |
7 | |
8 | void setup(){ |
9 | Serial.begin(57600); |
10 | pinMode(DATAPIN, INPUT); |
11 | pinMode(PLOADPIN, OUTPUT); |
12 | pinMode(CLOCKPIN, OUTPUT); |
13 | pinMode(CEPIN, OUTPUT); |
14 | |
15 | digitalWrite(CEPIN, HIGH); |
16 | digitalWrite(PLOADPIN, HIGH); |
17 | digitalWrite(CLOCKPIN, LOW); |
18 | }
|
19 | |
20 | void loop(){ |
21 | ShiftIn(); |
22 | delay(100); |
23 | }
|
24 | |
25 | void ShiftIn(){ |
26 | digitalWrite(PLOADPIN, LOW); |
27 | delayMicroseconds(10); |
28 | digitalWrite(PLOADPIN, HIGH); |
29 | delayMicroseconds(10); |
30 | |
31 | digitalWrite(CEPIN, LOW); |
32 | |
33 | for(int i = 0; i <= 23; i++){ |
34 | digitalWrite(CLOCKPIN, LOW); |
35 | delayMicroseconds(10); |
36 | digitalWrite(CLOCKPIN, HIGH); |
37 | bitarray[i] = digitalRead(DATAPIN); |
38 | delayMicroseconds(10); |
39 | }
|
40 | digitalWrite(CEPIN, HIGH); |
41 | |
42 | //convert to decimal
|
43 | long num = 0; |
44 | double msec = 0; |
45 | long tempNUM = 0; |
46 | for(int i = 0; i <= 23; i++){ |
47 | num = (pow(2, (23-i))*bitarray[i]); |
48 | tempNUM = tempNUM + num; |
49 | }
|
50 | msec = tempNUM / 32768; |
51 | for (int i = 0; i <= 23; i++){ |
52 | Serial.print(bitarray[i]); |
53 | }
|
54 | Serial.print(" "); |
55 | Serial.println(tempNUM); |
56 | }
|
Ausgabe (Ausschnitt entspr. ca. 1500ms): 100000001001110001011011 8428617 010010101010101010101001 4893340 001010101010101010101100 2796196 101010101010101001010100 11184706 101010101010010101010100 11183426 101010101010110101010100 11185473 101010101011010101010100 11187521 101001010101010101010101 10835265 010101010101010100101011 5592347 010101010101011010101011 5592730 011010101010101010100100 6990487 100101010101010101101011 9786709 010101010101011010101011 5592730 001010101010101001010101 2796110
"Zufallszahlen" sicher nicht. Vermutlich sind die oberen bits (die sich seltener ändernd) okay, und die unteren haben fehler. Dann liegt es, wie schon gesagt, daran, dass du den Wert zu früh nach der Clock-Flanke in die Schieberegister übernimmst. Im Datenblatt steht der Wert t_pd (Qn to Qn+1). Den nimmst du für deine Versorgungsspannung und Temperaturbereich (max.-Wert) 12 3. Angenommen das wären 100ns, darfst du den Zähler frühestens 3.6us nach der Clock auslesen. Das reicht dann immerhin noch für ca. 270 KHz. Da dein Schiebereigster ein parallel load signal hat, kannst du den aktuell anliegenden Zählerstand auf einen Schlag in das Schieberegister übernehmen. Danach hast du genügend Zeit, die Daten aus dem Schieberegister raustackern zu lassen, solange PE_N high ist, werden keine neuen (sich verändernden) Daten vom Zähler übernommen. Ich würde einfach kurz bevor der Zähler einen Clock-Impuls bekommt, die Schieberegister laden. Dann bist du auf der sicheren Seite.
Für den parallel load muss CEPIN und PLOADPIN low sein, und du dem Register eine Clock geben (low->high). Danach dann PLOADPIN wieder auf high und die Daten raustackern. Im Augenblick samplest du vermutlich Rauschen auf deinem offenen ersten seriellen Input des ersten Registers. An diesen Pin solltest du einen Pullup oder pulldown legen. Kannst ja mal gucken, ob du nur noch nullen bekommst, wenn du diesen Pin mal auf GND setzt.
:
Bearbeitet durch User
Das Problem ist halt, dass dein uC nicht weiss, mit welchem Abstand er zur Clock sampled. Mal doof gefragt: 33KHz sind ja nicht die Welt. Kannst du nicht einfach das Eingangssignal auf einen Input des uC legen, und eine Interruptfunktion zum Zählen benutzen? Die ist ja entsprechend kurz... void interrupt_function() { counter_value++; }
:
Bearbeitet durch User
Moin, Abgesehen von den schon angesprochenen Problemen: Ist das wirklich so gewollt, dass der Q12 der 4040s jeweils nicht an einen Schieberegistereingang gefuehrt ist? Deren Resetpins so offen rumfliegen lassen, ist sicher auch nicht gut. Gruss WK
derguteweka schrieb: > Abgesehen von den schon angesprochenen Problemen: Ist das wirklich so > gewollt, dass der Q12 der 4040s jeweils nicht an einen > Schieberegistereingang gefuehrt ist? Hehe, good catch, total übersehen. 3 Schieberegister reichen natürlich nur für 24 Bit = 2 Counter.
Hallo Leute. Vielen Dank für die schnelle Hilfe. Warum einfach wenns auch kompliziert geht. Den Impuls der RTC direkt über nen Interrupt zu zählen . . . Warum komm ich da net selber drauf. Da ich sonst keine zeitkritischen Funktionen im späteren Gesamtprogramm haben werde, ist das ne super Alternative. Werde die Möglichkeit mal im Zusammenhang mit dem Rest testen. Danke nochmal. Euer Forum und die erfahrenen Leute hier haben mir schon oft und viel geholfen.
Noch eine Anregung (reduziert die Anzahl der Interrupts): http://www.atmel.com/images/atmel-1259-real-time-clock-rtc-using-the-asynchronous-timer_ap-note_avr134.pdf
:
Bearbeitet durch User
Danke für den Hinweis. Ich nutze eine externe RTC inkl. Temperatursensor für sehr genaue Impulse da ich von dem Onboardcounter nicht so ganz überzeugt bin. Im Ganzen wird die Schaltung zur Zeitmessung mit der Genauigkeit 1//100s eingesetzt. Da hier später noch andere Tolleranzen mit reinspielen, wie z.B. allein die Ansprechzeit der Lichtschranken von ca. 500 μs, will ich Fehler wo es nur geht minimieren. Ich bin sicher, die externe RTC ist genauer als der Onboardchip des Arduino.
Chris schrieb: > Ich nutze eine externe RTC Werde allerdings noch einen Frequenzteiler einsetzen, dann ist der Interrupt denke auch nicht so gefordert ;-)
@administrator Der Thread kann geschlossen werden. Ich denke das Problem (Knoten im Hirn) ist behoben.
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.