#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 26 00:50:35 2019

@author: oyvind
"""
import math
import numpy as np
import matplotlib.pyplot as plt

# Name for the saved graph
filename = "SimuleringPy"

#RPM to simulate
RPM = 40000
#RPM to calculate tau
tauRPM = 40000

# Forward voltage of the diode
forwardVoltage = 0.7

# Threshold voltage of the transistor
thresholdVoltage = 2

# Upper voltage of the pulsetrain
upperVoltage = 5

# How many cycles you want it to run
cycles = 5
# The resolution of each cycle
resolution = 2000

# Converting from RPM to Hz and period in seconds and milliseconds
def RPMtoPeriod(rpm):
    Hz = rpm / 60.0
    period = 1 / Hz
    periodmS = period * 10**3
    return periodmS

periodmS = RPMtoPeriod(RPM)

print("Period in ms: " + str(periodmS))



# Calculates the tau based on the period, and the different voltages
def CalculateTau():
    # Calculate the roots of the tau-equation
    roots = np.roots([forwardVoltage, -upperVoltage, upperVoltage - thresholdVoltage])
    # Calculate the possible taus
    taus = -(RPMtoPeriod(tauRPM)) / (2 * np.log(roots)) 
    print(taus)
    # Discard the non-real tau
    if taus[0] > taus[1] and taus[0] > 0:
        return taus[0]
    return taus[1]
    
# Just creates a pulsetrain with some voltage and duty-cycle
def GeneratePulsetrain(voltage = 5, dutyCycle = 0.5):
    pulseTrain = []
    for i in range(cycles):
        for i in range(round(resolution * 2 * dutyCycle)):
            pulseTrain.append(voltage)
        for i in range(round(resolution * 2 * (1 - dutyCycle))):
            pulseTrain.append(0)
            
    return pulseTrain

# Generate the time-signatures from the number of cycles, the resolution and 
# the periodtime. result in milliseconds
def GenerateTime():
    times = []
    for t in range(cycles * resolution * 2):
        times.append(periodmS * t / (resolution * 2))
    return times


def OutVoltage(wave, times):
    cP = wave[0] # Start voltage-supply
    v0 = 0 # Start voltage
    cT = 0 #Start time
    volt = []
    for p in range(len(wave)):
        # If the voltage-supply changes, recalculate startvalues
        if wave[p] != cP:
            v0 = volt[-1] # New start voltage, uses the last voltage calculated
            if wave[p] == 0:
                v0 = forwardVoltage
            cP = wave[p] # Variable so the array is not accessed.
            cT = times[p] # Offset time for each period
        # Calculate the outgoing voltage over the CAPACITOR with the start values
        volt.append(cP + (v0 - cP) * math.exp(-(times[p] - cT) / tau ))
    return volt

def GenerateThreshLine(times):
    thresh = []
    for i in times:
        thresh.append(thresholdVoltage)
    return thresh

# Calculate Tau
tau = CalculateTau()
print("Tau in ms: " + str(tau))

# Generate all the lists of pulsetrain and time-signatures
time = GenerateTime()
pulse = GeneratePulsetrain(upperVoltage)
threshLine = GenerateThreshLine(time)

# Simulate the outgoing voltage
voltage = OutVoltage(pulse, time)

plt.figure(figsize=(12,5))
plt.plot(time, pulse)
plt.plot(time, voltage)
plt.plot(time, threshLine, 'k--')
plt.title("Spenningsutvikling ved " + str(RPM) + " RPM. Grensefrekvens er " + 
          str(tauRPM) + " RPM.")
plt.xlabel("Tid [ms]")
plt.ylabel("Spenning [V]")
plt.legend(["Pulstog, " + r'$v_1$', "Utgående spenning, " + r'$v_2$', "Terskelspenning, " + r'$V_T$'], loc="upper right")
plt.savefig(filename + ".png", dpi = 300)
plt.show()
            