Transforming Raspberry Pi 4 into a Barcode Scanner with a C++ App, USB Camera, and OLED Display

The Raspberry Pi 4, with its enhanced performance and connectivity features, offers a myriad of possibilities for DIY enthusiasts and developers. One such application is turning this compact computer into a fully functional barcode scanner. In this article, we’ll guide you through the process of setting up a barcode scanner using a C++ application, a USB camera, and an I2C OLED display module on a Raspberry Pi 4.

Raspberry Pi 4 Specifications

  • Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.5GHz
  • 2GB, 4GB or 8GB LPDDR4-3200 SDRAM (depending on model)
  • 2.4 GHz and 5.0 GHz IEEE 802.11ac wireless, Bluetooth 5.0, BLE
  • Gigabit Ethernet
  • 2 USB 3.0 ports; 2 USB 2.0 ports.
  • 2 × micro-HDMI ports (up to 4kp60 supported)

More…

Prerequisites

Raspberry Pi OS Installation and Configuration

Installation

  1. Download Raspberry Pi OS.
  2. Write the OS image to an SD card with Win32 Disk Imager.
  3. Insert the SD card into Raspberry Pi 4 and connect to power via USB-C connector (minimum 3A).

Configuration

Launch the OS and then enable the I2C, VNC, and SSH interfaces.

I2C interface

If you want to use Windows Remote Desktop Connection, you can install tightvncserver and xrdp:

sudo apt update
sudo apt install tightvncserver xrdp

rpi remote login

Check the disk space:

df -H
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        32G  8.9G   21G  30% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           2.1G     0  2.1G   0% /dev/shm
tmpfs           2.1G  9.1M  2.1G   1% /run
tmpfs           5.3M  4.1k  5.3M   1% /run/lock
tmpfs           2.1G     0  2.1G   0% /sys/fs/cgroup
/dev/mmcblk0p1  265M   54M  211M  21% /boot
tmpfs           405M  4.1k  405M   1% /run/user/1000

If not all of the SD card storage is available, run sudo raspi-config and select Advanced Options:

raspi config

Then select A1 to expand disk storage. A reboot is required to make it work:

rpi sd card storage

Install OpenCV on Raspberry Pi OS

OpenCV is used for grabbing frames from the USB camera. Here are the steps to install OpenCV 4.3.0 on Raspberry Pi OS:

  1. Download the latest OpenCV source code: https://github.com/opencv/opencv/releases

  2. Install the following required packages:

     sudo apt install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libjpeg-dev libpng-dev libtiff-dev
    
  3. Build (takes more than 1 hour) and install OpenCV:

     mkdir build
     cd build
     cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DOPENCV_GENERATE_PKGCONFIG=ON ..
     make -j4
     sudo make install
    

C/C++ Barcode Reader Project

Let’s create a CMake project named raspberry-pi-cpp-barcode under /home/pi directory:

cd /home/pi
mkdir raspberry-pi-cpp-barcode

Download Dynamsoft C++ Barcode SDK to get shared libraries for Linux ARM.

Link the barcode recognition library, WiringPi library and OpenCV libraries in CMakeLists.txt:

link_directories("${PROJECT_SOURCE_DIR}/platforms/linux/") 
find_package(OpenCV REQUIRED)
include_directories("${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/include/")

# Add the executable
add_executable(BarcodeReader ssd1306_i2c.c BarcodeReader.cxx)
target_link_libraries (BarcodeReader "DynamsoftBarcodeReader" ${OpenCV_LIBS} wiringPi)

Here is the OpenCV C/C++ code for grabbing frames from webcam:

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

Mat frame;
VideoCapture capture(0);
for (;;)
{
    int key = waitKey(10);
    if ((key & 0xff) == 27/*ESC*/) break;

    capture >> frame; // read the next frame from camera
    if (frame.empty())
    {
        cerr << "ERROR: Can't grab camera frame." << endl;
        break;
    }   
    imshow("Dynamsoft Barcode Reader", frame);
    
}

To decode barcodes from camera frames, we can utilize the barcode video APIs. These manage a frame queue and perform barcode detection on a worker thread:

#include "DynamsoftBarcodeReader.h"
#include "BarcodeReaderConfig.h"

void textResultCallback(int frameId, TextResultArray *pResults, void * pUser)
{
    char * pszTemp = NULL;
    pszTemp = (char*)malloc(4096);

    if (pResults->resultsCount == 0)
    {
        snprintf(pszTemp, 4096, "No barcode found.\r\n\r\n");
        printf(pszTemp);
        free(pszTemp);
        CBarcodeReader::FreeTextResults(&pResults);
        return;
    }
    
    for (int iIndex = 0; iIndex < pResults->resultsCount; iIndex++)
    {
        snprintf(pszTemp, 4096, "Barcode %d:\r\n", iIndex + 1);
        printf(pszTemp);
        snprintf(pszTemp, 4096, "Type: %s, Value: %s\r\n", pResults->results[iIndex]->barcodeFormatString, pResults->results[iIndex]->barcodeText);
        printf(pszTemp);

        draw_OLED(pszTemp);
    }
    free(pszTemp);
    CBarcodeReader::FreeTextResults(&pResults);
}

CBarcodeReader reader;
int iRet = reader.InitLicense("LICENSE-KEY");
reader.SetTextResultCallback(textResultCallback,NULL);
capture >> frame;
int width = capture.get(CAP_PROP_FRAME_WIDTH);
int height = capture.get(CAP_PROP_FRAME_HEIGHT);

iRet = reader.StartFrameDecoding(10, 10, width, height, frame.step.p[0], IPF_RGB_888, "");
for (;;)
{
        int key = waitKey(10);
        if ((key & 0xff) == 27/*ESC*/) break;

        capture >> frame; // read the next frame from camera
        if (frame.empty())
        {
            cerr << "ERROR: Can't grab camera frame." << endl;
            break;
        }   
        reader.AppendFrame(frame.data);

        imshow("Dynamsoft Barcode Reader", frame);
        
}

reader.StopFrameDecoding();    

You need to request a free trial license and replace the placeholder with your own license key:

int iRet = reader.InitLicense("LICENSE-KEY");

After obtaining the barcode decoding results, we can display the text on the OLED screen:

#include <wiringPi.h>
#include <wiringPiI2C.h>

#include "ssd1306_i2c.h"

void draw_OLED(char* content)
{
    ssd1306_clearDisplay();
    ssd1306_drawString(content);
    ssd1306_display();
}

Finally, compile and execute the C/C++ barcode reader program:

mkdir build
cd build
cmake ..
cmake –build .
./BarcodeReader

Raspberry Pi barcode QR detection

How to AutoStart the Barcode Scanner Program on Raspberry Pi OS

If you wish to launch the barcode scanner program upon OS startup, create a script file at /home/pi/autostart.sh:

#!/bin/sh
/home/pi/raspberry-pi-cpp-barcode/build/BarcodeReader

Additionally, you’ll need to modify the file permissions to make it executable:

chmod a+x autostart.sh

Subsequently, create a file at /home/pi/.config/autostart/autostart.desktop:

[Desktop Entry]
Type=Application
Exec=sh /home/pi/autostart.sh

Now you can reboot the OS to verify whether the barcode program will run automatically:

sudo reboot

Source Code

https://github.com/yushulx/cmake-cpp-barcode-qrcode-mrz/tree/main/examples/9.x/raspberry_pi_oled