Frequenzzähler

http://sites.schaltungen.at/arduino-uno-r4/frequenzzaehler

http://www.linksammlung.info/

http://www.schaltungen.at/

                                                                                            Wels, am 2019-05-10

BITTE nützen Sie doch rechts OBEN das Suchfeld  [                                                              ] [ Diese Site durchsuchen]

DIN A3 oder DIN A4 quer ausdrucken
*******************************************************************************I**
DIN A4  ausdrucken   (Heftrand 15mm / 5mm)     siehe     http://sites.schaltungen.at/drucker/sites-prenninger
********************************************************I*
~015_b_PrennIng-a_arduino-uno-r4/frequenzzaehler (xx Seiten)_1a.pdf


       ACHTUNG: Sketche könnten fehlerhaft sein ! ! !




Frequenzzähler mit Arduino
An manchen Schulen werden Zählraten und andere Ereignisse im Praktikum gemessen. Ein GM-Zählrohr liefert Impulse, die der Intensität von z.B. Gamma-Stahlen entsprechen. In der Mechanik können Geschwindigkeiten mittels Speichenrad in eine Frequenz gewandelt werden. Interferenzübergänge erlauben Aussagen zu optischen Weglängenänderungen.
FrequencyCounter 50Hz


Arduino zeigt die Netzfrequenz bei offenem Eingang auf einem LCD-Display.

Ein Blick in die Referenz auf arduino.cc zeigt bei den Eingaben unter 'Advanced I/O' die Funktion pulseIn(). Die Beschreibung sagt, dass mit dem Aufruf pulseiIn(pin, HIGH) gewartet wird, bis das Signal an dem Eingangs-Pin (pin) auf Logikpegel HIGH geht. Dann wird ein Timer gestartet und gewartet bis der Pegel LOW erreicht wird. Die verstrichene Zeit wird in Mikrosekunden zurück geliefert. Etwas anders ausgedrückt: puseIn(pin,HIGH) liefert die Impulsdauer ti.
Die Impulspause tp kann mit pulsIN(pin,LOW) ermittelt werden. Die Periodendauer T ergibt sich aus T = ti+ tp. Bei einem symmetrischen Rechtecksignal ist ti = tp, also die Zeit für HIGH-Pegel gleich der Zeit für LOW-Pegel.

Die Funktion kehrt bei einem Timeout mit dem Wert 0 zurück, womit auch bei fehlendem Signal das Programm fortgesetzt werden kann.

Der Kehrwert der Periodendauer T entspricht der Frequenz f. Aus Mikrosekunden (1e-6) werden Megahertz (1e6). Um eine Anzeige in Hertz zu erreichen wird mit 1e6 multipliziert. Hier der Sketch.

/* Frequenzzähler Gibt die Frequenz des Spannungsignals an Pin 7 aus */int pin = 7;unsigned long T;          //Periodendauer in usdouble f;                 //Frequenz in MHz void setup() {Serial.begin(9600); pinMode(pin, INPUT);}void loop() {T = pulseIn(pin, HIGH) + pulseIn(pin, LOW); if (T==0) Serial.println("Timeout."); else  {f=1/(double)T;          // f=1/T                   Serial.println(f*1e6);  //Ausgabe in Hertz } }

Quelle:
http://www.hjberndt.de/soft/ardfreq.html







Arduino Frequency Counter  27,78Hz


  • Arduino Uno.
  • 3 Pin LCD Interface Board.
  • 16 x 2 LCD
  • IC 74LS14

Program Code (if You Use LCD Without 3Pin Interface Board)


# Program code (if you use LCD without 3Pin interface Board)
#include <LiquidCrystal.h>
LiquidCrystal lcd(11, 7, 5, 4, 3, 2);
const int pulsePin = 12; // Input signal connected to Pin 12 of Arduino
int pulseHigh; // Integer variable to capture High time of the incoming pulse
int pulseLow; // Integer variable to capture Low time of the incoming pulse
float pulseTotal; // Float variable to capture Total time of the incoming pulse
float frequency; // Calculated Frequency


void setup() {
pinMode(pulsePin, INPUT);
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Instructables");
lcd.setCursor(0, 1);
lcd.print(" Freq Counter ");
delay(5000);
}


void loop() {
lcd.setCursor(0, 0);
lcd.print("Frequency is ");
lcd.setCursor(0, 1);
lcd.print(" ");

pulseHigh = pulseIn(pulsePin, HIGH);
pulseLow = pulseIn(pulsePin, LOW);
pulseTotal = pulseHigh + pulseLow; // Time period of the pulse in microseconds
frequency = 1000000/ pulseTotal; // Frequency in Hertz (Hz)

lcd.setCursor(0, 1);
lcd.print(frequency);
lcd.print(" Hz");

delay(500);
}


Quelle:
https://www.instructables.com/id/Arduino-Frequency-Counter/
https://www.collaborizm.com/project/S1_CiLJLl




ARDUINO FreqCount

Quelle:
https://www.arduinolibraries.info/libraries/freq-count






Frequency counter using Arduino (upto 40kHz)

Viele Leute hier fragten nach einem Frequenzzähler und endlich hatte ich genug Zeit, um einen zu machen.
Dieser Frequenzzähler, der Arduino verwendet, basiert auf der UNO-Version und kann bis zu 40 KHz zählen.
Ein 16 × 2 LCD-Display dient zur Anzeige der Frequenzzählung.
Die Schaltung hat ein Minimum an externen Komponenten und zählt direkt die Frequenz.
In jedem Fall darf die Amplitude der Eingangsfrequenz nicht größer als 5 V sein.
Wenn Sie Signale über 5 V messen möchten, müssen zusätzliche Begrenzungskreise hinzugefügt werden, die ich zu einem anderen Zeitpunkt anzeigen werde.
Jetzt machen Sie es einfach mit 5V-Signalen.

Die zu zählende Frequenz ist mit dem digitalen Pin 12 des Arduino verbunden.
Die Funktion pulseIn () wird hier zum Zählen der an Pin 12 angeschlossenen Frequenz verwendet.
Die Funktion pulseIn () zählt die Anzahl der Impulse (HIGH oder LOW), die an einem bestimmten Pin des Arduino ankommen.
Die allgemeine Syntax dieser Funktion lautet pulseIn (Pin, Wert, Zeit), wobei Pin der Name des Pins ist, Wert entweder HIGH oder LOW ist und Zeit die Zeit ist, für die die Funktion auf einen Impuls warten soll.
Die Funktion gibt Null zurück, wenn innerhalb der angegebenen Zeit kein gültiger Impuls vorhanden ist.
Die pulseIn () - Funktion kann Impulse mit einer Zeitspanne von 10 bis 3 Minuten zählen.



Schaltbild des Frequenzzählers mit ARDUINO UNO R3



Mit dem Potentimeter R1 = 10k wird der Kontrast des LCD-Bildschirms eingestellt.
Der Widerstand R2 begrenzt den Strom durch die LED-Hintergrundbeleuchtung.

Im Programm werden die hohe Zeit und die niedrige Zeit des Eingangssignals mit separaten pulseIn () - Funktionen gemessen.
Dann werden die hohen und niedrigen Zeiten addiert, um die Gesamtzeitdauer des Signals zu erhalten.
Die Frequenz ist nur eine Zeitspanne in Sekunden.
Die pulseIn () - Funktion gibt den Zeitraum in Mikrosekunden zurück.
Gesamtzeitspanne in Mikrosekunden, zuerst geteilt durch 1000.
Dann wird 1000 durch das Ergebnis geteilt, um die Frequenz in Hertz zu erhalten.
Das Programm des Frequenzzählers mit Arduino ist unten dargestellt.


Programm / Sketch
#include <LiquidCrystal.h>int input=12;int high_time;int low_time;float time_period;float frequency;LiquidCrystal lcd(7, 6, 5, 4, 3, 2);void setup(){pinMode(input,INPUT);lcd.begin(16, 2);}void loop(){lcd.clear();lcd.setCursor(0,0);lcd.print("Frequency Meter");high_time=pulseIn(input,HIGH);low_time=pulseIn(input,LOW); time_period=high_time+low_time;time_period=time_period/1000;frequency=1000/time_period;lcd.setCursor(0,1);lcd.print(frequency);lcd.print(" Hz");delay(500);}

Quelle:
http://www.circuitstoday.com/frequency-counter-using-arduino


Arduino Frequency Counter with 16×2 LCD Display

Frequenzzählgerät.
Vor kurzem hatte ein Freund von mir ein Problem mit der ECU seines Autos und brauchte ein Frequenzzählgerät.
Die Lösung war eine Vorrichtung zur Bestimmung der vom Steuergerät abgegebenen Impulsfrequenz gegen den Drehzahlmesser.
Das Gerät musste also in der Lage sein, digitale Impulse zwischen 1,0V und 5,0V zu lesen, die dann von einem digitalen pin am Arduino als HIGH- und LOW-Impulse interpretiert werden.
Dann wird die Frequenz in Hz / kHz auf dem LCD-Display ausgegeben.

Hardware
1x Arduino Uno
1x 16×2 LCD SPI (nicht der I2C)
3x Schaltdrähte 0,64mm

Die Einrichtung
Ich hatte einen 16×2-LCD-Monitor gekauft und nie etwas damit gemacht, also war es an der Zeit.
Das LCD hatte die Form eines mit Arduino Uno kompatiblen Schildes.
Ich schnappte das LCD auf den Arduino und befestigte einen Überbrückungsdraht an Analog-Pin A5.
Ich verwende immer noch den digitalen Eingang in meinem Code, aber da fast alle digitalen Pins vom LCD-Display belegt wurden, habe ich mich für eine analoge Pin entschieden.
Jetzt kann das Gerät über den USB-Anschluss, den Klinkenstecker oder die Vin mit Strom versorgt werden.
Ich verwende die Vin hier, da mir kein Wagenheber zur Verfügung stand und ich die Vorräte des Autos benutzte (ungefähr 12V..14V).

Schaltung
Wenn Sie die LCD-Abschirmung verwenden, können Sie diesen Teil überspringen.
Wenn Sie jedoch keine Abschirmung haben, finden Sie hier die erforderlichen Anschlüsse.

LCD ———— Arduino
RS ———– 12
Enable ——11
D4 ———– 5
D5 ———– 4
D6 ———– 3
D7 ———– 2
R / W - GND
Vss ———- GND
Vcc ------ + 5V

Fügen Sie einen 10k Ohm Widerstand zwischen + 5V und GND hinzu.
Stecken Sie die + 12V der Batterie in den Arduino Vin-Pin und die Masse der Batterie in die Arduino GND.
Zum Schluss wird der A1-Pin-Jumper mit der Quelle der zu messenden Frequenz verbunden.

HINWEIS:
In meinem Fall waren sowohl die ECU als auch der Arduino mit dem GND verbunden (am GND-Anschluss der Batterie).

Der Sketch
Die Sketch ist ziemlich einfach.
Wir werden 3 Werte auf dem Bildschirm anzeigen.
Die aktuelle Frequenz, die maximale Frequenz und die minimale Frequenz werden jede Sekunde aktualisiert.
Min und Max werden alle 5 Minuten zurückgesetzt.
Wir verwenden den LiquidCrystal.h, der in der Arduino IDE-Installation enthalten ist.
Sie müssen also nichts hinzufügen.

Einschränkungen
Wir haben das Gerät mit einem anderen Arduino getestet (was wahrscheinlich nicht das Beste ist)
und fanden heraus, dass das Gerät bei 50kHz einen Fehler von etwa +/- 3% hatte, also ist es ziemlich gut.
Über 50 kHz hinaus begann der Fehler zu steigen und wurde sehr ungenau.
Wir empfehlen daher, es nur für Frequenzen unter 50 kHz zu verwenden.



ARDUINO UNO Sketch
/* * The MIT License (MIT) *  * Copyright (c) 2016 RuntimeProjects *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: *  * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */#include <LiquidCrystal.h>LiquidCrystal lcd(8, 9, 4, 5, 6, 7);long microSecs;long freq;int lastBit;int nowVal;long secs;long maxHz;long minHz;long minmax;void setup() {  // set up the LCD's number of columns and rows:  lcd.begin(16, 2);  // Print a message to the LCD.  lcd.print("Loading...");  pinMode(A1,INPUT);  pinMode(A5,OUTPUT);  microSecs = micros();  freq = 0;  lastBit = 0;  nowVal =0;  maxHz=0;  minHz=0;  minmax=0;  secs = millis();  //Serial.begin(9600);}int x=0;void loop() {  if ((microSecs+20)<micros()){      nowVal=digitalRead(A1);       if (lastBit!=nowVal) {        lastBit=nowVal;        freq=freq+1;      }      if (freq>maxHz){        maxHz=freq;      }      if (freq<minHz){        minHz=freq;      }      //lcd.clear();      //lcd.print();      microSecs = micros();  }  if (secs+1000<millis()){    if (minmax+300000<millis())    {      minmax=millis();      minHz=freq;      maxHz=freq;          }            lcd.clear();      lcd.print((freq/2));      lcd.print("hz");      lcd.setCursor(0,1);      lcd.print("+: ");      lcd.print(maxHz);      lcd.print(" -: ");      lcd.print(minHz);            freq=0;      secs=millis();        }}

Sie zählen beide Flanken innerhalb von 20µs -> es ist klar, dass dies nur für weniger als 50kHz funktioniert.
Sie können einen Interrupt bei Änderung für die Eingabe verwenden.
Sie stellen die microSecs am Ende des Zählens neu ein - dies sollte durch Hinzufügen von 20 zu microSecs erfolgen
Sie prüfen während des Zählens auf Min & Max. Dies ist nicht erforderlich. Jede Sekunde ist gut


Quelle:
https://www.hackster.io/jasirtp/arduino-frequency-counter-with-16x2-lcd-display-c99779




Pulse Counter on Arduino

Frequency Counting Using Arduino

Quelle:

Quelle:
https://www.tek.com/sites/default/files/courseware/Arduino_Frequency_Counter.pdf



Speed Measuring Sensor Counter Motor Test Groove Coupler Module For Arduino


Vcc Connect the positive 3.3 5 v power supply
GND Connect power negative
Do TTL switch signal output
Ao This module does not work

Geschwindigkeitsmesssensorzähler Motor Test Groove Coupler Module für Arduino

Merkmal:
Verwendung eines optischen Sensors mit eingekerbter Nut, Breite 5 mm.
Der Ausgangsstatus leuchtet, wenn der Ausgangspegel hoch ist, sind die Lichter ausgeschaltet.
Wenn der Ausgangspegel niedrig ist, ist er eingeschaltet.
Wenn es abgedeckt ist, gibt es einen hohen Pegel aus, andernfalls einen niedrigen Pegel.
Gutes Signal und Wellenform mit starker Ansteuerung für mehr als 15mA.
Die Arbeitsspannung von 3,3V bis 5,0V.
Ausgang: Digitaler Schaltausgang (0 und 1).
Ausgestattet mit einem festen Bolzenloch, einfach zu installieren.
Platinengröße für kleine Platinen: 32mm x 14mm.
Use the LM393 wide voltage compare


Quelle:
https://forum.arduino.cc/index.php?topic=365449.0
https://www.amazon.com/Measuring-Sensor-Counter-Coupler-Arduino/dp/B00Q6WKFE2
https://nl.aliexpress.com/item/Speed-Meetsensor-Counter-Motor-Test-Groove-Koppeling-Module-Optische-Koppeling-Module-Voor-Arduino-3-2-cm/32914762903.html








Eingangsverstärker für den Arduino Frequenzzähler 10 Hz bis 10 MHz

Für den Arduino Uno Frequenzzähler wird ein Eingangsverstärker entwickelt um auch kleinere Signale messen zu können und den Arduino zu schützen.

Die Forderungen

Eine einfache 5V Spannungsversorgung.
Eine Transistor Schaltung für kleine und hohe Eingangsspannungen.
Ein breiter Frequenzbereich soll abgedeckt werden, von wenigen Hz bis 8 MHz.
Nur Standard Bauteile kommen zum Einsatz.
Am Ausgang soll eine saubere 5V TTL Spannung enstehen.

Die Schaltung




Eingangsverstärker

Die Bauteile
Es werden BC547B Transistoren verwendet mit einer Transitfrequenz (Verstärkung = 1) von ca. 300 MHz.
Die sollten bis 8 MHz ausreichend Verstärkung haben.

Um die Schaltung zu schützen wird ein Eingangswiderstand und 2 Dioden gegeneinander zu Masse geschaltet.
Der 1kOhm Widerstand muss bei 30V knapp 30mA Strom vertragen, was eine Gleichspannungs Verlustleistung von 0,9W ergibt.
Bei einer Wechselspannung ist das ca. die halbe Leistung, also 0,5W. Es kann ein Metallschicht Widerstand verwendet werden.
Die Dioden 1N4148 sind mit 30mA auch weit unter ihrem Maximalstrom von 300mA.
Die erste Stufe wird mir einem Kondensator gekoppelt um einen stabilen Gleichspanungsarbeitspunkt zu bekommen.
Für kleine Frequenzen wird ein 4,7uF Keramik Kondensator vorgeschaltet.
Zur Sicherheit für den Resonanzfall wird ein 100nF Kondensator parallel geschaltet.
Im Emitter wird ein Widerstand verwendet um die Schaltung etwas hochohmiger zu machen, dafür sinkt die Verstärkung.
Der CB Widerstand R2 wird auf eine Kollektorspannung von ca. 2,5V ausgelegt.

Die zweite Stufe wird auch über einen Kondensator gekoppelt, hier 2 x 4,7uF parallel zu 100 nF, da die Ausgangsspannung der ersten Stufe höher ist
und diese 2. Transistorstufe ohne Emitterwiderstand im Eingang niederohmiger ist.
Dahinter ist ein Inverter eingesetzt. Das wird in der Schaltung später ein 7400 TTL Baustein werden.
Hier reicht ein Koppelkondensator von 100nF. Damit ist eine saubere 5V TTL Ausgangsspannung gegeben, die direkt an den Arduino Uno Pin gelegt werden kann.

Die Simulationsergebnisse
Die Ergebnisse sind im Zeitbereich dargestellt für jeweils einige Schwingungen.
Rot > Eingangssignal
Blau > Signal nach der 1. Transistor Stufe
Grün > Ausgangssignal des idealen Inverters (hier 1V, später mit dem TTL Baustein 5V)


Eingangsspannung 10Hz / 10mV


Eingangsspannung 2MHz 1mV


Eingangsspannung 10MHz 10mV
Bei 10MHz macht sich die Verstärkungsabsenkung (ft=3MHZ) schon deutlich bemerkbar, sodass hier 10mV Eingangssignal anliegen sollten.
Die Simulation wurde mit LT-Spice durchgeführt, das bei Linear Technology kostenlos zur Verfügung steht.

Quelle:
http://shelvin.de/eingangsverstaerker-fuer-den-frequenzzaehler-10-hz-10-mhz/





Ein Frequenzzähler für niedrige Frequenzen mit dem Arduino Uno
und der Periodendauer Messung

Frequenzzähler für niedrige Frequenzen mit Pulslängenmessung
4 Antworten

Über die Messung der Pulslängen HIGH und LOW kann aus einem Rechtecksignal, oder einem ähnlichen Signal, die Frequenz bestimmt werden.
Der Arduino bietet hierzu die Funktion pulseIn(pin, signal) an.
Die funktioniert an jedem Digital Pin und misst, wenn man die HIGH und die LOW Zeit addiert die Periodendauer T in Mikrosekunden.

Die Grenzwertbetrachtung
Bei einer Periodendauer von 100 Mikrosekunden entspricht +- 1 Mikrosekunde Fehler 1%, sodass bis ca. 10 kHz gemessen werden kann mit einem Fehler <1%.
Die Periodendauer T wird als unsigned long angegeben und kann somit bis maximal 4.294.967.295 zählen.
Das entspricht 230 Mikroherz und somit ist der Millihertz Bereich voll erfasst und 3 Kommastllen sind bei niedrigen Frequenzen möglich.
Der Messbereich beträgt also 1 Millihertz bis 10 kHz.

Das Programm

void loop() {  time=micros();  do {    T = pulseIn(pin, HIGH) + pulseIn(pin, LOW);    if (T==0) {      Serial.println("Timeout.");    }    else {      f=1/(double)T;        // f=1/T         k++;        }      fsum+=f*1e6;  } while( micros() < (time+1e6)); // 1 Sekunde mitteln  f = fsum/k*0.9925;         // Korrekturwert einrechnen  Serial.println(f);  fsum=0.0;  k=0;}

Im Programm wird über 1 Sekunde (1e6 Mikrosekunden) gemittelt, deshalb sind nur Frequenzen bis runter zu ca. 3 Hz messbar.
Für niedrigerer Frequenzen muss entsprechend länger gemittelt werden, zum Beispiel 10, 100 oder 1000 Sekunden um 3 Millihertz erfassen zu können.
Fazit
Mit dieser einfachen und flexiblen Routine sind Messung von 3Hz bis 10 kHz möglich incl. einiger Nachkommastellen.
Links
Für höher Frequenzen wird die hier beschriebene Technik verwendet.

Quelle:
http://shelvin.de/ein-frequenzzaehler-fuer-niedrige-frequenzen-mit-dem-arduino-uno-und-der-pulslaengenmessung/





Frequenzzähler mit LCD Display am Arduino Uno




Zum Frequenzzähler wird ein LCD Display 16 x 2 hinzugefügt basierend auf den beiden Projekten:
– Frequenzzähler Teil 1 & Teil 2
– LCD Display Teil 1 & Teil 2
Das 1602 LCD Display soll die gemessene Frequenz ausgeben.
Die Anschlüsse bei beiden Projekten überschneiden sich nicht, sodass sie alle weiter verwendet werden.

Die Display Anschlüsse:

LCD > Arduino
————-
VSS > GND
VDD > +5V
V0 > 10k Poti + 1kOhm Widerstand > GND
RS > Pin 12
R/W > Pin 13
E > Pin 11
D4 > Pin 7
D5 > Pin 8
D6 > Pin 9
D7 > Pin 10
A > +5V
K > 10 Ohm Widerstand > GND

Die Messfrequenz wird mit einem Pegel von ca. 5V auf Pin 5 und GND angeschlossen.
Achtung: nicht über 5V Pegel!


Der Aufbau

Das Programm


// Arduino Uno Frequenzzähler bis ca. 5 MHz// Eingangsspannung muss an Pin 5 mit ca. 5V Pegel ankommen.// V 1.2: 1602 Display hinzugefügt// // Beschreibung und Library unter:// http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library///// Matthias Busse 24.05.2014 Version 1.2/* LCD Display Anschlüsse:LCD > Arduino-------------VSS > GNDVDD > +5VV0  > 10k Poti + 1kOhm Widerstand > GNDRS  > Pin 12R/W > Pin 13E   > Pin 11D4  > Pin 7D5  > Pin 8D6  > Pin 9D7  > Pin 10A   > +5VK   > 10 Ohm Widerstand > GND */#include < FreqCounter.h>#include < LiquidCrystal.h>LiquidCrystal lcd(12, 13, 11, 7, 8, 9, 10);long int rfreq, mfreq;               // rfreq=Rechenfrequenz, mfreq=Messfrequenzint hz=0, khz=0, mhz=0;              // Hz, kHz und MHz je 3 Ziffernchar sfreq[15];                      // sfreq=Stringfrequenzvoid setup() {  Serial.begin(38400);               // Serielle Ausgabe  Serial.println("Frequenz Zaehler V 1.2");  lcd.begin(20,4);  lcd.clear();  lcd.setCursor(0,0);  lcd.print("Frequenz Zaehler");  delay(1000);}void loop() {  FreqCounter::f_comp= 8;              // Kompensation einstellen  FreqCounter::start(1000);            // Zähler starten für 1000ms  while (FreqCounter::f_ready == 0)    // warten bis der Zähler fertig ist   mfreq=FreqCounter::f_freq;           // Ergebnis lesen  rfreq=mfreq;  hz=rfreq-(int((rfreq/1000))*1000);   // Hz ermitteln  rfreq=(rfreq-hz)/1000;               // kHz ermitteln  khz=rfreq-(int((rfreq/1000))*1000);  rfreq=(rfreq-khz)/1000;              // MHz ermitteln  mhz=rfreq-(int((rfreq/1000))*1000);  if(mfreq<1000)                       // Hz in String schreiben    sprintf(sfreq,"        %3d Hz",hz);  if((mfreq>=1000)&&(mfreq<1000000))   // kHz.Hz in String schreiben    sprintf(sfreq,"    %3d.%03d Hz",khz,hz);  if(mfreq>999999)                     // MHz.kHz.Hz in String schreiben    sprintf(sfreq,"%3d.%03d.%03d Hz",mhz,khz,hz);    Serial.println(sfreq);               // Terminal ausgeben  lcd.setCursor(1,1);                  // Display ausgeben  lcd.print("                ");  lcd.setCursor(1,1);  lcd.print(sfreq);}


Für den Frequenzeingang sollte noch eine Schutzschaltung vorgesehen werden,
z.B. ein 7400 IC mit 5V Berieb, das den Pin 5 des Arduino vor Überspannungen schützt.


Frequenzzähler mit dem Arduino Uno Teil 1

Wenn eine 5V Wechselspannung vorliegt, z.B. aus dem Rechteckgenerator, kann der Arduino die Frequenz direkt zählen.
Das funktioniert bis ca. 8 MHz bei einem symmetrischen
Rechtecksignal, ansonsten weniger. Martin Nawrath hat hierzu eine gute Library geschrieben und bereit gestellt.

Die Hardware
Beim Uno wird die 5V Rechteckspannung direkt an Pin 5 gelegt.
Bitte keine höhere Spitzenspannung verwenden, da das den Arduino beschädigen oder zerstören kann.
Am besten schaltet man einen TTL Baustein 74xx davor, der ist billiger zu ersetzen als der Mikrocontroller.

Die Software
Hier der Arduino Programmcode mit Kommentaren:

// Arduino Uno Frequenzzähler bis ca. 5 MHz// Eingangsspannung muss an Pin 5 mit 5V Pegel ankommen.// // Beschreibung und Library unter:// http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library///// Matthias Busse 11.04.2014 Version 1.0#include < FreqCounter.h>long int freq;void setup() {  Serial.begin(38400);               // Serielle Ausgabe  Serial.println("Frequenz Zaehler V 1.0");}void loop() { FreqCounter::f_comp= 8;             // Kompensation einstellen FreqCounter::start(1000);           // Zähler starten für 1000ms while (FreqCounter::f_ready == 0)   // warten bis der Zähler fertig ist  freq=FreqCounter::f_freq;           // Ergebnis lesen Serial.println(freq);               // und ausgeben}

Quelle:
http://shelvin.de/frequenzzaehler-mit-dem-arduino-uno/
http://shelvin.de/frequenzzaehler-mit-display/



Frequenzzähler mit dem Arduino Uno Teil 2

Die Frequenz wird zu besseren Lesbarkeit mit Dezimalpunkten ausgegeben.
Anstelle von 123445566 Hz wird nun 123.445.566 Hz ausgegeben.

Die Software
Hier der Arduino Programmcode mit Kommentaren:


// Arduino Uno Frequenzzähler bis ca. 5 MHz// Eingangsspannung muss an Pin 5 mit 5V Pegel ankommen.// // Beschreibung und Library unter:// http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library///// Matthias Busse 12.04.2014 Version 1.1#include < FreqCounter.h>long int rfreq, mfreq;               // rfreq=Rechenfrequenz, mfreq=Messfrequenzint hz=0, khz=0, mhz=0;              // Hz, kHz und MHz je 3 Ziffernchar sfreq[15];                      // sfreq=Stringfrequenzvoid setup() {  Serial.begin(38400);               // Serielle Ausgabe  Serial.println("Frequenz Zaehler V 1.1");}void loop() {  FreqCounter::f_comp= 8;              // Kompensation einstellen  FreqCounter::start(1000);            // Zähler starten für 1000ms  while (FreqCounter::f_ready == 0)    // warten bis der Zähler fertig ist   mfreq=FreqCounter::f_freq;           // Ergebnis lesen  rfreq=mfreq;  hz=rfreq-(int((rfreq/1000))*1000);   // Hz ermitteln  rfreq=(rfreq-hz)/1000;               // kHz ermitteln  khz=rfreq-(int((rfreq/1000))*1000);  rfreq=(rfreq-khz)/1000;              // MHz ermitteln  mhz=rfreq-(int((rfreq/1000))*1000);  if(mfreq<1000)                       // Hz in String schreiben    sprintf(sfreq,"        %3d Hz",hz);  if((mfreq>=1000)&&(mfreq<1000000))   // kHz.Hz in String schreiben    sprintf(sfreq,"    %3d.%03d Hz",khz,hz);  if(mfreq>999999)                     // MHz.kHz.Hz in String schreiben    sprintf(sfreq,"%3d.%03d.%03d Hz",mhz,khz,hz);  Serial.println(sfreq);               // und ausgeben}

Quelle:
http://shelvin.de/frequenzzaehler-mit-dem-arduino-uno-teil-2/



LCD Display Teil 1  4×20 am Arduino betreiben.

Ein LCD Display mit 4 Zeilen a 20 Zeichen mit dem Arduino betreiben.
Das Display wird im 4-Bit Modus parallel an den Arduino angeschlossen.

Die Hardware

Die Verbindungen
————————
LCD > Arduino
————————
VSS > GND
VDD > +5V
V0 > 10k Poti + 1kOhm Widerstand > GND
RS > Pin 12
R/W > Pin 13
E > Pin 11
D4 > Pin 7
D5 > Pin 8
D6 > Pin 9
D7 > Pin 10
A > +5V
K > 10 Ohm Widerstand > GND

Ich verwende hier zum Testen für die Anschlüsse ein Steckbrett.


LCD Steckbrett Arduino
Der Arduino kann das Display und die Hintergrundbeleuchtung gut mit 5V Spannung aus der USB Schnittstelle versorgen.

Eine zusätzliche Helligkeitseinstellung der Hintergrundbeleuchtung ist hier realisiert.

Die Software
Hier nun der Arduino Programmcode mit Kommentaren:


// 4x20 LCD Display Ausgabe//// Diese Bauteile verwendet werden: // Arduino Mega 2560 (auch für andere Arduinos geeignet)// LCD Display mit 4 Zeilen mit je 20 Zeichen// Widerstände: 1k und 10 Ohm// Poti: ca. 10 kOhm//// Matthias Busse 2.4.2013 Version 1.0/* LCD Display Anschlüsse:LCD > Arduino-------------VSS > GNDVDD > +5VV0  > 10k Poti + 1kOhm Widerstand > GNDRS  > Pin 12R/W > Pin 13E   > Pin 11D4  > Pin 7D5  > Pin 8D6  > Pin 9D7  > Pin 10 A   > +5VK   > 10 Ohm Widerstand > GND */#include < LiquidCrystal.h>LiquidCrystal lcd(12, 13, 11, 7, 8, 9, 10);void setup(){  lcd.begin(20,4);  lcd.clear();  lcd.setCursor(0,0); // Cursor Zeile 0 setzen  lcd.print("4x20 LCD TESTAUSGABE"); // Text ausgeben  lcd.setCursor(0,3); // Cusor Zeile 3  lcd.print("Matthias Busse V 1.0");}void loop(){  lcd.setCursor(3,1); // Zeile 1 Sekunden ausgeben  lcd.print("Sekunden: ");   lcd.setCursor(13,1);  lcd.print(millis()/1000); // die Sekunden seit Programmstart  delay(994); // nur fast 1000 ms warten weil das Programm auch ca. 6 ms benötigt}

Quelle:
http://shelvin.de/ein-lcd-display-4x20-am-arduino-betreiben/
https://www.arduino.cc/en/Reference/LiquidCrystal



LCD Display Teil 2   mit PWM Dimmer Funktion

Die Helligkeit der Hintergrundbeleuchtung beim LCD Display kann mit Hilfe der PWM – Puls Weiten Modulation – Funktion eingestellt werden.
Die Stromaufnahme meines Displays beträgt ca. 19mA gemessen.
Der Arduino Mega ist für maximal 40mA Ausgangsstrom an den Pins ausgelegt.
Das heisst wir sind weit im grünen Bereich und können die PWM Funktion des Arduino direkt für das Dimmen der LCD Hintergrundbeleuchtung verwenden.
Basierend auf der LCD 4×20 Schaltung wird eine Helligkeitseinstellung hinzugefügt.

Die Hardware
Der K Anschluss (Kathode / Minus) der Displaybeleuchtung wird über einen 10 Ohm Widerstand an den Arduino PWM Pin 6 gelegt ansonsten ist die Verkabelung genau wir bei der LCD 4×20 Schaltung.
Achtung: Die Logik ist jetzt umgekehrt, das heißt immer wenn der Pin 6 aus ist (0V) ist die LED Beleuchtung an.
PWM 0 bedeutet also volle Helligkeit und bei einem PWM Wert von 255 ist die Beleuchtung aus.
Die halbe Helligkeit wird bei einem Wert von ca. 200 erreicht.

Die Software
Hier der Arduino Programmcode mit Kommentaren:


// 4x20 LCD Display Ausgabe mit PWM Dimmer//// Diese Bauteile verwendet werden: // Arduino Mega 2560 (auch für andere Arduinos geeignet)// LCD Display mit 4 Zeilen mit je 20 Zeichen// Widerstände: 1k und 10 Ohm// Poti: ca. 10 kOhm//// Matthias Busse 22.4.2013 Version 1.1/* LCD Display Anschlüsse:LCD > Arduino-------------VSS > GNDVDD > +5VV0  > 10k Poti + 1kOhm Widerstand > GNDRS  > Pin 12R/W > Pin 13E   > Pin 11D4  > Pin 7D5  > Pin 8D6  > Pin 9D7  > Pin 10 A   > +5VK   > 10 Ohm Widerstand > PIN 6 */#include < LiquidCrystal.h>LiquidCrystal lcd(12, 13, 11, 7, 8, 9, 10);int belpin=6; // Pin für die Beleuchtungvoid setup(){  lcd.begin(20,4);  lcd.clear();  lcd.setCursor(0,0); // Cursor Zeile 0 setzen  lcd.print("4x20 LCD TESTAUSGABE"); // Text ausgeben  lcd.setCursor(0,3); // Cusor Zeile 3  lcd.print("Matthias Busse V 1.0");  pinMode(belpin, OUTPUT); // PWM Pin ist ein Ausgang}void loop(){  analogWrite(belpin, 200); // Beleuchtung 0(hell) - 255(dunkel)  lcd.setCursor(3,1); // Zeile 1 Sekunden ausgeben  lcd.print("Sekunden: ");   lcd.setCursor(13,1);  lcd.print(millis()/1000); // die Sekunden seit Programmstart  delay(994); // nur fast 1000 ms warten weil das Programm auch ca. 6 ms benötigt}

Quelle:
http://shelvin.de/lcd-display-mit-pwm-dimmer-funktion/




Den Frequenzzähler mit LCD Display auf der Platine aufgebaut.



Ist es möglich ein Schaltbild zu bekommen?
Dann könnte man besser erkennen, wie die beiden 15nF Kondensatoren und der 100 Ohm Widerstand
eingebaut wurden.
Ich habe das Bild für die Standard Quarz Beschaltung eingefügt.
Der 100 Ohm Widerstand ist für die LCD Beleuchtung und wird von LCD- (Kathode der LED Beleuchtung) zu Masse geschaltet.
Da war ein Fehler in der Beschreibung.
Die Quarz Kondensatoren sind nicht 15nF sondern 15pF.
Das ist jetzt geändert.
Schöner Artikel. Inzwischen gibt es ja arduinoartige Boards mit ESP8266 die mit 80 MHz getaktet werden.
Das müßte doch wesentlich höhere Grenzfrequenzen ergeben. Schon probieert?
Damit sollte es dann bis 30 MHz funktionieren.
Theoretisch liegt die maximal meßbare Frequenz bei der halben Taktfrequenz wenn das Meßsignal symetrisch ist.
In der Praxis ist das aber nicht sicher erreichbar, 1/3 ist da realistisch.



Ich habe den Frequenzzähler auf einer 4 x 6 cm großen Platine aufgebaut.
Mit einer Sockelleiste wird das 1602 LCD Display drauf gesteckt.
Die Stromversorgung wird an den Klemmen mit 5V herausgeführt. Hier kommt auch das Frequenz-Signal rein.

Basierend auf diesen vorherigen Artikeln wird nun alles zusammengeführt.
– Frequenzzähler Teil 1 & Teil 2
– LCD Display Teil 1 & Teil 2
Arduino Uno als ISP
Ein Frequenzzähler für niedrige Frequenzen …





Die Materialiste.

1 x Lochrasterplatine ca. 4 x 6 cm
1 x 26-poliger IC Sockel
1 x 16 polige Sockelleiste die Aufnahme des LCD Displays
1 x LCD Display 1602 mit 4-Bit Ansteuerung
1 x 16-polige Stiftleiste für das LCD Display
1 x 16MHz Quarz
2 x 15pF Kondensatoren SMD
1 x 100 Ohm Widerstand
1 x 1k Ohm Widerstand
1 x 5k Ohm Drehwiderstand
1 x 10uF Tantal Kondensator
1 x 4-polige Schraubklemme
1 Rolle Fädeldraht lötbar (ich verwende 0,28mm Material lackiert)

Alles zusammen für ca. 10-15 Euro Materialwert.


Nun zur Aufbaubeschreibung.
1. Als erstes werden in die Ecklöcher der Lochraster Platine 3mm Schrauben eingesetzt mit Muttern.
Sie schauen unter raus und sind die Standfüße.
Damit liegt die Platine nicht wackelig auf dem Tisch und es kann kein Kurzschluß durch herumliegende Metallteile (Drähte) entstehen.
2. Das LCD Display bekommt eine 16-polige Stiftleiste
3. Die 16-polige Sockelleiste wird an den Rand der Platine gesetzt, sodaß das LCD Display später direkt über der Platine liegt.
4. Der 28-polige Sockel für den ATMEGA328P-PU wird aufgelötet.
5. Der 16MHz Quarz wird an die IC-Pins 9 und 10 gelötet. Zwei Kondensatoren mit 15pF werden von den Pins an Masse gelegt.



6. Zur Stabilisierung der Spannungsversorgung wird ein 10nF Tantal ELKO an die Pins 7 (+) und 8 (-) gelötet.
7. Der Kontrast-Regelwiderstand wird aus einem 1kOhm Widerstand und einem 4,7kOhm Trimm-Widerstand aufgebaut.
Eine kleine senkrechte Bauform ist später leichter von der Seite einzustellen, ich hatte aber nur einen liegenden Widerstand in der Kiste.
8. Es kann noch ein 6-poliger Programmier-Stecker aufgelötet werden.
Ich habe mich später aber entschieden den ATMEGA328 auf dem Steckbrett zu programmieren.
Daher ist er vorhanden, wird hier aber nicht verwendet.
9. Die 4-polige Schraubklemme wird an den Rand gesetzt.
Die Belegung von links nach recht:
– 1 frei, hier kann eine 9 oder 12v Stromversorgung angeschlossen werden.
Dazu ist aber noch ein 5V Regler auf dem Board notwendig. Platz ist noch vorhanden.
– 2 Versorgungsspannung + 5V
– 3 Masse Versorgungsspannung und Signal
– 4 Signaleingang zum Vorverstärker

10. Daneben sitzt der Eingangsverstärker Transistor. Die Widerstände und der Eingangskondensator sind unter der Platine in SMD Bauform verlötet.
Aufbau wie hier, nur habe ich einen 2,2uF Kondensator im Eingang verwendet. Der Ausgang geht auf PIN 11.
11. Der Kathoden Anschluß der LCD Beleuchtung (LCD -) bekommt noch einen 100 Ohm Widerstand gegen Masse.
12. Nun werden alle Anschlüsse nacheinander mit Fädeldraht verbunden und verlötet. Hierfür habe ich gut 1m verbraucht.
Erst die Display Verbindungen und dann die Stromversorgung

Hier die Display Verbindungen.
Von der LCD Sockelleiste geht es direkt zum entsprechenden 328 IC Pin.
Die Arduino Uno Bezeichnungen sind hier auch noch erwähnt weil das für die Entwicklung auf den Steckbrett wichtig war.

LCD > Arduino > 328 IC 28DIL Gehäuse
————-
VSS > GND > P8
VDD > +5V > P7
V0 > 5k Poti + 1kOhm Widerstand > GND
RS > Pin 12 > P18
R/W > Pin 13 > P19
E > Pin 11 > P17
D4 > Pin 7 > P13
D5 > Pin 8 > P14
D6 > Pin 9 > P15
D7 > Pin 10 > P16
A > +5V
K > 100 Ohm Widerstand > GND



Die Software

// Arduino 328 Frequenzzähler auf Platine // von 1 Hz bis ca. 5 MHz// > 900 Hz Eingangsspannung muss an Pin 5 mit ca. 5V Pegel ankommen.// < 1000 Hz Eingangsspannung muss an Pin 5 mit ca. 5V Pegel ankommen.// V 1.2: 1602 Display hinzugefügt// V 2.0: niedrige Frequenzen hinzugefügt// V 2.41: hohe Frequenzen umgeschieben und lcdOut() hinzugefügt// V 2.42: FreqCounter Library wieder genommen// V 2.43: auf Nano 328 angepasst// V 2.44: auf Platine 328 + NPN Emitter Schutzschaltung//// Stromaufnahme incl. Display Beleuchtung 28mA// Messbereich bis ca. 5 MHz, je nach Symmetrie des Signals (max. 8 MHz) // Messsignal Amplitude min. 100mV SS// Eingangsschaltung: 2uF + BE-Strecke ( NPN 0,7V )//// Matthias Busse 16.11.2014 Version 2.44// http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/#include < FreqCounter.h>#include LiquidCrystal lcd(12, 13, 11, 7, 8, 9, 10);/* LCD Display Anschlüsse:LCD > Arduino > 328 IC 28DIL Gehäuse-------------VSS > GND > P8VDD > +5V > P7V0  > 5k Poti + 1kOhm Widerstand > GNDRS  > Pin 12 > P18R/W > Pin 13 > P19E   > Pin 11 > P17D4  > Pin 7 > P13D5  > Pin 8 > P14D6  > Pin 9 > P15D7  > Pin 10 > P16A   > +5VK   > 100 Ohm Widerstand > GND Frequenz Messeingang > 2uF > BC547B NPN Emitterschaltung > P11, beim 328 28DIL Gehäuse Messbereich bis ca. 5 MHz Eingangsamplitude min. 100mV SS */unsigned long rfreq, mfreq;int mihz=0, hz=0, khz=0, mehz=0; // mHz, Hz, kHz und MHz je 3 Ziffernchar sfreq[15];                  // sfreq=Stringfrequenzstatic int schnell=0;            // > 1kHz = 1static int slgrenze=2000;        // schnell / langsam Grenzedouble sum=0, mfrequency, rfrequency;int count=0;// langsamint k=0,pin=5;unsigned long T;     // Periodendauer in usdouble fsum=0.0;     // Summierendouble f=0;          // Frequenz in MHz unsigned long time;  // Startzeitvoid setup() {  pinMode(pin, INPUT);//  Serial.begin(38400);               // Serielle Ausgabe  lcd.begin(20,4);  lcd.clear();  lcd.setCursor(0,0);  lcd.print("Frequenz Zaehler");  lcd.setCursor(0,1);         // Display ausgeben  lcd.print(" MBS  Ver. 2.44 ");  // 2 Sekunden wegzählen, da die ersten beiden Messungen eh murks sind.  FreqCounter::f_comp=120;   // Cal Wert  FreqCounter::start(1000);  // 1 s Gate Time  while (FreqCounter::f_ready == 0)   mfreq=FreqCounter::f_freq;  FreqCounter::f_comp=120;   // Cal Wert  FreqCounter::start(1000);  // 1 s Gate Time  while (FreqCounter::f_ready == 0)   mfreq=FreqCounter::f_freq;  schnell=0;  if(mfreq > slgrenze) schnell=1;}void loop() {  if(schnell==1) {    FreqCounter::f_comp=120;   // Cal Wert    FreqCounter::start(1000);  // 1 s Gate Time    while (FreqCounter::f_ready == 0)     mfreq=FreqCounter::f_freq;    lcdOut((double)mfreq);    if(mfreq < (slgrenze*0.97)) {                   // auf langsam umschalten      schnell=0;    }  } // if (schnell==1)  else { // langsam    time=micros();    do {      T = pulseIn(pin, HIGH) + pulseIn(pin, LOW);      if (T==0) {//        Serial.println("Timeout.");      }      else {        f=1/(double)T;        // f=1/T           k++;          }        fsum+=f*1e6;    } while( micros() < (time+1e6)); // 1 Sekunde mitteln    mfrequency = fsum/k*0.9925;    lcdOut(mfrequency);    fsum=0.0;    k=0;    if(mfrequency > (slgrenze*1.03)) {      schnell=1;     }  } // else langsam */} // loopvoid lcdOut(double f) {// Frequenz formatiert ausgeben// auf dem 16x2 LCD Display //// Matthias Busse Version 1.0int nachkomma=0;unsigned long rf;  rf=(unsigned long)f*1000;  if((f-(int)f) > 0.005) { // Nachkommastellen    rf=(unsigned long)(f*1000);    nachkomma=1;    mihz = rf-(int(rf/1000)*1000);    rf=(rf-mihz)/1000;    }  rf=(unsigned long)f;  hz = rf-(int(rf/1000)*1000);  rf=(rf-hz)/1000;  khz = rf-(int(rf/1000)*1000);  rf=(rf-khz)/1000;  mehz = rf-(int(rf/1000)*1000);  if(f >= 1000000.0) {sprintf(sfreq," %3d %03d %03d Hz",mehz,khz,hz);}  if((f > slgrenze)&& (f<1000000.0)) {sprintf(sfreq,"     %3d %03d Hz",khz,hz);}  else if((f >= 1000.0) && (f<1000000.0)) {sprintf(sfreq," %3d %03d,%03d Hz",khz,hz,mihz);}  if((f>=1.0) && (f < 1000.0)) {sprintf(sfreq,"     %3d,%03d Hz",hz,mihz);}  if(f < 1.0) {sprintf(sfreq,"       0,%03d Hz",hz,mihz);}  lcd.setCursor(1,1);         // Display ausgeben  lcd.print("                ");  lcd.setCursor(1,1);  lcd.print(sfreq); }


Die IC Programmierung.
Nach der Programmentwicklung auf dem Steckbrett wurde der ATMEA238P-PU Chip vom Uno aus programmiert wie in diesem Artikel beschrieben und dann auf die Platine gesteckt.

Der erste Test
Alle Verbindungen werden überprüft und durchgeklingelt. Nachbar Lötpads werden auf Isolation überprüft. Dann kann es los gehen.
5V werden angeschlossen. Die Schaltung läuft und die Stromaufnahme ist ca. 28mA, alles OK.


Mit einem Frequenzgenerator werden die Grenzen ermittelt.
Die Eingangsspannung sollte mindestens 100mV Spitze-Spitze betragen, dann werden Frequenzen bis zu ca. 5MHz gemessen, abhängig von der Symmetrie.
Theoretisch sind sogar 8MHz (halbe Taktfrequenz ) möglich.

Ein Nachtrag:
Der Frequenz Messfehler liegt bei ca. 60ppm also in der 4. oder 5. Stelle der angezeigten Frequenz bei den verwendeten Standard Bauteilen.
Für eine genauere Messung der Frequenz kann dieses Uhrzeit Modul mit eingebunden werden.
Dadurch kann der Fehler der Messung kleiner 3ppm werden und liegt damit an der 5. oder 6. Stelle der Frequenz.




Quelle.
http://shelvin.de/den-frequenzzaehler-mit-lcd-auf-platine-aufgebaut/
http://shelvin.de/frequenzzaehler-mit-display/








Arduino Uno als ISP



ATMEGA328P-PU Bootloader laden vom Arduino Uno als ISP

Der Arduino Bootloader soll in einen neuen ATMEGA 328P-PU IC auf dem Steckbrett geladen werden.
Dazu wird der Arduino Uno als ISP (In-System-Programmer) verwendet. Dazu sind 4 Schritte notwendig.

1. Den UNO zum ISP Programmer umfunktionieren
Als erstes wird der UNO mit der Programmer Software geladen.
Dazu darf das Steckbrett noch nicht angeschlossen sein.
In der Arduino IDE unter Datei > Beispiele > ArduinoISP wird das ISP Programm geladen.
Die Einstellungen sind Tools > Board > Arduino UNO und die richtige COMx Schnittstelle.
Dann einfach hoch laden.

2. Das Steckbrett vorbereiten
Als nächstes wird das Steckbrett mit dem ATMEGA328P-PU angeschlossen. ( Sollte direkt hinter der 328 das P fehlen, wird das so nicht funktionieren, dann hilft Google weiter.)

ATMEGA328 DIL 500

Die Pinbelegung

Dann wird der 16MHz Quarz auf das Steckbrett gesetzt zwischen Pin9 und Pin10.

Die beiden Kondensatoren mit 22nF fallen hier weg, sie wurden nicht benötigt.
Für die Entstörung der Stromversorgung wird noch ein 100nF Keramik Kondensator in die Stromversorgung gesetzt zwischen Pin 7 und Pin 8.

Es werden 6 Leitungen vom Uno zum Steckbrett gezogen.
UNO GND > Pin 8
UNO +5V > Pin 7
UNO 10 > Pin 1 Reset
Uno 11 > Pin 17 MOSI
Uno 12 > Pin 18 MISO
Uno 13 > Pin 19 SCK



Zusätzlich kann noch die LED13 mit Vorwiderstand auf das Steckbrett gesetzt werden mit dieser Verkabelung.
IC Pin 19 > Widerstand 330-1000 Ohm > Diode (langes Bein) / Diode (kurzes Bein) > GND
Damit kann später die Funktion prima überprüft werden.


Arduino Uno als ISP
3. Den Bootloader auf das Steckbrett laden

Dann wird das Board ausgewählt Tools > Board > Arduino Uno , der richtige Serielle Port eingestellt, unter Tools > Programmer > Arduino as ISP und mit Tools > Bootloader installieren der Bootloader auf das Steckbrett IC übertragen.
4. Das Programm auf das Steckbrett laden

Unter Tools > Programmer > ist Arduino as ISP weiterhin eingetragen.
Dann öffne ich das Blink Beispiel unter Datei > Beispiele > Basics > Blink und lade es hoch mit Datei > Upload mit Programmer.
Das ist ein wichtiger Unterschied zu der normalen Programmierung.
Wenn Sie das einmal vergessen und wie gewohnt den Upload Button aufrufen, geht es nochmal bei Schritt 1 los, denn dann ist das Programm im UNO gelandet.
Jetzt wird die Verbindung UNO 13 getrennt, denn hier werden beide LEDs UNO und Steckbrett parallel geschaltet.
Nun blinkt nur noch die LED auf dem Steckbrett. Damit ist das Programm Blink auf dem Steckbrett angekommen und wird richtig ausgeführt.
Jetzt wird nur noch die 5V Spannungsversorgung und GND für das Steckbrett benötigt, die anderen Leitungen können entfernt werden.


Minimalschaltung
Das bleibt als Minimal-Schaltung mit dem ATMEGA328P-PU übrig.

Quelle:
http://shelvin.de/atmega328p-pu-bootloader-laden-vom-arduino-uno-als-isp/






Frequenzen messen zu können ist immer mal hilfreich (Drehzahl von Motoren, PWM, Schwingkreise, usw.), wofür man jedoch einen dedizierten Frequenzzähler benötigt. Dennoch ist das Prinzip dahinter nicht kompliziert, somit ist eine Messung mit einem normalen Mikrocontroller auch ohne zusätzlichen Schaltungsaufwand möglich, in der einfachsten Version leider nur im Bereich von wenigen 100 kHz.

 

Allgemeine Grundlagen

Doch wie misst man eigentlich eine Frequenz?

Definitionsgemäß ist eine Frequenz in der Elekrotechnik die Anzahl von Schwingungen eines
periodischen Signals in einer bestimmten Zeiteinheit.
(Der Einfachheit halber wählt man meistens eine Sekunde)

Jetzt gibt es zwei Möglichkeiten diese Anzahl zu messen, entweder man macht es wie die Defintion besagt und zählt die Anzahl der Impulse pro Zeit, oder die Periodenlänge, also den zeitlichen Abstand zwischen zwei Impulsen.

Was ist nun besser? Nun, wenn man die Takte einfach nur zählt, hat man den Vorteil, dass das ziemlich einfach zu lösen ist, meist wird über einen Interrupt-Pin eine Countervariable hochgezählt und sekündlich deren Wert ausgegeben. Außerdem kann man mit dieser Methode relativ genau hohe Frequenzen messen, allgemein wird dieses Prinzip Frequenzzählung genannt.
Der Nachteil besteht allerdings darin, dass die Genauigkeit immer 1Hz beträgt. Das ist beispielsweise bei 100000 Hz eine ziemlich genaue Angabe, weil der Wert verhältnismäßig groß ist, im Gegensatz zu geringen Frequenzen wie 8 Hz, wo ±1Hz viel ausmachen.

Um diesen Nachteil der Ungenauigkeit bei niedrigen Schwingungszahlen zu umgehen, wird häufig die Frequenzmessung angewendet. Hierbei wird die Zeit zwischen zwei Takten gemessen und über den Kehrbruch die Frequenz ausgerechnet. Da die meisten Mikroprozessoren einen Timer im µ-Sekundenbereich laufen haben, ist es möglich, 25 Hz mit bis zu 3 Nachkommastellen (also 25.012 Hz) anzugeben, allgemein lohnt sich die Messung aber erst ab Frequenzen mit weniger als ca. 300 Hz.

Als Endergebnis kann man festhalten, dass beide Methoden ihre Defizite haben, kombiniert man diese jedoch, hat man die Vorteile beider!
Klingt nicht nur gut, funktioniert auch in der Praxis.

 

Kombination beider Methoden

Wenn man nun den Vorteil der Frequenzmessung bei niedrigen Frequenzen, sowie den Vorteil der Frequenzzählung bei hohen Frequenzen vereint, hat man ein sehr gutes Mittelmaß an Präzision und Bandbreite (also der Abstand zwischen minimal und maximal messbarer Frequenz) erreicht.

Doch wie wird das praktisch umgesetzt? Da es zwei verschiedene Messmethoden sind, kann man diese nicht wirklich “kombinieren”, wohl aber selektiv ausführen. Das bedeutet für eine Messung, dass zunächst eine Frequenzzählung gestartet wird. Sollte die gemessene Frequenz unter einem bestimmten Schwellenwert liegen, bei dem eine Frequenzmessung genauer wäre als eine Zählung (beispielsweise so um die 300Hz), wird noch mal die Frequenz gemessen, jetzt allerdings über die Messung statt Zählung.

Somit hat man eine automatische Fallunterscheidung, ein Ablaufschema könnte folgendermaßen aussehen:

Frequenzzählung    –>    wenn Zähler größer/gleich 300    –>    return Ergebnis (Zähler) [Bsp: 491 Hz]
wenn kleiner 300    –>    Frequenzmessung                          –>    return Ergebnis (Messung) [Bsp: 243.4 Hz]

 

Beispiel an einem Arduino

Damit ein Pin des AVR-Chips als High-Pegel registriert wird, muss eine Spannung von mehr als 0,7*VCC anliegen, bei einem Arduino mit 5V-Logik also entsprechend 3,5 V, bei einem Arduino mit 3,3 V dann ~2,3 V. Unterhalb dieser Schwelle wird logischerweise kein Impuls feststellbar sein. Die Pins selbst sind mit Schutzdioden versehen, fügt man vor diesen noch einen 100k-Widerstand (und am Besten noch eine Diode gegen VCC), kann man auch höhere Spannung als 3,3/5V messen.

In dieser Zeile wird ein Interrupt auf den Pin 2 festgelegt, dessen Methode ausgeführt wird,
wenn der Pin auf HIGH wechselt.

attachInterrupt(0, Messung, RISING);


Hier ist die Methode des Interrupts. Sobald eine Frequenz am Pin vorliegt, wird bei jedem Takt eine Zählervariable hochgezählt (Frequenzzählung), sowie der Zeitpunkt der Messung in µS gespeichert und vom alten Zeitpunkt abgezogen, was dann der Periodendauer entspricht.
Wie man sieht, werden beide Messvarianten gleichzeitig angewendet, wobei für das Endergebnis immer nur eine Methode benutzt wird.



void Messung()
{
zaehler++;
timer = micros() - timerOld;
timerOld = micros();
}


Im Hauptteil wird einmal pro Sekunde die ermittelte Frequenz über den seriellen Port ausgegeben. Der Grund warum ich kein “delay(1000)” eingefügt habe, sondern die Verzögerung über einen Timer realisiere, ist ganz einfach der, dass im loop-Teil zwischen den Messwert-Ausgaben weiterer Code ausgeführt werden kann, während delay den ganzen Programmfluss für eine bestimmte Zeit anhält.

In der Praxis funktioniert das folgendermaßen:
Nach dem letzten Ausführen der if-Bedingung wird der Wert des aktuellen Timers auf die Variable “startzeit” übertragen. Die if-Bedingung wird dann erst wieder TRUE, wenn die Differenz zwischen aktueller Laufzeit und der letzten Ausführung (“startzeit”) größer/gleich der Variable “messzeit” ist, in diesem Fall beträgt diese genau 1000000, was 1 Sekunde entspricht. (1s = 1*106 µs)

Um Übertragungsfehler am seriellen Port zu vermeiden, wird während der Übertragung der Interrupt deaktiviert (Zeile 7) und nach Beendigung wieder aktiviert. (Zeile 24)



void loop()
{
if ((micros() - startzeit) >= messzeit)
{
float f = timer; //Datentyp 'float', wegen untenstehender Division
f = 1000000/f; //Aus Periodendauer Frequenz berechnen
detachInterrupt(0);
if(f >= 300){
Serial.print("Zaehler: ");
Serial.println(zaehler);
}
else if(f < 300 && f >= 30){
Serial.print("Messung: ");
Serial.println(f, 1);
}
else if(f < 30 && f >= 3){
Serial.print("Messung: ");
Serial.println(f, 3);
}
else if(f < 3){
Serial.print("Messung: ");
Serial.println(f, 5);
}
attachInterrupt(0, Messung, RISING);
zaehler = 0; //Frequenzzähler zurücksetzen
startzeit = micros(); //Zeitpunkt der letzten Ausgabe speichern
}








Quelle:
http://www.breadboarding.de/frequenzmessung-arduino/












Attiny13 Frequenzmesser und Drehzahlmesser
Opto Reflexkoppler CNY70


Quelle:
http://www.elektronik-labor.de/Elo/Drehzahl.html









Ein ganz einfacher Stückzähler mit Arduino mit DF-Robot LCD:
  • zählt die negativen Flanken an INT0 (digital pin 2)
  • nicht entprellt, also nicht geeignet für mechanische Schalter
  • Hallsensor oder Lichtschranke ist kein Problem
  • Zählerüberlauf bei 65535
  • Reset durch resetten des Arduino
Die maximal mögliche Zählfrequenz dürfte so irgendwo bei 60kHz liegen.


Die LiquidCrystal-Library bedient alle LCD-Displays, die auf dem HD44780 basieren.
Der LiquidCrystal-Konstruktor definiert die Pins, an denen das LCD angeschlossen ist.
Und mit dem begin(Spalten, Zeilen) erklärt man der Library die Geometrie des LCD.
Unterstützt wird alles von 8 bis 80 Zeichen, also 8x1 bis 20x4 bzw. 40x2

#include <stdint.h>#include <LiquidCrystal.h>LiquidCrystal mylcd(8, 9, 4, 5, 6, 7);#define InPin 2#define LCDdimmer 10#define Brightness 200volatile uint16_t counter;char pbuf[20];void setup() {  pinMode(InPin, INPUT);  digitalWrite(InPin, HIGH);  pinMode(LCDdimmer, OUTPUT);  analogWrite(LCDdimmer, Brightness);  mylcd.begin(16, 2);  mylcd.print("Stueckzahl:");  attachInterrupt(0, count, FALLING );}void loop() {  uint16_t lastcount=0xffff;  uint8_t sreg;  if (counter != lastcount) {    sreg = SREG;    cli();    lastcount = counter;    SREG = sreg;    sprintf(pbuf, "%5u", lastcount);    mylcd.setCursor(11, 0);    mylcd.print(pbuf);    delay(100);  }  delay(100);}void count() {  counter++;}







Quelle:
https://forum.zerspanungsbude.net/viewtopic.php?t=2769














Beispiel-Software für reziproke Frequenzzähler etc.
Diverse Programmbeispiele mit reziprokem Meßverfahren


1. aktuelles Programmbeispiel für ATmega88 0,005Hz - 200 MHz
2. reziproker Frequenzzähler GPS-stabilisiert ATmega162
3. Drehzahlmessung
4. 4-Kanal Drehzahlmessung
5. altes Programmbeispiel für AT90S2313
6. Start-Stopp, Geschwindigkeit, Pulsweite
7. Frequenz-Periode-Drehzahl angepaßt für Arduino UNO R3
8. Frequenz-Spannungs-Wandler, ATmega48
9. Frequenz-Spannungs(PWM)-Wandler, ATtiny44
10. ATmega48 mit BASCOM-AVR 0,005Hz - 200 MHz
11. 5-stell. Zähler, 10mm 7-Segment multiplex, Einbaumodul, Batteriebetrieb

xx. weitere Frequenzzähler mit LED-Anzeige ff.
zurück zur Übersicht


3. Drehzahlmessung, ATmega328P erstellt mit AVR-Studio 4.18:


Anbei eine Schaltung und ein Programm für einen einfachen Drehzahlmesser sowie die .hex-Datei.




Die Schaltung ist einfach: sie besteht aus einem ATmega328P, einer LCD-Anzeige 2x16 und wenigen passiven Bauteilen.
Das Programm ist einfach: eine einzige .c-Datei wird mit den Grundeinstellungen des AVR-Studio übersetzt wird.

Gemessen wird im Grunde die Eingangsfrequenz; angezeigt werden Drehzahl ("D") und Zeit_pro_Umdrehung ("T") als 6-stellige Werte (gerundet). Die Berechnungen werden mit den 'float'-Routinen des AVR-GCC durchgeführt; das Programm benötigt ca. 5,4KB Programmspeicher. Gemessen wird lückenlos - jede Sekunde ein neuer Wert bei 60 rpm - und angezeigt werden drei Ergebnisse/s; eine LED signalisiert eine fertige Messung.

Zur Schaltung:
Der Prozessor ist mit der Anzeige wie gezeigt verdrahtet; die Pinbelegung ist 'historisch' gewachsen (beruht auf einem abgemagerten Frequenzzähler). Das Eingangssignal wird über den analogen Komparator dem ICP des Timer1 zugeführt. Das hat den Vorteil, dass die Eingangsbeschaltung variabel ausgelegt und bei Bedarf die Eingangsempfindlichkeit auf einige 10mV erhöht werden kann. So lassen sich z.B. R4 und C3 als Widerstände 2M2 bestücken und D1 gegen einen Kondensator 100nF austauschen, wenn sehr kleine Drehzahlen nicht erwartet werden.

2013-08-12:
Das Programm ist um die Funktion "automatischer Abgleich" erweitert worden. Mit Hife eines Referenzsignals von 1Hz - am besten von einem GPS-Empfänger - wird intern ein Korrekturwert errechnet und im EEPROM gespeichert. Bei anliegendem Referenzsignal werden rund 60Upm und 1s angezeigt. Schaltet man nun den Eingang PORTC.2 gegen GND werden nach der aktuellen Messung Soll- und Istwert miteinander verglichen. Da das Referenzsignal eine Messdauer von genau 1s vorgibt, muß die intern gemessene Zeit (bei typ. 20MHz F_CLOCK) genau 20000000 ergeben. Die Abweichung zu diesem Wert ist der Korrekturwert.
2013-09-16:
Der 'Fangbereich' für die Quarzfrequenz wird von +/-100ppm auf +/-1000ppm erhöht.

Möchte man den Abgleich mit einem anderen Referenzsignal durchführen, kann man dazu den Korrekturwert selbst errechnen und direkt im EEPROM an Adr. 2-3 (low-high) als 'int16_t' ablegen.


avr_drehzahl

/*
Beispielprogramm 'einfacher Drehzahlmesser' fuer ATmega88
entwickelt mit AVR-Studio 4.18
Funktionsbereich etwa 0,3 rpm - 15 Mrpm bei 20MHz Prozessortakt
entsprechend 0,005Hz - 250kHz Eingangsfrequenz

Schaltung dazu siehe: FMETER48 in abgespeckter Form
http://www.mino-elektronik.de

Alle Angaben ohne Gewaehr !
2011-09-07

2013-08-11: automatischer Abgleich mit 1Hz Referenzsignal
oder manueller Abgleich durch ext. Programmierung des EEPROM
an Adresse EE_ADR_OFFSET.
*/


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdlib.h>

#define BIT(x)  (1<<x)
#define F_CLOCK         20000000    // 20MHz ggf. an eff.Frequenz anpassen
#define EE_ADR_OFFSET   2   // Platz f�r Korrekturwert
#define KAL_TASTE       2   // PORTC-2

#define STELLEN     6       // angezeigte Stellen
#define MESSZEIT    100     // max. 3 Messungen/Sek. (100 x 3,3ms)
#define LED_EIN     30      // 0,1 Sek. (30 x 3,3ms)
#define LED_BIT     5       // PORTD.5

#define LCD_CMD     1       // wenn ein Befehl ausgegeben wird
#define LCD_STROBE  2       // Schreibimpuls E fuers LCD
#define ZEILE1  0x7f        // jeweils 1 addieren fuer 1. Spalte
#define ZEILE2  0xbf        // dto.

enum status {MESSEN=0, AUSLESEN, AUSWERTEN};    // die Phasen der Messung

char text1[]={"D:"};        // 1.Zeile der Anzeige
char text2[]={"T:"};        // 2.Zeile der Anzeige
char f_dim[][5]={"Mrpm","krpm","rpm ","mrpm","sek ","ms  ","us  "}; // Dimensionen zum Messwert

float frequenz;             // float-Ergebnis
float f_clock;              // korrigierter Referenzwert

// 'volatile' zur Sicherheit
volatile unsigned char messwert_vorhanden,  // nur gueltige Messungen anzeigen
        mess_status,        // Ablaufsteuerung
        led_cnt,            // LED kurz aufleuchten lassen
        sync_flag;          // wird mit T1OV gesetzt

volatile unsigned int zeit_low,     // Timer1-Anteil
        zeit_high,          // T1 Ueberlauf-Anteil
        mess_dauer,         // minimale Wartezeit
        ueberlauf;

volatile unsigned long start_ereignis,      // Impulse zu Beginn der Messung
        end_ereignis,       // Impulse am Ende der Messung
        start_zeit,         // rel. Zeit: Beginn der Messung
        end_zeit,           // Zeitpunkt der Auswertung
        mess_zeit,          // genaue Zeit der Messung
        mess_ereignisse;    // Impulse der Messung




// Routinen zur Ausgabe auf LCD 2x16

void warten(void)               // Warteschleife fuer LCD-Init
{
volatile char n = 50;
  while(n--) _delay_ms(1);
}

void lcd_impuls(void)           // Schreibimpuls mit Mindestlaenge
{
  PORTC |= LCD_STROBE;
  _delay_us(2);
  PORTC &= ~LCD_STROBE;
}

void lcd_nibble(char c)         // 4-bit-Wert ausgeben
{
char temp;
  temp = PORTB & 0xc3;          // Datenleitungen an PortB.2 -> PortB.5
  temp |= ((c>>2) & 0x3c);
  PORTB = temp;
  lcd_impuls();
}

void lcd_out(char z,char mode)  // Ausgabe von Daten (mode==1) oder CMDs (mode==0)
{
  if(mode) PORTC |= LCD_CMD;
  else PORTC &= ~LCD_CMD;
  lcd_nibble(z);
  z <<= 4;
  lcd_nibble(z);
  _delay_ms(1);                 // wir haben Zeit
}

void lcd_cmd(char z)            // einen LCD-Befehl ausgeben
{
  lcd_out(z,0);
}

void lcd_zeichen(char z)        // ein Zeichen ausgeben
{
  lcd_out(z,1);
}

void lcd_f_string(char *s)      // Zeichenkette auf LCD
{
signed char temp;
  while((temp=*s++) != 0) {
     lcd_zeichen(temp);
  }
}

void lcd_init_nibble(char c)    // 4-bit-Wert ausgeben LCD_INIT
{
  lcd_nibble(c);
  _delay_ms(10);                // genug Zeit lassen
}

void init_lcd(void)             // LCD initialisieren
{
  warten();
  lcd_init_nibble(0x30);
  lcd_init_nibble(0x30);
  lcd_init_nibble(0x30);
  lcd_init_nibble(0x20);
  lcd_cmd(0x28);                // im 4-bit mode
  lcd_cmd(0xc);
  lcd_cmd(1);
  warten();

  lcd_cmd(ZEILE1+1);            // 1.Zeile, 1.Spalte
  lcd_f_string(text1);
  lcd_cmd(ZEILE2+1);            // 2.Zeile, 1.Spalte
  lcd_f_string(text2);
}


// Routine zur Wandlung und Ausgabe eines Me�wertes

void zeige_x(float x,char zeige_periode)    // Anzeige von Frequenz oder Periode
{
signed char i,j,dez_punkt,dimension;

  dez_punkt = 0;
  if(x >= 0.001) {                          // 1mHz ist Untergrenze
    if(!zeige_periode) {                    // Frequenz
      x *= 60.0;                            // auf Drehzahl skalieren
      dimension=2;                          // und in Sekunden als Dimension
    } else {                                // Zeit fuer eine Umdrehung
      x = 1/x;                              // Kehrwert bilden
      dimension=4;                          // und in Sekunden als Dimension
    }
    while(x<1.0) {x*=1000.0;dimension++;}   // in den Hz-Bereich bringen
    while(x>=1000.0) {x*=0.001;dimension--;}
    while(x >= 10.0) {
      x *= 0.1;
      dez_punkt++;
    }
    x += 5e-6;                              // runden
    if(x >= 10.0) {                         // Ueberlauf bei Rundung
      x *= 0.1;
      dez_punkt++;
      if(dez_punkt > 2) {                   // Ueberlauf der Dimension
        dimension--;
        dez_punkt = 0;
      } 
    }
  } else {
    x = 0.0; dez_punkt=0; dimension=2;      // 0.00000 rpm ausgeben
  }
  for(i=0;i<STELLEN;i++) {
    j = x;
    lcd_zeichen(j+'0');
    if(i == dez_punkt) lcd_zeichen('.');
    x -= j;
    x *= 10;
  }
  lcd_zeichen(' ');
  lcd_f_string(f_dim[dimension]);
  lcd_zeichen(' ');
}

// Routinen zur Erfassung der Eingangsimpulse

ISR(TIMER1_OVF_vect)            // wird mit ca. 305Hz aufgerufen (20MHz/65536)
{
  ueberlauf++;                  // Ueberlaeufe von T1 ergeben obere 16bit der Messzeit
  sei();                        // gleich wieder freigeben
// ab hier unkritisches Timing
  mess_dauer++;                 // ungefaehre Dauer der Messung
  if(led_cnt) {
    led_cnt--;                  // LED Einschaltdauer abzaehlen
    PORTD |= 1<<LED_BIT;        // LED einschalten
  } else {
    PORTD &= ~(1<<LED_BIT);     // LED ausschalten
  }
}

ISR(TIMER1_CAPT_vect)           // Eingangsimpulse mit genauem Zeitpunkt erfassen
{
static unsigned long count;     // Impulse per Interrupt               
  count++;
  if(mess_status == AUSLESEN) { // Ergebnisse synchron zum Eingangsimpuls auslesen+ablegen
    end_ereignis = count;       // Anzahl der Impulse lesen
    zeit_low = ICR1;            // capture-reg lesen: untere 16bit
    zeit_high = ueberlauf;      // dazu die oberen 16bit
    if((TIFR1 & 1<<TOV1) && (zeit_low < 0x8000))    // evtl. Ueberlauf T1 noch offen?
      zeit_high++;              // nur, wenn capture-int + overflow-int gleichzeitig !
    mess_status = AUSWERTEN;    // Daten fertig fuer Auswertung
  }
}

uint8_t ee_read_byte(uint16_t adr)
{
  while(EECR & BIT(EEPE));      // abwarten
  EEAR = adr;
  EECR |= BIT(EERE);            // lesebit setzen
  return(EEDR);
}

void ee_write_byte(uint8_t data, uint16_t adr)
{
  if(data != ee_read_byte(adr)) {
    cli();
    EEAR = adr;
    EEDR = data;
    EECR  = BIT(EEMPE);         // master schreibbit setzen, EEPMx l�schen
    EECR |= BIT(EEPE);          // schreibbit setzen
    sei();
  }
}

void ee_write_word(int16_t data, uint16_t adr)
{
  ee_write_byte((uint16_t)(data)%256, adr);
  ee_write_byte((uint16_t)(data)/256, adr+1);
}

int16_t ee_read_word(uint16_t adr)
{
int16_t temp;
  temp = ee_read_byte(adr);
  temp += ee_read_byte(adr+1) * 256;
  return(temp);
}



/* Test auf gedr�ckte Taste an PortC.2 und externes Referenzsignal von 1Hz.
Wenn beides vorliegt, wird die Referenzfrequenz 'f_clock' um den
Korrekturwert 'f_offset' angepasst. 'f_offset' wird im EEPROM gespeichert
und nach einem Reset erneut geladen und mit F_CLOCK verrechnet.
*/

void teste_kalibrierung(void)
{
static uint8_t temp_alt;                            // zur Ermittelung der aktiven Flanke
uint8_t temp;                                      
int16_t f_offset;                                   // Abweichung zu F_CLOCK
  temp = (PINC ^ BIT(KAL_TASTE)) & BIT(KAL_TASTE);  // Zustand des Tasters lesen
  if((temp ^ temp_alt) & temp) {                    // Taste wurde gedr�ckt
    if(frequenz > 0.999 && frequenz < 1.001) {    // Frequenzbereich eingrenzen +/- 1000ppm
      f_offset = mess_zeit - F_CLOCK;               // Differenz ist-soll ermitteln
      f_clock = (float) (F_CLOCK + f_offset);       // korrigierter Takt
      lcd_cmd(ZEILE1+5);                            // 1.Zeile, 5.Spalte
      lcd_f_string("Kal. FERTIG");
      ee_write_word(f_offset, EE_ADR_OFFSET);       // Korrekturwert speichern
      messwert_vorhanden = 0;                       // n�chte Messung verwerfen
    }
  }
  temp_alt = temp;                                  // f�rs n�chste Mal merken
}

// Hauptprogramm
int main(void)
{
  CLKPR = 0x80; CLKPR = 0x0;        // CKDIV auf 0; voller CPU-Takt
  PORTB = 0x3;                      // Pullup ungenutzte Pins
  PORTC = 0x3c;                     // dto.
  PORTD = 0x1f;                     // dto.
  DDRB = 0x3c;                      // fuer LC-Anzeige Datenleitungen
  DDRC = 0x03;                      // fuer LCD CMD+Strobe
  DDRD = 0x20;                      // fuer LED
  init_lcd();

  messwert_vorhanden = 0;           // 1.Ergebnis unterdruecken, weil es falsch ist
  ACSR |= 1<<ACIC;                  // analog Komparator verwenden
  mess_status = MESSEN;             // zuerst messen
  TCCR1B = 0x01;                    // Timer1 ohne Vorteiler
  TIMSK1 = 1<<ICIE1 | 1<<TOIE1;     // t1-overflow und cap. interrupts
  f_clock = (float) (F_CLOCK + ee_read_word(EE_ADR_OFFSET));    // eff. Referenzfrequenz
  sei();

  for(;;) {
    TIMSK1 &= ~(1<<TOIE1);          // t1-overflow interrupt sperren
    if(mess_status==MESSEN  && mess_dauer >= MESSZEIT) {
      mess_status=AUSLESEN;         // Auswertung starten
      mess_dauer = 0;               // wieder Messzeit abwarten
    }
    TIMSK1 |= 1<<TOIE1;             // t1-overflow interrupt freigeben

    if(mess_status==AUSWERTEN) {
      end_zeit = zeit_high*0x10000 + zeit_low;
      mess_zeit = end_zeit - start_zeit;                // Zeit-Differenz bilden
      start_zeit = end_zeit;        // neue startzeit merken
      mess_ereignisse = end_ereignis - start_ereignis;  // Impuls-Differenz
      start_ereignis = end_ereignis;// fuers naechste Intervall
      mess_status = MESSEN;         // wieder warten
      if(messwert_vorhanden) {
        led_cnt = LED_EIN;          // LED-Zeit vorgeben
        frequenz = ((float)mess_ereignisse * f_clock) / mess_zeit;  // Frequenz berechnen
        lcd_cmd(ZEILE1+5);          // 1.Zeile, 5.Spalte
        zeige_x(frequenz,0);        // Drehzahl anzeigen
        lcd_cmd(ZEILE2+5);          // 2.Zeile, 5.Spalte
        zeige_x(frequenz,1);        // Drehzahl anzeigen
        teste_kalibrierung();       // nach g�ltiger Messung ggf. neu abgleichen
      }
      else messwert_vorhanden = 1;  // sperre wieder aufheben
    }
  }
  return(815);
}





Quelle:
http://mino-elektronik.de/fmeter/fm_software.htm














DIN A4  ausdrucken
********************************************************I*
Impressum: Fritz Prenninger, Haidestr. 11A, A-4600 Wels, Ober-Österreich, mailto:[email protected]
ENDE