@@ -219,87 +219,94 @@ CHIP_ERROR EVSEManufacturer::ComputeChargingSchedule()
219
219
addedEnergy_mWh.SetNull ();
220
220
startTime_epoch_s.SetNull (); // If we FindNextTarget this will be computed below and set to a non null value
221
221
222
- uint8_t searchDay = 0 ;
223
- while (searchDay < 2 )
222
+ /* We can only compute charging schedules if the EV is plugged in and the charging is enabled
223
+ * so we know the charging current - i.e. can get the max power, and therefore can calculate
224
+ * the charging duration and hence start time
225
+ */
226
+ if (dg->IsEvsePluggedIn () && dg->GetSupplyState () == SupplyStateEnum::kChargingEnabled )
224
227
{
225
- err = FindNextTarget (dayOfWeekMap, minutesPastMidnightNow_m, targetTimeMinutesPastMidnight_m, targetSoC, addedEnergy_mWh,
226
- (searchDay != 0 ));
227
- if (err == CHIP_ERROR_NOT_FOUND)
228
+ uint8_t searchDay = 0 ;
229
+ while (searchDay < 2 )
228
230
{
229
- // We didn't find one for today, try tomorrow
230
- searchDay++;
231
- dayOfWeekMap = (dayOfWeekMap << 1 ) & 0x7f ;
232
- if (dayOfWeekMap == 0x00 )
231
+ err = FindNextTarget (dayOfWeekMap, minutesPastMidnightNow_m, targetTimeMinutesPastMidnight_m, targetSoC,
232
+ addedEnergy_mWh, (searchDay != 0 ));
233
+ if (err == CHIP_ERROR_NOT_FOUND)
233
234
{
234
- dayOfWeekMap = 0x01 ; // Must be Saturday and shifted off, so set it to Sunday
235
+ // We didn't find one for today, try tomorrow
236
+ searchDay++;
237
+ dayOfWeekMap = (dayOfWeekMap << 1 ) & 0x7f ;
238
+ if (dayOfWeekMap == 0x00 )
239
+ {
240
+ dayOfWeekMap = 0x01 ; // Must be Saturday and shifted off, so set it to Sunday
241
+ }
235
242
}
236
- }
237
- else
238
- {
239
- break ; // We found a target or we error'd out for some other reason
240
- }
241
- }
242
-
243
- if (err == CHIP_NO_ERROR && dg->IsEvsePluggedIn () && dg->GetSupplyState () == SupplyStateEnum::kChargingEnabled )
244
- {
245
- /* Set the target Time in epoch_s format*/
246
- tempTargetTime_epoch_s =
247
- ((now_epoch_s / 60 ) + targetTimeMinutesPastMidnight_m + (searchDay * 1440 ) - minutesPastMidnightNow_m) * 60 ;
248
- targetTime_epoch_s.SetNonNull (tempTargetTime_epoch_s);
249
-
250
- if (!targetSoC.IsNull ())
251
- {
252
- if (targetSoC.Value () != 100 )
243
+ else
253
244
{
254
- ChipLogError (AppServer, " EVSE WARNING: TargetSoC is not 100%% and we don't know the EV SoC! " );
245
+ break ; // We found a target or we error'd out for some other reason
255
246
}
256
- // We don't know the Vehicle SoC so we must charge now
257
- // TODO make this use the SoC featureMap to determine if this is an error
258
- startTime_epoch_s.SetNonNull (now_epoch_s);
259
247
}
260
- else
248
+
249
+ if (err == CHIP_NO_ERROR)
261
250
{
262
- // We expect to use AddedEnergy to determine the charging start time
263
- if (addedEnergy_mWh.IsNull ())
251
+ /* Set the target Time in epoch_s format*/
252
+ tempTargetTime_epoch_s =
253
+ ((now_epoch_s / 60 ) + targetTimeMinutesPastMidnight_m + (searchDay * 1440 ) - minutesPastMidnightNow_m) * 60 ;
254
+ targetTime_epoch_s.SetNonNull (tempTargetTime_epoch_s);
255
+
256
+ if (!targetSoC.IsNull ())
264
257
{
265
- ChipLogError (AppServer, " EVSE ERROR: Neither TargetSoC or AddedEnergy has been provided" );
266
- return CHIP_ERROR_INTERNAL;
258
+ if (targetSoC.Value () != 100 )
259
+ {
260
+ ChipLogError (AppServer, " EVSE WARNING: TargetSoC is not 100%% and we don't know the EV SoC!" );
261
+ }
262
+ // We don't know the Vehicle SoC so we must charge now
263
+ // TODO make this use the SoC featureMap to determine if this is an error
264
+ startTime_epoch_s.SetNonNull (now_epoch_s);
267
265
}
268
- // Simple optimizer - assume a flat tariff throughout the day
269
- // Compute power from nominal voltage and maxChargingRate
270
- // GetMaximumChargeCurrent returns mA, but to help avoid overflow
271
- // We use V (not mV) and compute power to the nearest Watt
272
- power_W = static_cast <uint32_t >((230 * dg->GetMaximumChargeCurrent ()) /
273
- 1000 ); // TODO don't use 230V - not all markets will use that
274
- if (power_W == 0 )
266
+ else
275
267
{
276
- ChipLogError (AppServer, " EVSE Error: MaxCurrent = 0Amp - Can't schedule charging" );
277
- return CHIP_ERROR_INTERNAL;
278
- }
268
+ // We expect to use AddedEnergy to determine the charging start time
269
+ if (addedEnergy_mWh.IsNull ())
270
+ {
271
+ ChipLogError (AppServer, " EVSE ERROR: Neither TargetSoC or AddedEnergy has been provided" );
272
+ return CHIP_ERROR_INTERNAL;
273
+ }
274
+ // Simple optimizer - assume a flat tariff throughout the day
275
+ // Compute power from nominal voltage and maxChargingRate
276
+ // GetMaximumChargeCurrent returns mA, but to help avoid overflow
277
+ // We use V (not mV) and compute power to the nearest Watt
278
+ power_W = static_cast <uint32_t >((230 * dg->GetMaximumChargeCurrent ()) /
279
+ 1000 ); // TODO don't use 230V - not all markets will use that
280
+ if (power_W == 0 )
281
+ {
282
+ ChipLogError (AppServer, " EVSE Error: MaxCurrent = 0Amp - Can't schedule charging" );
283
+ return CHIP_ERROR_INTERNAL;
284
+ }
279
285
280
- // Time to charge(seconds) = (3600 * Energy(mWh) / Power(W)) / 1000
281
- // to avoid using floats we multiply by 36 and then divide by 10 (instead of x3600 and dividing by 1000)
282
- chargingDuration_s = static_cast <uint32_t >(((addedEnergy_mWh.Value () / power_W) * 36 ) / 10 );
286
+ // Time to charge(seconds) = (3600 * Energy(mWh) / Power(W)) / 1000
287
+ // to avoid using floats we multiply by 36 and then divide by 10 (instead of x3600 and dividing by 1000)
288
+ chargingDuration_s = static_cast <uint32_t >(((addedEnergy_mWh.Value () / power_W) * 36 ) / 10 );
283
289
284
- // Add in 15 minutes leeway to account for slow starting vehicles
285
- // that need to condition the battery or if it is cold etc
286
- chargingDuration_s += (15 * 60 );
290
+ // Add in 15 minutes leeway to account for slow starting vehicles
291
+ // that need to condition the battery or if it is cold etc
292
+ chargingDuration_s += (15 * 60 );
287
293
288
- // A price optimizer can look for cheapest time of day
289
- // However for now we'll start charging as late as possible
290
- tempStartTime_epoch_s = tempTargetTime_epoch_s - chargingDuration_s;
294
+ // A price optimizer can look for cheapest time of day
295
+ // However for now we'll start charging as late as possible
296
+ tempStartTime_epoch_s = tempTargetTime_epoch_s - chargingDuration_s;
291
297
292
- if (tempStartTime_epoch_s < now_epoch_s)
293
- {
294
- // we need to turn on the EVSE now - it won't have enough time to reach the target
295
- startTime_epoch_s.SetNonNull (now_epoch_s);
296
- // TODO call function to turn on the EV
297
- }
298
- else
299
- {
300
- // we turn off the EVSE for now
301
- startTime_epoch_s.SetNonNull (tempStartTime_epoch_s);
302
- // TODO have a periodic timer which checks if we should turn on the charger now
298
+ if (tempStartTime_epoch_s < now_epoch_s)
299
+ {
300
+ // we need to turn on the EVSE now - it won't have enough time to reach the target
301
+ startTime_epoch_s.SetNonNull (now_epoch_s);
302
+ // TODO call function to turn on the EV
303
+ }
304
+ else
305
+ {
306
+ // we turn off the EVSE for now
307
+ startTime_epoch_s.SetNonNull (tempStartTime_epoch_s);
308
+ // TODO have a periodic timer which checks if we should turn on the charger now
309
+ }
303
310
}
304
311
}
305
312
}
0 commit comments