JEPL/jepl/jepl_circuits.py
2024-12-15 20:19:11 -04:00

241 lines
7.4 KiB
Python

'''
JMK Engineering Inc. Python Library for design and such.
by: Jeff MacKinnon
email: jeff@jmkengineering.com
Circuit Design Functions
'''
import pandas as pd
import numpy as np
import math
import sqlite3
def vd(current,length,resistance,runs=1):
'''
Calculates the voltage drop across the conductor length.
If there are parallel runs we assume that they are approximately the same length.
Therefore from the general equation of:
1/Req = 1/R1 + 1/R2 ... and all R1-Rn are the same.
Req = R/n or in the equation below r = resistance / runs.
'''
r = (length*resistance/1000) / runs
vd=round(2*current*r,8)
return vd
def percentvd(vd,nominal):
percent = (vd/nominal)*100
return percent
def voltage_drop(nominal_voltage, current, conductor_size, material ='cu', num_runs = 1, code = 'CEC'):
'''
This function will return the drop in voltage and in percent of the supply.
nominal_voltage = int
current = float
conductor_size = string
Voltage drop equation is:
Vdrop = 2 * I * L * R/1000
I = load current
L = circuit length in meters
R = Resistance in ohms/km
'''
# Check to see if the db we need exists
import os
import sys
if os.path.isfile('jepl-cable.db') == False:
return (print("Run init. \nCopy jeplinit.py to the same folder as this file and add \n%run jeplinit.py jepl/folder/location/\nto the notebook. Make sure there is a trailing slash."))
if (material == 'al'):
try:
with sqlite3.connect("jepl-cable.db") as con:
cur = con.cursor()
cur.execute('SELECT "AC Resistance" FROM "SW-Spec 25051" WHERE "Conductor Number" = 3 AND "Conductor Size"=?', (conductor_size,))
resistance = cur.fetchone()[0]
#print(resistance)
except sqlite3.OperationalError as e:
print(e)
elif (material == 'cu'):
try:
with sqlite3.connect("jepl-cable.db") as con:
cur = con.cursor()
cur.execute('SELECT "AC Resistance" FROM "SW-Spec 25055" WHERE "Conductor Number" = 3 AND "Conductor Size"=?', (conductor_size,))
resistance = cur.fetchone()[0]
except sqlite3.OperationalError as e:
print(e)
else:
return (print("error, choose material as cu or al"))
voltage = vd(nominal_voltage,current,resistance,num_runs)
percent = percentvd(voltage,nominal_voltage)
return [voltage, percent]
#
# voltage_drop_conductors is wrong
#
#
def voltage_drop_conductors(voltage,current,distance,v_drop_percent = 0.03,runs = 1,material='cu'):
'''
Calculates the minimum conductor size to accomodate for voltage drop based on:
voltage -> system nominal voltage
current -> the peak/design load for the circuit
distance -> meters
v_drop_percent -> The design voltage drop (default 0.03 or 3%)
runs -> number of parallel runs (default 1)
material -> the conductor material, either 'al' or 'cu'. (default 'cu')
First we calculate the necessary resistivity:
resistivity = ohms/km
but the distance is 2x (there and back)
resistivity = ohms/[(2 * distance)/1000] {ohms/km}
ohms = v/I or v_drop_percent/current
resistivity = (v_drop_percent/current)/[(2 * distance)/1000]
This works for 1 run, but for parallel runs Rtot = R/n where n is the number of runs.
in this equation we are looking for R, not Rtot, so we multiply the top by the number of runs.
therefore:
resistivity = [(v_drop_percent/current)*runs]/[(2 * distance)/1000]
'''
# Determine the resistivity needed in ohms/km
resistivity = ((v_drop_percent/current)*runs)/((2 * distance)/1000)
if resistivity < 0.1214:
print("add parallel runs")
print(resistivity)
else:
print(resistivity)
import os
import sys
if os.path.isfile('jepl-cable.db') == False:
return (print("Run init. \nCopy jeplinit.py to the same folder as this file and add \n%run jeplinit.py jepl/folder/location/\nto the notebook. Make sure there is a trailing slash."))
# Lookup the conductor size that meets this resistivity.
if (material == 'al'):
try:
with sqlite3.connect("jepl-cable.db") as con:
cur = con.cursor()
cur.execute('SELECT "Conductor Size" FROM "SW-Spec 25055" WHERE "Conductor Number" = 3 AND "AC Resistance"<?', (resistivity,))
conductor = cur.fetchone()[0]
print(conductor)
except sqlite3.OperationalError as e:
print(e)
elif (material == 'cu'):
try:
with sqlite3.connect("jepl-cable.db") as con:
cur = con.cursor()
cur.execute('SELECT "Conductor Size" FROM "SW-Spec 25051" WHERE "Conductor Number" = 3 AND "AC Resistance"<?', (resistivity,))
conductor = cur.fetchone()[0]
print(conductor)
except sqlite3.OperationalError as e:
print(e)
else:
return (print("error, choose material as cu or al"))
return (conductor)
# These functions need to be re-written with the databases.
'''
'''
def conductor_size(current, temp = 75, material = 'cu', code = 'CEC', raceway = True, ambient = 30, max = 500):
'''
The default temp column will be the 75C column as most terminals are rated for this.
The default code is CEC as that is where I am.
I still need to incorporate ambient temperature deratings, but that will be a future improvement
'''
material = material.upper()
code = code.upper()
max = str(max)
valid_temp = [60,75,90]
valid_temp_str = [str(x) for x in valid_temp]
valid_code = ['CEC',
]
valid_material = ['CU',
'AL',
]
#check to make sure that the values are valid
if temp not in valid_temp:
return print(temp + " is not valid. The valid temps are "+ str(valid_temp_str))
if code not in valid_code:
return print(code + " is not a valid code. The valid codes are "+ str(valid_code))
if material not in valid_material:
return print(material + " is not a valid material. I should be 'al' or 'cu'.")
# select the correct code table
if (code == 'CEC') & (material == 'CU') & (raceway == False):
code_table = CEC_table1
elif (code == 'CEC') & (material == 'CU') & (raceway == True):
code_table = CEC_table2
elif (code =='CEC') & (material =='AL') & (raceway == False):
code_table = CEC_table3
elif (code =='CEC') & (material =='AL') & (raceway == True):
code_table = CEC_table4
elif (code =='NEC') & (material =='CU'):
return (' I haven\'t created this table yet')
elif (code =='NEC') & (material =='AL'):
return (' I haven\'t created this table yet')
else:
return ('The variables were\'t right, but I\'m a loss to why.')
temp = str(temp)
max_current_loc = code_table.loc[code_table['size'] == max][str(temp)]
max_current = max_current_loc.iloc[0]
num_parallel = math.ceil(current / max_current)
con_current = current / num_parallel
size = code_table[code_table[temp].ge(con_current)]['size'].iloc[0]
return [size,num_parallel]
'''
'''
# ^
# These functions need to be re-written with the databases.
'''
'''