Arduino Snack Automaat – Ontwerp & Bouw Handleiding
Onderdelen en Benodigdheden
| Onderdeel | Aantal | Opmerking |
|---|---|---|
| Arduino UNO | 1 | Let op: Arduino Mega zou beter zijn voor meer I/O |
| Sensor Shield | 1 | Voor eenvoudige sensor-aansluiting |
| DC Motor 6V met wiel | 3 | Voor spiraalmechanisme |
| Infrarood (reflecterend) / lijnvolgsensor | 3 | Productdetectie |
| Proximity (elektromagnetische) sensor | 1 | Muntsensor 1 |
| Afstandsonderbreker (infrarood/optocoupler) sensor | 1 | Muntsensor 2 |
| Voeding 6V voor DC motoren | 1 | |
| Relais (generiek) | 1 | 4-kanaals relais |
| LCD (Nokia 5110) | 1 | Monochroom display |
| LED (wit) | 2 | Statusindicatie |
| Drukknoppen | 3 | Rood, Geel, Groen voor productkeuze |
Apps en Online Services
| App/Service | Opmerking |
|---|---|
| Arduino IDE | Codeerplatform |
| SolidWorks | Of een andere 3D-modelleertool |
Over dit Project
Introductie
Hallo, groetjes uit Indonesië. Deze snackautomaat was mijn afstudeerproject, afgerond eind 2015. Het doel: een automaat bouwen aangedreven door een Arduino-microcontroller, met "goedkope en makkelijk verkrijgbare" componenten uit lokale winkels.
De onderstaande video toont de eindtest: betaling/munt-test, productselectie en productafgifte.
Stap 1: Concept Schetsen
Allereerst: het concept. Mijn eerste schets toonde een snackautomaat die munten accepteert en een acryl behuizing heeft.
Kies en verfijn je concept, denk na over elk scenario, elke voorwaarde. Schets alles - maak je geen zorgen over lelijke tekeningen (kijk naar de mijne! :D). De juiste tijd om over de ondenkbare na te denken is vóórdat het project begint.

Stap 2: 3D-model Maken
Deze stap is misschien niet voor iedereen nodig, maar voor mij en dit project cruciaal. Ik maakte een volledig uitgewerkt SolidWorks-model. Ik moest de afmetingen bepalen van: snackverpakkingen, geaccepteerde/geweigerde muntgroottes, muntgolf, muntril, drukknoppen, Arduino-afmetingen, sensoren en hun plaatsing, LCD-plaatsing, en waar geaccepteerde munten naartoe gaan. Ook schroefgaten voor elk onderdeel.

De behuizing is van acryl, gelasercut. Daarom modeleer ik zo gedetailleerd en nauwkeurig mogelijk - hoe nauwkeuriger het model, hoe preciezer de behuizing.
Stap 3: Muntgolf Ontwerpen
Voor munsorting gebruik ik eerst muntafmetingen. Door de muntgolf te ontwerpen bepaal ik welke muntgroottes de machine mogen betreden. Als tweede filter bepaal ik welke munten geaccepteerd worden en naar de munthouder rollen. Door zwaartekracht vallen kleinere munten (diameter kleiner dan de lengte van de muntril) af en worden geweigerd.

- Links: Munt past niet in de golf.
- Midden: Munt valt af en wordt geweigerd.
- Rechts: Geaccepteerde munt, rolt naar munthouder.
Stap 4: Elke Component Voorbereiden en Testen

Maak de Arduino klaar, verzamel alles. Test elk component: LCD, drukknoppen, relais, LED. Combineer alles, leer verschillende logica en codering. Test tot de limiet, maar kap niks.
Waarom een weerstand? Wat gebeurt er als...? Waarom zijn sensorwaarden niet stabiel? Welke waarde leest de sensor daadwerkelijk? Ik testte en ontdekte dat de proximity-sensor "verstoring" had - een weerstand kalmeerde het signaal.

De infraroodsensor werkte slecht onder direct zonlicht (kende ik wel, maar voelde nu de impact). Oplossing: ducttape om de ontvanger van de IR-sensor te isoleren.
Stap 5: Spiraalmechanisme Bouwen
Dit is een van de belangrijkste delen: het afgifte-mechanisme. Ik gebruikte een spiraalmechanisme met aluminiumdraad (2mm diameter), handmatig gevormd tot spiraal met behulp van een PVC-buizen van 9cm diameter.



De spiraaldraad is met kabelbinders aan een wiel bevestigd. Bij aansturing van de DC-motor roteert het wiel en de spiraal. Een roterende spiraal zet rotatie om in lineaire beweging van het product.
Stap 6: Muntidentificatiemechanisme Bouwen



Muntsensor 1 (proximity/inductieve sensor): wanneer een geaccepteerde munt passeert, start de Arduino met tellen in milliseconden.
if sensor1 getriggerd dan start met tellen in milliseconden
Muntsensor 2 (afstandsonderbreker/optocoupler): wanneer de munt deze passeert, stopt de Arduino met tellen en berekent de reistijd tussen sensor 1 en 2.
if sensor2 getriggerd dan stop met tellen. "reistijd" is xxx milliseconden
Gebruik niet te veel magneten - dit veroorzaakt vastlopende munten op de ril. We willen dit voorkomen omdat we de reistijd voor elke munt nodig hebben om de muntwaarde te bepalen.
als "reistijd" >= "yyy" milliseconden, dan is het "aaa" munt, anders "bbb"
Stap 7: Productdetectiemechanisme Bouwen
Ik gebruikte 3 infraroodsensoren voor productdetectie wanneer het product valt na duwen door de spiraal.

Wanneer een product valt, triggert de IR-sensor en stuurt een UIT-signaal naar de DC-motor (via relais).
Stap 8: LCD Gebruiken voor Informatie

De LCD toont informatie (in Indonesische valuta) over geaccepteerde muntwaarde, totaal saldo, en instructies voor bediening.
- Machine AAN: Hoofdscherm = "Voer munt in".
- Munt ingevoerd: Toon muntwaarde en totaal saldo.
- Geen munt: Behoud hoofdscherm.
- Na succesvolle muntidentificatie:
- Totaal saldo ≥ productprijs = "Selecteer product".
- Totaal saldo < productprijs = "Voer meer munten in".
- Na spiraalactivering (afgifte):
- Productdetectie getriggerd = "Dank u wel", transactie voltooid.
- Wacht, terug naar hoofdscherm.
Stap 9: Afwerken en Testen
Eindelijk, de afgeronde snackautomaat! ;)



Na ~3 maanden was ik klaar voor de eindtest: betaling, selectie, afgifte. Deze handleiding hopelijk een inspiratie voor jullie volgende Arduino-automaat!
Stap 10: Verbeterpunten
- Muntwisselmechanisme toevoegen.
- Biljetacceptatie.
- Bitcoin/digitale betaling.
- Productvoorraad op LCD tonen.
- IoT: Notificatie bij elke transactie.
- IoT: Notificatie bij lege/lage voorraad.

Speciale dank: ITENAS Bandung, Afdeling Werktuigbouwkunde.
Code
Broncode voor Snack Automaat (Arduino)
const byte SIAP = 0;
const byte KOIN_MASUK1 = 1;
const byte KOIN_MASUK2 = 2;
const byte KOIN_MASUK3 = 3;
const byte KOIN_MASUK4 = 4;
const byte KOIN_MASUK5 = 5;
const byte KOIN_MASUK6 = 6;
const byte KOIN_MASUK7 = 7;
const byte SALDO_500 = 8;
const byte SALDO_500500 = 9;
const byte SALDO_500500500 = 10;
const byte SALDO_500500500500 = 11;
const byte SALDO_5005005001000 = 12;
const byte SALDO_5001000 = 13;
const byte SALDO_5001000500 = 14;
const byte SALDO_50010001000 = 15;
const byte SALDO_5005001000 = 16;
const byte SALDO_1000 = 17;
const byte SALDO_10001000 = 18;
const byte SALDO_1000500 = 19;
const byte SALDO_1000500500 = 20;
const byte SALDO_10005001000 = 21;
const byte KOIN_KELUAR = 22;
byte state = SIAP;
const float jeda_waktu = 876;
unsigned long time1, time2, time3, time4, time5, time6, time7;
#define PIN_SCE 7
#define PIN_RESET 6
#define PIN_DC 5
#define PIN_SDIN 4
#define PIN_SCLK 3
#define LCD_C LOW
#define LCD_D HIGH
#define LCD_X 84
#define LCD_Y 48
static const byte ASCII[][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00}, // 20 (spatie)
{0x00, 0x00, 0x5f, 0x00, 0x00}, // 21 !
{0x00, 0x07, 0x00, 0x07, 0x00}, // 22 "
{0x14, 0x7f, 0x14, 0x7f, 0x14}, // 23 #
{0x24, 0x2a, 0x7f, 0x2a, 0x12}, // 24 $
{0x23, 0x13, 0x08, 0x64, 0x62}, // 25 %
{0x36, 0x49, 0x55, 0x22, 0x50}, // 26 &
{0x00, 0x05, 0x03, 0x00, 0x00}, // 27 '
{0x00, 0x1c, 0x22, 0x41, 0x00}, // 28 (
{0x00, 0x41, 0x22, 0x1c, 0x00}, // 29 )
{0x14, 0x08, 0x3e, 0x08, 0x14}, // 2a *
{0x08, 0x08, 0x3e, 0x08, 0x08}, // 2b +
{0x00, 0x50, 0x30, 0x00, 0x00}, // 2c ,
{0x08, 0x08, 0x08, 0x08, 0x08}, // 2d -
{0x00, 0x60, 0x60, 0x00, 0x00}, // 2e .
{0x20, 0x10, 0x08, 0x04, 0x02}, // 2f /
{0x3e, 0x51, 0x49, 0x45, 0x3e}, // 30 0
{0x00, 0x42, 0x7f, 0x40, 0x00}, // 31 1
{0x42, 0x61, 0x51, 0x49, 0x46}, // 32 2
{0x21, 0x41, 0x45, 0x4b, 0x31}, // 33 3
{0x18, 0x14, 0x12, 0x7f, 0x10}, // 34 4
{0x27, 0x45, 0x45, 0x45, 0x39}, // 35 5
{0x3c, 0x4a, 0x49, 0x49, 0x30}, // 36 6
{0x01, 0x71, 0x09, 0x05, 0x03}, // 37 7
{0x36, 0x49, 0x49, 0x49, 0x36}, // 38 8
{0x06, 0x49, 0x49, 0x29, 0x1e}, // 39 9
{0x00, 0x36, 0x36, 0x00, 0x00}, // 3a :
{0x00, 0x56, 0x36, 0x00, 0x00}, // 3b ;
{0x08, 0x14, 0x22, 0x41, 0x00}, // 3c <
{0x14, 0x14, 0x14, 0x14, 0x14}, // 3d =
{0x00, 0x41, 0x22, 0x14, 0x08}, // 3e >
{0x02, 0x01, 0x51, 0x09, 0x06}, // 3f ?
{0x32, 0x49, 0x79, 0x41, 0x3e}, // 40 @
{0x7e, 0x11, 0x11, 0x11, 0x7e}, // 41 A
{0x7f, 0x49, 0x49, 0x49, 0x36}, // 42 B
{0x3e, 0x41, 0x41, 0x41, 0x22}, // 43 C
{0x7f, 0x41, 0x41, 0x22, 0x1c}, // 44 D
{0x7f, 0x49, 0x49, 0x49, 0x41}, // 45 E
{0x7f, 0x09, 0x09, 0x09, 0x01}, // 46 F
{0x3e, 0x41, 0x49, 0x49, 0x7a}, // 47 G
{0x7f, 0x08, 0x08, 0x08, 0x7f}, // 48 H
{0x00, 0x41, 0x7f, 0x41, 0x00}, // 49 I
{0x20, 0x40, 0x41, 0x3f, 0x01}, // 4a J
{0x7f, 0x08, 0x14, 0x22, 0x41}, // 4b K
{0x7f, 0x40, 0x40, 0x40, 0x40}, // 4c L
{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // 4d M
{0x7f, 0x04, 0x08, 0x10, 0x7f}, // 4e N
{0x3e, 0x41, 0x41, 0x41, 0x3e}, // 4f O
{0x7f, 0x09, 0x09, 0x09, 0x06}, // 50 P
{0x3e, 0x41, 0x51, 0x21, 0x5e}, // 51 Q
{0x7f, 0x09, 0x19, 0x29, 0x46}, // 52 R
{0x46, 0x49, 0x49, 0x49, 0x31}, // 53 S
{0x01, 0x01, 0x7f, 0x01, 0x01}, // 54 T
{0x3f, 0x40, 0x40, 0x40, 0x3f}, // 55 U
{0x1f, 0x20, 0x40, 0x20, 0x1f}, // 56 V
{0x3f, 0x40, 0x38, 0x40, 0x3f}, // 57 W
{0x63, 0x14, 0x08, 0x14, 0x63}, // 58 X
{0x07, 0x08, 0x70, 0x08, 0x07}, // 59 Y
{0x61, 0x51, 0x49, 0x45, 0x43}, // 5a Z
{0x00, 0x7f, 0x41, 0x41, 0x00}, // 5b [
{0x02, 0x04, 0x08, 0x10, 0x20}, // 5c ¥
{0x00, 0x41, 0x41, 0x7f, 0x00}, // 5d ]
{0x04, 0x02, 0x01, 0x02, 0x04}, // 5e ^
{0x40, 0x40, 0x40, 0x40, 0x40}, // 5f _
{0x00, 0x01, 0x02, 0x04, 0x00}, // 60 `
{0x20, 0x54, 0x54, 0x54, 0x78}, // 61 a
{0x7f, 0x48, 0x44, 0x44, 0x38}, // 62 b
{0x38, 0x44, 0x44, 0x44, 0x20}, // 63 c
{0x38, 0x44, 0x44, 0x48, 0x7f}, // 64 d
{0x38, 0x54, 0x54, 0x54, 0x18}, // 65 e
{0x08, 0x7e, 0x09, 0x01, 0x02}, // 66 f
{0x0c, 0x52, 0x52, 0x52, 0x3e}, // 67 g
{0x7f, 0x08, 0x04, 0x04, 0x78}, // 68 h
{0x00, 0x44, 0x7d, 0x40, 0x00}, // 69 i
{0x20, 0x40, 0x44, 0x3d, 0x00}, // 6a j
{0x7f, 0x10, 0x28, 0x44, 0x00}, // 6b k
{0x00, 0x41, 0x7f, 0x40, 0x00}, // 6c l
{0x7c, 0x04, 0x18, 0x04, 0x78}, // 6d m
{0x7c, 0x08, 0x04, 0x04, 0x78}, // 6e n
{0x38, 0x44, 0x44, 0x44, 0x38}, // 6f o
{0x7c, 0x14, 0x14, 0x14, 0x08}, // 70 p
{0x08, 0x14, 0x14, 0x18, 0x7c}, // 71 q
{0x7c, 0x08, 0x04, 0x04, 0x08}, // 72 r
{0x48, 0x54, 0x54, 0x54, 0x20}, // 73 s
{0x04, 0x3f, 0x44, 0x40, 0x20}, // 74 t
{0x3c, 0x40, 0x40, 0x20, 0x7c}, // 75 u
{0x1c, 0x20, 0x40, 0x20, 0x1c}, // 76 v
{0x3c, 0x40, 0x30, 0x40, 0x3c}, // 77 w
{0x44, 0x28, 0x10, 0x28, 0x44}, // 78 x
{0x0c, 0x50, 0x50, 0x50, 0x3c}, // 79 y
{0x44, 0x64, 0x54, 0x4c, 0x44} // 7a z
// ... (verkort voor leesbaarheid)
};
void LcdWrite(byte dc, byte data) {
digitalWrite(PIN_DC, dc);
digitalWrite(PIN_SCE, LOW);
shiftOut(PIN_SDIN, PIN_SCLK, MSBFIRST, data);
digitalWrite(PIN_SCE, HIGH);
}
void LcdCharacter(char character) {
LcdWrite(LCD_D, 0x00);
for (int index = 0; index < 5; index++) {
LcdWrite(LCD_D, ASCII[character - 0x20][index]);
}
LcdWrite(LCD_D, 0x00);
}
void LcdClear(void) {
for (int index = 0; index < LCD_X * LCD_Y / 8; index++) {
LcdWrite(LCD_D, 0x00);
}
}
void LcdInitialise(void) {
pinMode(PIN_SCE, OUTPUT);
pinMode(PIN_RESET, OUTPUT);
pinMode(PIN_DC, OUTPUT);
pinMode(PIN_SDIN, OUTPUT);
pinMode(PIN_SCLK, OUTPUT);
digitalWrite(PIN_RESET, LOW);
digitalWrite(PIN_RESET, HIGH);
LcdWrite(LCD_C, 0x21);
LcdWrite(LCD_C, 0xB1);
LcdWrite(LCD_C, 0x04);
LcdWrite(LCD_C, 0x14);
LcdWrite(LCD_C, 0x20);
LcdWrite(LCD_C, 0x0C);
}
void LcdString(char *characters) {
while (*characters) {
LcdCharacter(*characters++);
}
}
void setup() {
pinMode(11, INPUT); pinMode(12, INPUT); pinMode(14, INPUT);
pinMode(15, INPUT); pinMode(16, INPUT); pinMode(17, INPUT);
pinMode(18, INPUT); pinMode(19, INPUT);
pinMode(13, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT);
pinMode(10, OUTPUT); pinMode(2, OUTPUT);
digitalWrite(8, HIGH); digitalWrite(9, HIGH);
digitalWrite(10, HIGH); digitalWrite(13, LOW);
Serial.begin(9600);
Serial.println("=> Siap");
LcdInitialise();
LcdClear();
LcdString(" Masukkan Koin Rp500 atau Koin Rp1000 @ Rp2000");
delay(500);
}
void loop() {
int x = analogRead(14);
// State machine voor muntverwerking, productselectie en afgifte
// (Volledige code in origineel - staatmachine met 22+ states)
// Zie GitHub voor complete broncode
}
Aangepaste Onderdelen en Behuizingen
Dit is een printscreen van mijn SolidWorks 3D-model voor dit project.
Productieproces
- Automaatjes: Een Amerikaanse Industriemacht van $36,6 Mrd
- K30 CO2-sensor: Real-time binnenluchtkwaliteitmonitoring met Arduino
- Bouw een Digitale Lichaamslengtemeter: Je Lengte Meten met Arduino en Lasersensor
- Een DFRobot Capacitieve Vingerafdruksensor integreren met Arduino of ESP8266
- Bouw een Sensor Toren met Arduino Cloud: Temperatuur, Beweging & Gas Monitoring
- Slimme beweegactiverde waterpistool gebouwd met Arduino Nano
- Omgekeerde Inleverautomaat (RVM): DIY Slim Recyclingsysteem Kit
- Compact Arduino Radarsysteem met HC-SR04 Ultrasonische Sensor & 1.8" Display
- Verse melkautomaten ontdekken: Gemakkelijk, betaalbaar en ecologisch
- Ontdek Noedelautomaten: Hoe Ze Werken & Wat Je Kunt Krijgen
- Winst Maximaliseren: De Beste Prijs Instellen voor Gebruikte Machines