博客專欄

EEPW首頁(yè) > 博客 > DIY自動(dòng)售貨機(jī)——基于Arduino的機(jī)電一體化項(xiàng)目

DIY自動(dòng)售貨機(jī)——基于Arduino的機(jī)電一體化項(xiàng)目

發(fā)布人:電子資料庫(kù) 時(shí)間:2023-03-19 來(lái)源:工程師 發(fā)布文章

在這個(gè)項(xiàng)目中,我們將學(xué)習(xí)如何制作基于Arduino的DIY自動(dòng)售貨機(jī)。我將向您展示構(gòu)建它的整個(gè)過(guò)程,從切割和組裝MDF板到將所有電子部件連接在一起并編寫Arduino代碼。

概述

自動(dòng)售貨機(jī)具有四個(gè)連續(xù)旋轉(zhuǎn)伺服電機(jī)控制的四個(gè)出料單元、步進(jìn)電機(jī)控制的載體系統(tǒng)、液晶顯示器、四個(gè)選擇物品的按鈕和硬幣檢測(cè)器。


你現(xiàn)在可能會(huì)想,這個(gè)自動(dòng)售貨機(jī)沒(méi)有那么有用,是的,你可能是對(duì)的。但我的想法是讓這個(gè)項(xiàng)目更有趣或者更復(fù)雜,這樣你就能學(xué)到更多新東西。我認(rèn)為這個(gè)項(xiàng)目的想法可以很好的為電子或機(jī)電一體化的學(xué)生考慮建設(shè)一個(gè)作為他們的最后一年的項(xiàng)目,以及任何阿杜諾愛(ài)好者。

建造自動(dòng)售貨機(jī)

我從切割8毫米厚的中密度纖維板開(kāi)始。


我以前做了一個(gè)三維模型的機(jī)器,從那里我得到了所有的測(cè)量。您可以從下面的鏈接下載三維模型。

我用圓鋸切割中密度纖維板。實(shí)際上這是一個(gè),由我的搭檔Marija制作,在她的YouTube頻道上有一段DIY視頻 .

在用圓鋸切割了所有的面板之后,我繼續(xù)用倒置的拼圖在一些面板上開(kāi)孔。


實(shí)際上,一個(gè)拼圖甚至可以用于前一步,以防你沒(méi)有圓鋸。我也用拼圖切割有好幾個(gè)切口的小零件。但是,請(qǐng)注意,這些是危險(xiǎn)的機(jī)器,所以在使用它們時(shí)需要非常小心。

當(dāng)我準(zhǔn)備好所有的MDF部件后,我開(kāi)始用一些木膠和螺絲組裝它們。為了緊固面板,我用了90度角夾鉗。使用無(wú)繩鉆,我首先做了試點(diǎn)孔,然后做了柜臺(tái)下沉和螺絲3毫米的螺絲到位。我用同樣的方法組裝了所有的面板,其中一些面板我還使用了一些F夾具。


軌道系統(tǒng)

在裝配的這一點(diǎn)上,我將繼續(xù)制作軌道系統(tǒng)。為此,我使用鋁管,我用金屬手鋸將它們切割成一定的尺寸。水平軌道的管道直徑為16 mm,而垂直軌道的管道直徑為20 mm。在一個(gè)18毫米的實(shí)木板上,我用福斯特納鉆頭為管子做了槽,然后把管子連在上面。


水平軌道由兩根27厘米長(zhǎng)的管子組成,而垂直軌道由三根45厘米長(zhǎng)的管子組成。

接下來(lái)是滑塊,下面是我如何制作的。我用21×21厘米的木板在上面打了8毫米的洞。


然后我通過(guò)這些孔插入8毫米螺紋桿,并用墊圈和螺母固定22毫米軸承。至于水平滑塊,我使用了相同的方法,但直徑較小的軸承為16毫米。

當(dāng)我把滑塊插入管軌之間時(shí),我發(fā)現(xiàn)它有點(diǎn)松。為了解決這個(gè)問(wèn)題,我不得不縮短兩條鐵軌之間的距離。所以我先是擴(kuò)大了管子的槽,然后在管子上做了垂直的槽,最后用一根螺紋桿把兩個(gè)管子的軌道固定得更緊。在這之后,滑塊不再松動(dòng),它們正常工作。


然而,在這一點(diǎn)上,我不得不拆開(kāi)軌道,以便添加其他元素。首先,我添加了一個(gè)5毫米的螺栓在左側(cè)的軌道,我將附加一個(gè)滑輪的水平同步帶,以及兩個(gè)軸承將滑動(dòng)在左側(cè)垂直軌道。


在另一個(gè)右側(cè)的軌道,我不得不附加步進(jìn)電機(jī)水平運(yùn)動(dòng)。首先,我把電機(jī)固定在一塊8毫米的中密度纖維板上,然后在上面加了一塊支撐木,還把開(kāi)槽的部分固定在上面。最后,我用木膠和兩個(gè)螺絲將整個(gè)組件連接到垂直滑塊上。


接下來(lái),我繼續(xù)在水平滑塊上添加容器。為此,我用了一些小木片,用木膠把它們連接起來(lái)。一旦我完成了這項(xiàng)工作,我就準(zhǔn)備組裝鐵路系統(tǒng)。我用了一些環(huán)氧樹(shù)脂在軌道槽,并添加了一個(gè)額外的木板,以使整個(gè)軌道系統(tǒng)更硬。


在下一步中,我將組件插入垂直軌道之間,并將其固定到位?;瑝K和導(dǎo)軌系統(tǒng)的最終結(jié)果是工作良好。


我繼續(xù)安裝水平同步帶。我測(cè)量了我需要的長(zhǎng)度,剪成一定的尺寸,然后用一個(gè)拉鏈把它固定在滑塊上。至于垂直滑塊,我用一塊中密度纖維板和一些螺栓將步進(jìn)電機(jī)安裝在機(jī)器頂部。在底部,我連接了滑輪,并以類似的方式安裝了正時(shí)皮帶。


卸料裝置

接下來(lái),我轉(zhuǎn)到卸料單元。我用3毫米厚的金屬絲做了一個(gè)螺旋線圈,把它包裹在一個(gè)直徑7厘米的噴漆罐上。


之后我用膠水槍把它固定在一個(gè)連續(xù)旋轉(zhuǎn)的伺服電機(jī)上。


前面板

下一個(gè)是前門面板,我用簡(jiǎn)單的鉸鏈連接到自動(dòng)售貨機(jī)上,為了鎖上它,我用了一個(gè)磁性的門閂。然后我用一個(gè)5毫米厚的丙烯酸樹(shù)脂覆蓋前面的大開(kāi)口,而對(duì)于右側(cè)較小的開(kāi)口,我用了一塊非常錫的鋁板。我在這里為硬幣和紐扣做了4個(gè)洞. 我用鉆頭和鋼鋸做的。一旦我把電子部件連接到鋁板上,我就用5毫米的螺栓將其固定到前門板上。


為了把載體定位到它的起始位置,我安裝了兩個(gè)微型開(kāi)關(guān),對(duì)于硬幣,我粘了一個(gè)引導(dǎo)器,引導(dǎo)硬幣滑到機(jī)器底部。


當(dāng)硬幣附近有一個(gè)簡(jiǎn)單的紅外傳感器時(shí),它會(huì)給我們一個(gè)正面的反饋。

電路圖

接下來(lái)是有趣的部分,將所有電子元件連接到Arduino板上。這是這個(gè)DIY自動(dòng)售貨機(jī)項(xiàng)目的完整電路圖。


所以我們需要12伏電源,至少2安培。我們需要12伏的兩個(gè)步進(jìn)電機(jī),以及LED燈條,我將稍后附加在前門。然而,對(duì)于所有其他組件,我們需要5V,因此我使用了一個(gè)降壓轉(zhuǎn)換器將12V降壓到5V。DS04-NFC連續(xù)旋轉(zhuǎn)伺服電機(jī)由5V供電,并通過(guò)來(lái)自Arduino板的PWM信號(hào)控制,而. 四個(gè)按鈕和兩個(gè)微動(dòng)開(kāi)關(guān)連接到接地和Arduino數(shù)字引腳,因此使用Arduino板的內(nèi)部上拉電阻器,我們可以很容易地檢測(cè)到何時(shí)按下它們。

您可以從以下鏈接獲取本Arduino教程所需的組件:

DC-DC LM2596降壓轉(zhuǎn)換器

16×2液晶顯示器

360度連續(xù)旋轉(zhuǎn)伺服電機(jī)

步進(jìn)電機(jī)NEMA 17

A4988步進(jìn)電機(jī)驅(qū)動(dòng)器

紅外接近傳感器

按鈕

微型限位開(kāi)關(guān)

Arduino板

我用一些電子元件連接跨接線。它變得有點(diǎn)凌亂,有那么多電線,但一切正常。最后,我把兩個(gè)LED燈條貼在門板上,照亮自動(dòng)售貨機(jī)的內(nèi)部。


Arduino代碼

現(xiàn)在剩下的就是編程Arduino,這是我為這個(gè)項(xiàng)目制作的代碼。下面是代碼的說(shuō)明。

/* DIY Vending Machine - Arduino based Mechatronics Project

by Dejan Nedelkovski, www.HowToMechatronics.com

*/

#include <LiquidCrystal.h> // includes the LiquidCrystal Library

#include <Servo.h>

LiquidCrystallcd(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

intbuttonPressed;

voidsetup(){

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);

}

}

voidloop(){

// 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){

case1:

// 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;

case2:

// 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;

case3:

// 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;

case4:

// 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 ==

voidmoveUp(intsteps){

digitalWrite(dirPinVertical, LOW);

for(intx = 0; x<steps; x++){

digitalWrite(stepPinVertical, HIGH);

delayMicroseconds(300);

digitalWrite(stepPinVertical, LOW);

delayMicroseconds(300);

}

}

voidmoveDown(intsteps){

digitalWrite(dirPinVertical, HIGH);

for(intx = 0; x<steps; x++){

digitalWrite(stepPinVertical, HIGH);

delayMicroseconds(300);

digitalWrite(stepPinVertical, LOW);

delayMicroseconds(300);

}

}

voidmoveLeft(intsteps){

digitalWrite(dirPinHorizontal, HIGH);

for(intx = 0; x<steps; x++){

digitalWrite(stepPinHorizontal, HIGH);

delayMicroseconds(300);

digitalWrite(stepPinHorizontal, LOW);

delayMicroseconds(300);

}

}

voidmoveRight(intsteps){

digitalWrite(dirPinHorizontal, LOW);

for(intx = 0; x<steps; x++){

digitalWrite(stepPinHorizontal, HIGH);

delayMicroseconds(300);

digitalWrite(stepPinHorizontal, LOW);

delayMicroseconds(300);

}

}

源代碼說(shuō)明

首先,我們需要包括伺服和液晶庫(kù),定義LCD引腳、四個(gè)伺服電機(jī)、步進(jìn)電機(jī)引腳、硬幣探測(cè)器以及四個(gè)按鈕和兩個(gè)微型開(kāi)關(guān)。

在設(shè)置部分,我們?yōu)樯厦嫣岬降拿總€(gè)引腳設(shè)置引腳模式。我們可以注意到,對(duì)于按鈕和微型開(kāi)關(guān)引腳,我們激活了內(nèi)部上拉電阻器。這意味著這些引腳的邏輯電平將一直處于高位,一旦我們按下它們,邏輯電平將下降到低位。

在我們進(jìn)入主回路之前,我們還將載波設(shè)置到由兩個(gè)微動(dòng)開(kāi)關(guān)定義的起始位置。因此,在while循環(huán)中,我們繼續(xù)將載體移動(dòng)到其起始位置,一旦按下兩個(gè)微動(dòng)開(kāi)關(guān),電機(jī)將停止并移動(dòng)到所需的啟動(dòng)位置。

// 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);

}

在主程序中,首先在LCD上打印"插入硬幣"消息。然后我們被困在while循環(huán)中。一旦插入一個(gè)硬幣,它通過(guò)接近傳感器,硬幣探測(cè)器引腳的邏輯狀態(tài)將下降到低,在這種情況下,我們將使用break語(yǔ)句退出while循環(huán)。

// Wait until a coin is detected

while(true){

if(digitalRead(coinDetector)== LOW){// If a coin is detected, exit the from the while loop

break;

}

}

我們?cè)谘h(huán)中選擇另一條信息然后打印。

// 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;

}

}

這個(gè)while循環(huán)等待我們按下四個(gè)按鈕中的任何一個(gè),一旦我們按下了,我們就會(huì)退出并打印消息"Delivering"。

現(xiàn)在,根據(jù)按下的按鈕,我們?cè)趕witch語(yǔ)句中執(zhí)行一次case。如果我們按下了第一個(gè)按鈕,運(yùn)營(yíng)商將開(kāi)始使用定制的"moveUp()"函數(shù)上移。

switch(buttonPressed){

case1:

// 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;

}

如果我們看一下這個(gè)函數(shù),我們可以看到它只是將步進(jìn)電機(jī)設(shè)置為向特定的方向移動(dòng),并使我們輸入的步數(shù)作為參數(shù)。

voidmoveUp(intsteps){

digitalWrite(dirPinVertical, LOW);

for(intx = 0; x<steps; x++){

digitalWrite(stepPinVertical, HIGH);

delayMicroseconds(300);

digitalWrite(stepPinVertical, LOW);

delayMicroseconds(300);

}

}

我們可以注意到,我設(shè)置了A4988步進(jìn)驅(qū)動(dòng)器的工作在四分之一步的分辨率,和一些品味,我得出結(jié)論,我需要4900步,以使載體達(dá)到較高的位置。以類似的方式,我們將載體向左移動(dòng),直到到達(dá)位置1。

緊接著,我們旋轉(zhuǎn)連續(xù)旋轉(zhuǎn)電機(jī)950毫秒,使螺旋線圈完成一個(gè)完整的循環(huán)。

// Rotate the helical coil, discharge the selected item

servo1.writeMicroseconds(2000);// rotate

delay(950);

servo1.writeMicroseconds(1500);// stop

請(qǐng)注意,這些值有時(shí)會(huì)變化,并取決于電機(jī)本身。使用moveRight()和moveDown()自定義函數(shù),我們將載體帶回起始位置。以同樣的方式,我們可以卸下這四個(gè)項(xiàng)目中的任何一個(gè)。

最后我們只打印消息"項(xiàng)目已送達(dá)"。


*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請(qǐng)聯(lián)系工作人員刪除。



關(guān)鍵詞: 售貨機(jī) 機(jī)電

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉