VapingBad
Mod Maker
Mr Fix-it
Joined:January 2014
Posts: 13,800
Location:
Likes: 14,176
Recent Posts
Last Online Oct 6, 2024 16:13:51 GMT
|
Post by VapingBad on Dec 15, 2016 14:14:17 GMT
Recently I was asked if I would test a couple of AOSO 18650 batteries and give an opinion by one of the organisers on the London and South East Vapers vape meet Phoenixflame (Julie) & jessica . They had already had the usual pulsed constant current tests and other people had reported puff counts and mWh for their normal use pattern. I wanted something that was informative for vapers, nobody vapes at a constant current. The efficiency of the board also has an effect, here is the current a battery will have to supply for 25,50 and 75 watts for a mod with 85% efficiency like the DNA 75, but the DNA 75 low cut-off is a quarter volt higher so max current would be 32 A. I have removed the start of the lines as even the best batteries cannot supply that current without that much sag. The EScribe battery analyser is more realistic as it is pulsed constant power, far more like the way people vape, but with 10 second vape and 30 second gaps you can build up a lot of heat at 75 W. Looking at www.ecigstats.org/global-stats/ average puff time is under 3 seconds, so I though I could do something with the IronPython scripting in EScribe Device Monitor. This has the additional benefits that anybody with a DNA 75, EScribe V1.2SP5+, a spare dripper deck and some Kanthal can use for free. We could also share results, repeat other's tests to verify them, load them in Device Monitor (or many other apps that handle csv data) to look at details and compare them. (BTW If you record the EScribe Battery Analyzer test you can also load these into Device Monitor) From the start I wanted puff time, gap and power to be easily changeable settings and to set a max board temp limit, but the more I tested the more I added to my wish list in terms flexibility and what I wanted to measure. If you look at the script you can see the settings at the top. With testing at 75 W some of the batteries could not keep doing 3 s puff at full power for very long, but still kept going and 90% for quite a while, so I made that measurement part of the test as well, actually you can add a list of decreasing percentages to record now. I started testing at 75 W, 3 s puff, 57 s gap and found that after the battery couldn't supply enough power they still had a lot of charge that took far too long to test with 3 s puff every minute. The solution I came up with was to increase the length of the puff so it still drew the same amount of energy and while not exact it works very well. Like the limp home mode on your car this is using the DNA's soft limiting where you can at least get something to for your nic craving. Testing this one battery I saw do this for a long time before doubling the length of the puff so I record that as well. You can see the DNA's soft limiting in action in Device Monitor when the battery drops to the low cut-off voltage (default 2.75 V) the output power is lowered. So the test has 3 stages: 1 measure puffs where the battery can supply full power. 2 measure puffs where the battery can supply a given percentage of full power. 3 increasing puff time to compensate for lower watts just noting the point where puff length doubles (I think most people would have stopped vaping by then) and the remaining power which is not really useful for vaping. (Stage 1 & 2 are exact tests, stage 3 is a little fuzzier just because there is no way to tell the board to take x watt hours. I just extend the puff time by the proportion it fell short on the previous puff as it varies between batteries which is fair and consistent, but I think vapers would be taking more energy at this point.) Here is a old 25R that is near the end of its life. Here are some examples of puffs at different stages (all a AOSO 42 A, 75 W 3 s puff, 57 s gap). The first is a fully charged battery, 2nd is the last puff before the sag hits the low cut off. The 3rd it hits low cut off in the middle off the puff, note the yellow line falling. The 4th & 5th the sag is at the limit for the whole puff, you would have swapped the battery or charge by now if you could, but could still get a weaker vape. The 2nd pic of puff is where the test is lengthening the puff time trying to keep the yellow energy line at the same level as for the full power puff. I saves 2 files, the csv that EScribe records and a text file with the summary shown in the message window. How to run the test I want to make it clear that this is what is working for me and provided in all good faith, it is your responsibility asses risks and to ensure your personal safety, the safety of anyone or anything else that could be affected, basically only use at your own risk I take no responsibility for the fitness or safety of the script or the process. Do not use it if you don agree with these conditions. Make a resistance below 0.5 ohm on your dipper deck as you would for Battery Analyser, I use 4 parallel loops of 0.5 mm Kanthal about the diameter of a tennis ball. I also you a couple of old computer fans to provide extra cooling at high powers. Make sure the mod is stable and the coils are safely away form kids, pets and anything that could be damaged by heat. Copy the script into a text file, save and change the file extension to py, I chose to do it this way so it can not pass malware and you can see it before you put it on your PC. Open the file in a text editor like notepad++ or notepad and adjust the settings at the top, they should be pretty self explanatory. Set your computers power saving settings so it will not sleep, hibernate or shut down USB for the duration of the test. Open Device Monitor, click Diagnostics - Disable USB Charging, set the Graph Options - Time Scale to something sensible, 60 seconds to and hour 3600 seconds. Then click Diagnostics - Run Script and find the file, that's it a message box will pop up when it finishes, close Device Monitor if you want to stop it running. Code: # DNA 75 Battery test script for use in EScribe V1.2SP5 Device Monitor. # Disable USB Charging in Device Monitor before running. # Ensure your PC will not go into sleep mode while running. # At high powers your mod and battery can get very hot, take care. # If the board temp is at the max setting after a rest period the script will keep resting until is cools. # USE AT YOUR OWN RISK # # Thanks to Evolv for providing the free tools to do this. # Written by VapingBad
# test settings, things you will probably want to customise batteryModel = '25R' nominalCellVoltage = 3.7 puffPower = 50 puffTime = 4 restTimeBetweenPuffs = 46 dataCollectionPoints = [90,80] outputFileFolderPath = r'C:\data' # no trailing slash maxPuffTime = 20 maxNumOfMaxTimePuffs = 6 # safety cut-offs maxBoardTempF = 125 minBatteryVoltsAfterRest = 2.8 maxPuffCount = 1000
# DO NOT ALTER AFTER THIS POINT # DO NOT ALTER AFTER THIS POINT # DO NOT ALTER AFTER THIS POINT import time import datetime from System.IO import Path
# set up EScribe Device Monitor tracking, fields plotted and saved in the csv file if Recorder.IsRecording: Recorder.StopRecording() ECig.ClearTracking() ECig.Track('Power') ECig.Track('Battery Pack') ECig.Track('Last Puff Energy') ECig.Track('Last Puff Time') ECig['Power Set'] = puffPower; time.sleep(2)
# Homer Simpson guard clauses if minBatteryVoltsAfterRest < 2.75: minBatteryVoltsAfterRest = 2.75 if maxBoardTempF > 200.0: maxBoardTempF = 200.0 if puffTime > 20.0: puffTime = 20.0 if restTimeBetweenPuffs < 2 * puffTime: restTimeBetweenPuffs = 2 * puffTime if maxPuffTime < puffTime: maxPuffTime = puffTime if maxPuffTime > 20.0: maxPuffTime = 20.0
# conversion factors and constants secondsInAnHour = 3600.0 milliToBaseUnitConversionFactor = 0.001 lossCompensationFactor = 1.0/0.85 wattHourToMilliAmpHourFactor = 1000.0/nominalCellVoltage wiggleRoomFactor = 0.98
# classes class puffLogger: def __init__(self, lable): self.lable = lable puffs = 0 energy = 0.0 volts = 0.0 test = None next = None def copyReadings(self, fromThis): self.puffs = fromThis.puffs self.energy = fromThis.energy self.volts = fromThis.volts def checkPuff(self, puffEnergy, data): if self.test(puffEnergy): self.copyReadings(data) return self else: return self.next class compensatingPuffTime: def __init__(self, setTime, maxTime = 20.0, maxExtPuffs = 5): self.setTime = float(setTime) self.maxTime = maxTime self.maxExtPuffs = maxExtPuffs expectedPuffEnergy = 0.0 increasedPuffCount = 0 increaseFactor = 1.0 reachedLimit = False timeDoubledData = puffLogger('Up to double length puff') def puffTime(self): return self.setTime * self.increaseFactor def calcNextPuff(self, lastPuffEnergy, allPuffsData): factor = self.increaseFactor * self.expectedPuffEnergy / lastPuffEnergy if self.setTime * factor > self.maxTime: factor = float(self.maxTime) / self.setTime if self.increasedPuffCount >= self.maxExtPuffs: self.reachedLimit = True else: self.increasedPuffCount += 1 if factor < 1.0: factor = 1.0 if factor > 2.0 and self.timeDoubledData.puffs == 0: self.timeDoubledData.copyReadings(allPuffsData) self.increaseFactor = factor # variables date = datetime.datetime.now() expectedPuffEnergy = puffPower * puffTime / secondsInAnHour #* wiggleRoomFactor puffTimeCompensator = compensatingPuffTime(puffTime, maxPuffTime, maxNumOfMaxTimePuffs) puffTimeCompensator.expectedPuffEnergy = expectedPuffEnergy globalLogger = puffLogger('Battery capacity') fullPowerLogger = puffLogger("At full power") fullPowerLogger.test = lambda x: x >= expectedPuffEnergy * wiggleRoomFactor # chain puff tests together, when the test fails the next test will take it's place previous = fullPowerLogger for p in dataCollectionPoints: dp = puffLogger('Up to {}% power'.format(p)) dp.test = lambda x, y = p: x >= expectedPuffEnergy * wiggleRoomFactor * y / 100 previous.next = dp previous = dp
# make timestamped file names fileName = 'BatteryTest {0} {1}'.format(batteryModel, '{:%Y%m%d-%H%M}'.format(date)) outputFileNoExtension = Path.Combine(outputFileFolderPath, fileName) csvFilePath = '{0}.csv'.format(outputFileNoExtension) txtFilePath = '{0}.txt'.format(outputFileNoExtension)
# ACTUAL BATTERY TEST Recorder.Record(csvFilePath) initialVoltage = ECig['Battery Pack'] currentLogger = fullPowerLogger
while True: if ECig['Board Temperature'] >= maxBoardTempF: time.sleep(restTimeBetweenPuffs) continue ECig.Puff(puffTimeCompensator.puffTime()) time.sleep(restTimeBetweenPuffs) # there is a delay before this value is updated lastPuffEnergy = ECig['Last Puff Energy'] * milliToBaseUnitConversionFactor globalLogger.volts = ECig['Battery Pack'] globalLogger.puffs += 1 globalLogger.energy += lastPuffEnergy if currentLogger is not None: currentLogger = currentLogger.checkPuff(lastPuffEnergy, globalLogger) if currentLogger is None: puffTimeCompensator.calcNextPuff(lastPuffEnergy, globalLogger) if globalLogger.volts <= minBatteryVoltsAfterRest or globalLogger.puffs >= maxPuffCount or puffTimeCompensator.reachedLimit: break
if Recorder.IsRecording: Recorder.StopRecording()
# format, save and show result summary resultText = 'Battery test {} {:%c}\nInitial voltage {:.2f} V, Nominal voltage {:.2f} V\nTest: {} W, {} s puffs, {} s rest periods:\n'.format(batteryModel, date, initialVoltage, nominalCellVoltage, puffPower, puffTime, restTimeBetweenPuffs) writeResult = lambda r: ' {}:\n Puffs = {}\n Energy = {:.3f} Wh, {} mAh\n Resting Voltage = {:.2f} V\n'.format(r.lable, r.puffs, r.energy*lossCompensationFactor, int(r.energy*lossCompensationFactor*wattHourToMilliAmpHourFactor), r.volts) p = fullPowerLogger while p is not None: resultText += writeResult(p) p = p.next resultText += writeResult(puffTimeCompensator.timeDoubledData) resultText += writeResult(globalLogger)
with open(txtFilePath, 'w') as file: file.write(resultText)
UI.Message(resultText)
|
|
VapingBad
Mod Maker
Mr Fix-it
Joined:January 2014
Posts: 13,800
Location:
Likes: 14,176
Recent Posts
Last Online Oct 6, 2024 16:13:51 GMT
|
Post by VapingBad on Dec 15, 2016 15:00:42 GMT
Using it to compare batteries at different wattages
|
|
jtc
Super Member
Joined:January 2016
Posts: 8,447
Location:
Likes: 3,953
Recent Posts
Last Online Feb 17, 2022 19:12:17 GMT
|
Post by jtc on Dec 15, 2016 15:17:55 GMT
Hmmm very clever sir but a brain strain for me tbh Which battery would last the longest at 100w on my Rolo's please?
|
|
VapingBad
Mod Maker
Mr Fix-it
Joined:January 2014
Posts: 13,800
Location:
Likes: 14,176
Recent Posts
Last Online Oct 6, 2024 16:13:51 GMT
|
Post by VapingBad on Dec 15, 2016 15:38:52 GMT
Hmmm very clever sir but a brain strain for me tbh Which battery would last the longest at 100w on my Rolo's please? The 30Q, because the 200 is a lot more efficient and has three times the battery count you would be closest to the 25 W test. 100 W / 3 = 33.333 W per battery, 98% efficiency means 34 W required from the battery, 2nd last column.
|
|
jtc
Super Member
Joined:January 2016
Posts: 8,447
Location:
Likes: 3,953
Recent Posts
Last Online Feb 17, 2022 19:12:17 GMT
|
Post by jtc on Dec 15, 2016 15:40:34 GMT
Cheers VapingBad Yes I'm using some of them now and they've been great this last year tbh
|
|
VapingBad
Mod Maker
Mr Fix-it
Joined:January 2014
Posts: 13,800
Location:
Likes: 14,176
Recent Posts
Last Online Oct 6, 2024 16:13:51 GMT
|
Post by VapingBad on Dec 15, 2016 15:50:06 GMT
They are great at that level, but if you up the power the 25R can last longer so better value for most people IMO. Longer puff times would also have that effect, I am just testing the 60 A AOSO with 50% longer puff and rest time ATM and it hits the low cut off far earlier 3.7 V vs 3.5 V. I think it will be interesting to test it with 1.5, 3, 4.5 & 6 second puffs to show the effect.
|
|
VapingBad
Mod Maker
Mr Fix-it
Joined:January 2014
Posts: 13,800
Location:
Likes: 14,176
Recent Posts
Last Online Oct 6, 2024 16:13:51 GMT
|
Post by VapingBad on Dec 15, 2016 17:16:58 GMT
Wow, at 75 W with the AOSO 60 A with a 50% increase in puff time (3 -> 4.5 s) and rest time (57 -> 88.5 s) the available power drops to 52% for full power puff and 62% for 90% power puff.
|
|
VapingBad
Mod Maker
Mr Fix-it
Joined:January 2014
Posts: 13,800
Location:
Likes: 14,176
Recent Posts
Last Online Oct 6, 2024 16:13:51 GMT
|
Post by VapingBad on Dec 20, 2016 13:15:20 GMT
Changes for V2.1 Added a field to capture battery sag 0.1 seconds before the end of the last puff for each stage. Added setting doExtendPuffTimes to enable/disable the variable puff time feature. Changed the file name format to include the power, puff time and rest time EG BatteryTest 25R 50W-4-46 20161220-1039 Changed to allow rest time to equal puff time, previously it had to be double. Changed the wiggleRoomFactor from 0.98 to 0.99, this just allows a tiny tolerance when checking if a stage is complete. Fixed bug the sleep rest time, I should have added puff time.
I have used the script to discharge batteries for storage with these setting
puffPower = 20 puffTime = 2 restTimeBetweenPuffs = 2 doExtendPuffTimes = False minBatteryVoltsAfterRest = 3.7
V2.1 Code:
# DNA 75 Battery test script for use in EScribe V1.2SP5 Device Monitor. # Disable USB Charging in Device Monitor before running. # Ensure your PC will not go into sleep mode while running. # At high powers your mod and battery can get very hot, take care. # If the board temp is at the max setting after a rest period the script will keep resting until is cools. # USE AT YOUR OWN RISK # # Thanks to Evolv for providing the free tools to do this. # Written by VapingBad V2.1 # Thread https://evolvapor.forumchitchat.com/post/escribe-custom-battery-test-python-script-8344246
# test settings, things you will probably want to customise puffPower = 50 puffTime = 4 restTimeBetweenPuffs = 46 doExtendPuffTimes = True dataCollectionPoints = [90,80] batteryModel = '25R' nominalCellVoltage = 3.7 outputFileFolderPath = r'C:\data' # no trailing slash maxPuffTime = 20 maxNumOfMaxTimePuffs = 6 # safety cut-offs maxBoardTempF = 125 minBatteryVoltsAfterRest = 2.8 maxPuffCount = 1000
# DO NOT ALTER AFTER THIS POINT # DO NOT ALTER AFTER THIS POINT # DO NOT ALTER AFTER THIS POINT import time import datetime from System.IO import Path
# set up EScribe Device Monitor tracking, fields plotted and saved in the csv file if Recorder.IsRecording: Recorder.StopRecording() ECig.ClearTracking() ECig.Track('Power') ECig.Track('Battery Pack') ECig.Track('Last Puff Energy') ECig.Track('Last Puff Time') ECig['Power Set'] = puffPower; time.sleep(2)
# Homer Simpson guard clauses if minBatteryVoltsAfterRest < 2.75: minBatteryVoltsAfterRest = 2.75 if maxBoardTempF > 200.0: maxBoardTempF = 200.0 if puffTime > 20.0: puffTime = 20.0 if restTimeBetweenPuffs < puffTime: restTimeBetweenPuffs = puffTime if maxPuffTime < puffTime: maxPuffTime = puffTime if maxPuffTime > 20.0: maxPuffTime = 20.0
# conversion factors and constants secondsInAnHour = 3600.0 milliToBaseUnitConversionFactor = 0.001 lossCompensationFactor = 1.0/0.85 wattHourToMilliAmpHourFactor = 1000.0/nominalCellVoltage wiggleRoomFactor = 0.99
# classes class puffLogger: def __init__(self, lable): self.lable = lable puffs = 0 energy = 0.0 volts = 0.0 sag = 0.0 test = None next = None def copyReadings(self, fromThis): self.puffs = fromThis.puffs self.energy = fromThis.energy self.volts = fromThis.volts self.sag = fromThis.sag def checkPuff(self, puffEnergy, data): if self.test(puffEnergy): self.copyReadings(data) return self else: return self.next class compensatingPuffTime: def __init__(self, setPuffTime, maxTime = 20.0, maxExtPuffs = 6): self.setPuffTime = float(setPuffTime) self.maxTime = maxTime self.maxExtPuffs = maxExtPuffs expectedPuffEnergy = 0.0 increasedPuffCount = 0 increaseFactor = 1.0 reachedLimit = False timeDoubledData = puffLogger('Up to double length puff') def puffTime(self): return self.setPuffTime * self.increaseFactor def calcNextPuff(self, lastPuffEnergy, allPuffsData): factor = self.increaseFactor * self.expectedPuffEnergy / lastPuffEnergy if self.setPuffTime * factor > self.maxTime: factor = float(self.maxTime) / self.setPuffTime if self.increasedPuffCount >= self.maxExtPuffs: self.reachedLimit = True else: self.increasedPuffCount += 1 if factor < 1.0: factor = 1.0 if factor > 2.0 and self.timeDoubledData.puffs == 0: self.timeDoubledData.copyReadings(allPuffsData) self.increaseFactor = factor # variables date = datetime.datetime.now() timeToReadSagBeforeEndOfPuff = 0.1 expectedPuffEnergy = puffPower * puffTime / secondsInAnHour #* wiggleRoomFactor puffTimeCompensator = compensatingPuffTime(puffTime, maxPuffTime, maxNumOfMaxTimePuffs) puffTimeCompensator.expectedPuffEnergy = expectedPuffEnergy globalLogger = puffLogger('Battery capacity') fullPowerLogger = puffLogger("At full power") fullPowerLogger.test = lambda x: x >= expectedPuffEnergy * wiggleRoomFactor # chain puff tests together, when the test fails the next test will take it's place previous = fullPowerLogger for p in dataCollectionPoints: dp = puffLogger('Up to {}% power'.format(p)) dp.test = lambda x, y = p: x >= expectedPuffEnergy * wiggleRoomFactor * y / 100 previous.next = dp previous = dp
# make timestamped file names fileName = 'BatteryTest {} {}W-{}-{} {}'.format(batteryModel, puffPower, puffTime, restTimeBetweenPuffs, '{:%Y%m%d-%H%M}'.format(date)) outputFileNoExtension = Path.Combine(outputFileFolderPath, fileName) csvFilePath = '{}.csv'.format(outputFileNoExtension) txtFilePath = '{}.txt'.format(outputFileNoExtension)
# ACTUAL BATTERY TEST Recorder.Record(csvFilePath) initialVoltage = ECig['Battery Pack'] currentLogger = fullPowerLogger
while True: if ECig['Board Temperature'] >= maxBoardTempF: time.sleep(restTimeBetweenPuffs) continue ECig.Puff(puffTimeCompensator.puffTime()) time.sleep(puffTimeCompensator.puffTime() - timeToReadSagBeforeEndOfPuff) globalLogger.sag = globalLogger.volts - ECig['Battery Pack'] time.sleep(restTimeBetweenPuffs) lastPuffEnergy = ECig['Last Puff Energy'] * milliToBaseUnitConversionFactor globalLogger.volts = ECig['Battery Pack'] globalLogger.puffs += 1 globalLogger.energy += lastPuffEnergy if currentLogger is not None: currentLogger = currentLogger.checkPuff(lastPuffEnergy, globalLogger) if doExtendPuffTimes and currentLogger is None: puffTimeCompensator.calcNextPuff(lastPuffEnergy, globalLogger) if globalLogger.volts <= minBatteryVoltsAfterRest or globalLogger.puffs >= maxPuffCount or puffTimeCompensator.reachedLimit: break
if Recorder.IsRecording: Recorder.StopRecording()
# format, save and show result summary resultText = 'Battery test {} {:%c}\nInitial voltage {:.2f} V, Nominal voltage {:.2f} V\nTest: {} W, {} s puffs, {} s rest periods:\n'.format(batteryModel, date, initialVoltage, nominalCellVoltage, puffPower, puffTime, restTimeBetweenPuffs) writeResult = lambda r: ' {}:\n Puffs = {}\n Energy = {:.3f} Wh, {} mAh\n Max Voltage Sag = {:.3f} \n Resting Voltage = {:.2f} V\n'.format(r.lable, r.puffs, r.energy*lossCompensationFactor, int(r.energy*lossCompensationFactor*wattHourToMilliAmpHourFactor), r.sag, r.volts) p = fullPowerLogger while p is not None: resultText += writeResult(p) p = p.next resultText += writeResult(puffTimeCompensator.timeDoubledData) resultText += writeResult(globalLogger)
with open(txtFilePath, 'w') as file: file.write(resultText)
UI.Message(resultText)
|
|
manonabus
Junior Member
Joined:August 2015
Posts: 92
Location:
Likes: 73
Recent Posts
Last Online Jul 25, 2018 7:43:17 GMT
|
Post by manonabus on Dec 20, 2016 16:51:27 GMT
That looks very impressive but flown straight over my head. All I know is I have a SONY VTC5 IMR US18650 2600MAH 30/60A HIGH DRAIN Battery and I need to re-charge it every day Currently showing 3.4v @1 bar remaining fuel stop due shortly
|
|
tim
Super Member
Joined:February 2015
Posts: 2,137
Location:
Likes: 1,516
Recent Posts
Last Online May 25, 2022 22:18:37 GMT
|
Post by tim on Dec 21, 2016 22:20:25 GMT
I have a couple of Shockl 26650's I got from Torchy in my VT75. Do they compare with the AOSO's VapingBad? I have no idea what the amp rating is. I did, but I forget stuff nowdays..... I'm hoping they are quite good, but I'm having trouble getting my head round the Escribe stuff at the moment. Sorry to be a pain, but thanks if you have any idea.
|
|
VapingBad
Mod Maker
Mr Fix-it
Joined:January 2014
Posts: 13,800
Location:
Likes: 14,176
Recent Posts
Last Online Oct 6, 2024 16:13:51 GMT
|
Post by VapingBad on Dec 22, 2016 6:47:44 GMT
|
|
tim
Super Member
Joined:February 2015
Posts: 2,137
Location:
Likes: 1,516
Recent Posts
Last Online May 25, 2022 22:18:37 GMT
|
Post by tim on Dec 23, 2016 21:43:31 GMT
|
|