Go Down

Topic: Compare two sensor values (Read 14293 times) previous topic - next topic

snickers_90

Hey there :-)

I'm sort of new to Arduino and did an experiment with a flex sensor. If I bend it the status of it is shown via 10 LEDs (like here: http://arduinobasics.blogspot.de/2011/05/arduino-uno-flex-sensor-and-leds.html). Everything works fine until now.
Now I need to do it a bit modified for two sensors. I can describe it in words what I wanna do but I don't know how to write this in code :-(
Maybe I try to explain it for you:

From both sensors I get values between 200 and 360. I now want to compare both values and if they are the same (maybe with a tolerance of 10 or 20) a new LED should turn on. So if values of sensor 1 (+/-10) are the same like those of sensor two (+/-10) an new LED should show this to me.

How do I write this in the basic code from the link above?

Thanks a lot for your support :-)

Krodal

#1
May 11, 2012, 01:42 am Last Edit: May 11, 2012, 09:02 am by Krodal Reason: 1
I don't know what you want to program.
If the sensors are about the same, should a led turn on? Or should a new led turn (thus incrementing the led bar).

If you map both sensor values, you could just calculate the difference.
Code: [Select]

int difference = lightLevel2 - lightLevel1;

if (difference < 10 && difference > -10)
{
  // show new led.
}


snickers_90

I think this might be the right way  ;) Sorry for my difficult explanation, I've tried to explain it as understandable as possible in my best english ;-)

The construction of my prototype is about the same as in the tutorial (link). The only thing I want to add is another row of 10 LEDs for the second sensor. So if I get for example value 260 for sensor 1 and 260 for sensor 2 (+/-10 tolerance) another LED outside of these two rows should turn on and show me that both sensors have about the same value. This process should always be running in my sketch. Do you understand it a bit better now? I hope so :~

In your code you compare the two sensor values and if it's +/-10 an LED is turned on, right? So I think it's the way I have to do it isn't it?

Later on I will have an interface on the screen that replaces the LEDs. But for prototyping and learning Arduino I think this way is the better one for learning the tool.

Thanks a lot for you really quick reply :) I'm on my way to learn Arduino  ;)

Krodal

#3
May 11, 2012, 09:09 am Last Edit: May 11, 2012, 09:17 am by Krodal Reason: 1
I understand.

You want two led bars. One for each sensor.
And you want light a led if the both are about the same.

But the Arduino doesn't have enough pins for two led bars. You could use a 74hc595 and this: http://arduino.cc/en/Tutorial/ShiftOut
If you have used the 74hc595 before, it's easy to do.
If you didn't use the 74hc595 before, you might make things more complicated than they should be.
The same goes for Charlieplexing: http://arduino.cc/playground/Code/Charlieplex   http://www.instructables.com/id/CharliePlexed-LED-string-for-the-Arduino/

If you are just testing, test one sensor with the bar. And after that test the other sensor.
You might even use the bar to show how close the sensorsvalues match (by showing the absolute difference on the bar).

Code: [Select]

  // the absolute difference
  int difference = lightLevel2 - lightLevel1;

  difference = abs(difference);         // 'abs' is the absolute value, the result is always positive.

  if (difference >= 0 && difference < 10)
  {
    // match within 10
  }
  else if (difference >= 10 && difference < 20)
  {
    // they differ between 10 and 20
  }
  else if (difference >= 20 && difference < 30)
  {
    // they differ between 20 and 30
  }
  else
  {
    // outside range
  }



PaulS

Those if statements are unnecessarily complex.

If the first statement evaluates to true, the remaining ones will not be evaluated.

If the first statement evaluates to false, you KNOW that difference is not less than 10, so there is not need to test that condition again.

The same holds true for the remaining statements. The value in difference will be handled by the first statement that evaluates to true, so there is not need to keep confirming that difference is greater than or equal to the previous cut off value.
The art of getting good answers lies in asking good questions.

Krodal

#5
May 11, 2012, 04:02 pm Last Edit: May 11, 2012, 04:09 pm by Krodal Reason: 1
For PaulS:

Code: [Select]

  // the absolute difference
  int difference = lightLevel2 - lightLevel1;

  difference = abs(difference);       // 'abs' is the absolute value, the result is always positive.

  if (difference < 10)                      // it's always higher or equal than zero
  {
    // match within 10
  }
  else if (difference < 20)                // the range 0...10 has already been tested
  {
    // they differ between 10 and 20
  }
  else if (difference < 30)
  {
    // they differ between 20 and 30
  }
  else
  {
    // outside range
  }

PaulS

Quote
For PaulS:

Exactly. That code makes it much easier to see, at a glance, which block of code is going to be executed for any given value of difference, and makes the evaluation faster.
The art of getting good answers lies in asking good questions.

snickers_90

Thank you so much for your support. That's exactly what I was looking for  8)

Everything works fine in my code :-)


snickers_90

I need your help one more time. I now changed something in my code and it doesn't work any longer :(

I've tried to built in my LED outputs (5,6,7) in your "comparison function" but it doesn't work anymore  =(

Could you help me and explain what I'm doing wrong? Sorry, I'm really new to Arduino  :~ I think it has something to do with the "contrain". What exactly does this command do?

So here's my code:

Code: [Select]

// Sensor Pins (A0, A1)
int flexPin1 = 0;
int flexPin2 = 1;

// sets LED Pins 5,6,7 to output         
void setup() {
  for (int i=5; i<8; i++){
    pinMode(i, OUTPUT);
  }
}

// blink function: that you can see the LEDs turning on and off
void blink(int 5, int onTime, int offTime){
digitalWrite(5, HIGH); 
delay(onTime);
  digitalWrite(5, LOW); 
  delay(offTime);
}

//
void loop(){

  //Ensure to turn off ALL LEDs before continuing
for (int i=5; i<8; i++){
    digitalWrite(i, LOW);
  }

// the two sensor values are read
int lightLevel1 = (analogRead(flexPin1));
int lightLevel2 = (analogRead(flexPin2));
     

///////// compare the two sensor values //////////

// the absolute difference
  int difference = lightLevel2 - lightLevel1;

  difference = abs(difference);       // 'abs' is the absolute value, the result is always positive.

  if (difference < 10)                      // it's always higher or equal than zero
  {
    // match within 10
    int ledON = constrain(difference, 5, 7);
    blink(ledON, 10,1);
  }
  else if (difference < 20)                // the range 0...10 has already been tested
  {
    // they differ between 10 and 20
    int ledON = constrain(difference, 5, 7);
    blink(ledON, 10,1);
  }
  else if (difference < 30)
  {
    // they differ between 20 and 30
    int ledON = constrain(difference, 5, 7);
    blink(ledON, 10,1);
  }
  else
  {
    // outside range; i = all LEDs
    digitalWrite (i, LOW);
  }
  }

PaulS

Code: [Select]
int lightLevel1 = (analogRead(flexPin1));
int lightLevel2 = (analogRead(flexPin2));

Why is the analogRead() call in parentheses? They are not needed.

You are sorting out the difference between two sensor values. Then, you are constraining the difference to be in the range of 5 to 7. Then, regardless of what that function comes up with, you blink pin 5.

The most obvious problem is that you don't seem to understand what the constrain function does. Perhaps clamp() might have been a better name. If the input value is less than the low end of the range, the output value IS the low end of the range. If the input value is greater than the high end of the range, the output value is the high end of the range.

When difference is greater than 10, the output will always be 7. Is that what you want? If it is, there is no reason to have any if/else statements.

Making the blink function use an argument for the pin to blink, rather than a hardcoded value would be a good idea, too. I find it hard to believe that that even compiles.

One final comment. "t doesn't work" is incredibly lame. That code does something. You want it to do something. That the two somethings are not the same thing is pretty obvious. What either one of them is is not defined. If you really want help, you need to describe what the code does, what you expect it to do, and how those two differ.
The art of getting good answers lies in asking good questions.

snickers_90

I'm sorry but I'm at the moment confused of my own code  :~ And it's not easy to explain it in English. I really want to learn this tool but it's difficult to learn the language in such a fast way.I have to built this prototype for a project at school and hope it's my chance to learn it  ;)

Maybe again in words what I'd like to do: I still have 10 LEDs and two flex sensors. All I'm trying to do at the moment is showing that if both sensors have the same values (+/- tolerance --> the "if statements" in the code) an LED should turn on. In my code I've tried to turn on LED 5 for a tolerance of 0 to 10, LED 6 for a tolerance of 10 to 20 and LED 7 for a tolerance of 20 to 30. So all the other LEDs are not used for testing. As I said before, in the end I want to use processing for an interface on the screen.

Code: [Select]
  if (difference < 10)                      // it's always higher or equal than zero
  {
    // match within 10
    int ledON = constrain(difference, 5, 7);
    blink(ledON, 10,1);
  }


So here I'm trying to say:

"If there is a difference of both sensors of 0 to 10: turn on LED 5 by using the "blink function" (that should only be used to delay the LEDs' turning on and off)."

How can I say that only LED 5 should be turned on in this range? If I leave out the "7" in the statement it doesn't work.

Do you now understand a bit better what I'm trying to do?

robtillaart

#11
May 13, 2012, 02:57 pm Last Edit: May 13, 2012, 02:59 pm by robtillaart Reason: 1
Q: what is your native language? adjust your profile then we know :)

refactored your code to something that works again, maybe not what you want but a new starting point
+ blink function was incorrect (param 1)
+ removed constraining
+ adjusted blink timing to something visible (1 msec off is hardly visible)

(code compiles but not further tested)
Code: [Select]
// Sensor Pins (A0, A1)
int flexPin1 = 0;
int flexPin2 = 1;

// sets LED Pins 5,6,7 to output          
void setup() {
for (int i=5; i<8; i++){
pinMode(i, OUTPUT);
}

//Ensure to turn off ALL LEDs before continuing
for (int i=5; i<8; i++){
digitalWrite(i, LOW);
}
}

// blink function: that you can see the LEDs turning on and off
void blink(int pin, int onTime, int offTime)
{
digitalWrite(pin, HIGH);  
delay(onTime);
digitalWrite(pin, LOW);  
delay(offTime);
}

//
void loop()
{
int lightLevel1 = analogRead(flexPin1);
int lightLevel2 = analogRead(flexPin2);

///////// compare the two sensor values //////////

// the absolute difference
int difference = abs(lightLevel2 - lightLevel1);  // the diff is always >= 0.

if (difference < 10)                      // it's always higher or equal than zero
{
blink(5, 50, 50);
}
else if (difference < 20)                // the range 0...10 has already been tested
{
blink(6, 50, 50);
}
else if (difference < 30)
{
blink(7, 50, 50);
}
else
{
blink(5, 10, 10);
blink(6, 10, 10);
blink(7, 10, 10);
}
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

snickers_90

I'm from Germany  ;) I will edit my profile soon hehe...will be easier  :D

That is definitely more close to what I wanna do  8) great :-) It's even clearer arranged now...and understandable   :D

What it does:
- all LEDs are flickering after plugging my Arduino UNO to the USB port
- if I bend one of the sensors the LEDs 5 to 7 turn on and off in sequence
- the same works for both sensors bending them at the same time

But:
- I still cannot see the difference  :(
- the LEDs should only turn on if both sensors have different values
  (for example: flexPin1 gives me a value of 270, flexPin2 a value of 225 -> difference of 25 -> LED 7 should blink)
- at the moment they also turn on and off if they have the same values


But it's really really close to what I wanna do  8) You are great!!!

PaulS

Quote
- all LEDs are flickering after plugging my Arduino UNO to the USB port

Quote
- at the moment they also turn on and off if they have the same values

Because of this:
Code: [Select]
else
{
blink(5, 10, 10);
blink(6, 10, 10);
blink(7, 10, 10);
}

Remove this code if you want nothing to happen when the values are the same.

There are some improvements that could be made to the code that Rob posted (which was based on yours initially, so it is not his fault).

Code: [Select]
int lightLevel1 = analogRead(flexPin1);
int lightLevel2 = analogRead(flexPin2);

How do you get light level from a flex sensor? Meaningful names are very useful for writing code that does not require a lot of thinking to decipher/create.

I mean that there is nothing stopping you from writing:
  int lightLevel1 = analogRead(flexPin1);
  int q = analogRead(flexPin2);
But, of course, that makes little sense when you then subtract q from lightLevel1. Your names are only a little less confusing, since flex sensors and light are unrelated.

Unless you have actually written 1 and 2 on the sensors, names that reflect the physical arrangement of the sensors make more sense, too.

Quote
(for example: flexPin1 gives me a value of 270, flexPin2 a value of 225 -> difference of 25 -> LED 7 should blink)

There are no Serial.print() statements in the code that indicate that you know what the actual values are. Normally, I don't like to see commented out code in code that is posted, but commented out Serial.print() statements are an exception. With them present but commented out, it is easy to see that you do know how to debug code and that you have facts to support your suppositions.

Without them, we have no way of knowing what actual values you are reading from each sensor, or that you are even reading each sensor correctly.
The art of getting good answers lies in asking good questions.

snickers_90

Code: [Select]
Serial.println(analogRead(flexPin1));
         delay (100);


I now get values for sensor 1 from 398 to 496 and for sensor two from 492 to 340. But don't I have to use the "map function" again now in order to map those values to my LED ports? Something like this:
Code: [Select]
int lightLevel1 = map(analogRead(flexPin1), 398, 496, ??, ??);
What do I have to put in for the question marks? Cause I don't a have a row of LEDs now any longer that counts up and down. It now refers to the "compare function", doesn't it? It's getting too complicated for me as a beginner  =(

Here is my code so far:
Code: [Select]
// Sensor Pins (A0, A1)
int flexPin1 = 0;
int flexPin2 = 1;

// sets LED Pins 5,6,7 to output         
void setup() {
        Serial.begin(9600);
for (int i=5; i<8; i++){
pinMode(i, OUTPUT);
}

//Ensure to turn off ALL LEDs before continuing
for (int i=5; i<8; i++){
digitalWrite(i, LOW);
}
}

// blink function: that you can see the LEDs turning on and off
void blink(int pin, int onTime, int offTime)
{
digitalWrite(pin, HIGH); 
delay(onTime);
digitalWrite(pin, LOW); 
delay(offTime);
}

//
void loop()

        int lightLevel1 = analogRead(flexPin1);
int lightLevel2 = analogRead(flexPin2);

///////// compare the two sensor values //////////

// the absolute difference
int difference = abs(lightLevel2 - lightLevel1);  // the diff is always >= 0.
             //   Serial.println(analogRead(flexPin1));
             //   delay (100);
             //   Serial.println(analogRead(flexPin2));
if (difference < 10)                      // it's always higher or equal than zero
{
digitalWrite(5, HIGH);
}
else if (difference < 20)                // the range 0...10 has already been tested
{
digitalWrite(6, HIGH);;
}
else if (difference < 30)
{
digitalWrite(7, HIGH);;
}
else
{
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
}
}




Go Up