Liebes Forum,
Ich habe eine Lichtschranke über ein Relais mit dem Arduino gekoppelt.
Dieses soll Objekte, die die Lichtschranke passieren Zählen.
Ab einer gewissen Geschwindigkeit des Objekts,(wenn ich meinen Finger so schnell wie möglich bewege) höre ich das Relais, aber das Arduino Zählt nicht 1 Weiter.
Woran liegt das? Muss Ich vielleicht etwas am Programm ändern?
Vielen Dank im Voraus!
Code:
//Display
#include <SoftwareSerial.h>
// Attach the serial display's RX line to digital pin 2
SoftwareSerial mySerial(3,2); // pin 2 = TX, pin 3 = RX (unused)
//Stringarrays erstellen
char countstring[16], gesamtstring[10], averagestring[10];
//Zeitmessung
unsigned long ZeitDerGesamtenMessung; //Zeit seit dem 1. Stück
unsigned long Vorlaufzeit; //Zeit bevor die Messung beginnt
float Gesamtdurchschnitt; //Teile/ Ziet seit 1. Stück
float SecGesamtdurchschnitt; //Ges. / 1000
float hundertSecGesamtdurchschnitt; //Ges * 100
//Running Avarage lastTime
unsigned long Time;
unsigned long lastTime;
float timeDistance;
float secTimeDistance;
//Smoothing
const int numReadings = 50;
float readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
float total = 0; // the running total
float average = 0; // the average
float secAverage = 0;
float hundertSecAverage = 0; //* 100
// this constant won't change:
const int buttonPin = 3; // the pin that the pushbutton is attached to
const int ledPin = 13; // the pin that the LED is attached to
// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
void setup() {
// initialize the button pin as a input:
pinMode(buttonPin, INPUT);
// initialize the LED as an output:
pinMode(ledPin, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
//Display
mySerial.begin(9600); // set up serial port for 9600 baud
//Smoothing: initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
}
void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin);
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
// if the state has changed, increment the counter
if (buttonState == HIGH) {
// if the current state is HIGH then the button
// wend from off to on:
buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter);
//Zeitmessung
ZeitDerGesamtenMessung = millis() - Vorlaufzeit;
Serial.print("Zeit seit 1. Teil: ");
Serial.println(ZeitDerGesamtenMessung);
Gesamtdurchschnitt = ZeitDerGesamtenMessung / buttonPushCounter;
SecGesamtdurchschnitt = Gesamtdurchschnitt / 1000;
hundertSecGesamtdurchschnitt = SecGesamtdurchschnitt * 100;
Serial.print("Gesamtdurchschnitt pro 100 in Sec: ");
Serial.println(hundertSecGesamtdurchschnitt);
//Running Avarage
Time = millis();
timeDistance = Time - lastTime;
secTimeDistance = timeDistance / 1000;
Serial.print("Zeit/Teil ");
Serial.println(secTimeDistance);
//Smoothing
// subtract the last reading:
total= total - readings[index];
// read from the sensor:
readings[index] = timeDistance;
// add the reading to the total:
total= total + readings[index];
// advance to the next position in the array:
index = index + 1;
// if we're at the end of the array...
if (index >= numReadings)
// ...wrap around to the beginning:
index = 0;
// calculate the average:
average = total / numReadings;
secAverage = average / 1000;
hundertSecAverage = secAverage * 100;
Serial.print("Momentandurchschnitt pro 100 in sec: ");
// send it to the computer as ASCII digits
Serial.println(hundertSecAverage);
//Running Avarage last time aktualisieren
lastTime = millis();
//Daten auf Display ausgeben
//Clear Display
mySerial.write(254); // move cursor to beginning of first line
mySerial.write(128);
mySerial.write(" "); // clear display
mySerial.write(" ");
sprintf(countstring,"%16d",buttonPushCounter); // create strings from the numbers mit 16 Platzhaltern
mySerial.write(254); // move cursor to beginning of first line
mySerial.write(128);
mySerial.write(countstring); //anzahl Drucken
}
else {
// if the current state is LOW then the button
// went from on to off:
Serial.println("off");
}
}
// save the current state as the last state,
//for next time through the loop
lastButtonState = buttonState;
//Vorlaufzeit aktualisiseren
if (buttonPushCounter < 1)
{
Vorlaufzeit = millis();
}
//Daten auf Display ausgeben
//Clear Display
mySerial.write(254); // move cursor to beginning of first line
mySerial.write(128);
mySerial.write(" "); // clear display
mySerial.write(" ");
sprintf(countstring,"%16d",buttonPushCounter); // create strings from the numbers mit 16 Platzhaltern
mySerial.write(254); // move cursor to beginning of first line
mySerial.write(128);
mySerial.write(countstring); //anzahl Drucken
}
Das ist schon mal gut das kein delay() in der Loop Schleife vorhanden ist.
Wieso dein Programm nun zu langsam ist, kann ich dir nicht sagen.
Wenn du schnelle Impulse z.B: von Lichtschranken auswerten willst, musst du mit einem Interrupt arbeiten. Alle Arduinos besitzen 2 oder mehr Interrupts die herausgeführt sind.
DiMedici:
Ab einer gewissen Geschwindigkeit des Objekts,(wenn ich meinen Finger so schnell wie möglich bewege) höre ich das Relais, aber das Arduino Zählt nicht 1 Weiter.
Woran liegt das? Muss Ich vielleicht etwas am Programm ändern?
Die Hardware-Serial bremst den Sketch aus, wenn der Sendepuffer mit 63 noch nicht gesendeten Zeichen voll ist.
Falls Du also während der Programmlaufzeit mehr Zeichen pro Sekunde senden möchtest als es der Baudrate entspricht und dabei der Puffer mit 63 Zeichen vollläuft, wartet Dein Programm beim Serial.print und Serial.write immer so lange, bis wieder ein Zeichen aus dem Sendepuffer raus ist und das nächste Zeichen reingeschoben werden kann.
Versuche mal, die serielle Sendegeschwindigkeit zu erhöhen:
Serial.begin(115200);
(Seriellen Monitor entsprechend auch auf diese Baudrate einstellen)
Zeigt sich ein Unterschied, ja oder nein?
Über Deine Software-Serial scheinen wohl weniger Daten rauszugehen, da könnte ggf. die niedrigere Datenrate noch ausreichen. Die Anzahl der Zeichen (Byte, Char), die Du pro Zeiteinheit über eine serielle Schnittstelle raushauen kannst, ist ziemlich genau Baudrate geteilt durch zehn.
sth77:
Die Kombination Lichtschranke/Relais verstehe ich nicht so recht. Hast du mal einen Schaltplan parat?
Es gibt sehr viele Lichtschrankenbausätze die mit einem Relais arbeiten, ich habe damals auch mal so angefangen, wo ich noch keinen Arduino hatte. Daher geh ich mal davon aus das der Ersteller dieses Themas auch so einen verwendet.
DiMedici:
Ich habe die Sendegeschwindigkeit erhöht. Das hat leider nicht geholfen.
Gib mal einen Link auf das Datenblatt der verwendeten Lichtschranke!
Viele Lichtschranken haben eine Mindest-Auslösezeit, bevor geschaltet wird.
Z.B. wenn es sich um eine Personenlichtschranke handelt ist oft die Mindestauslösezeit so bemessen, dass ein Vogel im Flug die Lichtschranke durchfliegen kann, ohne dass es zur Auslösung kommt. Nicht, dass irgendeine Amsel einen Einbruchs-Fehlalarm auslöst oder beim Marathonlauf die Siegerzeit gutgeschrieben bekommt.
Allerdings sollte dann auch das Relais still bleiben und nicht schalten.
Wie ist das bei Dir: Du hörst das Relais schalten, aber der Arduino bekommt davon nichts mit?
Du hast natürlich Funktionen drin, die in der loop etwas Zeit benötigen. Wie ist das eigentlich mit Software-Serial? Landen da eigentlich die Zeichen auch in einem Sendepuffer und werden danach asynchron im Hintergrund gesendet? Oder wird zum Senden mit Software-Serial das Programm so lange angehalten, so lange wie Software-Serial sendet?
Wenn jedenfalls Funktionen so lange laufen, dass die Relais-Schaltzeit zu kurz ist, um sie in der loop zu erkennen, aber das Relais tatsächlich schaltet, wird man die Auslösung der Lichtschranke mit einer Interruptbehandlungsroutine trotzdem sicher erkennen können. Der Interrupt unterbricht ja längerdauernde Funktionen.
Was millis() betrifft: Du kannst millis() im Interrupt abfragen, aber millis() läuft innerhalb der Interrutbehandlung nicht weiter, denn durch die Unterbrechung ist alles andere bis auf die Interruptbehandlung angehalten, auch das Weiterlaufen der millis().
Ich habe eine Lichtschranke über ein Relais mit dem Arduino gekoppelt.
Das Schalten hören heißt noch nicht, daß der Kontakt auch wirklich zugeht. Ein Relais kann nur wenige Hz Schaltfrequenz haben ( schließen - öffnen - schließen ecc)
Die daten brauchst Du aufs Display nur ausgeben wenn der innhalt sprich die Variable buttonPushCounter sich geändert hat (Zeile 148ff) . Das ist nur im Falle der wahren if (buttonState != lastButtonState) { (Zeile 62)
Darum gib die Ausgabe auf das Display in die obengenannte Bedingung.
So hast Du bei nicht wahrer if (buttonState != lastButtonState) { (Zeile 62) -Bedingung eine sehr schnelle Loop.