Warum schwanken eigentlich die Werte der Fotowiderstände so stark, mal 120 und beim nächsten Start 440. Muß wohl doch von analog auf digitalpin umsteigen
mag sein das der code läuft.
Du hast jetzt alle codezeilen in loop reingepackt.
Damit wird das Programm sehr unübersichtlich. Das hat wenig Zeit gekostet um es so zu schreiben.
Aber es wird um so mehr Zeit kosten wieder etwas am Programm zu ändern.
Keine functions zu benutzen macht die Wartung / Weiterentwicklung deines Programms schwieriger, umständlicher und fehleranfälliger.
Aber anscheinend muss jeder Newcomer diese Erfahrung am eigenen Lieb erleben, das es laaange dauert bis so ein non-functions-programm geändert / angepasst ist und wie umständlich es ist da Fehler zu suchen.
Man kann den großen Festsaal 10m x 20m auch mit der Zahnbürste bohnern. Es dauert halt laaange. Wer Profi werden will fragt den Hausmeister
"Gibt es eine Bohnermaschine? " und "Wo finde ich die Bedienungsanleitung für die Bohnermaschine?"
Dann liest er 30 Minuten in der Bedienungsanleitung (das ist ja verschwendete Zeit weil man ja noch gar nicht am bohnern ist!) Und dann ist die 10m x 20m Fläche in 20 Minuten gebohnert.
Fertig nach 50 Minuten.
Der Zahnbürstler hat nach 50 Minuten erst 1m x 2m geschafft.
Du hast jetzt vermutlich so einen Mittelweg gewählt. Nachlesen wie geht switch-case und dann losprogrammiert. Das mit den functions lohnt sich wenn man später Änderungen machen will.
vgs
Die reagieren auf alles Licht, nicht nur auf das was sie sollen. Bei IR Fernbedienung nimmt man deshalb ein Trägersignal von 38kHz, das sich relativ einfach von konstantem Fremdlicht unterscheiden läßt.
Mir ist nicht klar was Du da machst. Laser und Fotowiderstände kommt mir vor wie ein Ferrari in der 30er Zone.
Wahrscheinlich hast Du einfach soviel Klammern gesetzt, bis der Compiler zufrieden war. So funktioniert das aber nicht. Die Klammern fehlen nicht am Ende sondern zwischendurch fehlen haufenweise schließende Klammern. Das bringt auch die ganze Logik durcheinander. Die Klammern sind nicht nur 'Schönheit'.
Drück mal ctrl-T. Dann siehst Du das.
Alle 'case' sollten in einer Ebene liegen.
Edit: Sowas:
if (qty == set) {
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set) {
ist auch ziemlicher Unsinn ( kommt mehrfach vor)
Edit: Der Compiler wird das wohl mit seiner Optimierung 'glattziehen' ![]()
Ich habe Dir mal ein paar Klammern spendiert, möglicherweise war ich aber zu freigiebig, mußt Du probieren:
#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
#include <MobaTools.h>
const byte stepPin = 3;
const byte dirPin = 2;
const byte stepPin1 = 5;
const byte dirPin1 = 4;
const int stepsPerRev = 200; // Steps per revolution - may need to be adjusted
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
MoToStepper MotorOben( stepsPerRev, STEPDIR ); // create a stepper instance
MoToStepper MotorUnten( stepsPerRev, STEPDIR ); // create a stepper instance
int qty = 0; // quantity of parts counted
int del = 50; // global debounce duration for buttons
int set = 0; // user input number of parts to be counted
byte state = 0;
uint8_t i = 0; // reads button input
const int signalPin = A0; // set up a constant for the photointerrupt signal pin
int switchState = 0; // variable to hold the value of the switchPin
int prevSwitchState = 0; // variable to hold previous value of the switchpin
void setup()
{
MotorOben.attach( stepPin, dirPin );
MotorOben.setSpeed( 1000 ); // 30 rev/min (if stepsPerRev is set correctly)
MotorUnten.attach( stepPin1, dirPin1 );
MotorUnten.setSpeed( 1000 ); // 30 rev/min (if stepsPerRev is set correctly)
pinMode(signalPin, INPUT); // set up the switch pin as an input
lcd.begin(16, 2); // set up the LCD's number of columns and rows
lcd.setCursor(0, 0);
lcd.print("SET QTY"); // print LCD column headers
Serial.begin(9600);
}
void loop()
{
lcd.setCursor(0, 1);
lcd.print(set); // print "set" to LCD
lcd.setCursor(13, 1);
lcd.print(qty); // print "qty" to LCD
uint8_t buttons = lcd.readButtons();
switchState = analogRead(signalPin);
Serial.println("aktueller Wert: " + String(switchState));
if (buttons)
{ // if any button is pressed
lcd.setCursor(0, 1);
lcd.print(" "); //clear LCD bottom row for new values
if (buttons & BUTTON_UP && set <= 998)
{ // if "UP" button is pressed
set = set + 1; // increase "set" value by one
delay(del); // debounce
}
else if (buttons & BUTTON_DOWN && set >= 1)
{ // if "DOWN" button is pressed
set = set - 1; // decrease "set value by one
delay(del); //debounce
}
else if (buttons & BUTTON_RIGHT && set <= 989)
{ // if "RIGHT" button is pressed
set = set + 10; // increase "set" value by ten
delay(del); // debounce
}
else if (buttons & BUTTON_LEFT && set >= 10)
{ // if "LEFT" button is pressed
set = set - 10; // increase "set" value by ten
delay(del); // debounce
}
if (buttons & BUTTON_SELECT)
{ // if "SELECT" button is pressed
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 1;
}
}
switch (state) {
case 0:
//Nix, warten auf Go Button
break;
case 1:
switchState = analogRead(signalPin);
Serial.println("aktueller Wert: " + String(switchState));
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 2;
} // <= fehlt
break;
case 2:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 3;
} // <= fehlt
break;
case 3:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 4;
} // <= fehlt
break;
case 4:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set) {
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set) {
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 5;
} // <= fehlt
break;
case 5:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set) {
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 6;
} // <= fehlt
break;
case 6:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 7;
} // <= fehlt
break;
case 7:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 8;
} // <= fehlt
break;
case 8:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 9;
} // <= fehlt
break;
case 9:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 10;
} // <= fehlt
break;
case 10:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 11;
} // <= fehlt
break;
case 11:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
if (qty < set)
{
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 12;
} // <= fehlt
break;
case 12:
switchState = analogRead(signalPin);
if (switchState > 600)
{ // if photointerrupt detects a part
qty = qty + 1; // increment part count by one
delay(50); // debounce
}
if (qty == set)
{
delay(0); // delay to clear ramp of counted pieces before stopping vibration.
MotorOben.stop( );
}
if (qty == set)
{
delay(100); // delay to clear ramp of counted pieces before stopping vibration.
MotorUnten.doSteps( -500 );
qty -= set; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
} // <= fehlt
break;
}
}
Der Linienlaser wirft sein Licht knapp über die Oberfläche des Abwurfschachtes auf 4 Fotowiderstände. Das Teil rutscht an den Dioden vorbei verdeckt dabei teilweise den Laserstrahl und verändert den Widerstand.
Dieser schwankt jedoch beim Leerlauf sehr stark.
Alternativ hab ich noch diese hier:
Die geben nur HIGH oder LOW zurück.
Vielleicht besser geeignet da eindeutiger?
poste mal ein Foto auf der man die Details der Stelle sehen kann an der du die Muttern zählst.
Sind die Muttern grundsätzlich aus Stahl?
Oder willst du auch welche aus Alu, Messing und Kunststoff durch die Maschine laufen lassen?
Wenn die immer aus Stahl sind dann würde ich einen induktiven Näherungssensor nehmen.
Sonst eine richtige Lichtschranke mit Sender und Empfänger.
Aber ich kann mir nicht vorstellen wie die Maschine an deiner Zählstelle aussieht
Deshalb ein Foto posten.
Wenn es schon super-lowcost sein muss dann würde ich superhelle LEDs nehmen.
mit Abstrahlwinkel 15 grad
Die LED in ein Kunststöffröhrchen um den Abstrahlwinkel weiter einzuengen.
Und einen Fototransistor (Gehäuse wie LED also nicht seitlich wie das Modul von Amazon).
der auch in ein schwarzes Röhrchen gesteckt wird damit er nur Licht aus einer Richtung empfangen kann.
vgs

Viel kann man nicht erkennen, auf dem ersten Bild den Laser, der auf die Fotowiderstände trifft.
Die vier Widerstände sind in Reihe geschaltet.
Es sollen auch Edelstahl & Kunststoff zahlbar sein.
Erst fielen die Teile im Freien Fall durch den Laservorhang, nach Umbau ist der Schacht jetzt in der Neigung verstellbar und die Teile rutschen vorbei.
Aha. hm.....
Edelstahl, Kunststoff. Also induktiver Näherungssensor fällt flach.
Die Teile stammen aus einem 3D-Drucker also muss es 3D-Dateien von den Bauteilen geben.
Kannst du die im Schnitt darstellen?
Oder mal einen handskizzierten geschnittenen Querschnitt?
Rutschen die Muttern einzeln durch? Oder kann es vorkommen das da zwei Muttern gleichzeitig unterwegs sind?
Was ist die kleinste Größe an Muttern?
Was haben diese kleinsten Muttern für eine Höhe?
Grundidee: Lichtschranke die von den vorbeirutschenden Muttern unterbrochen wird.
Fotowiderstände sind nicht das gelbe vom Ei wenn es um Lichtschranken geht.
Da nimmt man Fototransistoren oder Fotodioden.
Fotowiderstände ändern ihren Widerstand reativ langsam. Mit Fotowiderständen kann man 1000 Hz nicht detektieren. Für Fototransistoren ist das kein Problem.
Kann man den Linienlaser mit hoher Frequenz = 1000 Hz bis 50 kHz ein/ausschalten?
Durch das gepulste Signal kann man die Lichtschranke unempfindlich gegenüber Umgebungslicht machen. Nur wenn der Fototransistor mit der passenden Frequenz schaltet wird "Licht kommt an gemeldet"
Du hast ein Gehäuse drum herum da ist also eigentlich nicht viel mit Umgebungslicht.
Sollte auch so gehen.
vgs
Die Muttern sind immer einzeln und die kleinste Größe ist M2 Breite 4mm Höhe 1,5mm.
Gängig ist aber ab M4 Breite 7mm Höhe 3mm.
Durch das Gehäuse ist alles gut abgedunkelt. Trotzdem schwanken die Ausgangswerte der Widerstände schon nach dem Einschalten sehr stark
Das könnte auch an der Temperatur oder Verkabelung liegen.
So jetzt habe ich das mal mit IronCad nachgebastelt.
Stelle ich mir das so richtig vor?
Der Linienlaser streicht so knapp über die Oberfläche und wenn eine Mutter durchläuft wird ein Teil des Laserstrahls abgedeckt?
Ich habe jetzt gleich eine M2-Mutter reingesetzt.
Mag sein, das der Linienlaser irgendwie anders sitzt.
Noch knapper über dem "Rutschboden" oder weiter oben?
Sitzen die Fotowiderstände mit dem unteren Ende knapp über dem Boden
oder weiter oben/unten?
Umgebungslicht wird ja abgehalten. Aber der Linienlaser leuchtet ja den Innenraum gut aus.
Gibt das überhaupt einigermaßen Widerstandsänderung?
Weil die Mutter ja immer nur einen Teil des Lichtstrahls abdeckt?
Ich würde sagen ein ganz scharf gebündelter Lichtstrahl von 0,5mm Durchmesser
und ein einzelner Fototransistor auf der gegenüber liegenden Seite ergibt Randbedingungen
bei denen der Lichtstrahl vollständig unterbrochen wird. Den Lichtstrahl auf 0,5mm bekommen geht entweder über eine Lochblende mit so einem dünnen Loch oder mit einem Lasermodul bei dem man den Focus einstellen kann.
Und wenn der Laser ganz links sitzt und der Fototransistor rechts dann wird der Lichtstrahl auf jeden Fall unterbrochen egal wo die Mutter vorbeikommt.


einzelner scharf gebündelter Laserstrahl
vgs
Mensch Stefan,
da hast Du Dir ja richtig Arbeit gemacht.
So wie die oberen drei CADs sieht es im Moment aus. Die Fotowiderstände sitzen mittig knapp über der Oberfläche. Der Laser trifft die vier Stück genau mittig.
So wie auf dem unteren CADs wäre noch einen Versuch wert, dann gehen mir die Ideen aus.
Ich werf mal was in den Raum.
Kein mir bekanntes (Klein-)Teile-(Sortier-/)ZählSystem auf Basis von Normteilen arbeitet mit einem Durchlaufsensor zur Feststellung der Anzahl der tatsächlichen Teile.
Bau je eine Wägezelle unter Deine Schalen. Alternativ als Gesamtgewichtnehmer unter den sich drehenden Teller.
Das "Normteil" hat bei der Sollmenge ein Gewicht.
Als Toleranz werden +-50% eines Normteiles genommen.
So werden zuverlässig Fischstäbchen verpackt, genauso wie Gummibärchen oder Schrauben und Muttern.
Fertig.
Ich habe mir so eine Wiegezelle mitsamt Wiegeteller und AD-Wandler gekauft
https://www.ebay.de/itm/164725507990
Hat aufs Gramm genau das gleiche gewogen wie die Küchenwaage.
Was wiegt eine einzelne Mutter M2,5?
Habe diese Angabe dazu gefunden
M2,5 2,0 mm 0,024 Kg/ 100 Stück
24g / 10 Stück = 0,24g pro Stück. Da kommt so eine preiswerte Wiegezelle nicht mehr mit.
Selbst durchgeführte Überschlagsrechnung
Mutter M2
Zylindervolumen pi * d^2 / 4 * h mal Dichte von Stahl 7850g/dm³
3.14 * (0.044 dm)^2 / 4 * 0.016 dm * 7850 g / dm³ = 0,19 g kommt hin.
Klar können Profiwiegegeräte für M2-Muttern hundertstel Gramm Wiegen
Aber dann kostet die Wiegezelle wahrscheinlich auch 100 Euro.
vgs
Naja, um was geht es denn hier?
Wenn ich mich schon damit beschäftige einen Trommelseparator zu bauen, dann habe ich mehr vor, als mit einem 0815/4711 ichHabeNixBesseresAlsChinaPreise zu händeln.
Siehe auch hier: Hx711 Genauigkeit - #6 by nix_mehr_frei
Ich schreibe es gerne noch einmal:
Selbst Gummibären oder Fischstäbchen werden in der Industrie so verfüllt.
Da werden sogar mehrere Linien gleichzeitig gefahren und aus allen Linien wird dann ein Mix erstellt, der IMMER in Summe der Anforderung entspricht.
Selbst wenn der TO kein Budget nennt für
sind HX711 mit 5Kg eindeutig das falsche einer Grundlage zur Bewertung der Zuverlässigkeit.
Eine Küchenwaage sollte das können, einen Körperwaage bis 200kg natürlich nicht. Beides dürften handelsübliche und entsprechend preiswerte Artikel (unter 10€) sein.
Hm also dann eher so eine mit 0 bis 100g
https://www.ebay.de/itm/153282497983
die ist ohne HX711-AD-Wandler.
Passen diese HX711-Platinen ohne Anpassungen and nahezu jede Wägezelle?
Hat da jemand Erfahrung damit?
vgs
Das war mein erster Ansatz.
Da ich keine Wägezelle mit so fei er Auflösung fand, hab ich mir so eine Feinwaage bestellt:
Da mir die mechanischen Abläufe zu kompliziert erschienen, habe ich mich aufs Zählen versteift.
Beim Zählen wird es aber wohl kaum einen Universalzähler geben, sondern nur Zähler für ganz bestimmte Teile (Flaschen, Münzen...). So könntest Du mit einer Art Zahnrad die Teile vereinzeln und zählen, welche der vorbeilaufenden Abteile gefüllt sind. Bei Teilen, die sich miteinander verhaken oder verkleben (Gummibärchen) können, wirst Du Dich mit Zählen sowieso schwer tun.






