1

I'm using Arduino Micro to read from 5 flex sensors and display the corresponding angles to the Serial monitor. I am currently having quite some problems with the oscillating values I am getting from the analogRead(). It doesn't seem to matter whether the pin is connected to a flex sensor or just grounded - the output is oscillating a lot.

Originally everything was being read and outputted just fine but I wanted to have an exact 100Hz sampling frequency and tried to play a bit with Timer Interrupts. And that's when this oscillating behaviour started. I reversed to my original code, which just uses some delay(), and simplified to only read from two pins, but cannot seem to shake off the oscillations.

I think I may have messed up something about ADC when trying to implement Interrupts, but I don't know how to check it or fix it. Please, help me figure out how to fix this!

This is the raw output of analogRead. The drop in values occurs when I bend the flex sensor

And this is the resulting calculated angle. Also oscillating.

Here is my code minimal working example:


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);   
}

  • 1
    From the sounds of it, I think this has little to do with your code. You may want to try [Arduino Stack Exchange](https://arduino.stackexchange.com/) and [EE Stack Exchange](https://electronics.stackexchange.com/). – Mode77 Jun 24 '19 at 19:03

1 Answers1

2

ok, analogReads normally do have a little oscillation, its normal! they are measuring voltage values and depending on the sensor you are using they will oscillate, same idea of measuring voltage using a multi meter. if you want to learn a bit more about this, ADC's conversor is a good way to start.

What you need to do in order to prevent those oscillations is to develop a filter. this could be done on hardware or software. Obviously the software is the easiest way to go.

My tip for you would be to a average filter! it's a simple concept, you will get X readings at the same time of that sensors (values would go up and down on variation) and you would get the avarage value out of it.

Here is a simple example using your code:

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);   
}

The idea here is simple, to smooth the values by doing this average, leading to more consistent values. Obviously, Higher number of samples improve the results.

It's simple math, if you are getting 4 values like: 45, 50, 55, 50, your average would be 50 (45+50+55+50 = 200/nSamples = 50)

Nathan Almeida
  • 179
  • 1
  • 14
  • `Obviously the software is the easiest way to go.` simple RC filters take less effort but as this is SO and not Arduino Stack Exchange or EE Stack Exchange, it is still the right answer – Tarick Welling Jun 25 '19 at 08:47
  • Thanks Nathan, I agree, I was expecting a bit of oscillation. But here it is too much I think - I mean, although I keep the sensor bent, the output fluctuates between the 1023 and what I assume the correct value in some sort of periodic way. Like if every nth sample was correct and other samples are just reading 1023. I understand the idea of the average filter and I have tried out the example script you suggested. It does not help however. After using the filter, the angle output is a flat line, doesn’t matter if the sensor bends or not. And the raw (flex) output still fluctuates. – ForestApple Jun 25 '19 at 09:15
  • Honestly I think that while trying to do the interrupt I messed up something with the ADC, but I have no idea how to check it or fix it… – ForestApple Jun 25 '19 at 09:15
  • Well, @ForestApple, maybe try a fresh install if you can't remember where you messed with the interrupts – Nathan Almeida Jun 25 '19 at 11:42
  • How do I do a fresh install? – ForestApple Jun 25 '19 at 13:52