diff --git a/API.md b/API.md index b2a27a8..ad225ec 100644 --- a/API.md +++ b/API.md @@ -56,7 +56,7 @@ Note: all control functions validate their parameters. If you pass any value out - drive: 0 .. 30000 (W) - recup: 0 .. 30000 (W) - Note: both limits have a resolution of 500 W and will be rounded downwards - - Note: these limits do not apply if the SEVCON has been configured to ignore them (as done in some tuning configurations) + - Note: these limits do not apply if the [SEVCON has been configured](extras/SEVCON-Configuration.md) to ignore them - `bool setSOH(int soh)` -- Set state of health - soh: 0 .. 100 (%) @@ -67,7 +67,7 @@ Note: all control functions validate their parameters. If you pass any value out - Note: this does no implicit update on the overall pack voltage - `bool setVoltage(float volt, bool deriveCells)` -- Set battery pack voltage - - volt: 19.3 … 69.6 (SEVCON G48 series voltage range) + - volt: 19.3 .. 69.6 (SEVCON G48 series voltage range) - deriveCells: true = set all cell voltages to volt/14 - `bool setModuleTemperature(int module, int temp)` -- Set battery module temperature @@ -80,7 +80,7 @@ Note: all control functions validate their parameters. If you pass any value out - tempMax: -40 .. 100 (°C) - deriveModules: true = set all module temperatures to avg(min,max) - - `bool setError(unsigned long error)` -- Set error/warning indicators + - `bool setError(unsigned long error)` -- Set display error/warning indicators - error: 0x000000 .. 0xFFFFFF (0 = no error) or use a bitwise ORed combination of… | Code | Description | @@ -114,8 +114,8 @@ All callbacks are optional. See "Template" example for code templates and exampl - `void attachTicker(TwizyTickerCallback fn)` - fn: `void fn(unsigned int clockCnt)` - called by the 10 ms ticker *after* framework handling, i.e. after sending the Twizy CAN frames - - clockCnt: cyclic 10 ms interval counter range 0 … 2999 - - use this to add custom CAN sends or do periodic checks, keep in mind this is not called when in state `Off` + - clockCnt: cyclic 10 ms interval counter range 0 … 2999 (reset to 0 on `Off`/`Init`) + - use this to add custom CAN sends or do periodic checks - `void attachProcessCanMsg(TwizyProcessCanMsgCallback fn)` - fn: `void fn(unsigned long rxId, byte rxLen, byte *rxBuf)` @@ -130,6 +130,7 @@ The VirtualBMS will do state transitions automatically based on CAN input receiv __TwizyStates:__ - `Off` - `Init` + - `Error` - `Ready` - `StartDrive` - `Driving` @@ -145,17 +146,22 @@ Normal startup procedure involves the wakeup phase `Init` followed by `Ready`. D 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()`. + See [protocol documentation](extras/Protocol.ods) for details. __API:__ - `TwizyState state()` -- Query current state + - `bool inState(TwizyState state1 [, … state5])` -- Test for 1-5 states - `void enterState(TwizyState newState)` -- Force a state change - - **Note**: this is normally not necessary as the VirtualBMS does all state transitions automatically. Valid exceptions are: - - You may call `enterState(StopCharge)` to stop a running charge process. Note that `setChargeCurrent(0)` will do so as well. - - You may call `enterState(Off)` as an emergency measurement to cause the Twizy to stop. You should use `setError()` before and give the user enough time to react, as this may be dangerous depending on the driving situation. + - 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`. __Callbacks:__ - Before entering states `Ready`, `Driving`, `Charging` and `Trickle` from any other state, the user callback `CheckState()` will be called. + Exception is entering `Ready` from `Error`, this needs to be done manually anyway (don't expect SEVCON or charger to follow though). - After any state transition, the user callback `EnterState` will be called. diff --git a/DONORS.md b/DONORS.md new file mode 100644 index 0000000..72c0c06 --- /dev/null +++ b/DONORS.md @@ -0,0 +1,12 @@ +# Hall of Eternal Fame + +[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EQ2QDG7YRFYRE) + +**Donations** to support our efforts and further development are very welcome. +Please send donations via **Paypal** to: `virtualbms@dexters-web.de` +Add a comment to your donation if you want to stay anonymous. +**Thanks! :-)** + +*The following people have won our eternal love and respect by kindly supporting this project:* + +- **Klaus Zinser** diff --git a/HISTORY.md b/HISTORY.md index b2ae58f..cc910cd 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,19 +1,28 @@ # History -## Version: 1.0 (2017-06-10) +## Version: 1.0.0 (2017-06-17) - Conversion to Arduino library -- Added CAN RX callback bmsProcessCanMsg() -- Added twizySetError() and error codes +- Added CAN RX callback `ProcessCanMsg` +- Added `setError()` and error codes - Using ROM strings to save RAM - Configurable debug output level - Added example Template - Added example SimpleBMS -- Added setCanFilter() +- Added `setCanFilter()` - Added API documentation - Added hardware documentation - Added SEVCON configuration info +- Added charger configuration info +- Protocol documentation update on error codes +- Added `Error` state for emergency shutdowns +- Ticker callback also called in state `Off` +- Added donation info & donors file +- Added parts images +- Added inState() test functions +- Added Arduino components to parts list +- Added overview text for Blazejs prototype ## Version: 0.2 (2017-06-06) diff --git a/README.md b/README.md index bba2702..ef829b0 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,22 @@ You will also need these libraries: - [MCP_CAN_lib by Cory Fowler](https://github.com/coryjfowler/MCP_CAN_lib) - [TimerOne by Paul Stoffregen](https://github.com/PaulStoffregen/TimerOne) -To get the smallest possible ROM & RAM footprint, set `TWIZY_DEBUG_LEVEL` to 0 and `DEBUG_MODE` of the MCP_CAN library to 0. This reduces the core memory usage of the VirtualBMS library to (currently) 7782 bytes ROM and 403 bytes RAM. +To get the smallest possible ROM & RAM footprint, set `TWIZY_DEBUG_LEVEL` to 0 and `DEBUG_MODE` of the MCP_CAN library to 0. This reduces the core memory usage of the VirtualBMS library to (currently) 7758 bytes ROM and 403 bytes RAM. + + +## Documentation + + - [API reference](API.md) + - [History](HISTORY.md) + + - [Twizy CAN object dictionary](https://docs.google.com/spreadsheets/d/1gOrG9rnGR9YuMGakAbl4s97a6irHF6UNFV1TS5Ll7MY) + - [Twizy BMS protocol](extras/Protocol.ods) + + - [Battery connection scheme](extras/Twizy-BMS-wiring-scheme.pdf) + - [Battery connection part list](extras/Twizy-Battery-Part-List.md) + + - [SEVCON configuration](extras/SEVCON-Configuration.md) + - [Charger configuration](extras/CHARGER-Configuration.md) ## Hardware requirements @@ -26,7 +41,7 @@ To get the smallest possible ROM & RAM footprint, set `TWIZY_DEBUG_LEVEL` to 0 a Pascal is using Nissan Leaf cells, which offer a very good combination of capacity, availability and price. Blazej is using cheap 120 Ah lead acid batteries (price ~400 Euro for a complete set). Klaus will use chinese prismatic cells adding up to ~12 kWh. - **Note**: Klaus offers to organize a bulk order of high capacity prismatic cells priced at ~230 Euro/kWh. For details please contact him at . + **Note**: Klaus offers to organize a bulk order of high capacity prismatic 3.2V LiFePO4 cells in the range of 330€ down to 260€/kWh. For a high performance large capacity setup with 48V 240 Ah (double of the standard battery capacity) a total price only for the battery pack between 2800 and 3200€ seems possible. Each buyer would have the risk in case of failures and should add some spare cells. For details please contact Klaus at . - **BMS**: using a BMS is optional for lead acid batteries but _strongly recommended_ for lithium based batteries. You may pick any BMS, but you should focus on those that can be connected to the Arduino to query the battery state. Our recommendation is picking a good BMS capable of early balancing, monitoring the coulomb (Ah) consumption and calculating the real SOC. @@ -43,9 +58,18 @@ To get the smallest possible ROM & RAM footprint, set `TWIZY_DEBUG_LEVEL` to 0 a **Note**: Lutz Schäfer offers to build individual custom battery cases offering more space. For details please contact him at . +## Compliance + +As the Virtual BMS (as well as the OVMS and other Twizy tools) is based on re-engineering of the CAN protocol, a 100% compliance cannot be reached. There are still unknown fields and codes, look for question marks in the CAN object dictionary for details. Unknown parts may have an effect under special conditions that could not be produced during analysis. + +Having said that, the BMS protocol emulation has successfully been tested and is actually being used in real Twizys, enabling the full standard operation using custom batteries. + +If you encounter any kind of issue, please send us all details including a full CAN trace for analysis. + + ## Authors -This library has been created and is maintained by Michael Balzer (https://dexters-web.de/). +This library has been created and is maintained by Michael Balzer ( / https://dexters-web.de/). The CAN & hardware protocol decoding and reengineering has been done by a joint effort of (in reverse alphabetical order): @@ -56,17 +80,18 @@ The CAN & hardware protocol decoding and reengineering has been done by a joint Special thanks to Klaus Zinser for support and to Blazej Blaszczyk for prototype implementation and testing! +Btw: we're all available for **consulting**, **integration** and **customization** jobs. -## Documentation - - [API reference](API.md) - - [History](HISTORY.md) - - - [Twizy CAN object dictionary](https://docs.google.com/spreadsheets/d/1gOrG9rnGR9YuMGakAbl4s97a6irHF6UNFV1TS5Ll7MY) - - [Twizy BMS protocol](extras/Protocol.ods) +## Donations - - [Battery connection scheme](extras/Twizy-BMS-wiring-scheme.pdf) - - [Battery connection part list](extras/Twizy-Battery-Part-List.md) +[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EQ2QDG7YRFYRE) + +**Donations** to support our efforts and further development are very welcome. +Please send donations via **Paypal** to: `virtualbms@dexters-web.de` +**Thanks! :-)** + +Donors will be honored in our [Hall of Eternal Fame](DONORS.md), please add a comment to your donation if you'd rather stay anonymous. ## License diff --git a/examples/SimpleBMS/SimpleBMS.ino b/examples/SimpleBMS/SimpleBMS.ino index a4453b8..3e93182 100644 --- a/examples/SimpleBMS/SimpleBMS.ino +++ b/examples/SimpleBMS/SimpleBMS.ino @@ -99,13 +99,12 @@ void bmsEnterState(TwizyState currentState, TwizyState newState) { // -------------------------------------------------------------------------- // Callback: timer ticker // - called every 10 ms by twizyTicker() after twizy handling -// - not called when Twizy is in state Off -// - clockCnt cyclic range: 0 .. 2999 = 30 seconds +// - clockCnt cyclic range: 0 .. 2999 = 30 seconds (reset to 0 on Off/Init) // Note: avoid complex operations, this needs to be fast. // void bmsTicker(unsigned int clockCnt) { - if (clockCnt % 100 == 0) { + if (twizy.inState(Off) && (clockCnt % 100 == 0)) { // per second: Serial.println(F("\nbmsTicker:")); @@ -118,7 +117,7 @@ void bmsTicker(unsigned int clockCnt) { twizy.setVoltage(vpack, true); // derive SOC change from voltage: - if (twizy.state() == Charging) { + if (twizy.inState(Charging)) { newsoc = (vpack - VMIN_CHG) / (VMAX_CHG - VMIN_CHG) * 100.0; } else { diff --git a/examples/SimpleBMS/TwizyVirtualBMS_config.h b/examples/SimpleBMS/TwizyVirtualBMS_config.h index f0ec7cc..3592156 100644 --- a/examples/SimpleBMS/TwizyVirtualBMS_config.h +++ b/examples/SimpleBMS/TwizyVirtualBMS_config.h @@ -29,7 +29,7 @@ // If you've connected the CAN module's IRQ pin: //#define TWIZY_CAN_IRQ_PIN 2 -// Set your 3MW control pin here: +// Set your 3MW (ECU_OK) control pin here: #define TWIZY_3MW_CONTROL_PIN 3 #endif // _TwizyVirtualBMS_config_h diff --git a/examples/Template/Template.ino b/examples/Template/Template.ino index e90f84c..4e87575 100644 --- a/examples/Template/Template.ino +++ b/examples/Template/Template.ino @@ -90,8 +90,7 @@ void bmsProcessCanMsg(unsigned long rxId, byte rxLen, byte *rxBuf) { // -------------------------------------------------------------------------- // Callback: timer ticker // - called every 10 ms by twizyTicker() after twizy handling -// - not called when Twizy is in state Off -// - clockCnt cyclic range: 0 .. 2999 = 30 seconds +// - clockCnt cyclic range: 0 .. 2999 = 30 seconds (reset to 0 on Off/Init) // Note: avoid complex operations, this needs to be fast. // void bmsTicker(unsigned int clockCnt) { diff --git a/examples/Template/TwizyVirtualBMS_config.h b/examples/Template/TwizyVirtualBMS_config.h index f0ec7cc..3592156 100644 --- a/examples/Template/TwizyVirtualBMS_config.h +++ b/examples/Template/TwizyVirtualBMS_config.h @@ -29,7 +29,7 @@ // If you've connected the CAN module's IRQ pin: //#define TWIZY_CAN_IRQ_PIN 2 -// Set your 3MW control pin here: +// Set your 3MW (ECU_OK) control pin here: #define TWIZY_3MW_CONTROL_PIN 3 #endif // _TwizyVirtualBMS_config_h diff --git a/extras/CHARGER-Configuration.md b/extras/CHARGER-Configuration.md new file mode 100644 index 0000000..604d7a3 --- /dev/null +++ b/extras/CHARGER-Configuration.md @@ -0,0 +1,21 @@ +# Charger Configuration + +You do not need to change the charger if your battery can be charged at the standard voltage and current levels provided by the builtin [IES-Synergy Elips 2000W](http://www.ies-synergy.com/en/chargers/onboard-sealed-chargers/elips-2000w) charger. + +- The Elips 2000W can charge with a final voltage of up to 60 V. +- Charge current can be set from 0 - 35 A in 5 A steps. + +It may be possible to configure the Elips in the future, at the moment you need to control the charge current and stop the charge process using the `setChargeCurrent()` [API call](../API.md), if your battery cannot cope with the Elips standard charge process. + + +## Using a custom charger + +If you need or want to use a custom charger, take care not to remove the Elips 2000W from the Twizy without further consideration. + +The Elips is operating with a specialized firmware and has a crucial role in the Twizy's control protocol. + +You can charge a custom battery directly without using the Elips, but for driving and 12V trickle charging the Elips needs to be connected to the battery and CAN bus. + +If you're interested in replacing the Elips: creating a "Twizy Virtual Charger" should be possible as well, but has to be done yet. + + diff --git a/extras/Protocol.ods b/extras/Protocol.ods index e39f8c6..09791aa 100644 Binary files a/extras/Protocol.ods and b/extras/Protocol.ods differ diff --git a/extras/Prototype-Blazej.md b/extras/Prototype-Blazej.md new file mode 100644 index 0000000..1e1a729 --- /dev/null +++ b/extras/Prototype-Blazej.md @@ -0,0 +1,28 @@ +# Prototype build by Blazej Blaszczyk + +This is a prototype actually powering Blazejs own Twizy. + +It uses four standard 120 Ah lead acid batteries. Range with new batteries is ~ 50-60 km on flat terrain. + +No Renault parts have been used. The main power relais is from a fork lift. + +There is no BMS other than the Arduino (Nano) itself. The pack voltage is measured using a voltage divider, the pack temperature is measured using an LM35D sensor. SOC is derived from the (smoothed) pack voltage. The software is basically the "SimpleBMS" example from the library with calibration for Blazejs components. + +If you'd like to know more, contact Blazej Blaszczyk . + + +## Images + +(click to zoom) + +[![20170604_163414-nm.jpg](Prototype-Blazej/20170604_163414-sm.jpg)](Prototype-Blazej/20170604_163414-nm.jpg) +[![20170604_163556-nm.jpg](Prototype-Blazej/20170604_163556-sm.jpg)](Prototype-Blazej/20170604_163556-nm.jpg) +[![DSC_9520-nm.jpg](Prototype-Blazej/DSC_9520-sm.jpg)](Prototype-Blazej/DSC_9520-nm.jpg) +[![DSC_9521-nm.jpg](Prototype-Blazej/DSC_9521-sm.jpg)](Prototype-Blazej/DSC_9521-nm.jpg) +[![DSC_9522-nm.jpg](Prototype-Blazej/DSC_9522-sm.jpg)](Prototype-Blazej/DSC_9522-nm.jpg) +[![DSC_9523-nm.jpg](Prototype-Blazej/DSC_9523-sm.jpg)](Prototype-Blazej/DSC_9523-nm.jpg) +[![DSC_9524-nm.jpg](Prototype-Blazej/DSC_9524-sm.jpg)](Prototype-Blazej/DSC_9524-nm.jpg) +[![DSC_9525-nm.jpg](Prototype-Blazej/DSC_9525-sm.jpg)](Prototype-Blazej/DSC_9525-nm.jpg) +[![DSC_9526-nm.jpg](Prototype-Blazej/DSC_9526-sm.jpg)](Prototype-Blazej/DSC_9526-nm.jpg) +[![DSC_9527-nm.jpg](Prototype-Blazej/DSC_9527-sm.jpg)](Prototype-Blazej/DSC_9527-nm.jpg) + diff --git a/extras/Prototype-Blazej/20170604_163414.jpg b/extras/Prototype-Blazej/20170604_163414-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/20170604_163414.jpg rename to extras/Prototype-Blazej/20170604_163414-nm.jpg diff --git a/extras/Prototype-Blazej/20170604_163414-sm.jpg b/extras/Prototype-Blazej/20170604_163414-sm.jpg new file mode 100644 index 0000000..85340c9 Binary files /dev/null and b/extras/Prototype-Blazej/20170604_163414-sm.jpg differ diff --git a/extras/Prototype-Blazej/20170604_163556.jpg b/extras/Prototype-Blazej/20170604_163556-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/20170604_163556.jpg rename to extras/Prototype-Blazej/20170604_163556-nm.jpg diff --git a/extras/Prototype-Blazej/20170604_163556-sm.jpg b/extras/Prototype-Blazej/20170604_163556-sm.jpg new file mode 100644 index 0000000..f3fcb58 Binary files /dev/null and b/extras/Prototype-Blazej/20170604_163556-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9520.JPG b/extras/Prototype-Blazej/DSC_9520-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9520.JPG rename to extras/Prototype-Blazej/DSC_9520-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9520-sm.jpg b/extras/Prototype-Blazej/DSC_9520-sm.jpg new file mode 100644 index 0000000..434dd41 Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9520-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9521.JPG b/extras/Prototype-Blazej/DSC_9521-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9521.JPG rename to extras/Prototype-Blazej/DSC_9521-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9521-sm.jpg b/extras/Prototype-Blazej/DSC_9521-sm.jpg new file mode 100644 index 0000000..e37e08e Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9521-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9522.JPG b/extras/Prototype-Blazej/DSC_9522-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9522.JPG rename to extras/Prototype-Blazej/DSC_9522-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9522-sm.jpg b/extras/Prototype-Blazej/DSC_9522-sm.jpg new file mode 100644 index 0000000..553f978 Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9522-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9523.JPG b/extras/Prototype-Blazej/DSC_9523-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9523.JPG rename to extras/Prototype-Blazej/DSC_9523-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9523-sm.jpg b/extras/Prototype-Blazej/DSC_9523-sm.jpg new file mode 100644 index 0000000..9eb2c92 Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9523-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9524.JPG b/extras/Prototype-Blazej/DSC_9524-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9524.JPG rename to extras/Prototype-Blazej/DSC_9524-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9524-sm.jpg b/extras/Prototype-Blazej/DSC_9524-sm.jpg new file mode 100644 index 0000000..2cde13f Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9524-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9525.JPG b/extras/Prototype-Blazej/DSC_9525-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9525.JPG rename to extras/Prototype-Blazej/DSC_9525-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9525-sm.jpg b/extras/Prototype-Blazej/DSC_9525-sm.jpg new file mode 100644 index 0000000..d9194e7 Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9525-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9526.JPG b/extras/Prototype-Blazej/DSC_9526-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9526.JPG rename to extras/Prototype-Blazej/DSC_9526-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9526-sm.jpg b/extras/Prototype-Blazej/DSC_9526-sm.jpg new file mode 100644 index 0000000..aa2ce15 Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9526-sm.jpg differ diff --git a/extras/Prototype-Blazej/DSC_9527.JPG b/extras/Prototype-Blazej/DSC_9527-nm.jpg similarity index 100% rename from extras/Prototype-Blazej/DSC_9527.JPG rename to extras/Prototype-Blazej/DSC_9527-nm.jpg diff --git a/extras/Prototype-Blazej/DSC_9527-sm.jpg b/extras/Prototype-Blazej/DSC_9527-sm.jpg new file mode 100644 index 0000000..ea68c27 Binary files /dev/null and b/extras/Prototype-Blazej/DSC_9527-sm.jpg differ diff --git a/extras/SEVCON-Configuration.md b/extras/SEVCON-Configuration.md index 844d492..5e7a3a8 100644 --- a/extras/SEVCON-Configuration.md +++ b/extras/SEVCON-Configuration.md @@ -9,7 +9,9 @@ If your battery cannot cope with these limits, you can either use the Virtual BM If you need to set the limits regularly below the standards, consider tuning the Twizy down. Triggering the power limiter will result in a sudden power cutback followed by slowly raising power levels until the limit is reached again. This continues over and over leading to an inconvenient pumping effect. -**Note**: SEVCON write access has been limited by Renault on Twizys (SEVCONs) delivered after June 2016. The write protection only applies to power and driving profile tuning registers, most other parameters can still be changed, including voltage limits. +**Note**: SEVCON write access has been limited by Renault on Twizys (SEVCONs) delivered after June 2016. The write protection applies to all power and driving profile tuning registers, and also to the voltage limits. **If you've got a locked Twizy, your battery should match the standard battery parameters.** + +A locked SEVCON will respond to register writes with an error. You can also check the software version (`rs 100a 00`): if it's `0712.0003` or higher, the Twizy is locked. ## Tools diff --git a/extras/Twizy-Battery-Part-List.md b/extras/Twizy-Battery-Part-List.md index 138ffd5..247ba62 100644 --- a/extras/Twizy-Battery-Part-List.md +++ b/extras/Twizy-Battery-Part-List.md @@ -5,47 +5,103 @@ For explosion drawings and OE part numbers, see… 1. [partsouq.com](https://partsouq.com/en/catalog/genuine/vehicle?c=Renault&ssd=%24HAxLcgIFBQEDBA5SXAdCUkZQXEd0e1pcB19WWkBRXFBTOQoWRnN5BAsCDXEVOjkCamFBSEtkVSECMBNNV0dyAw%24&vid=1409&cid=2043523126&q=) 2. [catcar.info](https://www.catcar.info/renault/?lang=en&l=c3Q9PTUwfHxzdHM9PXsiMTAiOiJNb2RlbCIsIjIwIjoiVHdpenkiLCIzMCI6Ik1BTUEiLCI0MCI6Ik1hbnVhbCIsIjUwIjoiMTkgQ29vbGluZyBzeXN0ZW0gLSBSZXNlcnZvaXJzIC0gRXhoYXVzdCBzeXN0ZW0gLSBFbmdpbmUgbW91bnRpbmcgXC8gVHJhY3Rpb24gYmF0dGVyeSJ9fHxub3Bycz09MTQwOXx8YnJhbmQ9PVJlbmF1bHR8fG5vcHI9PTE0MDl8fHR5cGU9PU1BTUF8fGNhdF9pZD09TXx8aW1nPT0wMTA0MDI2NHx8Z3JwX2lkPT0xOXx8c3ViR3JwX2lkPT0xOUd8fGNybnROb3ByPT0xNDA5fHxyZWZhY2Nlcz09TjE5OTAwMA%3D%3D) +A good source for all parts is [JC Parts](https://www.jcparts.eu/). -## Connectors and relais -| # | Part | OE number | ~Price | -| --- | --- | --- | --- | -| 1x | Fusible Principal Fltg Ent Chr | 296539341R | 4.41 € | -| 1x | Fusible Chargeur Fltg Ent Chrj | 296539051R | 1.67 € | -| 1x | Fusible Apres Contact Fltg Ent | 296535672R | 1.30 € | -| 1x | Relais Principal Boitier Cnx P | 294B16331R | 56.63 € | -| 1x | Platine Fusible | 296713282R | 10.48 € | -| 1x | Platine Fusible | 296712452R | 7.96 € | -| 1x | Embase Connecteur Ba | 296746418R | 30.67 € | -| 1x | Embase Connecteur Batterie Tra | 296743399R | 52.22 € | -| 1x | Embase Connecteur | 296740718R | 86.30 € | -| 1x | Relais Precharge Boitier Cnx P | 294B20431R | 21.19 € | -| 1x | Relais Chargeur Fltg Ent Chrjr | 296156226R | 39.96 € | +## Fuses, connectors and relais -Total: ~ 310 € +| # | Image | Part | OE number | ~Price | +| --- | --- | --- | --- | --- | +| 1x | [![296539341R](parts/296539341R-sm.jpg)](parts/296539341R-nm.jpg) | Fusible Principal Fltg Ent Chr
*Main fuse 500A* | 296539341R | 4.41 € | +| 1x | [![296539051R](parts/296539051R-sm.jpg)](parts/296539051R-nm.jpg) | Fusible Chargeur Fltg Ent Chrj
*Charge fuse 50A* | 296539051R | 1.67 € | +| 1x | [![296535672R](parts/296535672R-sm.jpg)](parts/296535672R-nm.jpg) | Fusible Apres Contact Fltg Ent
*Precharge fuse 5A* | 296535672R | 1.30 € | +| 1x | [![296535672R](parts/296535672R-sm.jpg)](parts/296535672R-nm.jpg) | Platine Fusible
*Main fuse holder* | 296535672R | 10.48 € | +| 1x | [![296712452R](parts/296712452R-sm.jpg)](parts/296712452R-nm.jpg) | Platine Fusible
*Charge fuse holder* | 296712452R | 7.96 € | +| 1x | [![296743399R](parts/296743399R-sm.jpg)](parts/296743399R-nm.jpg) | Embase Connecteur Batterie Tra
*Main connector (DELPHI)* | 296743399R | 52.22 € | +| 1x | [![296746418R](parts/296746418R-sm.jpg)](parts/296746418R-nm.jpg) | Embase Connecteur Ba
*Charge connector (DELPHI)* | 296746418R | 30.67 € | +| 1x | [![296740718R](parts/296740718R-sm.jpg)](parts/296740718R-nm.jpg) | Embase Connecteur
*Signal connector (Yazaki)* | 296740718R | 86.30 € | +| 1x | [![294B16331R](parts/294B16331R-sm.jpg)](parts/294B16331R-nm.jpg) | Relais Principal Boitier Cnx P
*Main relais 150A* | 294B16331R | 56.63 € | +| 1x | [![294B20431R](parts/294B20431R-sm.jpg)](parts/294B20431R-nm.jpg) | Relais Precharge Boitier Cnx P
*Precharge relais 10A* | 294B20431R | 21.19 € | +| 1x | [![296156226R](parts/296156226R-sm.jpg)](parts/296156226R-nm.jpg) | Relais Chargeur Fltg Ent Chrjr
*Charge relais 40A* | 296156226R | 39.96 € | +| | | **Total** *(prices may change)* | | **~ 310 €** | -Parts may of course be replaced by functionally compatible ones, for example use a fork lift relais for the main power relais. Blazej Blaszczyk has built his prototype without using Renault parts. For details please contact him at . +Parts may of course be replaced by functionally compatible ones, for example use a fork lift relais for the main power relais (relais & fuses are no special parts). Blazej Blaszczyk has built his prototype without using Renault parts. For details please contact him at . - - The `296740718R` signal connector is Yazaki part no. 7282-8854-30 [male](http://connectors-catalog.sys.yzk.co.jp/yazaki-web/servlet/SubServlet_e?forward=7282-8854-30&plist=detail&select=XX) [female](http://connectors-catalog.sys.yzk.co.jp/yazaki-web/servlet/SubServlet_e?forward=7283-8854-30&plist=detail&select=XX). - - The `296743399R` main power connector is DELPHI part no. [F473110](http://ecat.delphi.com/feature?search=F473110), with contact terminals (F176600)[ecat.delphi.com/feature?search=F176600]. + - The `296740718R` signal connector is Yazaki part no. [7282-8854-30](http://connectors-catalog.sys.yzk.co.jp/yazaki-web/servlet/SubServlet_e?forward=7282-8854-30&plist=detail&select=XX) (contact terminals sold separate). + - The `296743399R` main power connector is DELPHI part no. [F473110](http://ecat.delphi.com/feature?search=F473110), with contact terminals [F176600](http://ecat.delphi.com/feature?search=F176600). - The `296746418R` charger power connector is DELPHI part no. [F873110](ecat.delphi.com/feature?search=F873110), with contact terminals [15516298](http://ecat.delphi.com/feature?search=15516298). ## Casing -| # | Part | OE number | ~Price | -| --- | --- | --- | --- | -| 1x | CARTER SUP BATTERI | 295F00162R | 129 € | -| 1x | CARTER INF BATTERI | 295F19016R | 216 € | -| 1x | JOINT ETC CARTER B | 295G32560R | 46 € | - -Total: ~ 390 € +| # | Image | Part | OE number | ~Price | +| --- | --- | --- | --- | --- | +| 1x | [![295F00162R](parts/295F00162R-sm.jpg)](parts/295F00162R-nm.jpg) | CARTER SUP BATTERI
*Casing cover* | 295F00162R | 129 € | +| 1x | [![295F19016R](parts/295F19016R-sm.jpg)](parts/295F19016R-nm.jpg) | CARTER INF BATTERI
*Casing base* | 295F19016R | 216 € | +| 1x | | JOINT ETC CARTER B
*Casing seal* | 295G32560R | 46 € | +| | | **Total** *(prices may change)* | | **~ 390 €** | **Note**: Lutz Schäfer offers to build individual custom battery cases offering more space. For details please contact him at . __Sizes__: - Standard Renault Box: 724 x 368 x 208 mm - - Lutz-Box Box V1 (without car modification): 745 x 400 x 245 mm + - Lutz-Box V1 (without car modification): 745 x 400 x 245 mm - Lutz-Box V2 (car modification necessary): 745 x 480 x 245 mm +## Arduino + +**Note**: if you plan to use **Pascals integrated Twizy BMS**, you won't need an Arduino. The integrated BMS also implements the Twizy protocol. + +For a basic setup you'll need an Arduino, a CAN interface and a relais to switch the 3MW signal. + +Standard Arduinos can be powered from 12V, but will burn the voltage difference (convert to heat), so a step-down voltage regulator is highly recommended. The [Pololu A-Star SV series](https://www.pololu.com/category/149/a-star-programmable-controllers) has on-board step-down regulators suitable for a 12V supply. + +Using an Arduino Uno style main board with shields reduces soldering requirements but needs more money and space than for example a Nano based board with break out components. + +Keep in mind for all setups, this is an automotive application: expect high levels of mechanical stress due to road shocks and temperature expansion/contraction. Protect your electronics against humidity. + +**Price note**: there are lots of cheap Arduino clones available. These can of course be used as well. Expect a lower build quality, so better order some spares (always a good idea). + + +### Example basic Uno/Shield setup + +| Category | Component | ~Price | +| --- | --- | --- | +| Main+Power | Pololu A-Star 32U4 Prime SV | 24.95 € | +| CAN | Seeed Studio CAN-BUS Shield v1.2 | 24.95 € | +| Relais | Seeed Studio Relais Shield V3.0 | 21.95 € | +| **Total** | | **~ 72 €** | + + +### Example basic Nano setup + +| Category | Component | ~Price | +| --- | --- | --- | +| Main | Arduino Nano V3 clone | 4.95 € | +| I/O | Arduino NANO Screw Terminal Expansion Board | 4.95 € | +| CAN | NiRen MCP2515_CAN (TJA1050) | 4.50 € | +| CAN | … 16 MHz quartz | 0.23 € | +| Relais | 5V 2 Channel Relay Shield | 2.95 € | +| **Total** | | **~ 18 €** | + + +### Example components + +| Category | Component | ~Price | +| --- | --- | --- | +| Main | Arduino Uno R3 | 20.80 € | +| Main | Arduino Nano V3 | 23.80 € | +| Main+Power | Pololu A-Star 32U4 Prime SV | 24.95 € | +| Power | Pololu 5V, 2.5A Step-Down Voltage Regulator D24V22F5 | 8.95 € | +| CAN | Seeed Studio CAN-BUS Shield v1.2 | 24.95 € | +| CAN | NiRen MCP2515_CAN (TJA1050)
*Note: these come with 8 MHz quartz, you should replace this with a 16 MHz type* | 4.50 € | +| Relais | Seeed Studio Relais Shield V3.0 | 21.95 € | +| Relais | 5V 2 Channel Relay Shield | 2.95 € | +| I/O | Adafruit Proto-Screwshield | 15.50 € | +| I/O | Arduino NANO Screw Terminal Expansion Board | 4.95 € | +| I/O | Adafruit ADS1015 12-Bit ADC - 4 Channel | 10.95 € | +| I/O | Mayhew Labs Extended ADC Shield | 30 € | +| I/O | Seeed Studio RS232 Shield | 12.50 € | + + diff --git a/extras/parts/294B16331R-nm.jpg b/extras/parts/294B16331R-nm.jpg new file mode 100644 index 0000000..6b25a36 Binary files /dev/null and b/extras/parts/294B16331R-nm.jpg differ diff --git a/extras/parts/294B16331R-sm.jpg b/extras/parts/294B16331R-sm.jpg new file mode 100644 index 0000000..b306083 Binary files /dev/null and b/extras/parts/294B16331R-sm.jpg differ diff --git a/extras/parts/294B20431R-nm.jpg b/extras/parts/294B20431R-nm.jpg new file mode 100644 index 0000000..d3d8df8 Binary files /dev/null and b/extras/parts/294B20431R-nm.jpg differ diff --git a/extras/parts/294B20431R-sm.jpg b/extras/parts/294B20431R-sm.jpg new file mode 100644 index 0000000..663a258 Binary files /dev/null and b/extras/parts/294B20431R-sm.jpg differ diff --git a/extras/Renault-Box-1.jpg b/extras/parts/295F00162R-nm.jpg similarity index 100% rename from extras/Renault-Box-1.jpg rename to extras/parts/295F00162R-nm.jpg diff --git a/extras/parts/295F00162R-sm.jpg b/extras/parts/295F00162R-sm.jpg new file mode 100644 index 0000000..4a4abae Binary files /dev/null and b/extras/parts/295F00162R-sm.jpg differ diff --git a/extras/Renault-Box-2.jpg b/extras/parts/295F19016R-nm.jpg similarity index 100% rename from extras/Renault-Box-2.jpg rename to extras/parts/295F19016R-nm.jpg diff --git a/extras/parts/295F19016R-sm.jpg b/extras/parts/295F19016R-sm.jpg new file mode 100644 index 0000000..d026569 Binary files /dev/null and b/extras/parts/295F19016R-sm.jpg differ diff --git a/extras/parts/296156226R-nm.jpg b/extras/parts/296156226R-nm.jpg new file mode 100644 index 0000000..a5a3cbd Binary files /dev/null and b/extras/parts/296156226R-nm.jpg differ diff --git a/extras/parts/296156226R-sm.jpg b/extras/parts/296156226R-sm.jpg new file mode 100644 index 0000000..6c2b76b Binary files /dev/null and b/extras/parts/296156226R-sm.jpg differ diff --git a/extras/parts/296535672R-nm.jpg b/extras/parts/296535672R-nm.jpg new file mode 100644 index 0000000..ae0e76a Binary files /dev/null and b/extras/parts/296535672R-nm.jpg differ diff --git a/extras/parts/296535672R-sm.jpg b/extras/parts/296535672R-sm.jpg new file mode 100644 index 0000000..abfe015 Binary files /dev/null and b/extras/parts/296535672R-sm.jpg differ diff --git a/extras/parts/296539051R-nm.jpg b/extras/parts/296539051R-nm.jpg new file mode 100644 index 0000000..ae31cd1 Binary files /dev/null and b/extras/parts/296539051R-nm.jpg differ diff --git a/extras/parts/296539051R-sm.jpg b/extras/parts/296539051R-sm.jpg new file mode 100644 index 0000000..14d56db Binary files /dev/null and b/extras/parts/296539051R-sm.jpg differ diff --git a/extras/parts/296539341R-nm.jpg b/extras/parts/296539341R-nm.jpg new file mode 100644 index 0000000..738e919 Binary files /dev/null and b/extras/parts/296539341R-nm.jpg differ diff --git a/extras/parts/296539341R-sm.jpg b/extras/parts/296539341R-sm.jpg new file mode 100644 index 0000000..5db8426 Binary files /dev/null and b/extras/parts/296539341R-sm.jpg differ diff --git a/extras/parts/296712452R-nm.jpg b/extras/parts/296712452R-nm.jpg new file mode 100644 index 0000000..6bf952d Binary files /dev/null and b/extras/parts/296712452R-nm.jpg differ diff --git a/extras/parts/296712452R-sm.jpg b/extras/parts/296712452R-sm.jpg new file mode 100644 index 0000000..0187436 Binary files /dev/null and b/extras/parts/296712452R-sm.jpg differ diff --git a/extras/parts/296713282R-nm.jpg b/extras/parts/296713282R-nm.jpg new file mode 100644 index 0000000..5de5227 Binary files /dev/null and b/extras/parts/296713282R-nm.jpg differ diff --git a/extras/parts/296713282R-sm.jpg b/extras/parts/296713282R-sm.jpg new file mode 100644 index 0000000..d6bda5a Binary files /dev/null and b/extras/parts/296713282R-sm.jpg differ diff --git a/extras/Yazaki-7282-8854-30.jpg b/extras/parts/296740718R-nm.jpg similarity index 100% rename from extras/Yazaki-7282-8854-30.jpg rename to extras/parts/296740718R-nm.jpg diff --git a/extras/parts/296740718R-sm.jpg b/extras/parts/296740718R-sm.jpg new file mode 100644 index 0000000..cbe0cd4 Binary files /dev/null and b/extras/parts/296740718R-sm.jpg differ diff --git a/extras/296740718R.jpg b/extras/parts/296740718R-tapping.jpg similarity index 100% rename from extras/296740718R.jpg rename to extras/parts/296740718R-tapping.jpg diff --git a/extras/parts/296743399R-nm.jpg b/extras/parts/296743399R-nm.jpg new file mode 100644 index 0000000..fd76537 Binary files /dev/null and b/extras/parts/296743399R-nm.jpg differ diff --git a/extras/parts/296743399R-sm.jpg b/extras/parts/296743399R-sm.jpg new file mode 100644 index 0000000..3ea3c74 Binary files /dev/null and b/extras/parts/296743399R-sm.jpg differ diff --git a/extras/parts/296746418R-nm.jpg b/extras/parts/296746418R-nm.jpg new file mode 100644 index 0000000..5c4c129 Binary files /dev/null and b/extras/parts/296746418R-nm.jpg differ diff --git a/extras/parts/296746418R-sm.jpg b/extras/parts/296746418R-sm.jpg new file mode 100644 index 0000000..c392182 Binary files /dev/null and b/extras/parts/296746418R-sm.jpg differ diff --git a/extras/parts/Overview-nm.jpg b/extras/parts/Overview-nm.jpg new file mode 100644 index 0000000..85dd1f9 Binary files /dev/null and b/extras/parts/Overview-nm.jpg differ diff --git a/extras/parts/Overview-sm.jpg b/extras/parts/Overview-sm.jpg new file mode 100644 index 0000000..3aa49cc Binary files /dev/null and b/extras/parts/Overview-sm.jpg differ diff --git a/keywords.txt b/keywords.txt index ed52817..a8357d7 100644 --- a/keywords.txt +++ b/keywords.txt @@ -33,8 +33,10 @@ attachProcessCanMsg KEYWORD2 attachTicker KEYWORD2 sendMsg KEYWORD2 +setCanFilter KEYWORD2 state KEYWORD2 +inState KEYWORD2 enterState KEYWORD2 dumpId KEYWORD2 @@ -54,6 +56,7 @@ TWIZY_3MW_CONTROL_PIN LITERAL1 Off LITERAL1 Init LITERAL1 +Error LITERAL1 Ready LITERAL1 StartDrive LITERAL1 Driving LITERAL1 diff --git a/library.properties b/library.properties index 75a1050..b59c6c9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Twizy Virtual BMS -version=1.0 +version=1.0.0 author=Michael Balzer maintainer=Michael Balzer sentence=Emulation of Renault Twizy BMS (battery management system) diff --git a/src/TwizyVirtualBMS.h b/src/TwizyVirtualBMS.h index 6c3cbe3..5fea5d0 100644 --- a/src/TwizyVirtualBMS.h +++ b/src/TwizyVirtualBMS.h @@ -47,7 +47,7 @@ #include "TwizyVirtualBMS_config.h" #endif -#define TWIZY_VBMS_VERSION "V1.0 (2017-06-10)" +#define TWIZY_VBMS_VERSION "V1.0.0 (2017-06-17)" #ifndef TWIZY_TAG #define TWIZY_TAG "twizy." @@ -63,6 +63,7 @@ enum TwizyState { Off, Init, + Error, Ready, StartDrive, Driving, @@ -77,9 +78,10 @@ enum TwizyState { // Twizy state names: #if TWIZY_DEBUG_LEVEL >= 1 -const char PROGMEM twizyStateName[12][13] = { +const char PROGMEM twizyStateName[13][13] = { "Off", "Init", + "Error", "Ready", "StartDrive", "Driving", @@ -94,9 +96,9 @@ const char PROGMEM twizyStateName[12][13] = { #endif -// Known error codes for twizySetError(): +// Known error codes for setError(): // Note: these can be used singularly or be ORed to set multiple indicators. -// i.e. do twizySetError(TWIZY_SERV_TEMP|TWIZY_SERV_STOP) to indicate +// i.e. do setError(TWIZY_SERV_TEMP|TWIZY_SERV_STOP) to indicate // a severely high temperature #define TWIZY_OK 0x00000000 // clear all indicators #define TWIZY_SERV 0x00eeee00 // set SERV indicator @@ -192,12 +194,27 @@ public: TwizyState state() { return twizyState; } - void enterState(TwizyState newState); + bool inState(TwizyState state1) { + return (twizyState==state1); + } + bool inState(TwizyState state1, TwizyState state2) { + return (twizyState==state1 || twizyState==state2); + } + bool inState(TwizyState state1, TwizyState state2, TwizyState state3) { + return (twizyState==state1 || twizyState==state2 || twizyState==state3); + } + bool inState(TwizyState state1, TwizyState state2, TwizyState state3, TwizyState state4) { + return (twizyState==state1 || twizyState==state2 || twizyState==state3 || twizyState==state4); + } + bool inState(TwizyState state1, TwizyState state2, TwizyState state3, TwizyState state4, TwizyState state5) { + return (twizyState==state1 || twizyState==state2 || twizyState==state3 || twizyState==state4 || twizyState==state5); + } + void enterState(TwizyState newState); // CAN interface access: bool sendMsg(INT32U id, INT8U len, INT8U *buf); - void setCanFilter(byte filterNum, unsigned int canId); - + void setCanFilter(byte filterNum, unsigned int canId); + // Debug utils: void dumpId(FLASHSTRING *name, int len, byte *buf); void debugInfo(); @@ -469,8 +486,9 @@ bool TwizyVirtualBMS::setTemperature(int tempMin, int tempMax, bool deriveModule return true; } -// Set battery error +// Set display battery error indicators // error: 0x000000 .. 0xFFFFFF (0 = no error) +// See error code definitions. bool TwizyVirtualBMS::setError(unsigned long error) { CHECKLIMIT(error, 0x000000, 0xFFFFFF); id628[0] = (error & 0xFF0000) >> 16; @@ -604,9 +622,9 @@ bool TwizyVirtualBMS::sendMsg(INT32U id, INT8U len, INT8U *buf) { #endif //TWIZY_CAN_SEND - sendErrors++; - return false; - + sendErrors++; + return false; + // Note: MCP_CAN.sendMsgBuf() is not optimized for throughput. // Despite having three send buffers in the MCP, it will wait // for the send to finish and return an error on timeout. @@ -622,116 +640,121 @@ bool TwizyVirtualBMS::sendMsg(INT32U id, INT8U len, INT8U *buf) { void TwizyVirtualBMS::ticker() { - if (twizyState == Off) { - clockCnt = 0; - return; - } - if (++clockCnt == 3000) clockCnt = 0; - bool ms100 = (clockCnt % 10 == 0); - bool ms1000 = (clockCnt % 100 == 0); - bool ms3000 = (clockCnt % 300 == 0); - bool ms10000 = (clockCnt % 1000 == 0); + // Note: currently we turn off all CAN sends in state Error, + // as that reliably lets the SEVCON and charger switch off. + // It may be an option to only turn off ID 554 (or all 55x) + // instead, as that happened on one CAN trace of a defective + // original battery. - - // - // Send CAN messages - // - - sendMsg(0x155, sizeof(id155), id155); - - if (ms100) { - sendMsg(0x424, sizeof(id424), id424); - sendMsg(0x425, sizeof(id425), id425); - } - if (ms1000) { - sendMsg(0x554, sizeof(id554), id554); - } - if (ms100) { - sendMsg(0x556, sizeof(id556), id556); - } - if (ms1000) { - sendMsg(0x557, sizeof(id557), id557); - sendMsg(0x55E, sizeof(id55E), id55E); - sendMsg(0x55F, sizeof(id55F), id55F); - } - if (ms100) { - sendMsg(0x628, sizeof(id628), id628); - } - if (ms3000) { - sendMsg(0x659, sizeof(id659), id659); - } - - - // - // Create 3MW pulse cycle - // (high 150ms → low 150ms → high) - // - - if (counter3MW > 0) { - --counter3MW; - // 3MW low after 150 ms: - if (counter3MW == 15) { - digitalWrite(TWIZY_3MW_CONTROL_PIN, 0); - } - // 3MW high after 300 ms (pulse finished): - else if (counter3MW == 0) { - digitalWrite(TWIZY_3MW_CONTROL_PIN, 1); - } - } - - - // - // Check for state transition - // - - switch (twizyState) { + if ((twizyState != Off) && (twizyState != Error)) { - // Transition to Ready? - case Init: - case StopDrive: - case StopCharge: - case StopTrickle: - if (!bmsCheckState || (*bmsCheckState)(twizyState, Ready)) { - enterState(Ready); + bool ms100 = (clockCnt % 10 == 0); + bool ms1000 = (clockCnt % 100 == 0); + bool ms3000 = (clockCnt % 300 == 0); + bool ms10000 = (clockCnt % 1000 == 0); + + + // + // Send CAN messages + // + + sendMsg(0x155, sizeof(id155), id155); + + if (ms100) { + sendMsg(0x424, sizeof(id424), id424); + sendMsg(0x425, sizeof(id425), id425); + } + if (ms1000) { + sendMsg(0x554, sizeof(id554), id554); + } + if (ms100) { + sendMsg(0x556, sizeof(id556), id556); + } + if (ms1000) { + sendMsg(0x557, sizeof(id557), id557); + sendMsg(0x55E, sizeof(id55E), id55E); + sendMsg(0x55F, sizeof(id55F), id55F); + } + if (ms100) { + sendMsg(0x628, sizeof(id628), id628); + } + if (ms3000) { + sendMsg(0x659, sizeof(id659), id659); + } + + + // + // Create 3MW pulse cycle + // (high 150ms → low 150ms → high) + // + + if (counter3MW > 0) { + --counter3MW; + // 3MW low after 150 ms: + if (counter3MW == 15) { + digitalWrite(TWIZY_3MW_CONTROL_PIN, 0); } - break; + // 3MW high after 300 ms (pulse finished): + else if (counter3MW == 0) { + digitalWrite(TWIZY_3MW_CONTROL_PIN, 1); + } + } + + + // + // Check for state transition + // + + switch (twizyState) { + // Transition to Ready? + case Init: + case StopDrive: + case StopCharge: + case StopTrickle: + if (!bmsCheckState || (*bmsCheckState)(twizyState, Ready)) { + enterState(Ready); + } + break; + // Transition to Driving? - case StartDrive: - if (!bmsCheckState || (*bmsCheckState)(twizyState, Driving)) { - enterState(Driving); - } - break; - + case StartDrive: + if (!bmsCheckState || (*bmsCheckState)(twizyState, Driving)) { + enterState(Driving); + } + break; + // Transition to Charging? - case StartCharge: - if (!bmsCheckState || (*bmsCheckState)(twizyState, Charging)) { - enterState(Charging); - } - break; - + case StartCharge: + if (!bmsCheckState || (*bmsCheckState)(twizyState, Charging)) { + enterState(Charging); + } + break; + // Transition to Trickle? - case StartTrickle: - if (!bmsCheckState || (*bmsCheckState)(twizyState, Trickle)) { - enterState(Trickle); - } - break; - - } - - - // - // Debug info every 10 seconds - // - - #if TWIZY_DEBUG_LEVEL >= 1 - if (ms10000) { - debugInfo(); - } - #endif + case StartTrickle: + if (!bmsCheckState || (*bmsCheckState)(twizyState, Trickle)) { + enterState(Trickle); + } + break; + + } + + + // + // Debug info every 10 seconds + // + + #if TWIZY_DEBUG_LEVEL >= 1 + if (ms10000) { + debugInfo(); + } + #endif + + } // if ((twizyState != Off) && (twizyState != Error)) // @@ -827,23 +850,36 @@ void TwizyVirtualBMS::enterState(TwizyState newState) { case Off: case Init: + id155[3] = 0x94; id424[0] = 0x00; id425[0] = 0x1D; digitalWrite(TWIZY_3MW_CONTROL_PIN, 0); + counter3MW = 0; + clockCnt = 0; + break; + + case Error: + // Note: these updates are just for consistency, will currently + // not be sent as Error turns off sending (may change) + id155[3] = 0x94; + id424[0] |= 0x80; + id425[0] = 0x24; + digitalWrite(TWIZY_3MW_CONTROL_PIN, 0); break; case Ready: - // keep stop charge request if set: - if (id424[0] != 0x12) { - id424[0] = 0x11; - } // restore minimum charge current level: if (id155[0] == 0) { id155[0] = 1; } + id155[3] = 0x54; + // keep stop charge request if set: + if (id424[0] != 0x12) { + id424[0] = 0x11; + } id425[0] = 0x24; - // if just switched on... - if (twizyState == Init) { + // if switching on... + if (digitalRead(TWIZY_3MW_CONTROL_PIN) == 0) { // ...start 3MW pulse cycle: digitalWrite(TWIZY_3MW_CONTROL_PIN, 1); counter3MW = 30; @@ -869,7 +905,6 @@ void TwizyVirtualBMS::enterState(TwizyState newState) { case Trickle: id425[0] = 0x2A; break; - } // call BMS state transition: @@ -907,9 +942,9 @@ void TwizyVirtualBMS::begin() { twizyCAN.init_Mask(1, 0, 0x07FF0000); twizyCAN.init_Filt(2, 0, 0x05990000); // DISPLAY: 599 - twizyCAN.init_Filt(3, 0, 0x00000000); - twizyCAN.init_Filt(4, 0, 0x00000000); - twizyCAN.init_Filt(5, 0, 0x00000000); + twizyCAN.init_Filt(3, 0, 0x00000000); // usable by setCanFilter(1) + twizyCAN.init_Filt(4, 0, 0x00000000); // usable by setCanFilter(2) + twizyCAN.init_Filt(5, 0, 0x00000000); // usable by setCanFilter(3) #ifdef TWIZY_CAN_IRQ_PIN pinMode(TWIZY_CAN_IRQ_PIN, INPUT); diff --git a/src/TwizyVirtualBMS_config.h b/src/TwizyVirtualBMS_config.h index f0ec7cc..3592156 100644 --- a/src/TwizyVirtualBMS_config.h +++ b/src/TwizyVirtualBMS_config.h @@ -29,7 +29,7 @@ // If you've connected the CAN module's IRQ pin: //#define TWIZY_CAN_IRQ_PIN 2 -// Set your 3MW control pin here: +// Set your 3MW (ECU_OK) control pin here: #define TWIZY_3MW_CONTROL_PIN 3 #endif // _TwizyVirtualBMS_config_h