首页 > 解决方案 > 即使引脚接地,analogRead() 输出也会振荡

问题描述

我正在使用 Arduino Micro 从 5 个柔性传感器中读取数据并将相应的角度显示到串行监视器。我目前对从analogRead() 获得的振荡值有相当多的问题。引脚是否连接到柔性传感器或仅接地似乎无关紧要 - 输出振荡很多。

最初一切都被很好地读取和输出,但我希望有一个精确的 100Hz 采样频率,并尝试使用 Timer Interrupts 播放一下。这就是这种振荡行为开始的时候。我反转了我的原始代码,它只使用了一些延迟(),并简化为仅从两个引脚读取,但似乎无法摆脱振荡。

我想我在尝试实现中断时可能搞砸了 ADC,但我不知道如何检查或修复它。请帮我弄清楚如何解决这个问题!

这是analogRead 的原始输出。当我弯曲弯曲传感器时会发生值下降

这就是计算得到的角度。也在震荡。

这是我的代码最小工作示例:


int fin;
const int input[5] = {A0,A1,A2,A3,A4}; // the analog pins

int flex[5]; // analog signal read
float flexV; 
float flexR[5]; // resistance on the 47k resistor
int angle[5]; // joint angles

const float VCC = 4.98; // Measured voltage of Arduino 5V line
// Measured resistance of the 47k resistors R1-R5
const float R[5] = {45900.0,45900.0,45900.0,45900.0,45900.0}; 

// Calibration values of resistance measured during straight phase and 90 deg bend phase
const float R_STRAIGHT[5] = {37651.0,37651.0,37651.0,37651.0,37651.0};
const float R_BEND[5] = {71783.0,71783.0,71783.0,71783.0,71783.0};

void setup() {

}

void loop() {

  for(fin = 0; fin <= 4; fin++) {
   flex[fin] = analogRead(input[fin]);
   flexV = flex[fin]*VCC/1023.0;
   flexR[fin] = R[fin] * (VCC/flexV - 1.0);
   angle[fin] = map(flexR[fin],R_STRAIGHT[fin],R_BEND[fin],0,90.0);
   delay(1);   
    }
    Serial.print(angle[0]);
    Serial.print(" ");
    Serial.print(angle[1]);
    Serial.print(" ");
    Serial.print(angle[2]);
    Serial.print(" ");
    Serial.print(angle[3]);
    Serial.print(" ");
    Serial.print(angle[4]);
    Serial.print(" ");
    Serial.println(millis());
    delay(6);   
}

标签: arduinoadc

解决方案


好的,analogReads 通常确实有一点振荡,这是正常的!它们正在测量电压值,并且根据您使用的传感器,它们会振荡,与使用万用表测量电压的想法相同。如果你想了解更多关于这方面的知识,ADC 的转换器是一个很好的开始。

为了防止这些振荡,您需要做的是开发一个过滤器。这可以在硬件或软件上完成。显然,该软件是最简单的方法。

我给你的建议是平均过滤器!这是一个简单的概念,您将同时获得该传感器的 X 个读数(值会随着变化而上升和下降),并且您会从中获得平均值。

这是一个使用您的代码的简单示例:

int fin;
const int input[5] = {A0,A1,A2,A3,A4}; // the analog pins

int flex[5]; // analog signal read
float flexV; 
float flexR[5]; // resistance on the 47k resistor
float average; //Variable to store the sum of measurements
int nSamples = 4;  //Number of reading you are going to use
int angle[5]; // joint angles

const float VCC = 4.98; // Measured voltage of Arduino 5V line
// Measured resistance of the 47k resistors R1-R5
const float R[5] = {45900.0,45900.0,45900.0,45900.0,45900.0}; 

// Calibration values of resistance measured during straight phase and 90 deg bend phase
const float R_STRAIGHT[5] = {37651.0,37651.0,37651.0,37651.0,37651.0};
const float R_BEND[5] = {71783.0,71783.0,71783.0,71783.0,71783.0};

void setup() {

}

void loop() {

  for(fin = 0; fin <= 4; fin++) {
   /* A new for here to make readings and store them on the average variable */
   for(int x = 0; x <= nSamples; x++){
    flex[fin] = analogRead(input[fin]);
    average = average + flex[fin];
   }
   /*Do de avarage and clear the value on this variable*/
   flex[fin] = average/nSamples;
   avarage = 0;
   flexV = flex[fin]*VCC/1023.0;
   flexR[fin] = R[fin] * (VCC/flexV - 1.0);
   angle[fin] = map(flexR[fin],R_STRAIGHT[fin],R_BEND[fin],0,90.0);
   delay(1);   
    }
    Serial.print(angle[0]);
    Serial.print(" ");
    Serial.print(angle[1]);
    Serial.print(" ");
    Serial.print(angle[2]);
    Serial.print(" ");
    Serial.print(angle[3]);
    Serial.print(" ");
    Serial.print(angle[4]);
    Serial.print(" ");
    Serial.println(millis());
    delay(6);   
}

这里的想法很简单,通过进行平均来平滑值,从而产生更一致的值。显然,更多的样本会改善结果。

这是简单的数学运算,如果您得到 4 个值,例如:45、50、55、50,您的平均值将为 50 (45+50+55+50 = 200/nSamples = 50)


推荐阅读