Generating 2.5Khz Square Signal using Arduino

Hi Guys,

I have a trouble with generating signal from Arduino Uno using digitalWrite() and timer using millis(). [ I tried did it using delay() method but there was same result].

First of all, My task is to generate identical signal as on the screen below :

So I made measurements on the oscilloscope and I split the signal into logical 0 and 1.
Then using extra tools I got finally that one logic signal lasts 0.4 ms.

I had all I need so lets begin coding.

This is my code, It waits 5 seconds then generates my signal, but to interval = 1 everything was fine, then the signal frequency is constant despite the interval changes. My code below :

Paweł Bocian <boocianpawel@gmail.com>
00:23 (0 minut temu)
do mnie

const int signalPin =  13;      // the number of the Signal pin output
const int onSignal[180] = {0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1};

// Variables will change:
int outputState = HIGH;         // outputState used to set the signal
long previousMillis = 0;          // will store last time signal was updated
int countDown =0;                // temporary variable
int iterator =0;                     // Iterator thought signal

//Time variabl3
long interval = 8.9;
long begintime = 0;
long firstSignalTime =0;
long lastSignalTime =0;

void setup() {
  // put your setup code here, to run once:
  pinMode(signalPin, OUTPUT);
  Serial.begin(115200);
 
}

void loop() {
  // put your main code here, to run repeatedly:
  if(countDown == 5){
      firstSignalTime = millis();
    while(iterator < 180){
      unsigned long currentMillis = millis();
     
      if(currentMillis - previousMillis > interval) {
        // save the last time you change signal
        previousMillis = currentMillis;  
     
        // if the signal is 0 generate LOW signal and vice-versa.
        if (onSignal[iterator] == 0)
          outputState = LOW;
        else
          outputState = HIGH;
     
        // set the signal with the sigalState of the variable:
        digitalWrite(signalPin, outputState);
        Serial.println(iterator);
        iterator++;
        countDown++;
      }
    }
      lastSignalTime = millis();
  }else {
    Serial.print("Jeszcze nie : ");
    Serial.println(countDown);
    Serial.print("FirstSignal at : ");
    Serial.println(firstSignalTime);
    Serial.print("LastSignal at : ");
    Serial.println(lastSignalTime);
    delay(1000);
    countDown++;

  }
}

There is some extra variables to measure if my "delay" works.

My question is how to generate signal like from the picture ? I have also ESP8266 nodeMcu v3 but its quite similar device.

Extra pic : differences-in-signal-period hosted at ImgBB — ImgBB
White signal - original signal from IR diode,
Yellow signal - my signal generated

signal.png

long interval = 8.9;

This is wrong. interval is in milliseconds, and it can only be a whole integer value.
interval and all the other time variables should be unsigned long to match millis().

So I made measurements on the oscilloscope and I split the signal into logical 0 and 1.
Then using extra tools I got finally that one logic signal lasts 0.4 ms.

How did you get from 2.5 KHz and the .4 ms period to an 8ms interval between signals.

It waits 5 seconds then generates my signal, but to interval = 1 everything was fine, then the signal frequency is constant despite the interval changes.

Where in your code does the interval change?

Consider using tone().

I have used the Timer1 library to generate a square wave. Just set the duty cycle to 50% (512). Also you can use the same library to attach an interrupt with a timer value of period/2 and just complement the output in the interrupt routine.