Skip to content

Instantly share code, notes, and snippets.

@juanmf
Last active October 21, 2023 01:07
Show Gist options
  • Save juanmf/d756e2fbe794934287717b0444440692 to your computer and use it in GitHub Desktop.
Save juanmf/d756e2fbe794934287717b0444440692 to your computer and use it in GitHub Desktop.
Writes a CSV waveform.csv to local dir meant to import in a function generator. Merging specified frequencies. See https://gist.github.com/juanmf/2fd9ae5a6f7a6bfe851c6c699b98e8d1 for output sample. use Junctek windows app to upload to device http://www.junteks.com/newsinfo/835494.html
##
# 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")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment