Hint: begin with the "Template" example to get a standard usage template including all callbacks.
## Library inclusion
1. Create a TwizyVirtualBMS object (`twizy` is a good name for this)
2. Call `twizy.begin()` in your setup function
3. Call `twizy.looper()` in your main loop:
```c++
#include "TwizyVirtualBMS_config.h"
#include "TwizyVirtualBMS.h"
TwizyVirtualBMS twizy;
void setup() {
Serial.begin(115200);
twizy.begin();
}
void loop() {
twizy.looper();
}
```
## Twizy control functions
Note: all control functions validate their parameters. If you pass any value out of bounds, nothing will be changed, an error message will be generated on the serial port and the function will return `false`.
-`bool setChargeCurrent(int amps)` -- Set battery charge current level
- amps: 0 .. 35 A current level at battery
- will stop charge if set to 0 while charging
- Note: this has a 5 A resolution rounded downwards
- Note: 35 A will not be reached with current charger generation (max ~32 A)
| Current level | Power drawn from socket |
| ------------- | ----------------------- |
| 35 A | ~ 2.2 kW |
| 30 A | ~ 2.1 kW |
| 25 A | ~ 1.7 kW |
| 20 A | ~ 1.4 kW |
| 15 A | ~ 1.0 kW |
| 10 A | ~ 0.7 kW |
| 5 A | ~ 0.4 kW |
-`bool setCurrent(float amps)` -- Set momentary battery pack current level
Normal startup procedure involves the wakeup phase `Init` followed by `Ready`. Depending on the mode of operation requested, this will be followed by one of the `Start…` states with operation mode established resulting in the according `…ing` state.
The shutdown procedure begins with a transition from the `…ing` state to the according `Stop…` state, followed by `Ready` and finally `Off`.
Use the `Error` state to signal **severe problems** to the Twizy and cause an emergency shutdown. `Error` turns off CAN sends and drops the 3MW (ECU_OK) signal. SEVCON and charger will switch off all battery power immediately. To resolve the `Error` state from driving, the user needs to do a power cycle. When used during a charge, the charger will send the BMS into `Off` state, so the charge can simply be restarted by replugging the charger.
**Note**: to indicate **non-critical** problems, do not enter the `Error` state but instead only use `setError()`.
- Call `enterState(StopCharge)` to stop a running charge process. Note that `setChargeCurrent(0)` will do so as well.
- Call `enterState(Error)` to cause an emergency shutdown. Before doing this you should use `setError()` and (if possible) give the user some time to react when in state `Driving`.
- After any state transition, the user callback `EnterState` will be called.
## CAN interface access
To hook into the CAN receiver, use `attachProcessCanMsg()` (see above).
Standard filters will pass IDs `0x423`, `0x597` and `0x599`. Three free CAN filters can be used. The mask is fixed to match the whole ID, so you can filter at most three additional IDs at a time.
-`void setCanFilter(byte filterNum, unsigned int canId)` -- Set a free ID filter
- filterNum: 1 … 3
- canId: 11 bit CAN ID i.e. `0x196`
-`bool sendMsg(INT32U id, INT8U len, INT8U *buf)` -- Send a CAN message
- Note: will do three retries if TX buffers are full.
- Returns true if message has been sent, false on error.
- Retry and error counts are logged every 10 seconds if debug logging is enabled.
## Debug utils
-`void dumpId(FLASHSTRING *name, int len, byte *buf)` -- Dump a byte buffer in hex numbers
- name: must be a PROGMEM string, i.e. `dumpId(F("id123"), ...)`
-`void debugInfo()` -- Dump VirtualBMS status, include frame buffers if debug level >= 2
- this is automatically called every 10 seconds if debug level >= 1
Beginning with version 1.3.0, the VirtualBMS supports sending an extended BMS status information on the CAN bus. The frame layout has been designed by Pascal Ripp and Michael Balzer to create a standard base for CAN bus tools like the Twizplay and the OVMS.
The extended info frame is sent at CAN ID 0x700 once per second in all states except `Off`. The frame transports these fields:
- Byte 0: BMS specific state #1 (main state, i.e. twizy.state())
- Byte 1: highest 3 bits = BMS type ID (see below), remaining 5 bits = BMS specific error code (see below)
- Bytes 2-4: cell voltages #15 (encoded in 12 bits like #1-#14)
- Byte 7: BMS specific state #2 (auxiliary state or data)
The VirtualBMS will not send frame 0x700 unless you set the BMS type. It will also not insert any data into the fields by itself, to fill in data you need to use the API calls as shown below. This way you can use the VirtualBMS library to implement other BMS types as well.
### BMS types
The BMS type is meant for CAN tools to be able to identify the BMS and decode the BMS specific states and error info.
There are currently 7 possible BMS types, defined in `enum TwizyBmsType`:
- 0 = `bmsType_VirtualBMS` (states and error codes as documented here)
- 1 = `bmsType_EdriverBMS` (see Pascal's documentation for details)
- 2…6 = reserved
- 7 = `bmsType_undefined` (disables frame 0x700)
Types #2…#6 can be assigned to future BMS types.
Please contact us if you want to allocate an ID. Keep in mind: any new BMS type needs support in all CAN tools, so try to reuse one of the already defined BMS types as long as possible.
### BMS error codes (for `bmsType_VirtualBMS`)
Our basic standard proposition covers these error codes (defined in `enum TwizyBmsError`):
- 0 = `bmsError_None`
- 1 = `bmsError_EEPROM`
- 2 = `bmsError_SensorFailure`
- 3 = `bmsError_VoltageHigh`
- 4 = `bmsError_VoltageLow`
- 5 = `bmsError_VoltageDiff`
- 6 = `bmsError_TemperatureHigh`
- 7 = `bmsError_TemperatureLow`
- 8 = `bmsError_TemperatureDiff`
- 9 = `bmsError_ChargerTemperatureHigh`
Custom error codes can be added beginning at 128. Please contact us if you'd like to add standard error codes.
### API calls
-`bool setInfoBmsType(byte bmsType)` -- Set informational BMS type