博客專欄

        EEPW首頁 > 博客 > DIY自動售貨機——基于Arduino的機電一體化項目

        DIY自動售貨機——基于Arduino的機電一體化項目

        發布人:電子資料庫 時間:2023-03-19 來源:工程師 發布文章

        在這個項目中,我們將學習如何制作基于Arduino的DIY自動售貨機。我將向您展示構建它的整個過程,從切割和組裝MDF板到將所有電子部件連接在一起并編寫Arduino代碼。

        概述

        自動售貨機具有四個連續旋轉伺服電機控制的四個出料單元、步進電機控制的載體系統、液晶顯示器、四個選擇物品的按鈕和硬幣檢測器。


        你現在可能會想,這個自動售貨機沒有那么有用,是的,你可能是對的。但我的想法是讓這個項目更有趣或者更復雜,這樣你就能學到更多新東西。我認為這個項目的想法可以很好的為電子或機電一體化的學生考慮建設一個作為他們的最后一年的項目,以及任何阿杜諾愛好者。

        建造自動售貨機

        我從切割8毫米厚的中密度纖維板開始。


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

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

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


        實際上,一個拼圖甚至可以用于前一步,以防你沒有圓鋸。我也用拼圖切割有好幾個切口的小零件。但是,請注意,這些是危險的機器,所以在使用它們時需要非常小心。

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


        軌道系統

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


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

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


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

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


        然而,在這一點上,我不得不拆開軌道,以便添加其他元素。首先,我添加了一個5毫米的螺栓在左側的軌道,我將附加一個滑輪的水平同步帶,以及兩個軸承將滑動在左側垂直軌道。


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


        接下來,我繼續在水平滑塊上添加容器。為此,我用了一些小木片,用木膠把它們連接起來。一旦我完成了這項工作,我就準備組裝鐵路系統。我用了一些環氧樹脂在軌道槽,并添加了一個額外的木板,以使整個軌道系統更硬。


        在下一步中,我將組件插入垂直軌道之間,并將其固定到位。滑塊和導軌系統的最終結果是工作良好。


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


        卸料裝置

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


        之后我用膠水槍把它固定在一個連續旋轉的伺服電機上。


        前面板

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


        為了把載體定位到它的起始位置,我安裝了兩個微型開關,對于硬幣,我粘了一個引導器,引導硬幣滑到機器底部。


        當硬幣附近有一個簡單的紅外傳感器時,它會給我們一個正面的反饋。

        電路圖

        接下來是有趣的部分,將所有電子元件連接到Arduino板上。這是這個DIY自動售貨機項目的完整電路圖。


        所以我們需要12伏電源,至少2安培。我們需要12伏的兩個步進電機,以及LED燈條,我將稍后附加在前門。然而,對于所有其他組件,我們需要5V,因此我使用了一個降壓轉換器將12V降壓到5V。DS04-NFC連續旋轉伺服電機由5V供電,并通過來自Arduino板的PWM信號控制,而. 四個按鈕和兩個微動開關連接到接地和Arduino數字引腳,因此使用Arduino板的內部上拉電阻器,我們可以很容易地檢測到何時按下它們。

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

        DC-DC LM2596降壓轉換器

        16×2液晶顯示器

        360度連續旋轉伺服電機

        步進電機NEMA 17

        A4988步進電機驅動器

        紅外接近傳感器

        按鈕

        微型限位開關

        Arduino板

        我用一些電子元件連接跨接線。它變得有點凌亂,有那么多電線,但一切正常。最后,我把兩個LED燈條貼在門板上,照亮自動售貨機的內部。


        Arduino代碼

        現在剩下的就是編程Arduino,這是我為這個項目制作的代碼。下面是代碼的說明。

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

        }

        }

        源代碼說明

        首先,我們需要包括伺服和液晶庫,定義LCD引腳、四個伺服電機、步進電機引腳、硬幣探測器以及四個按鈕和兩個微型開關。

        在設置部分,我們為上面提到的每個引腳設置引腳模式。我們可以注意到,對于按鈕和微型開關引腳,我們激活了內部上拉電阻器。這意味著這些引腳的邏輯電平將一直處于高位,一旦我們按下它們,邏輯電平將下降到低位。

        在我們進入主回路之前,我們還將載波設置到由兩個微動開關定義的起始位置。因此,在while循環中,我們繼續將載體移動到其起始位置,一旦按下兩個微動開關,電機將停止并移動到所需的啟動位置。

        // 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循環中。一旦插入一個硬幣,它通過接近傳感器,硬幣探測器引腳的邏輯狀態將下降到低,在這種情況下,我們將使用break語句退出while循環。

        // Wait until a coin is detected

        while(true){

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

        break;

        }

        }

        我們在循環中選擇另一條信息然后打印。

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

        }

        }

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

        現在,根據按下的按鈕,我們在switch語句中執行一次case。如果我們按下了第一個按鈕,運營商將開始使用定制的"moveUp()"函數上移。

        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;

        }

        如果我們看一下這個函數,我們可以看到它只是將步進電機設置為向特定的方向移動,并使我們輸入的步數作為參數。

        voidmoveUp(intsteps){

        digitalWrite(dirPinVertical, LOW);

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

        digitalWrite(stepPinVertical, HIGH);

        delayMicroseconds(300);

        digitalWrite(stepPinVertical, LOW);

        delayMicroseconds(300);

        }

        }

        我們可以注意到,我設置了A4988步進驅動器的工作在四分之一步的分辨率,和一些品味,我得出結論,我需要4900步,以使載體達到較高的位置。以類似的方式,我們將載體向左移動,直到到達位置1。

        緊接著,我們旋轉連續旋轉電機950毫秒,使螺旋線圈完成一個完整的循環。

        // Rotate the helical coil, discharge the selected item

        servo1.writeMicroseconds(2000);// rotate

        delay(950);

        servo1.writeMicroseconds(1500);// stop

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

        最后我們只打印消息"項目已送達"。


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: 售貨機 機電

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 温州市| 垫江县| 荆州市| 旬邑县| 聂荣县| 英山县| 柏乡县| 浦县| 庄浪县| 禄丰县| 东丰县| 南乐县| 上思县| 襄城县| 新安县| 海林市| 孝昌县| 泰州市| 精河县| 山丹县| 阳春市| 靖安县| 锡林浩特市| 灵台县| 灵璧县| 霍林郭勒市| 哈巴河县| 南阳市| 新宾| 湖南省| 行唐县| 隆安县| 东港市| 阳江市| 宝鸡市| 河津市| 额济纳旗| 南澳县| 田东县| 盐边县| 民勤县|