- Added support for level control input & state LEDs

- Added example wiring scheme
This commit is contained in:
Michael Balzer 2019-05-17 16:15:37 +02:00
parent ad479942b8
commit 528058ad71
6 changed files with 104 additions and 34 deletions

View file

@ -2,12 +2,18 @@
This is a very simple tool to limit the Twizy charge current if you don't have an OVMS. This is a very simple tool to limit the Twizy charge current if you don't have an OVMS.
It can currently only limit the charge current to a fixed level (defined in the config file). It can limit the charge current to a fixed level (defined in the config file) or use a
coded rotary switch or simple DIP switch for dynamic level adjustment. It can signal
the charging state and active throttling by LEDs.
See [wiring scheme](extras/Wiring.pdf) for an example using a coded rotary switch.
The Arduino needs to be connected to the Twizy CAN bus during the charge process to be able The Arduino needs to be connected to the Twizy CAN bus during the charge process to be able
to actively overwrite the charge current control frames. to actively overwrite the charge current control frames.
Note: using an interrupt capable CAN shield is highly recommended. Note: using an interrupt capable CAN shield is highly recommended. No attempt at
reducing the Arduino current consumption is made, include a power switch or fork and
extend the code for sleep mode (and send me a pull request).
## Info ## Info

View file

@ -13,12 +13,18 @@
* https://www.gnu.org/licenses/lgpl.html * https://www.gnu.org/licenses/lgpl.html
* *
*/ */
#define TWIZY_CT_VERSION "V1.0 (2019-05-10)" #define TWIZY_CT_VERSION "V2.0 (2019-05-17)"
#include <mcp_can.h> #include <mcp_can.h>
#include <mcp_can_dfs.h> #include <mcp_can_dfs.h>
#include "TwizyChargeThrottle_config.h" #include "TwizyChargeThrottle_config.h"
#if TWIZY_DEBUG >= 1
#define DEBUG1(cmd) cmd
#else
#define DEBUG1(cmd)
#endif
// CAN interface: // CAN interface:
MCP_CAN CAN(TWIZY_CAN_CS_PIN); MCP_CAN CAN(TWIZY_CAN_CS_PIN);
@ -33,12 +39,23 @@ bool charging = false;
// Current level: // Current level:
byte level = 0; byte level = 0;
// Throttling level:
#ifdef FIXED_LEVEL
const byte throttle = FIXED_LEVEL;
#else
byte throttle = 0;
#define READ_LEVEL() \
( digitalRead(IN_LEVEL_B1) \
| digitalRead(IN_LEVEL_B2) << 1 \
| digitalRead(IN_LEVEL_B4) << 2)
#endif
#if TWIZY_CAN_IRQ_PIN > 0 #if TWIZY_CAN_IRQ_PIN > 0
volatile bool msgReceived = false; volatile bool msgReceived = false;
void canISR() { void canISR() {
msgReceived = true; msgReceived = true;
} }
#endif #endif
@ -50,8 +67,8 @@ void setup() {
// Init CAN interface: // Init CAN interface:
#if TWIZY_CAN_IRQ_PIN > 0 #if TWIZY_CAN_IRQ_PIN > 0
pinMode(TWIZY_CAN_IRQ_PIN, INPUT); pinMode(TWIZY_CAN_IRQ_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(TWIZY_CAN_IRQ_PIN), canISR, FALLING); attachInterrupt(digitalPinToInterrupt(TWIZY_CAN_IRQ_PIN), canISR, FALLING);
#endif #endif
while (CAN.begin(MCP_STDEXT, CAN_500KBPS, TWIZY_CAN_MCP_FREQ) != CAN_OK) { while (CAN.begin(MCP_STDEXT, CAN_500KBPS, TWIZY_CAN_MCP_FREQ) != CAN_OK) {
@ -73,10 +90,24 @@ void setup() {
CAN.setMode(MCP_NORMAL); CAN.setMode(MCP_NORMAL);
// Init I/O:
#ifndef FIXED_LEVEL
pinMode(IN_LEVEL_B1, INPUT);
pinMode(IN_LEVEL_B2, INPUT);
pinMode(IN_LEVEL_B4, INPUT);
throttle = READ_LEVEL();
#endif
pinMode(OUT_CHARGING_PIN, OUTPUT);
pinMode(OUT_THROTTLING_PIN, OUTPUT);
digitalWrite(OUT_CHARGING_PIN, LOW);
digitalWrite(OUT_THROTTLING_PIN, LOW);
Serial.println(F("Setup done.")); Serial.println(F("Setup done."));
Serial.print(F("Throttling configured to current level: ")); Serial.print(F("Throttling to current level: "));
Serial.println((char)('0' + TWIZY_CHARGE_THROTTLE)); Serial.println((char)('0' + throttle));
} }
@ -84,9 +115,9 @@ void loop() {
while (true) { while (true) {
#if TWIZY_CAN_IRQ_PIN > 0 #if TWIZY_CAN_IRQ_PIN > 0
// Wait for interrupt signal: // Wait for interrupt signal:
while (!msgReceived); while (!msgReceived);
msgReceived = false; msgReceived = false;
#endif #endif
// Process CAN read buffer: // Process CAN read buffer:
@ -98,12 +129,20 @@ void loop() {
bool _charging = ((msgBuf[1] & 0x60) == 0x20); bool _charging = ((msgBuf[1] & 0x60) == 0x20);
#if TWIZY_DEBUG > 0
if (_charging && !charging) if (_charging && !charging)
Serial.println(F("Charge START")); {
digitalWrite(OUT_CHARGING_PIN, HIGH);
#ifndef FIXED_LEVEL
throttle = READ_LEVEL();
#endif
DEBUG1(Serial.println(F("Charge START")));
}
else if (!_charging && charging) else if (!_charging && charging)
Serial.println(F("Charge STOP")); {
#endif digitalWrite(OUT_CHARGING_PIN, LOW);
digitalWrite(OUT_THROTTLING_PIN, LOW);
DEBUG1(Serial.println(F("Charge STOP")));
}
charging = _charging; charging = _charging;
level = 0; level = 0;
@ -117,31 +156,40 @@ void loop() {
if (_level == 0xFF) if (_level == 0xFF)
continue; // init phase, skip continue; // init phase, skip
if (_level > TWIZY_CHARGE_THROTTLE) if (throttle != 0 && _level > throttle)
{ {
// overwrite: // overwrite:
msgBuf[0] = TWIZY_CHARGE_THROTTLE; msgBuf[0] = throttle;
CAN.sendMsgBuf(0x155, 0, 8, msgBuf); CAN.sendMsgBuf(0x155, 0, 8, msgBuf);
digitalWrite(OUT_THROTTLING_PIN, HIGH);
}
else
{
digitalWrite(OUT_THROTTLING_PIN, LOW);
} }
#if TWIZY_DEBUG > 1 #if TWIZY_DEBUG > 1
if (_level != level) if (_level != level)
{ {
Serial.print(F("Level ")); Serial.print(F("Level "));
if (_level > TWIZY_CHARGE_THROTTLE) { if (_level > throttle) {
Serial.print((char)('0' + _level)); Serial.print((char)('0' + _level));
Serial.print('>'); Serial.print('>');
Serial.println((char)('0' + TWIZY_CHARGE_THROTTLE)); Serial.println((char)('0' + throttle));
} else { } else {
Serial.println((char)('0' + _level)); Serial.println((char)('0' + _level));
}
} }
}
#endif #endif
level = _level; level = _level;
} }
} }
#ifndef FIXED_LEVEL
throttle = READ_LEVEL();
#endif
} // while (true) } // while (true)
} }

View file

@ -6,19 +6,35 @@
#ifndef _TwizyChargeThrottle_config_h #ifndef _TwizyChargeThrottle_config_h
#define _TwizyChargeThrottle_config_h #define _TwizyChargeThrottle_config_h
// Set the charge current throttle level here: // Charge current throttle levels:
// 7 = 35 A = 2,3 kW (full power, no throttling)
// 6 = 30 A = 2,1 kW // 6 = 30 A = 2,1 kW
// 5 = 25 A = 1,7 kW // 5 = 25 A = 1,7 kW
// 4 = 20 A = 1,4 kW // 4 = 20 A = 1,4 kW
// 3 = 15 A = 1,0 kW // 3 = 15 A = 1,0 kW
// 2 = 10 A = 0,7 kW // 2 = 10 A = 0,7 kW
// 1 = 5 A = 0,4 kW // 1 = 5 A = 0,4 kW
#define TWIZY_CHARGE_THROTTLE 5 // 0 = no throttling
// If not using a power level input, define a fixed throttling level like this:
// #define FIXED_LEVEL 5
// If this is defined, the power level inputs will not be used.
// Power level input:
// Use an 8 position binary coded rotary switch or a 3 pin DIP switch (or similar),
// define the input ports used here (analog ports may be used as well):
#define IN_LEVEL_B1 3
#define IN_LEVEL_B2 4
#define IN_LEVEL_B4 5
// Status outputs (e.g. LEDs):
#define OUT_CHARGING_PIN 8
#define OUT_THROTTLING_PIN 9
// Serial debug output level: // Serial debug output level:
// 1 = show charge start/stop // 1 = show charge start/stop
// 2 = show current level changes // 2 = show current level changes
#define TWIZY_DEBUG 2 #define TWIZY_DEBUG 0
// Serial interface baud rate: // Serial interface baud rate:
#define SERIAL_SPEED 115200 #define SERIAL_SPEED 115200
@ -27,7 +43,7 @@
#define TWIZY_CAN_MCP_FREQ MCP_16MHZ #define TWIZY_CAN_MCP_FREQ MCP_16MHZ
// Set your CAN CS pin number here: // Set your CAN CS pin number here:
#define TWIZY_CAN_CS_PIN SS #define TWIZY_CAN_CS_PIN 10
// Set your CAN IRQ pin here (0 = no IRQ): // Set your CAN IRQ pin here (0 = no IRQ):
#define TWIZY_CAN_IRQ_PIN 2 #define TWIZY_CAN_IRQ_PIN 2

BIN
extras/Wiring.fzz Normal file

Binary file not shown.

BIN
extras/Wiring.pdf Normal file

Binary file not shown.

BIN
extras/Wiring.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB