ich habe das Modell eines Kleinteilezählgerätes gebaut. Mit diesem sollen Normteile gezählt und in kleine Behälter gefüllt werden.
Der Aufbau ist folgender:
Drehteller 1 oben zum separieren der Normteile angetrieben durch Steppermotor 1
Lasersensor (Sender & Empfänger) zum zählen der separierten Teile
Drehteller 2 unten für die fertig abgezählten VEs
Funktionsbeschreibung:
Einstellung der abzuzählenden Menge am Adafruit LCD Shield 16x2 Zeichen 2 x I2C Pins
Bestätigung über Taster (Es geht los)
Drehteller 1 setzt sich in Bewegung und separiert die Normteile
Laser zählt die Stückzahl hoch, wenn Stückzahl erreicht stoppt Drehteller 1
Nach Füllung des Auffangbehälters dreht Drehteller 2 30 Grad weiter (12 Behälter)
dann setzt sich Drehteller 1 wieder in Bewegung und das Spiel beginnt von vorn bis die Anzahl der programierten Wiederholung (12) erreicht ist.
Stellt der Laser wärend der Schritte 5 und 6 keinen Durchlauf fest, dreht der Teller 1 kurz und schnell im Urzeigersinn zurück um Verstopfungen und Verhakungen aufzulösen.
Nun habe ich im Internet eine Seite entdeckt, da hat jemand einen Vibrationsförderer mit dem Arduino verbunden, und einen Code eingestellt. Der schaltet nach erreichen der eingestellten Menge ein Relais.
Bei mir arbeiten zwei A4988 und zwei NEMA17 1.5A 17HS4401.
Die Zählung erreiche ich mit einem Linienlaser und vier in Reihe geschalteten Fotowiderständen.
Um nun alles einzeln funktionierenden Abläufe miteinander zu verknüpfen fehlt mir jegliche Erfahrung.
Kurz, ich benötige Eure Hilfe, gern auch gegen Gebühr.
#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
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
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
int pwr = 13; // power pin to vibration on/off relay
void setup()
{
pinMode(signalPin, INPUT); // set up the switch pin as an input
pinMode(pwr, OUTPUT); // set pwr pin to output
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
}
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();
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
}
if (buttons & BUTTON_DOWN && set >= 1) // if "DOWN" button is pressed
{
set = set - 1; // decrease "set value by one
delay(del); //debounce
}
if (buttons & BUTTON_RIGHT && set <= 989) // if "RIGHT" button is pressed
{
set = set + 10; // increase "set" value by ten
delay(del); // debounce
}
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
{
digitalWrite(pwr, HIGH); // start vibration
delay(del); // debounce
}
}
switchState = analogRead(signalPin); // check the status of the photointerrupt
if (switchState != prevSwitchState) // compare the switchState to its previous state
{
if (switchState == LOW) // if photointerrupt detects a part
{
qty = qty + 1; // increment part count by one
delay(20); // debounce
}
}
{
if (qty == set)
{
delay(400); // delay to clear ramp of counted pieces before stopping vibration.
digitalWrite(pwr, LOW); // stop vibration
qty -= qty; // reset counted part quantity
lcd.setCursor(14, 1);
lcd.print(" "); // write LCD qty zero
}
prevSwitchState = switchState; // reset photointerrupt's state
}
}
Hat da eine super intelligente Maschine void setup grammatisch richtig übersetzt? Das wieder rückgängig zu machen helfe ich auf keinen Fall. Mit solchen Maschinen fange ich keinen Streit an.
Punkte 5/6 ist ja sehr ähnlich zu 1-4 nur mit anderen Daten: statt Zähler die Fertigmeldung des unterlagerten Schritt 4 und als Anzahl nicht die in deinem Eingabegerät eingestellte Zahl sondern die feste 12.
Der Sketch kam meinen Anforderungen am nächsten.
Allerdings gibt es da nur einen Motor welcher per Relais geschaltet wird.
Lass ich den (das) Sketch durchlaufen, kann ich die Menge wählen und es findet auch eine Zählung bis zur eingestellten Menge statt. Ist diese erreicht, beginnt die Zählung bei 0. Der Teil funktioniert also.
Nun muß jedoch die Relaisschaltung für einen DC Motor gegen zwei A4988 Schaltungen für Steppermotoren ausgetauscht werden. Und hier fehlt mir das benötigte Wissen.
Den ersten Beitrag schrieb ich am PC, nun bin ich unterwegs und hab mich in Ermangelung der Einlogdaten neu im Forum angemeldet. Will doch Eure Beiträge kommentieren und nicht bis morgen warten müssen.
Transparenz ist das Alpha und Omega guter Kommunikation!
Ich bin unbezahlbar
Meine Anmerkungen:
Mir erschließt sich nicht, warum Drehteller 1 mit einem Schrittmotor angetrieben werden soll. Ein DC-Motor mit H-Brücke zur Richtungsumkehr täte es auch.
Zum Antrieb von Drehteller 2 schreibst Du hingegen nichts. Der positioniert die Behälter, weshalb ein Schrittmotor sinnvoll ist.
Zur Ansteuerung von Schrittmotoren empfehle ich die Bibliothek MobaTools, zu installieren über der Bibliotheksverwalter der IDE.
delay() mußt Du aus Deinen Programmen verbannen, verträgt sich nicht mit Echtzeitanwendungen.
Vom Adafruit LCD Shield lese ich in diesem Forum das erste Mal, da könnte die Unterstützung dünn sein. Ich hoffe, ich irre!
Willst Du wirklich diese Miniaturtaster für eine produktive Maschine einsetzen? Dann könnte ich mit meinen Wurstfingern nicht bei Dir arbeiten
@mariob77 ... mich wundert ja dass dein Sketch nur annährnd das machst was du brauchst. Aber generelle Taktik wäre, die einzelnen Schritte die du in #1 beschrieben hast in einzelnen Funktionen auszulagen, jede Funktion einzeln zu testen und dann stückchenweise mit einer "Finite Stat Machine" der Reihe nach aufrufen zu lassen bzw. dieser FSM den Ablauf zu überlassen.
Ein logisches Schaltbild,
einen Programmablauf zeichnen,
dann einen Code machen.
Bist Du Dir da sicher? Ohne Getriebe wird das nix mit hohem Drehmoment, und dann kann man auch einen DC Motor statt Stepper nehmen. Im Stillstand schaltet man den DC Motor einfach ab, während der Stepper dann den meisten Strom zieht.
Bei der Positionierung würde ich mich auch nicht auf den Schrittmotor verlassen, dafür sollte an jeder Position ein Bündig-Schalter benutzt werden, wie bei Aufzügen. Dafür genügt 1 Schalter und Nocken am Drehteller die mechanisch oder optisch abgetastet werden. Einen Schalter brauchst Du auch beim Stepper, für die Anfangsposition, das wird auch nicht einfacher als mit dem DC Motor.
Dann packe die einzelnen Schritte jeweils in ein Unterprogramm, das sich einzeln austesten läßt. Zuletzt werden diese Schritte im fertigen Programm der Reihe nach aufgerufen.
es ist üblich und völlig normal, das man eine neue Coderversion in einem neuen Posting postet.
Als Code-Section verbraucht es nicht viel Bildschirmhöhe.
Nach dem reinen "funktioniert die Baugruppe?"-Test mit einem Breadboard
steige ich auf Lochrasterplatine mit Buchsen/Stiftleisten-Steckverbindungen um.
Da ist mir persönlich der Drahtverhau auf einem Breadboard zu "lose"
Vor allem wenn auch noch Mechanik mit dabei ist.
Wenn man da immer so gaaanz vorsichtig anfassen muss wie beim Entschärfen einer Bombe
mag ich das nicht.
Ansonsten stimme ich zu. Jede Teilfunktion in eine eigene function diese Teilfunktion austesten
dann kommt die nächste.
vgs
Hallo,
Ich Danke Euch für Eure Unterstützung.
Nun läuft das ganze wie es soll.
Feinheiten sind noch einzustellen, wie die Motorgeschwindigkeit oder die Empfindlichkeit der Fotowiderstände.
Ich hab jetzt 12x case /state & break verwendet. Die schließenden Klammern am Ende sind noch suboptimal.
#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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 2;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 3;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 4;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 5;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 6;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 7;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 8;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 9;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 10;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 11;
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
if (qty < set) {
delay(2000);
MotorOben.setSpeed( 300 );
MotorOben.rotate( 1 );
state = 12;
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
break;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}