0

I am trying to build an application that reads item weight and scan its barcode. So I thought using multiprocessing in python could be the good with the idea of creating a process for each device, weighing scale, barcode scanner and others. I was able to get the barcode scanner and scale working separately but whenever I try to combine them using multiprocessing, I run into different errors.

this is my first Multiprocessing code so I am as new as it can be but have a little experience with python. here is the code import io import pyqrcode from base64 import b64encode import eel #import png import json import ast import cv2 from multiprocessing import Process import os import RPi.GPIO as GPIO # import GPIO from hx711 import HX711 # import the class HX711 import numpy as np from pyzbar.pyzbar import decode #thanks to How can I get a String from HID device in Python with evdev?

from evdev import InputDevice, categorize, ecodes  

scancodes = {
    # Scancode: ASCIICode
    0: None, 1: u'ESC', 2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8',
    10: u'9', 11: u'0', 12: u'-', 13: u'=', 14: u'BKSP', 15: u'TAB', 16: u'q', 17: u'w', 18: u'e', 19: u'r',
    20: u't', 21: u'y', 22: u'u', 23: u'i', 24: u'o', 25: u'p', 26: u'[', 27: u']', 28: u'CRLF', 29: u'LCTRL',
    30: u'a', 31: u's', 32: u'd', 33: u'f', 34: u'g', 35: u'h', 36: u'j', 37: u'k', 38: u'l', 39: u';',
    40: u'"', 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'z', 45: u'x', 46: u'c', 47: u'v', 48: u'b', 49: u'n',
    50: u'm', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 57: u' ', 100: u'RALT'
}

capscodes = {
    0: None, 1: u'ESC', 2: u'!', 3: u'@', 4: u'#', 5: u'$', 6: u'%', 7: u'^', 8: u'&', 9: u'*',
    10: u'(', 11: u')', 12: u'_', 13: u'+', 14: u'BKSP', 15: u'TAB', 16: u'Q', 17: u'W', 18: u'E', 19: u'R',
    20: u'T', 21: u'Y', 22: u'U', 23: u'I', 24: u'O', 25: u'P', 26: u'{', 27: u'}', 28: u'CRLF', 29: u'LCTRL',
    30: u'A', 31: u'S', 32: u'D', 33: u'F', 34: u'G', 35: u'H', 36: u'J', 37: u'K', 38: u'L', 39: u':',
    40: u'\'', 41: u'~', 42: u'LSHFT', 43: u'|', 44: u'Z', 45: u'X', 46: u'C', 47: u'V', 48: u'B', 49: u'N',
    50: u'M', 51: u'<', 52: u'>', 53: u'?', 54: u'RSHFT', 56: u'LALT',  57: u' ', 100: u'RALT'
}

def readBarcode(devicePath):

    dev = InputDevice(devicePath)
    dev.grab() # grab provides exclusive access to the device

    x = ''
    caps = False

    for event in dev.read_loop():
        if event.type == ecodes.EV_KEY:
            data = categorize(event)  # Save the event temporarily to introspect it
            if data.scancode == 42:
                if data.keystate == 1:
                    caps = True
                if data.keystate == 0:
                    caps = False

            if data.keystate == 1:  # Down events only
                if caps:
                    key_lookup = u'{}'.format(capscodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode)  # Lookup or return UNKNOWN:XX
                else:
                    key_lookup = u'{}'.format(scancodes.get(data.scancode)) or u'UNKNOWN:[{}]'.format(data.scancode)  # Lookup or return UNKNOWN:XX

                
                
                if (data.scancode != 42) and (data.scancode != 28):
                    if key_lookup == 'None':
                        return x
                   
                    
                    x += key_lookup
                   
                    
                    

                if(data.scancode == 28):
                    return(x)


def startWeighingScale(arg):
    print(arg)
    try:
        GPIO.setmode(GPIO.BCM)  # set GPIO pin mode to BCM numbering
        # Create an object hx which represents your real hx711 chip
        # Required input parameters are only 'dout_pin' and 'pd_sck_pin'
        hx = HX711(dout_pin=5, pd_sck_pin=6)
        # measure tare and save the value as offset for current channel
        # and gain selected. That means channel A and gain 128
        err = hx.zero()
        # check if successful

        if err:
            raise ValueError('Tare is unsuccessful.')

        reading = hx.get_raw_data_mean()
        if reading:  # always check if you get correct value or only False
            # now the value is close to 0
            print('Data subtracted by offset but still not converted to units:',
                  reading)
        else:
            print('invalid data', reading)

        # In order to calculate the conversion ratio to some units, in my case I want grams,
        # you must have known weight.
        input('Put known weight on the scale and then press Enter')
        reading = hx.get_data_mean()
        if reading:
            print('Mean value from HX711 subtracted by offset:', reading)
            known_weight_grams = input(
                'Write how many grams it was and press Enter: ')
            try:
                value = float(known_weight_grams)
                print(value, 'grams')
            except ValueError:
                print('Expected integer or float and I have got:',
                      known_weight_grams)

            # set scale ratio for particular channel and gain which is
            # used to calculate the conversion to units. Required argument is only
            # scale ratio. Without arguments 'channel' and 'gain_A' it sets
            # the ratio for current channel and gain.
            ratio = reading / value  # calculate the ratio for channel A and gain 128
            hx.set_scale_ratio(ratio)  # set ratio for current channel
            print('Ratio is set.')
        else:
            raise ValueError('Cannot calculate mean value. Try debug mode. Variable reading:', reading)

        # Read data several times and return mean value
        # subtracted by offset and converted by scale ratio to
        # desired units. In my case in grams.
        print("Now, I will read data in infinite loop. To exit press 'CTRL + C'")
        input('Press Enter to begin reading')
        print('Current weight on the scale in grams is: ')
        while True:
            print(hx.get_weight_mean(20), 'g')

    except (KeyboardInterrupt, SystemExit):
        print('Bye :)')


def initiateBarcodeReader(arg):
    print(arg)
    while True:
        print("listening for barcode and qr")
        s = readBarcode("/dev/input/event0")
        print(s)
    



if __name__ == '__main__':
    
    scale = Process(target=startWeighingScale, args=('weighing started',))
    barcode = Process(target=initiateBarcodeReader, args=('Barcode called',))
    scale.start()
    barcode.start()

The barcode and scale function works separately but whenever i run the above code I keep getting this error

Process Process-2:
Traceback (most recent call last):
  File "/usr/lib/python3.7/multiprocessing/process.py", line 297, in _bootstrap
    self.run()
  File "/usr/lib/python3.7/multiprocessing/process.py", line 99, in run
    self._target(*self._args, **self._kwargs)
  File "/home/pi/Documents/Konstant/py/cartos.py", line 142, in initiateBarcodeReader
    s = readBarcode("/dev/input/event0")
  File "/home/pi/Documents/Konstant/py/cartos.py", line 41, in readBarcode
    dev.grab() # grab provides exclusive access to the device
  File "/home/pi/.local/lib/python3.7/site-packages/evdev/device.py", line 320, in grab
    _input.ioctl_EVIOCGRAB(self.fd, 1)
OSError: [Errno 16] Device or resource busy

How could I run the barcode scanner and scale function in parallel?

e.iluf
  • 1,389
  • 5
  • 27
  • 69
  • 1
    Have you tried catching the error and then waiting to try again to avoid clashes? Or, have you heard of or tried locks? – Random Davis Dec 10 '20 at 16:24
  • @RandomDavis I've heard of lock but will have to look into it – e.iluf Dec 10 '20 at 16:27
  • Does this answer your question? [How to perform Multithreading in Raspberry Pi 4 for multiple input devices](https://stackoverflow.com/questions/65333556/how-to-perform-multithreading-in-raspberry-pi-4-for-multiple-input-devices) – Ulrich Eckhardt Dec 19 '20 at 18:34

0 Answers0