Kleine Teile mit Arduino zählen

Hallo liebe Arduino Gemeinge,

An meinem Projekt komme ich leider nicht weiter.
kurze Beschreibung:
Es sollen kleine Teile gezählt werden (kleine Zahnräder im Durchmesser von 5mm und eine höhe von
0.2mm).
Ich dachte mir, dass ich diese Aufgabe mit einer Gabelichtschranke lösen kann.
Leider ist es mir nicht gelungen.
Der Arduino zählt nur, wenn die Teile etwas größer sind.
Ich habe es mit einer Gabellichtschranket mit eingebautem Komporator LM393 probiert, es ging etwas besser aber trotzdem nicht stabil. In vielen Fällen zählt der Arduino einfach nicht.
Dann habe ich es mit einem Laser und einem Fotowiederstand BPW34. Die habe ich einfach über Wiederstände am Arduino angeschlossen. Leider hat es auch nicht so richtig geklappt. Der Arduino auch nicht stabil gezählt. Es fehlte etwas.
Jetzt meine Frage:
welchen Typ von Sensoren soll ich verwenden?
Soll ich nocht was dazuschalten z.B. Impedanzwandler, Operationsverstärker...?
Oder soll ich etwas im Sketch ändern?

OLED_Z_HLER.ino (1.07 KB)

BPW34 ist kein Fotowiderstand sondern einen Fotodiode. Diese muß ganz anders verwendet werden.

Umgebungslicht abschirmen!

Grüße Uwe

moca:
...
Oder soll ich etwas im Sketch ändern?

Vielleicht funktioniert es besser, wenn Du die Möglichkeit externer Interrupts auf den Pins 2 und 3 benutzt. Davon habe ich bislang allerdings keine Ahnung.

Gruß

Gregor

Man könnte evtl. auch einen der eingebauten Counter(Timer) zum counten überreden. Dann gehts auch quasi ohne Prozessorbelastung.

Hier müsste man erst mal klären ob das ein Hardware- oder ein Software-Problem ist. Am einfachsten geht das natürlich mit einem Oszilloskop. Aber an eine Lichtschranke kann man man auch direkt eine LED + Vorwiderstand anschließen. Der LM393 schafft auch 16mA als Stromsenke

oder ein Software-Problem

3 mal die Hardware ausgetauscht, und Problem persistiert.
Wenn auch die Hardware nicht perfekt sein mag, riecht das doch arg nach Software.

Es ist zu sehen, denn der Quellcode liegt bei.

  1. Wire ist gespickt mit blockierenden Aufrufen.
  2. Delay im Code

Beide sind Zeitfresser, welche Zählungen wirksam unterbinden können/werden.

Ok, auf delay() könne man verzichten.
Aber ein Umbau von Wire wird wohl zuviel Aufwand sein.

Ein pollen scheidet also aus, da man Ereignisse verlieren/übersehen kann.
(Hier scheint der Hase im Pfeffer zu liegen.)

Also bleibt wohl nur Hardware Counter, oder Interrupts.

Wenn analog gelesen werden soll, bietet sich der Analog Comparator Interrupt an.
Bis zu wenigen tausend Ereignissen pro Sekunde, sind Pin Interrupts, eine brauchbare Wahl.
Bei noch höheren Zählraten, oder um Prozessorlast einzusparen, verwendet man dann doch besser einen Hardware Timer/Counter


Warum analog?
Wieviel Ereignisse pro Sekunde?
Länge des einzelnen Ereignisses?

Ja, der Code ist doch sehr wirr :confused:

Auch das Display in loop() zu löschen macht nur Probleme

gregorss:
Vielleicht funktioniert es besser, wenn Du die Möglichkeit externer Interrupts auf den Pins 2 und 3 benutzt. Davon habe ich bislang allerdings keine Ahnung.

Gruß

Gregor

Ok, danke für den Hinweis.
Ich habe schon etwas von Interrupts gehört jedoch habe ich auch keine Ahnung wie es funktioniert.

combie:
Wenn analog gelesen werden soll, bietet sich der Analog Comparator Interrupt an.
Bis zu wenigen tausend Ereignissen pro Sekunde, sind Pin Interrupts, eine brauchbare Wahl.
Bei noch höheren Zählraten, oder um Prozessorlast einzusparen, verwendet man dann doch besser einen Hardware Timer/Counter


Warum analog?
Wieviel Ereignisse pro Sekunde?
Länge des einzelnen Ereignisses?

Es muss nicht unbedingt analog gelesen werden. Ich habe es auch mit digital probiert und es war das gleiche Ergebnis. Die Teile wurden nicht immer erkannt. Es sieht allgemein so aus, als ob es an Empfindlichkeit fehlte.

Es wird ca. einmal pro 5 Sekunden gezählt.
(Länge des einzelnen Ereignisses) weniger als eine Sekunde.

Leider habe ich mit Interrupt noch nichts zutun gehabt. Bin noch ziemlich am Anfang. :confused:

Serenifly:
Ja, der Code ist doch sehr wirr :confused:

Was soll in dem Code noch geändert werden? :confused:

[/quote]

Serenifly:
Auch das Display in loop() zu löschen macht nur Probleme

Was meins du mit Display in loop() zu löschen? Kannst du es etwas genauer sagen?

moca:
Was soll in dem Code noch geändert werden? :confused:

Statt das ganze Display zu löschen, den Text neu schreiben, spart Zeit.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
const int sensorPin = 2;
const int ledPin = 13;
#define OLED_RESET -1 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);
int Counter = 0;
bool DetectorState;         // current state of the Detector
bool lastDetectorState;

void setup()   {

  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE, BLACK);  // Vordergrund-, Hintergrundfarbe
  display.setTextSize(3);
  display.setCursor(34, 12);
  display.println(Counter);
  display.display();
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT_PULLUP);
  Serial.begin(9600);
  DetectorState = digitalRead(sensorPin);
  lastDetectorState = DetectorState;
}

void loop() {
  lastDetectorState = DetectorState;
  DetectorState = digitalRead(sensorPin);
  digitalWrite(ledPin, DetectorState);
  if (!lastDetectorState && DetectorState) {
    Counter++;
    display.setCursor(34, 12);
    display.println(Counter);
    display.display();
  }
}

moca:
Was meins du mit Display in loop() zu löschen? Kannst du es etwas genauer sagen?

Formatiere den Text auf eine konstante Breite (z.B. mit führenden Nullen oder führenden/nachfolgenden Leerzeichen). Dann wird nur das überschrieben was man braucht

agmue:
Statt das ganze Display zu löschen, den Text neu schreiben, spart Zeit.

#include <SPI.h>

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
const int sensorPin = 2;
const int ledPin = 13;
#define OLED_RESET -1 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);
int Counter = 0;
bool DetectorState;        // current state of the Detector
bool lastDetectorState;

void setup()  {

// initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE, BLACK);  // Vordergrund-, Hintergrundfarbe
  display.setTextSize(3);
  display.setCursor(34, 12);
  display.println(Counter);
  display.display();
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT_PULLUP);
  Serial.begin(9600);
  DetectorState = digitalRead(sensorPin);
  lastDetectorState = DetectorState;
}

void loop() {
  lastDetectorState = DetectorState;
  DetectorState = digitalRead(sensorPin);
  digitalWrite(ledPin, DetectorState);
  if (!lastDetectorState && DetectorState) {
    Counter++;
    display.setCursor(34, 12);
    display.println(Counter);
    display.display();
  }
}

Vielen Dank für die Hilfe, es funktioniert alles Wunderbar.
Ich habe noch eine Führung mit eingebaut damit die Teile auf einer Linie durch die Diode fallen und es leichter fällt, die Teile durch den Strahl fallen zu lassen, denn die Teilchen sie wie schon gesagt klein.