Connecter plusieurs Capteurs de poids

Un lieu pour discuter des composants et de leur utilisation. Un passage obligé si vous devez interfacer votre Raspberry Pi avec le monde extérieur. On y trouvera aussi les cartes type commande de moteur pas à pas, continu, servo...

Modérateurs : Francois, smba38

Répondre
christophe27
Messages : 38
Enregistré le : lun. 3 nov. 2014 14:04

Connecter plusieurs Capteurs de poids

Message par christophe27 » lun. 27 mars 2017 12:25

Bonjour
Dans un premier montage J'arrive a connecter 1 capteur sur deux GPIO du raspberry cela fonctionne bien.
Voici les divers éléments et tuto sur les-quel je me suis appuyé:
le matériel:
http://www.gotronic.fr/art-capteur-de-f ... -19653.htm
https://www.amazon.com/HX711-Weighing-S ... B00LGCITTA
le montage:
http://hivetool.org/w/index.php?title=I ... X711_to_Pi
le code:
https://gist.github.com/Richard-Major/6 ... ca9e014362
(il faut changer les N° des GPIO suivant le montage)

ONT PEU BRANCHER PLUSIEURS CAPTEURS EN UTILISANT 2 GPIO DIFFERANT POUR CHAQUE MONTAGE

MON PROBLEME:
Je veut pesée 2 cuve a 4 pieds distante de 50 m du raspberry.
il me faut donc 16 conducteur + l'alimentation !!!!! il ne me restera pas assé de GPIO de libre pour le reste de l'instalation!!!

J'ai essayé d'utiliser un MCP23017 pour ajouter des GPIO a distance via I2C:
http://wiki.mchobby.be/index.php?title= ... k-MCP230XX
ce bus fonctionne ""pour allumer des leds"" en output et input ...

MAIS lorsque je veut utiliser les gpio du mcp , avec le code"adapté", pour les capteurs de poids ça ne marche pas!


#!/usr/bin/python
# Development for reading sparkfun HX711 load cell amp

import time
import os
import glob
import RPi.GPIO as GPIO
import sys
import MySQLdb as mdb
import datetime
#GPIO.setmode(GPIO.BCM)


#############mcp23017
from Adafruit_I2C import Adafruit_I2C
import smbus
import time

MCP23017_IODIRA = 0x00
MCP23017_IODIRB = 0x01
MCP23017_GPIOA = 0x12
MCP23017_GPIOB = 0x13
MCP23017_GPPUA = 0x0C
MCP23017_GPPUB = 0x0D
MCP23017_OLATA = 0x14
MCP23017_OLATB = 0x15
MCP23008_GPIOA = 0x09
MCP23008_GPPUA = 0x06
MCP23008_OLATA = 0x0A

class Adafruit_MCP230XX(object):
OUTPUT = 0
INPUT = 1

def __init__(self, address, num_gpios, busnum=-1):
assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16"
self.i2c = Adafruit_I2C(address=address, busnum=busnum)
self.address = address
self.num_gpios = num_gpios

# set defaults
if num_gpios <= 8:
self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A
self.direction = self.i2c.readU8(MCP23017_IODIRA)
self.i2c.write8(MCP23008_GPPUA, 0x00)
elif num_gpios > 8 and num_gpios <= 16:
self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A
self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B
self.direction = self.i2c.readU8(MCP23017_IODIRA)
self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8
self.i2c.write8(MCP23017_GPPUA, 0x00)
self.i2c.write8(MCP23017_GPPUB, 0x00)

def _changebit(self, bitmap, bit, value):
assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value
if value == 0:
return bitmap & ~(1 << bit)
elif value == 1:
return bitmap | (1 << bit)

def _readandchangepin(self, port, pin, value, currvalue = None):
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
#assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
if not currvalue:
currvalue = self.i2c.readU8(port)
newvalue = self._changebit(currvalue, pin, value)
self.i2c.write8(port, newvalue)
return newvalue


def pullup(self, pin, value):
if self.num_gpios <= 8:
return self._readandchangepin(MCP23008_GPPUA, pin, value)
if self.num_gpios <= 16:
lvalue = self._readandchangepin(MCP23017_GPPUA, pin, value)
if (pin < 8):
return
else:
return self._readandchangepin(MCP23017_GPPUB, pin-8, value) << 8

# Set pin to either input or output mode
def config(self, pin, mode):
if self.num_gpios <= 8:
self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode)
if self.num_gpios <= 16:
if (pin < 8):
self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode)
else:
self.direction |= self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8

return self.direction

def output(self, pin, value):
# assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin
if self.num_gpios <= 8:
self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA))
if self.num_gpios <= 16:
if (pin < 8):
self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA))
else:
self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) << 8

return self.outputvalue


self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue)
return self.outputvalue

def input(self, pin):
assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios)
assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin
if self.num_gpios <= 8:
value = self.i2c.readU8(MCP23008_GPIOA)
elif self.num_gpios > 8 and self.num_gpios <= 16:
value = self.i2c.readU8(MCP23017_GPIOA)
value |= self.i2c.readU8(MCP23017_GPIOB) << 8
return value & (1 << pin)

def readU8(self):
result = self.i2c.readU8(MCP23008_OLATA)
return(result)

def readS8(self):
result = self.i2c.readU8(MCP23008_OLATA)
if (result > 127): result -= 256
return result

def readU16(self):
assert self.num_gpios >= 16, "16bits required"
lo = self.i2c.readU8(MCP23017_OLATA)
hi = self.i2c.readU8(MCP23017_OLATB)
return((hi << 8) | lo)

def readS16(self):
assert self.num_gpios >= 16, "16bits required"
lo = self.i2c.readU8(MCP23017_OLATA)
hi = self.i2c.readU8(MCP23017_OLATB)
if (hi > 127): hi -= 256
return((hi << 8) | lo)

def write8(self, value):
self.i2c.write8(MCP23008_OLATA, value)

def write16(self, value):
assert self.num_gpios >= 16, "16bits required"
self.i2c.write8(MCP23017_OLATA, value & 0xFF)
self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF)

# RPi.GPIO compatible interface for MCP23017 and MCP23008

class MCP230XX_GPIO(object):
OUT = 0
IN = 1
BCM = 0
BOARD = 0
def __init__(self, busnum, address, num_gpios):
self.chip = Adafruit_MCP230XX(address, num_gpios, busnum)
def setmode(self, mode):
# do nothing
pass
def setup(self, pin, mode):
self.chip.config(pin, mode)
def input(self, pin):
return self.chip.input(pin)
def output(self, pin, value):
self.chip.output(pin, value)
def pullup(self, pin, value):
self.chip.pullup(pin, value)


if __name__ == '__main__':
# ***************************************************
# Set num_gpios to 8 for MCP23008 or 16 for MCP23017!
# ***************************************************
#mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) # MCP23008
mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 16) # MCP23017

# Set pins 0, 1 and 2 to output (you can set pins 0..15 this way)
# mcp.config(0, mcp.OUTPUT)
# mcp.config(1, mcp.OUTPUT)
#mcp.config(2, mcp.OUTPUT)

# Set pin 3 to input with the pullup resistor enabled
# mcp.config(3, mcp.INPUT)
#mcp.pullup(3, 0)

# Read input pin and display the results
# print "Pin 3 = %d" % (mcp.input(3) >> 3)

# Python speed test on output 0 toggling at max speed
# print "Starting blinky on pin 0 (CTRL+C to quit)"
# while (True):
# print"marche"
# mcp.output(0, 1) # Pin 0 High
# time.sleep(1)
# print"arret"
# mcp.output(0, 0) # Pin 0 Low
# time.sleep(2)

################################HX711
class HX711:
def __init__(self, dout, pd_sck, gain=128, readBits=24):
self.PD_SCK = pd_sck
self.DOUT = dout
self.readBits = readBits
self.twosComplementOffset = 1 << readBits
self.twosComplementCheck = self.twosComplementOffset >> 1

mcp.config(self.PD_SCK, mcp.OUTPUT)####GPIO.setup(self.PD_SCK, GPIO.OUT)

mcp.config(self.DOUT, mcp.INPUT)####GPIO.setup(self.DOUT, GPIO.IN)

self.GAIN = 0
self.OFFSET = 0
self.SCALE = 1
self.lastVal = 0

self.set_gain(gain)

def is_ready(self):
return mcp.input(self.DOUT) == 0 #####return GPIO.input(self.DOUT) == 0

def set_gain(self, gain):
if gain is 128:
self.GAIN = 1
elif gain is 64:
self.GAIN = 3
elif gain is 32:
self.GAIN = 2

mcp.output(self.PD_SCK, False)#####GPIO.output(self.PD_SCK, False)
self.read()

def waitForReady(self):
while not self.is_ready():
pass

def setChannelGainFactor(self):
for i in range(self.GAIN):
mcp.output(self.PD_SCK, True)###GPIO.output(self.PD_SCK, True)###
mcp.output(self.PD_SCK, False)###GPIO.output(self.PD_SCK, False)

def correctForTwosComplement( self , unsignedValue ):
if ( unsignedValue >= self.twosComplementCheck ):
return -self.twosComplementOffset + unsignedValue
else:
return unsignedValue

def read(self):
self.waitForReady();
unsignedValue = 0

for i in range(0,self.readBits):
mcp.output(self.PD_SCK, True)
unsignedValue = unsignedValue << 1
mcp.output(self.PD_SCK, False)
bit = mcp.input(self.DOUT)
if ( bit ):
unsignedValue = unsignedValue | 1

self.setChannelGainFactor()
signedValue = self.correctForTwosComplement( unsignedValue )

self.lastVal = signedValue
return self.lastVal

def read_average(self, times=3):
sum = 0
for i in range(times):
sum += self.read()

return sum / times

def get_value(self, times=3):
return self.read_average(times) - self.OFFSET

def get_units(self, times=3):
return self.get_value(times) / self.SCALE

def tare(self, times=15):
sum = 0 ###self.read_average(times) supression tare automatique
self.set_offset(sum)

def set_scale(self, scale):
self.SCALE = scale

def set_offset(self, offset):
self.OFFSET = offset

def power_down(self):
mcp.output(self.PD_SCK, False)###GPIO.output(self.PD_SCK, False)
mcp.output(self.PD_SCK, True)###GPIO.output(self.PD_SCK, True)

def power_up(self):
mcp.output(self.PD_SCK, False)

def pesee_rond_fn():


val = hx.get_units(1)
poid = int(val) #0.01503
pesee_rond = round(poid,0)
print pesee_rond
time.sleep(0.1)
return pesee_rond

############# EXAMPLE



s_brut = 0
cpt =0
brut_p = 0
try:
while(cpt<3):
hx = HX711(6, 7,128)
hx.set_scale(92)
hx.tare()

brut = pesee_rond_fn()

if brut <( brut_p + 50) and brut > (brut_p - 50) :
s_brut += brut
cpt+=1
brut_p = brut

else:
s_brut = 0
cpt = 0
brut_p = brut

pied1 =int(s_brut/cpt)
s_brut = 0
cpt = 0
print "pied 1 silo",pied1

while(cpt<3):
hx = HX711(8,9,128)
hx.set_scale(92)
hx.tare()

brut = pesee_rond_fn()

if brut <( brut_p + 50) and brut > (brut_p - 50) :
s_brut += brut
cpt+=1
brut_p = brut

else:
s_brut = 0
cpt = 0
brut_p = brut

pied2 =int(s_brut/cpt)
s_brut = 0
cpt = 0
print "pied 2 silo",pied2

while(cpt<3):
hx = HX711(10, 11,128)
hx.set_scale(92)
hx.tare()

brut = pesee_rond_fn()

if brut <( brut_p + 50) and brut > (brut_p - 50) :
s_brut += brut
cpt+=1
brut_p = brut

else:
s_brut = 0
cpt = 0
brut_p = brut

pied3 =int(s_brut/cpt)
s_brut = 0
cpt = 0
print "pied 3 silo",pied3

while(cpt<3):
hx = HX711(12,13,128)
hx.set_scale(92)
hx.tare()

brut = pesee_rond_fn()

if brut <( brut_p + 50) and brut > (brut_p - 50) :
s_brut += brut
cpt+=1
brut_p = brut

else:
s_brut = 0
cpt = 0
brut_p = brut

pied4 =int(s_brut/cpt)
s_brut = 0
cpt = 0
print "pied 4 silo",pied4


silo = pied1+pied2+pied3+pied4

print "total silo",silo

except KeyboardInterrupt:
quit()


ESt t-il possible d'utiliser un HX711 avec un MCP23017?
ou
Est-il possible de regrouper 4 capteur sur un même HX711?
ou
Avez vous une meilleur idée?

d'avance MERCI

guillaume9344
Raspinaute
Messages : 629
Enregistré le : mar. 6 janv. 2015 19:44
Localisation : finistere

Re: Connecter plusieurs Capteurs de poids

Message par guillaume9344 » mar. 28 mars 2017 18:04

Bonjour,
vous pouvez mutualiser la broche d'horloge, donc une horloge pour les 8 modules et 8 fils de données , ca économise 7 fils.
rpi b+ ,osmc, motioneyes
rpi 2 raspbian , server minecraft 24h/24 , utilisation gpio
orange pi pc debian ,utilisation gpio, motion cam

christophe27
Messages : 38
Enregistré le : lun. 3 nov. 2014 14:04

Re: Connecter plusieurs Capteurs de poids

Message par christophe27 » mar. 28 mars 2017 22:18

Bonsoir
Merci pour ce retour.
mais je découvre l'électronique, et tous ce qui va avec le raspberry.... !
J'ai besoins de quelques conseils:
je branche tous les pd_sck en paralelle ?
la charge sur le GPIO d'horloge ne sera pas trop importante?
Dans le code python faut t-il le modifier de façon a récuperer les données des 8 modules a chaque "coup" d'horlge OU
est-ce que je peut utiliser toujours le même N° de GPIO dans chaque boucle while?
(voir la fin du code en modifiant le nom des gpio)

.....
while(cpt<3):
hx = HX711(23, 24,128) <<<<<<<<<<<<<<ici
hx.set_scale(92)
hx.tare()

brut = pesee_rond_fn()

if brut <( brut_p + 50) and brut > (brut_p - 50) :
s_brut += brut
cpt+=1
brut_p = brut

else:
s_brut = 0
cpt = 0
brut_p = brut

pied1 =int(s_brut/cpt)
s_brut = 0
cpt = 0
print "pied 1 silo",pied1

while(cpt<3):
hx = HX711(18,24,128) <<<<<<<<<<<<<<<ici
hx.set_scale(92)
hx.tare()

brut = pesee_rond_fn()

if brut <( brut_p + 50) and brut > (brut_p - 50) :
s_brut += brut
....

D'avance MERCI

guillaume9344
Raspinaute
Messages : 629
Enregistré le : mar. 6 janv. 2015 19:44
Localisation : finistere

Re: Connecter plusieurs Capteurs de poids

Message par guillaume9344 » mer. 29 mars 2017 09:14

*Oui c'est tout a fait ca , les 8 pd_sk en parallèle, et le même numéros de pin , mais vous pouvez continuer a lire les 8 modules les un aprés les autre , au début , puis vous pourrez les 8 à chaque front d'horloge.
Je n'ai pas trouvé dans la doc , le courant demandé par une pin pd_sk , je pense qu'il est trésfaible , mais il faudrait essayé de trouver plus d'info, essayez avec 4 en premier.
rpi b+ ,osmc, motioneyes
rpi 2 raspbian , server minecraft 24h/24 , utilisation gpio
orange pi pc debian ,utilisation gpio, motion cam

Répondre

Retourner vers « L'électronique et le Raspberry Pi »