10 Simultaneous PWM Signals in Offset

I am currently having trouble figuring out how to run 10 leds simultaneously in 1/10 timing offset of each other using this individual sine function code base:

int Pin = 3;

void setup() { Serial.begin(9600); pinMode(Pin, INPUT); }

void loop() { float something = millis()/1000.0; int value = 128.0 + 128 * sin( something * 2.0 * PI ); analogWrite(Pin,value); }

  • so as to generate a linear propagating/graduating sinusoidal wave flash with the 10 leds. First, I thought of using a specified delay with each led. The first led would have a delay of zero while each of the following 9 pins would be assigned a delay of 100 + n. Pin() = Delay(t) 1 = 0 2 = 100 3 = 200 4 = 300 5 = 400 6 = 500 7 = 600 8 = 700 9 = 800 10 = 900

Of course, I learned that the delay command does not facilitate this setup as only one delay can be used at at time with nothing else running. Currently, I am toggling the Timer1 library with no success. May someone please assist me from here?

You don't really give any code here to modify or the type of board you are using, but in your callback, you can setup a counter. Based on that counter, you would set the appropriate value to each pin using analogWrite() assuming you have that many pins that do PWM. If you don't, you would have to do the PWM code for those that don't support PWM yourself.

Good luck!

Adrian

I am what you would call a newbie. Could you write up how this analogWrite() callback is supposed to be setup?

The board I am using is a 2560 Mega. As for the code, each 10 PWM pins run on the same individual code shown above.

QAMember: I am what you would call a newbie.

So could you read the how to use this forum sticky post at the start of the section.

Also what are you actually trying to do. The phrase:-

to generate a linear propagating/graduating sinusoidal wave flash with the 10 leds.

Means very little to me. That code is only using one LED.

If you think of the relationships between the LEDs as a phase angle then you can simply add a fixed offset to the sin wave calculation for each LED.

I'd suggest setting up an array of pin numbers, and writing a loop to adjust the brightness of each LED. Use the approach demonstrated in 'blink without delay' to execute that loop at regular intervals.

That base code represents the function for each pwm pin 3 through 13. There will be 10 of these function segments. Each "led" lights up and fades out in a sinusoidal fashion. All 10 pins must operate these functions simultaneously but in an offset 1/10 of each other. Thus, if the PWM function period, or trigonometric sine period is 1000 millis, then each successive pin after 3 should add a delay of 100 milliseconds. Get it?

Thank you, very much, PeterH. I will see what I can do. Any code structure examples of how to set this up would be highly gratified. Thanks, everyone.

Specifically, how do I go about setting the initial function brightness in terms of phase degrees?

Your phase increment is simply 2 Pi / 10 For each LED you add n times this to the sin function where n is the LED number.

I see now what you want but are you aware that it might not look like you think it might due to the fact that the eye has a non linear responce to brightness. So when the PWM has a high value small or even medium changes are not seen very much. I imagin this will not so much look like a fade but a rapid on and off. Still you can see when you implement it. Don't forget the resistors on the LEDs.

Well, since you have so many outputs with PWM, you don't need a callback, unless this is supposed to work while you are doing something else.

You have the basic idea as to how to create the appropriate intensity for a point on the wave form, so put that into a function that takes an time offset as your parameter and an LED to set. From there you just call it 10 times with the appropriate offset and LED.

Here's a function you could use in case you are not familiar with programming in C/C++, this is assuming that your original code worked.

void sinLED(int Pin, int time, float offset)
{
  float something = time/1000.0;
  int value = 128.0 + 128 * sin( something * 2.0 * PI  + offset);
  analogWrite(Pin,value);
}

You can then use a for loop to iterate over all of the pins you want.

There are several optimizations that can be done, such as creating an array preprogrammed with the intensity values so that they don't have to be recalculated all the time, but that is an exercise left up the the reader.

Good luck,

Adrian