Generate two square waveforms simultaneously with different frequency

Hi,
I want to generate the two square waveforms with two different frequency
Both should run simultaneously, so that I can compare the states of two at that instant.

Issue -

  1. Because of sequential flow loop, I'm able to write pin HIGH and LOW ( for f1 - 100hz and f2 - 200 Hz ).
  2. Two functions I have written, sequential execution results into state of both signal as LOW.

How I can solve this issue.
Both wave should run independent of each other.

This is for testing purpose So generating two waves internally .

Hello
Specify the timing constrains more in detail.

Has the use of one or 2 of a MCU timers been considered?

An ESP32 has 4 timers that produce square waves without CPU intervention and sends those square waves to GPIO pins. Perhaps the MCU being used has timers as well?

General Purpose Timer (GPTimer) - ESP32 - — ESP-IDF Programming Guide latest documentation (espressif.com)

High Resolution Timer - ESP32 - — ESP-IDF Programming Guide latest documentation (espressif.com)

Please post your best attempt at a sketch to do what you want

here's a purely software approach (msec can be replaced with usec, millis() with micros())


struct Wave {
    const byte          pin;
    const unsigned long period;
    unsigned long       msec;
    unsigned long       msecLst;
};

Wave waves [] = {
    { 10, 200 },
    { 11, 300 },
    { 12, 450 },
};
#define N_Wave      (sizeof(waves)/sizeof(Wave))

// -----------------------------------------------------------------------------
void
loop (void)
{
    unsigned long msec = millis ();

    Wave *w = & waves [0];
    for (unsigned n = 0; n < N_Wave; n++, w++)  {
        if ( (msec - w->msecLst) >= w->period)  {
            w->msecLst = msec;
            digitalWrite (w->pin, ! digitalRead (w->pin));
        }
    }
}

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin (9600);

    for (unsigned n = 0; n < N_Wave; n++)
        pinMode (waves [n].pin, OUTPUT);
}

Then output them to two different pins and mix the signals together with a couple of resistors.

What is the point of trying to compare these two signals because after all you are generating them so you know at any instance what they are?

What are you really trying to do?

const byte OutputPin1 = 4;
const byte OutputPin2 = 5;
const byte DifferencePin = 6;

// Microseconds per half cycle:
unsigned long T1 = 1000000 / (2 * 100); // 100 Hz
unsigned long T2 = 1000000 / (2 * 200); // 200 Hz


void setup()
{
  Serial.begin(115200);
  delay(200);  // Give time for Serial Monitor to connect

  pinMode(OutputPin1, OUTPUT);
  pinMode(OutputPin2, OUTPUT);
  pinMode(DifferencePin, OUTPUT);
}

void loop()
{
  unsigned long currentMicros = micros();
  
  static unsigned long Time1 = 0;
  static unsigned long Time2 = 0;

  static int oldState1 = LOW;
  static int oldState2 = LOW;

  if (currentMicros - Time1 >= T1)
  {
    Time1 += T1;
    oldState1 = !oldState1;
    digitalWrite(OutputPin1, oldState1);
  }

  if (currentMicros - Time2 >= T2)
  {
    Time2 += T2;
    oldState2 = !oldState2;
    digitalWrite(OutputPin2, oldState2);
  }

  digitalWrite(DifferencePin, oldState1 != oldState2);
}

Since one is half the frequency of the other they don't have to be completely independent. :wink:

Thanks I tried this ...
This is working fine but facing the issue with generating asynchronous square waves with differnet frequencies

Can't do any hardware changes .
Also I want to generate two asynchronous square wave with different frequencies.

This I need to try

How, incidentally, are you able to verify the results? Have you got an oscilloscope or logic analyser?
Does this exercise also involve changing the dutyCycle and phase of the square wave signals as well as its frequency?

Hello
Try this small example and check the timing requierements.

constexpr int outPutPin1 {9};
constexpr int outPutPin2 {10};
constexpr unsigned long UpdateRate {1000};

void setup() {
  pinMode(outPutPin1, OUTPUT);
  pinMode(outPutPin2, OUTPUT);
}

void loop() {
  delay(UpdateRate);
  static int counter;
  digitalWrite(outPutPin1, counter & 1);
  digitalWrite(outPutPin2, counter & 2);
  counter++;
}

Have a nice day and enjoy coding in C++.

You havent told us ANYTHING about the hardware you propose to use. Or is this just a "programming exercise"?

Nor the characteristics of the "square waves" - are they just arduino digital outputs?

If you dont give us the information we will likely give you suggestions that dont meet your needs.

If they are to be COMPLETELY independent have you considered using TWO Arduinos?

  1. Its for PLL kind of logic for my application
  2. Hardware is STM32 with Arduino wrapper ( mentioned above)

Square waves Requirements -

  1. Two square waves - Diff freq and phase ( asynchronous)
  2. They should run simulatanosuely but independantly
  3. Results I want to verify for now on continues basis
  4. FOr testing purpose , we can consider the digital outputs of arduino to generate square waves

Start simple

int periods[] = {1000, 700};
unsigned long startTimes[2];
const byte outputPins[] = {3, 5};

void setup()
{
  Serial.begin(115200);
  pinMode(outputPins[0], OUTPUT);
  pinMode(outputPins[1], OUTPUT);
}

void loop()
{
  unsigned long currentTime = millis();
  for (int x = 0; x < 2; x++)
  {
    if (currentTime - startTimes[x] > periods[x])
    {
      digitalWrite(outputPins[x], !digitalRead(outputPins[x]));
      startTimes[x] = currentTime;
    }
  }
  if (digitalRead(outputPins[0]) == HIGH && digitalRead(outputPins[1]) == HIGH)
  {
    Serial.println("both HIGH");
  }
}

If you want frequencies other than the 100 Hz and 200 Hz that you provided as an example, just put them in here:

// Microseconds per half cycle:
unsigned long T1 = 1000000 / (2 * 100); // 100 Hz
unsigned long T2 = 1000000 / (2 * 200); // 200 Hz

Re-calculate T1 and/or T2 whenever you want to change frequency.

Hi @johnwasser,

what do you think about adding an "unsigned long phase" here

if (currentMicros - Time2 >= T2 + phase)

or this way

if (currentMicros - Time2 + phase >= T2)

in your code from post 7? That should shift the phase left or right ...

???!?
Since the two DIFFERENT frequencies are not synchronized, the phase is shifting all the time. Adding a value to T1 or T2 will lower the frequency, not change the phase difference .

This would not change my advice in post #6
Also this suggests to me this is a class assignment and you want us to do it for you.

On the same pin or different pins?

Ok a step closer but still rubbish in describing what you want to do. Is it a big secrete?

Absolutely no idea what that means.

A PLL implies you have a fixed frequency output and you are trying to synchronise a free running voltage controlled oscillator to that or to a sub multiple of that. So I don't see where two oscillators in the Arduino come into that, unless you want to make one of them a voltage controlled oscillator. Something you have not mentioned before.

The good people who are supplying you with code are only guessing at what you want based on what you say. But what you say is not making any sense because you are NOT telling us what the hell you want to do.

Maybe this is an [url= http://xyproblem.info/]X-Y Problem[/url]

2 Likes