Twizy Virtual BMS V1.0.0 (2017-06-17)
- 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
22
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.
|
||||
|
||||
|
||||
|
|
12
DONORS.md
Normal file
|
@ -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**
|
17
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)
|
||||
|
|
45
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 <klauszinser@posteo.eu>.
|
||||
**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 <klauszinser@posteo.eu>.
|
||||
|
||||
- **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 <aquillo@t-online.de>.
|
||||
|
||||
|
||||
## 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 (<dexter@dexters-web.de> / 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 <klauszinser@posteo.eu> for support and to Blazej Blaszczyk <blazej.blaszczyk@pascal-engineering.com> for prototype implementation and testing!
|
||||
|
||||
Btw: we're all available for **consulting**, **integration** and **customization** jobs.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [API reference](API.md)
|
||||
- [History](HISTORY.md)
|
||||
## Donations
|
||||
|
||||
- [Twizy CAN object dictionary](https://docs.google.com/spreadsheets/d/1gOrG9rnGR9YuMGakAbl4s97a6irHF6UNFV1TS5Ll7MY)
|
||||
- [Twizy BMS protocol](extras/Protocol.ods)
|
||||
[![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)
|
||||
|
||||
- [Battery connection scheme](extras/Twizy-BMS-wiring-scheme.pdf)
|
||||
- [Battery connection part list](extras/Twizy-Battery-Part-List.md)
|
||||
**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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
21
extras/CHARGER-Configuration.md
Normal file
|
@ -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.
|
||||
|
||||
|
28
extras/Prototype-Blazej.md
Normal file
|
@ -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 <blazej.blaszczyk@pascal-engineering.com>.
|
||||
|
||||
|
||||
## 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)
|
||||
|
Before Width: | Height: | Size: 888 KiB After Width: | Height: | Size: 888 KiB |
BIN
extras/Prototype-Blazej/20170604_163414-sm.jpg
Normal file
After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 924 KiB After Width: | Height: | Size: 924 KiB |
BIN
extras/Prototype-Blazej/20170604_163556-sm.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 936 KiB After Width: | Height: | Size: 936 KiB |
BIN
extras/Prototype-Blazej/DSC_9520-sm.jpg
Normal file
After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 909 KiB After Width: | Height: | Size: 909 KiB |
BIN
extras/Prototype-Blazej/DSC_9521-sm.jpg
Normal file
After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 913 KiB After Width: | Height: | Size: 913 KiB |
BIN
extras/Prototype-Blazej/DSC_9522-sm.jpg
Normal file
After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 912 KiB After Width: | Height: | Size: 912 KiB |
BIN
extras/Prototype-Blazej/DSC_9523-sm.jpg
Normal file
After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 776 KiB After Width: | Height: | Size: 776 KiB |
BIN
extras/Prototype-Blazej/DSC_9524-sm.jpg
Normal file
After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 835 KiB After Width: | Height: | Size: 835 KiB |
BIN
extras/Prototype-Blazej/DSC_9525-sm.jpg
Normal file
After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 837 KiB After Width: | Height: | Size: 837 KiB |
BIN
extras/Prototype-Blazej/DSC_9526-sm.jpg
Normal file
After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 843 KiB After Width: | Height: | Size: 843 KiB |
BIN
extras/Prototype-Blazej/DSC_9527-sm.jpg
Normal file
After Width: | Height: | Size: 57 KiB |
|
@ -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
|
||||
|
|
|
@ -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 <br/> *Main fuse 500A* | 296539341R | 4.41 € |
|
||||
| 1x | [![296539051R](parts/296539051R-sm.jpg)](parts/296539051R-nm.jpg) | Fusible Chargeur Fltg Ent Chrj <br/> *Charge fuse 50A* | 296539051R | 1.67 € |
|
||||
| 1x | [![296535672R](parts/296535672R-sm.jpg)](parts/296535672R-nm.jpg) | Fusible Apres Contact Fltg Ent <br/> *Precharge fuse 5A* | 296535672R | 1.30 € |
|
||||
| 1x | [![296535672R](parts/296535672R-sm.jpg)](parts/296535672R-nm.jpg) | Platine Fusible <br/> *Main fuse holder* | 296535672R | 10.48 € |
|
||||
| 1x | [![296712452R](parts/296712452R-sm.jpg)](parts/296712452R-nm.jpg) | Platine Fusible <br/> *Charge fuse holder* | 296712452R | 7.96 € |
|
||||
| 1x | [![296743399R](parts/296743399R-sm.jpg)](parts/296743399R-nm.jpg) | Embase Connecteur Batterie Tra <br/> *Main connector (DELPHI)* | 296743399R | 52.22 € |
|
||||
| 1x | [![296746418R](parts/296746418R-sm.jpg)](parts/296746418R-nm.jpg) | Embase Connecteur Ba <br/> *Charge connector (DELPHI)* | 296746418R | 30.67 € |
|
||||
| 1x | [![296740718R](parts/296740718R-sm.jpg)](parts/296740718R-nm.jpg) | Embase Connecteur <br/> *Signal connector (Yazaki)* | 296740718R | 86.30 € |
|
||||
| 1x | [![294B16331R](parts/294B16331R-sm.jpg)](parts/294B16331R-nm.jpg) | Relais Principal Boitier Cnx P <br/> *Main relais 150A* | 294B16331R | 56.63 € |
|
||||
| 1x | [![294B20431R](parts/294B20431R-sm.jpg)](parts/294B20431R-nm.jpg) | Relais Precharge Boitier Cnx P <br/> *Precharge relais 10A* | 294B20431R | 21.19 € |
|
||||
| 1x | [![296156226R](parts/296156226R-sm.jpg)](parts/296156226R-nm.jpg) | Relais Chargeur Fltg Ent Chrjr <br/> *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 <blazej.blaszczyk@pascal-engineering.com>.
|
||||
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 <blazej.blaszczyk@pascal-engineering.com>.
|
||||
|
||||
- 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 <br/> *Casing cover* | 295F00162R | 129 € |
|
||||
| 1x | [![295F19016R](parts/295F19016R-sm.jpg)](parts/295F19016R-nm.jpg) | CARTER INF BATTERI <br/> *Casing base* | 295F19016R | 216 € |
|
||||
| 1x | | JOINT ETC CARTER B <br/> *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 <aquillo@t-online.de>.
|
||||
|
||||
__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) <br/> *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 € |
|
||||
|
||||
|
||||
|
|
BIN
extras/parts/294B16331R-nm.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
extras/parts/294B16331R-sm.jpg
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
extras/parts/294B20431R-nm.jpg
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
extras/parts/294B20431R-sm.jpg
Normal file
After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 246 KiB After Width: | Height: | Size: 246 KiB |
BIN
extras/parts/295F00162R-sm.jpg
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 264 KiB |
BIN
extras/parts/295F19016R-sm.jpg
Normal file
After Width: | Height: | Size: 992 B |
BIN
extras/parts/296156226R-nm.jpg
Normal file
After Width: | Height: | Size: 193 KiB |
BIN
extras/parts/296156226R-sm.jpg
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
extras/parts/296535672R-nm.jpg
Normal file
After Width: | Height: | Size: 188 KiB |
BIN
extras/parts/296535672R-sm.jpg
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
extras/parts/296539051R-nm.jpg
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
extras/parts/296539051R-sm.jpg
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
extras/parts/296539341R-nm.jpg
Normal file
After Width: | Height: | Size: 158 KiB |
BIN
extras/parts/296539341R-sm.jpg
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
extras/parts/296712452R-nm.jpg
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
extras/parts/296712452R-sm.jpg
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
extras/parts/296713282R-nm.jpg
Normal file
After Width: | Height: | Size: 151 KiB |
BIN
extras/parts/296713282R-sm.jpg
Normal file
After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
BIN
extras/parts/296740718R-sm.jpg
Normal file
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
BIN
extras/parts/296743399R-nm.jpg
Normal file
After Width: | Height: | Size: 215 KiB |
BIN
extras/parts/296743399R-sm.jpg
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
extras/parts/296746418R-nm.jpg
Normal file
After Width: | Height: | Size: 187 KiB |
BIN
extras/parts/296746418R-sm.jpg
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
extras/parts/Overview-nm.jpg
Normal file
After Width: | Height: | Size: 244 KiB |
BIN
extras/parts/Overview-sm.jpg
Normal file
After Width: | Height: | Size: 6.7 KiB |
|
@ -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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=Twizy Virtual BMS
|
||||
version=1.0
|
||||
version=1.0.0
|
||||
author=Michael Balzer
|
||||
maintainer=Michael Balzer <dexter@dexters-web.de>
|
||||
sentence=Emulation of Renault Twizy BMS (battery management system)
|
||||
|
|
|
@ -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,11 +194,26 @@ 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);
|
||||
|
@ -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,8 +622,8 @@ 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
|
||||
|
@ -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.
|
||||
|
||||
if ((twizyState != Off) && (twizyState != Error)) {
|
||||
|
||||
bool ms100 = (clockCnt % 10 == 0);
|
||||
bool ms1000 = (clockCnt % 100 == 0);
|
||||
bool ms3000 = (clockCnt % 300 == 0);
|
||||
bool ms10000 = (clockCnt % 1000 == 0);
|
||||
|
||||
|
||||
//
|
||||
// Send CAN messages
|
||||
//
|
||||
//
|
||||
// Send CAN messages
|
||||
//
|
||||
|
||||
sendMsg(0x155, sizeof(id155), id155);
|
||||
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);
|
||||
if (ms100) {
|
||||
sendMsg(0x424, sizeof(id424), id424);
|
||||
sendMsg(0x425, sizeof(id425), id425);
|
||||
}
|
||||
// 3MW high after 300 ms (pulse finished):
|
||||
else if (counter3MW == 0) {
|
||||
digitalWrite(TWIZY_3MW_CONTROL_PIN, 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Check for state transition
|
||||
//
|
||||
//
|
||||
// Create 3MW pulse cycle
|
||||
// (high 150ms → low 150ms → high)
|
||||
//
|
||||
|
||||
switch (twizyState) {
|
||||
|
||||
// Transition to Ready?
|
||||
case Init:
|
||||
case StopDrive:
|
||||
case StopCharge:
|
||||
case StopTrickle:
|
||||
if (!bmsCheckState || (*bmsCheckState)(twizyState, Ready)) {
|
||||
enterState(Ready);
|
||||
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;
|
||||
case StartTrickle:
|
||||
if (!bmsCheckState || (*bmsCheckState)(twizyState, Trickle)) {
|
||||
enterState(Trickle);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Debug info every 10 seconds
|
||||
//
|
||||
//
|
||||
// Debug info every 10 seconds
|
||||
//
|
||||
|
||||
#if TWIZY_DEBUG_LEVEL >= 1
|
||||
if (ms10000) {
|
||||
debugInfo();
|
||||
}
|
||||
#endif
|
||||
#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);
|
||||
|
|
|
@ -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
|
||||
|
|