Optimising EV Charging for Carbon Using Go
Schedule your EV charging when the grid is cleanest using a simple optimisation algorithm written in Go.

Electric vehicles are a crucial part of decarbonising transport, but charging them when the electricity grid is cleanest makes them even greener. In this post, we’ll walk through a simple algorithm written in Go that selects the lowest carbon intensity time slots to meet a given energy target.
This is a great starting point for building a smart EV charging system.
What We’re Building
We want to charge an EV during the lowest carbon intensity periods in a given time window, using 30-minute charging slots.
Here’s what the algorithm does:
- Takes a start and end time
- Generates a list of 30-minute charging slots
- Assigns a carbon intensity to each slot (mocked here)
- Sorts the slots by lowest carbon intensity
- Selects the greenest slots until the energy target is met
Simplifying Assumptions
- Each time slot is exactly 30 minutes
- Charging power is constant (e.g. 7.4 kW)
- Each slot provides the same amount of energy (3.7 kWh)
INFO
In reality, slot durations and charging rates may vary, and energy per slot would need to be calculated dynamically. This example keeps it simple to demonstrate the core logic.
The Algorithm in Go
Step 1: Generate 30-Minute Time Slots
func generateTimeSlots(start, end time.Time) []time.Time {
var slots []time.Time
for t := start; !t.After(end); t = t.Add(30 * time.Minute) {
slots = append(slots, t)
}
return slots
}
Step 2: Assign Carbon Intensity
func mockCarbonIntensity(t time.Time) float64 {
// Simulates daily carbon intensity curve
return 100 + 50*math.Sin(float64(t.Hour())/24*2*math.Pi)
}
Step 3: Sort by Cleanest First
type Slot struct {
Time time.Time
CarbonIntensity float64
}
func getGreenestSlots(times []time.Time) []Slot {
var slots []Slot
for _, t := range times {
slots = append(slots, Slot{
Time: t,
CarbonIntensity: mockCarbonIntensity(t),
})
}
sort.Slice(slots, func(i, j int) bool {
return slots[i].CarbonIntensity < slots[j].CarbonIntensity
})
return slots
}
Step 4: Select Cleanest Slots Until Target Met
func optimiseCharging(slots []Slot, energyTarget, energyPerSlot float64) []Slot {
var selected []Slot
accumulated := 0.0
for _, slot := range slots {
if accumulated >= energyTarget {
break
}
selected = append(selected, slot)
accumulated += energyPerSlot
}
return selected
}
Step 5: Main Function
func main() {
start := time.Date(2025, 7, 10, 18, 0, 0, 0, time.UTC)
end := time.Date(2025, 7, 11, 8, 0, 0, 0, time.UTC)
energyTarget := 20.0 // kWh
energyPerSlot := 3.7 // kWh per 30 mins
times := generateTimeSlots(start, end)
sorted := getGreenestSlots(times)
plan := optimiseCharging(sorted, energyTarget, energyPerSlot)
fmt.Println("Recommended charging slots:")
for _, slot := range plan {
fmt.Printf("%s – %.2f gCO₂/kWh\n", slot.Time.Format("15:04"), slot.CarbonIntensity)
}
}
Sample Output
Recommended charging slots:
02:30 – 71.22 gCO₂/kWh
03:00 – 72.15 gCO₂/kWh
03:30 – 73.92 gCO₂/kWh
...
Next Steps
This is a simple prototype. In a real-world implementation, you’d likely:
- Use real-time carbon intensity data (e.g. from carbon-intensity API)
- Adjust energy per slot based on charger efficiency or dynamic power levels
- Respect constraints like max charging sessions, battery SoC, or tariffs
TIP
This algorithm can also be extended to optimise fleets, support demand shifting, or integrate with home energy management systems.
Summary
By choosing the greenest times to charge an EV, we can reduce emissions without sacrificing convenience. With just a few lines of Go, we’ve built a simple yet effective optimiser that can help make smarter energy decisions.
If you’re building a system like this—or want to integrate green charging logic into your platform—we can help.
Reach out to discuss how we can support your next energy optimisation project.