- 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.
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
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

View file

@ -13,12 +13,18 @@
* 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_dfs.h>
#include "TwizyChargeThrottle_config.h"
#if TWIZY_DEBUG >= 1
#define DEBUG1(cmd) cmd
#else
#define DEBUG1(cmd)
#endif
// CAN interface:
MCP_CAN CAN(TWIZY_CAN_CS_PIN);
@ -33,12 +39,23 @@ bool charging = false;
// Current level:
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
volatile bool msgReceived = false;
void canISR() {
msgReceived = true;
}
volatile bool msgReceived = false;
void canISR() {
msgReceived = true;
}
#endif
@ -50,8 +67,8 @@ void setup() {
// Init CAN interface:
#if TWIZY_CAN_IRQ_PIN > 0
pinMode(TWIZY_CAN_IRQ_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(TWIZY_CAN_IRQ_PIN), canISR, FALLING);
pinMode(TWIZY_CAN_IRQ_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(TWIZY_CAN_IRQ_PIN), canISR, FALLING);
#endif
while (CAN.begin(MCP_STDEXT, CAN_500KBPS, TWIZY_CAN_MCP_FREQ) != CAN_OK) {
@ -73,10 +90,24 @@ void setup() {
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.print(F("Throttling configured to current level: "));
Serial.println((char)('0' + TWIZY_CHARGE_THROTTLE));
Serial.print(F("Throttling to current level: "));
Serial.println((char)('0' + throttle));
}
@ -84,9 +115,9 @@ void loop() {
while (true) {
#if TWIZY_CAN_IRQ_PIN > 0
// Wait for interrupt signal:
while (!msgReceived);
msgReceived = false;
// Wait for interrupt signal:
while (!msgReceived);
msgReceived = false;
#endif
// Process CAN read buffer:
@ -98,12 +129,20 @@ void loop() {
bool _charging = ((msgBuf[1] & 0x60) == 0x20);
#if TWIZY_DEBUG > 0
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)
Serial.println(F("Charge STOP"));
#endif
{
digitalWrite(OUT_CHARGING_PIN, LOW);
digitalWrite(OUT_THROTTLING_PIN, LOW);
DEBUG1(Serial.println(F("Charge STOP")));
}
charging = _charging;
level = 0;
@ -117,31 +156,40 @@ void loop() {
if (_level == 0xFF)
continue; // init phase, skip
if (_level > TWIZY_CHARGE_THROTTLE)
if (throttle != 0 && _level > throttle)
{
// overwrite:
msgBuf[0] = TWIZY_CHARGE_THROTTLE;
msgBuf[0] = throttle;
CAN.sendMsgBuf(0x155, 0, 8, msgBuf);
digitalWrite(OUT_THROTTLING_PIN, HIGH);
}
else
{
digitalWrite(OUT_THROTTLING_PIN, LOW);
}
#if TWIZY_DEBUG > 1
if (_level != level)
{
Serial.print(F("Level "));
if (_level > TWIZY_CHARGE_THROTTLE) {
Serial.print((char)('0' + _level));
Serial.print('>');
Serial.println((char)('0' + TWIZY_CHARGE_THROTTLE));
} else {
Serial.println((char)('0' + _level));
if (_level != level)
{
Serial.print(F("Level "));
if (_level > throttle) {
Serial.print((char)('0' + _level));
Serial.print('>');
Serial.println((char)('0' + throttle));
} else {
Serial.println((char)('0' + _level));
}
}
}
#endif
level = _level;
}
}
#ifndef FIXED_LEVEL
throttle = READ_LEVEL();
#endif
} // while (true)
}

View file

@ -6,19 +6,35 @@
#ifndef _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
// 5 = 25 A = 1,7 kW
// 4 = 20 A = 1,4 kW
// 3 = 15 A = 1,0 kW
// 2 = 10 A = 0,7 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:
// 1 = show charge start/stop
// 2 = show current level changes
#define TWIZY_DEBUG 2
#define TWIZY_DEBUG 0
// Serial interface baud rate:
#define SERIAL_SPEED 115200
@ -27,7 +43,7 @@
#define TWIZY_CAN_MCP_FREQ MCP_16MHZ
// 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):
#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