Help with sine wave on Arduino and LED ring

Hello everyone,

I made a program (Arduino IDE) in February of this year (2024) to generate a light sinusoid as perfectly as possible. I used an Arduino UNO and a ring of 35 neopixel LEDs. The program is attached.

//LIGHT SIN by Caprario 

#include <Adafruit_NeoPixel.h>  //biblioteca do anel
#include <Math.h>

#define NUMLED 35                                                               //número de leds do anel
#define PIN 10                                                                  // pino controle do anel
#define LED 8                                                                   // pino controle led de referência
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMLED, PIN, NEO_GRB + NEO_KHZ800); // seta o anel

#define brilhopad 50 //brilho direto
byte brilhot[510];
byte bmax = 255;
byte bmin = 20;
byte delta = (bmax - bmin);
int id = int(delta) * 2;
//double periodo[] = { 8000, 4000, 3000, 2000, 1000, 750, 500 };
double periodo[] = { 4000 };  // digitar apenas o cliclo a ser ensaiado
float intervalo;
float a;
int NCICLOS = 10;
byte corR, corG, corB;

void setup() {
  Serial.begin(9600);
  pinMode(LED, OUTPUT);  // led de referência
  strip.begin();
  clearring();
}

void loop() {
  float tempo = 0;
  int lote = sizeof(periodo) / sizeof(double);  // tamanho da matriz de períodos
  // Seleção das cores
  corR = brilhopad;
  corG = brilhopad;
  corB = brilhopad;

  for (int k = 0; k < (lote); k++) {
    Serial.println("clique enter para começar");
    while (!Serial.available()) {
      // Aguarde até que haja dados disponíveis no buffer serial
    }
    // Limpe o buffer serial
    while (Serial.available()) {
      Serial.read();
    }
    Serial.print("****************   VAI COMEÇAR   ****************    ");
    Serial.println(periodo[k]);
    delay(2000);  // corrida para preparar o ensaio, ligar a camêra etc.



    intervalo = periodo[k] / (2 * float(delta));  // em milisegundos
    for (int i = 0; i < id; i++) {
      a = float(delta / 2);
      a = a * (sin((2 * PI * intervalo * float(i) / periodo[k]) + 1.5 * PI) + 1);
      a = a + bmin;
      brilhot[i] = byte(a);
    }
    intervalo = intervalo * 1000;  // em microsegundos
    clearring();
    delay(500);

    analogWrite(LED, 220);
    delay(15);  // tempo de led acesso infravermelho
    analogWrite(LED, 0);

    tempo = micros();

    for (int l = 0; l < NCICLOS; l++) {
      for (int j = 0; j < id; j++) {  // calculo do brilho para cada intervalo
        tempo = tempo + intervalo;
        while (micros() < tempo) {
          strip.setBrightness(brilhot[j]);
          for (int i = 0; i < NUMLED; i++) {
            strip.setPixelColor(i, strip.Color(corR, corG, corB));
          }
          strip.show();  // mostra o anel conforme programado
        }
      }
    }
    clearring();  //apaga o anel
  }
  //}
  Serial.println("c'est fini ");
  delay(100);
}

void clearring() {  //esta opção apaga o anel
  for (int i = 0; i < NUMLED; i++) {
    strip.setPixelColor(i, strip.Color(0, 0, 0));
  }
  strip.show();
}

I checked the result by making a video where the ring illuminates a white plane. Processing the image in Python OpenCV, the result is a beautiful sinusoid, almost perfect and with all cycles the same (Image 1).

However, I used the same program on the Arduino IDE at the end of April, and the sinusoid was distorted (Image 2). An intensity peak appears in the first cycle, in addition to noise at the peak of the other cycles.

I have already tried changing the ring, the Arduino board, the cables, with and without a power supply, old versions of the program (which also worked), old versions of the Neopixel library, control pins (10,8,3), other computers and operating systems, I analyzed the images with other programs (Matlab), but the result remains the same, a distorted sinusoid with an intensity peak in the first cycle.

I still have not managed to solve this mystery. Can anyone help me?

Any suggestions will be appreciated :blush:.

Thank you very much.

Could it be Math.h (big M) has changed? I recognize "math.h" (small m) is a c-library.

Arduino double is the same as Arduino float, 32 bits.

For much faster processing, store a lookup table of sine * 10000 as integer per angle (pi/6 would be 5000) in flash (using PROGMEM) since there is 32K total flash on an Uno and your code might not use 8K.

Consider that it takes less than half a usec to fetch a 16 bit value, you can interpolate 3 places (with ints, with longs 6 at least) way faster than using floats and sin(). IMO for graphing that is plenty close!

Thank you for your suggestion, but unfortunately, it didn't make any difference to the result. Even the "math.h" library does not need to be called for the code to run, but I left it because it was in the code when it worked.

Thank you very much for the suggestion. The problem is not the processing speed. The code, as presented, was working in February. But in April, it began to generate this greater intensity in the first cycle, affecting all peaks in subsequent cycles. In the meantime, the only things that changed were the updates to the Arduino IDE and the Neopixel library (adafruit). But even after uninstalling everything and returning to the previous versions of the problem, the problem continues! :cry:

... and position of the sun at the time of measurement. Are you measuring in a light-tight box?

Sorry, I forgot to mention it in the text. The recording was carried out in an environment with controlled lighting, without external influence. The only lighting in the environment is the recording camera display, configured with the lowest brightness allowed and positioned in the opposite direction of the generated signal.

Outside chance (but real): Is the facility in which you are running the system the same in "good" and "bad"? The reason I ask is some facilities condition their commercial power, where normal commercial power is not. The "filtered" power is actually worse than commercial (noisy ground) and can have an effect on the devices.

The system installation is the same in both tests. The Arduino was powered by the CPU connected to the home network. We thought about this possibility of variation in the electrical network, so we tested the Arduino's power supply connected directly to the electrical network and from the laptop's battery (without a direct electricity connection). But all the options tested in this second moment presented the same problem of peak intensity and noise.

  1. Verify your power supply has a good connection (soldered).
  2. Verify the capacitor across the power supply is good (get a new one)
  3. Verify the resistor from the signal pin to DIN is good (get a new one)
  4. Try a new pixel ring.

I have read users say pixels diminish in brightness and color over time of use.

  • We have already tested the connection to the power supply. We used a multimeter to check all connections and solders. We tested three different power supply and connection cables to eliminate this uncertainty.

  • We tested three different Arduino UNO boards and an ESP Room 32 (one of the Arduino boards and the ESP board were new).

  • The pixel ring is connected directly to the Arduino. However, we also connected the pixel ring to a protoboard using a new resistor to eliminate the doubt (checking the connections with the multimeter).

  • We tested four new pixel rings with varying numbers of LEDs.

And the problem persists! :cry:

A fresh proto board will work, but over time galvanic corrosion will occur... you are using dissimilar metals, the protoboard might have brass-coated steel... Solder connections for power and signal.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.