Pages: [1]   Go Down
Author Topic: LEDS, cross fading, mapping question  (Read 462 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 0
Posts: 126
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

so i think i have a pretty decent sketch that does what i need. to sum it up, the values from an infrared sensor are being averaged and then mapped to control pwm range of some LED's. as you increase, decrease, the leds crossfade between each other.

now my question: i want to simply trigger a 3rd LED to digital HIGH and set the other two crossfading LED's to LOW, but when i try this with my if statement, the mapping from sensor is causing confliction and in turn, causing the crossfade LEDS to flicker. suggestions? heres the code:

Code:
//Use of MaxSonar EZ1 sonar module in analog mode with arduino
// median filter of five consecutive readings to eliminate spikes
//
// Bill Gentles, Nov. 12, 2010
//borrowing an idea from the Arduino Forum on array sort
//http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1283456170/12
//the "insert sort" code is from whistler
//
//take 5 readings and store them in an array rangevalue[]
//using an "ascending insert sort" rearrange the array values in ascending order
//choose the middle element in the array, which will by definition be the median of the set of values
//
//Analog pin 1 for reading in the analog voltage from the MaxSonar device.
 const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
 int vals;
 const int anPin = 1;
const int led1 = 10; // DIGITAL output pin that the LED is attached to
const int ledsignal = 13;
const int led2 = 9; // DIGITAL output pin that the LED is attached to
int sensorValue = 0; // value read from the pot
int outputValue1 = 0; // value output to the PWM
int outputValue2 = 0; // value output to the PWM
//variables needed to store values
int arraysize = 3;  //quantity of values to find the median (sample size). Needs to be an odd number
int rangevalue[] = {0, 0, 0};    //declare an array to store the samples. not necessary to zero the array values here, it just makes the code clearer
//*********************************************************************************************
void setup()
{
    for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;         
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(ledsignal, OUTPUT);
  //This opens up a serial connection to shoot the results back to the PC console
  Serial.begin(9600);
  printArray(rangevalue, arraysize);
 //delay(10);   //wait a while to open serial monitor window

}
//********************************************************************************
void loop()
{
// subtract the last reading:
  total= total - readings[index];         
  // read from the sensor: 
  readings[index] = analogRead(anPin);
  // add the reading to the total:
  total= total + readings[index];       
  // advance to the next position in the array: 
  index = index + 1;                   

  // if we're at the end of the array...
  if (index >= numReadings)             
    // ...wrap around to the beginning:
    index = 0;                           

  // calculate the average:
  average = total / numReadings;     
  pinMode(anPin, INPUT);
  vals = constrain(vals, 66, 490);
  outputValue1 = map(vals, 66, 211, 0, 255);
outputValue2 = map(vals, 490, 241, 0, 255);
// change the analog out value:
analogWrite(led1, outputValue1);
analogWrite(led2, outputValue2);
//delay(1000);

if ( vals >= 212 && vals<=240 ){
  digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
      digitalWrite(ledsignal, HIGH);
}
else {
  digitalWrite(ledsignal, LOW);
}
  //MaxSonar Analog reads are known to be very sensitive. See the Arduino forum for more information.
  //Maxbotix does not recommend averaging readings as the occasional value can be wildly inaccurate and skew the average
  //A median sort is the preferred method.

   for(int i = 0; i < arraysize; i++)
   {     //array pointers go from 0 to 4

    //Used to read in the analog voltage output that is being sent by the MaxSonar device.
    //The MaxSonar Scale factor is (Vcc/512) per inch. A 5V supply yields ~9.8mV/in
    //The Arduino will map input voltages between 0 and 5 volts into integer values between 0 and 1023.
    //This yields a resolution between readings of: 5 volts / 1024 units or, .0049 volts (4.9 mV) per unit.
    //Therefore, one unit from the arduino's ADC represents 0.5 inches

     rangevalue[i] = analogRead(anPin);
//     Serial.print("i, value   ");
//     Serial.print(i);
//     Serial.print(" ,  ");
//     Serial.print(rangevalue[i]);
//     Serial.println();

     //delay(1);  //wait between analog samples
    }

   //Serial.print("unsorted ");
   printArray(rangevalue, arraysize);
  // Serial.println();
   isort(rangevalue, arraysize);
   //Serial.print("sorted ");
   printArray(rangevalue, arraysize);
   //Serial.println();

 // now show the medaian range
    int midpoint = arraysize/2;    //midpoint of the array is the medain value in a sorted array
//note that for an array of 5, the midpoint is element 2, as the first element is element 0
    // Serial.print("median range value ");
    // Serial.print(rangevalue[midpoint]);
    // Serial.println();
     //Serial.println();
 vals = rangevalue[midpoint];
  //delay(1);    //wait a while so you can read the values on the serial monitor

}   //end of loop

//*********************************************************************************
// sort function
void isort(int *a, int n)
   //  *a is an array pointer function
{
  for (int i = 1; i < n; ++i)
  {
    int j = a[i];
    int k;
    for (k = i - 1; (k >= 0) && (j < a[k]); k--)
    {
a[k + 1] = a[k];
    }
    a[k + 1] = j;
  }
}
//***********************************************************************************
//function to print array values
void printArray(int *a, int n)
{

  for (int i = 0; i < n; i++)
  {
   // Serial.print(a[i], DEC);
    //Serial.print(' ');
  }

  //Serial.println();
}


Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46090
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;         
The compiler has already set the elements in readings to 0.

Code:
  printArray(rangevalue, arraysize);
Why? You know what values are in the array at this point.

Code:
  readings[index] = analogRead(anPin);
<snip>
  pinMode(anPin, INPUT);
You set the pin to INPUT after you've read from it. Why? The pin mode should be declared in setup(), not loop(). In any case, this is wrong. The pinMode() function is for digital pins. So, you just set the mode for digital pin 1 (a serial pin, specifically the TX pin) to input. Bad idea.

Code:
if ( vals >= 212 && vals<=240 ){
  digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
      digitalWrite(ledsignal, HIGH);
}
I
   love
       code
            that
                 wanders
                     across
                          the
                               page
                                    for
                                        no
                                            reason.

Code:
vals = rangevalue[midpoint];
vals is a scalar. Why is the name plural? A more meaningful name would be useful.

The variable vals is used and then computed. Why is that?

Quote
but when i try this with my if statement, the mapping from sensor is causing confliction and in turn, causing the crossfade LEDS to flicker. suggestions?
What does "causing confliction" mean?

You are turning the fading LEDs off, but then on the next pass though loop, you resume them fading, and then turn them off again. It's no wonder they don't stay off.

Code:
if(vals >= 212 && vals<=240)
{
   digitalWrite(led1, LOW);
   digitalWrite(led2, LOW);
   digitalWrite(ledsignal, HIGH);
}
else
{
  analogWrite(led1, outputValue1); // <-- move the analog writes to here
  analogWrite(led2, outputValue2);
  digitalWrite(ledsignal, LOW);
}
would work better.
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 126
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks for the helpful (and at times unnecessarily snarky) tips. cheers
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24361
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To avoid similar comments in future, maybe use the IDE's auto format tool before posting code?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Full Member
***
Karma: 0
Posts: 126
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

great suggestion. thanks
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 126
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

actually now I'm trying to crossfade between the 3 LED's and I'm having a road block conceptually on how to tackle this. i ended up making two more map functions, but i know this isn't necessary. so transition is led1 cross fades into led2; led 2 crossfades into led3 
Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 126
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

sorry, here is what I'm doing:

Code:
  outputValue1 = map(values, 25, 40, 0, 255);
  outputValue2 = map(values, 40, 25, 0, 255);
  outputValue3 = map(values, 2, 24, 0, 255);
  outputValue4= map(values, 24, 2, 0, 255);
  // change the analog out value:


  //analogWrite(led1, outputValue1);
  //  analogWrite(ledsignal, outputValue2);

  if(values >= 25 ){

    analogWrite(led1, outputValue1);
    analogWrite(ledsignal, outputValue2);
  }

  if(values >= 2 && values <= 24)
  {
    analogWrite(led2, outputValue4);
    analogWrite(ledsignal, outputValue3);


  }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46090
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  outputValue1 = map(values, 25, 40, 0, 255);
  outputValue2 = map(values, 40, 25, 0, 255);
  outputValue3 = map(values, 2, 24, 0, 255);
  outputValue4= map(values, 24, 2, 0, 255);
There's a problem here. You are saying to map the value in values (please, is that name meaningful in any way?) from two different ranges to a value in the range 0 to 255. Suppose values contains 47. What do you expect the outputValueN values to be? What if it is 30? What if it is 20? What if it is 0?

The map function will, correctly, return a value that is not in the to range, if the input is not in the from range, so for any given value of values, you are going to get at least two output values that are greater than 255 or less than 0. Possibly 4 of them.
Logged

Pages: [1]   Go Up
Jump to: