Go Down

Topic: Lichtschranke mit Widerständen zeitverzögern (Read 1 time) previous topic - next topic

Tommy56

Die Schaltung sagt aber etwas anderes aus.
Dort ist diese Widerstandskette zwischen 5V und GND geschaltet und über den Drehschalter nimmst Du verschiedene Spannungen ab.

Diese sollst Du an einem Analogeingang Des Arduino messen. Mache das erst mal in einem eigenen Sketch, da wird es übersichtlicher. Gib einfach den Wert von analogRead(A?Pin) auf Serial aus.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

slartibartfast

Ich würde das so machen:
Code: [Select]

/*   Beschaltung:
 *   Ein 100kOhm-Widerstand von A0 nach +5V
 *   Fuenf 1kOhm-Widerstaende in Reihe schalten zwischen +5V und GND
 *   den mittleren Anschluss vom Drehschalter an A0
 *   und die anderen fuenf Anschluesse der Reihe nach (bei GND anfangen) an die Widerstaende
 */
 
#define KeyboardIn A0  // die Widerstandsreihe liegt am Analoganschluss A0

const long KeyVals[] = {1000, 800, 600, 400, 200, 0}; // ungefaehre Analogwerte (bei 5 x 1kOhm, 5% Widerstaende)
const byte KeyChar[] = {0, 5, 4, 3, 2, 1};            // die dazugehoerigen Tasten oder Schaltstellungen bei einem Drehschalter
const byte KeyCount = sizeof(KeyChar);                // die Anzahl der Tasten (KeyChar ist ein Byte-Array, also reicht sizeof)
const byte tolerance = 100;                           // dieser Toleranzwert wird zu den obigen Werten addiert (die Widerstandswerte schwanken)

byte key, prevkey;         // zum merken der aktuellen und der letzten Taste
uint32_t DebounceMillis;   // zum merken der Entprellzeit
uint16_t analogValue = 0;  // zum auslesen des Analogwertes

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start"));
}

void loop() {
  if (millis() - DebounceMillis > 50) {
    DebounceMillis = millis();
    key = GetKey();
    if (key > 0 && key != prevkey) {
      prevkey = key;
      Serial.print(F("Analogwert: "));
      Serial.print(analogValue);
      Serial.print(F(" Taste: "));
      Serial.println(key);
    }
  }
}

byte GetKey() {
  analogValue = analogRead(KeyboardIn);
  for (byte i = 0; i < KeyCount; i++) {
    if (analogValue + tolerance >= KeyVals[i]) return KeyChar[i];
  }
}

"Schaltplan" im Anhang.

Tommy56

#17
Feb 16, 2017, 07:09 pm Last Edit: Feb 16, 2017, 07:10 pm by Tommy56
In Deiner Schaltung fehlt die 5V-Verbindung.
Was versprichst Du Dir von dem 100 kOhm-Widerstand? Definiertes Potential in der Umschaltlücke?

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

slartibartfast

In Deiner Schaltung fehlt die 5V-Verbindung.
Was versprichst Du Dir von dem 100 kOhm-Widerstand?

Die 5V-Verbindung ist doch vorhanden (rotes Kabel).
Und der 100kOhm-Widerstand ist notwendig, weil sonst beim umschalten A0 in der Luft hängt und zufällige Werte raushaut.
Ich hab's aufgebaut, das ist wirklich so.

Theseus

#19
Feb 16, 2017, 07:14 pm Last Edit: Feb 16, 2017, 07:16 pm by Theseus
Kann mir dabei jemand behilflich sein oder hat dazu vielleicht einen guten Artikel parat, wie ich das am besten mit welchen Programmierfunktionen umsetzen kann?
Steht doch oben schon. Lass dir die Werte zur Sicherheit mit Serial.Print ausgeben, ob die Werte passen.

Du könntest für ein erstes Erfolgserlebnis z.B. delay(Stufe*250+500) nehmen.
Nächster Schritt wäre die Umstellung auf millis()

zwei Varianten:
a) analog:
 Eine Kette aus 5 gleichen Widerständen von 5V auf GND, die Spannungknoten werden über den Schalter ausgewählt und analog eingelesen.
Code: [Select]
int ad = analogRead(A0);
  int Stufe;
  if      (ad < 102)  Stufe = 0;
  else if (ad < 307)  Stufe = 1;
  else if (ad < 512)  Stufe = 2;
  else if (ad < 716)  Stufe = 3;
  else if (ad < 921)  Stufe = 4;
  else                Stufe = 5;


Tommy56

Ok, den roten Draht habe ich nicht richtig verfolgt. Das andere hatte ich über Edit noch hinterher geschoben, da warst Du schneller.
Wenn 2 auf den gleichen Gedanken kommen, ist das schon ein gutes Zeichen ;)

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Bloqq

Die Schaltung sagt aber etwas anderes aus.
Dort ist diese Widerstandskette zwischen 5V und GND geschaltet und über den Drehschalter nimmst Du verschiedene Spannungen ab.

Diese sollst Du an einem Analogeingang Des Arduino messen. Mache das erst mal in einem eigenen Sketch, da wird es übersichtlicher. Gib einfach den Wert von analogRead(A?Pin) auf Serial aus.

Gruß Tommy
Das habe ich nun gemacht mit dem ReadAnalogVoltage Tutorial hier auf der Seite.

Angefangen bei Stufe 1 zeigt mir der Serielle Monitor nun den Wert 5.00 an, pro Stufe die ich weiter schalte, sinkt der Wert um je 1V ab.



Das ist mein Code dafür:

Code: [Select]


unsigned long previousMillis=0;
const long interval = 2000;

void setup() {
  Serial.begin(9600);
}

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  {
    previousMillis=currentMillis;
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.0);
  Serial.println(voltage);
  }

}






Ich würde das so machen:

Wenn ich das richtig erkenne, ist das ja genau das Programm, das ich bräuchte.
Vielen Dank für die Mühe!! :)
Gerne würde ich aber die oben aufgeführte Version versuchen umsetzen, falls ich daran scheitere komme ich sehr gerne darauf zurück.

Tommy56

Du kannst ja auch beide probieren ;)

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

slartibartfast

Wenn ich das richtig erkenne, ist das ja genau das Programm, das ich bräuchte.
Vielen Dank für die Mühe!! :)
Gerne würde ich aber die oben aufgeführte Version versuchen umsetzen, falls ich daran scheitere komme ich sehr gerne darauf zurück.
Das ist sehr löblich, dass Du es selbst versuchen willst.
Aus den eigenen Fehlern lernt man am meisten.  :)
Bedenke aber, dass die Widerstände eine Toleranz besitzen (temperaturabhängig) und auch die Betriebsspannung am Arduino eine Rolle spielt.
Somit sind die gemessenen Werte nicht konstant. Du musst beim auswerten also eine Toleranz bei Deinen Werten einplanen.

Theseus

#24
Feb 16, 2017, 07:45 pm Last Edit: Feb 16, 2017, 07:46 pm by Theseus
Bedenke aber, dass die Widerstände eine Toleranz besitzen (temperaturabhängig) und auch die Betriebsspannung am Arduino eine Rolle spielt.
Somit sind die gemessenen Werte nicht konstant. Du musst beim auswerten also eine Toleranz bei Deinen Werten einplanen.

Die Betriebsspannung spielt keine Rolle, da die Widerstände mit der selben Betriebsspannung wie der Arduino versorgt werden. Damit heben sich Schwankungen auf. Solange das Verhältnis der Widerstände untereinander gleich bleibt, ändern sich die Spannungen bei einem Spannungsteiler nicht. Die Temperatur wird auch nur bei extremen Unterschieden zwischen den Widerständen interessant. Es müsste schon ein Widerstand auf 200°C gebracht werden und ein anderer mit Trockeneis gekühlt werden, damit man das wirklich merkt. Alle in Trockeneis oder alle auf 200°C, bleibt das Verhältnis gleich.

In so einem Programm ist unüblich mit Spannungswerten zu arbeiten. Lass dir die Analogread-Werte ohne umrechnen ausgeben und Unterscheide dann danach.

guntherb

Mit dem Code aus dem Ohmmeter von http://www.elektronik-labor.de/Arduino/Ohmmeter.html habe ich mir nun für die verschiedenen Schalterstellungen einen Ohmwert ausgeben lassen.
Ich habe doch in Antwort #6 zum Schaltbild auch gleich den Code zum Auswerten mitgepostet.  :smiley-confuse:
Gesehen? Gelesen? Verstanden?

Das könnte man so einbetten:
Code: [Select]


int sensorPin = A0;
int DrehschalterPin = A1;
int sensorValue = 0;
int ledPin = 13;
int ledPin2 = 12;
unsigned long int startzeit;

void setup ()
{
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  sensorValue = analogRead(sensorPin);
  Serial.println(sensorValue);


  int ad = analogRead(DrehschalterPin);  // einlesen Spannungwert Drehschalter
  unsigned long Wartezeit;
  if      (ad < 102)  Wartezeit = 1000;  // je nach Schalterstellung
  else if (ad < 307)  Wartezeit = 1500;   // entsprechende Wartezeit zuweisen.
  else if (ad < 512)  Wartezeit = 2000;
  else if (ad < 716)  Wartezeit = 2500;
  else if (ad < 921)  Wartezeit = 3000;
  else                Wartezeit = 3500;

  bool sensor = sensorValue < 500;  // SensorValue auswerten.
  /* eigentlich muss man hier auf die Flank auswerten, damit bei durchbrochener Lichtschranke
      nur einmal ausgelöst wird.    */

  if (sensor) {
    startzeit = millis(); // Zeit merken, wann Sensor ausgelöst wurde
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, HIGH);
  }

  if (millis() - startzeit > Wartezeit) { // prüfen, ob die Zeit zu Abschalten gekommen ist.
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, HIGH);
  }

} // End loop





Grüße
Gunther

Bloqq

Hi,

also nach einigen Fehlversuchen es selbst zu lösen, mit den diversen Hilfen die hier schon gegeben wurden, habe ich es leider dennoch nicht hinbekommen.

In meiner Frustration habe ich ganz unkreativ nun den Code von Gunter kopiert und aufgespielt.


Dabei stelle ich nun folgendes Problem fest:

-ledPin 13 (der den Auslöser der Kamera betätigen soll) bleibt immer dunkel, egal ob ich die Lichtschranke unterbreche oder nicht.

-ledPin 12 (die "Anzeige" ob ich mit dem Laser die Fotodiode treffe und der Arduino ein Signal bekommt) leuchtet immer, egal ob ich die Lichtschranke unterbreche oder nicht.


Wo könnte da mein Fehler liegen?
Wegen diesem Fehler konnte ich die Zeitverzögerung, wie lange ausgelöst wird, leider noch nicht überprüfen.



Beste Grüsse

Alex

Tommy56

Gib Dir doch mal die Sensor-Werte auf Serial aus.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Bloqq

Der Serielle Monitor gibt bei unterbrochener Lichtschranke einen Wert von ca. 1000 aus, bei nicht unterbrochener Lichtschranke ungefähr einen Wert von 4.

Gruss

Tommy56

Ich habe den Code mal etwas umgebaut, damit auch die von guntherb als Kommentar angemerkter Flanke mit rein kommt.
Da ich keinen Sensor habe, habe ich eine Umschaltfunktion aller 10 Sekunden zwischen 800 und 200 für sensorValue benutzt.
Achtung: ledPin2 ist bei mir 2!
Code: [Select]



int sensorPin = A0;
int DrehschalterPin = A1;
int sensorValue = 0;
int ledPin = 13;
int ledPin2 = 2;
unsigned long startzeit, lastChange;
boolean isEin = false;
bool oldSensor = true;
void setup ()
{
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  Serial.begin(115200);
  sensorValue = 800;
}

void loop() {
  // sensorValue = analogRead(sensorPin);
//  Serial.println(sensorValue);


  int ad = 900; //analogRead(DrehschalterPin);  // einlesen Spannungwert Drehschalter
  unsigned long Wartezeit;
  if      (ad < 102)  Wartezeit = 1000;  // je nach Schalterstellung
  else if (ad < 307)  Wartezeit = 1500;   // entsprechende Wartezeit zuweisen.
  else if (ad < 512)  Wartezeit = 2000;
  else if (ad < 716)  Wartezeit = 2500;
  else if (ad < 921)  Wartezeit = 3000;
  else                Wartezeit = 3500;

  bool sensor = sensorValue < 500;  // SensorValue auswerten.
  /* eigentlich muss man hier auf die Flank auswerten, damit bei durchbrochener Lichtschranke
      nur einmal ausgelöst wird.    */
  if (oldSensor != sensor) {   
    Serial.print("Sensor: "); Serial.println(sensor);
    Serial.print("SensoeValue: "); Serial.println(sensorValue);
    if (sensor) {
      Serial.println("Anschalten");
      isEin = true;
      startzeit = millis(); // Zeit merken, wann Sensor ausgelöst wurde
      digitalWrite(ledPin, LOW);
      digitalWrite(ledPin2, HIGH);
    }
    oldSensor = sensor;
  }

  if (isEin && millis() - startzeit > Wartezeit) { // prüfen, ob die Zeit zu Abschalten gekommen ist.
    Serial.println("Ausschalten");
    isEin = false;
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin2, LOW);
    delay(1000);
  }
  // zum Umschalten, da ich keinen Sensor habe
  if (millis() - lastChange > 10000) {
    Serial.println("Umschalten");
    lastChange = millis();
    if (sensorValue == 800) sensorValue = 200;
    else sensorValue = 800;
  }
} // End loop


Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Go Up