我目前正在进行一个项目,要求我读取16个不同传感器的模拟电压,并将它们转换为角度读数。为了实现这一点,我决定使用MCP3008 ADC芯片以及rpi和python,因为这是我以前在其他需要类似过程的项目中所做的事情。然而,与我之前的项目不同,我必须使用2个MCP3008芯片,因为它们每个只能读取8个通道。我知道,基于spi通信的工作方式和MCP3008芯片的工作方式,这应该是可能的,但我遇到了一些问题,使这两个芯片同时工作。首先,我使用adafruits mcp3xxx库来处理芯片。我尝试的第一件事是使用不同的芯片选择将两个芯片放在同一个spi总线上。我所使用的代码如下所示
import busio
import digitalio
import board
import time
import adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn
# this function is used to calculate angle of displacement
def Angle(Vmin,Vmax,R,Vt):
return ((Vt-Vmin)/(Vmax-Vmin))*R
# create the spi bus
spi = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
#create the chip select(s)
cs0 = digitalio.DigitalInOut(board.CE0)
cs1 = digitalio.DigitalInOut(board.CE1)
#create the mcp object(s)
mcp0 = MCP.MCP3008(spi,cs0)
mcp1 = MCP.MCP3008(spi,cs1)
#create the analog channels
chan0_0 = AnalogIn(mcp0, MCP.P0)
chan1_0 = AnalogIn(mcp1, MCP.P0)
R_elbow = 180;
from CalibratedVoltages import*
while True:
# A_elbow = Angle(VminElbow,VmaxElbow,R_elbow,chan0_0.voltage)
# time.sleep(1)
# A_knee = Angle(VminKnee, VmaxKnee, R_knee,chan1_0.voltage)
# print('elbow angle:', A_elbow,'degrees')
print('0',chan0_0.voltage)
print('1',chan1_0.voltage)
time.sleep(2)
print('update')但是,使用此设置,由于某种原因,对mcp1对象的任何读取都依赖于对mcp0对象的读取。例如,如果要在mcp1的0通道上读取,而不是从0到3.3伏特(这是应该的),它的范围从0到在mcp0对象的通道0上读取的任何内容。对于mcp1对象上的所有通道,这都是一样的。
无法弄清楚为什么会发生这种情况,所以我决定将每个MCP3008芯片放在一个单独的spi总线上,以防止由于共享总线而造成的干扰,这就是我所认为的导致错误的原因。我做了一个dtoverlay来启用spi1总线,然后将我的代码更改为类似这样的代码。
import busio
import digitalio
import board
import time
import adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn
# this function is used to calculate angle of displacement
def Angle(Vmin,Vmax,R,Vt):
return ((Vt-Vmin)/(Vmax-Vmin))*R
# create the spi bus
spi0 = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
spi1 = busio.SPI(clock=21, MISO=19, MOSI=20)
#create the chip select(s)
cs0 = digitalio.DigitalInOut(board.D5)
cs1 = digitalio.DigitalInOut(board.D9)
#create the mcp object(s)
mcp0 = MCP.MCP3008(spi0,cs0)
mcp1 = MCP.MCP3008(spi1,cs1)
#create the analog channels
chan1_0 = AnalogIn(mcp1, MCP.P0)
chan0_0 = AnalogIn(mcp0, MCP.P0)
#chan0_1 = AnalogIn(mcp0, MCP.P1)
#chan0_2 = AnalogIn(mcp0, MCP.P2)
#chan0_3 = AnalogIn(mcp0, MCP.P3)
#chan0_4 = AnalogIn(mcp0, MCP.P4)
#chan0_5 = AnalogIn(mcp0, MCP.P5)
#chan0_6 = AnalogIn(mcp0, MCP.P6)
R_elbow = 180;
from CalibratedVoltages import*
while True:
# A_elbow = Angle(VminElbow,VmaxElbow,R_elbow,chan0_0.voltage)
# time.sleep(1)
# A_knee = Angle(VminKnee, VmaxKnee, R_knee,chan1_0.voltage)
# print('elbow angle:', A_elbow,'degrees')
print('0',chan0_0.voltage)
print('1',chan1_0.voltage)
# print('2',chan0_2.voltage)
# print('3',chan0_3.voltage)
# print('4',chan0_4.voltage)
# print('5',chan0_5.voltage)
# print('6',chan0_6.voltage)
time.sleep(2)
print('update')在此设置下,只有spi1总线上的MCP芯片工作,而其他芯片则在所有通道上返回0.0,而不管附加到它上的电压如何。即使您将代码更改为仅使用spi0总线,spi0总线上的芯片仍将继续返回所有0.0读取,直到并除非我重新启动rpi并运行仅用于spi0总线读取的代码,而无需运行为spi1总线设置任何内容的任何线路。此时,我相当迷茫,只能假设这与我正在使用的库之一有关,我选择了MCP3008芯片,因为我知道adafruit提供了一个易于使用的库,我希望避免在这个项目的这一部分上投入大量的精力。如果有人有同样的问题,并知道如何解决它,甚至只是猜测,这将是非常感谢的。对上述任何一个问题的解决方案将使我能够完成这个项目。
发布于 2022-03-07 11:19:35
我做了同样的事,也得到了同样的结果。
调试这个程序的最好工具叫做'piscope‘,可以在这里找到:http://abyz.me.uk/rpi/pigpio/piscope.html
以下是答案--不要使用CE0。
说明:由于某种原因,当使用adafruit库时,每当发生spi调用时,CE0就会降低--不管配置的是哪种设备/芯片选择。
这可以通过观察gpio引脚在鱼镜中看到。正确的cs引脚变低了--但是过了一会儿,CE0也变低了,使得spi设备都处于活动状态,并造成了碰撞情况。
在布局pcb时,我遵循了典型的逻辑,并让我的两个设备使用cs CE0和CE1,就像逻辑所说的那样,因为这些是默认的。
我不知道是adafruit库还是实际的pi内核造成了冲突,但是为了解决这个问题,我从我的芯片中取出了引脚D8,并连接到D20 --一个未使用的引脚。
然后,我按预期设置python中的cs配置: cs1 = digitalio.DigitalInOut(board.D7) cs2 = digitalio.DigitalInOut(board.D20)
一切都很完美-16个通道的独立电压读数。
在鱼镜下观看显示了我的预期:对于每一个spi呼叫,CE0都会下降。
解决方案:不要在多个spi设备设计中使用CE0。
我还使用了另外两个只配置了设备的软件进行测试,总共有4个带有4个gpio引脚的单独spi调用,没有D8。每个调用导致CE0被拉低,但是当不连接硬件中的CE0时,spi调用正常运行,显示(暂时)任何数量的设备都可以通过adafruit库连接到spi总线。
发布于 2022-03-07 21:43:01
手动设置gpio将无法工作。
我尝试了对GPIO的手动操作,但是CE0总是覆盖甚至手动gpio条件。CE0覆盖位于adafruit库中,或者可能是spi驱动程序的pi内核。
有几种寻址引脚的方法,我从不使用粒子法。我在某个地方读到粒子标识符是为非常高水平的处理器类型的人,而我不是。我使用adafruit示例级别代码。
import RPi.GPIO as GPIO
# create the spi bus
spi = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
# create the cs (chip select)
cs1 = digitalio.DigitalInOut(board.D7)
cs2 = digitalio.DigitalInOut(board.D20)
# create the mcp object
mcp1 = MCP.MCP3008(spi, cs2)
mcp2 = MCP.MCP3008(spi, cs2)要使用GPIO指定,只需将GPIOxx的GPIO部分更改为Dxx。例如,D20是pin 38,或D15/A6作为粒子。D7为GPIO7,pin 26,D8 (未使用)为GPIO8或pin 24。
以下是我的热敏电阻测试的完整代码:
import busio
import math
import digitalio
from decimal import Decimal
import board
import adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn
import time
from time import sleep
from gpiozero import CPUTemperature
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
# create the spi bus
spi = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
# create the cs (chip select)
cs1 = digitalio.DigitalInOut(board.D7)
cs2 = digitalio.DigitalInOut(board.D20)
# create the mcp object
mcp1 = MCP.MCP3008(spi, cs1)
mcp2 = MCP.MCP3008(spi, cs2)
while True:
print(mcp1)
print("Channel 1")
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P0)
c1=c1+chan.value
print (c1/100/64)
sleep(.2)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P1)
c1=c1+chan.value
print (c1/100/64)
sleep(.2)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P2)
c1=c1+chan.value
print (c1/100/64)
sleep(.2)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P3)
c1=c1+chan.value
print (c1/100/64)
sleep(.2)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P4)
c1=c1+chan.value
print (c1/100/64)
sleep(.2)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P5)
c1=c1+chan.value
print (c1/100/64)
sleep(.2)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P6)
c1=c1+chan.value
print (c1/100/64)
sleep(.2)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp1, MCP.P7)
c1=c1+chan.value
print (c1/100/64)
print (" ")
sleep(3)
print(mcp2)
print("Channel 2")
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P0)
c1=c1+chan.value
print (c1/100/64)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P1)
c1=c1+chan.value
print (c1/100/64)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P2)
c1=c1+chan.value
print (c1/100/64)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P3)
c1=c1+chan.value
print (c1/100/64)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P4)
c1=c1+chan.value
print (c1/100/64)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P5)
c1=c1+chan.value
print (c1/100/64)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P6)
c1=c1+chan.value
print (c1/100/64)
c1 = 0
for i in range (1, 101):
chan=AnalogIn(mcp2, MCP.P7)
c1=c1+chan.value
print (c1/100/64)
sleep(3)
print(" ")
sleep(3)我发现mcp3008的噪音比较大,即使输入信号是干净的,所以我用100个样本来平均值最终的结果。事情慢了一点,但结果看上去更好。
https://stackoverflow.com/questions/71345822
复制相似问题