CHAdeMO
Loading...
Searching...
No Matches
chademo_se.h
Go to the documentation of this file.
1
41
42#ifndef CHADEMO_SE_DEFINITION_HEADER_GUARD
43#define CHADEMO_SE_DEFINITION_HEADER_GUARD
44
45#include <stdbool.h>
46#include <stdint.h>
47
48/* Skip certain definitions if EV header is already included */
49#if !defined(CHADEMO_EV_DEFINITION_HEADER_GUARD)
50/******************************************************************************
51 * _CHADEMO_XX DEFINITIONS (COMMON FOR EV AND SE)
52 *****************************************************************************/
55 uint32_t id;
56 uint8_t len;
57 uint8_t data[8];
58};
59
61#define chademo_se_can_frame chademo_xx_can_frame
62
64#define chademo_ev_can_frame chademo_xx_can_frame
65
66/******************************************************************************
67 * _CHADEMO_EV DEFINITIONS
68 *****************************************************************************/
70enum _chademo_ev_can_frame_id {
71 _CHADEMO_EV_CAN_FRAME_ID_H100 = 0x100u,
72 _CHADEMO_EV_CAN_FRAME_ID_H101 = 0x101u,
73 _CHADEMO_EV_CAN_FRAME_ID_H102 = 0x102u
74};
75
76enum _chademo_ev_field_h100_protocol_number {
78 _CHADEMO_EV_FIELD_H109_CONTROL_PROTOCOL_NUMBER_0 = 0u,
79
81 _CHADEMO_EV_FIELD_H109_CONTROL_PROTOCOL_NUMBER_1 = 1u,
82
84 _CHADEMO_EV_FIELD_H109_CONTROL_PROTOCOL_NUMBER_2 = 2u
85};
86
87enum _chademo_ev_field_h102_fault {
89 _CHADEMO_EV_FIELD_H102_FAULT_BATTERY_OVERVOLTAGE = 1u,
90
92 _CHADEMO_EV_FIELD_H102_FAULT_BATTERY_UNDERVOLTAGE = 2u,
93
95 _CHADEMO_EV_FIELD_H102_FAULT_BATTERY_CURRENT_DEVIATION = 4u,
96
98 _CHADEMO_EV_FIELD_H102_FAULT_BATTERY_HIGH_TEMPERATURE = 8u,
99
101 _CHADEMO_EV_FIELD_H102_FAULT_BATTERY_VOLTAGE_DEVIATION = 16u
102};
103
104enum _chademo_ev_field_h102_status {
106 _CHADEMO_EV_FIELD_H102_STATUS_CHARGING_ENABLED = 1u,
107
109 _CHADEMO_EV_FIELD_H102_STATUS_SHIFT_POSITION_NOT_PARKED = 2u,
110
112 _CHADEMO_EV_FIELD_H102_STATUS_CHARGING_SYS_FAULT = 4u,
113
116 _CHADEMO_EV_FIELD_H102_STATUS_CONTACTOR_OPEN = 8u,
117
119 _CHADEMO_EV_FIELD_H102_STATUS_NORMAL_STOP_REQUEST_BEFORE_CHARGING = 16u
120};
121
123struct _chademo_ev_h100 {
124 /* uint8_t reserved; */
125 /* uint8_t reserved; */
126 /* uint8_t reserved; */
127 /* uint8_t reserved; */
128 uint16_t max_battery_voltage_V;
129 uint8_t charged_rate_ref_const; /* 1% / bit, 100% (fixed) = 0x64 */
130 /* uint8_t reserved; */
131};
132
133struct _chademo_ev_h101 {
134 /* uint8_t reserved; */
135 uint8_t max_charge_time_10s;
136 uint8_t max_charge_time_60s;
137 uint8_t est_charge_time_60s;
138 /* uint8_t reserved; */
139 uint16_t total_cap_of_battery_100wh; /* 0.1 kWh/bit, 0–6553.5 kWh */
140};
141
142struct _chademo_ev_h102 {
143 uint8_t control_protocol_number;
144 uint16_t target_battery_voltage;
145 uint8_t charging_current_request;
146 uint8_t fault;
147 uint8_t status;
148 uint8_t charged_rate;
149 /* uint8_t reserved; */
150};
151
152/******************************************************************************
153 * _CHADEMO_SE DEFINITIONS
154 *****************************************************************************/
156enum _chademo_se_can_frame_id {
157 _CHADEMO_SE_CAN_FRAME_ID_H108 = 0x108u,
158 _CHADEMO_SE_CAN_FRAME_ID_H109 = 0x109u
159};
160
162enum _chademo_se_field_h109_protocol_number {
164 _CHADEMO_SE_FIELD_H109_CONTROL_PROTOCOL_NUMBER_0 = 0u,
165
167 _CHADEMO_SE_FIELD_H109_CONTROL_PROTOCOL_NUMBER_1 = 1u,
168
170 _CHADEMO_SE_FIELD_H109_CONTROL_PROTOCOL_NUMBER_2 = 2u
171};
172
174enum _chademo_se_field_h109_status {
176 _CHADEMO_SE_FIELD_H109_STATUS_CHARGING = 1u,
177
179 _CHADEMO_SE_FIELD_H109_STATUS_CHARGER_MALFUNCTION = 2u,
180
182 _CHADEMO_SE_FIELD_H109_STATUS_CONNECTOR_LOCKED = 4u,
183
185 _CHADEMO_SE_FIELD_H109_STATUS_INCOMPATIBLE = 8u,
186
188 _CHADEMO_SE_FIELD_H109_STATUS_SYS_MALFUNCTION = 16u,
189
192 _CHADEMO_SE_FIELD_H109_STATUS_STOP_CONTROL = 32u
193};
194
196struct _chademo_se_h108 {
197 bool welding_detection_support;
198 uint16_t avail_output_voltage_V;
199 uint8_t avail_output_current_A;
200 uint16_t threshold_voltage_V;
201 /* uint8_t reserved; */
202 /* uint8_t reserved; */
203};
204
206struct _chademo_se_h109 {
207 /* Transported via h109 */
208 uint8_t control_protocol_number;
209 uint16_t present_output_voltage_V;
210 uint8_t present_output_current_A;
211 /* uint8_t _reserved; */
212 uint8_t status;
213 uint8_t remaining_charge_time_10s; /* 10s/bit */
214 uint8_t remaining_charge_time_60s; /* 60s/bit */
215};
216#endif /* !defined(CHADEMO_EV_HEADER__) */
217
218/******************************************************************************
219 * CHADEMO_SE VIRTUAL CAN2.0 TX ROUTINE
220 *****************************************************************************/
221enum _chademo_se_vcan_tx_state {
222 _CHADEMO_SE_VCAN_TX_STATE_IDLE,
223 _CHADEMO_SE_VCAN_TX_STATE_TRANSMISSION,
224 _CHADEMO_SE_VCAN_TX_STATE_DELAY
225};
226
228struct _chademo_se_vcan_tx {
229 uint8_t state;
230
231 /* TX-side messages */
232 struct _chademo_se_h108 h108;
233 struct _chademo_se_h109 h109;
234
236 struct chademo_se_can_frame frames[2];
237
239 uint8_t count;
240
242 uint32_t timer_ms;
243};
244
249void _chademo_se_vcan_tx_init(struct _chademo_se_vcan_tx *self)
250{
251 self->state = _CHADEMO_SE_VCAN_TX_STATE_IDLE;
252
253 self->h108.welding_detection_support = false;
254 self->h108.avail_output_voltage_V = 0u;
255 self->h108.avail_output_current_A = 0u;
256 self->h108.threshold_voltage_V = 0u;
257
258 self->h109.control_protocol_number = 0u;
259 self->h109.present_output_voltage_V = 0u;
260 self->h109.present_output_current_A = 0u;
261 self->h109.status = 0u;
262 self->h109.remaining_charge_time_10s = 0xFFu;
263 self->h109.remaining_charge_time_60s = 0xFFu;
264
265 /* struct chademo_se_can_frame frames[2]; */
266
267 self->count = 0u;
268 self->timer_ms = 0u;
269}
270
271void _chademo_se_vcan_tx_pack_frames(struct _chademo_se_vcan_tx *self)
272{
273 struct chademo_se_can_frame *f;
274
275 /* We transmit exactly two frames. */
276 self->count = 2u;
277
278 f = &self->frames[0];
279 f->id = _CHADEMO_SE_CAN_FRAME_ID_H108;
280 f->len = 8u;
281 f->data[0] = self->h108.welding_detection_support;
282 f->data[1] = (self->h108.avail_output_voltage_V & 0x00FFu) >> 0u;
283 f->data[2] = (self->h108.avail_output_voltage_V & 0xFF00u) >> 8u;
284 f->data[3] = self->h108.avail_output_current_A;
285 f->data[4] = (self->h108.threshold_voltage_V & 0x00FFu) >> 0u;
286 f->data[5] = (self->h108.threshold_voltage_V & 0xFF00u) >> 8u;
287 f->data[6] = 0x00u;
288 f->data[7] = 0x00u;
289
290 f = &self->frames[1];
291 f->id = _CHADEMO_SE_CAN_FRAME_ID_H109;
292 f->len = 8u;
293 f->data[0] = self->h109.control_protocol_number;
294 f->data[1] = (self->h109.present_output_voltage_V & 0x00FFu) >> 0u;
295 f->data[2] = (self->h109.present_output_voltage_V & 0xFF00u) >> 8u;
296 f->data[3] = self->h109.present_output_current_A;
297 f->data[4] = 0x00u;
298 f->data[5] = self->h109.status;
299 f->data[6] = self->h109.remaining_charge_time_10s;
300 f->data[7] = self->h109.remaining_charge_time_60s;
301}
302
303void _chademo_se_vcan_tx_start(struct _chademo_se_vcan_tx *self)
304{
305 _chademo_se_vcan_tx_init(self);
306
307 self->state = _CHADEMO_SE_VCAN_TX_STATE_TRANSMISSION;
308}
309
310void _chademo_se_vcan_tx_stop(struct _chademo_se_vcan_tx *self)
311{
312 _chademo_se_vcan_tx_init(self);
313
314 self->state = _CHADEMO_SE_VCAN_TX_STATE_IDLE;
315}
316
317void _chademo_se_vcan_tx_step(struct _chademo_se_vcan_tx *self,
318 uint32_t delta_time_ms)
319{
320 /* TODO check for untransmitted frames */
321
322 switch (self->state) {
323 case _CHADEMO_SE_VCAN_TX_STATE_TRANSMISSION:
324 _chademo_se_vcan_tx_pack_frames(self);
325
326 /* _CHADEMO_SE_VCAN_TX_STATE_DELAY INIT */
327 self->state = _CHADEMO_SE_VCAN_TX_STATE_DELAY;
328 self->timer_ms = 0u;
329 break;
330
331 case _CHADEMO_SE_VCAN_TX_STATE_DELAY:
332 self->timer_ms += delta_time_ms;
333
334 /* 100ms delay between messages */
335 if (self->timer_ms < 100u) {
336 break;
337 }
338
339 /* _CHADEMO_SE_VCAN_TX_STATE_TRANSMISSION INIT */
340 self->state = _CHADEMO_SE_VCAN_TX_STATE_TRANSMISSION;
341 break;
342
343 case _CHADEMO_SE_VCAN_TX_STATE_IDLE:
344 /* Do nothing here */
345 break;
346
347 default:
348 /* Something really gone wrong here
349 * (probably memory corruption or worse)
350 * We must immediately go into termination and never
351 * start again until fault is diagnosed properly.
352 *
353 * TODO */
354 break;
355 }
356}
357
358/******************************************************************************
359 * CHADEMO_SE VIRTUAL CAN2.0 RX ROUTINE
360 *****************************************************************************/
361enum _chademo_se_vcan_rx_state {
362 _CHADEMO_SE_VCAN_RX_STATE_IDLE,
363 _CHADEMO_SE_VCAN_RX_STATE_LISTEN
364};
365
367struct _chademo_se_vcan_rx {
368 uint8_t state;
369
370 struct _chademo_ev_h100 h100;
371 struct _chademo_ev_h101 h101;
372 struct _chademo_ev_h102 h102;
373
375 uint32_t timer_ms;
376
378 uint8_t recv_flags;
379
381 bool has_frames;
382};
383
388void _chademo_se_vcan_rx_init(struct _chademo_se_vcan_rx *self)
389{
390 self->state = _CHADEMO_SE_VCAN_RX_STATE_IDLE;
391
392 self->h100.max_battery_voltage_V = 0x00u;
393 self->h100.charged_rate_ref_const = 0x00u;
394
395 self->h101.max_charge_time_10s = 0x00u;
396 self->h101.max_charge_time_60s = 0x00u;
397 self->h101.est_charge_time_60s = 0x00u;
398 self->h101.total_cap_of_battery_100wh = 0x00u;
399
400 self->h102.control_protocol_number = 0x00u;
401 self->h102.target_battery_voltage = 0x00u;
402 self->h102.charging_current_request = 0x00u;
403 self->h102.fault = 0x00u;
404 self->h102.status = 0x00u;
405 self->h102.charged_rate = 0x00u;
406
407 /* TODO implement properly */
408 self->timer_ms = 0u;
409 self->recv_flags = 0u;
410 self->has_frames = false;
411}
412
413void _chademo_se_vcan_rx_unpack_frame(struct _chademo_se_vcan_rx *self,
414 struct chademo_se_can_frame *f)
415{
416 bool valid_frame = true;
417
418 switch (f->id) {
419 case _CHADEMO_EV_CAN_FRAME_ID_H100:
420 self->h100.max_battery_voltage_V = f->data[4] << 0u;
421 self->h100.max_battery_voltage_V |= f->data[5] << 8u;
422
423 self->h100.charged_rate_ref_const = f->data[6];
424
425 self->recv_flags |= (1u << 0u);
426 break;
427
428 case _CHADEMO_EV_CAN_FRAME_ID_H101:
429 self->h101.max_charge_time_10s = f->data[1];
430 self->h101.max_charge_time_60s = f->data[2];
431 self->h101.est_charge_time_60s = f->data[3];
432
433 self->h101.total_cap_of_battery_100wh = f->data[5] << 0u;
434 self->h101.total_cap_of_battery_100wh |= f->data[6] << 8u;
435
436 self->recv_flags |= (1u << 1u);
437 break;
438
439 case _CHADEMO_EV_CAN_FRAME_ID_H102:
440 self->h102.control_protocol_number = f->data[0];
441 self->h102.target_battery_voltage = f->data[1] << 0u;
442 self->h102.target_battery_voltage |= f->data[2] << 8u;
443 self->h102.charging_current_request = f->data[3];
444 self->h102.fault = f->data[4];
445 self->h102.status = f->data[5];
446 self->h102.charged_rate = f->data[6];
447
448 self->recv_flags |= (1u << 2u);
449 break;
450
451 default:
452 valid_frame = false;
453 break;
454 }
455
456 /* TODO reset timer only if all frames have been get */
457 if (valid_frame && (self->recv_flags == ((1u << 3u) - 1u))) {
458 self->has_frames = true;
459 self->timer_ms = 0u;
460 }
461}
462
463void _chademo_se_vcan_rx_start(struct _chademo_se_vcan_rx *self)
464{
465 /* We won't assume a shit, just reset all the time. */
466 _chademo_se_vcan_rx_init(self);
467
468 self->state = _CHADEMO_SE_VCAN_RX_STATE_LISTEN;
469}
470
471void _chademo_se_vcan_rx_stop(struct _chademo_se_vcan_rx *self)
472{
473 /* We won't assume a shit, just reset all the time. */
474 _chademo_se_vcan_rx_init(self);
475
476 self->state = _CHADEMO_SE_VCAN_RX_STATE_IDLE;
477}
478
479void _chademo_se_vcan_rx_step(struct _chademo_se_vcan_rx *self,
480 uint32_t delta_time_ms)
481{
482 (void)self;
483 (void)delta_time_ms;
484 /* TODO check timeouts */
485 /* TODO check errors */
486}
487
488/******************************************************************************
489 * CHADEMO_SE VIRTUAL SENSORS (VOLTAGE, CURRENT, LEAKAGE, ETC)
490 *****************************************************************************/
491/* R-SW-036
492 The charger shall be equipped with a means of measuring
493 charging cable voltage in order to judge whether voltage may be applied to
494 the vehicle circuit and charging connector may be removed. */
499 uint16_t out_terminals_voltage_V; /* TODO rename to cable voltage */
500};
501
502void _chademo_se_vsensors_init(struct chademo_se_vsensors *self)
503{
504 /* Assume maximum voltage, until other value been providen */
505 self->out_terminals_voltage_V = 0xFFFF;
506}
507
508/******************************************************************************
509 * CHADEMO_SE POWER SUPPLY UNIT CONTROLLER (controls external PSU)
510 *****************************************************************************/
528
530enum _chademo_se_psuctl_state {
531 _CHADEMO_SE_PSUCTL_STATE_IDLE,
532 _CHADEMO_SE_PSUCTL_STATE_CONFIG,
533 _CHADEMO_SE_PSUCTL_STATE_BOOT,
534 _CHADEMO_SE_PSUCTL_STATE_RUNNING,
535 _CHADEMO_SE_PSUCTL_STATE_SHUTDOWN
536};
537
540 CHADEMO_SE_PSUCTL_FLAGS_FAULT_OVERVOLTAGE = 1u,
541 CHADEMO_SE_PSUCTL_FLAGS_FAULT_OVERCURRENT = 2u,
542 CHADEMO_SE_PSUCTL_FLAGS_FAULT_OVERTEMP = 4u,
543 CHADEMO_SE_PSUCTL_FLAGS_FAULT_MALFUNCTION = 8u,
544 CHADEMO_SE_PSUCTL_FLAGS_FAULT_OTHER = 16u,
545
548};
549
560
569
571struct _chademo_se_psuctl {
572 uint8_t state;
573
574 struct chademo_se_psuctl_inputs inputs;
575 struct chademo_se_psuctl_outputs outputs;
576};
577
578void _chademo_se_psuctl_init(struct _chademo_se_psuctl *self)
579{
580 self->state = _CHADEMO_SE_PSUCTL_STATE_IDLE;
581
582 self->outputs.set_voltage_dc_V = 0u;
583 self->outputs.set_current_dc_A = 0u;
584
586 self->inputs.voltage_dc_V = 0xFFFF;
587 self->inputs.current_dc_A = 0xFF;
588
590 self->inputs.flags_fault = CHADEMO_SE_PSUCTL_FLAGS_FAULT_API;
591}
592
593void _chademo_se_psuctl_start(struct _chademo_se_psuctl *self)
594{
595 _chademo_se_psuctl_init(self);
596
597 self->state = _CHADEMO_SE_PSUCTL_STATE_CONFIG;
598}
599
600void _chademo_se_psuctl_stop(struct _chademo_se_psuctl *self)
601{
602 if ((self->state > (uint8_t)_CHADEMO_SE_PSUCTL_STATE_IDLE) &&
603 (self->state < (uint8_t)_CHADEMO_SE_PSUCTL_STATE_SHUTDOWN)) {
604 self->state = _CHADEMO_SE_PSUCTL_STATE_SHUTDOWN;
605 }
606}
607
608void _chademo_se_psuctl_detect_faults(struct _chademo_se_psuctl *self)
609{
610 if (self->inputs.flags_fault > 0u) {
611 self->state = _CHADEMO_SE_PSUCTL_STATE_SHUTDOWN;
612 self->outputs.event =
614 }
615}
616
617void _chademo_se_psuctl_step(struct _chademo_se_psuctl *self,
618 uint32_t delta_time_ms)
619{
620 (void)delta_time_ms;
621
622 switch (self->state) {
623 case _CHADEMO_SE_PSUCTL_STATE_IDLE:
624 break;
625
626 case _CHADEMO_SE_PSUCTL_STATE_CONFIG:
627 self->outputs.event =
629
630 /* TODO check inputs */
631
632 /* _CHADEMO_SE_PSUCTL_STATE_BOOT INIT */
633 self->state = _CHADEMO_SE_PSUCTL_STATE_BOOT;
634 break;
635
636 case _CHADEMO_SE_PSUCTL_STATE_BOOT:
637 _chademo_se_psuctl_detect_faults(self);
638
639 /* Wait user to acknowledge full readiness */
640 if (self->inputs.ready_for_operation) {
641 break;
642 }
643
644 self->outputs.event =
646
647 /* _CHADEMO_SE_PSUCTL_STATE_RUNNING INIT */
648 self->state = _CHADEMO_SE_PSUCTL_STATE_RUNNING;
649 break;
650
651 case _CHADEMO_SE_PSUCTL_STATE_RUNNING:
652 _chademo_se_psuctl_detect_faults(self);
653 break;
654
655 case _CHADEMO_SE_PSUCTL_STATE_SHUTDOWN:
656 self->outputs.event =
658
659 /* _CHADEMO_SE_PSUCTL_STATE_IDLE INIT */
660 self->state = _CHADEMO_SE_PSUCTL_STATE_IDLE;
661 break;
662
663 default:
664 /* Something really gone wrong here
665 * (probably memory corruption or worse)
666 * We must immediately go into termination and never
667 * start again until fault is diagnosed properly.
668 *
669 * TODO */
670 break;
671 }
672}
673
674/******************************************************************************
675 * CHADEMO_SE VIRTUAL GPIO
676 *****************************************************************************/
679struct _chademo_se_vgpio_in {
680 bool oc_j;
681
682 /* R-SW-021
683 * Not a part of main CHAdeMO circuit
684 * ( Colors: O - obligatory, R - recomended ): */
685 bool bt_emergency;
686 bool bt_start;
687 bool bt_stop;
688};
689
692struct _chademo_se_vgpio_out {
693 bool sw_d1;
694 bool sw_d2;
695};
696
697/* R-SW-023
698 * Dedicated control signal lines shall be used to transmit signals
699 * concerning the start and termination of Charging. */
702 struct _chademo_se_vgpio_in in;
703 struct _chademo_se_vgpio_out out;
704};
705
706void _chademo_se_vgpio_init(struct chademo_se_vgpio *self)
707{
708 self->in.oc_j = false;
709
710 self->in.bt_emergency = false;
711 self->in.bt_start = false;
712 self->in.bt_stop = false;
713
714 self->out.sw_d1 = false;
715 self->out.sw_d2 = false;
716}
717
718/******************************************************************************
719 * CHADEMO_SE MAIN INSTANCE
720 *****************************************************************************/
722enum _chademo_se_state_cf {
723 _CHADEMO_SE_STATE_CF_AWAIT_CHARGE_START_BUTTON,
724 _CHADEMO_SE_STATE_CF_TRANSMIT_CHARGE_START_SIGNAL,
725 _CHADEMO_SE_STATE_CF_AWAIT_CAN_RX_AND_START_TX_AFTER,
726 _CHADEMO_SE_STATE_CF_PROCESS_INFO_BEFORE_CHARGING,
727 _CHADEMO_SE_STATE_CF_LOCK_CHARHING_CONNECTOR,
728 _CHADEMO_SE_STATE_CF_CHECK_EV_CONTACTORS_ARE_OPEN,
729 _CHADEMO_SE_STATE_CF_INSULATION_TEST_ON_DC_CIRCUIT,
730 _CHADEMO_SE_STATE_CF_CHECK_TERMINATION_OF_INSULATION_TEST,
731 _CHADEMO_SE_STATE_CF_TRANSMIT_SIGNAL_OF_CHARGER_SETUP_COMPLETION,
732 _CHADEMO_SE_STATE_CF_START_CHARGING_CURRENT_OUTPUT
733};
734
737 CHADEMO_SE_EVENT_NONE,
738 CHADEMO_SE_EVENT_CHARGE_START_BUTTON_PRESSED,
739 CHADEMO_SE_EVENT_GOT_EV_INITIAL_PARAMS,
740 CHADEMO_SE_EVENT_INFO_BEFORE_CHARGING_IS_PROCESSED,
741 CHADEMO_SE_EVENT_VEHICLE_CHARGE_PERMISSION,
742 CHADEMO_SE_EVENT_EV_CONTACTORS_ARE_OPEN
743};
744
747 enum _chademo_se_state_cf _state_cf;
748
749 /* R-SW-013
750 * A data communications interface shall be used to transmit parameters
751 * required for charging control.
752 * The charger and vehicle shall exchange the parameters
753 * through the interface.*/
754 struct _chademo_se_vcan_tx _can_tx;
755 struct _chademo_se_vcan_rx _can_rx;
756
757 struct chademo_se_vsensors _sensors;
758 struct chademo_se_vgpio _gpio;
759 struct _chademo_se_psuctl _psuctl;
760};
761
762/******************************************************************************
763 * CHADEMO_SE MAIN INSTANCE PUBLIC METHODS
764 *****************************************************************************/
766void chademo_se_init(struct chademo_se *self)
767{
768 self->_state_cf = _CHADEMO_SE_STATE_CF_AWAIT_CHARGE_START_BUTTON;
769
770 _chademo_se_vcan_tx_init(&self->_can_tx);
771 _chademo_se_vcan_rx_init(&self->_can_rx);
772 _chademo_se_vsensors_init(&self->_sensors);
773 _chademo_se_vgpio_init(&self->_gpio);
774 _chademo_se_psuctl_init(&self->_psuctl);
775}
776
779 struct chademo_se_vgpio *dst)
780{
781 dst->in = self->_gpio.in;
782}
783
786 struct chademo_se_vgpio *src)
787{
788 self->_gpio.in = src->in;
789}
790
793 struct chademo_se_vgpio *dst)
794{
795 dst->out = self->_gpio.out;
796}
797
800 struct chademo_se_vsensors *src)
801{
802 self->_sensors = *src;
803}
804
807 struct chademo_se_psuctl_outputs *dst)
808{
809 *dst = self->_psuctl.outputs;
810}
811
816 struct chademo_se_can_frame *f)
817{
818 bool has_consumed_frame = false;
819
820 if (self->_can_rx.state == (uint8_t)_CHADEMO_SE_VCAN_RX_STATE_LISTEN) {
821 _chademo_se_vcan_rx_unpack_frame(&self->_can_rx, f);
822
823 has_consumed_frame = true;
824 }
825
826 return has_consumed_frame;
827}
828
833 struct chademo_se_can_frame *f)
834{
835 bool frame_available = false;
836
837 if (self->_can_tx.count > 0u) {
838 self->_can_tx.count--;
839
840 *f = self->_can_tx.frames[self->_can_tx.count];
841
842 frame_available = true;
843 }
844
845 return frame_available;
846}
847
850 uint32_t delta_time_ms)
851{
852 struct _chademo_se_vcan_tx *tx = &self->_can_tx;
853 struct _chademo_se_vcan_rx *rx = &self->_can_rx;
854
855 struct chademo_se_vsensors *sensors = &self->_sensors;
856 struct chademo_se_vgpio *gpio = &self->_gpio;
857
858 struct _chademo_se_psuctl *psuctl = &self->_psuctl;
859
860 enum chademo_se_event event = CHADEMO_SE_EVENT_NONE;
861
862 _chademo_se_vcan_rx_step(rx, delta_time_ms);
863
864 /* State machine reflecs chademo charger control flow precisely */
865 switch (self->_state_cf) {
866 /* "Charge start button" ON */
867 case _CHADEMO_SE_STATE_CF_AWAIT_CHARGE_START_BUTTON:
868 if (gpio->in.bt_start != true) {
869 break;
870 }
871
872 event = CHADEMO_SE_EVENT_CHARGE_START_BUTTON_PRESSED;
873
874 /* _CHADEMO_SE_STATE_CF_TRANSMIT_CHARGE_START_SIGNAL INIT */
875 self->_state_cf =
876 _CHADEMO_SE_STATE_CF_TRANSMIT_CHARGE_START_SIGNAL;
877
878 /* We can start PSU to prepare for charging. */
879 _chademo_se_psuctl_start(psuctl);
880
881 break;
882
883 /* Transmit charge start signal */
884 case _CHADEMO_SE_STATE_CF_TRANSMIT_CHARGE_START_SIGNAL:
885 gpio->out.sw_d1 = true; /* CONNECTOR PIN: 5 */
886
887 /* _CHADEMO_SE_STATE_CF_AWAIT_CAN_RX_AND_START_TX_AFTER INIT */
888 self->_state_cf =
889 _CHADEMO_SE_STATE_CF_AWAIT_CAN_RX_AND_START_TX_AFTER;
890
891 _chademo_se_vcan_rx_start(rx);
892 break;
893
894 /* Receive initial vehicle CAN data and
895 transmit charger CAN data in return
896
897 R-SW-024
898 The charger and vehicle
899 shall exchange the parameters through the circuit. */
900 case _CHADEMO_SE_STATE_CF_AWAIT_CAN_RX_AND_START_TX_AFTER:
901 /* TODO timeout */
902
903 /* Await for all RX frames */
904 if (!rx->has_frames) {
905 break;
906 }
907
908 /* Charger params must be set by user after this event! */
909 event = CHADEMO_SE_EVENT_GOT_EV_INITIAL_PARAMS;
910
911 /* _CHADEMO_SE_STATE_CF_PROCESS_INFO_BEFORE_CHARGING INIT */
912 self->_state_cf =
913 _CHADEMO_SE_STATE_CF_PROCESS_INFO_BEFORE_CHARGING;
914
915 _chademo_se_vcan_tx_start(tx);
916
917 break;
918
919 /* Process the information for charge control
920 before charging (Battery compatibility, charging
921 time calculation etc.) */
922 case _CHADEMO_SE_STATE_CF_PROCESS_INFO_BEFORE_CHARGING:
923 /* See A.7.2.7.2 */
924
925 /* TODO more validation */
926
927 if ((rx->h100.max_battery_voltage_V >
928 tx->h108.avail_output_voltage_V)) {
929 /* TODO terminate */
930 }
931
932 /* TODO calculate approximate estimated charge time
933 * based on current and voltage demand and pack kwh */
934
935 event = CHADEMO_SE_EVENT_INFO_BEFORE_CHARGING_IS_PROCESSED;
936
937 /* _CHADEMO_SE_STATE_CF_LOCK_CHARHING_CONNECTOR INIT */
938 self->_state_cf = _CHADEMO_SE_STATE_CF_LOCK_CHARHING_CONNECTOR;
939
940 break;
941
942 /* Lock charging connector */
943 case _CHADEMO_SE_STATE_CF_LOCK_CHARHING_CONNECTOR:
944 /* Wait for vehicle readiness */
945 if (gpio->in.oc_j != true) { /* CONNECTOR PIN: 4 */
946 break;
947 }
948
949 event = CHADEMO_SE_EVENT_VEHICLE_CHARGE_PERMISSION;
950
951 /* _CHADEMO_SE_STATE_CF_CHECK_EV_CONTACTORS_ARE_OPEN INIT */
952 self->_state_cf =
953 _CHADEMO_SE_STATE_CF_CHECK_EV_CONTACTORS_ARE_OPEN;
954 break;
955
956 /* Check that EV contactors are surely opened
957 (Voltage on output terminals is less than 10V.) */
958 case _CHADEMO_SE_STATE_CF_CHECK_EV_CONTACTORS_ARE_OPEN:
959 if (sensors->out_terminals_voltage_V >= 10u) {
960 /* TODO terminate or wait ??? */
961 break;
962 }
963
964 event = CHADEMO_SE_EVENT_EV_CONTACTORS_ARE_OPEN;
965
966 /* _CHADEMO_SE_STATE_CF_INSULATION_TEST_ON_DC_CIRCUIT INIT */
967 self->_state_cf =
968 _CHADEMO_SE_STATE_CF_INSULATION_TEST_ON_DC_CIRCUIT;
969
970 break;
971
972 /* Insulation test on output DC circuit */
973 case _CHADEMO_SE_STATE_CF_INSULATION_TEST_ON_DC_CIRCUIT:
974 /* Insulation test is mostly transparent for the vehicle.
975 * We might skip this step for the future. */
976 /* TODO implement */
977
978 /* _CHADEMO_SE_STATE_CF_CHECK_TERMINATION_OF_INSULATION_TEST
979 * INIT */
980 self->_state_cf =
981 _CHADEMO_SE_STATE_CF_CHECK_TERMINATION_OF_INSULATION_TEST;
982 break;
983
984 /* Check the termination of insulation test
985 (Voltage on output terminals is less than 20V.) */
986 case _CHADEMO_SE_STATE_CF_CHECK_TERMINATION_OF_INSULATION_TEST:
987 if (sensors->out_terminals_voltage_V >= 20u) {
988 /* TODO terminate or wait ??? */
989 break;
990 }
991
992 /* _CHADEMO_SE_STATE_CF_TRANSMIT_SIGNAL_OF_CHARGER_SETUP_COMPLETION
993 * INIT */
994 self->_state_cf =
995 _CHADEMO_SE_STATE_CF_TRANSMIT_SIGNAL_OF_CHARGER_SETUP_COMPLETION;
996
997 break;
998
999 /* Transmit the signal of charger setup completion */
1000 case _CHADEMO_SE_STATE_CF_TRANSMIT_SIGNAL_OF_CHARGER_SETUP_COMPLETION:
1001 /* TODO TIMEOUT */
1002
1003 gpio->out.sw_d2 = true; /* CONNECTOR PIN: 10 */
1004
1005 /* Wait until voltage is more than 50V */
1006 if (sensors->out_terminals_voltage_V < 50u) {
1007 break;
1008 }
1009
1010 /* Try to equalize PSU voltage (if that's required) */
1011 psuctl->outputs.set_voltage_dc_V =
1012 sensors->out_terminals_voltage_V;
1013
1014 /* Break if PSU still booting, or... Whatever? */
1015 if (psuctl->state !=
1016 (uint8_t)_CHADEMO_SE_PSUCTL_STATE_RUNNING) {
1017 break;
1018 }
1019
1020 /* _CHADEMO_SE_STATE_CF_START_CHARGING_CURRENT_OUTPUT INIT */
1021 self->_state_cf =
1022 _CHADEMO_SE_STATE_CF_START_CHARGING_CURRENT_OUTPUT;
1023
1024 break;
1025
1026 /* Start charging current output */
1027 case _CHADEMO_SE_STATE_CF_START_CHARGING_CURRENT_OUTPUT:
1028 tx->h109.status &= _CHADEMO_SE_FIELD_H109_STATUS_STOP_CONTROL;
1029 tx->h109.status |= _CHADEMO_SE_FIELD_H109_STATUS_CHARGING;
1030
1031 /* TODO implement */
1032 break;
1033
1034 default:
1035 /* Something really gone wrong here
1036 * (probably memory corruption or worse)
1037 * We must immediately go into termination and never
1038 * start again until fault is diagnosed properly.
1039 *
1040 * TODO */
1041 break;
1042 }
1043
1044 _chademo_se_vcan_tx_step(tx, delta_time_ms);
1045
1046 return event;
1047}
1048
1049#endif /* CHADEMO_SE_DEFINITION_HEADER_GUARD */
chademo_se_psuctl_event
Definition chademo_se.h:512
@ CHADEMO_SE_PSUCTL_EVENT_PSU_CAN_BE_POWERED
Definition chademo_se.h:520
@ CHADEMO_SE_PSUCTL_EVENT_NONE
Definition chademo_se.h:514
@ CHADEMO_SE_PSUCTL_EVENT_PSU_CAN_PROVIDE_POWER
Definition chademo_se.h:523
@ CHADEMO_SE_PSUCTL_EVENT_PSU_MUST_SHUTDOWN
Definition chademo_se.h:526
@ CHADEMO_SE_PSUCTL_EVENT_PLEASE_PROVIDE_INPUTS
Definition chademo_se.h:517
chademo_se_event
Definition chademo_se.h:736
void chademo_se_set_vgpio_inputs(struct chademo_se *self, struct chademo_se_vgpio *src)
Definition chademo_se.h:785
void chademo_se_init(struct chademo_se *self)
Definition chademo_se.h:766
void chademo_se_set_vsensors_inputs(struct chademo_se *self, struct chademo_se_vsensors *src)
Definition chademo_se.h:799
void chademo_se_get_vgpio_inputs(struct chademo_se *self, struct chademo_se_vgpio *dst)
Definition chademo_se.h:778
enum chademo_se_event chademo_se_step(struct chademo_se *self, uint32_t delta_time_ms)
Definition chademo_se.h:849
#define chademo_se_can_frame
Definition chademo_se.h:61
void chademo_se_get_vgpio_outputs(struct chademo_se *self, struct chademo_se_vgpio *dst)
Definition chademo_se.h:792
void chademo_se_get_psuctl_outputs(struct chademo_se *self, struct chademo_se_psuctl_outputs *dst)
Definition chademo_se.h:806
bool chademo_se_push_vcan_frame(struct chademo_se *self, struct chademo_se_can_frame *f)
Definition chademo_se.h:815
bool chademo_se_pop_vcan_frame(struct chademo_se *self, struct chademo_se_can_frame *f)
Definition chademo_se.h:832
chademo_se_psuctl_flags_fault
Definition chademo_se.h:539
@ CHADEMO_SE_PSUCTL_FLAGS_FAULT_API
Definition chademo_se.h:547
Definition chademo_se.h:552
uint8_t flags_fault
Definition chademo_se.h:558
uint16_t voltage_dc_V
Definition chademo_se.h:555
bool ready_for_operation
Definition chademo_se.h:553
uint8_t current_dc_A
Definition chademo_se.h:556
Definition chademo_se.h:563
uint16_t set_voltage_dc_V
Definition chademo_se.h:566
uint8_t set_current_dc_A
Definition chademo_se.h:567
uint8_t event
Definition chademo_se.h:564
Definition chademo_se.h:701
struct _chademo_se_vgpio_out out
Definition chademo_se.h:703
struct _chademo_se_vgpio_in in
Definition chademo_se.h:702
Definition chademo_se.h:497
uint16_t out_terminals_voltage_V
Definition chademo_se.h:499
Definition chademo_se.h:746
Definition chademo_se.h:54
uint8_t data[8]
Definition chademo_se.h:57
uint8_t len
Definition chademo_se.h:56
uint32_t id
Definition chademo_se.h:55