MCP3208 读取错误并且值非常不稳定 - Raspberry Pi 4

问题描述 投票:0回答:1

简而言之,我使用此 ADC 通过放大器读取传感器的输出。我验证了运算放大器的输出符合我的预期,而且确实如此。直接在 ADC 引脚上测量时,电压是正确的。 它由来自 Raspberry 的 3.3V 供电,Vref 引脚也为 3.3V。

所以问题来自于ADC(我已经尝试过使用两个芯片)。它读取的值是错误的且非常嘈杂。这是我得到的输出示例:

Raw Value: 1338 | Voltage: 1.078V
Raw Value: 1079 | Voltage: 0.870V
Raw Value: 88 | Voltage: 0.071V
Raw Value: 816 | Voltage: 0.658V
Raw Value: 1250 | Voltage: 1.007V
Raw Value: 1496 | Voltage: 1.206V
Raw Value: 0 | Voltage: 0.000V
Raw Value: 1095 | Voltage: 0.882V
Raw Value: 711 | Voltage: 0.573V
Raw Value: 1482 | Voltage: 1.194V
Raw Value: 327 | Voltage: 0.264V
Raw Value: 1344 | Voltage: 1.083V
Raw Value: 967 | Voltage: 0.779V
Raw Value: 38 | Voltage: 0.031V
Raw Value: 647 | Voltage: 0.521V
Raw Value: 3673 | Voltage: 2.960V
Raw Value: 967 | Voltage: 0.779V
Raw Value: 704 | Voltage: 0.567V
Raw Value: 1087 | Voltage: 0.876V
Raw Value: 999 | Voltage: 0.805V
Raw Value: 384 | Voltage: 0.309V
Raw Value: 583 | Voltage: 0.470V
Raw Value: 1112 | Voltage: 0.896V
Raw Value: 1343 | Voltage: 1.082V
Raw Value: 1279 | Voltage: 1.031V
Raw Value: 2672 | Voltage: 2.153V
Raw Value: 1248 | Voltage: 1.006V

在此示例中,引脚上施加了 3.3V 电压。

这是用于从 ADC 获取值的库:

#include "MCP3208.h"

#include <wiringPi.h>

using namespace std;

MCP3208::MCP3208(int CS, int CLK, int MOSI, int MISO) {
    this->CS = CS;
    this->CLK = CLK;
    this->MOSI = MOSI;
    this->MISO = MISO;
}

void MCP3208::setupSPI() {
    wiringPiSetup();
    
    pinMode(CS, OUTPUT);
    pinMode(CLK, OUTPUT);
    pinMode(MOSI, OUTPUT);
    pinMode(MISO, INPUT);

    digitalWrite(CS, HIGH);
    digitalWrite(CLK, LOW);
    digitalWrite(MOSI, LOW);
}

int MCP3208::readADC(int channel) {
    if (channel > 7 || channel < 0) return -1;
    
    digitalWrite(CS, LOW); //Starts the conversation

    // Constructs command
    // 0b -> Binary
    // 11 -> Start of the command
    // (channel << 3) -> Specified channel converted to binary and moved to the bits 5, 4 and 3
    // Last 000 -> Don't Care Bits
    unsigned char command = 0b11000000 | (channel << 3);
    
    // Sends command, left to right
    for (int i = 7; i >= 0; i--) {
        digitalWrite(MOSI, (command >> i) & 1); // Extracts the value of the i-th bit by shifting bits to the right and leaving the desired bit last (to the right) with the mask '& 1'
        digitalWrite(CLK, HIGH);
        digitalWrite(CLK, LOW);
    }

    // Read 12-bit ADC data
    int value = 0;
    for (int i = 11; i >= 0; i--) {
        value <<= 1; // Shifts all existing bits to the left, to create space for the next bit to be read
        digitalWrite(CLK, HIGH); // Signals the ADC to output the next bit on MISO
        if (digitalRead(MISO)) {
            value |= 1; // Adds the bit when it is equal to 1, 0 by default when shifting bits
        }
        digitalWrite(CLK, LOW);
    }

    digitalWrite(CS, HIGH);

    return value;
}

这是用于实际打印值的程序:

#include "/home/pi/Desktop/MCP3208/MCP3208.h"

#include <wiringPi.h>
#include <stdio.h>

// MCP3208 parameters
#define CS 10    // Chip Select
#define CLK 14   // Clock
#define MOSI 12  // Master Out Slave In
#define MISO 13  // Master In Slave Out

MCP3208 adc(CS, CLK, MOSI, MISO);

int main() {
    adc.setupSPI();
  
    while (1) {
        int value = adc.readADC(1); // Read from channel 0
        float voltage = value * 3.3 / 4095.0;
  
        printf("Raw Value: %d | Voltage: %.3fV\n", value, voltage);
  
        delay(500);
    }
  
    return 0;
}

顺便说明一下,该电路已经使用 MCP3008 进行了测试,但为了获得更高的读数精度,已将其替换为 MCP3208。根据这两种 ADC 的数据表,至少在理论上,可以在不改变电路其余部分的情况下更换另一种。然而,我可能是错的,这可能是所有这些头痛的原因,我只是不知道我需要准确检查什么。

我希望我的解释足够清楚!

raspberry-pi adc
1个回答
0
投票

您应该尝试校准 ADC。我相信可以通过短接 Vref 和 AGND 引脚来完成,尽管这需要一些验证,然后在不关闭系统电源的情况下再次尝试您的程序。

否则我不会在您的代码中看到错误。看起来 SPI 通讯是正确的。

© www.soinside.com 2019 - 2024. All rights reserved.