산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

개요

이 프로젝트에서는 아두이노 기반 DIY 자판기 만드는 법을 배웁니다. MDF 보드 재단/조립부터 모든 전자부품 연결, 아두이노 코드 작성까지 전 과정을 보여드립니다.

아래 비디오를 시청하거나 작성된 튜토리얼을 읽어보세요.

기능 개요

이 자판기는 4개의 연속 회전 서보 모터로 제어되는 4개 배출 유닛, 스테퍼 모터로 제어되는 아이템 캐리어 시스템, LCD, 품목 선택용 4개 버튼, 동전 감지기로 구성됩니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

아이템 캐리어가 이 자판기에 그다지 유용하지 않아 보일 수 있습니다. 맞습니다. 하지만 제 아이디어는 이 프로젝트를 더 흥미롭고 복잡하게 만들어 더 많은 걸 배우게 하려는 것이었습니다. 이 프로젝트 아이디어는 졸업 작품으로 자판기 제작을 고려하는 전자/메카트로닉스 전공 학생이나 아두이노 애호가들에게 훌륭하다고 생각합니다.

자판기 제작

8mm 두께 MDF 보드를 크기에 맞게 재단하는 것으로 시작합니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

미리 3D 모델을 만들어 모든 치수를 거기서 가져왔습니다.

이 3D 모델은 Thangs에서 찾아 다운로드하거나 브라우저에서 탐색할 수 있습니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

MDF 재단은 원형 톱으로 했습니다. 사실 이건 원형 톱, 라우터, 직쏘가 장착된 홈메이드 작업대인데, 제 파트너 Marija가 만들었고 그녀의 유튜브 채널 Creativity Hero에 DIY 영상이 있습니다.

원형 톱으로 모든 패널 재단 후, 일부 패널의 개구부는 거꾸로 장착한 직쏘로 만들었습니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

직쏘는 원형 톱이 없을 때 이전 단계에도 사용할 수 있습니다. 여러 컷이 필요한 작은 부품들도 직쏘로 재단했습니다. 다만 이 기계들은 위험하니 매우 조심해서 사용해야 합니다.

모든 MDF 부품이 준비되면 목공 본드와 나사로 조립합니다. 패널 고정용 90도 앵글 클램프 사용. 무선 드릴로 파일럿 홀 뚫고 카운터싱크 후 3mm 나사 조임. 같은 방식으로 모든 패널 조립, 일부엔 F-클램프도 사용.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

레일 시스템

이 시점에서 레일 시스템 제작으로 넘어갑니다. 알루미늄 튜브를 금속 손톱으로 크기에 맞게 자릅니다. 수평 레일 튜브 직경 16mm, 수직 레일 튜브 직경 20mm. 18mm 두꺼운 원목 판에 포스너 비트로 튜브용 슬롯을 내고 튜브를 고정합니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

수평 레일은 27cm 튜브 2개, 수직 레일은 45cm 튜브 3개로 구성.

슬라이더 제작: 21x21cm 목재 판에 8mm 구멍을 뚫습니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

8mm 나사봉을 구멍에 통과시키고 와셔/너트로 22mm 베어링 고정. 수평 슬라이더는 같은 방식이나 16mm 외경 베어링 사용.

슬라이더를 튜브 레일 사이에 끼워보니 좀 헐거웠습니다. 두 레일 간격을 좁혀 해결. 튜브 슬롯 확장, 튜브에 수직 슬롯 가공, 나사봉으로 두 튜브 레일을 당겨 간격 좁힘. 이후 슬라이더 헐거움 해결, 정상 작동.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

이 시점에서 다른 요소 추가를 위해 레일 분해 필요. 레일 좌측에 5mm 볼트 달아 수평 타이밍 벨트용 풀리와 좌측 수직 레일 슬라이드용 베어링 2개 부착.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

우측에는 수평 이동용 스테퍼 모터 장착. 모터를 8mm MDF 판에 고정, 지지목 추가, 슬롯 부분 고정 후 수직 슬라이더에 목공 본드와 나사 2개로 전체 조립체 고정.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

수평 슬라이더에 컨테이너 장착. 작은 목재 조각을 목공 본드로 접합. 레일 시스템 조립 준비 완료. 레일 슬롯에 에폭시 바르고 레일 측면에 추가 목재 판 대 전체 시스템 강화.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

조립체를 수직 레일 사이에 끼우고 고정. 슬라이더와 레일 시스템 최종 결과 훌륭하게 작동.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

수평 타이밍 벨트 설치. 필요 길이 측정 재단, 지퍼 타이로 슬라이더 고정. 수직 슬라이더용 스테퍼 모터를 기계 상단에 MDF 조각과 볼트로 고정. 하단에 풀리 달고 같은 방식으로 타이밍 벨트 설치.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

배출 유닛

아이템 배출 유닛으로 넘어갑니다. 3mm 철사를 7cm 직경 스프레이 캔에 감아 나선형 코일 제작.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

글루건으로 연속 회전 서보 모터에 고정.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

전면 패널

전면 도어 패널을 일반 경첩으로 자판기에 부착, 자석 도어 캐처로 잠금. 큰 전면 개구부는 5mm 아크릴로, 우측 작은 개구부는 얇은 알루미늄 판으로 커버. 알루미늄 판에 버튼 4개 구멍, 동전 투입구, LCD 개구부 가공(드릴과 톱 사용). 전자부품을 알루미늄 판에 부착 후 5mm 볼트로 전면 도어 패널에 고정.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

캐리어 시작 위치 설정용 마이크로 스위치 2개 설치. 동전 가이드를 접착해 동전이 기계 바닥으로 미끄러지게 유도. 동전 감지기는 간단한 적외선 근접 센서로, 동전이 지나가면 양성 피드백 제공.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

회로도

이제 재미있는 부분: 모든 전자부품을 아두이노 보드에 연결. 이 DIY 자판기 프로젝트 완전 회로도입니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

최소 2A 정격 12V 파워 서플라이 필요. 12V는 두 스테퍼 모터와 나중에 전면 도어에 부착할 LED 스트립용. 그 외 모든 부품은 5V 필요하므로 벅 컨버터로 12V를 5V로 강압. DS04-NFC 연속 회전 서보 모터는 5V 전원, 아두이노 PWM 신호로 제어. 스테퍼 모터는 A4988 드라이버로 제어. 4개 버튼과 2개 마이크로 스위치는 그라운드와 아두이노 디지털 핀 연결, 아두이노 내부 풀업 저항으로 눌림 감지.

필요한 부품

점퍼 와이어로 전자부품 연결. 와이어가 많아 좀 지저분하지만 모두 정상 작동. 마지막에 전면 도어 패널에 LED 라이트 스트립 2개 부착해 자판기 내부를 밝힙니다.

스마트 아두이노 자판기 직접 만들기: 완전한 DIY 메카트로닉스 가이드

아두이노 코드

이제 아두이노 프로그래밍. 이 프로젝트용 코드입니다. 아래에 코드 설명.

/* DIY Vending Machine - Arduino based Mechatronics Project
   by Dejan Nedelkovski, www.HowToMechatronics.com */
#include <LiquidCrystal.h>
#include <Servo.h>

LiquidCrystal lcd(27, 26, 25, 24, 23, 22); // (rs, enable, d4, d5, d6, d7)
Servo servo1, servo2, servo3, servo4; // DS04-NFC 모터

// 스테퍼 모터 핀
#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);
  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);
  // 내부 풀업 저항 활성화
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(button3, INPUT_PULLUP);
  pinMode(button4, INPUT_PULLUP);
  pinMode(microSwitchV, INPUT_PULLUP);
  pinMode(microSwitchH, INPUT_PULLUP);

  // 수직 시작 위치
  digitalWrite(dirPinVertical, HIGH);
  while (true) {
    if (digitalRead(microSwitchV) == LOW) {
      moveUp(70); // 살짝 위로 이동 후 루프 탈출
      break;
    }
    digitalWrite(stepPinVertical, HIGH);
    delayMicroseconds(300);
    digitalWrite(stepPinVertical, LOW);
    delayMicroseconds(300);
  }
  // 수평 시작 위치
  digitalWrite(dirPinHorizontal, LOW);
  while (true) {
    if (digitalRead(microSwitchH) == LOW) {
      moveLeft(350);
      break;
    }
    digitalWrite(stepPinHorizontal, HIGH);
    delayMicroseconds(300);
    digitalWrite(stepPinHorizontal, LOW);
    delayMicroseconds(300);
  }
}

void loop() {
  // LCD에 "Insert a coin!" 출력
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Insert a coin!");
  // 동전 감지 대기
  while (true) {
    if (digitalRead(coinDetector) == LOW) { 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?");
  // 버튼 눌림 대기
  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; }
  }
  // "Delivering..." 출력
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Delivering...");
  // 눌린 버튼에 따라 캐리어 이동 및 아이템 배출
  switch (buttonPressed) {
    case 1: // 위치 1로 이동
      moveUp(4900); // 4900 스텝 업 (스테퍼 드라이버 1/4 스텝 해상도 설정)
      delay(200);
      moveLeft(1700); // 1700 스텝 좌측
      delay(300);
      // 나선 코일 회전, 아이템 배출
      servo1.writeMicroseconds(2000); // 회전
      delay(950);
      servo1.writeMicroseconds(1500); // 정지
      delay(500);
      // 시작 위치로 복귀
      moveRight(1700);
      delay(200);
      moveDown(4900);
      break;
    case 2: // 위치 2
      moveUp(4900);
      delay(200);
      servo2.writeMicroseconds(2000);
      delay(950);
      servo2.writeMicroseconds(1500);
      delay(500);
      moveDown(4900);
      break;
    case 3: // 위치 3
      moveUp(2200);
      delay(200);
      moveLeft(1700);
      delay(300);
      servo3.writeMicroseconds(2000);
      delay(950);
      servo3.writeMicroseconds(1500);
      delay(500);
      moveRight(1700);
      delay(200);
      moveDown(2200);
      break;
    case 4: // 위치 4
      moveUp(2200);
      delay(200);
      servo4.writeMicroseconds(2000);
      delay(950);
      servo4.writeMicroseconds(1500);
      delay(500);
      moveDown(2200);
      break;
  }
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Item delivered!");
  delay(2000);
}

// 커스텀 함수들
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);
  }
}

소스 코드 설명

Servo, LiquidCrystal 라이브러리 포함, LCD 핀, 4개 서보, 스테퍼 핀, 동전 감지기, 4개 버튼, 2개 마이크로 스위치 정의.

setup에서 위 핀들 핀 모드 설정. 버튼과 마이크로 스위치 핀엔 내부 풀업 저항 활성화(평상시 HIGH, 눌리면 LOW).

메인 루프 진입 전, 두 마이크로 스위치로 정의된 캐리어 시작 위치로 이동. while 루프로 캐리어 계속 이동시키다 두 마이크로 스위치 눌리면 모터 정지 후 원하는 시작 위치로 이동.

// 수직 시작 위치
digitalWrite(dirPinVertical, HIGH);
while (true) {
  if (digitalRead(microSwitchV) == LOW) {
    moveUp(70);
    break;
  }
  digitalWrite(stepPinVertical, HIGH);
  delayMicroseconds(300);
  digitalWrite(stepPinVertical, LOW);
  delayMicroseconds(300);
}
// 수평 시작 위치
digitalWrite(dirPinHorizontal, LOW);
while (true) {
  if (digitalRead(microSwitchH) == LOW) {
    moveLeft(350);
    break;
  }
  digitalWrite(stepPinHorizontal, HIGH);
  delayMicroseconds(300);
  digitalWrite(stepPinHorizontal, LOW);
  delayMicroseconds(300);
}

메인 프로그램에서 LCD에 "Insert a coin" 출력. while 루프에서 대기. 동전 투입 시 근접 센서 지나가면 coinDetector 핀 로직이 LOW로 떨어져 break로 루프 탈출.

while (true) {
  if (digitalRead(coinDetector) == LOW) { break; }
}

"Select your item" 출력 후 또 다른 while 루프에서 버튼 눌림 대기.

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

4개 버튼 중 하나 눌리면 루프 탈출 후 "Delivering" 출력.

눌린 버튼에 따라 switch문 case 실행. 1번 버튼 경우 moveUp() 커스텀 함수로 캐리어 상향 이동.

case 1:
  moveUp(4900);
  delay(200);
  moveLeft(1700);
  delay(300);
  servo1.writeMicroseconds(2000);
  delay(950);
  servo1.writeMicroseconds(1500);
  delay(500);
  moveRight(1700);
  delay(200);
  moveDown(4900);
  break;

moveUp() 함수는 스테퍼 모터를 특정 방향으로 설정하고 인자로 받은 스텝 수만큼 이동시킵니다.

void moveUp(int steps) {
  digitalWrite(dirPinVertical, LOW);
  for (int x = 0; x < steps; x++) {
    digitalWrite(stepPinVertical, HIGH);
    delayMicroseconds(300);
    digitalWrite(stepPinVertical, LOW);
    delayMicroseconds(300);
  }
}

A4988 드라이버를 1/4 스텝 해상도로 설정했고, 테스트 결과 캐리어 상단 위치 도달에 4900 스텝 필요함을 확인. 같은 방식으로 좌측 이동해 위치 1 도달.

연속 회전 모터를 950ms 회전시켜 나선 코일 한 바퀴 돌림.

servo1.writeMicroseconds(2000); // 회전
delay(950);
servo1.writeMicroseconds(1500); // 정지

이 값들은 모터마다 다를 수 있습니다. moveRight(), moveDown()으로 캐리어 시작 위치 복귀. 같은 방식으로 4개 아이템 모두 배출 가능.

마지막에 "Item delivered" 출력.

정말 간단하죠? 즐겁게 보셨고 새로운 걸 배우셨길 바랍니다. 질문은 댓글로, 제 아두이노 프로젝트 모음도 확인해보세요.

제조공정

  1. 자판기: 366억 달러 규모의 미국 거대 산업
  2. 집에서 직접 만드는 DIY 숙제 작성 머신 (펜 플로터)
  3. 아두이노 나노 RP2040으로 만드는 DIY 포토샵 컨트롤 콘솔
  4. 아두이노로 모니터 앰비라이트(Ambilight) 시스템 직접 만들기
  5. 아두이노로 초음파 부양 장치 만들기: 단계별 가이드
  6. 아두이노와 스마트폰으로 만드는 스마트 전압계 – 초간단 DIY 프로젝트
  7. 아두이노로 만드는 신뢰도 높은 적외선 심박 센서: 단계별 가이드
  8. 아두이노 틱택토 게임 - MAX7219 LED 매트릭스와 골판지 케이스
  9. 아두이노와 노키아 5110 LCD로 만드는 DIY 전압계 - 단계별 가이드
  10. 유한 상태 머신으로 아두이노 디지털 시계 만들기