DEV Community

Cover image for Vending Machine Controller
Jorge Martin
Jorge Martin

Posted on

Vending Machine Controller

This is the blog of the P3-SETR, where I have created a Vending Machine Controller using an Arduino Kit.

Schematic

Here I show you the schematic of the circuit.
Arduino Schematic

Components

Component Name Amount
Arduino Uno board x1
Protoboard x1
LEDs x2
Button x1
DHT11 sensor x1
Ultrasonic sensor x1
Joystick x1
LCD x1
330Ω resistance x3
2kΩ resistance x1

Requirements

  • One of the LEDs must be connected to a digital input (pin 1 to pin 13) in order to be able to modify the LED intensity using pulse-width modulation (PWM).
  • The button must be connected in the pin 2 or 3, those pins are associated to the interruptions.
  • The joystick have 2 potentiometer (X and Y) that generate analogic signals so the pins related to the X and Y axis of the joystick must being connected to an analogic input.
  • The button of the joystick must be connected to a digital input in order to be able to declare the button as a pull-up input.

Coding

Libraries

During this proyect we need to use multiple libraries.

  • This library is related to the implementation and management of threads.
#include <Thread.h>
#include <ThreadController.h>
#include <StaticThreadController.h>
Enter fullscreen mode Exit fullscreen mode
  • This library is used to control the LCD.
#include <LiquidCrystal.h>
Enter fullscreen mode Exit fullscreen mode
  • This library is necessary to interact with the DHT sensor.
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
Enter fullscreen mode Exit fullscreen mode
  • This library is used to set and control timers.
#include "TimerOne.h"
Enter fullscreen mode Exit fullscreen mode
  • This library is used to set and control the watchdog.
#include <avr/wdt.h> 
Enter fullscreen mode Exit fullscreen mode

Threads

To make this project i used 5 differents thread associated to periodic tasks.

  • Show distance in real time.
// Creation of threads
Thread show_distanceThread = Thread();

void setup(){
  Serial.begin(9600);

  // show_distance Thread config
  show_distanceThread.enabled = true;
  show_distanceThread.setInterval(200);
  show_distanceThread.onRun(callback_measure_distance);
}

void callback_measure_distance(){
  // Send a 10us pulse
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // Calculate the distance in cm
  t = pulseIn(echoPin, HIGH);
  d = t/59;

  // Print on the LCD the actual disntance
  lcd.clear();
  lcd.print(d);
  lcd.print(" cm");
}
Enter fullscreen mode Exit fullscreen mode
  • Show how much time has passed since the program started.
// Creation of threads
Thread clockThread = Thread();

void setup(){
  Serial.begin(9600);

   // clock Thread config
  clockThread.enabled = true;
  clockThread.setInterval(200);
  clockThread.onRun(callback_clock);
}

void callback_clock(){
  initial_time = millis();
  lcd.clear();
  lcd.print(initial_time);
}
Enter fullscreen mode Exit fullscreen mode
  • Check if someone is near the machine (< 1m).
// Creation of threads
Thread check_distanceThread = Thread();

void setup(){
  Serial.begin(9600);

   // check_distance Thread config
  check_distanceThread.enabled = true;
  check_distanceThread.setInterval(2500);
  check_distanceThread.onRun(callback_check_distance);
}

void callback_check_distance() {
  // Send a 10us pulse
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // Calculate the distance in cm
  t = pulseIn(echoPin, HIGH);
  d = t/59;
  lcd.clear();
  // If someone is < 1m from the sensor, distance = true
  if (d < 100){
    distance = true;
  }
  else{
    distance = false;
    show_temp = true;
  }

  return distance, show_temp;
}
Enter fullscreen mode Exit fullscreen mode

Controller

For the next 2 threads we will need a controller, because one of the threads will show the temperature and the other will show the humidity, they must update themselves, but they must be executed interleaved.

  • Show temperature thread.
// Creation of threads
Thread measure_tempThread = Thread();

void setup(){
  Serial.begin(9600);

   // measure_temp Thread config
  measure_tempThread.enabled = true;
  measure_tempThread.setInterval(1000);
  measure_tempThread.onRun(callback_measure_temp);
}

void callback_measure_temp() {
  // Lógica para medir la temperatura aquí
  temperature = dht.readTemperature();
  lcd.clear();
  lcd.print("T: ");
  lcd.print(temperature);
  lcd.print("C");
  delay(1000);
}
Enter fullscreen mode Exit fullscreen mode
  • Show humidity thread.
// Creation of threads
Thread measure_humThread = Thread();

void setup(){
  Serial.begin(9600);

   // measure_hum Thread config
  measure_humThread.enabled = true;
  measure_humThread.setInterval(1000);
  measure_humThread.onRun(callback_measure_hum);
}

void callback_measure_hum() {
  // Lógica para medir la humedad aquí
  humidity = dht.readHumidity();
  lcd.clear();
  lcd.print("H: ");
  lcd.print(humidity);
  lcd.print("%");
}
Enter fullscreen mode Exit fullscreen mode
  • Controller for the two threads.
// Creation of the controller
ThreadController controller = ThreadController();

void setup(){
  Serial.begin(9600);

   // adding measure_temp Thread and measure_hum Thread to the controller
  controller.add(&measure_tempThread);
  controller.add(&measure_humThread);
}

void admin_temp(){
  while (analogRead(pinX) > 400){
    controller.run();
  }
}
Enter fullscreen mode Exit fullscreen mode

Interruption

I used interruptions to be able to enter the admin mode and reset while serving a coffee.
I used 2 types of interruptions:

  • Hardware interruption.
void setup() {
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(BUTTON), button_pressed, CHANGE);
}
Enter fullscreen mode Exit fullscreen mode
  • Software interruption.
void setup() {
  Serial.begin(9600);
  Timer1.initialize(1000000);  
  Timer1.attachInterrupt(callback_count);
}
Enter fullscreen mode Exit fullscreen mode
  • Both interruptions:
void button_pressed() {
  // Enable interruptions
  interrupts();

  // Enable the watchdog (8sec)
  wdt_enable(WDTO_8S);

  // If the button is not pressed
  if (digitalRead(BUTTON) == HIGH) {
    wdt_disable();

    // Stops the timer
    Timer1.stop();

    // Depending on the time and where were you before entering the interruption does a thing or an other
    if (pressed_time >= 2 && pressed_time <= 3) {
      // Reset pressed_time
      pressed_time = 0;
      Serial.println("Botón pulsado entre 2 y 3 segundos");
      if (check_serve == true){
        check_serve = false;
        menu();
      }
    } 
    else if (pressed_time >= 5) {
      // Reset pressed_time
      pressed_time = 0;
      Serial.println("Botón pulsado más de 5 segundos");
      if (check_admin == false){
        admin();
      }
      else if (check_admin == true){
        analogWrite(LED2, 0);
        digitalWrite(LED1, LOW);
        menu();
      }
    }
    // Reset pressed_time
    pressed_time = 0;

  } 
  else {
    // Enable interruptions
    interrupts();

    // Enable watchdog(8s)
    wdt_enable(WDTO_8S);

    // Start the timer
    Timer1.start();
  }
}
void callback_count() {
  // Disable interruptions
  noInterrupts();

  pressed_time++;
  Serial.println(pressed_time);
}
Enter fullscreen mode Exit fullscreen mode

Variables

To modify variables that are inside interruptions, we need to declare them as volatile.

volatile bool check_admin = false;
volatile int pressed_time;
volatile bool check_serve = false;
Enter fullscreen mode Exit fullscreen mode

TimerOne

We need to use TimerOne library because the Timer0 of the Arduino board doesn´t work while it´s inside an interruption, so, to count how many seconds have you been pressing the button we need it.

Watchdog

This program has a watchdog in the interruptions, in case something has blocked or is not responding to the behavior wanted, the watchdog resets the system after 8 seconds.

void setup() {
  Serial.begin(9600);
  // Disable the watchdog
  wdt_disable();
}

void button_pressed() {
  // Enable the watchdog (8sec)
  wdt_enable(WDTO_8S);
}
Enter fullscreen mode Exit fullscreen mode

Functionality

Top comments (1)

Collapse
 
stockdale_roger_999e292a7 profile image
stockdale roger

I want to know this good article which haven't person to look