BSmiths1544 Posted October 9, 2021 Posted October 9, 2021 49 minutes ago, Steven P said: You could try this and see what you think, the prompts in the command line should guide you. the output is a table of mtexts. You mentioned doing a recalculation if the selected wire gauge isn't quite right - that should be easy to do but for another day maybe As always if anyone wants to rip the LISP to pieces and let me know a better way to do things, always appreciated. So try this as a start, command is vdcalc ;;;Building Blocks copied from other stuff;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;http://www.turvill.com/t2/free_stuff/tlen.lsp ;;TLEN Sum line lengths (defun TLEN (/ ss tl n ent itm obj l) ;;;-GETS TOTAL LENGTH OF SELECTED LINES, POLYLINES AND SO ON-;;; (setq ss (ssget '((-4 . "<OR")(0 . "LINE")(0 . "LWPOLYLINE")(0 . "ELLIPSE")(0 . "LWPOLYLINE")(0 . "SPLINE")(-4 . "OR>")) ) tl 0 n (1- (sslength ss)) ) (while (>= n 0) (setq ent (entget (setq itm (ssname ss n))) obj (cdr (assoc 0 ent)) l (cond ((= obj "LINE") (distance (cdr (assoc 10 ent))(cdr (assoc 11 ent)))) ((= obj "ARC") (* (cdr (assoc 40 ent)) (if (minusp (setq l (- (cdr (assoc 51 ent)) (cdr (assoc 50 ent))))) (+ pi pi l) l))) ((or (= obj "CIRCLE")(= obj "SPLINE")(= obj "POLYLINE") (= obj "LWPOLYLINE")(= obj "ELLIPSE")) (command "_.area" "_o" itm) (getvar "perimeter")) (T 0)) tl (+ tl l) n (1- n) ) ) tl ;;returns tl, total length ) (defun getfroment (ent listorstring entcodes / acount acounter mytext newtext stringtext) ;;;-Gets text string from a selected entity (text, mtext, block, dimension etc)-;;; ;;;-It won't remove formatting codes in for example mtexts.. which is why output table is mtexts....-;;; ;;get dotted pairs list (setq entlist (entget ent)) (setq acount 0) (while (< acount (length entlist)) (setq acounter 0) (while (< acounter (length entcodes)) (setq entcode (nth acounter entcodes)) (if (= (car (nth acount entlist)) entcode ) (progn (setq newtext (cdr (nth acount entlist))) (if (numberp newtext)(setq newtext (rtos newtext))) ;fix for real numbers (setq mytext (append mytext (list (cons (car (nth acount entlist)) newtext) )) ) );end progn );end if (setq acounter (+ acounter 1)) );end while (setq acount (+ acount 1)) );end while ;;get string from dotted pair lists (if (= listorstring "astring") ;convert to text (progn (if (> (length mytext) 0) (progn (setq acount 0) (setq temptext "") (while (< acount (length mytext)) (setq temptext (cdr (nth acount mytext)) ) (if (= stringtext nil) (setq stringtext temptext) (setq stringtext (strcat stringtext temptext )) );end if (setq acount (+ acount 1)) );end while );end progn );end if (if (= stringtext nil)(setq stringtext "")) (setq mytext stringtext) );end progn );end if mytext ) ;;get text (defun gettext( message / ent1 entlist1 entcodes1 text01) (setq ent1 (getent message)) (setq entlist1 (entget ent1)) (setq entcodes1 (list 3 4 1 172 304) ) ;list of ent codes containing text. (if (= (cdr (assoc 0 entlist1)) "DIMENSION") (setq entcodes1 (list 4 1 172 304) )) ;;if dimension (setq text01 (getfroment ent1 "astring" entcodes1) ) ;Text as string text01 ) ;;;;end of building blocks;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;Only does loop for a single circuit (defun c:vdcalc( / mysource mystartvolts mycircuitname wireresistances mywiresize mycircuit mydevice mydevicecurrent nomuttvar linelengths acount nextdevice circuitcount myresults drop totvd) ;;initial conditions. Note no error checking and so on. (setq circuitcount 1) (setq acount 1) (setq nextdevice "Y") (setq mycircuit (list (list "Circuit Name" "From" "Circuit Volts" "Wire Size" "Circuit Length" "To" "Device Current" "Volt Drop" "End volts")) ) (setq totcurrent 0) (setq wireresistances (list (cons 12 2.01) (cons 14 3.19) (cons 16 5.08) (cons 18 8.08) (cons 22 16.14))) ;;Set up system details (setq mysource (gettext "\nSelect Panel Name")) (setq mystartvolts (getreal "\nEnter Supply Terminal Volts ")) ;;;- see below for mywiresize if you want to limit circuit voltage to a set amount how to do that-;;; ;;circuit details (setq mycircuitname (getstring t "\nEnter Circuit Name/Number ")) ;;;-wire sizes-;;; ;;;-assumes same wire size for the circuit-;;; (initget "12 14 16 18 22") (setq mywiresize (atof (getkword "\nEnter Circuit Wire Gauge [12/14/16/18/22] "))) ;;getkword so initget works ;;Loop for circuit (while (= nextdevice "Y") (setq nomuttvar (getvar "nomutt")) (princ (strcat "\nSelect Lines, to device " (rtos acount 2 0) ", then press enter " ))(setvar "nomutt" 1) (setq linelengths (tlen)) (setvar "nomutt" nomuttvar) (setq mydevice (gettext (strcat "\nSelect device " (rtos acount 2 0) " name"))) (setq mydevicecurrent (getreal "\nEnter Current Draw: ") ) (setq totcurrent (+ totcurrent mydevicecurrent )) (setq mycircuit (append mycircuit (list (list mycircuitname mysource (rtos mystartvolts 2 2) (rtos mywiresize 2 0) (rtos linelengths) mydevice (rtos mydevicecurrent 2 3) )) )) (initget "Y N YES NO") (setq nextdevice (strcase (getstring "\nSelect another device [Y/N]")) ) (setq acount (+ acount 1)) ) (setq myresults (list (nth 0 mycircuit))) (setq acount 1) (setq totvd 0) (while (< acount (length mycircuit)) (setq res (cdr (assoc (atof (nth 3 (nth acount mycircuit))) wireresistances) )) (setq dist (atof (nth 4 (nth acount mycircuit)))) ;;;-Calculation-;;; ;;;-from BigAl-;;; (setq drop (* totcurrent (* res (/ (* dist 2.0) 1000.0)))) (setq totvd (+ totvd drop)) (setq endvolts (- (atof (nth 2 (nth acount mycircuit))) totvd) ) (setq myresults (append myresults (list (append (nth acount mycircuit) (list (rtos drop 2 3)) (list (rtos endvolts 2 3))) ))) (setq acount (+ acount 1)) ) (setq myresults (append myresults (list (list "" "" "" "" "" "" "Total Volt Drop:" (rtos totvd) )) )) ;;Make up a table - just mtext, nothing fancy (setq pt (getpoint "Enter table Insertion Point")) (setq pt1 pt) (setq acount 0) (while (< acount (length myresults)) (setq acounter 0) (while (< acounter (length (nth acount myresults)) ) (entmakex (list (cons 0 "MTEXT") (cons 100 "AcDbEntity") (cons 100 "AcDbMText") (cons 10 pt1) '(40 . 2.5) (cons 1 (nth acounter (nth acount myresults))) )) (setq pt1 (list (+ (nth 0 pt1) 25) (nth 1 pt1) (nth 2 pt1))) (setq acounter (+ acounter 1)) ) (setq pt1 (list (nth 0 pt) (- (nth 1 pt1) 7.5) (nth 2 pt))) (setq acount (+ acount 1)) ) (princ) ) Thanks for taking time to put this together! When I load and try to run it, I get the following message: Command: VDCALC ; error: no function definition: GETENT Quote
Steven P Posted October 9, 2021 Posted October 9, 2021 OK always a problem when I copy and paste, I missed this one, add the following into my Building Blocks section 'getent'. ;;entget or nentget a single entity ;;note entget for example in dimensions, nentget for the rest (defun getent ( aprompt / enta entb pt ) (princ "\n") (setq enta (car (nentsel aprompt))) (setq pt (cdr (assoc 10 (entget enta))) ) ;;;;fix for nenset or entsel requirements (setq entb (last (last (nentselp pt)))) (if (and (/= entb nil) (/= (type entb) 'real) ) (progn (if (wcmatch (cdr (assoc 0 (entget entb))) "ACAD_TABLE,*DIMENSION")(setq enta entb)) ) ) enta ) Quote
BSmiths1544 Posted October 9, 2021 Posted October 9, 2021 That did the trick! This is a great start, thank you so much. I will mess around with it more later today and maybe even see if I can make some adjustments myself. Quote
Steven P Posted October 9, 2021 Posted October 9, 2021 1 hour ago, BSmiths1544 said: That did the trick! This is a great start, thank you so much. I will mess around with it more later today and maybe even see if I can make some adjustments myself. Enjoy... (just be aware that it all makes sense... in my head, might be bonkers to anyone else or might be perfect, who knows). if you can work it out all the bits should be there to do what you want, the circuit information is saved as a list, or array and if you can work out how I did that you should be good, Quote
BIGAL Posted October 9, 2021 Posted October 9, 2021 I just replace all Initget now with the multi radio just feel easier to pick off screen for user input. No need for code to exist in your code. As the buttons are only choice can not enter anything else. (if (not AH:Butts)(load "Multi Radio buttons.lsp")) (if (= but nil)(setq but 1)) (setq mywiresize (atof (ah:butts but "V" '("Enter Wire Gauge" " 12" " 14" " 16" " 18" " 22" )))) (setq but 1) ; needed if calling multi radio again later in program can set to next desired button number (setq Nextdevice (ah:butts but "h" '("Select another device" "YES" "NO"))) (setq but 1) Did find a mistake in code for horizontal as per yes no so change multi radio buttons for horizontal. Was missing check width of heading. (if (= (strcase verhor) "V") (progn (write-line " : boxed_radio_column {" fo) (write-line (strcat " width = " (rtos (+ (strlen (nth 0 butlst)) 10) 2 0) " ;") fo) ; increase 10 if label does not appear ) (progn (write-line " : boxed_radio_row {" fo) (write-line (strcat " width = " (rtos (+ (strlen (nth 0 butlst)) 10) 2 0) " ;") fo) ; increase 10 if label does not appear ) ) 1 Quote
BIGAL Posted October 10, 2021 Posted October 10, 2021 For Bsmiths you need to add the attributes to the visibilty state for the horn, that way makes it way easier to get the Draw. You can using lisp to pop the visibilty states when inserting the block rather than having to click on the arrow to choose, it uses Lee-mac dynamic block lisp to read the states, then populate the Multi radio. If you edit the block can provide for you. 1 Quote
Steven P Posted October 10, 2021 Posted October 10, 2021 16 hours ago, BIGAL said: I just replace all Initget now with the multi radio just feel easier to pick off screen for user input. No need for code to exist in your code. As the buttons are only choice can not enter anything else. Good idea, I should use it more often. It is annoying at times to swap keyboard input to mouse to keyboard and back again, quicker to stick to one form or the other. You might take this further using the multi radio to select the other inputs on the assumption that each will only have a limited discrete number of options, in this example, all horns have a current draw of 0.151A, perhaps with a "other" option at the end for free entry. Maybe for another day, see how busy next week turns out to be Quote
BSmiths1544 Posted October 10, 2021 Posted October 10, 2021 (edited) This block should have voltage or amp attributes for any applicable device. I like that idea. I would say an "other" option would be fantastic, seeing as we use the same devices 95% of the time. That way, if it were a different brand as a replacement, I could enter it separately. My only other thought is having it extract the first attribute for each device (amps or voltage) when it's clicked. Could also extract the second attribute (device name/ID) for the table, eliminating the need to manually input. This way, if a certain component was added to our installs, I wouldn't have to go back and adjust the options every time. I am also attempting to modify this to do the other time consuming calculation... battery calcs. It's to ensure the proper sized secondary power supply is used for each panel. I will post as far as I'm able to get shortly. FIRE_BLOCK_10.8.21.dwg Edited October 10, 2021 by BSmiths1544 Quote
BIGAL Posted October 10, 2021 Posted October 10, 2021 (edited) For Stephen P, I have a 2 column radio button, have a play with this, I am looking at replacing the current version with just 1 version but accepts multi columns based on the number of lists provided. Easy to add a "Other". For Bsmiths I was wondering if it was easier to not have a dynamic block but rather a block for each type a bit more old school. You can use a tool palette or like me the older menu images. Multi radio buttons 2col.lsp Edited October 10, 2021 by BIGAL 1 Quote
Steven P Posted October 11, 2021 Posted October 11, 2021 Thanks, I'll save that away for later. Quote
BSmiths1544 Posted October 11, 2021 Posted October 11, 2021 Quote For Bsmiths I was wondering if it was easier to not have a dynamic block but rather a block for each type a bit more old school. You can use a tool palette or like me the older menu images. I used to have my set up like this, but once the projects got larger (100-200 devices), it made more sense to change to dynamic. I am constantly swapping devices out, adjusting locations, rotating, etc. as the project goes on. I could definitely give it a try using a palette. What benefit do you see in this method vs dynamic? Quote
BSmiths1544 Posted October 11, 2021 Posted October 11, 2021 We can visit this one later, but I just wanted to give an idea of what I'm trying to accomplish. The basic idea with battery calculation is adding up any device (current draw) on each separate panel to ensure proper secondary power source (battery). This is based on code required 24 amp hours for standby, and either 5 minutes (normal alarm 5/60) or 15 minutes (voice evacuation system 15/60). This will require me to add attribute1= standby draw and attribute2= alarm draw to each device block for extraction. Similar concept: enter command, you'd select source and then click every device on that panel. The routine would calculate standby current * 24 and alarm current * .083 for normal alarm or .25 for voice evac. It would then add the results for both, and multiply it be a derating factor of 1.2 (code standard). Example: Standby draw = 0.3 amps Alarm draw = 2 amps Standby load = 0.3 amps x 24 hours = 7.2 amp hours Alarm load = 2 amps x 0.083 hours = 0.17 ah Total load = 7.2 ah + 0.17 ah = 7.37 amp hours Derating factor = 20% per code (*1.2) 7.37 ah x 1.2 = 8.85 AH minimum required We can then select an appropriate battery. This is my first attempt ever so there are definitely components missing, in the wrong place, or some that are likely unnecessary. Tried to find the patterns in Steven P's volt drop lisp. ;;Adds total standby and alarm load and calculates amp hour requirements for secondary power source (battery) to panel (FACP or Power Supply Panel) in order to determine required size ;; (defun c:battcalc ( / systemtype totalstandbyload totalalarmload totalallload standbyah alarmah deratingfactor requiredstandbytime requiredalarmtime requiredvoiceevactime mysystem myresults mysystemname mysystemcurrent acount nomuttvar totah) (setq systemtype (list (cons AlarmOnly .083) (cons VoiceEvac 0.25) (setq acount 1) (setq totalstandbyload 0) (setq totalalarmload 0) (setq totalallload 0) (setq requiredstandbytime 24) (setq requiredalarmtime 5) (setq requiredvoiceevactime 15) (setq deratingfactor 1.2) (setq mysystem (list (list "Power Source" "System Type" "Total Load Standby" "Total Load Alarm" "Standby Time (Minutes)" "Alarm Time (Minutes)" "Total Load All" "Derating Factor")) ) ;;Select system type;; (initget "AlarmOnly VoiceEvac") (setq systemtype (atof (getkword "\nStandard Alarm or Voice Evacuation System? [AlarmOnly/VoiceEvac] "))) ;;System details;; (setq mysystemname (getstring t "\nEnter Panel Name ")) ;;Loop to select all devices on selected panel, extract "Standby" and "Alarm" voltage attributes and add to find sum of both?;; (setq nomuttvar (getvar "nomutt")) (princ (strcat "\nSelect All Devices On Panel " (rtos acount 2 0) ", Then Press Enter " ))(setvar "nomutt" 1) (setq mysystemalcurrent (;;;Extract;;;) (setq mysystemsbcurrent (;;;Extract;;;) (setq totalstandbyload (+ totalstandbyload mysystemsbcurrent)) (setq totalalarmload (+ totalalarmload mysystemalcurrent)) (setq mysystem (append mysystem (list (list mysystemname (rtos systemtype 2 2) (rtos totalstandbyload 2 0) (rtos totalalarmload 2 0) (rtos requiredstandbytime) (rtos requiredalarmtime) (rtos totalallload) (rtos deratingfactor) )))) (setq myresults (list (nth 0 mysystem))) (setq acount 1) ;;totah is total amp hours;; (setq totah 0) ;;Calculation;; ;;add current of devices in standby operation AMPS; this is per panel (FACP, Power Supply Panel ... each have seperate batt calc.);; (setq totalstandbyload ( "Amps")) ;;add current of devices in alarm condition AMPS; this is per panel (FACP, Power Supply Panel ... each have seperate batt calc.);; (setq totalalarmload ( "Amps")) ;;multiply standby current x 24 hours AMP HOURS (setq standbyah (* totalstandbyload 24) "Amp Hours") ;;multiply alarm current by 5 minutes for alarm (5/60) OR 15 minutes for voice evac (15/60) AMP HOURS (setq alarmah (* totalalarmload systemtype) "Amp Hours") ;;add standby load + alarm load AMP HOURS (setq totalallload (+ alarmah standbyah) "Amp Hours") ;;multiply by derating factor of 1.2 TOTAL AMP HOURS REQUIRED (setq totah (* totalallload 1.2) (setq myresults(append myresults(list (list "" "" "" "" "" Total Amp Hours Required: (rtos totah) )))) ;;Insert Table;; (setq pt (getpoint "Enter Table Insertion Point")) (setq pt1 pt) Quote
BIGAL Posted October 12, 2021 Posted October 12, 2021 If you have got used to using dynamic blocks keep going that way, you should add attributes to the dynamic block, you basically have to make the attributes visible in the appropriate visibility state. Again much easier to read the values from a block rather than separate mtext. Quote
BSmiths1544 Posted October 12, 2021 Posted October 12, 2021 (edited) On 10/11/2021 at 7:08 PM, BIGAL said: If you have got used to using dynamic blocks keep going that way, you should add attributes to the dynamic block, you basically have to make the attributes visible in the appropriate visibility state. Again much easier to read the values from a block rather than separate mtext. I've updated the block with values for terminal cut off voltage (if applicable), alarm current draw, and standby current draw. They are visible currently, although it may confuse someone who doesn't know what they represent on the floor plan. If I'm able to keep them invisible, I'd rather do that. I also intend to add part number attributes when I have the time. I also thought I was on to something with Gilles Increment App : I wanted to give each block a Device ID attribute, and use this to go through and automatically give each device on the circuit an incremented ID (for example, N1.1 , N1.2, N1.3 etc...). The problem I'm running into now is that you can only select one tag name at a time while using the app, and you can't use the same tag name for more than one device (there are multiple device types per circuit). That is something to figure out another day I suppose. FIRE_ALARM.dwg EDIT: I found another solution for the Device ID autonumbering. EDIT2: I found a way to "toggle" between visible and invisible attributes quickly. Edited October 15, 2021 by BSmiths1544 Quote
BSmiths1544 Posted October 18, 2021 Posted October 18, 2021 Steven P, In regards to the vdcalc routine, I failed to mention that I typically add 10ft to each wire segment to account for having to drop from the ceiling down to the device. How would I go about adding this to each polyline segment before the calculation happens? Quote
Steven P Posted October 19, 2021 Posted October 19, 2021 13 hours ago, BSmiths1544 said: In regards to the vdcalc routine, I failed to mention that I typically add 10ft to each wire segment to account for having to drop from the ceiling down to the device. How would I go about adding this to each polyline segment before the calculation happens? I should have thought about that, we typically do that, add a few percent on and then round up to the nearest whole number for cable lengths. So 2 ways to do this, if you can find the line length from my 'linelengths' variable (setq linelengths (tlen))) You can change it to (setq linelengths (+ (tlen) 10)) You might want to replace the '10' by a variable (defined earlier in the code) for when you come back to this in a few years time and wonder how it all works again. Similarly you can add other mathmatical functions to this for example (setq linelengths (* (+ (tlen) 0) 1.1) ) to give you a 10% increase The other part you can update instead is from what BigAl suggested (setq drop (* totcurrent (* res (/ (* dist 2.0) 1000.0)))) and do a similar change to 'dist': (setq drop (* totcurrent (* res (/ (* (+ dist 10) 2.0) 1000.0)))) 1 Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.