-1

I try to change the brightness of an LED following the formular in out1. I'm pretty sure that something is going wrong because it doesn't really change its brightness and it never stops lightening. Can pleas somebody help me. It should basically do the same than a sin wave but instead of the sin I try to use my equation!

const int LED = 11;
const int LED1 = 10;
const int LED2 = 9;

void setup()
{
}

void loop()
{
float in1, out1, out2, out3;

for (in1 = 0; in1 < 10; in1++)
{
out1 = 8.8 * pow(10,-4) * pow(in1,4) - 0.0034 * pow(in1,3) +0.37* pow(in1,2) -6.7 *in1 +1.7 *pow(10,2);
//out2 = 1.207*pow(in1,4)-0.0011*pow(in1,3)+0.16*pow(in1,2)-5.5*in1+2,0763;
//out3 = 4.829*pow(in1,4)-0.034*pow(in1,3)+0.37*pow(in1,2)-6.7*in1+2,076;

analogWrite(LED,out1);
delay(10);
//analogWrite(LED1,out2);
//analogWrite(LED2,out3);

}

analogWrite(LED,LOW);

/*analogWrite(LED,out1);
analogWrite(LED1,out2);
analogWrite(LED2,out3);
//analogWrite(LED1,LOW);*/
delay(500);
3
  • You wrote: “8.8 * pow(10,-4)”. You mean 8.8e-4. And you should implement Horner's method instead of using the (very expensive) pow() function. Commented Jul 11, 2017 at 14:01
  • Don't cross post. You already asked this on SO.
    – gre_gor
    Commented Jul 11, 2017 at 14:02
  • 1
    You wrote: “The formula [...] comes from data I've plottet in Matlab”. Why don't you tell us what you actually want to achieve? Your code is probably working just fine, and the Arduino is doing what you asked for. Only you know what you actually want it to do. Commented Jul 11, 2017 at 19:21

2 Answers 2

1

Here is the proper way to implement a polynomial function. It's a direct application of Horner's method:

// Polynomial function for output 1.
static float f1(float x)
{
    return (((8.8e-4 * x - 0.0034) * x + 0.37) * x - 6.7) * x + 1.7e2;
}

You would use it like this:

void loop()
{
    for (int x = 0; x < 10; x++) {
        analogWrite(LED, f1(x));
        delay(10);
    }
    digitalWrite(LED, LOW);
    delay(500);
}
5
  • Thank you for your help.It's hard for me to tell if it's working but the plot of the function looks like this : link I'm not quite sure but i think the brightness should not fall down at a certain point. Do you have any idea what the issue could be? I was also wondering if I could do more steps with the brightness....
    – gamma
    Commented Jul 11, 2017 at 16:15
  • 1
    The most likely issue is your poor choice of polynomial. You are varying the brightness over a tiny range: the variation will be hardly visible. Commented Jul 11, 2017 at 17:07
  • anlogWrite uses 0...255, that is only 8 bit. A led intensity with a curve into a 8 bit intensity resolution ? That is not very useful. The first 10 steps are far too coarse. The Neopixels and other RGB leds often have more bits, and those can be programmed with a nice visual brightness curve. As far as I know, all led PWM modes are linear, but the human eye is not linear. Therefor you need more bits for finer steps when the led is dim.
    – Jot
    Commented Jul 11, 2017 at 18:45
  • @Jot: The Neopixels (and the WS2811, WS2812 and SK6812) are 8-bits per channel. Commented Jul 11, 2017 at 19:18
  • @EdgarBonet, thanks, so the most common 5050 RGB leds are still 8-bits per color. That's disappointing. Even the 5050 RGBW leds are 8 bits (times four for each 'color'). Some PWM led driver chips are 12 or 16 bits. Sometimes I use two digital outputs with different resistors to get more resolution.
    – Jot
    Commented Jul 11, 2017 at 22:18
0

You should make sure that your code works with known good values for out1.

After dthat, try to make sure that your formula produce values in a valid range - check analogWrite to see what values it expects.

Then you should make sure that your code formula is what you want. Aka the code reflects your intent correctly.

edit: here is what I use to calculate polynomial functions.

//return poly functions
//x: independent variable
//degree: degree of the polynomial function
//p[]: array for the coefficients
double poly(double x, int degree, double p[]) {
  double tmp=0;  //temp variable

  while (degree--) tmp = tmp * x + p[degree];

  return tmp;
}

by providing different "degree" and "p[]/coef", you can calculate any polynomial function with one call to poly().

I generally use a set of macros to further simplify the calling to that function.

6
  • The formular is a little bit strange but it comes from Data I've plottet in Matlab and afterwards I did cirve fitting. Is there no easy way to have more steps? Maybe by doing a fourrier transformation?
    – gamma
    Commented Jul 11, 2017 at 18:16
  • Think simple. Your problem isn't the lack of complexity. So adding more complexity will not get you where you want to go. Instead, focus on the basics
    – dannyf
    Commented Jul 11, 2017 at 18:56
  • Ok first of all my possible maximum vallue is 255. So everything above will not be displayed right? I've normalized the values with Matlab so no value is above 1. Is there a way to do the same thing with ardouino? Because in this case I could Multiplay the normalized Vector by 100. I'm probably thinking to complex, you're right! So could you give me an instruction I can follow to solve this? It would really help me a lot! Thanks!
    – gamma
    Commented Jul 11, 2017 at 19:51
  • Your problem doesn't require Fourier transformation to solve. It only requires common sense and basics, as laid out to you earlier.
    – dannyf
    Commented Jul 11, 2017 at 20:52
  • In poly(), you should increment degree before the while loop, otherwise you fail to add the leading term. Alternatively, you could rename degree and document that this parameter is the length of the p array, which is not the same as the degree of the polynomial. Commented Jul 12, 2017 at 8:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.