Examples-> Basics-> Fade re: clarification on code/environment

I am trying to get a better understanding of writing my own (initial and very basic) code on the arduino. I am new to this and may use terminology wrong, feel free to correct me I am not offended by free learning :slight_smile:

I am looking at the basic led fader (File-> Exmaples-> Basics-> Fade). I want to try making this work in a few different ways and then to understand this in reference to the 'environment' it is operating inside of.

Facts:

  • Arduino-Knockoff Nano
  • ground wired to cathode of 3 separate leds
  • Pins 3, 5 and 9 each wired to the anode side of an LED+Resistor

Intended Result:
Change fade program to:
1.)fade the first led on brighter,
2.)then when the first led begins dimming to begin fading the second led on,
3.)when the second led has reached maximum brightness the first led will have just reached minimum (off) brightness, the first led remains off while the second led begins it's dimming cycle and the third led begins to increase it's brightness from off,
4.)When the third led is at maximum, the second led will now be off and the third led will begin dimming, triggering the increasing brightness on the first led and starting the process all over again.

I realize I have not written code for the third led, I have gotten the second led to address directly by simply operating both leds together, so I can use other pins successfully but I'm not creating separate processes/events and making one the trigger for the next. I suspect that I will use whatever this process, in order to allow the third led dimming point of time to coincide with (or trigger) the first led starting up again and tieing the code back into itself.

I believe that I am posting in the proper fashion and that this question has not been addressed. What I am asking for is pretty basic, probably so basic is why is has not been addressed

I have reviewed the following two links:

http://forum.arduino.cc/index.php?topic=97455.0
("read this before posting a programming question")

which references: http://forum.arduino.cc/index.php/topic,148850.0.html
("how to use this forum" under "Installation and Troubleshooting")

These are just my ideas on how this can be possibly accomplished but may or may not apply

If my first LED is LED9 and my second led is LED3; Can I make one led reaching maximum (255) brightness become a trigger, a sort of:

{
if (brightness == 255) {
int led2 = 3
int brightness = 0 // how bright the LED is
int fadeAmount = 5 // How much to fade the led by each cycle
pinMode(led2, OUTPUT); // declare pin 3 to be an output:
analogWrite(led2, brightness); // set the brightness of pin 3
brightness = brightness + fadeAmount; //(dang, which led am i addressing with this statement?) // change the brightness for next time through the loop:

if (brightness == 255) {
fadeAmount = -fadeAmount ;
// reverse the direction of the fading at the end of the Brightening cycle (0-255 but do not reverse when reaching 255-0, simply stay off until code from another led cycle triggers this process to start once more).

delay(30);
// wait for 30 milliseconds to see the dimming effect

Perhaps there is a way to run all 3 leds independently and then put a delay on each one so they cycle like I described but not actually having code interconnected; of course I must understand the timing of the environment, this has been explained in terms of clock cycles but I'm not clear esp enough for 'real world timing' like this. Also are there interrupts the arduino simply experiences as a matter of normal operation that would cause delays in these cycles to build up and malign them (heck would running another cycle for a second and third led be the very cause of the random interrupts)?

I really prefer to learn how to make the code actually link, of course by looking at my code above some of you will be able to spot some pretty basic mistakes (I get the first led to light up from off, then to light up from off, and so on, it never dims back down from Bright and nothing else actually triggers)

HarmlessJohnny5:
feel free to correct me I am not offended by free learning :slight_smile:

Now there is an attitude we could use more of.

Have a look at the demo Several Things at a Time - especially the function that moves the servo in small increments. You could modify that so that the increments represent the brightness of your LEDs and you could have several copies of the modified function - one for each LED.

...R

Sweet thanks! I'll get slogging into that asap, there is (of course, like everyone else I'm sure) a project already going that I'm going to work this into (and so many more things I'll be able to do, motors are probably the next thing I want to do anyway since their proper control is so similar to leds).

You may also be interested in Planning and Implementing a Program

...R

Ok, the current part I'm stuck on and can't seem to find in the 'tutorials' or your information (I do miss things sometimes) is how to do a sort of 'if->then' statement, or exactly how to format the defining of a 'switch' (as mentioned in comments as an alternate approach from the thread of the first link you linked)

I am trying things like this:

int led = 3;           // the PWM pin the LED is attached to
int brightness = 5;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  // declare pin 3 to be an output:
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of pin 3:
  analogWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness == 0 || brightness == 255) {
    fadeAmount = -fadeAmount ;
  }

  if (brightness == 0) {
int led = 5;

i'm trying to implement the idea of:
int pin = 13;
int pin2 = pin;
pin = 12;

(as described in Tutorial, Variables)

Please verify the following statement anyone who can do so (or refute them, so I can see that I have not understood)

int pin = 13
**Initial Pin (being used) will be 13

void setup()
{
}
**These items will be set once, changes made by the following Void Loop once the program is running to the things listed between the { and } will simply be overridden and not refreshed on the next 'cycle' of the program/arduino (barring a 'reset' button press)

void loop()
{
}
**There may be more than one but Void Loop will follow Void Setup, Anything in here will operate repeatedly but with respect to the parameters set in the immediate proceeding Void Setup.

I want to say something like
int Led1 = 3
int led2 = 5

//now the second led has reached maximum brightness and is begining to dimm, the first led (led1) will have reached 0 brightness: led1 is off and will be reassigned physically just in front of led2 by addressing the led on pin 6 and causing it to perform the entire operation of led1 from pin 3 but using the new led on pin 6 that 'led1' is now assigned to.
if led2 (brightness == 255) {
led1 = 6

By repeating this function and by operationg 2 leds at once and by starting one at maximum brightness and one at minimum I can run this process for ever while producing the visual result I want (ending code for led1 on pin 6 to default back to original poistion; pins 3 and 5 will shift their operational behavior to pins 6 and 9, pins 6 and 9 will shift their behavior back to pins 3 and 5 as above (the opposit pin shifting when reaching brightness = 255, or perhaps pins switching themselves when they reach brightness z, then start them all at brightness 5)
Do I need to reassign all the behavior for the pins when the pin changes (pin is analogwrite, high) (int led brightness = initial led brightness is = 5 or is = 0) (fade ammount = 5) (if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount ;
and so on?

Oh hey, I only realize after a couple of hours that you are "that guy" that wrote "that stuff" you linked :slight_smile:
Great information, incredibly useful

I don't understand why you want to change the pin numbers - but it is perfectly possible. It does mean that the LED on the original pin will be left uncontrolled (either ON or OFF).

I think a more usual treatment would be to put the pin numbers in an array and iterate over the array. Something like

byte arrayPins[4] = {3,4,5,6};

The you can operate on pin 4 with code like this (note that the first element is numbered 0)

analogWrite(arrayPins[1], 135);

And you could work through all the pins like this

for (byte p = 0; p < 4; p++) {
   analogWrite(arrayPins[p], 135);
}

You could also have another array to hold the indiviual brightness for each LED - something like

for (byte p = 0; p < 4; p++) {
   analogWrite(arrayPins[p], ledBright[p]);
}

Of course I may have misunderstood the question :slight_smile:

...R

nono you did not misunderstand :slight_smile:

"I don't understand why you want to change the pin numbers"

Sheer ignorance my friend, I think the array is the way to go. This 'array' approach is EXACTLY what I needed and I will be using it a LOT for many things.
array for brightness and another for addressing leds.

This helps a lot, I'm using the terminology page pretty heavily right now ("int" "byte" "void", the basics).

I'm going to keep working on this and pipe back with more questions once I understand this last bit enough to ask another useful question

loop() is not a "void". It is a function. This is important to understand because the fundamental method of organizing a C program is the function.

Functions isolate and contain low level details so that your higher-level functions don't need to worry about what goes on 'under the hood.' For example, the analogWrite() function is really quite complex but your average Arduino program doesn't need to know that. You just call the function and it does what you expect. For this reason, functions need to have descriptive names. The function name should describe (or at least remind you) what the function actually does. If you write a function called flashLED() then it makes the programming very confusing if you later modify that function to turn a relay on and off.

The void keyword is sort of a historical relic. Other languages have both procedures and functions. Functions were supposed to be used like mathematical functions y=f(x) and so on. A function must 'return' a value. That is, it must have a single numerical 'answer' as the result of its processing. A procedure on the other hand does something. It turns on an LED, updates some array variables or whatever. A procedure doesn't need to return anything because there is no result required for those actions. So when you write a function in C, there is a special way of saying "this function doesn't return anything" which means you give it the return type of void. You also see functions that really should be void but the programmer has decided to use the return value as some kind of indicator or error message. The print() function returns the number of characters printed, even though nobody ever uses that information.

But the Arduino is programmed in C++, which adds another unit of organization, the object (also called a class, which is another historical relic.) The details of objects need a separate post but you can think of it as a way to organize a group of related functions together. The Serial object is a good example.

byte arrayPins[3] = {3,5,6};

byte p = 0; p < 3; p++; {
analogWrite(arrayPins[p], 135);
}

p=0
This states that beginning with led p0 (led on pin 3)?
p<3
This states that the array numbers are less than the number 3 (0, 1 and 2)?
p++
I do not know, this causes the value of P to increase (select the next led) once certain criteria are met?

In using this portion of the code I am unable to achieve any result other than led p1 lighting up. I can define led p0 p1 or p2 directly and have success this way
such as in:
analogWrite(arrayPins[0], 10)
in order to dimly light the first led (on pin3)

byte arrayPins[3] = {3,5,6};
int brightness = 5;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  // declare pins 3, 5 and 6 to be an output array:
  pinMode(arrayPins[1-3], OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
// individually select and set the brightness of any of the 3 pins in the array, p=-1 p=0 and p=1)
byte p = 0; p < 3; p++; 
   analogWrite(arrayPins[p], brightness);


  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness == 255) 
    fadeAmount = -fadeAmount ;

  // wait for 30 milliseconds to see the dimming effect
  delay(30);
  • This allows me to select a single led and fade it's brightness from dim to bright.
    What happens is that the brightness cycles from 5, up to 255 (or whatever number I defined, I have tried 25), then back down to off. The led then turns on all the way (even no matter what settings I used previously) and fades down to off at the proper rate, repeating this last step.

  • What I want to happen is that the led cycles from off to full brightness

  • at full brightness the next led begins to turn on, the third led still remaining off

  • as the first led finally ends its fade (dimming back to off and remaining off); -the second led is now at maximum brightness at this same moment; -also at this moment the third led begins turn on.

I add these switches to the end of each led being cycled:
a.) When reaching maximum brightness 255, initiate the fade cycle on the next led (led 3 triggering 5, led 5 triggering 6 and led 6 triggering 3)
b.) stay off at dimmed back down to 0, perhaps by starting at brightness 1 or 5)

If anyone can suggest proper structure to proceed from here to achieve these effects I would appreciate that

Get rid of the delay. Open the example Blink_Without_Delay from your Examples menu. Study it. Add a second or third LED to the code. Change it from blinking to adjusting brightness.

Then all you have to do is work out how to code it for the pattern you want.

Much appreciated! I will study that after my exam tomorrow and try to get that down. I've been really trying to figure a way out but this sounds promising.

HarmlessJohnny5:

byte p = 0; p < 3; p++; 

analogWrite(arrayPins[p], brightness);

For some reason you left off part of the code that Robin2 shared, the for. The above code should be changed to:

for (byte p = 0; p < 3; p++) {
  analogWrite(arrayPins[p], brightness);
}

For an explanation of the for statement see http://www.arduino.cc/en/Reference/For

you can also do it like this.

its just a snippet and not all the code is included.
just to give a idea about the possebilties
and this code work with as many output as you like. or at least at a moment the Uno doesnt like it anymore.

void OutputValue::GoTo(uint8_t Channel, uint16_t FadeTime, int8_t Value) {
  if (Value != _OV_NewValue[Channel]) {
    _OV_PrevMicros[Channel] = _OV_Micros; // Set Micros
    _OV_PrevValue[Channel] = _OV_NewValue[Channel]; // Put newvalue into old value
    _OV_NewValue[Channel] = Value; // Get new value
    if(FadeTime != 0){ // IF fadetime != 0 run next code
    _OV_Arv[Channel] = ((uint32_t)FadeTime * 1000) / abs(_OV_NewValue[Channel] - _OV_PrevValue[Channel]);
    //Arv = fadetime * 1000 / abs (Newvalue - old value)
    //SO:
    //Newvalue = 0, Old value = 255, fadetime = 1000 or 1 sec
    //0 - 255 = -255 Abs makes it Positive so 255
    //1000 * 1000 / 255 = 3921 Because i use millis 1000000 = 1 Sec now i can use 2 byte value instead of 4 bytes.
    // 3921 will be needed for the next function.
    } else {
      _OV_Arv[Channel] = 0;
    }
  }
}

void OutputValue::Refresh() {
  _OV_Micros = micros();
  for (uint16_t Channel = 0; Channel < NumberOfOutputs; Channel++) { // go thru all the outputs.
    if (_OV_Arv[Channel] == 0) { // when Arv == 0 go to next value, NO fade!
      _OV_Output[Channel] = _OV_NewValue[Channel]; // go to next value no fade.
    } else {
      if (_OV_NewValue[Channel] > _OV_Output[Channel]) { // Yeah value is bigger lets Increase the output
        _OV_Output[Channel] = _OV_PrevValue[Channel] + (_OV_Micros - _OV_PrevMicros[Channel]) / _OV_Arv[Channel];
        // 255 + 500000 (0.5sec) - 0 / 3921 = 127.58 output
        // As you see after 0.5 sec the output value = halve way
      } else if (_OV_NewValue[Channel] < _OV_Output[Channel]) {//Yeah value is Smaller lets Decrease the output
        _OV_Output[Channel] = _OV_PrevValue[Channel] - (_OV_Micros - _OV_PrevMicros[Channel]) / _OV_Arv[Channel];
        // Same only then to decrease value.
      }
    }
    _OV_Output[Channel] = constrain(_OV_Output[Channel], 0, 255);
  }
}

been a while since I've posted here, school gets on top of me sometimes and I drop everything else in the sacred quest for grades and understanding :slight_smile:

I've been reviewing this code snippet and looking up the terms to figure out exactly what/how this code is/works. I do appreciate the code, haven't dropped the project and will of course put a little video of the really crude demonstration when it's one day finished (with more questions and explanations to boot : )

thanks a bunch for the help guys

yup, still school and stuff. I appreciate everyone's help a whole lot and am chomping at the bit to get back to this project and take advantage of the last few posts of information :slight_smile: