Der Quark-Prozessor läuft auf dem RTOS ViperOS und unterstützt den Arduino-Prozessor bei der Erledigung der schwierigsten Aufgaben.
Das Modul besitzt 14 digitale Ein- und Ausgangskontakte, von denen 4 als PWM-Ausgänge genutzt werden können, 6 analoge Eingänge, einen USB-Anschluss für das Hochladen von Programmen
und serielle Kommunikation, einen Stromanschluss sowie eine ICSP-Einheit mit SPI-Signalen und Kontakten für I²C.
Die Spannungen zur Versorgung des Betriebs und der Ein- und Ausgabe des Moduls betragen 3,3 Volt, wobei alle Kontakte gegen eine Überspannung von 5 Volt geschützt sind.
Das Genuino 101 Entwicklungsboard wurde in Zusammenarbeit mit Intel entwickelt.
Ausführung
Bluetooth® LE
6-Achsen Accelerometer/Gyro.
2 Prozessorkerne mit 32 MHz
WENN Du den Abstand 330 mm machst, dann prescht ein schnelles Auto in 1/100 sek durch, ein Fußgänger in etwa 0,3 sek.
Beides ist für nen Mikrocontroller easy zu messen - mit ausreichender Genauigkeit.
ABER wenn das Auto in diesem Abschnitt etwas nickt (z.B. kleine Bodenwelle) dann kann der Lichtstrahl an den beiden Messpunkten an
ERHEBLICH unterschiedlichen Punkten des Autos abgeschattet werden => der Messwert ist recht ungenau.
Beim Fußgänger kann z.B. der Fuß (Schuh) gemessen werden - der bewegt sich abschnittweise
z.T. mit fast doppelter Geschwindigkeit des Menschen . . . .
Geschwindigkeit (m/h) = Balldurchmesser/Impulszeit x 3600 = 35mm / 6,3ms x 3600 = 20.000m/h = 20,0km/h
https://www.youtube.com/watch?v=m4gGomP5DC8
********************************************************I*
4) Geschwindigkeitsmessung mit Arduino über zwei Laserlichtschranken
z.B Paintball Geschwindigkeit oder Geschoss-Dm 5,5 bis 12mm
Benötigte Teile:
1 x Arduino UNO
1 x LCD-Modul 20x4
1 x I2C Interfacemodule für LCD
2 x Fotodiode BPW34
2 x Laser rot 650nm 4,5V / 5mWLichtleistung
2 x 100R..150R (als Vorwiderstand für Laser)
2 x 39k (als Messwiderstand für Fotodiode)
Laser Ub = 3,5V / 15mA = 52,5mW I = 5V - 3,5V / 100R = 15mA
Abstand der beiden Lichtschranken 91mm
650nm 5x6mm 4,5V 5mW rot Laserdiode Lasermodul Diode Module Laser Dot Laserdiodenmodul
https://www.amazon.de/650nm-Laserdiode-Lasermodul-Module-Laserdiodenmodul/dp/B00P7S708U/ref=sr_1_2?ie=UTF8&qid=1458478840&sr=8-2&keywords=5x+650
Fotodiode, Empfänger,
BPW34
https://www.amazon.de/Unbekannt-Fotodiode-Empf%25e4nger-BPW-34/dp/B016YH71WW/ref=sr_1_1?ie=UTF8&qid=1458478915&sr=8-1&keywords=fotodiode+bpw34
niceeshop(TM)
2004 LCD Modul für Arduino 20x4 / weiß auf Blauer Schirm Basierend auf Der Beliebten HD44780 Controller
https://www.amazon.de/niceeshop-Arduino-Basierend-Beliebten-Controller/dp/B00MODAKM4/ref=sr_1_1?ie=UTF8&qid=1458479137&sr=8-1&keywords=2004+LCD+Modul
IIC/I2C/TWI/SPI Serial Interface Board Module für Arduino 1602LCD
https://www.amazon.de/Serial-Interface-Module-Arduino-1602LCD/dp/B00LVQ7MH6/ref=sr_1_4?ie=UTF8&qid=1458479205&sr=8-4&keywords=IIC%2FI2C
Details siehe
Quelle:
http://sites.schaltungen.at/sie-fahren-km-h/weidmann
Quelle:
https://www.youtube.com/watch?v=iMvzBdijVwU
5) Drehzahlmessung und Geschwindigkeit gemessen mit einem ARDUINO
Im Versuch simuliere ich die Drehzahl eines Fahrrades und die eines Sportwagens und berechne aus der Drehzahl und dem Reifenumfang die Geschwindigkeit in km/h.
Die Messwerte werden auf einer LCD-Anzeige ausgegeben und das Ausgangssignal des
Details siehe
Quelle:
http://sites.schaltungen.at/sie-fahren-km-h/weidmann
Quelle:
https://www.youtube.com/watch?v=oT7__vTji7o
6) Geschwindigkeismessung mit zwei Lichtschranken
Bauteile
1x ARDUINO UNO
2x IR-LED
2x IR-Fotodiode
2x 220R Widerstand
2x 100k
8x Steckkabel 0,64mm rot blau gelb grün
Quelle:
https://schuelerlabor.informatik.rwth-aachen.de/sites/default/files/dokumente/Station 3 - Geschwindigkeitsmessung.pdf
7) Micros - Zeiterfassung / Geschwindigkeitsmessung mit zwei Lichtschranken
Ich habe mir eine kleine Funktion zur Geschwindigkeitsmessung von Autos mittels zweier Lichtschranken zusammengebastelt, den Sketch habe ich dazu unten angehängt.
Jetzt habe ich das ganze mal mit einem fahrenden Auto ausprobiert und stieß dabei auf ein Problem.
Die Funktion micros() wirft bei mir bis zu einer ganzen Stelle unterschiedliche Werte aus,
z.B. 400345 und 40034. Woran liegt das?
Für die Geschwindigkeitsberechnung war ich eigentlich der Meinung mit 10^-6 umzurechnen, aber nur mit 10^-5 komm ich annähernd auf den genauen Wert!?
Ich weiß, dass es mit dem Arduino möglich ist auf 4 us bzw. auf 0.5 us genau die Zeit zu erfassen, bin mir aktuell nur nicht sicher ob ich irgendwo noch ein Denkfehler drinnen habe!?!
Ist für micros() die Schnelligkeit wichtig - Serial.begin(19200); ?
Verwendet wir ein Arduino Mega 2560 der neuesten Generation.
// Variablendeklaration
byte li_start = 2; // Pin Lichtschranke Start
byte li_ende = 3; // Pin Lichtschranke Ende
unsigned long start = 0;
unsigned long ende = 0;
unsigned int zeit_signaldauer = 0;
boolean zeitmessung_aktiv = false;
float result;
int ergebnis;
String myString;
double v = 0; // unsigned long
void setup() {
Serial.begin(19200);
pinMode(2, INPUT); // Lichtschranke Beginn
pinMode(3, INPUT); // Lichtschranke Ende
attachInterrupt(0, startabfrage, FALLING);
attachInterrupt(1, zeitmessung, FALLING);
}
void loop(){
v = (2.0 / (zeit_signaldauer * pow(10, -5) ) ); // Durchschnittsgeschwindigkeit
result = v + 0.5;
ergebnis = (int)result;
Serial.print("Startzeit: ");
Serial.println(start);
Serial.print("Zeitdifferenz: ");
Serial.println(zeit_signaldauer);
Serial.print("Geschwindigkeit: ");
Serial.println(v);
Serial.println(result);
Serial.println(ergebnis);
Serial.print("\n");
delay(0);
}
void startabfrage(){
if(digitalRead(li_start) == LOW && zeitmessung_aktiv == false){
start = micros(); // Aktueller Zeitwert
zeitmessung_aktiv = true;
}
}
void zeitmessung(){
if(digitalRead(li_ende) == LOW && zeitmessung_aktiv == true){
//ende = micros(); // Aktueller Zeitwert
zeit_signaldauer = micros() - start ; // Berechnung Zeitdifferenz
zeitmessung_aktiv = false;
}
}
Wenn ich das richtig sehe dann gibst du die Werte immer aus...
Vielleicht nur dann ausgeben wenn eine Messung wirklich erfolgt ist was du durch ein weiteres Flag regeln kannst.
Start und Ende hast du richtigerweise als unsigned long definiert.
Die Differenz aus beiden (zeit_signaldauer) sollte dann auch unsigned long und nicht int sein.
Sonst gibt es nach 65536 µs u.U. einen Überlauf der int Variablen bei der Differenzbildung.
Hat hierzu noch jemand eine Ahnung:
Für die Geschwindigkeitsberechnung war ich eigentlich der Meinung mit 10^-6 umzurechnen, aber nur mit 10^-5 komm ich annähernd auf den genauen Wert!?
Ist für micros() die Schnelligkeit wichtig - Serial.begin(19200); ?
********************************************************I*
8) Geschwindigkeit messen mit Arduino
Was man immer schon wissen wollte..
Wie schnell sind die kleinen Rennautos.
Mit einem Arduino und wenigen Bauteilen kann man die Geschwindigkeit messen.
Die Bauteile sind praktisch in der Bastelkiste oder im Starter-Kit und kosten wenig, allerdings muss man etwas sägen und hämmern um es zu bauen.
Man braucht einen Laserpointer und eine Fotodiode wie etwa BPW34 (LDR geht sicher auch), dann ein paar Oberflächenspiegel, die sind aus einer alten Harddisk ausgebaut und sehen so aus wie eine glänzende CD.
Mit der Blechschere werden daraus zwei Segmente geschnitten, das sind die Spiegel zum Umlenken des Laserstrahls. Zwei Bretter braucht man auch noch um das zu befestigen.
Download: Speedy.zip
/*
Arduino Speedy
measure time and calculate speed
uses a laserpointer, 2 mirrors and a photodiode for light barrier
photodiode signal goes to Input Capture Pin on PB0, Arduino pin8
measures time from falling edge to next falling edge = total time
first measures time from falling edge to next rising edge = time1 (low time)
useful to abt 50 us, minimum low time is 4 us
serial output and LCD defined/not used
GS 3-2014
This is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*/
//include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
/*
* LCD RS pin to digital pin 7
* LCD Enable pin to digital pin 6
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
*/
#ifndef F_CPU
#define F_CPU 16000000L
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
int pinLed=13; // on board Led
int pinStart=9; // HIGH to measure, LOW to adjust
int pinTrig=8; // ICP pin input
volatile unsigned char p_mlt = 0; // Timer1 Overflows total
volatile unsigned char p_mlt1 = 0; // Timer1 Overflows low time
volatile unsigned char p_ready; // Flag
volatile unsigned int StartTime = 0; // ICP pin 1st edge falling
volatile unsigned int EndTime1 = 0; // ICP pin next edge rising
volatile unsigned int EndTime2 = 0; // ICP pin last edge falling
ISR( TIMER1_CAPT_vect )
{
static unsigned char edge = 0;
if( p_ready ) return; // wait until display done
if( edge == 0 ) // 1st edge falling
{
StartTime = ICR1;
TIMSK1 = 0; // stop Interrupts , Capture & Overflow
p_mlt = 0;
p_mlt1 = 0;
TCCR1B |= (1<<ICES1); // then change to rising
++edge; //
TIMSK1 = (1<<ICIE1) | (1<<TOIE1); // enable Interrupts , Capture & Overflow
}
else if( edge == 1 ) // 2nd edge rising
{
EndTime1 = ICR1; // time high
TIMSK1 = 0; // stop Interrupts , Capture & Overflow
p_mlt1 = p_mlt;
TCCR1B &= ~(1<<ICES1); // then change ICES1 to falling
++edge; //
TIMSK1 = (1<<ICIE1) | (1<<TOIE1); // enable Interrupts , Capture & Overflow
}
else if( edge == 2 ) // 3rd edge falling
{
EndTime2 = ICR1; // total time
p_ready = TRUE; // p_ready to display
edge = 0;
}
}
ISR( TIMER1_OVF_vect ) // count overflow
{
p_mlt++;
}
void setup() {
pinMode(pinLed, OUTPUT); // on board led
pinMode(pinStart, INPUT_PULLUP); // start Input Capture, pin9
pinMode(pinTrig, INPUT); // Input Capture Pin on PB0, pin8
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.print("Speed Counter");
Serial.begin(9600); // prepare for serial out
Serial.println("Pulsewidth to Speed");
TCCR1A = 0; //
TIMSK1 = (1<<ICIE1) | (1<<TOIE1); // 2 Interrupts: Capture & Overflow
TCCR1B &= ~(1<<ICES1); // ICES1 trigger on falling
TIMSK2 &= ~(1<<OCIE2A); // disable Timer2 Interrupt, millis
sei();
}
void loop()
{
char FString[12];
double myTime = 0.0;
double pwpercent = 0.0;
unsigned long pwidth;
unsigned long pwidth1;
if (digitalRead(pinStart) == HIGH) // start ISR else adjust
{
if( p_ready )
{
TCCR1B = 0; // stop Input Capture
pwidth1 = (p_mlt1 * 65536) + EndTime1 - StartTime;
Serial.print("PW low= ");
Serial.print(pwidth1); //PW1 in counts
pwidth = (p_mlt * 65536) + EndTime2 - StartTime;
Serial.print(" PWtotal= ");
Serial.print(pwidth); //PW total in counts
Serial.print(" PW % = ");
pwpercent = pwidth1*100.0/pwidth;
dtostrf( pwpercent, 5, 2, FString ); // 2 digits
Serial.println(FString); //PW in counts
myTime = pwidth/16.0 ; // in usec
dtostrf( myTime, 8, 2, FString ); // 2 digits
Serial.print("Time= ");
Serial.print(FString);
Serial.print(" usec ");
lcd.print(FString);
myTime = (p_mlt * 65536) + EndTime2 - StartTime;
myTime = (F_CPU *25.0)/ myTime; // 25cm / t
dtostrf( myTime, 8, 3, FString ); // 3 digits
Serial.print("Speed= ");
Serial.print(FString);
Serial.println(" cm/sec");
lcd.print(FString);
//
p_ready = FALSE;
digitalWrite(pinLed,!digitalRead(pinLed)); // blink Led 13 on board
TCCR1B = (1<<ICES1) | (1<<CS10); // enable Input Capture Edge, PreScale 1
TCCR1B &= ~(1<<ICES1); // ICES1 trigger on falling
} //if( p_ready )
}
else // stop to adjust
{
TCCR1B = 0;
digitalWrite(pinLed,digitalRead(pinTrig)); // Led 13 on board shows status
}
// delay(50);
}
Quelle:
http://www.elektronik-labor.de/Arduino/Speed.html
********************************************************I*
9) Tropfenzähler mit Gabellichtschranke
Der Tropfenzähler soll als einzelner Baustein aber auch als Teil des Fraktionssammlerprojektes verwendbar sein.
In Erweiterung seiner Verwendbarkeit soll er auch als Blasenwächter für Glas- oder Silikonschläuche verwendbar sein.
Lichtschranken können fallende Tropfen erkennen. Gabellichtschranken helfen Fehljustierungen zu vermeiden.
Ein Wassertropfen besitzt ein Volumen von etwa 50 µl und damit einen entsprechenden Durchmesser von mehreren Millimetern.
Elektronische Bauteile wie die Lichtquelle und der Lichtsensor der Lichtschranke sind unbedingt vor Feuchtigkeit zu schützen.
Dieser Schutz kostet Spaltbreite / Raum.
Die Gabellichtschranke GP1A57HRJ00F besitzt eine Öffnungsweite von 10 mm.
Schaltplan des Breakoutboards:
https://www.sparkfun.com/datasheets/Sensors/Infrared/PhotoInterrupter-Breakout-v20.pdf
Datenblatt:
https://www.sparkfun.com/datasheets/Components/GP1A57HRJ00F.pdf
Auf der linken Seite des Bauteils ist die IR-LED untergebracht.
Die größere Länge des hinteren Beinchens wie auch die Prägung auf dem Bauteil
(obere Ansicht hier nicht gezeigt) gibt, weist daraus hin, dass es sich um die Kathode handelt.
Im Datenblatt mit Pin (2) bezeichnet. Das kürzere, vordere, rechte Beinchen ist somit die Anode.
Um die IR-LED ohne Schaden am Arduino UNO betreiben zu können, bedarf es eines 220 oder 330 Ohm Vorwiderstandes,
der am besten zwischen die Kathode (rechtes, hinteres Beinchen im Bild) und Masse (GND) geschaltet wird.Über die genaue Verwendung informiert dieser Forenbeitrag
http://forum.arduino.cc/index.php?topic=102418.0
oder der Schaltplan des Breakoutboards von Sparkfun.
https://cdn.sparkfun.com/datasheets/Sensors/Infrared/PhotoInterrupter-Breakout-2.2.pdf
Aus dem Schaltplan des Breakout-Boards geht auch nochmals die genaue Beschaltung hervor.
Auf der linken Seite der obigen Darstellung befindet sich demnach vorne der Massenanschluss (-) (Englisch Ground = GND).
Etwas zur Mitte versetzt befindet sich der im Datenblatt mit Vo bezeichnete Signalausgang und ganz hinten die Spannungsversorgung (+).
Ein Aufbau unmittelbar auf einem Breadboard funktioniert nicht. Die Beinchen sind zu dünn und falsch positioniert.
Für einen fliegenden Aufbau bleibt also nur ein Aufbau mit Lötkolben und Schrumpfschlauch an eine Steckerleiste, die entsprechend in des Steckbrett eingefügt werden kann.
Später wird der Aufbau mit einem Schrumpfschlauch mit größerem Durchmesser und weiblich-männlichen Patchkabeln im Einsatz getestet.
Zunächst aber die Funktionsprüfung mithilfe eines Sketches.
Der Signalausgang der Lichtschranke wird mit digitalPin2 verbunden (Dieser Eingang ist interrupttauglich, was später verwendet werden soll).
Dem Standard folgend verwenden wir zur Verbindung der Anode an Vcc ein rotes Jumperkabel und zur Verbindung mit GND ein schwarzes Jumperkabel.
Die eingebaute LED am Digitaleingangspin 13 soll bei Aufleuchten, wenn sich ein Hindernis im Spalt der Lichtschranke befindet.
// Testprogramm Gabellichtschranke
int Led13 = 13;
int signalSchranke = 2;
int val;
void Setup () { // Pins und Co initialisieren
pinMode Led13, OUTPUT); // Digitalpin 13 als Ausgang schalten
pinMode (signalSchranke, INPUT); // Digitalpin 2 als Eingang schalten
}
void Loop () {
val = digitalRead(signalSchranke);
if (val == HIGH) {
digitalWrite (Led13, HIGH);
}
else {
digitalWrite (Led13, LOW);
}
}
Für erste Gehversuche eignet sich auch das Breakoutmodul KY-010.
https://tkkrlab.nl/wiki/Arduino_KY-010_Optical_broken_module
Nach einer leichten Modifikation des Sketches (Zum Beispiel dem Einfügen einer Zeile „delay(500);“ nach dem „digitalWrite(Led13, HIGH);“
und vor allem vor das anschließende „}“) und dem Test der Lichtschranke mit einem dünnen Drahtstück, das schnell hindurchgezogen wird, stellen sich erste Irritationen ein.
Offensichtlich führt nicht jeder Durchgang eines Gegenstandes durch die Lichtschranke zu einer Auslösung des Signals.
Das Problem tritt noch deutlicher auf, wenn das Programm umfangreicher wird und eine Kommunikation auf den „Serial Monitor“ erfolgt.
Während der Arduino gerade mit anderen Dingen beschäftigt ist, mangelt es an Aufmerksamkeit für den Sensor.
Erik Bartmann hat dieses Problem in dem frei verfügbaren Ergänzungstext zur ersten Auflage seines Buches
„Die elektronische Welt mit dem Arduino entdecken“ ganz wunderbar beschrieben.
http://erik-bartmann.de/component/attachments/download/79.html
Die 2. Auflage des Buches deckt diesen Bereich zwar ab, ist aber nicht so prägnant.
Mit der entsprechenden Modifikation des Sketches funktioniert der Sensor jetzt in der beabsichtigten Weise.
Das Echtzeitmodul des Tropfenzählers ersetzen zunächst die Funktionen millis().
Diese Funktion gibt die Zeit seit dem Start des Programms an und kann damit ein Zeitintervall von fast 50 Tagen messen, bevor der Wert der Funktion überläuft und damit wieder bei Null beginnt.
Es soll zum Beispiel die Tropfgeschwindigkeit in Anzahl Tropfen pro Minute angegeben werden.
Die Variable vorwert soll den Zeitstempel des letzten Ereignisses beinhalten.
Sie wird vor der Setup-Funktion mit:
unsigned long vorwert;
eingeführt.
Die Tropfgeschwindigkeit kann durch Bestimmung der Differenz tropfzutropfzeit zwischen der istzeit und dem vorwert in der Einheit Millisekunden berechnet werden.
Damit diese Routine nur aufgerufen wird, wenn ein Tropfen gefallen ist, wird eine boolsche Variable „getropft“ eingeführt, die die Interruptroutine auf „TRUE“ setzt.
if (getropft== TRUE)
{
istzeit = millis();
tropfzutropfzeit = istzeit – vorwert;
vorwert = istzeit;
tropfgeschwindigkeit = tropfzutropfzeit / 60000;
getropft = FALSE;
}
Es sollte noch berücksichtigt werden, dass eine Tropfgeschwindigkeit erst bestimmt werden kann, wenn wenigstens der zweite Tropfen gefallen ist.
Die Geschwindigkeitsanzeige kann so angepasst werden, dass immer der gleitende Mittelwert
von einer zuvor festgelegten Anzahl von Ereignissen (zum Beispiel 3) ein Wert auf dem „Serial Monitor“ ausgegeben wird.
Quelle:
http://technik-garage.de/tropfenzaehler/
10) Tropfenzähler mit Gabellichtschranke
SHARP GP1A57HRJ00F
Aufgabe dieses ersten Teils ist zunächst die sichere Erfassung fallender Tropfen.
Zusätzlich soll anhand des Zeitabstandes zwischen zwei nacheinander fallenden Tropfen die Tropfgeschwindigkeit pro Minute geschätzt werden.
// dropcounter
/***************************************************/
int photoInterrupterPin = 2; // Signal der Gabellichtschranke, Pegel bei Unterbrechung des Lichtweges "low" sonst "high"
int interruptNumber = 0; // Pin 2 des Arduino Uno / Mega ist mit Interruptnummer 0 verbunden
int dropsPM = 0; // Ergebnisangabe in Tropfen pro Minute
volatile int dropNumber = 0; // Variable zum Speichern der Tropfenzahl. "volatile" gewährleistet saubere Übergabe
int tempDropNumber = 0; // dient zur Zwischenspeicherung der Tropfenzahl
volatile unsigned long deltaTime = 0; // Zeitabstand zwischen 2 aufeinanderfolgenden Unterbrechungen
volatile unsigned long lastInterruptTime = 0; // Zwischenspeicherung des letzten Aufrufzeitpunktes
/***************************************************/
void setup() // Initialisierung der Pins, Einhängen und Typisieren des Interrupts
{
pinMode(photoInterrupterPin, INPUT); // Pin 2 als Eingang definieren
attachInterrupt(interruptNumber, interruptroutine, FALLING); // Immer wenn an Pin 2 der Pegel fällt, löst das Interrupt 0 aus
// und die Funktion "interruptroutine" wird aufgerufen
Serial.begin(38400); // Kommunikation mit Baudrate von 38400 initialisieren
// langsamere Geschwindigkeiten führen zu Datenverlusten
}
/***************************************************/
void loop() // Hauptprogrammschleife
{
if ((dropNumber > tempDropNumber) and (dropNumber > 1)) // Hat sich die Tropfenzahl erhöht?
{ // Zeit zwischen 2 Tropfen nur bei mehr als 1 Tropfen sinnvoll
dropsPM = 60000 / deltaTime; // 60000 ms = 1 Minute / Zeitdifferenz zwischen 2 Tropfen
deltaTime = 0; // Zeitdifferenz wieder auf Null setzen
tempDropNumber = dropNumber; // Aktuelle Tropfenzahl zwischenspeichern
Serial.println(dropNumber);
Serial.print("Tropfen pro Minute: ");
Serial.println(dropsPM);
}
delay(5); // 5 ms warten. Das entspricht ebenfalls der Wartezeit der
// Interruptroutine. Es geht also keine Zeit verloren.
}
/******************************************************/
void interruptroutine() // Wird aufgerufen, immer wenn der Pegel an Pin 2 abfällt.
{
unsigned long interruptTime = millis(); // Zeitpunkt zu dem der Interrupt aufgerufen wird
deltaTime = interruptTime - lastInterruptTime; // Da erst ab dem 2. Tropfen gezählt werden soll, gibt es
// einen vorangegangenen Zeitpunkt eines Interuoptaufrufs
if (deltaTime > 5) // Zeit zwischen 2 aufeinander folgenden Dropfen muss 5 ms
{ // überschreiten (verhindert Nebenefekte der Hardware)
dropNumber++; // Tropfenzahl wird um "1" erhöht wenn der Abstand zwischen
} // 2 Ereignissen länger als 5 ms war.
else // sonst
{ // war 's wohl ein Fehler und
deltaTime = 0; // der Zeitabstand wird auf "0" zurückgesetzt
}
lastInterruptTime = interruptTime; // Zeitpunkt des aktuellen Pegelwechsels wird zwischengespeichert.
}
Quelle:
http://technik-garage.de/tropfenzaehler-teil-1/
// Testprogramm Gabellichtschranke
int Led13 = 13;
int signalSchranke = 2;
int val;
void Setup () { // Pins und Co initialisieren
pinMode Led13, OUTPUT); // Digitalpin 13 als Ausgang schalten
pinMode (signalSchranke, INPUT); // Digitalpin 2 als Eingang schalten
}
void Loop () {
val = digitalRead(signalSchranke);
if (val == HIGH)
{
digitalWrite (Led13, HIGH);
}
else
{
digitalWrite (Led13, LOW);
}
}
Quellen, die mich zu dieser Art des Codes bewegt haben:
„
Using a KY040 Rotary Encoder with Arduino“ von Big Dan The Blogging Man
„
Interrupts“ von Nick Gammon
„
Arduino Interruptsteuerung (Teil 1)“ von Erik Bartmann
303_c_Bartmann-x_#002 ARDUINO Intrrupt-Handling Teil 1_1a.pdf
Die sichere Erfassung zeitkritischer Vorgänge erfordert den Einsatz von Interrupts.
Der Arduino UNO verfügt über 2 Pins / digitale Eingänge zur Erfassung externer Interrupts.
Es sind dies die Pins 2 und 3. Hier wird Pin 2 als Eingang verwendet. Der Signalausgang der Gabellichtschranke funktioniert als
Schmitt-Trigger.
Die Signaländerungen verlaufen also sehr steil und schnell, so dass es kaum zu einer „Fehlinterpretation“ in Bezug auf eine Unterbrechung des Lichtweges kommen kann.
Wird der Lichtweg unterbrochen fällt die Spannung am Signalausgang auf nahezu 0 V. Die Interruptroutine muss also stets bei fallendem Pegel („falling“)aufgerufen werden.
Wird sie bei sich ändernden Peglen („change“) aufgerufen, ergeben sich pro Tropfenfall 2 Signale.
Das erste entsteht zu Beginn der Unterbrechung des Lichtweges und das zweite beim Verlassen des Lichtweges durch den fallenden Tropfen.
Die Sprache des Arduino sieht die Funktion „millis()“ zur Bestimmung der Zeit vom Einschalten des Prozessors vor.
Wie der Name nahe legt erfolgt die Angabe in Millisekunden. Damit lässt sich ein Zeitraum von bis zu 50 Tagen erfassen, da die Funktion den Datentyp „Long“ als Ergebnis liefert.
Eine genauere Erfassung in z.B. Mikrosekunden wäre zwar möglich, ist auf Grund der Größe der Tropfen und der maximal möglichen Fallgeschwindigkeit nicht nötig.
Die Ermittlung einer Zeitdifferenz erfordert die Bestimmung von mindestens 2 Zeitpunkten.
Die Bestimmung der Tropfgeschwindigkeit kann also erst vom zweiten Tropfendurchgang an erfolgen, weshalb „dropNumber > 1“ eine notwendige Bedingung ist,
die abgefragt wird sobald die Tropfenzahl „dropNumber“ größer als die vorangegangene temporär gespeicherte Tropfenzahl „tmpDropNumber“ ist.
Die temporäre Variable wird mit „0“ initialisiert. Somit wäre „dropNumber > temDropNumer“ schon für den ersten fallen Tropfen erfüllt.
Eine alternative – aber weniger transparente – Lösung wäre die Initialisierung von tempDropNumber mit „1“.
Die Kommunikation des Arduino über die serielle Schnittstelle mit dem PC (Serial Monitor) kostet Zeit.
Experimentell stellte sich heraus, dass erst ab einer Baudrate von mehr als 38400 eine zuverlässige Tropfenerkennung möglich ist.
Einer weiteren Erhöhung der Baudrate steht allerdings nichts im Wege.
Das eingefügte „delay(5)“ bgrenzt den unnötigen Energieverbrauch der Prozessors und damit Erwärmung.
Die verwendeten 5 ms entsprechen der Zeit die ohnehin in der Interruptroutine gewartet wird.
Der gewählte Zeitrahmen stammt auf dem Encoder-Beispiel und funktionierte auch hier.
Klare Plastikfolie oder Polycarbonat stören den Strahlengang nicht.
Durch einen Ring aus Polycarbonat kann eine Kontamination der IR-LED oder des Sensors vermieden werden.
Die Folgeversion der Software soll zusätzlich eine Funktion zur Näherung der Tropfgeschwindigkeit aus der Mittelung mehrerer Tropfzeitdifferenzen enthalten.
Ein Ausgangssignal auf einen Digitalausgang soll zudem den sicheren und frei definierbaren Zeitrahmen für die Bewegung des Tropfenzählers zum nächsten Gefäß signalisieren
Quelle:
http://technik-garage.de/tropfenzaehler/
11) Tropfenzählerprobleme und Lösungen
Ziel:
Es gibt einen Strauß von Sensoren, die ausgelesen und dessen Daten ausgewertet werden wollen.
Natürlich sollen die Daten in regelmäßigen Intervallen gelesen, übermittelt und/oder gespeichert werden.
Regelmäßige Intervalle?
Gleichmäßige Pausen?
Klarer Fall, einfache Lösung „Delay“! Könnte man denken und versuchen.
Irgendwie funktioniert während der Delay-Zeit aber nicht alles wie geplant.
Das Problem und seine Ursache findet sich in der Hilfe der Arduino-IDE (bzw. auf der Arduino-Webseite).
Zitat:
Der Trick besteht in der Verwendung der millis().
Die Funktion millis() zählt die Zeit seit dem Einschalten des Arduino in Millisekunden.
Damit eine Aktion in gleichmäßigen Abständen stattfindet, benötigt man die aktuelle Zeit, die vorgesehene Zeitdifferenz und die Zeit des letzten Auftretens der Aktion.
Dafür sind entsprechend geeignete Variablen zu definieren.
unsigned long jetzt = 0;
unsigned long vorhin = 0;
long intervall = 60000;
Während des Programmablaufs wird stetig überprüft, ob der Unterschied zwischen der „jetzt“-Zeit und der „vorhin“-Zeit das vorgesehene Intervall übersteigt.
Ist das der Fall verzweigt das Programm zur geplanten Aktion.
Da hier eine der geplanten Aktionen ablaufen soll, ist es an der Zeit, den Zeitpunkt in der Variablen „vorhin“ festzuhalten.
Dem schließt sich die geplante Aktion an.
int photoPin = 2;
int interruptNumber = 0;
unsigned long vordropcount = 0;
volatile unsigned long dropCount = 0;
unsigned long jetzt = 0;
unsigned long vorhin = 0;
volatile boolean geaendert = false;
long intervall = 60000;
void setup() {
// put your setup code here, to run once:
pinMode(photoPin, INPUT);
attachInterrupt( interruptNumber, interruptRoutine, RISING);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if (geaendert == true) {Serial.println(dropCount);}
geaendert = false;
jetzt = millis();
if (jetzt - vorhin > intervall)
{
vorhin = jetzt;
Serial.print((dropCount - vordropcount));
Serial.println(" Tropfen pro Minute");
vordropcount = dropCount;
Serial.println(dropCount);
}
}
void interruptRoutine()
{
dropCount++;
geaendert = true;
delay(2);
}
Der vorangestellte Sketch zählt mit Hilfe einer Lichtschranke Tropfen und gibt sowohl die Gesamtzahl der gezählten Tropfen als auch die pro Minute gezählten Tropfen an.
Die letztere Angabe erfolgt jeweils minütlich auf den Serial-Monitor.
Damit der Tropfenzählsensor kein Signal übersieht und zählen kann, muss die laufende Arbeit des Arduino unterbrochen werden.
Dies leistet die Interruptfunktion.
Für den Tropfenzähler hat sich ein Aufruf der Routine bei steigenden Signalen „RISING“ als geeignet herausgestellt.
Zudem wird eine Funktion benannt, die im Fall eines Signalanstiegs (LOW auf HIGH) am benannten Digitalpin ablaufen soll.
Die Funktion sollte möglichst knapp gehalten sein und keine (oder nur sehr kurze) Delay-Aufrufe enthalten.
Sollen im ganzen Programm gültige Variable innerhalb der Interruptfunktion verändert werden, müssen sie als Veränderliche „volatile“ deklariert werden,
damit andere Teile des Programms mit die jeweiligen Veränderungen geeignet aufnehmen und umsetzen können (Näheres siehe Link auf „Arduino Interruptsteuerung (Teil1)“) .
http://technik-garage.de/tropfenzaehlerprobleme-und-loesungen/
********************************************************I*
12) Arduino UNO als Geiger-Müller-Zähler
Zählimpuls 100us Impulsverlängerung auf 5ms
Zeitdifferenzmessung
Für die Zählraten-Bestimmung hat man prinzipiell zwei Möglichkeiten.
Entwender man gibt eine Zeit vor und zählt wie viele Impulse man in dieser Zeit bekommt oder aber
man gibt die Zahl der Impulse vor, die man abwarten will und man mißt die Zeit die man benötigt bis man die vorgegebene Impulsanzahl erreicht.
In beiden Fällen ergibt sich die Impulsrate in dem man die Impulszahl durch die Zeit dividiert.
In vielen Fällen wird die erste Variante gewählt, weil sie naheliegender scheint.
Die zweite Variante hat aber einen großen Vorteil gegenüber der ersten:
Die Statistik (die Streuung) des Ergebnisses bleibt unabhängig von der Aktivität.
Das liegt daran, dass durch die Zufälligkeit der Zählimpulse ja immer eine Unsicherheit in der berechneten Zählrate bleibt,
die sich darin äußert, dass sie bei gleichbleibender Aktivität streut, da man sich auf eine endliche Anzahl an Zählpulsen zur Berechnung beschränken muss.
Diese Streuung hängt von der Zahl an Zählimpulsen ab und nicht von der Zeit.
Wenn man daher immer die gleich Zahl an Zählimpulsen abwartet, dann bleibt auch die Streuung des Ergebnisses gleich.
Dabei passt sich die Messzeit automatisch an die Verhältnisse an, wenn man eine hohe Aktivität hat,
erhält man aktualisierte Zählraten in rascher Folge, nur wenn die Zählrate niedrig ist, dauert die Messung länger.
Damit wartet man bei einer Änderung der Zählrate immer die kürzest mögliche Zeit (bei gegebener Statistik) für den nächsten Messwert.
Daher wird in diesem Beispiel die zweite Methode gezeigt.
ARDUINO Sketch Zählraten-Bestimmung
// Sketch Geiger-Müller-Zähler - Zählraten-Bestimmung
#define MAXCNT 10 // maxCNT
Zahl der Impulse 10 bis 200
#define
CalFactor 1 // CalFactor Umrechnung der Zählrate (cpm=counts per minute) in eine Dosierleistung uSv/h
volatile
int counter = 0;
unsigned long oldTime = 0;
int speaker = 5; // Lautsprecher an pin-5
void setup() {
pinMode(speaker, OUTPUT);
digitalWrite(speaker, LOW);
Serial.begin(9600);
attachInterrupt(0, count, FALLING);
}
void loop() {
unsigned long time;
unsigned long dt;
float rate;
if (counter == MAXCNT) {
detachInterrupt(0);
time =
millis();
dt = time-oldTime;
rate = (
float)MAXCNT*60.0*1000.0/(
float)dt/
CalF
actor;
Serial.println(rate);
oldTime = time;
counter = 0;
attachInterrupt(0, count,
FALLING);
}
}
void count()
{
counter++;
digitalWrite(speaker,
HIGH);
delayMicroseconds(50000); // 50ms Pause
digitalWrite(speaker,
LOW);
}
a
Quelle
303_Arduino-x_Bestimmung der Zählimpulsrate von Geiger-Müller-Sensoren (für Radioaktivität) mit dem ARDUINO_1a.pdf
********************************************************I*
Arduino als Zollstock
13) Ultraschall-Abstandsmessung mit Arduino
Es soll Schulen geben, da ist Abstandsmessung mit Ultraschall Teil des Praktikums im Fach Physiktechnik.
Mit Oszilloskop und Frequenzgenerator werden Impulspakete im 40-kHz-Bereich erzeugt.
Das alles soll den S/E-Kopf der Ultraschallprüfung verdeutlichen.
Für den Arduino wird zufällig ein ähnlicher Aufbau geliefert.
Quelle:
http://hjberndt.de/soft/ardping.html
********************************************************I*
Arduino als CompuLab (updated)
Compact erkennt Arduino
Quelle:
http://hjberndt.de/soft/ardcompact.htm
********************************************************I*
17.11.14: Sparrow-App:
Reaktionstest
http://www.elektronik-labor.de/AVR/Sparrow/SparrowTeleBin.html#reaktion
3.3.15:
LED-Kerzen mit induktiver Ladeschaltung
http://www.elektronik-labor.de/Labortagebuch/Tagebuch0315.html#led
Digispark-Luxmeter
http://www.elektronik-labor.de/Arduino/Digispark-Luxmeter.html
: Bascom-AVR: Widerstandsmessung 1 k ... 10 M
http://www.elektronik-labor.de/AVR/Rmessung.html
Schaltunsgtechnik: Resistiver Feuchtesensor
http://www.elektronik-labor.de/Notizen/FeuchteSensor.html
ATtiny13: Lernpaket Mikrocontroller über USB
http://www.elektronik-labor.de/AVR/LP-Mikrocontroller-clone.html#usb
19.12.14: Messtechnik: BPW34-Luxmeter
http://www.elektronik-labor.de/Lernpakete/Kalender14/Advent14.html#bpw34
13.12.14: Mikrocontroller: Motortreiber L293D
http://www.elektronik-labor.de/Lernpakete/Kalender14/Advent14.html#l293
27.11.14: Elektronik-Projekt: Gewitter-Monitor mit Grafik-LCD
http://www.elektronik-labor.de/Projekte/GewitterMonitor.html
12.5.14: Schaltungsnotizen: Solarleuchte als Durchgangsprüfer
http://www.elektronik-labor.de/Notizen/BauteileTester.html
9.5.14: Labortagebuch:
12-V-LED-Lampe an 230 V
http://www.elektronik-labor.de/Labortagebuch/Tagebuch0514.html
10.2.14: Labortagebuch:
Schrittmotor am ULN2803
http://www.elektronik-labor.de/Labortagebuch/Tagebuch0214.html#uln
4.2.14: Labortagebuch:
Solarlampe erhält Schottky-Diode
http://www.elektronik-labor.de/Labortagebuch/Tagebuch0214.html#solar
16.1.14: Schaltungswettbewerb:
Reaktionstester
http://www.elektronik-labor.de/Lernpakete/Kalender13/Reaktion.html
15.1.14: Schaltungswettbewerb:
Bleiakku-Vitalisierer
http://www.elektronik-labor.de/Lernpakete/Kalender13/Akku.html
15.1.14: Schaltungswettbewerb:
Ultraschallabstandsensor
http://www.elektronik-labor.de/Lernpakete/Kalender13/Ultraschall.html
15.1.14: Schaltungswettbewerb:
Ei-Timerschaltungen
http://www.elektronik-labor.de/Lernpakete/Kalender13/Timer.html
15.1.14: Schaltungswettbewerb:
PWM-Generator
http://www.elektronik-labor.de/Lernpakete/Kalender13/PWM2.html
14.1.14: Schaltungswettbewerb:
Zweikanalvorsatz für Oszilloskop
http://www.elektronik-labor.de/Lernpakete/Kalender13/Zweikanal.html
13.1.14: Schaltungswettbewerb:
Lichtschranke mit 4093
http://www.elektronik-labor.de/Lernpakete/Kalender13/Schranke.html
11.1.14: Schaltungswettbewerb:
Logiktester
http://www.elektronik-labor.de/Lernpakete/Kalender13/Logik.html
6.1.14: Schaltungswettbewerb:
Mückenscheuche mit 4093
http://www.elektronik-labor.de/Lernpakete/Kalender13/Muecke.html
19.12.13: Mikrocontroller:
Was ist Arduino?
http://www.b-kainka.de/Weblog/Mikrocontroller/Arduino.html
23.8.13: Bascom-AVR:
Hot-Spot-Temperaturregler
http://www.elektronik-labor.de/AVR/HotSpot.html
20.8.13: Schaltungstechnik:
Temperaturmessen mit 555 und PC
http://www.elektronik-labor.de/Notizen/Temp555.html
23.7.13: Elektronik-Dachbude:
Strommessungan der Solaranlage
27.5.13: Bascom-AVR:
Einfachedigitale Filter
http://www.elektronik-labor.de/AVR/Filter.html
21.5.13: Bastelecke:
Minimalistische Geigerzäher
http://www.b-kainka.de/bastel76.htm#mini
6.5.13: ATtiny13:
Stroboskop
http://www.elektronik-labor.de/AVR/dds/MicroDDS.html#strobo
22.4.13: Strahlenmessung:
BPW34misst Betastrahlen
http://www.elektronik-labor.de/Projekte/Alpha7.html#k40
19.4.13: Strahlenmessung:
RadioaktiveGlimmlampen
http://www.elektronik-labor.de/Labortagebuch/Tagebuch0413.html#glimm
9.4.13: Tiny13-Contest:
Servo-Voltmeter
http://www.elektronik-labor.de/AVR/T13contest/Servo.html#volt
5.4.13: Tiny13-Contest:
HelligkeitsempfindlicheLED
http://www.elektronik-labor.de/AVR/T13contest/Reaktiv.html
24.10.12: Elektronik-Grundlagen:
Operationsverstärker-Schnellkurs
http://www.elektronik-labor.de/Lernpakete/OPV/OPV_6.html
29.6.12: HT46F47:
Servo-Impulslängenmessung
http://www.elektronik-labor.de/Holtek/Holtek10.html
28.6.12: Labortagebuch:
Stromwandlermit einer Relais-Spule
http://www.elektronik-labor.de/Labortagebuch/Tagebuch08/Tagebuch0408.html#rel
22.6.12: AVR-Controller:
Bascom-Bootloaderfür Arduino
http://www.elektronik-labor.de/AVR/Bootloader.html#arduino
2.6.10: Elektronik-Labor:
RS232-Programmierung
http://www.elektronik-labor.de/RS232//RS232_3.htm
5.4.10: In der Bastelecke:
Der Kneipen-Reaktionstester
http://www.b-kainka.de/bastel122.html
23.1.07: Neues zum Software Defines Radio:
Messungenan der Soundkarte
http://www.b-kainka.de/iqrx3.htm
3.11.06: Basteln, Umbauen und Reparieren:
DieSolar-Gartenlampe
http://www.b-kainka.de/bastel111.htm
16.3.01: Die Bastelecke wird 50:
Taschenrechnerals Digitalzähler
http://www.b-kainka.de/bastel50.htm
********************************************************I*
Zählerbau mit wenig Zeilen
Arduino als Frequenzzähler für Arduino in C
Der Aufruf pulseIn() macht Zählerbau mit dem Arduino einfach. Mit einer LCD-Anzeige wird ein eigenes Gerät daraus. Impulsratenzähler im Eigenbau.
Arduino als Zähler
14) 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.
Arduino zeigt die Netzfrequenz bei offenem Eingang auf einem LCD-Display.
/* 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 } }
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.
Probe mit DSO-Quad
Das
Hosentaschenoszilloskop 'DSO-Quad' mit seinem eingebauten Frequenzgenerator soll als Testsignalgeber dienen.
Die Rechteckfrequenz kann in weiten Bereichen eingestellt werden. Mit zwei Verbindungen kann der Test beginnen.
Masse an Masse und Generatorausgang vom Quad an Pin 7 des Arduino.
Bei der Frequenz 5000 Hz wird in der Tat auch ein Wert um 5025 angezeigt.
Wer da jetzt im Recht ist, müsste eine Kalibrierung zeigen. Für einfache Messungen sollte das jedoch zunächst reichen.
Ratemeter oder Impulszähler
/* Impulszähler Gibt die Impulse pro Sekunde des Spannungsignals an Pin 7 aus */int pin = 7;unsigned long N; //Anzahl der Impulseunsigned long T; //Zeitintervall in usunsigned long time; //Startzeitvoid setup() { Serial.begin(9600); pinMode(pin, INPUT); T = 1e6;}void loop() { N = 0; time = micros(); do //what goes up must come down {if (pulseIn(pin, HIGH)>0) N++; }while( micros() < (time+T) ); Serial.println(N);}
Bei parallel laufenden, freien Praktika kann es vorkommen, dass plötzlich alle Impulszähler in Gebrauch sind.
Abhilfe schafft da ein kleiner Arduino mit einem kleinen Sketch. Impulsraten sind Ereignisse aperiodischer Signale pro Zeiteinheit, wie zum Beispiel die Impulsfolge eines Geiger-Müller-Zählrohrs.
In wenigen Zeilen wird hier mittels pulseIN() und micros() die Impulsrate an Pin 7 gemessen.
Als Zeitintervall T ist hier eine Sekunde, bzw. 1000000 (1e6) Mikrosekunden voreingestellt.
In der Hauptschleife wird die Einzelmessung initialisiert und dann während des Zeitintervalls T mittels pulseIn() auf eine ansteigende Flanke gewartet.
Anschließend enthält N die Anzahl der Impulse pro Sekunde und wird via Serial.println gesendet.
Benutzt man symmetrische Signale (Rechteck, Sinus, Dreieck), so ergeben sich bei beiden Zählervarianten gleiche Ergebnisse, obwohl sie anders funktionieren.
Durch Änderung der Variablen T kann die Messdauer verändert werden.
Für eine Zähldauer von z.B. 10 Sekunden würde T = 10*1e6 betragen.
LCD-Anzeige
Wie beim '
Arduino als Zollstock' macht eine LCD-Anzeige die Messanordnung autonom.
Auf einem 2x16-Display erfolgt die Darstellung durch Einbindung der 'LiquidCrystal'-Bibliothek, die unter
Da die Umlaute wieder Probleme machen, zeigt das Display 'FrequencyCounter'. Bei offenem Eingang fängt sich der Zähler hier die Netzfrequenz ein. /* Frequenzzähler
Gibt die Frequenz des Spannungsignals an Pin 7 aus */#include <LiquidCrystal.h>int pin = 7;unsigned long T; //Periodendauer in usdouble f; //Frequenz in MHz char fm[] = " %8ld Hertz";LiquidCrystal lcd(12, 11, 5, 4, 3, 2);void setup() { lcd.begin(16, 2); pinMode(pin, INPUT); lcd.print("FrequencyCounter");}void loop() { char s[20]; // Messen von ti + tp = T T = pulseIn(pin, HIGH) + pulseIn(pin, LOW); T == 0 ? f = 0 : f=1/(double)T; sprintf(s,fm,(unsigned long)(f*1e6)); lcd.setCursor(0, 1); lcd.print(s); delay(200);}
/* Frequenzzähler Gibt die Frequenz des Spannungsignals an Pin 7 aus */#include <LiquidCrystal.h>int pin = 7;unsigned long T; //Periodendauer in usdouble f; //Frequenz in MHz char fm[] = " %8ld Hertz";LiquidCrystal lcd(12, 11, 5, 4, 3, 2);void setup() { lcd.begin(16, 2); pinMode(pin, INPUT); lcd.print("FrequencyCounter");}void loop() { char s[20]; // Messen von ti + tp = T T = pulseIn(pin, HIGH) + pulseIn(pin, LOW); T == 0 ? f = 0 : f=1/(double)T; sprintf(s,fm,(unsigned long)(f*1e6)); lcd.setCursor(0, 1); lcd.print(s); delay(200);}
Quelle:
http://www.hjberndt.de/soft/ardfreq.html
********************************************************I*
Temperatur und Luftfeuchte mit einfachen Routinen (ohne Bibliotheken)
15) DHT11 am Arduino - Daten im Gänsemarsch
Wetter, Wetter, Wetter
Daten im Gänsemarsch für Arduino in C
Bibliotheken führen mit wenigen Klicks zum gewünschten Ergebnis, sie schirmen den Programmierer aber quasi ab.
Der hier eingesetzte Sensor für Temperatur und Luftfeuchte benutzt ein 1-Wire-Verfahren.
Ohne Bibliotheken sollen überschaubare Routinen den serielle Datenstrom verdeutlichen.
Im Netzt gibt es unzählige Sensoren für Arduino & Co. Der DHT11 ist dabei weit verbreitet und liefert einen positiven Temeraturwert in Celsius, sowie die Relative Luftfeuchte in Prozent.
Die Arduino-Gemeinde ist es gewohnt verwöhnt zu werden - anders ausgedrückt - es gibt zu jedem Sensor in kürzester Zeit eine Bibliothek
und schon kann der Küchentisch-Elektroniker und Patchwork-Programmierer mit drei Klicks seine Vorstellungen in kürzester Zeit realisieren.
Das Beispiel "Arduino als Zollstock" ist so zu verstehen.
Ist man allerdings interessiert, wie die Dinge im Untergrund der Technik und Bibliotheken funktionieren, wird die Sache schon schwieriger.
Im Blog
embedded-lab.com wird eine ganz bequeme Art vorgestellt den Sensor ohne Breadboard zu benutzen.
Das
DSO-Quad zeigt am Digitaleingang D den Beginn der Übertragung. Nach 18 Millisekunden LOW folgt etwa 40 us HIGH als Anforderung vom Arduino.
Der Sensor antwortet mit ca. 50 us LOW und ca 80 us HIGH.
Dann folgt eine Impulspause der festen Länge 50 us und das erste Bit mit kurzer Impulsbreite, also eine "0".
Die ersten Bits wären hiernach 0010010 ...
Dieser Sensor DHT11 sendet seine Informationen seriell im Gänsemarsch über die Leitung.
Die Besonderheit ist, dass eine Leitung für beide Richtungen verwendet wird. So sendet der Arduino ein Signal und schaltet anschließend auf Empfang.
Der Ausgang wird also zum Eingang. Der Datenaustausch kann wie folgt aus dem Datenblatt entnommen und zusammengefasst werden:
Ausgabe des Startsignals (Arduino)
Abwarten der Bestätigung (Sensor)
Einlesen von 40 Bit (5 Byte) Messdaten und Kontrolldaten
Im Detail ist das Startsignal ein Impuls der mindesten 18 ms LOW und 20 bis 40 us HIGH ist.
Danach wird auf Empfang geschaltet und auf die Antwort des Sensors gewartet.
Dieser legt zur Bestätigung den Eingang nun für 80 us auf LOW und danach 80 us auf HIGH. Nun folgen die 40 Bits bzw. 5 Bytes mit folgendem Inhalt:
Byte 1: Relative Luftfeuchte in Prozent
Byte 2: Nachkommastellen der Luftfeuchte (DHT11 immer 0)
Byte 3: Temperatur in Celsiusgrad
Byte 4: Nachkommastellen der Temperatur (DHT11 immer 0)
Byte 5: Summe der ersten vier Bytes zur Kontrolle
Ob ein Bit "1" oder "0" ist entscheidet die Impulsbreite.
Nach einer immer gleich langen Impulspause (LOW) von 50 us folgt eine Impulsbreite (HIGH) von entweder 26 bis 28 us für eine "0" oder 70 us für eine "1".
Damit steht einer Dekodierung nichts mehr im Weg. Das Signal erinnert etwas an das Funkuhr-Signal vom DCF77-Sender - mit anderen Zeiten.
Vorbereitungen - setup
Die Messdaten werden vom Arduino über die RS232-Leitung geschickt.
Der Sensor lag in der Nähe des Heizkörpers an einem kalten Winterabend. Die Luft war trocken ...
Vier globale Variablen - wegen der Einfachheit - sind für die Messergebnisse vorgesehen.
Einmal zwei Ganzzahlen (Integer), da der DHT11 hier keine Nachkommastellen liefert und zwei Zeichenketten (Strings), die diese Werte als Text enthalten.
Für die Ausgabe über Serial.print macht das keinen Unterschied, für eine möglicherweise angeschlossene Anzeige aber schon.
Als Anschluss für den Sensor DHT11 ist Pin 2 rein willkürlich gewählt worden. In der Setup-Routine wird die RS232-Schnittstelle konfiguriert und danach eine Sekunde gewartet.
Der Quelltextauschnitt zeigt folgendes Bild:
#define DHT_PIN 2
int feuchte, temperatur;
char sfeuchte[10],stemperatur[10];
void setup()
{Serial.begin(9600);
Serial.println("DHT11 Messung.");
delay(1000);
}
Hauptschleife - loop
In der Hauptschleife werden die Messungen einmal in der Sekunde abgerufen und zur Anzeige gebracht.
Die Funktion dht11(pin) führt die Konversation mit dem Sensor und liefert Messdaten für die Ausgabe.
void loop()
{dht11(DHT_PIN);
Serial.print("DHT11 Luftfeuchte[%]/Temperatur[C]: ");
Serial.print(sfeuchte);
Serial.print("/");
Serial.println(stemperatur);
delay(1000);
}
Datenabfrage - 1 oder 0
Die eigentliche Daten-Abfrage erfolgt so wie es der Hersteller angibt.
Nacheinander werden folgende Dinge ausgeführt:
Byte-Puffer auf Null setzen
Messanforderung senden
Bestätigung empfangen
Die 40 Bits einlesen und ablegen
Messwert in die Variablen übertragen
Die Funktion dht11 führt genau diese Schritte aus. Nach dem Rücksetzen der Byte-Puffer folgt die Anforderung (Request Sample) mit delay und delayMicroseconds.
Danach wird der Pin als Eingang geschaltet.
Mit pulseIn werden die ca. 70 us der Antwort (Acknowledge) abgewartet.
Zeitlich entspricht dies dem 5. Skalenteil des Oszillogramms oben.
Die 40 Bits (Read Output) werden nun anhand der Impulsbreite abgefragt, dabei liegt die zeitliche Schwelle bei 40 us.
Falls der Impuls länger ist, wird ein gesetztes Bit (1) bitcnt-mal nach links geschoben (<<), damit es im Byte an der richtigen Stelle steht.
Wenn ein Byte voll ist, wird der Bytezähler ix erhöht. Das wird so auch in der entsprechenden Bibliothek gemacht.
Sind alle 40 Bits eingelaufen, folgen die Variablenzuweisungen.
Für den DHT11 gibt es keine Kommastellen, darum wird das Byte 0 zur Luftfeuchte und das Byte 3 zur Temperatur.
An dieser Stelle müsste dies für Sensoren wie DHT22 etwas angepasst werden, ebenso wie die Checksummenabfrage (die im Hobbybereich auch entfallen kann).
Zum Schluss erfolgt die Umwandlung der Zahlen in Zeichenketten. In C ist das itoa (Integer zu Ascii).
Bei genauem Hinsehen erfolgt die Abfrage der Impulslänge der 40 Bit nicht mit der eingebauten pulseIn()-Funktion, da diese hier aus noch unklaren Gründen nicht so wie erwartet funktioniert.
Das liegt möglicherweise an der gerade benutzen Arduino-IDE.
Zur Umgehung dieses Problems wird eine ähnliche Routine aufgerufen, die hier das erwartete Ergebnis zeigt: mypulseIn
Pulslängenabfrage - Eigenbau mypulseIn()
Die integrierte pulseIn-Funktion wurde schon beim Projekt "
Arduino als Zähler" erfolgreich verwendet.
Falls Flanken nicht per Interrupt verarbeitet werden müssen, ist eine solche Funktion einfach in der Handhabung.
Wenn die Beschreibung der Funktion unter
Arduino.cc richtig verstanden wurde, ergibt sich - ohne im Quelltext zu wühlen - etwa folgender Ablauf:
unsigned long mypulseIn(int pin,int level){unsigned long t0,t1,t2,timeout=200; t0=micros(); if(level==HIGH) {while(!digitalRead(pin) && (micros()-t0)<timeout);//Wait for _/ t1=micros(); while( digitalRead(pin) && (micros()-t1)<timeout);//Wait for \_ t2=micros(); } else {while( digitalRead(pin) && (micros()-t0)<timeout);//Wait for \_ t1=micros(); while(!digitalRead(pin) && (micros()-t1)<timeout);//Wait for _/ t2=micros(); } return t2-t1; }
Diese Eigenbauroutine mit festen 200us Timeout funktioniert hier mit dem Arduino Uno R3.
// H.-J. Berndt 2015 auf www.hjberndt.de// DHT11-Sensor mit 1-Draht-Datenprotokoll// ohne Bibliotheken abfragen#define DHT_PIN 2 int feuchte, temperatur;char sfeuchte[10],stemperatur[10];void setup(){ Serial.begin(9600); Serial.println("DHT11 Messung."); delay(1000);}void loop(){dht11(DHT_PIN); Serial.print("DHT11 Luftfeuchte[%]/Temperatur[C]: ");Serial.print(sfeuchte); Serial.print("/");Serial.println(stemperatur); delay(1000);}void dht11(int pin){int bitcnt=7,ix=0; uint8_t Byte[5]; for(int i=0;i<5;i++)Byte[i]=0; pinMode(pin, OUTPUT); // REQUEST SAMPLE digitalWrite(pin, LOW); delay(18); digitalWrite(pin, HIGH);delayMicroseconds(30); pinMode(pin, INPUT); pulseIn(pin,HIGH); // ACKNOWLEDGE ~ 70 us for (int i=0; i<40; i++) // READ OUTPUT - 40 BITS = 5 BYTE {if (mypulseIn(pin,HIGH) > 40) Byte[ix] |= (1 << bitcnt); if (--bitcnt < 0)// next byte {bitcnt = 7; // restart ix++; } } feuchte = Byte[0]; //BYTE[1] bei DHT11 immer 0 temperatur = Byte[2]; //BYTE[3] bei DHT11 immer 0 if (Byte[4] != Byte[0]+Byte[2]){feuchte=88;temperatur=88;} itoa(feuchte,sfeuchte,9); itoa(temperatur,stemperatur,9);}unsigned long mypulseIn(int pin,int level){unsigned long t0,t1,t2,timeout=200; t0=micros(); if(level==HIGH) {while(!digitalRead(pin) && (micros()-t0)<timeout);//Wait for _/ t1=micros(); while( digitalRead(pin) && (micros()-t1)<timeout);//Wait for \_ t2=micros(); } else {while( digitalRead(pin) && (micros()-t0)<timeout);//Wait for \_ t1=micros(); while(!digitalRead(pin) && (micros()-t1)<timeout);//Wait for _/ t2=micros(); } return t2-t1; }
Der Gesamtquelltext ist
hier hinterlegt.
Quelle:
http://www.hjberndt.de/soft/arddht11.html
DIN A4 ausdrucken
********************************************************I*
Impressum: Fritz Prenninger, Haidestr. 11A, A-4600 Wels, Ober-Österreich, mailto:
[email protected]
ENDE