Peak Shaving Through The Use of Battery Technology

In circumstances where there’s a large extra demand for power, peak shaving is one method that can be used to attempt to address the imbalance.

Onsite battery storage for peak shaving
Maintaining a 50Hz for efficient operation

Ireland's electrical grid must maintain a frequency of 50Hz for efficient operation. When there is a sudden unexpected rise or reduction in demand the frequency changes in response. If demand is sufficient enough then the frequency can change rapidly and steps must be taken to mitigate this as frequency imbalance can damage electrical systems, and eventually lead to a national blackout.

Peak Shaving is commonly mistaken for 'Load Shedding'. Load Shedding is a method to reduce your load on the grid also, however, at a significant cost in comparison to Peak Shaving, as it entails slowing production for some time whilst other generative methods come online, as they can take several minutes to spool up.

The purpose of Peak Shaving is to reduce a company's power demand on the grid and keep it as constant as possible. To reduce or eliminate demand charges from their energy bill.

By applying this method, companies can save thousands of euro/dollars a year in demand charges on their energy bill.1

However, Demand Charges are not the sole charge incurred when using the grid during a peak load period. If a consumer is applying the method of peak shaving, making their load on the national grid constant, they are still using a large amount of power during a period of peak power demand. Since the electricity price varies, with the grid's demand, the cost is significantly higher during these periods of high demand and significantly lower during periods of little demand, such as in the middle of the night.

By utilizing a commonplace onsite battery paired with the method of Peak Shaving, consumers can not only lower and possibly abolish their demand charges.  They can also lower their electricity spending by charging their batteries at night while the cost of electricity is low and by using power from those batteries during periods of high demand when the cost of energy is significantly higher.

Not only can you use peak shaving technology to lower your overall electricity spend, it is also feasible to make a profit through the batteries 'used' for peak shaving when they are not in use. As previously mentioned, the power price is directly related to the demand on the grid. Charging the battery at night while the demand and price are low and selling that power back to the grid during a period of high demand at a higher cost can yield a significant profit. So long as the algorithm doing this factors in and optimises for battery wear and tear, and battery price. As it happens, Full Stack Energy specialises in the design and development of algorithms for tasks like this.

To demonstrate the effectiveness of Battery Powered Peak Shaving Technology:

I created a simple Peak Shaving algorithm and used it with demand data from Ireland's grid for 24 hours to evaluate its effectiveness on real-world data. An essential part of a Peak Shaving algorithm is that it must be tuned to the customer's power usage and facilities. This is demonstrated in the charts below.  

When the algorithm was first created and run using standard tuning parameters, it looked like this:

WITHOUT TUNING, THE ALGORITHM CANNOT PERFORM EFFICIENTLY.

Notably, the algorithm tends to spike downward suddenly in this instance when attempting to shave a slight peak. It also only slightly decreases the two primary peaks.

Before Tuning

However, once the algorithm was tuned specifically for our simulated battery size and facility resources:

WE CAN SEE A SIGNIFICANT INCREASE IN ITS EFFECTIVENESS.

In contrast to our last simulation, the entrance toward the first peak is significantly lower. Leading toward a gradual exit of the peak.

After Tuning

Let's take a closer look at the algorithm’s first actions:

Time Remaining Charge (%) Action Grid Frequency (Hz)
06:00 87.5 Discharged Battery 49.93
06:15 67.5 Discharged Battery 49.95
12:00 80 Charged Battery 50.04
12:15 92.5 Charged Battery 50.02
14:15 80 Discharged Battery 49.93
15:00 92.5 Charged Battery 50.01

This chart demonstrates the algorithm's first actions. The algorithm's first action was to discharge the battery at 6 AM, which decreased the initial peak, establishing an overall lower primary peak. Additionally, the algorithm chose to charge its battery around noon when a sudden drop in demand occurred. This levelled out the top of our first peak and set itself up to deal with subsequent peaks by charging during this period.

If you would like to try this out project or see how it works in further detail, check out this project's GitHub repository

import csv

#----------------- Begin User Configuration -----------------------------------------------
Interval = 0.25 #As a fraction of an hour, Note, your data interval needs to match this

MinCharge = 65 #Minium Charge level
Capacity = 20 #Battery Capacity in MWh

CutIn = 49.945 #Frequency For Battery To Cut In
CutOut = 50.01 #Frequency for battery to charge

#----------------- End User Configuration -----------------------------------------------

Charge = 100 #Battery Charge Level
IntervalCap = (Capacity * Interval)

FreqFile = open('../Data/Frequency/Data.csv')
FreqRows = list(csv.reader(FreqFile, delimiter=','))

DemandFile = open('../Data/Demand/chart.csv')
DemandRows = list(csv.reader(DemandFile, delimiter=','))

with open('Log.csv', 'a') as Log_file:
    Log_file.truncate(0) #Clear the file, of previous Logs
    Log_Writer = csv.writer(Log_file)
    PrevDemand = 0
    PrevActualDemand = 0

    for row in FreqRows:
        #Format timestamp, and get frequency data
        timestamp = row[0]
        data = row[1]

        for Demand_Row in DemandRows:
            if str(timestamp) in Demand_Row[0]:
                #Row Is Active, get power demand
                Demand = Demand_Row[1]
                if PrevActualDemand == 0:
                    PrevActualDemand = float(Demand)
                    PrevDemand = float(Demand)


                #Get the change in demand from the real world data, apply it to the simulated data (Diff)
                #Simulating data, to show the scripts impact if it was applied in the field

                #Calculating the change in deamnd:
                #Checks the actual demand from previous time stamp, then compare with the difference with the current
                #Then add or subtract the change in demand to the simulated demand data


                diff = (float(Demand) - PrevActualDemand) 
                CurDemand = PrevDemand + diff
                

                if float(data) >= CutOut:
                    #Charge Battery if it needs it

                    if Charge < Capacity:
                        #Battery Needs Charging
                        Charge += IntervalCap
                        if Charge > Capacity:
                            #Capping the charge at 100
                            Charge == Capacity
                        
                        PrevActualDemand = float(Demand)
                        PrevDemand = (float(CurDemand) + Capacity)
                        LogInput = [row[0].replace(':', ''), Charge, 'Charged', row[1], Demand, str((float(CurDemand) + Capacity))]
                        Log_Writer.writerow(LogInput)
                        break
                    
                    else:
                        #Battery Does not need charging
                        PrevDemand = float(CurDemand)
                        PrevActualDemand = float(Demand)
                        LogInput = [row[0].replace(':', ''), Charge, 'No Need To Charge', row[1], Demand, CurDemand]
                        Log_Writer.writerow(LogInput)
                        break
                
                elif float(data) <= CutIn:
                    #Grid Needs Battery To Cut In
                    if Charge > MinCharge:
                        #Battery Has Sufficent Capacity to discharge
                        Charge -= IntervalCap
                        PrevDemand = (float(CurDemand) - Capacity)
                        PrevActualDemand = float(Demand)
                        LogInput = [row[0].replace(':', ''), Charge, 'Discharged', row[1], Demand, str((float(CurDemand) - Capacity))]
                        Log_Writer.writerow(LogInput)
                        break
                    else:
                        #Battery Cirically low, cannot discharge
                        PrevDemand = float(CurDemand)
                        PrevActualDemand = float(Demand)
                        LogInput = [row[0].replace(':', ''), Charge, 'Critically Low', row[1], Demand, CurDemand]
                        Log_Writer.writerow(LogInput)
                        break
                else:
                    #No Action Required
                    PrevDemand = float(CurDemand)
                    PrevActualDemand = float(Demand)
                    LogInput = [row[0].replace(':', ''), Charge, 'Did Nothing', row[1], Demand, CurDemand]
                    Log_Writer.writerow(LogInput)
                    break

At Full Stack Energy, we simply love to deep dive into these sorts of projects.  It's where we excel and where we add most value to our clients.  Contact us today if you have an energy project you need some help with, we would be delighted to get involved.

 

 

Contact us