Ich habe folgendes Setup: Arduino Nano (China Replikat), TRCT5000 IR-Sensor.
Die beiden Dioden habe ich aus dem TRCT5000 Modul ausgelötet und so platziert, dass sie sich mit ca 10mm Abstand genau gegenüber sitzen. Sieht die Empfänger-Diode kein IR mehr, dann sollen kurz LEDs aufblitzen.
Das funktioniert soweit auch alles gut, Bewege ich zB einen Bleistift zügig durch die Lichtschranke wird das korrekt erkannt und die LEDs leuchten. Konkret geht es aber darum eine 6mm große Kugel die ca 90m/s schnell ist zu detektieren. Die Kugel unterbricht die Lichtschranke rein physikalisch definitiv, da die Bahn auf der sie sich bewegt vorgegeben ist.
Kann es sein dass das Board einfach nicht schnell genug arbeitet? Ich habe schon hohe Baudraten probiert (siehe Code), damit konnte ich zumindest erreichen dass geschalten wird wenn ich die Kugel durch die Apparatur durchfallen lasse. Gibt es ein Bauteil welches besser für diese Anwendung geeignet wäre?
Vielen Dank
const int pinIRd = 8;
const int pinIRa = A0;
const int pinLED = 9;
int Trigger = 1;
int IRvalueA = 0;
int IRvalueD = 0;
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define LED_PIN 4
#define LED_COUNT 15
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Serial.begin(1000000);
pinMode(pinIRd,INPUT);
pinMode(pinIRa,INPUT);
pinMode(pinLED,OUTPUT);
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
strip.begin();
strip.show();
strip.setBrightness(255);
}
void loop() {
IRvalueA = analogRead(pinIRa);
IRvalueD = digitalRead(pinIRd);
if ((IRvalueA > 30) && (Trigger == 1)){ //IRvaluaA output ~25 in idle
//Turn on
for (int i=0; i <= LED_COUNT ; i++){
strip.setPixelColor(i,255,120,0);}
strip.show();
//Duration on
delay(40);
//Turn off
for (int i=0; i <= LED_COUNT ; i++){
strip.setPixelColor(i,0,0,0);}
strip.show();
Trigger = 0;
//delay(700);
}
if (IRvalueA < 30){
Trigger = 1;
}
}
@paulpaulson:
Geht es dir um die Noise/Data-Sache? Die Dioden sitzen in einem Gehäuse an einer Stelle welche kaum Fremdlicht reinlässt. Werd da aber trotzdem mal nachlesen, danke.
@my_xy_projekt:
Ja, aber ich halte den Code erst an, nachdem das Signal getriggert wurde?! Oder hab ich da einen groben Denkfehler drin?
disorder218:
Ja, aber ich halte den Code erst an, nachdem das Signal getriggert wurde?! Oder hab ich da einen groben Denkfehler drin?
wenn keine weitere Kugel kommt.
Ansonsten:
if (IRvalueA < 30)
{
Trigger = 1;
}
dürfte das (D)ein Problem sein.
Bau Dir mal einen Sketch, der fortlaufend den Wert aufnimmt -> Nicht auf dem SerMon ausgeben(!) und wenn die Kugel durch ist gib Dir die Werte aus.
Das wird je nach Aufbau einiges an Zeit und Aufwand kosten....
@my_xy_projekt:
"Wenn keine weitere Kugel kommt", ja richtig, der Intervall dazwischen ist groß genug, aber auch beim ersten Durchflug funktioniert es nicht. Dort sehe ich das Problem eher nicht.
Mit diesem "Trigger" will ich nur bezwecken dass pro Detektion (zB der Bleistift wie beschrieben) nur einmal ausgelöst wird, egal wie lange das IR-Signal blockiert wird. Ist für den Durchflug der Kugel aber sicher obsolet, ich werd das mal rausschmeißen und schauen ob das was ändert.
Wie nehme ich den Wert auf, wenn nicht mit dem Serial Monitor? Stecke noch nicht so tief in der Materie drin...
disorder218:
Mit diesem "Trigger" will ich nur bezwecken dass pro Detektion (zB der Bleistift wie beschrieben) nur einmal ausgelöst wird, egal wie lange das IR-Signal blockiert wird. Ist für den Durchflug der Kugel aber sicher obsolet, ich werd das mal rausschmeißen und schauen ob das was ändert.
Das ist Deine Einzige Aufnahme eines Signals.
Und dann sperrst Du.
if ((IRvalueA > 30) && (Trigger == 1)){ //IRvaluaA output ~25 in idle
Eine weitere / andere Signalaufnahme /-auswertung gibt es nicht.
Das kannst Du doch machen, indem Du die Änderung an der Lichtschranke auswertest.
Annahme in Ruhe LOW
Pseudocode:
bool oldLs = true;
// im loop
bool ls = lesenLichtschranke();
if (ls != oldLs) {
oldLs = ls;
if (ls) mache Was bei Start der Unterbrechung
else mache was beim Ende der Unterbrechung
}
Nochmal auf den Ansatz zurück:
90m/s == 9000cm/s == 90000mm/s == 90mm/ms
Bei einer 6mm Kugel passt die 15 Mal vollständig.
Das heisst, du musst sicherstellen, das 1/15ms sicher erkannt wird.
my_xy_projekt:
Nochmal auf den Ansatz zurück:
90m/s == 9000cm/s == 90000mm/s == 90mm/ms
Bei einer 6mm Kugel passt die 15 Mal vollständig.
Das heisst, du musst sicherstellen, das 1/15ms sicher erkannt wird.
Wie sieht Deine Voraussetzung dazu aus?
Das war ja unter anderem meine Frage, ob die Bauteile dafür überhaupt geeignet sind. Ich habe leider keine weitreichenden Kenntnisse was das angeht, nur grundlegende Programmierkenntnisse, grundlegendes technisches Verständnis und ich kann so halbwegs nach Anleitung Schaltungen löten. Dann hört es aber leider auch schon auf
disorder218:
Wie nehme ich den Wert auf, wenn nicht mit dem Serial Monitor? Stecke noch nicht so tief in der Materie drin...
Vielleicht mit dem Sketch unten.
Der misst einfach und schreibt die Werte fortlaufend in einen 256 Einträge langen Puffer. Da der Pufferindex ein Byte ist, läuft der automatisch um.
Es gibt einen Start-Trigger (wenn das Objekt in die Lichtschranke eintritt) und einen Stop-Trigger. Wenn der erfüllt ist wird der Puffer ausgegeben.
Getestet auf Uno mit Random als Signalgeber; den Überlauf habe ich damit aber nicht gesehen :(.
const int pinIRd = 8;
const int pinIRa = A0;
const int BUFFER_LEN = 256;
int IRvalueAbuffer[BUFFER_LEN];
byte IRvalueDbuffer[BUFFER_LEN];
byte bufferIndex = 0;
bool bufferOverflow = false;
// Hier Triggerschwelle für Analogwerte eintragen
const int SCHWELLE = 30;
bool kugelImLicht = false;
void setup()
{
Serial.begin(/* 115200 */ 1000000);
pinMode(pinIRd, INPUT);
pinMode(pinIRa, INPUT);
// randomSeed(analogRead(A5));
}
void printThreeDigitValue(int value)
{
if (value < 100)
Serial.print(' ');
if (value < 10)
Serial.print(' ');
Serial.print(value);
}
void loop()
{
IRvalueAbuffer[bufferIndex] = analogRead(pinIRa); // random(0, 100);
IRvalueDbuffer[bufferIndex] = digitalRead(pinIRd);
// Start-Trigger für "Kugel im Licht"
if (IRvalueAbuffer[bufferIndex] < SCHWELLE)
{
kugelImLicht = true;
}
// Stop-Trigger für "Kugel nicht im Licht" (durchgelaufen)
if (kugelImLicht && (IRvalueAbuffer[bufferIndex] >= SCHWELLE))
{
// Ist der Puffer wenigstens einmal vollgeschrieben worden?
if (bufferOverflow)
{
Serial.print(F("stop event triggered at buffer index "));
Serial.println(bufferIndex);
}
// buffer ausgeben
// Falls noch nie rundgelaufen: Nur bis zum aktuellen Index (das ist der wo der Stop-Trigger angeschlagen hat)
// Falls einmal vollgeschrieben: Der ganze Puffer
Serial.println(F("IDX A D "));
Serial.println(F("---------------"));
for (int count = 0; count <= (bufferOverflow ? 255 : bufferIndex); count++)
{
printThreeDigitValue(count);
Serial.print(F(" "));
printThreeDigitValue(IRvalueAbuffer[count]);
Serial.print(F(" "));
printThreeDigitValue(IRvalueDbuffer[count]);
Serial.println();
}
Serial.println(F("---------------"));
// Anhalten.
while (1);
}
bufferIndex++;
if (!bufferIndex)
bufferOverflow = true;
}
wno158:
Vielleicht mit dem Sketch unten.
Der misst einfach und schreibt die Werte fortlaufend in einen 256 Einträge langen Puffer. Da der Pufferindex ein Byte ist, läuft der automatisch um.
Es gibt einen Start-Trigger (wenn das Objekt in die Lichtschranke eintritt) und einen Stop-Trigger. Wenn der erfüllt ist wird der Puffer ausgegeben.
Getestet auf Uno mit Random als Signalgeber; den Überlauf habe ich damit aber nicht gesehen :(.
const int pinIRd = 8;
const int pinIRa = A0;
const int BUFFER_LEN = 256;
int IRvalueAbuffer[BUFFER_LEN];
byte IRvalueDbuffer[BUFFER_LEN];
byte bufferIndex = 0;
bool bufferOverflow = false;
// Hier Triggerschwelle für Analogwerte eintragen
const int SCHWELLE = 30;
bool kugelImLicht = false;
// Start-Trigger für "Kugel im Licht"
if (IRvalueAbuffer[bufferIndex] < SCHWELLE)
{
kugelImLicht = true;
}
// Stop-Trigger für "Kugel nicht im Licht" (durchgelaufen)
if (kugelImLicht && (IRvalueAbuffer[bufferIndex] >= SCHWELLE))
{
// Ist der Puffer wenigstens einmal vollgeschrieben worden?
if (bufferOverflow)
{
Serial.print(F("stop event triggered at buffer index "));
Serial.println(bufferIndex);
}
// buffer ausgeben
// Falls noch nie rundgelaufen: Nur bis zum aktuellen Index (das ist der wo der Stop-Trigger angeschlagen hat)
// Falls einmal vollgeschrieben: Der ganze Puffer
Serial.println(F("IDX A D "));
Serial.println(F("---------------"));
for (int count = 0; count <= (bufferOverflow ? 255 : bufferIndex); count++)
{
printThreeDigitValue(count);
Serial.print(F(" "));
printThreeDigitValue(IRvalueAbuffer[count]);
Serial.print(F(" "));
printThreeDigitValue(IRvalueDbuffer[count]);
Serial.println();
}
Serial.println(F("---------------"));
// Anhalten.
while (1);
}
bufferIndex++;
if (!bufferIndex)
bufferOverflow = true;
}
Super Idee, dass könnte damit funktionieren KARMA++
Super, zumindest ein Teilerfolg. Vielen Dank schon mal. Die Leds leuchten jetzt bei ungefähr 50% der durchgehenden Kugeln bei voller Geschwindigkeit auf.
Ich hab den Code für das Aufblitzen der LEDs wie folgt eingebunden, ich hoffe ich habe es halbwegs richtig verstanden und es ist nicht grob falsch (nicht "zitierte" Teile des Code bleiben unverändert):
[...]
// Ist der Puffer wenigstens einmal vollgeschrieben worden?
if (bufferOverflow)
{
Serial.print(F("stop event triggered at buffer index "));
Serial.println(bufferIndex);
for (int i=0; i <= LED_COUNT ; i++){
strip.setPixelColor(i,255,120,0);}
strip.show();
delay(40);
for (int i=0; i <= LED_COUNT ; i++){
strip.setPixelColor(i,0,0,0);}
strip.show();
}
[...]
Beim Test mit dem Bleistift hat der Code nur genau ein mal, beim ersten Unterbrechen funktioniert, danach nicht mehr, deswegen habe ich folgendes auskommentiert. Danach wurden mehrere Durchgänge erkannt.
// Anhalten.
//while (1);
Woran könnte es jetzt noch liegen dass nicht alle Durchgänge erkannt werden? Mit großer Wahrscheinlichkeit liegt das noch an meinem hinzugefügten Code?
Und nur nochmal dass es nicht untergeht: der delay(40); sollte kein Problem sein, oder? Der Intervall zwischen den Kugeln ist größer als 40ms.
Edit: Ich habe vorher versucht das Schalten der LEDs im Start-Trigger einzubinden, leider ohne Erfolg. Da steh ich auf dem Schlauch, weil das wäre ja sicher der sinnvollere Weg und würde eventuell das noch bestehende Problem beheben?!
Nun, fangen wir beim Einfachsten an:
Den while(1) wegzunehmen ist richtig, wenn es mehr als einmal funktionieren soll.
Dass nicht alle Durchgänge erkannt werden, kann grundsätzlich auch damit zusammenhängen, dass die Ausgabe der Messung auf die serielle Schnittstelle Zeit braucht und - das ist das eigentliche Problem - das Start-Trigger-Flag nicht zurückgesetzt wird - ich hatte das für nur einen Durchgang nach Reset ausgelegt.
Wenn Du nochmal meinen Sketch hernimmst und an der "Anhalten"-Stelle das Flag zurücksetzt, sollte eigentlich jeder Durchgang erkannt werden. Das System ist aber solange blind wie die Ausgabe dauert.
// Anhalten.
// while (1);
kugelImLicht = false;
So und dann kommen wir zu den LEDs:
So wie Du den Ausschnitt jetzt präsentiert hast, blitzt es nur, wenn der Puffer wenigstens einmal komplett vollgeschrieben wurde - Du hast den LED-Code in den Anweisungsblock eingefügt, der nur ausgeführt wird, wenn es mehr als 256 Messungen gegeben hat if (bufferOverflow) ....
Besser wäre es entweder vor dieser Bedingung oder aber wieder unten, wo jetzt das Flag zurückgesetzt wird.
In jedem Fall verlängert sich damit die blinde Zeit um die Zeit, die Du für die LEDs brauchst.
Allerdings:
Der Sketch war eigentlich nur zum Messen gedacht - um rauszubekommen, wie die Sensorwerte sich beim Durchlauf der Kugel verhalten. Für die Produktiv-Version mit Lichteffekt brauchst Du natürlich den Puffer nicht - da reicht eigentlich die Start/Stop-Bedingung. Das ist im Prinzip das, was Tommy oben vorgeschlagen hat.
Für das Auslesen der Werte im Serial Monitor kann ich die Kugel nur durchfallen lassen (montiert am Bestimmungsort kann ich kein Kabel anschließen, da wird mit Akku betrieben). Da hat es mir Werte von 23-25 geschrieben. Keinen über 30. Sollte das nicht aber eigentlich der Fall sein?
Den nächsten Test kann ich erst morgen vornehmen, dann melde ich mich wieder.
disorder218:
Okay, also sollte es klappen wenn ich den Code für die LEDs unter folgendem einfüge?! Also wie folgt?
Ja.
... Da hat es mir Werte von 23-25 geschrieben. Keinen über 30. Sollte das nicht aber eigentlich der Fall sein?
In Deinem ersten Sketch hast Du ~25 als Leerlaufwert (kein Objekt im Lichtstrahl) im Kommentar vermerkt. Dann würde das Resultat der Messung bedeuten, dass dieses System aus Hard- und Software die schnelle laufende Kugel wohl wirklich nicht zuverlässig detektieren kann - was my_xy_projekt in Post #10 schon befürchtet hat.
Genauer kann ich es auch nicht beurteilen.
disorder218:
Woran könnte es jetzt noch liegen dass nicht alle Durchgänge erkannt werden?
Es geht, wenn ich es richtig verstanden habe, um das Unterbrechen einer Lichtschranke durch eine Kugel. Welchen Sinn hat dann analogRead in diesem Zusammenhang? Das Unterbrechen ist doch ein rein digitales Ereignis, oder?
Mein Ansatz wäre die Verwendung eines Interrupts, das sollte zumindest theoretisch zuverlässig funktionieren:
wno158:
Dann würde das Resultat der Messung bedeuten, dass dieses System aus Hard- und Software die schnelle laufende Kugel wohl wirklich nicht zuverlässig detektieren kann - was my_xy_projekt in Post #10 schon befürchtet hat.
ICH würde mit einem Hallsensor und einem Magnet oder einer "Laserlichtschranke" probieren. Wenn die Kugel so präzise da durch macht, ist beides kein Problem.
Ich hatte letztens noch ne Gabellichtschranke mit 15mm im Auge, hab sie aber leider nicht mehr gefunden...