====== 2D Code reader ======
{{ :bdev:2dcode_reader.png?400 |}}
{{ :bdev:actualpic.png?400 |}}
{{ :bdev:actualpic2.png?400 |}}
{{ :bdev:actualpic2_lights.png?400 |}}
{{ :bdev:48_well_example.png?400 |}}
----
When running the camera for 2D matix code reading and (likely dealing with different types of plates in general), depending on the environment and type of plate, you should be prepared to adjust the variable to assure the image is still in focus and there is sufficient lightly. There are at least 3 variables to consider in order to get good quality images for 2D matrix code reading:
- Correct lighting - the LEDs underneath the plate are run by 12V power supply, there is a voltage controller that adjusts the voltage from 11.5V to 12V. Its not much of a range but the LEDs turn off below 11.5V. There are 3 settings if you are in a bright room you probably need the lowest setting but this also depends on how bright you want the camera to be which leads to the next setting.
- Brightness - the camera is run by the picamera library - https://picamera.readthedocs.io/en/release-1.13/. This is a programmable setting that is used in the camera optimization script.
- Focus - This is controlled by the Arducam, enable_i2c_vc.sh that comes with the github package- https://github.com/ArduCAM/RaspberryPi - Connect to preview
So how this works is that you have a “Driver” computer that sends commands to the 2 RaspberryPi computers “Client”, each running the Arducam focusing camera. Initially I tried to just use ssh and have the clients share the Driver public key (the recipe for sharing keys on windows is here: VisionTracker Legacy 2D matrix scanner )but the focusing feature was not working. So now the Clients are both MQTT subscribers and the Driver is the MQTT publisher.
The example optimization python script, called optimizer.py looks like this:
import os,sys,time
#The plate identifier
plate = sys.argv[1]
#Your focus settings
ff = ['110','210','310','410','510','610']
#Your brightness settings
bb = ['30','40','50']
for f in f:
for b in leftb:
cmd = "mosquitto_pub -h 192.168.1.110 -t 'dcam1' -m 'snap "+plate+"left_"+f+"_"+b+"'"
os.system(cmd)
time.sleep(1)
cmd = "mosquitto_pub -h 192.168.1.120 -t 'dcam2' -m 'snap "+plate+"right_"+f+"_"+b+"'"
os.system(cmd)
time.sleep(2)
cmd = 'scp pi@192.168.1.110:/home/pi/'+plate+'left_'+f+'_'+b+'.jpg ./'
os.system(cmd)
time.sleep(2)
cmd = 'scp pi@192.168.1.120:/home/pi/'+plate+'right_'+f+'_'+b+'.jpg ./'
os.system(cmd)
time.sleep(2)
The client subscriber script looks like this:
import os
import time
import sys
import threading
import pygame,sys
import picamera
from pygame.locals import *
from time import ctime, sleep
import re
import paho.mqtt.client as mqtt
#Establish a connection to MQTT
def establishconnection():
### mqtt ###
broker_address="localhost"
print("creating new instance")
client = mqtt.Client("P2") #create new instance
client.on_message=on_message #attach function to callback
print("connecting to broker")
client.connect(broker_address) #connect to broker
print("Subscribing to topic","dcam2")
client.subscribe("dcam2")
print("ok its subscribed")
# Continue the network loop
client.loop_forever()
return client
def runFocus(plate,ff,bright):
temp_val = int(ff)
value = (temp_val<<4) & 0x3ff0
dat1 = (value>>8)&0x3f
dat2 = value & 0xf0
os.system("i2cset -y 0 0x0c %d %d" % (dat1,dat2))
#camera.resolution = (640,480)
camera.resolution = (960,720)
camera.brightness = int(bright)
cmd = '/home/pi/'+re.sub("snap ", "", plate)+'_'+str(temp_val)+'_'+bright+'.jpg'
camera.capture(cmd)
## mqtt message handler ##
def on_message(client, userdata, message):
print("message received")
cmd = str(message.payload.decode("utf-8"))
if re.match("^snap .*", cmd):
aa = re.match("^.* (.*)", cmd)
(plate,ff,bright) = re.split("_",cmd)
print(ff)
runFocus(plate,ff,bright)
pygame.init()
camera = picamera.PiCamera()
client = establishconnection()
----
|{{ :bdev:arducam_rotate_case.png?200 |}}|{{ :bdev:arducam_rotate_case.stl |}}|
|{{ :bdev:backbackpanel.png?200 |}}|{{ :bdev:backbackpanel.stl |}}|
|{{ :bdev:bottom.png?200 |}}|{{ :bdev:bottom.stl |}}|
|{{ :bdev:code_imager_banner.png?200 |}}|{{ :bdev:code_imager_banner.stl |}}|
|{{ :bdev:code2d_emblem.png?200 |}}|{{ :bdev:code2d_emblem.stl |}}|
|{{ :bdev:dual_camera_assy.png?200 |}}|{{ :bdev:dual_camera_assy.stl |}}|
|{{ :bdev:dual_camera_stand.png?200 |}}|{{ :bdev:dual_camera_stand.stl |}}|
|{{ :bdev:ffrontpanel.png?200 |}}|{{ :bdev:ffrontpanel.stl |}}|
|{{ :bdev:htsresources_banner.png?200 |}}|{{ :bdev:htsresources_banner.stl |}}|
|{{ :bdev:pr_lightfixture_mod.png?200 |}}|{{ :bdev:pr_lightfixture_mod.stl |}}|
|{{ :bdev:pr_lightfixture_mod_diffuse.png?200 |}}|{{ :bdev:pr_lightfixture_mod_diffuse.stl |}}|
|{{ :bdev:pr_lightfixture_mod3.png?200 |}}|{{ :bdev:pr_lightfixture_mod3.stl |}}|
|{{ :bdev:sd_lightfixture_mod.png?200 |}}|{{ :bdev:sd_lightfixture_mod.stl |}}|
|{{ :bdev:sd_lightfixture_mod_diffuse.png?200 |}}|{{ :bdev:sd_lightfixture_mod_diffuse.stl |}}|
|{{ :bdev:sd_lightfixture_mod3.png?200 |}}|{{ :bdev:sd_lightfixture_mod3.stl |}}|
|{{ :bdev:teachplate_core.png?200 |}}|{{ :bdev:teachplate_core.stl |}}|
|{{ :bdev:top.png?200 |}}|{{ :bdev:top.stl |}}|