简而言之,我使用此 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 的数据表,至少在理论上,可以在不改变电路其余部分的情况下更换另一种。然而,我可能是错的,这可能是所有这些头痛的原因,我只是不知道我需要准确检查什么。
我希望我的解释足够清楚!
您应该尝试校准 ADC。我相信可以通过短接 Vref 和 AGND 引脚来完成,尽管这需要一些验证,然后在不关闭系统电源的情况下再次尝试您的程序。
否则我不会在您的代码中看到错误。看起来 SPI 通讯是正确的。