Eslam Ali
Published

Arduino-Based Bitcoin Candy Vending Machine

Implement your own Bitcoin candy vending machine that accepts testnet Bitcoins and dispenses goods.

AdvancedFull instructions provided12 hours19,692
Arduino-Based Bitcoin Candy Vending Machine

Things used in this project

Hardware components

Wemos D1 Mini
Espressif Wemos D1 Mini
×1
Jumper wires (generic)
Jumper wires (generic)
×25
Arduino Mega 2560
Arduino Mega 2560
×1
Breadboard (generic)
Breadboard (generic)
×1
Capacitor 470 µF
Capacitor 470 µF
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
×1
Adafruit Servo motors
×4
Adafruit PushButton
×4
Resistor 2.21k ohm
Resistor 2.21k ohm
Better 2.7K Ohms
×1
Power Supply
×1

Software apps and online services

Arduino IDE
Arduino IDE
Bitcoin Testnet application
Koyn Library

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)
Or use the regular saw tools to cut off the wood

Story

Read more

Custom parts and enclosures

Vending Machine

Schematics

Vending Machine

Code

BitcoinVendingMachine(Wemos)

Arduino
This is the code for Wemos board
#define MAX_HDLC_FRAME_LENGTH 32


#include "Arduhdlc.h"
#include "Koyn.h"

BitcoinAddress myAddress("muutGNozJxnA3z4nMrcKvZvSnz8WHFWNb2", ADDRESS_ENCODED);

Arduhdlc hdlc(&byteSender, &frameCallback, MAX_HDLC_FRAME_LENGTH);

void byteSender(uint8_t data) {
  Serial.write(data);
}

void frameCallback(const uint8_t *data, uint16_t length) {

}

void setup() {
  Serial.begin(115200);
  // CONNECT TO WIFI
  wifiConnect();
  Koyn.begin();
  Koyn.onNewTransaction(&paymentCallback);
  //  Koyn.onNewBlockHeader(&blockCallback);
}

void loop() {
  if (Koyn.isSynced()) {
    Koyn.trackAddress(&myAddress);
  }
  Koyn.run();
}

void paymentCallback(BitcoinTransaction tx) {
  Serial.println("Got Transaction");
  for (int j = 0; j < tx.getOutputsCount(); j++)
  {
    BitcoinAddress to;
    tx.getOutput(j, &to);
    if (to == myAddress) {
      Serial.println("My Address");
      uint64_t amount = tx.getOutputAmount(j);
      hdlc.frameDecode((uint8_t *)&amount,8);
      break;
    }
  }
}

void wifiConnect()
{
  WiFi.begin("SSID_NAME", "SSID_PASSWORD");
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.print("Connected, IP address: ");
  Serial.println(WiFi.localIP());
}

BitcoinVendingMachine(Mega)

Arduino
This is the code for Arduino Mega
#include <LiquidCrystal.h> // includes the LiquidCrystal Library
#include <Servo.h>
#include "Arduhdlc.h"

#define MAX_HDLC_FRAME_LENGTH 32

#define button1 13
#define button2 12
#define button3 11
#define button4 10

#define button1_price 1000000
#define button2_price 2000000
#define button3_price 3000000
#define button4_price 4000000

LiquidCrystal lcd(27, 26, 25, 24, 23, 22);
Servo servo1, servo2, servo3, servo4;

Arduhdlc hdlc(&byteSender, &frameCallback, MAX_HDLC_FRAME_LENGTH);

int buttonPressed;

long long balance = 0;

void byteSender(uint8_t data) {
    Serial.write(data);
}

void frameCallback(const uint8_t *data, uint16_t length) {
  if(length == 8){
    balance += *((long long *)data);
  }
}

void setup() {
  Serial.begin(115200);
  lcd.begin(16, 2); 

  servo1.attach(4);
  servo2.attach(5);
  servo3.attach(6);
  servo4.attach(7);

  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(button3, INPUT_PULLUP);
  pinMode(button4, INPUT_PULLUP);

  pinMode(9,OUTPUT);
  analogWrite(9,100);
  lcd.clear();
}

void loop() {
  lcd.setCursor(0, 0);
  if(balance<=0){
    lcd.print(" Send Bitcoins! ");}
  else{
    delay(10);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Select your item");
    lcd.setCursor(0, 1);
    lcd.print("Balance = ");
    lcd.print((float)balance/100000000ul);
    
    while (balance>0) {
      if (digitalRead(button1) == LOW) {
        if(balance>=button1_price){
          balance -=button1_price;
          buttonPressed = 1;
          break;
        }
        else{
          lcd.setCursor(0, 0);
          lcd.print(" Topup balance! ");
          delay(1000);
          lcd.setCursor(0, 0);
          lcd.print("Select your item");
        }
      }
      if (digitalRead(button2) == LOW) {
        if(balance>=button2_price){
          balance -=button2_price;
          buttonPressed = 2;
          break;
        }
        else{
          lcd.setCursor(0, 0);
          lcd.print(" Topup balance! ");
          delay(1000);
          lcd.setCursor(0, 0);
          lcd.print("Select your item");
        }
      }
      if (digitalRead(button3) == LOW) {
        if(balance>=button3_price){
          balance -=button3_price;
          buttonPressed = 3;
          break;
        }
        else{
          lcd.setCursor(0, 0);
          lcd.print(" Topup balance! ");
          delay(1000);
          lcd.setCursor(0, 0);
          lcd.print("Select your item");
        }
      }
      if (digitalRead(button4) == LOW) {
        if(balance>=button4_price){
          balance -=button4_price;
          buttonPressed = 4;
          break;
        }
        else{
          lcd.setCursor(0, 0);
          lcd.print(" Topup balance! ");
          delay(1000);
          lcd.setCursor(0, 0);
          lcd.print("Select your item");
        }
      }
      readFromSerial();
      lcd.setCursor(0, 1);
      lcd.print("Balance = ");
      lcd.print((float)balance/100000000ul);
    }
    
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Delivering...");
    
    switch (buttonPressed) {
      case 1:
        // Rotate the helical coil, discharge the selected item
        servo1.writeMicroseconds(1000); // rotate
        delay(2000);
        servo1.writeMicroseconds(1500);  // stop
        delay(500);
        break;
        
       case 2:
        // Rotate the helix, push the selected item
        servo2.writeMicroseconds(1000); // rotate
        delay(2000);
        servo2.writeMicroseconds(1500);  // stop
        delay(2000);
        break;
  
        case 3:
        // Rotate the helix, push the selected item
        servo3.writeMicroseconds(1000); // rotate
        delay(2000);
        servo3.writeMicroseconds(1500);  // stop
        delay(500);
        break;
  
        case 4:
        // Rotate the helix, push the selected item
        servo4.writeMicroseconds(1000); // rotate
        delay(2000);
        servo4.writeMicroseconds(1500);  // stop
        delay(500);
        break;
    }
    
    lcd.clear(); // Clears the display
    lcd.setCursor(0, 0);
    lcd.print("Item delivered!"); // Prints on the LCD
    delay(1000);
  }
  readFromSerial();
}

void readFromSerial() {
    while (Serial.available()) {
        hdlc.charReceiver(Serial.read());
    }
}

Koyn

A fully decentralized and trustless Bitcoin light (aka SPV) client implementation for the Arduino platform based on Electrum protocol.

Arduhdlc

A simple library protocol for Arduino boards

Credits

Eslam Ali

Eslam Ali

2 projects • 17 followers

Comments