Several changes to dimensioner hardware and software
This commit is contained in:
parent
584da34666
commit
3c98242a82
BIN
hardware/dimensioner/dimensioner-sensor-clip-straight.stl
Normal file
BIN
hardware/dimensioner/dimensioner-sensor-clip-straight.stl
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
77
src/dimensioner/config.py
Normal file
77
src/dimensioner/config.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright 2025 PostalPortal LLC and Netsyms Technologies LLC
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or
|
||||
# without modification, are permitted provided that
|
||||
# the following conditions are met:
|
||||
# 1. Redistributions of source code must retain
|
||||
# the above copyright notice, this list of conditions
|
||||
# and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce
|
||||
# the above copyright notice, this list of conditions
|
||||
# and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder
|
||||
# nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
# CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||||
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
# THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
#
|
||||
# Hardware configuration
|
||||
#
|
||||
SENSOR_TYPE = "US-100" # "PING" for Parallax PING))) or "US-100" for US-100
|
||||
SENSOR_MAX_MM = 3000 # Maximum range sensor supports and is accurate within
|
||||
SENSOR_MIN_MM = 100 # Minimum range below which sensor is not accurate
|
||||
SENSOR_PIN = 17 # Analog pin for PING sensor
|
||||
SENSOR_TX = 16 # Digital pin for US-100
|
||||
SENSOR_RX = 17 # Digital pin for US-100
|
||||
UART_ID = 0 # TX/RX: UART 0: 12/13, 16/17; UART 1: 4/5, 8/9
|
||||
ZERO_RANGE_MM = 10 # +/- mm away from zero before a non-zero value is transmitted
|
||||
SAMPLE_SIZE = 10 # Number of times to sample distance per reading, averaging the results
|
||||
UNSTABLE_DELTA_MM = 50 # Max difference between largest and smallest samples (before averaging), larger than this will report as unstable
|
||||
ZERO_BUTTON_PIN = 13 # Pin to read if hardware zero button is pressed
|
||||
UNITS_BUTTON_PIN = 14 # Pin to read if hardware unit change button is pressed
|
||||
FIRMWARE_VERSION = "1.0"
|
||||
|
||||
#
|
||||
# USB configuration
|
||||
#
|
||||
VID = 0x1209 # USB Vendor ID
|
||||
PID = 0xA002 # USB Product ID
|
||||
MANU = "PostalPortal LLC" # USB manufacturer string
|
||||
PROD = "PostalPoint Parcel Dimensioner" # USB product string
|
||||
INTERFACE = "PostalPoint" # Interface string
|
||||
USBHID_ENABLED = True # Disable USB, use serial output only (good for debugging)
|
||||
|
||||
|
||||
#
|
||||
# Display configuration
|
||||
#
|
||||
ENABLE_DISPLAY = True # Set to False to ignore display commands
|
||||
DISPLAY_WIDTH = 128
|
||||
DISPLAY_HEIGHT = 64
|
||||
# Available pin combinations for I2C:
|
||||
# I2C 0 – SDA: GP0/GP4/GP8/GP12/GP16/GP20
|
||||
# I2C 0 – SCL: GP1/GP5/GP9/GP13/GP17/GP21
|
||||
# I2C 1 – SDA: GP2/GP6/GP10/GP14/GP18/GP26
|
||||
# I2C 1 – SCL: GP3/GP7/GP11/GP15/GP19/GP27
|
||||
# Just don't conflict with the pin assignments for the sensor and buttons!
|
||||
DISPLAY_SDA_PIN = 6
|
||||
DISPLAY_SCL_PIN = 7
|
||||
DISPLAY_I2C_CONTROLLER = 1
|
||||
ENABLE_BUTTON_LEGEND = True # If true, will display onscreen labels for two buttons on the left side of the screen: top button zeros, bottom button changes units
|
@ -42,19 +42,7 @@ from time import sleep_ms
|
||||
from ssd1306big import setOLED, line1, line2
|
||||
import framebuf
|
||||
import math
|
||||
|
||||
ENABLE_DISPLAY = True # Set to False to ignore display commands
|
||||
DISPLAY_WIDTH = 128
|
||||
DISPLAY_HEIGHT = 64
|
||||
# Available pin combinations for I2C:
|
||||
# I2C 0 – SDA: GP0/GP4/GP8/GP12/GP16/GP20
|
||||
# I2C 0 – SCL: GP1/GP5/GP9/GP13/GP17/GP21
|
||||
# I2C 1 – SDA: GP2/GP6/GP10/GP14/GP18/GP26
|
||||
# I2C 1 – SCL: GP3/GP7/GP11/GP15/GP19/GP27
|
||||
# Just don't conflict with the pin assignments for the sensor and buttons!
|
||||
DISPLAY_SDA_PIN = 6
|
||||
DISPLAY_SCL_PIN = 7
|
||||
DISPLAY_I2C_CONTROLLER = 1
|
||||
from config import *
|
||||
|
||||
i2c = I2C(DISPLAY_I2C_CONTROLLER, sda=Pin(DISPLAY_SDA_PIN), scl=Pin(DISPLAY_SCL_PIN), freq=400000)
|
||||
oled = SSD1306_I2C(DISPLAY_WIDTH, DISPLAY_HEIGHT, i2c)
|
||||
@ -62,152 +50,185 @@ oled = SSD1306_I2C(DISPLAY_WIDTH, DISPLAY_HEIGHT, i2c)
|
||||
|
||||
def bootDisplay(firmwareVersion):
|
||||
if ENABLE_DISPLAY:
|
||||
# Bootup dead pixel self-test
|
||||
oled.fill(0)
|
||||
oled.show()
|
||||
oled.fill(1)
|
||||
oled.show()
|
||||
sleep_ms(500)
|
||||
oled.fill(0)
|
||||
oled.show()
|
||||
# 128x32 PostalPoint logo bitmap
|
||||
logo = bytearray([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0x40, 0x40, 0xc0, 0x80,
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xfc, 0x0e, 0x0a, 0x1a, 0x13, 0xf1, 0x19, 0x08, 0x08, 0xfc, 0xfc, 0x0c, 0x08,
|
||||
0x19, 0xf1, 0xf1, 0x1b, 0x0a, 0x0e, 0xfc, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0xf8,
|
||||
0x1c, 0x1c, 0x1c, 0xf8, 0xf8, 0xf0, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x00,
|
||||
0x00, 0x00, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x80, 0xf0, 0xf8, 0xf8, 0xe0, 0xe0,
|
||||
0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40, 0x00, 0x00, 0xf0, 0xfc, 0xfe, 0x0e,
|
||||
0x00, 0x00, 0xf0, 0xf8, 0xf8, 0x1c, 0x1c, 0x18, 0xf8, 0xf8, 0xf0, 0x00, 0x00, 0x80, 0xc0, 0xe0,
|
||||
0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0xc8, 0xfc, 0xfe, 0x0c, 0x00, 0xc0, 0xe0, 0xe0, 0xe0,
|
||||
0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0xf8, 0xf8, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x7f, 0xc0, 0x80, 0x80, 0x80, 0x07, 0x0e, 0x0a, 0x1a, 0xf1, 0xf1, 0x1b, 0x0a,
|
||||
0x0e, 0x0f, 0x07, 0x80, 0x80, 0xc0, 0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f, 0x3f, 0x07,
|
||||
0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x1f, 0x3f, 0x7f, 0x70, 0x70, 0x38, 0x1f, 0x0f, 0x03,
|
||||
0x20, 0x71, 0x73, 0x77, 0x76, 0x3e, 0x3c, 0x08, 0x00, 0x18, 0x3f, 0x7f, 0x73, 0x70, 0x30, 0x00,
|
||||
0x0c, 0x3f, 0x7f, 0x73, 0x70, 0x30, 0x3f, 0x7f, 0x3f, 0x00, 0x00, 0x3f, 0x7f, 0x7f, 0x20, 0x00,
|
||||
0x70, 0x7f, 0x7f, 0x0f, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x0c, 0x3f, 0x3f, 0x73, 0x70,
|
||||
0x70, 0x3f, 0x1f, 0x0f, 0x00, 0x70, 0x7f, 0x3f, 0x0f, 0x00, 0x20, 0x7e, 0x7f, 0x1f, 0x01, 0x20,
|
||||
0x7f, 0x7f, 0x0f, 0x00, 0x00, 0x3f, 0x7f, 0x7f, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x02, 0x06, 0x07, 0x07, 0x06, 0x02,
|
||||
0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
|
||||
fbuf = framebuf.FrameBuffer(logo, 128, 32, framebuf.MONO_VLSB)
|
||||
oled.blit(fbuf, 0, 0, 0)
|
||||
# Show info
|
||||
oled.text(" Parcel", 0, 32, 1)
|
||||
oled.text(" Dimensioner", 0, 40, 1)
|
||||
firmVerStr = "FW Ver " + firmwareVersion
|
||||
oled.text(f"{firmVerStr:^16}", 0, 56, 1)
|
||||
oled.show()
|
||||
sleep_ms(1500)
|
||||
try:
|
||||
# Bootup dead pixel self-test
|
||||
oled.fill(0)
|
||||
oled.show()
|
||||
oled.fill(1)
|
||||
oled.show()
|
||||
sleep_ms(500)
|
||||
oled.fill(0)
|
||||
oled.show()
|
||||
# 128x32 PostalPoint logo bitmap
|
||||
logo = bytearray([
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0x40, 0x40, 0xc0, 0x80,
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xfc, 0x0e, 0x0a, 0x1a, 0x13, 0xf1, 0x19, 0x08, 0x08, 0xfc, 0xfc, 0x0c, 0x08,
|
||||
0x19, 0xf1, 0xf1, 0x1b, 0x0a, 0x0e, 0xfc, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0xf8,
|
||||
0x1c, 0x1c, 0x1c, 0xf8, 0xf8, 0xf0, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0x00,
|
||||
0x00, 0x00, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x80, 0xf0, 0xf8, 0xf8, 0xe0, 0xe0,
|
||||
0x00, 0x00, 0x80, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x40, 0x00, 0x00, 0xf0, 0xfc, 0xfe, 0x0e,
|
||||
0x00, 0x00, 0xf0, 0xf8, 0xf8, 0x1c, 0x1c, 0x18, 0xf8, 0xf8, 0xf0, 0x00, 0x00, 0x80, 0xc0, 0xe0,
|
||||
0xe0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0xc8, 0xfc, 0xfe, 0x0c, 0x00, 0xc0, 0xe0, 0xe0, 0xe0,
|
||||
0xe0, 0xe0, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0xf8, 0xf8, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x7f, 0xc0, 0x80, 0x80, 0x80, 0x07, 0x0e, 0x0a, 0x1a, 0xf1, 0xf1, 0x1b, 0x0a,
|
||||
0x0e, 0x0f, 0x07, 0x80, 0x80, 0xc0, 0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f, 0x3f, 0x07,
|
||||
0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x1f, 0x3f, 0x7f, 0x70, 0x70, 0x38, 0x1f, 0x0f, 0x03,
|
||||
0x20, 0x71, 0x73, 0x77, 0x76, 0x3e, 0x3c, 0x08, 0x00, 0x18, 0x3f, 0x7f, 0x73, 0x70, 0x30, 0x00,
|
||||
0x0c, 0x3f, 0x7f, 0x73, 0x70, 0x30, 0x3f, 0x7f, 0x3f, 0x00, 0x00, 0x3f, 0x7f, 0x7f, 0x20, 0x00,
|
||||
0x70, 0x7f, 0x7f, 0x0f, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x0c, 0x3f, 0x3f, 0x73, 0x70,
|
||||
0x70, 0x3f, 0x1f, 0x0f, 0x00, 0x70, 0x7f, 0x3f, 0x0f, 0x00, 0x20, 0x7e, 0x7f, 0x1f, 0x01, 0x20,
|
||||
0x7f, 0x7f, 0x0f, 0x00, 0x00, 0x3f, 0x7f, 0x7f, 0x70, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x02, 0x06, 0x07, 0x07, 0x06, 0x02,
|
||||
0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
|
||||
fbuf = framebuf.FrameBuffer(logo, 128, 32, framebuf.MONO_VLSB)
|
||||
oled.blit(fbuf, 0, 16, 0)
|
||||
# Show info
|
||||
oled.text(" Parcel", 0, 40, 1)
|
||||
oled.text(" Dimensioner", 0, 48, 1)
|
||||
firmVerStr = "FW Ver " + firmwareVersion
|
||||
oled.text(f"{firmVerStr:^16}", 0, 56, 1)
|
||||
oled.show()
|
||||
sleep_ms(1500)
|
||||
except:
|
||||
pass
|
||||
|
||||
def errorDisplay(code, message = ""):
|
||||
global oled
|
||||
if ENABLE_DISPLAY:
|
||||
setOLED(oled)
|
||||
oled.fill(0)
|
||||
if code == 1:
|
||||
line1(" ERROR! ")
|
||||
oled.text(message, 0, 22, 2)
|
||||
if message == "Sensor timeout":
|
||||
pass
|
||||
elif code == 3:
|
||||
line1("UNSTABLE")
|
||||
oled.text("Distance is not", 0, 22, 2)
|
||||
oled.text("stable. Waiting", 0, 30, 2)
|
||||
oled.text("for it to settle", 0, 38, 2)
|
||||
oled.text("down and stop", 0, 46, 2)
|
||||
oled.text("moving around.", 0, 54, 2)
|
||||
elif code == 5:
|
||||
line1("UNDER 0!")
|
||||
oled.text("Object farther", 0, 22, 2)
|
||||
oled.text("from platform", 0, 30, 2)
|
||||
oled.text("than it should", 0, 38, 2)
|
||||
oled.text("be. Check and", 0, 46, 2)
|
||||
oled.text("re-zero.", 0, 54, 2)
|
||||
elif code == 6:
|
||||
line1("TOO FAR!")
|
||||
oled.text("Distance is too", 0, 22, 2)
|
||||
oled.text("far from sensor", 0, 30, 2)
|
||||
oled.text("for accurate", 0, 38, 2)
|
||||
oled.text("measurement.", 0, 46, 2)
|
||||
elif code == 7:
|
||||
line1("TOO NEAR")
|
||||
oled.text("Object is too", 0, 22, 2)
|
||||
oled.text("close to sensor", 0, 30, 2)
|
||||
oled.text("for accurate", 0, 38, 2)
|
||||
oled.text("measurement.", 0, 46, 2)
|
||||
elif code == 8:
|
||||
line1("HOST ERR")
|
||||
oled.text("Connected PC", 0, 22, 2)
|
||||
oled.text("sent an invalid", 0, 30, 2)
|
||||
oled.text("command.", 0, 38, 2)
|
||||
elif code == 9:
|
||||
line1("BAD UNIT")
|
||||
oled.text("Measurement too", 0, 22, 2)
|
||||
oled.text("large to display", 0, 30, 2)
|
||||
oled.text("with current", 0, 38, 2)
|
||||
oled.text("unit setting.", 0, 46, 2)
|
||||
oled.text("Change units.", 0, 54, 2)
|
||||
elif code == 0x4D:
|
||||
line1(" REPL ")
|
||||
oled.text("Device is in", 0, 22, 2)
|
||||
oled.text("debugging mode.", 0, 30, 2)
|
||||
oled.text("Power off and", 0, 38, 2)
|
||||
oled.text("back on to", 0, 46, 2)
|
||||
oled.text("cancel.", 0, 54, 2)
|
||||
elif code == 0x50:
|
||||
line1(" UPDATE ")
|
||||
oled.text("Device is in", 0, 22, 2)
|
||||
oled.text("firmware update", 0, 30, 2)
|
||||
oled.text("mode. Power off", 0, 38, 2)
|
||||
oled.text("and back on to", 0, 46, 2)
|
||||
oled.text("cancel.", 0, 54, 2)
|
||||
oled.show()
|
||||
try:
|
||||
setOLED(oled)
|
||||
oled.fill(0)
|
||||
if code == 1:
|
||||
line1(" ERROR! ")
|
||||
oled.text(message, 0, 22, 2)
|
||||
if message == "Sensor timeout":
|
||||
pass
|
||||
elif code == 3:
|
||||
line1("UNSTABLE")
|
||||
oled.text("Distance is not", 0, 22, 2)
|
||||
oled.text("stable. Waiting", 0, 30, 2)
|
||||
oled.text("for it to settle", 0, 38, 2)
|
||||
oled.text("down and stop", 0, 46, 2)
|
||||
oled.text("moving around.", 0, 54, 2)
|
||||
elif code == 5:
|
||||
line1("UNDER 0!")
|
||||
oled.text("Object farther", 0, 22, 2)
|
||||
oled.text("from platform", 0, 30, 2)
|
||||
oled.text("than it should", 0, 38, 2)
|
||||
oled.text("be. Check and", 0, 46, 2)
|
||||
oled.text("re-zero.", 0, 54, 2)
|
||||
elif code == 6:
|
||||
line1("TOO FAR!")
|
||||
oled.text("Distance is too", 0, 22, 2)
|
||||
oled.text("far from sensor", 0, 30, 2)
|
||||
oled.text("for accurate", 0, 38, 2)
|
||||
oled.text("measurement.", 0, 46, 2)
|
||||
elif code == 7:
|
||||
line1("TOO NEAR")
|
||||
oled.text("Object is too", 0, 22, 2)
|
||||
oled.text("close to sensor", 0, 30, 2)
|
||||
oled.text("for accurate", 0, 38, 2)
|
||||
oled.text("measurement.", 0, 46, 2)
|
||||
elif code == 8:
|
||||
line1("HOST ERR")
|
||||
oled.text("Connected PC", 0, 22, 2)
|
||||
oled.text("sent an invalid", 0, 30, 2)
|
||||
oled.text("command.", 0, 38, 2)
|
||||
elif code == 9:
|
||||
line1("BAD UNIT")
|
||||
oled.text("Measurement too", 0, 22, 2)
|
||||
oled.text("large to display", 0, 30, 2)
|
||||
oled.text("with current", 0, 38, 2)
|
||||
oled.text("unit setting.", 0, 46, 2)
|
||||
oled.text("Change units.", 0, 54, 2)
|
||||
elif code == 0x4D:
|
||||
line1(" REPL ")
|
||||
oled.text("Device is in", 0, 22, 2)
|
||||
oled.text("debugging mode.", 0, 30, 2)
|
||||
oled.text("Power off and", 0, 38, 2)
|
||||
oled.text("back on to", 0, 46, 2)
|
||||
oled.text("cancel.", 0, 54, 2)
|
||||
elif code == 0x50:
|
||||
line1(" UPDATE ")
|
||||
oled.text("Device is in", 0, 22, 2)
|
||||
oled.text("firmware update", 0, 30, 2)
|
||||
oled.text("mode. Power off", 0, 38, 2)
|
||||
oled.text("and back on to", 0, 46, 2)
|
||||
oled.text("cancel.", 0, 54, 2)
|
||||
oled.show()
|
||||
except:
|
||||
pass
|
||||
|
||||
def updateDisplay(measurement, units, tempC):
|
||||
def updateDisplay(measurement, units, tempC, unstable = False):
|
||||
global oled
|
||||
if ENABLE_DISPLAY:
|
||||
setOLED(oled)
|
||||
wholeNumber = str(math.floor(abs(measurement)))
|
||||
decimalPart = int(abs(measurement % 1) * 100)
|
||||
numberLine = " "
|
||||
if measurement < 0:
|
||||
numberLine = "-"
|
||||
if decimalPart > 0:
|
||||
decimalPart = 100 - decimalPart # Fix a bug where -.75 displays as -.25
|
||||
try:
|
||||
setOLED(oled)
|
||||
numberLine = " "
|
||||
if unstable:
|
||||
if units == "mm":
|
||||
wholeNumber = "-------"
|
||||
decimalPart = ""
|
||||
elif units == "cm":
|
||||
wholeNumber = "-----"
|
||||
decimalPart = "-"
|
||||
else:
|
||||
wholeNumber = "----"
|
||||
decimalPart = "--"
|
||||
else:
|
||||
wholeNumber = str(math.floor(abs(measurement)))
|
||||
decimalPart = int(abs(measurement % 1) * 100)
|
||||
if measurement < 0:
|
||||
numberLine = "-"
|
||||
if decimalPart > 0:
|
||||
decimalPart = 100 - decimalPart # Fix a bug where -.75 displays as -.25
|
||||
|
||||
if units == "mm":
|
||||
numberLine = numberLine + f"{wholeNumber:>7}"
|
||||
elif units == "cm":
|
||||
numberLine = numberLine + f"{wholeNumber:>5}.{decimalPart:0<1}"
|
||||
elif units == "in":
|
||||
numberLine = numberLine + f"{wholeNumber:>4}.{decimalPart:0<2}"
|
||||
elif units == "ft":
|
||||
numberLine = numberLine + f"{wholeNumber:>4}.{decimalPart:0<2}"
|
||||
if units == "mm":
|
||||
numberLine = numberLine + f"{wholeNumber:>7}"
|
||||
elif units == "cm":
|
||||
numberLine = numberLine + f"{wholeNumber:>5}.{decimalPart:0<1}"
|
||||
elif units == "in":
|
||||
numberLine = numberLine + f"{wholeNumber:>4}.{decimalPart:0<2}"
|
||||
elif units == "ft":
|
||||
numberLine = numberLine + f"{wholeNumber:>4}.{decimalPart:0<2}"
|
||||
|
||||
oled.fill(0) # Fill with black to clear screen
|
||||
line1(numberLine[:8]) # Write measurement to screen (but only first 8 chars to prevent IndexError: list index out of range)
|
||||
oled.text(f"{units:^16}", 0, 22, 1) # Write units centered below measurement
|
||||
if measurement == 0: # Write zero indicator on right below measurement
|
||||
oled.text(" ZERO", 0, 22, 1)
|
||||
tempStr = str(tempC) + "C"
|
||||
oled.text(f"{tempStr:>16}", 0, 50, 1) # Write temperature in bottom-right corner
|
||||
oled.show()
|
||||
oled.fill(0) # Fill with black to clear screen
|
||||
line1(numberLine[:8]) # Write measurement to screen (but only first 8 chars to prevent IndexError: list index out of range)
|
||||
oled.text(f"{units:^16}", 0, 22, 1) # Write units centered below measurement
|
||||
if measurement == 0: # Write zero indicator on right below measurement
|
||||
oled.text(" ZERO", 0, 22, 1)
|
||||
tempStr = str(tempC) + "C"
|
||||
oled.text(f"{tempStr:>16}", 0, 50, 1) # Write temperature in bottom-right corner
|
||||
if ENABLE_BUTTON_LEGEND:
|
||||
# Draw a vertical, double-ended arrow for the two physical buttons
|
||||
oled.line(5, 24, 5, 40, 1) # Vertical line for top arrow
|
||||
oled.line(5, 46, 5, 62, 1) # Vertical line for top arrow
|
||||
oled.line(0, 28, 5, 24, 1) # Left-top arrow part
|
||||
oled.line(10, 28, 5, 24, 1) # Right-top arrow part
|
||||
oled.line(0, 58, 5, 62, 1) # Left-bottom arrow part
|
||||
oled.line(10, 58, 5, 62, 1) # Right-bottom arrow part
|
||||
oled.text("SET 0", 10, 30, 1)
|
||||
oled.text("UNITS", 10, 50, 1)
|
||||
oled.show()
|
||||
except:
|
||||
pass
|
||||
|
||||
def clearDisplay():
|
||||
oled.fill(0)
|
||||
oled.show()
|
||||
try:
|
||||
oled.fill(0)
|
||||
oled.show()
|
||||
except:
|
||||
pass
|
@ -111,7 +111,7 @@ def roundUnits(x, units):
|
||||
#
|
||||
bufferSize = 1024 # size of circular buffer to allocate
|
||||
buffer = [' '] * bufferSize # circuolar incomming USB serial data buffer (pre fill)
|
||||
bufferEcho = True # USB serial port echo incooming characters (True/False)
|
||||
bufferEcho = False # USB serial port echo incooming characters (True/False)
|
||||
bufferNextIn, bufferNextOut = 0,0 # pointers to next in/out character in circualr buffer
|
||||
terminateThread = False # tell 'bufferSTDIN' function to terminate (True/False)
|
||||
#
|
||||
@ -131,7 +131,7 @@ def bufferSTDIN():
|
||||
bufferNextIn = 0
|
||||
#
|
||||
# instantiate second 'background' thread on RD2040 dual processor to monitor and buffer
|
||||
# incomming data from 'stdin' over USB serial port using ‘bufferSTDIN‘ function (above)
|
||||
# incoming data from 'stdin' over USB serial port using ‘bufferSTDIN‘ function (above)
|
||||
#
|
||||
bufferSTDINthread = start_new_thread(bufferSTDIN, ())
|
||||
|
||||
|
@ -70,35 +70,8 @@ from usb.device.hid import HIDInterface
|
||||
import ujson as json
|
||||
from dimensioner_utils import *
|
||||
from dimensioner_screen import updateDisplay, errorDisplay, bootDisplay, clearDisplay
|
||||
from config import *
|
||||
|
||||
#
|
||||
# Hardware configuration
|
||||
#
|
||||
SENSOR_TYPE = "US-100" # "PING" for Parallax PING))) or "US-100" for US-100
|
||||
SENSOR_MAX_MM = 3000 # Maximum range sensor supports and is accurate within
|
||||
SENSOR_MIN_MM = 100 # Minimum range below which sensor is not accurate
|
||||
SENSOR_PIN = 17 # Analog pin for PING sensor
|
||||
SENSOR_TX = 16 # Digital pin for US-100
|
||||
SENSOR_RX = 17 # Digital pin for US-100
|
||||
UART_ID = 0 # TX/RX: UART 0: 12/13, 16/17; UART 1: 4/5, 8/9
|
||||
ZERO_RANGE_MM = 10 # +/- mm away from zero before a non-zero value is transmitted
|
||||
SAMPLE_SIZE = 20 # Number of times to sample distance per reading, averaging the results
|
||||
UNSTABLE_DELTA_MM = 50 # Max difference between largest and smallest samples (before averaging), larger than this will report as unstable
|
||||
ZERO_BUTTON_PIN = 13 # Pin to read if hardware zero button is pressed
|
||||
UNITS_BUTTON_PIN = 14 # Pin to read if hardware unit change button is pressed
|
||||
FIRMWARE_VERSION = "1.0"
|
||||
|
||||
machine.freq(240000000) # Set CPU to 240MHz (about twice as fast as default)
|
||||
|
||||
#
|
||||
# USB configuration
|
||||
#
|
||||
VID = 0x1209 # USB Vendor ID
|
||||
PID = 0xA002 # USB Product ID
|
||||
MANU = "PostalPortal LLC" # USB manufacturer string
|
||||
PROD = "PostalPoint Parcel Dimensioner" # USB product string
|
||||
INTERFACE = "PostalPoint" # Interface string
|
||||
USBHID_ENABLED = True # Disable USB, use serial output only (good for debugging)
|
||||
|
||||
class USBHIDInterface(HIDInterface):
|
||||
def __init__(self):
|
||||
@ -222,8 +195,8 @@ def getAmbientTemp():
|
||||
else:
|
||||
return ambientTempC
|
||||
|
||||
def sendToDisplay(measurement):
|
||||
updateDisplay(measurement, reportUnits, getAmbientTemp())
|
||||
def sendToDisplay(measurement, unstable = False):
|
||||
updateDisplay(measurement, reportUnits, getAmbientTemp(), unstable)
|
||||
|
||||
def setUnits(units):
|
||||
global reportUnits
|
||||
@ -302,7 +275,7 @@ def getAverageDistanceMM(samples = SAMPLE_SIZE):
|
||||
maxV = sample
|
||||
total = total + sample
|
||||
i = i + 1
|
||||
sleep_us(1000) # PING datasheet says wait a minimum of 200us between measurements
|
||||
sleep_us(2000) # PING datasheet says wait a minimum of 200us between measurements
|
||||
if abs(maxV - minV) > UNSTABLE_DELTA_MM:
|
||||
raise DeltaError
|
||||
return total / samples
|
||||
@ -421,7 +394,7 @@ try:
|
||||
sendToDisplay(round(sizeInUnits, 2))
|
||||
except DeltaError:
|
||||
usbinterface.send_data(b'\x02\x03\x00\x00\x00\x00\x00')
|
||||
errorDisplay(3)
|
||||
sendToDisplay(999, True)
|
||||
print("E3: Unstable")
|
||||
except KeyboardInterrupt:
|
||||
terminateThread = True
|
||||
|
@ -2,6 +2,7 @@
|
||||
include("$(MPY_DIR)/ports/rp2/boards/manifest.py")
|
||||
require("usb-device-hid")
|
||||
require("ssd1306")
|
||||
module("config.py")
|
||||
module("dimensioner_utils.py")
|
||||
module("dimensioner_screen.py")
|
||||
module("ssd1306big.py")
|
||||
|
Loading…
x
Reference in New Issue
Block a user