Open sgbaird opened 2 months ago
Received the female female adapters for the DB9 RS232 plugs. This is because the waveshare module and the digital scale both have male adapters.
All the hardware should be available here.
There's also a precision screwdriver set on the desk that can be used.
EDIT: Also adding the 5V charger and usb cable to the mix.
Trying to connect scale to raspberry pi + base but cannot get it to connect.
Sorry for the above notifications, I was just playing with the settings.
Hi @evelynnesher, here is the documentation for the PICO-2CH-RS232 module. Connecting the scale directly to the Pico W won't work. You also won't need to user the Maker Pi Pico base. Just the Pico W and the RS232 module (I think they're already plugged in to each other).
The resources from the first post should also help:
Using waveshare.com/wiki/Pico-2CH-RS232 and US Solid 3kg scale
EDIT: one Pico-2CH-RS232 is available (in 3D printer room). Both the scale and the adapter that came with the RS232 module are male, so I also ordered F-F adapters. The same applies for the A&D scale.
I had trouble finding the instructions/manual for the US Solid scale online. Here is a scan of a paper copy:
uss-dbs-series-operation-manual.pdf
The directions are somewhat sparse, perhaps because continuous output is essentially the only option (compared with A&D which has a lot more functionality exposed).
Related microcourse module: ac-microcourses.readthedocs.io/en/latest/courses/robotics/3.2-serial-communication.html
You will need to check the manual for the scale to see what UART command is required (it differs from the example shown).
@sgbaird I think I don't have a Industrial RS232 to 3.3V TTL Converter.
@sgbaird I think I don't have a Industrial RS232 to 3.3V TTL Converter.
Correct, I'm mostly referring to the code snippet. You have this one https://www.waveshare.com/pico-2ch-rs232.htm (an alternative to the one you linked).
Did I set this up correctly? Still having connection issues
I think that's correct. Could you describe the connection issue in more detail?
When all the parts connect, it is not reading any data. Specifically, I make sure to check the scale is connected but uart.any() is always empty. I also make sure to follow the instructions on page 7 of the scale operations manual, data output settings.
Can you share the full code snippet that you're running? Use three backticks to apply code formatting
The following code from module 3.2 of the microcourse:
import machine
import utime
# Initialize UART
uart = machine.UART(1, baudrate=9600, tx=machine.Pin(4), rx=machine.Pin(5))
# Send the "Q" command and read response
uart.write(b"Q\r\n")
utime.sleep(0.1)
if uart.any():
print(uart.read().decode("utf-8"))
# Continuous reading loop
while True:
if uart.any():
print(uart.read().decode("utf-8"))
utime.sleep(1)
You can remove the "Q" command. That doesn't apply to the US solid scale. It may not affect anything, but will make debugging easier.
Assuming you've set the scale up in continuous output mode per the instruction manual, it may be worth using the uartassist software that was mentioned and connect directly to your computer, however you'll need a different type of cable. I think I have the required connectors in the office. I'll set those aside for you to pick up (likely tomorrow).
Actually, it looks like you have it connected into channel 0, however you're specifying the pins for channel 1. Check the pin legend on the Pico 2ch rs232 wiki.
The code from that draft was generated by ChatGPT (meant to be adapted), and I haven't tested the scale or the rs232 module yet, so it's not a drop-in replacement.
@sgbaird I am trying to correctly set up the scale to send continuous output. I follow the continuous output instructions (pasted below/ found on page 7 of the instructions manual), once I get to the last step and I click TARE, it sends the display to C06-0. I provided the reference for C06 displays.
I had ChatGPT write Thonny code that checks if the scale is connected. I believe my issue either lies in the continuous output or the physical setup.
import utime
# Initialize UART1 on pins GP4 (TX) and GP5 (RX)
uart = machine.UART(1, baudrate=9600, tx=machine.Pin(4), rx=machine.Pin(5))
def check_scale_connection():
print("Checking if the scale is connected...")
# Try reading data from the UART
if uart.any(): # If there's data available on the UART
response = uart.read() # Read the data
if response:
try:
# Try to decode the response as UTF-8
decoded_data = response.decode("utf-8").strip()
print("Scale connected. Data received:", decoded_data)
except UnicodeDecodeError:
# If the data cannot be decoded, show it in raw form
print("Scale connected. Non-text data received:", response)
else:
print("Scale connected, but no data received.")
else:
print("No data received. The scale may not be connected or may not be sending data.")
# Run the check in a loop to continuously check if the scale is connected
while True:
check_scale_connection()
utime.sleep(2) # Check every 2 seconds
Thanks for the info! I'm not sure what the issue is. Happy to take a look when you're nearby. Otherwise, you could take a video of the full process and I can look over it.
https://github.com/user-attachments/assets/60bff6e9-e8eb-4627-bbc4-e17e1bfe4ec2
I added a video of me following the manual instructions. As for the physical connection, it is the same as the picture I added yesterday except it is in channel 1 instead of 0 to correspond with the code. I have two adaptations of the F-F adapter. When I take the screws out it falls apart/ doesn’t stay inside the port in the scale so I just play around with it until it stays.
https://github.com/user-attachments/assets/ab9fdf10-f28d-4be1-8f42-a9c7c035b08f
It's different from what the instructions say, but maybe worth trying a long press of the tare at the end, or ignoring the last step of pressing tare. Directly connecting to a computer with a DB9 to USB-A cable (in one of the boxes in the room with the 3D printer), and using the uartassist software will likely help with the troubleshooting. We also have a second type of scale that probably has better documentation.
Aside: Some additional Pico 2-channel RS232 modules came in
I’ve gone through every combination of buttons, so the long TARE at the end isn’t the solution. I’ll stop by around 3 tomorrow to pick up the new materials. Will you be available then? If so, we can take a look together; if not, I’ll keep trying to sort it out on my own.
Here's the cable that you should be able to use to connect directly to your computer for troubleshooting. It's in the room with a 3D printer
There is a second scale that may be worth troubleshooting with. This one is more sensitive and needs to stay in the office. Instructions are also different, but I think there are links on the micro course website. This is one that we know can do serial communication.
Thank you! I’d like to start with the first one you provided. If that doesn’t work, I’ll come back and try the second scale.
UartAssist Software worked. Worked with Channel COM9 with the baud rate, parity, data bits, stop bits, and flow control set to the values specified by the scale manual.
Amazing! Narrows things down for sure.
And these were the correct instructions?
https://github.com/AccelerationConsortium/ac-training-lab/issues/20#issuecomment-2375510617
These were the instructions available for using the software To use the UartAssist Software, you configure the serial options (top left) then click open and it gives you continuous input.
I'm trying everything to debug the issue. Could the problem be related to the fact that the scale's output is 110V/220V while the Pico operates at 3.3V~5V? Could this voltage difference be causing the communication issue? Scale technical parameters: Pico-2CH-RS232 Specifications:
As part of my debugging efforts, I wrote some code to check the connection with the scale. The uart.any() method checks for available data in the UART and returns the number of bytes present in the receive buffer. However, it hasn’t provided any clarity, as it consistently returns False/zero. This means that there is no data available (I’m not sure if you already know this, but I wanted to clarify since you mentioned you're not familiar with the RS232 module). Any suggestions/next steps?
import machine
import utime
# Initialize UART
#uart = machine.UART(1, baudrate=9600, tx=machine.Pin(4), rx=machine.Pin(5))
uart = machine.UART(1, baudrate=9600, tx=machine.Pin(4), rx=machine.Pin(5), bits=8, parity=None, stop=1)
#pins 4 and 5, 8 and 9 work
# Function to check if the scale is connected
def check_scale_connection():
utime.sleep(0.1)
if uart.any(): # Check if there's any response
response = uart.read() # Read the response
if response:
print("Scale connected. Response:", response.decode("utf-8").strip())
else:
print("Scale is not responding.")
else:
print("No response from the scale. Check connections.")
# Check if the scale is connected
check_scale_connection()
Since we know it's not the scale, maybe reach out to the company for support. There's a "submit ticket" button at the bottom of https://www.waveshare.com/wiki/Pico-2CH-RS232.
Various resources:
Demo code from the "Download Example" section from the wiki, using https://files.waveshare.com/upload/5/5a/Pico_2CH_RS232_Code.7z, which can be downloaded manually and viewed (Windows seemed to do fine opening it up even in the archived state, not sure if that's because I did something special a while back to get it to work with 7z, or if it's a default for Windows now). The following Python example is given:
from machine import UART, Pin
import time
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
uart0 = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1))
txData = b'RS232 receive test...\r\n'
uart0.write(txData)
time.sleep(0.1)
while True:
#rxData = bytes()
while uart0.any() > 0: #Channel 0 is spontaneous and self-collecting
rxData0 = uart0.read()
uart0.write("{}".format(rxData0.decode('utf-8')))
print(rxData0)
if(uart0.any()==0):
uart0.write("\r\n")
while uart1.any() > 0: #Channel 1 is spontaneous and self-collecting
rxData1 = uart1.read()
uart1.write("{}".format(rxData1.decode('utf-8')))
print(rxData1)
if(uart1.any()==0):
uart1.write("\r\n")
Some other code examples:
EDIT: Verified that if I connect TX and RX together, the code works. For example, TX0 <--> RX1
and TX1 <--> RX2
with the code example above.
In terms of the US Solid scale, it may be that the black wire is actually TX, not GND... (i.e., the three dupont cables are flipped). I'm able to get some reading by switching.
EDIT: the female-female DB9 adapter needed to have screws removed to be able to attach to the scale. It would be better to get some connectors that don't have the threaded nuts on each side.
I think the issue may actually be the use of the female-female adapter, in that it flips the connections from what is expected.. this was my bad. I'm planning to get something like the following so we can have more control:
Futheda 5PCS D-SUB DB9 RS232 Interface Breakout Board Connector 9-pin 2-Row Female RS-232 Serial Port Solderless Terminal Block Adapter with Positioning Nuts https://a.co/d/6LEEta6
Likewise, the existing connector could be modified, but maybe better to just wait and go with the one above.
Hi, I hope you're doing well.
I'm working on connecting a Pico-2CH-RS232 module to a U.S. Solid Digital Scale. I'm following the RS232 module instructions for continuous output as outlined in the scale's manual, aiming to have the Pico collect and manage the data. The digital scale is connected to Channel 1 on the Pico Base using a Dupont 3-pin to DB-9 wire cable. We've confirmed that the scale works by testing the continuous output with UartAssist software.
However, the main issue we're facing is that, when using MicroPython on Thonny, we cannot read any connection from the scale. After following the continuous output instructions from the scale manual, nothing happens. We have also tried the basic example demo code from the "Download Example" section from the wiki, using https://files.waveshare.com/upload/5/5a/Pico_2CH_RS232_Code.7z
Here’s the code I’m currently using, which continuously prints "No response from the scale. Check connections":
import machine
import utime
# Initialize UART
# uart = machine.UART(1, baudrate=9600, tx=machine.Pin(4), rx=machine.Pin(5))
uart = machine.UART(1, baudrate=9600, tx=machine.Pin(4), rx=machine.Pin(5), bits=8, parity=None, stop=1)
# Function to check if the scale is connected
def check_scale_connection():
while True:
if uart.any(): # Check if there's any response
response = uart.read() # Read the response
if response:
print("Scale connected. Response:", response.decode("utf-8").strip())
else:
print("Scale is not responding.")
else:
print("No response from the scale. Check connections.")
# Check if the scale is connected
check_scale_connection()
Here’s the GitHub thread where we've outlined all the troubleshooting steps we've taken so far: https://github.com/AccelerationConsortium/ac-training-lab/issues/20
Please let me know if you need further information or have any suggestions on how I can proceed.
Best regards, Evelyn
The new part to help with troubleshooting should be here on Monday.
https://github.com/user-attachments/assets/9da69e02-e084-4394-aefa-b2872de8c110
I got it working! I used the Female DB9 breakout board adapter with three male-to-male jumper wires. I connected GND to GND, TX on the breakout board to RX on the Pico, and RX on the breakout board to TX on the Pico. I didn’t need to use the DB9 to multicore cable. I attached a video demonstrating the continuous output and included the code I used.
import machine
import utime
# Initialize UART
uart = machine.UART(1, baudrate=9600, tx=machine.Pin(4), rx=machine.Pin(5))
# Send the "Q" command and read response
uart.write(b"Q\r\n")
utime.sleep(0.1)
if uart.any():
print(uart.read().decode("utf-8"))
# Continuous reading loop
while True:
if uart.any():
print(uart.read().decode("utf-8"))
utime.sleep(1)
By using the new adapter, I realized that the connection issue wasn’t due to the Female-Female adapter, but rather with the TX-RX connection. Instead of directly plugging the DB9 into TX1, RX1, and GND on the microcontroller (as shown in the earlier pictures), I used male-male jumper cables with our original setup. I connected the jumper wires as shown in the picture: black to black and red to yellow.
Review of differences to help decide which setup is better suited for our needs: Assembly: First Setup: A screwdriver was needed for assembly, adding a minor step but ensuring tighter, more secure connections. Second Setup: No screwdriver was required Both were very easy to setup.
Adapter Durability: In the second setup, the female-female adapter falls apart if not held together. This happens because the nuts on the adapter had to be removed to fit. While this hasn't caused disconnection issues yet, it may pose a risk during long-term use.
Wire Bending: First Setup: Both sides of the wires bend slightly when secured in the terminal blocks, but it doesn't affect functionality. Second Setup: Only one side of the wires bends, making it slightly cleaner, but again, it doesn't impact functionality.
Data Relay Speed: The data speed appears to be the same in both setups, but I will be further testing to confirm.
Way to go! That's great you figured it out on both setups. Great progress.
Let's ditch the F-F adapter setup. I think sticking with the terminal breakout is fine.
I wouldn't worry much about the data transfer speed. Instead, the next priority will be setting up MQTT and a hugging face spaces web app for it.
This will be very similar to the fan control demo, except without the "send command" aspect. Will share some links.
Now that you have the scale working, can you start working on an MQTT + gradio web app implementation for one way streaming of the scale data? (See https://ac-training-lab.readthedocs.io/en/latest/devices/setup_iolt_devices.html)
Definitely, I’ve started already. You want me to use Gradio instead of Streamlit?
Great, and yes - it would be best to switch over (see https://github.com/AccelerationConsortium/ac-training-lab/issues/77#issuecomment-2429034334).
I successfully established the MQTT connection and will now start implementing Gradio. It's currently set up to send the following data:
{
"weight": "15.5g",
"time": "2024-10-30 12:34:56",
"device_id": "ambiguous-goose"
}
On HiveMQ, I can see the following information organized under the columns Message, Topic, and QoS:
For Hugging Face Spaces, would you like a button to turn continuous data on and off, and should the scale send just the weight or include the timestamp and other information? Should the output appear below the button, or would you prefer it to be displayed elsewhere?
Nice! That's great. I think weight and timestamp works, and you can use a unique ID from the Pico W in the topic structure and leave off the device ID. Something like <US Solid product ID>/<Pico ID>
.
For id, see https://github.com/sparks-baird/self-driving-lab-demo/blob/3d45417f1832679f84044f52e3c64daeb5437ca3/src/public_mqtt_sdl_demo/main.py#L63. For UTC timestamp, see (https://github.com/sparks-baird/self-driving-lab-demo/blob/3d45417f1832679f84044f52e3c64daeb5437ca3/src/public_mqtt_sdl_demo/lib/sdl_demo_utils.py#L188 and https://github.com/sparks-baird/self-driving-lab-demo/blob/3d45417f1832679f84044f52e3c64daeb5437ca3/src/public_mqtt_sdl_demo/main.py#L106) (i.e., you should synchronize the time via ntptime before calling).
For Hugging Face, I think as soon as it starts up, then start streaming the weigh data. You will want to try to avoid re-instantiating the MQTT client within a session.
Also, I recommend using some variation of the plotting code from https://huggingface.co/spaces/AccelerationConsortium/fan-control
Needs Refresh: Continuous:
I’ve completed the Gradio app in a personal space on my account. I made two versions: one displays data when you click the refresh button, and the other updates continuously. The continuous one currently updates slowly, but I'm working on sending real-time updates.
Let me know what changes to make. I’ll also need access to the Acceleration Consortium space so I can implement it there.
Currently, I run main.py on Thonny to collect the data and send it to HiveMQ, while I run app.py on Hugging Face Spaces to create the graph that retrieves data from HiveMQ.
Nice! Can you provide links to these two spaces?
Continuously updating graph : https://huggingface.co/spaces/evelyn-nesher19/scale-test-continous This graph updates smoothly in real-time and includes a refresh button for manual updates.
Manual Refresh Needed: https://huggingface.co/spaces/evelyn-nesher19/scale-test-refresh This version has a "connection status" button and requires manual refreshing to display the latest data.
Maybe use a sliding window for the data, with a history of ~30 seconds? I don't think a manual refresh is needed in this case. Maybe have a look at the main.py for the fan control demo in the AC training lab repo (nested under src
). You can reduce the time sampling so that data points get sent every 2-3 seconds for example.
Overall looks clean and good!
I've embedded the space into Gather Town!
Nice! Looks great 😊
I noticed something in the logs when trying to click connect:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/gradio/queueing.py", line 624, in process_events
response = await route_utils.call_process_api(
File "/usr/local/lib/python3.10/site-packages/gradio/route_utils.py", line 323, in call_process_api
output = await app.get_blocks().process_api(
File "/usr/local/lib/python3.10/site-packages/gradio/blocks.py", line 2015, in process_api
result = await self.call_function(
File "/usr/local/lib/python3.10/site-packages/gradio/blocks.py", line 1562, in call_function
prediction = await anyio.to_thread.run_sync( # type: ignore
File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync
return await get_async_backend().run_sync_in_worker_thread(
File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2441, in run_sync_in_worker_thread
return await future
File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 943, in run
result = context.run(func, *args)
File "/usr/local/lib/python3.10/site-packages/gradio/utils.py", line 865, in wrapper
response = f(*args, **kwargs)
File "/home/user/app/app.py", line 46, in connect_mqtt
client.tls_set()
File "/usr/local/lib/python3.10/site-packages/paho/mqtt/client.py", line 1302, in tls_set
self.tls_set_context(context)
File "/usr/local/lib/python3.10/site-packages/paho/mqtt/client.py", line 1193, in tls_set_context
raise ValueError('SSL/TLS has already been configured.')
ValueError: SSL/TLS has already been configured.
Fixed! I don't have access to edit AC Hugging Face Spaces Collections, so I can't place it under the "Hardware Control" Collection. Ready to set it up at the office with your HiveMQ credentials and start my next task.
Nice! If there are any updates to main.py
on the microcontroller, do you mind making a PR? If not, you can ignore. The Pico W will need the Nokia credentials, and you can use the 248 broker and username/password (the public test credentials) for now. We may switch to a different one a bit later.
Also, I added the HF space to the collection.
Perhaps the next task will be the autotrickler, since that carries over the RS232 experience and is a natural extension.
I have added a connection status bar. It changes in real time, and is currently live.
Here are three possible connection states:
Using https://www.waveshare.com/wiki/Pico-2CH-RS232 and US Solid 3kg scale
EDIT: one Pico-2CH-RS232 is available (in 3D printer room). Both the scale and the adapter that came with the RS232 module are male, so I also ordered F-F adapters. The same applies for the A&D scale.
I had trouble finding the instructions/manual for the US Solid scale online. Here is a scan of a paper copy:
uss-dbs-series-operation-manual.pdf
The directions are somewhat sparse, perhaps because continuous output is essentially the only option (compared with A&D which has a lot more functionality exposed).
Related microcourse module: https://ac-microcourses.readthedocs.io/en/latest/courses/robotics/3.2-serial-communication.html