Arduino Pins getaktet einlesen

Hi Freunde,

Ich habe einen Arduino Nano v3.0

Ich lese einen Sinus mit variabler Frequenz und einen Offset von 2,5 V und einen Vpp von 5 V ein und bewerte diesen mit LOW und high um an einen Ausgang eine Rechteck Spannung zu erzeugen.

Bis ca. 1KHz Frequenz funktioniert dies auch super, allerdings kommt es dann zu Verzerrungen beispielsweise ist das Aussignal bei 19KHz 3 mal so lang wie das an Signal bei 20KHz ist dies dann anderes Rum das high Signal ist 3 mal so lang wie das aus Signal.

Ich möchte gern eine Abtastung von 44.000 Hz erzeugen und meinen Loop halt über einen Timer steuern. Leider habe ich davon nicht so viel Geschick dies zu realisieren. Im Moment läuft der Loop() ohne Abtastung sondern einfach nur über analogRead.

Hat da einer eine Idee ?

Danke für eure hilfe.

Was Du also möchtest ist ein Komparator.
Welchen Frequenzbereich erwartest Du? Muss es dafür unbedingt ein µC sein?

Wenn du ab ca 1kHz Probleme kriegst, spricht das dafür, dass du ca. 1ms loop() durchlaufzeit hast. Ohne Code läßt sich das schwer sagen.
ein analogReag() dauert ca. 120µs. 44kHz wirst du nicht schaffen.

Wenn du aber schlicht einen Sinus in ein Rechteck wandeln willst, ist vielleicht eine reine Hardwarelösung besser.

Klaus_ww:
Was Du also möchtest ist ein Komparator.

Hat der Atmega328 übrigens eingebaut. Wird aber durch die Arduino IDE nicht implementiert.

Per Hand ansteuern:

Mit Lib:
http://www.leonardomiliani.com/2012/analogcomp-una-libreria-per-gestire-il-comparatore-analogico/?lang=en

Beim ADC kann man den Prescaler auf 16 ändern:
http://www.microsmart.co.za/technical/2014/03/01/advanced-arduino-adc/

Damit hat man einen ADC Takt von 1MHz, eine Wandlungszeit von ca. 20µs und theoretisch 50.0000 Samples pro Sekunde.

Aber wenn man hier schon den ADC verwendet, dann sollte man das auch per Hand machen und den free running mode verwenden:

(Wobei mit der Code da nicht so gefällt, da er nicht die Namen der Bits verwendet, aber in den Kommentaren steht was gemacht wird)

Im free running mode, macht der ADC ständig Wandlungen. Nachdem eine Wandlung fertig ist, wird automatisch die nächste gestartet und ein Interrupt ausgelöst. Zwischen den Wandlungen kann man dann andere Dinge tun. Das heißt anders als analogRead() blockiert das nicht! Das muss man dann auch mit dem niedrigeren Prescaler kombinieren.

Und wenn man den ADC über einen Timer steuern will, ist es auch besser das per Hand zu machen, als über die Arduino Sprachmittel mit denen man sich nur Overhead einfängt. Man kann den ADC nämlich direkt über Timer Interrupts triggern. Siehe Datenblatt Seite 256f.

Ein Komparator ist aber sicherlich die bessere Lösung! :slight_smile:

Erst mal danke für die schnellen Antworten.

µC ist Pflicht-Programm :smiley: nicht einfach weg rationalisieren.
Danke für die Tipps ich werde es ganz einfach mache und die Frequenz nicht über 1 kHz kommen lassen.
Gibt es eigentlich eine Möglichkeit den Arduino C Dialekt in normales C oder am besten gleich in Assembler um zu wandeln ?

Danke schon mal dafür im voraus.

Mit freundlichen Grüßen

Dir steht frei in der Arduino IDE das ganz normale AVR C zu verwenden wie es in AtmelStudio üblich ist (das meiste davon jedenfalls). Man kann auch beides problemlos kombinieren. Die Arduino Mittel für Dinge verwenden die nicht perfomant sein müssen und dann die Register des µC direkt ansprechen wenn es schnell gehen muss oder man etwas hat, dass in der Arduino IDE nicht implementiert ist.

Den Assembler Code kann man sich mit avr-objdump ansehen:

Und natürlich kann man auch inline Assembler einfügen:
http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

Für viele Dinge reichen die Arduino Sachen auch völlig aus. Das hier ist ein Fall wo man weiter gehen muss. Man muss halt wissen was die Grenzen sind.

@guntherb: 44.1 kHz geht mit einem 644P ECE 4760 Final Project: Phased Array Speaker System. Der ADC ist aber auch nicht schneller als in einem Arduino --> mit analogRead geht das in der Tat nicht, mit einem Arduino aber schon.

Der interne ADC des Atmega644 funktioniert auch nicht anders als der des 328. Das ist ein sukzessiver Approximation ADC, der über den Teiler vom Prozessortakt getaktet wird. Das ist bei allen Atmegas so.

Bei dem verlinkten Projekt wurde ein externen ADC verwendet und über SPI angesteuert. Der Atmega644 wurde verwendet weil er mehr I/Os hat. Das war nötig, da die zwei DACs mit parallel-Interface haben:

Ah, da hätte ich mal genauer lesen sollen. Also Blick ins Datenblatt wo die echte Grenze ist --> ADC braucht bzw 13.5 Zyklen. ADC Clock muesste bei ~600 kHz sein --> möglich allerdings nicht mit 10 Bit Auflösung.