Post Go back to editing

树莓派4B驱动AD7606驱动问题

您好,我用python尝试着写了写spi接收的AD7606驱动,但采样的结果不正确,比如应该是0V的电压值,但接收回来的却是1V左右。而且感觉采样点数很少,达不到200k。可能是我写的代码的问题,但我找不出来,辛苦您帮我看一下该怎么修改,不胜感激。

代码如下:

import RPi.GPIO as GPIO, numpy as np, spidev, time, sys
GPIO.setwarnings(False)

SAMPLING_POINTS = 1000 #采样点数
nums = 0 #初始化变量,记录采样的数量

# 定义引脚
AD_CS_PIN = 16 #低有效
AD_RESET_PIN = 18
AD_CONVST_PIN = 7 #pwm控制转换启动
AD_RANGE_PIN = 11
AD_OS0_PIN = 13
AD_OS1_PIN = 15
AD_OS2_PIN = 31
AD_BUSY_PIN = 29
GPIO.setmode(GPIO.BOARD) #物理引脚
GPIO.setup(AD_CS_PIN, GPIO.OUT)
GPIO.setup(AD_RESET_PIN, GPIO.OUT)
GPIO.setup(AD_OS0_PIN, GPIO.OUT)
GPIO.setup(AD_OS1_PIN, GPIO.OUT)
GPIO.setup(AD_OS2_PIN, GPIO.OUT)
GPIO.setup(AD_RANGE_PIN, GPIO.OUT)
GPIO.setup(AD_CONVST_PIN, GPIO.OUT)
GPIO.setup(AD_BUSY_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) #启用上拉电阻,低表示正在转换

num_rows = 8 #定义数据矩阵的行数
num_columns = SAMPLING_POINTS #定义数据矩阵的列数,与采样点数一致

#SPI 通信设备初始化,设置spi通信参数
spi = spidev.SpiDev() #spi是SPI通信的设备对象
spi.open(0, 0) #打开SPI接口,使用总线0,设备0
spi.max_speed_hz = 8000000 #设置SPI通信速度为8MHz
spi.mode = 0b00 #设置SPI模式,采用cpol=0,cpha=0的模式

ad7606SamplingDoneFlag = 0

data2 = np.zeros((8, 1000))

def AD7606_Raspberry_Pi(RANGE =0, OS = 0): #定义了一个函数AD7606_Raspberry_Pi(RANGE = 1, OS = 0),用于控制AD7606的采样
global AD_CS_PIN, AD_RESET_PIN, AD_CONVST_PIN, AD_OS0_PIN, AD_OS1_PIN, AD_OS2_PIN, AD_RANGE_PIN, ad7606SamplingDoneFlag
# Initialize CS pin
GPIO.output(AD_CS_PIN, GPIO.LOW) #初始化片选信号低电平

# Reset AD7606 #重置AD7606芯片
GPIO.output(AD_RESET_PIN, GPIO.LOW)# 将RESET引脚拉低
time.sleep(0.001) # 等待一段时间,以确保复位操作完成
GPIO.output(AD_RESET_PIN, GPIO.HIGH) # 将RESET引脚拉高,完成复位操作
time.sleep(0.001)# 再次等待一段时间,以确保复位操作完成
GPIO.output(AD_RESET_PIN, GPIO.LOW)# 将RESET引脚再次拉低,再拉高不行,这里的复位是高电平有效


# PWM 通过PWM信号启动AD7606的转换。PWM信号的频率为100000Hz,占空比为99%,100kHz理论上对应着每秒转换100K次,速度上也合理
PWM0 = GPIO.PWM(AD_CONVST_PIN, 100000)
PWM0.start(90) #调节占空比对输出速度没有明显的效果

GPIO.output(AD_OS0_PIN, GPIO.LOW)
GPIO.output(AD_OS1_PIN, GPIO.LOW)
GPIO.output(AD_OS2_PIN, GPIO.LOW)

if RANGE == 0: #根据输入参数RANGE,设置量程。如果RANGE为1,则设置范围为±10V
GPIO.output(AD_RANGE_PIN, GPIO.LOW)
else:
GPIO.output(AD_RANGE_PIN, GPIO.HIGH)
#等待采样完成
while True:#进入无限循环,等待AD7606完成采样
if ad7606SamplingDoneFlag: #如果采样完成标志ad7606SamplingDoneFlag被设置,则关闭PWM信号,停止转换过程
PWM0.ChangeDutyCycle(0)
#PWM0.stop()
GPIO.output(AD_CS_PIN, GPIO.HIGH)
ad7606SamplingDoneFlag = 0 #之后将采样完成标志重置为未完成
GPIO.cleanup() #清理GPIO设置
break #退出循环
#回调函数部分
def call_back(channel):
global AD_CS_PIN, array, nums, ad7606SamplingDoneFlag # # 声明全局变量
if nums < SAMPLING_POINTS: # 如果采样点数小于设定的最大采样点数
ad7606SamplingDoneFlag = 0 #重置采样完成标志
for i in range(8): #对每个通道进行采样
GPIO.output(AD_CS_PIN, GPIO.LOW) # 将片选信号拉低,选中AD7606
#
rx_data = spi.xfer2([0x00, 0x00]) # 从SPI接口读取数据,这里的x应该指16进制
# print(i,rx_data)
#
data = (rx_data[0] << 8) | rx_data[1]
# print(nums,data)
if data >= 32768:
data1 = data - 32768
else :
data1 = data + 32768
# print(1,data1)
data2[i][nums] = ((int(data1) / 65535 ) * 20) - 10

if i == 0: # 如果当前是第一个通道
print(nums,":",data2[i][nums]) # 打印该通道的数据

GPIO.output(AD_CS_PIN, GPIO.HIGH) # 将片选信号拉高,取消选中AD7606
nums = nums + 1 # 增加采样点数计数器
else:
ad7606SamplingDoneFlag = 1 # 如果采样点数不小于设定的最大采样点数,则设置采样完成标志为已完成


if __name__ == "__main__": # 主执行部分:设置事件检测并初始化AD7606 ADC
GPIO.add_event_detect(AD_BUSY_PIN, GPIO.FALLING, callback=call_back) # 当AD_BUSY_PIN引脚状态发生变化时,触发回调函数call_back()
AD7606_Raspberry_Pi(RANGE=0, OS=0)

打印出来的结果为(正常这些结果应该在0V左右):

0 : 0.6227206836041805
1 : 1.010910200656138
2 : 0.5058365758754864
3 : 0.9962615396353094
4 : 0.9962615396353094
5 : 0.4982070649271382
6 : 0.9971770809491112
7 : 1.245288776989394
8 : 0.9971770809491112
9 : 1.010910200656138
10 : 0.5055313954375524
11 : 0.4982070649271382
12 : 0.6245517662317841
13 : 0.9962615396353094
14 : 0.624856946669718
15 : 1.245288776989394
16 : 1.2306401159685656
17 : 1.2306401159685656

  • 我发现我有一个接地引脚没接,导致的数据不稳定,现在这个小问题解决了。

    但是感觉采样结果的输出速度依然很慢,达不到200k,请问代码怎么修改一下可以提升一下?

  • 你好呀,AD7606是SAR型的ADC,其数据输出速率除了取决于其最短tCONV时间以外,很大程度上还取决于你的施加到ADC上的spi速率,启动转换的速率,这些你都确保够快了吗?我看你程序上设置的确实不小,但是树莓派主控在程序上的设置和它外设本身能跑出来的速度可能有差异,建议用逻辑分析仪抓一下实际测试中的波形,看是哪一块的速度根不上。