© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
E. Wu, D. MaslovRaspberry Pi Retail Applicationshttps://doi.org/10.1007/978-1-4842-7951-9_3

3. Vending Machine

Elaine Wu1   and Dmitry Maslov1
(1)
Shenzhen, China
 

Problem Overview

Vending machines are great! They help selling goods when personnel is limited, for example at night or in remote, underserviced locations.

The first modern coin-operated vending machines were introduced in London, England in the early 1880s. They dispensed postcards. That machine was invented by Percival Everitt in 1883 and soon became a widespread feature at railway stations and post offices, dispensing envelopes, postcards, and notepaper. See Figure 3-1.
Figure 3-1

An early coin-operated vending machine

Since then, vending machines have increased in complexity. Nowadays, they are used to sell almost anything, from iced drinks to underwear. According to a report by the Food and Agriculture Organization of the United Nations (FAO), in 2012 there were about 60 million vending machines in the world. The top four countries in terms of vending machines are Japan, China, United States, and Russia. The global vending machine industry was worth $41 billion in 2014 and is expected to reach $52 billion by 2019, with a CAGR of 4.4 percent.

There are several types of vending machines. The most common ones are:
  • Candy and snack vending machines

  • Coffee vending machines

  • Fuel vending machines

  • Redemption vending machines

  • Vending kiosk vending machines

And of course there are many more! See Figure 3-2.
Figure 3-2

A vending machine in Carpi, Italy that dispenses hot pizza

As a business owner, you might need a specific type of vending machine or even a customized design. In this chapter, you learn how to use the Raspberry Pi Compute Module to process the orders and control the hardware of the machine. Furthermore, since the compute module cannot be used standalone without a carrier board, you learn how to interface the Raspberry Pi Compute Module with a customized carrier board for the specific hardware application.

Business Impact

As mentioned, vending machines can serve customers in times and locations where allocating full-time personnel is not economically viable. The main economic benefit of vending machines is their very low upkeep, especially as compared to human workers. The only things needed are electricity and regular maintenance/restocking services, thus they reduce labor costs in retail establishments. For example, a grocery store may want to have an employee restocking the shelves, but the cost of employing a worker is not justified by the extra revenue generated. Employing a vending machine allows the store to determine how much labor is needed to keep the shelves stocked.

Vending machines can also help a company have a more positive image with its customers and increase the coverage of its business. For example, a sandwich shop may want to offer delivery, but it would be too expensive to employ full-time delivery drivers. A vending machine could be placed in the lobby of the shop and the sandwiches could be delivered by a company that already delivers mail or packages.

Vending machines have the potential to increase employee productivity. Because cashiers are not needed, more registers can be opened without having to hire more employees. This leads to shorter lines and faster service.

Also, vending machines can provide a good level of privacy and security, as there is no direct human contact involved. This is especially true for coin-operated vending machines, as they don't have touchscreens or any other ways to identify the customer.

Seeing all the benefits vending machines can provide for retail businesses, you might be wondering if you can leverage Raspberry Pi 4 hardware to utilize this technology. The answer depends on the scale of your operations and the exact nature of services/products sold. Unlike with the project described in Chapter 2, creating/customizing a vending machine is a task only suitable for medium-to-large scale enterprises. Smaller companies might find it is more cost-effective to use existing products. On the other hand, if your company sells a product that is not very well covered by existing options, building your own vending machine might make a lot of sense from an economic perspective. With Raspberry Pi 4 Compute Module as the hardware backbone, it is not too complicated to do so!

Related Knowledge

Vending machines rely on a number of different technologies to perform their functions. They typically use electricity to power the lights and the refrigeration. Some of the more advanced machines may use computerized systems that are capable of monitoring inventory levels and can ensure that the product is available when the customer wants it. Vending machines are a good example of the interplay between technology and business. The business requirements of a company will determine which technologies are best suited for that application.

Vending machines' mechanical systems differ drastically depending on the application, but their electronic components are similar. In general, a modern vending machine needs:
  • A screen to interact with customers

  • A computer to process requests and receive payments

  • A controller for the mechanical system

Optional components include:
  • A card reader for accepting purchases with plastic cards

  • A WiFi/4G module for Internet connection

  • A stock-monitoring system, such as one using computer vision

The regular Raspberry Pi 4 has too many unnecessary components that won’t be useful for this application, such as USB ports, Ethernet ports, and HDMI connectors. On the other hand, it lacks a touchscreen and for mechanical systems control, an extension board must be used. All of that makes it impractical to use the standalone Raspberry Pi 4 board. Fortunately, there is a better solution—the Raspberry Pi 4 Compute Module (hereinafter referred to as Raspberry Pi 4 CM for brevity). It has a compact form factor for deeply embedded applications.

Raspberry Pi 4 CM incorporates a quad-core ARM Cortex-A72 processor, dual video output, and a wide selection of other interfaces. It contains many of the same specifications as the original Raspberry Pi 4, but it does away with most of the connectors, opting for a couple of 100-pin, high-density Hirose connectors on the underside. Rather than be an affordable desktop placement like the traditional Raspberry Pi, the Raspberry Pi 4 CM is intended for industrial applications where the module is embedded into a custom PCB and enclosure. It is available in 32 variants, with a range of RAM and eMMC Flash options, and with or without wireless connectivity. See Figure 3-3.
Figure 3-3

A hardware overview of the Raspberry Pi 4 Compute Module

Unlike a standalone Raspberry Pi 4 board, the Raspberry Pi 4 CM cannot be used without a carrier board, since it lacks IO interfaces. There is an CM4IO official carrier board for the Raspberry Pi 4 CM, which contains most of the inputs and outputs of the standard Raspberry Pi 4 and some more. See Figure 3-4.
Figure 3-4

Reference carrier board for the Raspberry Pi 4 CM

As you probably have guessed, the reference carrier board is not meant to be used in production. Instead, since the designs and schematics for it are freely available from the official Raspberry Pi source, it is meant to serve as a reference for people building their own carrier boards. Additionally, a handful of other hardware manufacturers offer carrier boards tailored for different applications. For example, the Dual Gigabit Ethernet carrier board for Raspberry Pi CM4 from Seeed Studio offers plentiful wired/wireless connectivity options in a compact form factor. These are especially suitable for designing/implementing router/NAS/Internet-connected smart camera solutions. See Figure 3-5.
Figure 3-5

Seeed Studio’s Dual Gigabit Ethernet carrier board

Or, the Gumstix Raspberry Pi CM4 PoE smart camera—which contains a Google Edge TPU ML Inference accelerator, camera connector, and a PoE-enabled Ethernet port—is ideal for smart, compact camera uses. See Figure 3-6.
Figure 3-6

Gumstix Raspberry Pi CM4 PoE smart camera

There are dozens of carrier boards available at the moment of writing this book and this list will only expand in the future.

If you decide to pick a readily available carrier board, pay attention to the following specifications:
  • Display/touchscreen connector

  • I2C/SPI/UART interfaces

  • LTE module integration/support

  • RTC (real-time clock) module and battery for it

If there is no board on the market that completely satisfies your product requirements, designing one is not a difficult task. Since this book focuses on use case analysis and software layer examples, we don’t providing a complete step-by-step guide to designing a carrier board. Instead, we walk you through the important details and know-hows of the process, so that you know how to explain your requirements to the board designer.

Decide on PCB Manufacturer Beforehand

Different PCB manufacturers have different rules on board designs and what each manufacturer is capable of doing. So ideally you’ll want to decide on a PCB manufacturer before you start designing the board or give the requirements to the third-party designer. Well-known PCB manufacturers include OSHPARK from the United States (see Figure 3-7), PCB TRAIN from the UK, and Seeed Studio’s Fusion service from PRC.
Figure 3-7

Logo of OSHPARK, a prominent PCB manufacturer

Of course, there are many more. Very likely, your designer—be it a freelancer specialist or a company—has contacts with the PCB manufacturing service their clients use most often.

Determine the Interfaces You Need

Prototyping a PCB can be a time-consuming process, especially if you ship the PCB or PCBA from manufacturing facilities overseas. So it is very important to decide what elements you need on the carrier board and create a working prototype, which includes the hardware and software, to make sure you’re not missing anything in the requirements to the carrier board design. With a working prototype, it is also easier to present the project to the PCB designer.

Look at Third-Party Open Source Designs for Your elements

In the open source world, there are many community-created designs, which you might find applicable to your project. Some of them are very advanced and you can use them with little or even no modification. See Figure 3-8.
Figure 3-8

RHINO, Reconfigurable Hardware Interface for Computing and Radio, is a relatively large platform for developing software-defined radio applications

If you’re building a consumer electronics device, you look at the Open Source Hardware page on the Element 14 community.

Look at How Other People Have Solved the Same Problem

At the very least, you might get some inspiration from what others have done before you. This is especially helpful if you have a very specific problem and there are no open source projects addressing this issue directly. OSHPARK has a great page with various open source projects for PCB designs.

Decide on Your Form Factor

Another very important decision is to decide what form factor to use for the carrier board, i.e. what will be the dimensions of the carrier board and how it will fit into the vending machine. If you plan to use a touchscreen for customer interaction, you should also keep that in mind when designing a board, so that the screen can be integrated with the carrier board for easier maintenance.

Determine the Location of Connectors and Headers

There are many different ways to place elements on the carrier board. You can put them on the front panel, on both sides of the board, or even under the board. It is very important to think about how you will place these elements and make sure you won’t be blocking any connectors or headers with other elements.

Take Special Care of Heatsinks and Cooling Elements

A lot of Raspberry Pi 4 Compute Module interfaces are very close to each other, especially to the CPU. You need to make sure that there is enough space around Broadcom BCM2711 SoC and even more space around the connectors, like the HDMI and USB ports. See Figure 3-9.
Figure 3-9

A heatsink for Raspberry Pi 4 CM

The last thing you want is a thermal runaway because of insufficient cooling while operating or an overheat while soldering the board, which is even more dangerous.

Implementation

For this chapter’s project, you’re going to implement a minimal prototype of a vending machine that can be controlled with a web interface displayed on the user's phone. This interface can be accessed by scanning a QR code on the vending machine. You’ll also use a servo motor to push imaginary wares to your customers.
  1. 1)

    Implement servo control with Raspberry Pi 4.

     
  2. 2)

    Implement a simple web server that can be accessed on a local network and can be used to “buy” things from the vending machine.

     
  3. 3)

    Add a PayPal payment processor.

     

Implement Servo Control with Raspberry Pi 4

Servos typically have three inputs, two of which supply power to the motor located inside the plastic body. The third input controls how much the servo turns. See Figure 3-10.
Figure 3-10

Very common 9g micro-servo from TowerPro

Usually, the input signal is pulse-width modulated (PWM) and its frequency doesn’t change over time. Instead, the servo motor rotates to a certain angle when the duty cycle of the PWM input signal changes. The servo used in this example can turn 180 degrees in total (90 degrees in each direction). When the duty cycle is 5% (a one-millisecond long, high pulse), the servo rotates to its minimum position. If the duty cycle changes to 10% (which is a two-millisecond long, high pulse), the servo rotates all the way to the right. Duty cycles in between correlate to different angles between -90° and +90°. However, these numbers might vary for different servos and between manufacturers. Therefore, it’s always necessary to consult the datasheet of the servo.

Note that the Raspberry Pi shouldn’t supply the voltage to the servo. Instead, employ an external power supply to drive the servo motor, because the Raspberry Pi’s GPIO pins might be unable to supply enough power to make the motor turn at an acceptable rate.

To make a Raspberry Pi control a servo motor, connect the +5 V and GND lines of the servo to an external power supply and the remaining signal wire to any I/O pin of the Raspberry Pi. See Figure 3-11.
Figure 3-11

Connection schematic for Raspberry Pi 4 and two servos

Don’t forget to connect any GND pin of the Raspberry Pi to the ground of the power supply as well.

As mentioned, servos typically expect a PWM signal that tells them where to turn. Therefore, there are several methods to rotate a servo to a specific angle. One method is to use the gpiozero library that contains a servo module.

You can use 64-bit image of Raspberry Pi OS as a starting point, the same one you flashed on the SD card in Chapter 2.

You can use pip to install the library on a Raspberry Pi. If the rpi.gpio package isn't installed, download it as well. Otherwise, the gpiozero library won’t work:
sudo apt-get install python3-rpi.gpio
pip3 install gpiozero
Then, from the Chapter_3 folder, execute the following command to install the rest of the dependencies necessary to run the other examples:
pip3 install -r requirements.txt
Once that’s done, it’s possible to execute the following script with Python3 (Chapter_3/exercise_1/test_servo.py):
from gpiozero import Servo
from time import sleep
servo = Servo(25)
try:
      while True:
      servo.min()
      sleep(0.5)
      servo.mid()
      sleep(0.5)
      servo.max()
      sleep(0.5)
except KeyboardInterrupt:
      print("Program stopped")
As you can see, this library allows you to quickly turn the servo to one of three predefined positions. This simple Python script first imports the required libraries. Then, it defines that the servo is connected to pin 25 before starting an infinite loop in which the servo gets rotated to its minimum, mid, and maximum positions. In between angle changes, the script waits for half a second. See Figure 3-12.
Figure 3-12

A 9g servo connected to Raspberry Pi 4

Since servos are essentially just DC motors with a potentiometer and a control chip that allows them to turn to a certain angle, you can instruct the servo to turn to a precise angle with the help of the AngularServo class in the gpiozero library.

Use the following code to create an AngularServo class object and let the servo rotate its shaft slowly from 0 (initial position) to 180 (the maximum position). You can find the following script at Chapter_3/exercise_1/test_servo_precise.py:
from gpiozero import AngularServo
import time
s = AngularServo(17, min_angle=0, max_angle=180)
try:
    for i in range(180):
       s.angle = i
       time.sleep(0.1)
except KeyboardInterrupt:
    print("Program stopped")
As mentioned in the documentation for the gpiozero library, to reduce servo jitter, use the pigpio pin driver rather than the default RPi.GPIO driver (pigpio uses DMA sampling for much more precise edge timing). You can use the pigpio pin driver by adding the following lines to the beginning of the script:
from gpiozero.pins.native import NativeFactory
from gpiozero import Device, LED
Device.pin_factory = NativeFactory()

Now that you know how to control a servo, it is time to work on the second element of the vending machine—user interaction.

Implement a Simple Web Server with Flask

In order to create the web server, you will be using a Python microframework called Flask. Flask is a web framework. It’s a Python module that lets you easily develop web applications. It has a small and easy-to-extend core and allows for implementing features like URL routing and template engine. It’s easy to get started with Flask, because it doesn’t have a huge learning curve.

On top of that, it’s very explicit, which increases readability. To create the “Hello World” app, you only need a few lines of code.

This is a boilerplate code example.
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello World!'
if __name__ == '__main__':
    app.run()
If you want to develop on your local computer, you can do so easily. Save this program as server.py and run it with python server.py .
python server.py
 * Serving Flask app "hello"
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

It then starts a web server that’s available only on your computer. In a web browser, open localhost on port 5000 (the URL) and you’ll see “Hello World” show up.

You can see the example code for the vending machine interface in the Chapter_3/exercise_2 folder. Let’s go through the most important parts of the code.
qrcode = pyqrcode.create('http://' + get_ip()+ ':5000')
print(qrcode.terminal(quiet_zone=1))
This creates a QR code using a dedicated library called pyqrcode . The QR code contains the IP address and the port of the server and prints this out in the terminal. You then use your phone’s camera to scan that code and visit a web page that contains a vending machine control interface.
app = Flask(__name__)
app.run(host='0.0.0.0', port=5000, debug=True)

These two lines are responsible for creating the Flask web server.

You then use the route() decorator to tell Flask what URL should trigger the function. The vending machine interface will have the following pages:
@app.route("/")
This is the main page, which will contain items, their prices, and the buttons to purchase an item.
@app.route("/<item>/<action>")
This route will get the item name and action (“buy”) from the user's browser when the user clicks an item button. In the sample app, it will redirect the user to the success page.
@app.route("/success")
@app.route("/cancel")

These two routes display a payment success or failure message. The success route function will also trigger servo movement, which is supposed to push the goods the customer purchased out of the shelf.

It stores the items’ names, prices, and availability status in a dictionary as follows:
item_dict = {'coke': {'price':1, 'available': True},
'energy bar': {'price':2.5, 'available': True},
'chewing gum': {'price':0.5, 'available': True}}
Then, when the main page is visited, the program passes the values from this dictionary to the .html template :
templateData = {
'items' : item_dict
}
return render_template('main.html', **templateData)
Let’s look at the contents of the main.html file located in the templates folder. This is a Jinja template and it resembles Python code. For example
{% for item in items %}
This line loops through the values in the items entry and renders the following elements for each item:
<h2>{{ item }}
{% if items[item].available == true %}
<strong>{{ items[item].price}} USD</strong></h2><div class="row"><div class="col-md-2">
<a href="/{{item}}/buy" class="btn btn-block btn-lg btn-default" role="button">Buy</a></div></div>
{% else %}
<strong>{{ items[item].price}} USD </strong></h2><div class="row"><div class="col-md-2">
<a href="/{{item}}/buy" class="btn btn-block btn-lg btn-primary" role="button">Not available</a></div></div>
{% endif %}
{% endfor %}
This template block writes the name of the item in bold and then, depending on if the item’s available value is true or not, displays “Buy” or “Not available” on the button. Pressing the button will cause the browser to visit the /name-of-the-item/buy route (e.g., /cola/buy).
@app.route("/<item>/<action>")
def action(item, action):
   global hostname
   print(item, item_dict[item]['price'])
   return redirect(hostname + "/success", code=302)
Which in turn will call an action function, which prints the name and price of the item and redirects the user to the /success route of the web server.
@app.route("/success")
def success():
   global hostname
   control_servo('servo.min')
   return render_template('success.html')
The /success route of the server sends the servo to its minimum angle and renders the success.html template with very simple content.
<body>
<h1>Vedi Vending</h1>
<h2>Order successful</h2>
Please take your purchase!
<meta http-equiv="refresh" content="10; URL=/" />
</body>
</html>

The <meta http-equiv="refresh" content="10; URL=/" /> command will cause the user's browser to automatically go back to the server's main page after ten seconds.

You can run the application from the Chapter_3/exercise_2 folder by typing the following in the terminal:
python3 app.py
It will display a QR code, which you need to scan with your phone’s camera application. For this example your phone needs to be on the same network as the Raspberry Pi. See Figure 3-13.
Figure 3-13

An interface that can be seen from a mobile phone browser after scanning the QR code

We discuss how to implement a more scalable variant in the “Pro Tips” section of this chapter.

You can now make “purchases” from the vending machine with your phone.

Of course, unless you’re going to create a charity vending machine, you want to add a payment option to the device. See Figure 3-14.
Figure 3-14

PayPal Checkout SDK usage

For illustrative purposes, we’re going to use the PayPal payment SDK here, since PayPal is a globally available payment system. Your actual solution might handle the notes, tokens, or even cryptocurrency!

Add a PayPal Payment Processor

To get started with processing PayPal payments , you need to download and install the latest version of PayPal Python SDK. If you installed Python3 libraries from the requirements.txt file in the Chapter_3 folder, you should already have PayPal Python SDK installed.

After making sure PayPal Python SDK is present, check the sample application code in the Chapter_3/exercise_3 folder. It is very similar to the Exercise 2 code, with a few differences. First of all, there is a new file called create_order.py, which takes care of creating an order request with the name and price of the item. You need to import the create_order function from the CreateOrder module in app.py. The most important difference in the app.py file is that, instead of simply redirecting to the success.html page , it creates a PayPal order with the name and price of the item and then redirects to the PayPal payment page.
response = CreateOrder().create_order(item_dict[item]['price'], item, hostname)
order_id = ''
print('Creating Order...')
if response.status_code == 201:
   order_id = response.result.id
for link in response.result.links:
   print((' {} link: {} Call Type: {}'.format(str(link.rel).capitalize(), link.href, link.method)))
   print('Created Successfully ')
   print('Copy approve link and paste it in browser. Login with buyer account and follow the instructions. Once approved hit enter...')
   return redirect(response.result.links[1].href, code=302)
else:
   print('Link is unreachable')
   exit(1)
In order for this example to work, you need to specify two environment variables in a bash shell before you run app.py :
PAYPAL_CLIENT_ID
and
PAYPAL_CLIENT_SECRET.
You can get these variables by going to the PayPal Developers Website home page at https://developer.paypal.com/home . Then click Login to the Dashboard. Go to [Your Name], then go to Dashboard in the top-right corner. Choose the Create App button. See Figure 3-15.
Figure 3-15

PayPal app creation interface in the dashboard

Fill in the details for the new app and then create it. A new screen will open. On the next page, you can see your PayPal client ID and secret.

Note

You will find the sandbox app settings and credentials on the same page.

To set PAYPAL_CLIENT_ID and PAYPAL_CLIENT_SECRET in a bash terminal session, execute the following commands:
export PAYPAL_CLIENT_ID="your-Paypal-client-id"
export PAYPAL_CLIENT_SECRET="your-Paypal-secret"
Note

Environmental variables do not persist between sessions, so you need to set them up if you open another terminal. Alternatively you can add these variables permanently to a .bashrc file on your Raspberry Pi 4. Needless to say, that solution only works during development and not for actual production, because of the security risks associated with storing CLIENT_ID and PASSWORD in an unencrypted file.

After that, type the following in the terminal:
python3 app.py
This is where you executed previous commands to test the app. See Figure 3-16.
Figure 3-16

The result of clicking one of the items on the web page from Figure 3-13

You’ll see a familiar web interface from Exercise 2. The difference this time is that when you click the item, you’ll be redirected to a PayPal sandbox payment page (see Figure 3-17). From there, you can pay with a mock account. If the mock payment is successful, you’ll be redirected to the /success route of your web server, which will display the corresponding web page and cause the servo to go to its minimum position.
Figure 3-17

PayPal mobile Checkout page

Pro Tips

While this implementation can be done on a small scale (say, a dozen vending machines), for large-scale deployment, a centralized server is better in terms of stability and security. Customers would be directed to this centralized server upon scanning the QR code. The link in the QR code in this scenario would contain each vending machine’s unique ID. The central server would query the vending machines for supply status of items and, once the payment is successfully completed, it would send the signal to the particular vending machine to move the servo. See Figure 3-18.
Figure 3-18

A possible schematic for implementing a production-ready vending machine payment system

The difficulty of implementing the central server approach depends on how many machines are involved and how geographically distant they are from the main server. In the case of a dozen vending machines in a local area, a central server can be implemented using a Raspberry Pi or a low-end computer along with a touchscreen. In the case of a larger-scale project, a server farm will be required. Another consideration is the time required for each vending machine to receive the signal from the server. A vending machine on the other side of the globe may take a while to receive the signal from the server. In order to reduce latency, a local server can be implemented on top of the central server.

The system can be upgraded to support multiple levels of security, from a simple PIN code to fingerprint recognition. It can also be extended to include other products, such as newspapers, lottery tickets, and food. Other types of vending machines could also be created, such as snack vending machines, drink vending machines, and ice cream vending machines, all of which require more operations. Additional elements, such as a bio-sensor to measure the temperature of the cold storage to prevent the food from going bad, could be added in the framework described in the chapter.

Summary

In this chapter, you learned how to utilize the Raspberry Pi 4 development board or compute module to build a customized prototype vending machine. Among the technologies discussed in this chapter were:
  • Important points to pay attention to when creating a customized carrier board

  • How to use the Python Flask framework to build a web application

  • How to use the PayPal Checkout SDK to provide a payment gateway for vending machine purchases

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.168.80