Generating random square wave that last for certain time

Question:

I am trying to generate a random square wave signal in Python that lasts for a certain amount of time. Specifically,each square wave should have a fixed duration of 5 minutes and a random amplitude that is bounded between 0 and 1. The square wave should remain at each amplitude level for the full 5 minutes and then transition to a new amplitude level.

I’ve tried adapting existing code, but so far, I haven’t been able to generate the square waves as described. I’m using NumPy and Matplotlib for the simulation and visualization.

import numpy as np
import matplotlib.pyplot as plt

# Define the bounds of the random vectors
min_value = 0.0
max_value = 1.0

# Define the duration of each square value in seconds
square_duration = 5 * 60  # 5 minutes

# Define the total number of samples in the simulation
max_sim = 1 * 60 * 60  # 24 hours * 60 minutes/hour * 60 seconds/minute

# Initialize the load and renewable profiles vectors
pl = np.zeros(max_sim)

# Generate the random bounded vectors
for i in range(max_sim):
    if i % (square_duration + 1) == 0:  # Start a new square value
        square_value = np.random.uniform(min_value, max_value)
        square_counter = 0
        square_change = np.random.randint(1, square_duration + 1)
    if square_counter < square_change:  # Use the same square value
        pl[i] = square_value
        square_counter += 1
    else:  # Start a new square value
        square_value = np.random.uniform(min_value, max_value)
        pl[i] = square_value
        square_counter = 0
        square_change = np.random.randint(1, square_duration + 1)

    # Add sinusoidal variation to the load profile
    pl[i] += np.sin(i / max_sim * 2 * np.pi) * 0.15 * 1

    # Clip the values to the defined bounds
    pl[i] = np.clip(pl[i], min_value, max_value)
   

plt.show()

Can anyone suggest how to modify the existing code or provide an alternative solution to generate the random square wave profiles I need?

This is the output I am having:

Randomly generated square waves

It is almost ready but I need that the duration of each square to be constant.

Asked By: K. Rincon

||

Answers:

Would something like below work for you? Although you should tweak it according to your needs. Right now I am setting the square count manually. Maybe you can calculate it from simulation duration.

import numpy as np
import matplotlib.pyplot as plt

min_value = 0.0
max_value = 1.0

square_count = 20
square_duration = 60*5

a = np.random.uniform(min_value, max_value, size=(square_count, 1))
a = np.tile(a, (1, square_duration)).flatten()
plt.plot(a)

output image:

square waves

Answered By: Metin Usta

Several suggestions

Clearer variable names

I suggest making clear what is the amplitude and what is the y value at a particular time.

You can also specify units, such as seconds which will help you.

Separate the creation of the amplitude from creation of the y value

You also will need a variable for the period of the square wave.

If you really mean the amplitude, the wave should go from +amplitude to -amplitude (not to 0)

enter image description here

Source: https://no.wikipedia.org/wiki/Amplitude

Possible solution

import numpy as np
import matplotlib.pyplot as plt

# Define the bounds of the random vectors
min_value = -1.0
max_value = 1.0

square_wave_half_period_seconds = 30
block_duration_seconds = 5 * 60  # 5 minutes
simulation_duration_seconds = 1 * 60 * 60  # 1 hour * 60 minutes/hour * 60 seconds/minute

# Initialize the load and renewable profiles vectors
ys = np.zeros(simulation_duration_seconds)

# Generate the random bounded vectors
for t_seconds in range(simulation_duration_seconds):
    if t_seconds % (block_duration_seconds) == 0:  # Start a new square value
        amplitude = np.random.uniform(min_value, max_value)

    am_in_first_half_of_square_wave = (t_seconds // square_wave_half_period_seconds) % 2 == 0
    ys[t_seconds] = amplitude * (1 if am_in_first_half_of_square_wave else -1)
    ys[t_seconds] += np.sin(t_seconds * 2 * np.pi) * 0.15 * 1

    # Clip the values to the defined bounds
    ys[t_seconds] = np.clip(ys[t_seconds], min_value, max_value)
   

plt.plot(ys)
plt.show()

enter image description here

Answered By: ProfDFrancis
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.