## # Writes a CSV waveform.csv to local dir meant to import in a function generator. # The wave is meant to be input in a highside bridge switching a coil to create a BEMF # on every LOW (0). # It merges several frequencies together by adding a LOW (trigger BEMF impulse) at the start of every # cycle of included frequencies. Very much like swing seats you push only at the beggining of each cycle, # each with a different period. # Selected Frequencies are in line with the equation (Planck * ϕ ^ N) ## ## # Ok after a lot of search found the JDS8000 CSV format, has 8192 points, one column. # Junctek csv # 0 # 0.0035 # ... ## import csv import numpy # Frequencies, All corresponding to wave lengths that are GoldenRatio exponents of plank # (p * ϕ^n) n=[199, 200, 202, 203, 205, 208], closely matching Schumann Harmonics and brain waves. # # 47.8377133094 Hz 2.09E-02 0.0209040092 # 29.5653327693 Hz 3.38E-02 0.0338233974 # 11.2929522292 Hz 8.86E-02 0.0885508041 # 6.9794283109 Hz 1.43E-01 0.1432782107 # 2.6659043927 Hz 3.75E-01 0.3751072254 # 0.6293346582 mHz 1.59E+00 1.5889797057 # # Frequencies in Hz # All Negentropic frequencies above Schumann/Brain Freqs, up to max 10,000 Hz found in Rife lists. # Leaving a safe gap from brain waves bellow # f13 = 9519.9453330204 # makes file too heavy. # f12 = 5883.6497868471 # makes file too heavy. f11 = 3636.2955461724 f10 = 2247.3542406742 f9 = 1388.9413054978 # (close match) by Dan's Equation. f8 = 858.4129351762 # Rife: 852Hz (rise awareness) f7 = 530.5283703214 # Rife 528Hz (love/healing) # Aligned with brain and Schumann f6 = 47.8377133094 f5 = 29.5653327693 f4 = 11.2929522292 f3 = 6.9794283109 f2 = 2.6659043927 f1 = 0.6293346582 # useless. longer than allowed data-points can cover. # Leaving out higher frequencies =, at decent sample rates it renders most 0s. frequencies = [f2, f3, f4, f5, f6, f7] #f1, f8, f9, f10, f11] # Periods in Seconds p6 = 0.0209040092 p5 = 0.0338233974 p4 = 0.0885508041 p3 = 0.1432782107 p2 = 0.3751072254 p1 = 1.5889797057 longestPeriod = p2 # Where every Brain/Schumann frequency meet again after zero. For a clean Fundamental cycle. # Seconds # FundamentalPeriod = 206.3491206 # Supposedly ideal to restart cycles from Zero. by file too large # Sample rate optimized to fit My coil charging time to one datapoint duration. # That way, the opening of the MOSFET switch happens right after coild is full, and no current # is wated to GND. sampling_rate = 8192 / (2 * longestPeriod) # in Hz ~2x max freq used # (8192 = sampling_rate * FundamentalPeriod) To match one cycle to Junctek's 8192 data-points window FundamentalPeriod = 2 * longestPeriod num_points = int(FundamentalPeriod * sampling_rate) # Generate time values time_values = [i / sampling_rate for i in range(num_points)] waveform = [] lastImpulseTime = -1 # Returns 1 unless a frequency completed a cycle in currentTime, where it returns a negative value # representing the index in the frequencies list, # meaning an Impulse should be produced. # All Frequencies "Complete a cycle" on time zero. # spacing ensures the given amount of time is preserved between impulses regardless of frequencies. def getLevel(currentTime: float, previousTime: float, spacing: float) -> float: global lastImpulseTime if (currentTime - lastImpulseTime) < spacing: # Avoid impulses, Coil re-charging. return 0.1 for i in range(len(frequencies)): f = frequencies[i] period = 1.0 / f currentMod = currentTime % period previousMod = previousTime % period if currentMod <= previousMod: # A cycle completed send them impulses! level = - (i / (len(frequencies) - 1)) lastImpulseTime = currentTime return level # No one completed a cycle. return 0.1 # Wave form is pulse: HIGH unless any used freq is starting a cycle. # This is intended to create an impulse at the start of every cycle. # Impulse frequency is 1MHz. so need to wait min 10X to charge coil. # That is guarantee min UP time of 10uS (microSeconds) between LOWs. def makeWave(): global waveform, num_points # return to one right after an impulse adds extra elements on both time_values & waveform # which can have JDS8000 confused when no constant increments in time interval. # safe side is to ensure spacing > timeIncrements spacing = 1 / (sampling_rate - 1) # waveform admits 0 or 1 values. waveform = numpy.empty(num_points, float) for i in range(num_points): level = getLevel(time_values[i], 0 if i == 0 else time_values[i - 1], spacing) waveform[i] = level if level < 0.1 and i > 0: # charcge the coil in previous datapoint, note coil resonance Freq must be # >= 10x sample_rate to allow time for charging. waveform[i - 1] = 1 #if level == 0 and spacing < timeIncrements: # return to one right after. Adds extra elements on both time_values & waveform # or maybe not, as JDS8000 might get confused when no constant increments in time interval. #safe side is to ensure spacing > timeIncrements makeWave() print(f"waveform length {len(waveform)}") print(f"time_values length {len(time_values)}") maxValues = 8192 # maxValues = num_points # Header: # Junctek csv with open('waveform.csv', mode='w', newline='', encoding='us-ascii') as file: writer = csv.writer(file, delimiter=';') writer.writerow(['Junctek_csv']) for i in range(maxValues): # writer.writerow([waveform[i]]) writer.writerow([f"{waveform[i]:.4f}"]) print(f"waveform duration: {time_values[maxValues - 1]} Seconds") print(f"waveform 'freq' for fn generator config: {1 / time_values[maxValues - 1]} Hz")