Entonces necesitamos una fuente de alimentación de 12V, con al menos 2 amperios. Necesitamos los 12V para los dos motores paso a paso, así como las tiras de luces LED que luego colocaré en la puerta principal. Sin embargo, para todos los demás componentes necesitamos 5 V, por lo que utilicé un convertidor reductor para reducir los 12 V a 5 V. Los servomotores de rotación continua DS04-NFC se alimentan con 5 V y se controlan a través de señales PWM provenientes de la placa Arduino, mientras que los motores paso a paso se controlan a través de los controladores A4988. Los cuatro botones y los dos microinterruptores están conectados a tierra y a los pines digitales de Arduino, por lo que al usar las resistencias internas de la placa Arduino podemos detectar fácilmente cuándo se presionan.
Puede obtener los componentes necesarios para este tutorial de Arduino desde los siguientes enlaces:
Conecté los componentes electrónicos usando algunos cables de salto. Se volvió un poco desordenado con tantos cables, pero todo funcionó correctamente. Al final coloqué dos tiras de luces LED en el panel de la puerta para iluminar el interior de la máquina expendedora.
Código Arduino
Lo que queda ahora es programar el Arduino y aquí está el código que hice para este proyecto. Debajo de esto hay una descripción del código.
/* DIY Vending Machine - Arduino based Mechatronics Project
by Dejan Nedelkovski, www.HowToMechatronics.com
*/
#include <LiquidCrystal.h> // includes the LiquidCrystal Library
#include <Servo.h>
LiquidCrystal lcd(27, 26, 25, 24, 23, 22); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7)
Servo servo1, servo2, servo3, servo4; // DS04-NFC motors
// Stepper motors pins
#define dirPinVertical 0
#define stepPinVertical 1
#define dirPinHorizontal 2
#define stepPinHorizontal 3
#define coinDetector 9
#define button1 13
#define button2 12
#define button3 11
#define button4 10
#define microSwitchV 15
#define microSwitchH 14
int buttonPressed;
void setup() {
lcd.begin(16, 2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display
servo1.attach(4);
servo2.attach(5);
servo3.attach(6);
servo4.attach(7);
pinMode(dirPinVertical, OUTPUT);
pinMode(stepPinVertical, OUTPUT);
pinMode(dirPinHorizontal, OUTPUT);
pinMode(stepPinHorizontal, OUTPUT);
pinMode(coinDetector, INPUT);
// Activating the digital pins pull up resistors
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
pinMode(button3, INPUT_PULLUP);
pinMode(button4, INPUT_PULLUP);
pinMode(microSwitchV, INPUT_PULLUP);
pinMode(microSwitchH, INPUT_PULLUP);
// Vertical starting position
digitalWrite(dirPinVertical, HIGH); // Set the stepper to move in a particular direction
while (true) {
if (digitalRead(microSwitchV) == LOW) { // If the micro switch is pressed, move the platfor a little bit up and exit the while loop
moveUp(70);
break;
}
// Move the carrier up until the micro switch is pressed
digitalWrite(stepPinVertical, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinVertical, LOW);
delayMicroseconds(300);
}
// Horizontal starting position
digitalWrite(dirPinHorizontal, LOW);
while (true) {
if (digitalRead(microSwitchH) == LOW) {
moveLeft(350);
break;
}
digitalWrite(stepPinHorizontal, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinHorizontal, LOW);
delayMicroseconds(300);
}
}
void loop() {
// Print "Insert a coin!" on the LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Insert a coin!");
// Wait until a coin is detected
while (true) {
if (digitalRead(coinDetector) == LOW) { // If a coin is detected, exit the from the while loop
break;
}
}
delay(10);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select your item");
lcd.setCursor(0, 1);
lcd.print(" 1, 2, 3 or 4?");
// Wait until a button is pressed
while (true) {
if (digitalRead(button1) == LOW) {
buttonPressed = 1;
break;
}
if (digitalRead(button2) == LOW) {
buttonPressed = 2;
break;
}
if (digitalRead(button3) == LOW) {
buttonPressed = 3;
break;
}
if (digitalRead(button4) == LOW) {
buttonPressed = 4;
break;
}
}
// Print "Delivering..."
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Delivering...");
// Depending on the pressed button, move the carrier to that position and discharge the selected item
switch (buttonPressed) {
case 1:
// Move the container to location 1
moveUp(4900); // Move up 4900 steps (Note: the stepper motor is set in Quarter set resolution)
delay(200);
moveLeft(1700); // Move left 1700 steps
delay(300);
// Rotate the helical coil, discharge the selected item
servo1.writeMicroseconds(2000); // rotate
delay(950);
servo1.writeMicroseconds(1500); // stop
delay(500);
// Move the container back to starting position
moveRight(1700);
delay(200);
moveDown(4900);
break;
case 2:
// Move the container to location 2
moveUp(4900);
delay(200);
// Rotate the helix, push the selected item
servo2.writeMicroseconds(2000); // rotate
delay(950);
servo2.writeMicroseconds(1500); // stop
delay(500);
moveDown(4900);
break;
case 3:
// Move the container to location 3
moveUp(2200);
delay(200);
moveLeft(1700);
delay(300);
// Rotate the helix, push the selected item
servo3.writeMicroseconds(2000); // rotate
delay(950);
servo3.writeMicroseconds(1500); // stop
delay(500);
// Move the container back to starting position
moveRight(1700);
delay(200);
moveDown(2200);
break;
case 4:
// Move the container to location 4
moveUp(2200); // Move verticaly 4800 steps
delay(200);
// Rotate the helix, push the selected item
servo4.writeMicroseconds(2000); // rotate
delay(950);
servo4.writeMicroseconds(1500); // stop
delay(500);
moveDown(2200);
break;
}
lcd.clear(); // Clears the display
lcd.setCursor(0, 0);
lcd.print("Item delivered!"); // Prints on the LCD
delay(2000);
}
// == Custom functions ==
void moveUp (int steps) {
digitalWrite(dirPinVertical, LOW);
for (int x = 0; x < steps; x++) {
digitalWrite(stepPinVertical, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinVertical, LOW);
delayMicroseconds(300);
}
}
void moveDown (int steps) {
digitalWrite(dirPinVertical, HIGH);
for (int x = 0; x < steps; x++) {
digitalWrite(stepPinVertical, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinVertical, LOW);
delayMicroseconds(300);
}
}
void moveLeft (int steps) {
digitalWrite(dirPinHorizontal, HIGH);
for (int x = 0; x < steps; x++) {
digitalWrite(stepPinHorizontal, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinHorizontal, LOW);
delayMicroseconds(300);
}
}
void moveRight (int steps) {
digitalWrite(dirPinHorizontal, LOW);
for (int x = 0; x < steps; x++) {
digitalWrite(stepPinHorizontal, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinHorizontal, LOW);
delayMicroseconds(300);
}
}
Code language: Arduino (arduino) Explicación del código fuente
Primero, debemos incluir las bibliotecas Servo y LiquidCrystal, definir los pines de la pantalla LCD, los cuatro servomotores, los pines de los motores paso a paso, el detector de monedas, así como los cuatro botones y los dos microinterruptores.
En la sección de configuración, configuramos los modos de pin para cada uno de los pines mencionados anteriormente. Podemos notar que para los botones y los pines de los micro interruptores activamos las resistencias pull up internas. Esto significa que el nivel lógico en estos pines será ALTO todo el tiempo, y una vez que los presionemos, el nivel lógico caerá a BAJO.
Antes de ingresar al bucle principal, también configuramos el transportador en su posición inicial, que está definida por los dos microinterruptores. Entonces, con el ciclo while seguimos moviendo el transportador a su posición inicial y una vez que se presionen los dos microinterruptores, los motores se detendrán y se moverán a la posición inicial deseada.
// Vertical starting position
digitalWrite(dirPinVertical, HIGH); // Set the stepper to move in a particular direction
while (true) {
if (digitalRead(microSwitchV) == LOW) { // If the micro switch is pressed, move the platfor a little bit up and exit the while loop
moveUp(70);
break;
}
// Move the carrier up until the micro switch is pressed
digitalWrite(stepPinVertical, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinVertical, LOW);
delayMicroseconds(300);
}
// Horizontal starting position
digitalWrite(dirPinHorizontal, LOW);
while (true) {
if (digitalRead(microSwitchH) == LOW) {
moveLeft(350);
break;
}
digitalWrite(stepPinHorizontal, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinHorizontal, LOW);
delayMicroseconds(300);
}
Code language: Arduino (arduino)
En el programa principal, comience imprimiendo en la pantalla LCD el mensaje "Inserte una moneda". Entonces nos quedamos atrapados en el bucle while. Una vez que inserte una moneda y pase cerca del sensor de proximidad, el estado lógico en el pin del detector de monedas caerá a BAJO y, en ese caso, saldremos del ciclo while usando la instrucción break.
// Wait until a coin is detected
while (true) {
if (digitalRead(coinDetector) == LOW) { // If a coin is detected, exit the from the while loop
break;
}
}
Code language: Arduino (arduino)
Luego imprimimos el mensaje "Seleccione su artículo" y nos quedamos atascados en otro bucle while.
// Wait until a button is pressed
while (true) {
if (digitalRead(button1) == LOW) {
buttonPressed = 1;
break;
}
if (digitalRead(button2) == LOW) {
buttonPressed = 2;
break;
}
if (digitalRead(button3) == LOW) {
buttonPressed = 3;
break;
}
if (digitalRead(button4) == LOW) {
buttonPressed = 4;
break;
}
}
Code language: Arduino (arduino)
Este ciclo while espera a que presionemos cualquiera de los cuatro botones, y una vez que lo hacemos salimos de él e imprimimos el mensaje "Delivering".
Ahora, dependiendo del botón presionado, ejecutamos uno de los casos en la declaración de cambio. En caso de que hayamos presionado el primer botón, el transportista comenzará a moverse hacia arriba utilizando la función "moveUp()" personalizada.
switch (buttonPressed) {
case 1:
// Move the container to location 1
moveUp(4900); // Move up 4900 steps (Note: the stepper motor is set in Quarter set resolution)
delay(200);
moveLeft(1700); // Move left 1700 steps
delay(300);
// Rotate the helical coil, discharge the selected item
servo1.writeMicroseconds(2000); // rotate
delay(950);
servo1.writeMicroseconds(1500); // stop
delay(500);
// Move the container back to starting position
moveRight(1700);
delay(200);
moveDown(4900);
break;
}
Code language: Arduino (arduino)
Si echamos un vistazo a esta función, podemos ver que simplemente configura el motor paso a paso para que se mueva en una dirección particular y realiza la cantidad de pasos que ingresamos como argumento.
void moveUp (int steps) {
digitalWrite(dirPinVertical, LOW);
for (int x = 0; x < steps; x++) {
digitalWrite(stepPinVertical, HIGH);
delayMicroseconds(300);
digitalWrite(stepPinVertical, LOW);
delayMicroseconds(300);
}
}
Code language: Arduino (arduino)
Podemos notar aquí que configuré el controlador paso a paso A4988 para que funcionara en una resolución de un cuarto de paso, y con algunas degustaciones llegué a la conclusión de que necesitaba 4900 pasos para que el operador llegara a la posición superior. De manera similar movemos el transportador hacia la izquierda hasta llegar a la ubicación número 1.
Acto seguido giramos el motor de rotación continua durante 950 milisegundos para que la bobina helicoidal haga un ciclo completo.
// Rotate the helical coil, discharge the selected item
servo1.writeMicroseconds(2000); // rotate
delay(950);
servo1.writeMicroseconds(1500); // stop
Code language: Arduino (arduino)
Tenga en cuenta aquí que estos valores a veces pueden variar y depende del motor en sí. Usando las funciones personalizadas moveRight() y moveDown(), llevamos el transportador de vuelta a la posición inicial. De la misma forma podemos descargar cualquiera de los cuatro elementos.
Al final simplemente imprimimos el mensaje "Artículo entregado".
Es así de simple, y espero que hayas disfrutado este video y hayas aprendido algo nuevo. No dude en hacer cualquier pregunta en la sección de comentarios a continuación y consulte mi colección de proyectos Arduino.