Closed Ankitjaiswal1201 closed 2 years ago
@Ankitjaiswal1201 Per my error message, it appears you're passing an MCP object into the pin field, which is just supposed to be an integer input that aligns with the BCM pinout. If the BCM pinout is correct for your uses, it would just be the value [9, 11], and my code does the rest of the work to allocate them as input pins.
The BCM pinout can be found here. I'm not familiar with this breakout board and if you're even able to access the GPIO pins the way this codeset does. HX711-Multi is just sampling directly with the GPIO pins using the RPi GPIO module.
I include a raw GPIO script, so you can see exactly how the GPIO is used to sample an HX711. This is here, also below:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) # set GPIO pin mode to BCM numbering
sck_pin = 1
dout_pin = 2
channel_select = 'A'
channel_A_gain = 128
# init GPIO
GPIO.setup(sck_pin, GPIO.OUT) # sck_pin is output only
GPIO.setup(dout_pin, GPIO.IN) # dout_pin is input only
# prepare for read
GPIO.output(sck_pin, False) # start by setting the pd_sck to 0
# check if dout pin is ready by confirming zero
for _ in range(20):
ready = (GPIO.input(dout_pin) == 0)
if ready:
break
if not ready:
print('GPIO pin not ready, quitting..')
quit()
# for each bit in 24 bits, perform ADC read
raw_read = 0
for _ in range(24):
# pulse sck high to request each bit
GPIO.output(sck_pin, True)
GPIO.output(sck_pin, False)
# left shift by one bit then bitwise OR with the new bit
raw_read = (raw_read << 1) | GPIO.input(dout_pin)
# set channel after read
# get number of pulses based on channel configuration
num_pulses = 2 # default 2 for channel B
if channel_select == 'A' and channel_A_gain == 128:
num_pulses = 1
elif channel_select == 'A' and channel_A_gain == 64:
num_pulses = 3
# pulse num_pulses
for _ in range(num_pulses):
GPIO.output(sck_pin, True)
GPIO.output(sck_pin, False)
print(f'Raw read (2s complement): {raw_read}')
if raw_read in [0x800000, 0x7FFFFF, 0xFFFFFF]:
print(f'Invalid raw value detected')
# calculate int from 2's complement
# check if the sign bit is 1, indicating a negative number
if (raw_read & 0x800000):
# convert from 2's complement to negative int
signed_value = -((raw_read ^ 0xffffff) + 1)
else: # else do not do anything the value is positive number
signed_value = raw_read
print(f'Raw read (signed integer): {signed_value}')
GPIO.cleanup()
@Ankitjaiswal1201 I just read up on it a little more. If you're trying to access the measurements through a secondary SPI or I2C interface, the RPi GPIO module won't be able to access it the same way. Can you successfully read high and low values from pins 9 and 11 through the MCP23017? Are you able to do this with the GPIO module from RPi, or do you have to sample through that I2C class (I expect you do)?
If you can adapt my raw code above to work with your MCP (replace any GPIO portions that won't work for you), I might be able to add some functionality to adapt to that need.
@Ankitjaiswal1201 Per my error message, it appears you're passing an MCP object into the pin field, which is just supposed to be an integer input that aligns with the BCM pinout. If the BCM pinout is correct for your uses, it would just be the value [9, 11], and my code does the rest of the work to allocate them as input pins.
The BCM pinout can be found here. I'm not familiar with this breakout board and if you're even able to access the GPIO pins the way this codeset does. HX711-Multi is just sampling directly with the GPIO pins using the RPi GPIO module.
I include a raw GPIO script, so you can see exactly how the GPIO is used to sample an HX711. This is here, also below:
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) # set GPIO pin mode to BCM numbering sck_pin = 1 dout_pin = 2 channel_select = 'A' channel_A_gain = 128 # init GPIO GPIO.setup(sck_pin, GPIO.OUT) # sck_pin is output only GPIO.setup(dout_pin, GPIO.IN) # dout_pin is input only # prepare for read GPIO.output(sck_pin, False) # start by setting the pd_sck to 0 # check if dout pin is ready by confirming zero for _ in range(20): ready = (GPIO.input(dout_pin) == 0) if ready: break if not ready: print('GPIO pin not ready, quitting..') quit() # for each bit in 24 bits, perform ADC read raw_read = 0 for _ in range(24): # pulse sck high to request each bit GPIO.output(sck_pin, True) GPIO.output(sck_pin, False) # left shift by one bit then bitwise OR with the new bit raw_read = (raw_read << 1) | GPIO.input(dout_pin) # set channel after read # get number of pulses based on channel configuration num_pulses = 2 # default 2 for channel B if channel_select == 'A' and channel_A_gain == 128: num_pulses = 1 elif channel_select == 'A' and channel_A_gain == 64: num_pulses = 3 # pulse num_pulses for _ in range(num_pulses): GPIO.output(sck_pin, True) GPIO.output(sck_pin, False) print(f'Raw read (2s complement): {raw_read}') if raw_read in [0x800000, 0x7FFFFF, 0xFFFFFF]: print(f'Invalid raw value detected') # calculate int from 2's complement # check if the sign bit is 1, indicating a negative number if (raw_read & 0x800000): # convert from 2's complement to negative int signed_value = -((raw_read ^ 0xffffff) + 1) else: # else do not do anything the value is positive number signed_value = raw_read print(f'Raw read (signed integer): {signed_value}') GPIO.cleanup()
@Morrious Thank you for your reply. The expander MCP23017 that I am using is from CircuitPython. That code is written in Board Numbering. I am not sure if making pin9 as 9 will work. Will pi not be confused about using its own GPIO pin 9 instead of using expander? Yes, I am referring to https://pinout.xyz/ for BMC numbering for Pi but could not finding anything for the expander.
I am using your Raw GPIO code too. I saw that you mentioned about Raw GPIO file in other issues. When I connected one hx711 directly with Pi, it worked properly. But when I am trying to connect it via breadboard, it is just giving me 0,0 value. I think this can be because of a loose connection as it should work via Breadboard too. This is a different problem so don't want to discuss in this thread. I will try to look for more details about it.
@Ankitjaiswal1201 I just read up on it a little more. If you're trying to access the measurements through a secondary SPI or I2C interface, the RPi GPIO module won't be able to access it the same way. Can you successfully read high and low values from pins 9 and 11 through the MCP23017? Are you able to do this with the GPIO module from RPi, or do you have to sample through that I2C class (I expect you do)?
If you can adapt my raw code above to work with your MCP (replace any GPIO portions that won't work for you), I might be able to add some functionality to adapt to that need.
@Morrious I tested a simple Led example on the expander MCP23017. And it worked well. Just Led and resistor is important with expander. Switch is not used.
With the HX711 connected to the expander, I am not able to read anything. But for LED, any pin I connect is working. I was using the following code
# SPDX-FileCopyrightText: 2017 Tony DiCola for Adafruit Industries
#
# SPDX-License-Identifier: MIT
# Simple demo of reading and writing the digital I/O of the MCP2300xx as if
# they were native CircuitPython digital inputs/outputs.
# Author: Tony DiCola
import time
import board
import busio
import digitalio
from adafruit_mcp230xx.mcp23017 import MCP23017
# Initialize the I2C bus:
i2c = busio.I2C(board.SCL, board.SDA)
# Create an instance of either the MCP23008 or MCP23017 class depending on
# which chip you're using:
mcp = MCP23017(i2c) # MCP23017
# Optionally change the address of the device if you set any of the A0, A1, A2
# pins. Specify the new address with a keyword parameter:
mcp = MCP23017(i2c, address=0x20) # MCP23017 A0,A1,A2 not set
# Now call the get_pin function to get an instance of a pin on the chip.
# This instance will act just like a digitalio.DigitalInOut class instance
# and has all the same properties and methods (except you can't set pull-down
# resistors, only pull-up!). For the MCP23008 you specify a pin number from 0
# to 7 for the GP0...GP7 pins. For the MCP23017 you specify a pin number from
# 0 to 15 for the GPIOA0...GPIOA7, GPIOB0...GPIOB7 pins (i.e. pin 12 is GPIOB4).
pin8 = mcp.get_pin(8)
pin9 = mcp.get_pin(9)
# Setup pin0 as an output that's at a high logic level.
pin8.switch_to_output(value=True)
print("Line 45")
# Setup pin1 as an input with a pull-up resistor enabled. Notice you can also
# use properties to change this state.
pin9.direction = digitalio.Direction.INPUT
pin9.pull = digitalio.Pull.UP
# Now loop blinking the pin 0 output and reading the state of pin 1 input.
while True:
# Blink pin 0 on and then off.
pin8.value = True
time.sleep(0.5)
pin8.value = False
time.sleep(0.5)
I also tried changing the GPIO portion in your Raw file. Did some changes but later got confused about the type of GPIO pin. When I check the type of GPIO pin9, it says Adafruit Object.
@Ankitjaiswal1201 sorry for the delay in replying. I have been very busy lately and this fell off my radar.
I created a dev branch to try out passing custom external functions to the HX711 for the GPIO functionality. I created a test script as well and copied in what I expect might work for your MCP setup. Please clone and check out the dev branch and try out the test script.
This update basically just allows you to pass your own init/read/write functions to the HX711 which passes the pin numbering already configured with the HX711 to pass pin numbers to your custom functions. I think that this should work with your mcp objects initialized before the functions, but I'm not certain. Give the test a try and see if those functions get run properly and the inputs/outputs work.
Branch: dev-expander-support Test Script: tests/simple_read_test_external_mcp.py
#!/usr/bin/env python3
# try to import hx711, first from src dir, second from src dir after adding parent to path, last from pip
try:
from src.hx711_multi import HX711
except:
try:
# try after inserting parent folder in path
import sys
import pathlib
from os.path import abspath
sys.path.insert(0, str(pathlib.Path(abspath(__file__)).parents[1]))
from src.hx711_multi import HX711
except:
from hx711_multi import HX711
from time import perf_counter
import board
import busio
import digitalio
from adafruit_mcp230xx.mcp23017 import MCP23017
readings_to_average = 10
sck_pin = 1
dout_pins = [2]
weight_multiples = [1]
# initialize MCP
i2c = busio.I2C(board.SCL, board.SDA)
mcp = MCP23017(i2c) # MCP23017
mcp = MCP23017(i2c, address=0x20) # MCP23017 A0,A1,A2 not set
# create custom functions for init, write, read
def mcp_init_gpio_func(sck_pin, dout_pins):
# init clock/sck pin
mcp_sck_pin = mcp.get_pin(sck_pin)
mcp_sck_pin.switch_to_output(value=True)
# init dout pins
for dout in dout_pins:
mcp_dout_pin = mcp.get_pin(dout)
# mcp_dout_pin.direction = digitalio.Direction.INPUT
# mcp_dout_pin.pull = digitalio.Pull.UP
mcp_dout_pin.switch_to_input(pull=digitalio.Pull.UP)
def mcp_gpio_output_func(pin_number, value=False):
mcp_output_pin = mcp.get_pin(pin_number)
mcp_output_pin.value = value
def mcp_gpio_input_func(pin_number):
mcp_output_pin = mcp.get_pin(pin_number)
return mcp_output_pin.value
# create hx711 instance
hx711 = HX711(
dout_pins=dout_pins,
sck_pin=sck_pin,
channel_A_gain=128,
channel_select='A',
all_or_nothing=False,
log_level='CRITICAL',
init_gpio_func=mcp_init_gpio_func,
gpio_output_func=mcp_gpio_output_func,
gpio_input_func=mcp_gpio_input_func,
)
# reset ADC, zero it
hx711.reset()
try:
hx711.zero(readings_to_average=readings_to_average * 3)
except Exception as e:
print(e)
# uncomment below loop to see raw 2's complement and read integers
# for adc in hx711._adcs:
# print(adc.raw_reads) # these are the 2's complemented values read bitwise from the hx711
# print(adc.reads) # these are the raw values after being converted to signed integers
hx711.set_weight_multiples(weight_multiples=weight_multiples)
# read until keyboard interrupt
try:
while True:
start = perf_counter()
# perform read operation, returns signed integer values as delta from zero()
# readings aare filtered for bad data and then averaged
raw_vals = hx711.read_raw(readings_to_average=readings_to_average)
# request weights using multiples set previously with set_weight_multiples()
# This function call will not perform a new measurement, it will just use what was acquired during read_raw()
weights = hx711.get_weight()
read_duration = perf_counter() - start
sample_rate = readings_to_average / read_duration
print('\nread duration: {:.3f} seconds, rate: {:.1f} Hz'.format(read_duration, sample_rate))
print('raw', ['{:.3f}'.format(x) if x is not None else None for x in raw_vals])
print(' wt', ['{:.3f}'.format(x) if x is not None else None for x in weights])
# uncomment below loop to see raw 2's complement and read integers
# for adc in hx711._adcs:
# print(adc.raw_reads) # these are the 2's complemented values read bitwise from the hx711
# print(adc.reads) # these are the raw values after being converted to signed integers
except KeyboardInterrupt:
print('Keyboard interrupt..')
except Exception as e:
print(e)
Hello @Morrious , Thank you for your reply. I tried to do the run the above code, but I am getting an error. The error is as follows:
I tried to go in the file and see if I can resolve it but could not find solution for this function error. I got rid of that module not found error but could not get rid of that function name error. This I was trying after cloning the dev branch in a folder.
I tried to install the repo again with development branch after uninstalling everything related to hx711 with pip install @dev branch but then got the following error.
>>> %Run test_mcp23017.py
Traceback (most recent call last):
File "/home/pi/Documents/electronicSensor/src/test_mcp23017.py", line 59, in <module>
hx711 = HX711(
TypeError: __init__() got an unexpected keyword argument 'init_gpio_func'
Not sure what I am doing wrong.
It looks like I misunderstood typing an input argument as a "function" type. The input shouldn't be "init_gpio_func: function", it should be "init_gpio_func: Callable" and I need to import Callable.
I am away from my computer for a day or two, but you can try editing that code yourself to try to fix the error. You'll need to add an import line near the top to import Callable, and then replace the "function" typing with "Callable" in multiple places where I define something like "func: function". Here is the solution from StackOverflow:
https://stackoverflow.com/questions/37835179/how-can-i-specify-the-function-type-in-my-type-hints
Ya, I will try it and get back to you. I have an other question which I will ask in another issue.
Hello @Morrious , I tried the above solution, works partly. There was some error which i was getting but for now i have put those lines in comments and then all the errors are resolved. The error lines were:
I have put the comments here:
the sck_pin mentioned is 1. This 1 corresponds to bmc numbering or board?
Also as i understood from the ada_fruit docs for MCP_23017, the total number of pins defined in code is 0 to 15 where we can specify a pin number from 0 to 15 for the GPIOA0...GPIOA7, GPIOB0...GPIOB7 pins (i.e. pin 12 is GPIOB4). AdaFruit Link
So in the following code, when we give pin 1 to sck_pin, aren't we giving GPIOA1?
In my connection, I have connected pin 2,3 (BMC) to MCP23017 and pin 1 (BMC) to the 3 HX711 that I am using.
Looks like my function typing checks still don't work, I'll have to debug that later. Commenting out the error check is fine for now.
In my use-case the PIN number is the BCM GPIO number. With the MCP, the integer should be the 0-15 value I would guess.
With the code I added, it will always use the custom functions if passed, so you're using only the MCP pins, right? Or are you using a mixture of MCP and normal GPIO?
Stale issue message
Hello @Morrious ,
Firstly thank you for making this git repository available. I connected on HX711 with raspberry pi 3B and everything worked fine.
I have issue. I wanted to connect four HX711 with expander mcp23017 which is connected to Raspberry Pi. I wanted to ask can I use this package to connect with expander mcp23017? I see you have used BMC numbering which is where I am getting errors. For expander MCP23017, I have used CircuitPython code which can be found here .
The combined code which I have written is:
Initial error I am getting for dout pins.
What can I do in this case?