├── .cproject ├── .gitattributes ├── .gitignore ├── .project.copy ├── BatteryManager.cpp ├── BatteryManager.h ├── BrusaMotorController.cpp ├── BrusaMotorController.h ├── CMakeLists.txt ├── CanBrake.cpp ├── CanBrake.h ├── CanHandler.cpp ├── CanHandler.h ├── CanPIDListener.cpp ├── CanPIDListener.h ├── CanThrottle.cpp ├── CanThrottle.h ├── CodaMotorController.cpp ├── CodaMotorController.h ├── DCDCController.cpp ├── DCDCController.h ├── DMOC.txt ├── Device.cpp ├── Device.h ├── DeviceManager.cpp ├── DeviceManager.h ├── DeviceTypes.h ├── DmocMotorController.cpp ├── DmocMotorController.h ├── ELM327Processor.cpp ├── ELM327Processor.h ├── ELM327_Emu.cpp ├── ELM327_Emu.h ├── EVIC.cpp ├── EVIC.h ├── FaultCodes.h ├── FaultHandler.cpp ├── FaultHandler.h ├── GEVCU.h ├── GEVCU.ino ├── GEVCU.kdev4 ├── GEVCU.sln ├── GEVCU.vcxproj ├── GEVCU.vcxproj.filters ├── Heartbeat.cpp ├── Heartbeat.h ├── Logger.cpp ├── Logger.h ├── MemCache.cpp ├── MemCache.h ├── MotorController.cpp ├── MotorController.h ├── OBD2Handler.cpp ├── OBD2Handler.h ├── PotBrake.cpp ├── PotBrake.h ├── PotThrottle.cpp ├── PotThrottle.h ├── PrefHandler.cpp ├── PrefHandler.h ├── README.md ├── SerialConsole.cpp ├── SerialConsole.h ├── Shield ├── Ampseal.lbr ├── Analog_Board.brd ├── Analog_Board.sch ├── Analog_Shield.brd ├── Analog_Shield.sch ├── Canbus-Proto.brd ├── Canbus-Proto.sch ├── Canbus-proto2.brd ├── Eagle_Dued_autorouted.brd ├── Eagle_Dued_autorouted.sch ├── GEVCU-4.brd ├── GEVCU-4.sch ├── canbus-proto2.sch ├── ck_custom.lbr └── dc-dc-converter.lbr ├── Sys_Messages.h ├── ThinkBatteryManager.cpp ├── ThinkBatteryManager.h ├── Throttle.cpp ├── Throttle.h ├── ThrottleDetector.cpp ├── ThrottleDetector.h ├── TickHandler.cpp ├── TickHandler.h ├── config.h ├── constants.h ├── docs ├── Design Drawings.vsd ├── GEVCU pinout.txt ├── GEVCU-35pinout.jpg ├── GEVCU1-1.03.docx ├── ThrottleFiltering.xlsx ├── UQMplug.jpg ├── gevcumanual403.docx └── howtocreatemodule.docx ├── eeprom_layout.h ├── gearsandopstates.txt ├── ichip_2128.cpp ├── ichip_2128.h ├── readme.eclipse.txt ├── sys_io.cpp ├── sys_io.h ├── util ├── BBESAB0801.IMF ├── MultiSerial │ └── MultiSerial.ino ├── connectTOap │ └── connectTOap.ino ├── connectasAP │ └── connectasAP.ino ├── connectsetup │ └── connectsetup.ino ├── i2128d810d35BCOM.IMF └── i2128d810d35BCOM.IMZ ├── website ├── README.txt ├── src │ ├── about.htm │ ├── annunciator.htm │ ├── annunciator.js │ ├── config.htm │ ├── config.xml │ ├── control.js │ ├── dashboard.htm │ ├── dashboard.xml │ ├── devices.htm │ ├── devices.xml │ ├── fonts │ │ ├── digital-7-mono.eot │ │ └── digital-7-mono.ttf │ ├── gauge.js │ ├── gauges.js │ ├── index.htm │ ├── inputs.htm │ ├── inputs.xml │ ├── outputs.htm │ ├── outputs.xml │ ├── status.htm │ ├── status.xml │ ├── styles.css │ └── throttleSettingsCanvas.js └── website.img └── workinprogress.txt /.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 29 | 30 | 31 | 32 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behaviour, in case users don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files we want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.c text 7 | *.h text 8 | *.cpp text 9 | *.ino text 10 | *.txt text 11 | *.brd text 12 | *.sch text 13 | 14 | # Declare files that will always have CRLF line endings on checkout. 15 | *.sln text eol=crlf 16 | *.vcxproj eol=crlf 17 | 18 | # Denote all files that are truly binary and should not be modified. 19 | *.png binary 20 | *.jpg binary -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build and Release Folders 2 | bin/ 3 | bin-debug/ 4 | bin-release/ 5 | 6 | # Other files and folders 7 | .settings/ 8 | arduino 9 | Libraries 10 | Release 11 | .project 12 | 13 | # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` 14 | # should NOT be excluded as they contain compiler settings and other important 15 | # information for Eclipse / Flash Builder. 16 | *.d 17 | *.eep 18 | *.o 19 | *.lss 20 | *.elf 21 | *.map 22 | *.srec 23 | *.vcx* 24 | -------------------------------------------------------------------------------- /.project.copy: -------------------------------------------------------------------------------- 1 | 2 | 3 | GEVCU 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | org.eclipse.cdt.core.ccnature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | it.baeyens.arduinonature 27 | 28 | 29 | 30 | Libraries/DueTimer 31 | 2 32 | ArduinoPivateLibPath/DueTimer 33 | 34 | 35 | Libraries/due_can 36 | 2 37 | ArduinoPivateLibPath/due_can 38 | 39 | 40 | Libraries/due_rtc 41 | 2 42 | ArduinoPivateLibPath/due_rtc 43 | 44 | 45 | Libraries/due_wire 46 | 2 47 | ArduinoPivateLibPath/due_wire 48 | 49 | 50 | arduino/core 51 | 2 52 | ArduinoPlatformPath/cores/arduino 53 | 54 | 55 | arduino/variant 56 | 2 57 | ArduinoPinPath/arduino_due_x 58 | 59 | 60 | 61 | 62 | ArduinoHardwareLibPath 63 | file:/Z:/development/arduino/arduino-1.5.2_win_32bit/hardware/arduino/sam/libraries 64 | 65 | 66 | ArduinoPinPath 67 | file:/Z:/development/arduino/arduino-1.5.2_win_32bit/hardware/arduino/sam/variants 68 | 69 | 70 | ArduinoPlatformPath 71 | file:/Z:/development/arduino/arduino-1.5.2_win_32bit/hardware/arduino/sam 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /BatteryManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * BatteryManager.cpp 3 | * 4 | * Parent class for all battery management/monitoring systems 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #include "BatteryManager.h" 30 | 31 | BatteryManager::BatteryManager() : Device() 32 | { 33 | packVoltage = 0; 34 | packCurrent = 0; 35 | } 36 | 37 | BatteryManager::~BatteryManager() 38 | { 39 | } 40 | 41 | DeviceType BatteryManager::getType() { 42 | return (DEVICE_BMS); 43 | } 44 | 45 | void BatteryManager::handleTick() { 46 | } 47 | 48 | void BatteryManager::setup() { 49 | #ifndef USE_HARD_CODED 50 | if (prefsHandler->checksumValid()) { //checksum is good, read in the values stored in EEPROM 51 | } 52 | else { //checksum invalid. Reinitialize values and store to EEPROM 53 | //prefsHandler->saveChecksum(); 54 | } 55 | #else 56 | #endif 57 | 58 | //TickHandler::getInstance()->detach(this); 59 | //TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_MOTOR_CONTROLLER_DMOC); 60 | 61 | } 62 | 63 | int BatteryManager::getPackVoltage() 64 | { 65 | return packVoltage; 66 | } 67 | 68 | signed int BatteryManager::getPackCurrent() 69 | { 70 | return packCurrent; 71 | } 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /BatteryManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BatteryManager.h 3 | * 4 | * Parent class for battery management / monitoring systems 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef BATTMANAGE_H_ 30 | #define BATTMANAGE_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "Device.h" 35 | 36 | class BatteryManager : public Device { 37 | public: 38 | BatteryManager(); 39 | ~BatteryManager(); 40 | int getPackVoltage(); //in tenths of a volt 41 | signed int getPackCurrent(); //in tenths of an amp 42 | //bool allowCharging(); 43 | //bool allowDischarging(); 44 | DeviceType getType(); 45 | void setup(); 46 | void handleTick(); 47 | //a bunch of boolean functions. Derived classes must implment 48 | //these functions to tell everyone else what they support 49 | virtual bool hasPackVoltage() = 0; 50 | virtual bool hasPackCurrent() = 0; 51 | virtual bool hasTemperatures() = 0; 52 | virtual bool isChargeOK() = 0; 53 | virtual bool isDischargeOK() = 0; 54 | protected: 55 | int packVoltage; //tenths of a volt 56 | signed int packCurrent; //tenths of an amp 57 | int SOC; //state of charge in percent 58 | int lowestCellV, highestCellV; //in mv 59 | int lowestCellTemp, highestCellTemp; 60 | //should be some form of discharge and charge limit. I don't know if it should be % or amps 61 | //some BMS systems will report one way and some the other. 62 | int dischargeLimit, chargeLimit; 63 | bool allowCharge, allowDischarge; 64 | 65 | private: 66 | }; 67 | 68 | #endif 69 | 70 | 71 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(gevcu) 2 | 3 | add_executable(gevcu main.cpp) 4 | 5 | install(TARGETS gevcu RUNTIME DESTINATION bin) 6 | -------------------------------------------------------------------------------- /CanBrake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CanBrake.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef CAN_BRAKE_H_ 28 | #define CAN_BRAKE_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "Throttle.h" 33 | #include "TickHandler.h" 34 | #include "CanHandler.h" 35 | #include "CanThrottle.h" 36 | #include "constants.h" 37 | 38 | class CanBrakeConfiguration : public ThrottleConfiguration { 39 | public: 40 | uint16_t minimumLevel1, maximumLevel1; // values for when the pedal is at its min and max 41 | uint16_t carType; // the type of car, so we know how to interpret which bytes 42 | }; 43 | 44 | class CanBrake: public Throttle, CanObserver { 45 | public: 46 | CanBrake(); 47 | void setup(); 48 | void handleTick(); 49 | void handleCanFrame(CAN_FRAME *frame); 50 | DeviceId getId(); 51 | DeviceType getType(); 52 | 53 | RawSignalData *acquireRawSignal(); 54 | void loadConfiguration(); 55 | void saveConfiguration(); 56 | 57 | protected: 58 | bool validateSignal(RawSignalData *); 59 | uint16_t calculatePedalPosition(RawSignalData *); 60 | int16_t mapPedalPosition(int16_t); 61 | 62 | private: 63 | CAN_FRAME requestFrame; // the request frame sent to the car 64 | RawSignalData rawSignal; // raw signal 65 | uint8_t ticksNoResponse; // number of ticks no response was received 66 | uint32_t responseId; // the CAN id with which the response is sent; 67 | uint32_t responseMask; // the mask for the responseId 68 | bool responseExtended; // if the response is expected as an extended frame 69 | }; 70 | 71 | #endif /* CAN_BRAKE_H_ */ 72 | 73 | 74 | -------------------------------------------------------------------------------- /CanHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CanHandler.h 3 | 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef CAN_HANDLER_H_ 27 | #define CAN_HANDLER_H_ 28 | 29 | #include 30 | #include "config.h" 31 | #include "due_can.h" 32 | #include 33 | #include "variant.h" 34 | #include 35 | #include "Logger.h" 36 | #include "DeviceManager.h" 37 | #include "sys_io.h" 38 | 39 | class Device; 40 | 41 | class CanObserver { 42 | public: 43 | virtual void handleCanFrame(CAN_FRAME *frame); 44 | }; 45 | 46 | class CanHandler { 47 | public: 48 | enum CanBusNode { 49 | CAN_BUS_EV, // CAN0 is intended to be connected to the EV bus (controller, charger, etc.) 50 | CAN_BUS_CAR // CAN1 is intended to be connected to the car's high speed bus (the one with the ECU) 51 | }; 52 | 53 | void initialize(); 54 | void attach(CanObserver *observer, uint32_t id, uint32_t mask, bool extended); 55 | void detach(CanObserver *observer, uint32_t id, uint32_t mask); 56 | void process(); 57 | void sendFrame(CAN_FRAME& frame); 58 | void CANIO(CAN_FRAME& frame); 59 | static CanHandler *getInstanceCar(); 60 | static CanHandler *getInstanceEV(); 61 | protected: 62 | 63 | private: 64 | struct CanObserverData { 65 | uint32_t id; // what id to listen to 66 | uint32_t mask; // the CAN frame mask to listen to 67 | bool extended; // are extended frames expected 68 | uint8_t mailbox; // which mailbox is this observer assigned to 69 | CanObserver *observer; // the observer object (e.g. a device) 70 | }; 71 | static CanHandler *canHandlerEV; // singleton reference to the EV instance (CAN0) 72 | static CanHandler *canHandlerCar; // singleton reference to the car instance (CAN1) 73 | 74 | CanBusNode canBusNode; // indicator to which can bus this instance is assigned to 75 | CANRaw *bus; // the can bus instance which this CanHandler instance is assigned to 76 | CanObserverData observerData[CFG_CAN_NUM_OBSERVERS]; // Can observers 77 | 78 | CanHandler(CanBusNode busNumber); 79 | void logFrame(CAN_FRAME& frame); 80 | int8_t findFreeObserverData(); 81 | int8_t findFreeMailbox(); 82 | }; 83 | 84 | #endif /* CAN_HANDLER_H_ */ 85 | 86 | 87 | -------------------------------------------------------------------------------- /CanPIDListener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CanPidListener.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef CAN_PID_H_ 28 | #define CAN_PID_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "Throttle.h" 33 | #include "DeviceManager.h" 34 | #include "TickHandler.h" 35 | #include "CanHandler.h" 36 | #include "constants.h" 37 | 38 | 39 | class CanPIDConfiguration : public DeviceConfiguration { 40 | public: 41 | uint32_t pidId; //what ID are we listening for? 42 | uint32_t pidMask; 43 | bool useExtended; 44 | }; 45 | 46 | class CanPIDListener: public Device, CanObserver { 47 | public: 48 | CanPIDListener(); 49 | void setup(); 50 | void handleTick(); 51 | void handleCanFrame(CAN_FRAME *frame); 52 | DeviceId getId(); 53 | 54 | void loadConfiguration(); 55 | void saveConfiguration(); 56 | 57 | protected: 58 | 59 | private: 60 | uint32_t responseId; // the CAN id with which the response is sent; 61 | uint32_t responseMask; // the mask for the responseId 62 | bool responseExtended; // if the response is expected as an extended frame 63 | bool processShowData(CAN_FRAME* inFrame, CAN_FRAME& outFrame); 64 | bool processShowCustomData(CAN_FRAME* inFrame, CAN_FRAME& outFrame); 65 | }; 66 | 67 | #endif //CAN_PID_H_ 68 | 69 | 70 | -------------------------------------------------------------------------------- /CanThrottle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CanThrottle.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef CAN_THROTTLE_H_ 28 | #define CAN_THROTTLE_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "Throttle.h" 33 | #include "TickHandler.h" 34 | #include "CanHandler.h" 35 | #include "constants.h" 36 | #include "DeviceManager.h" 37 | 38 | enum CanCarType { 39 | unknowkn = 0x00, 40 | Volvo_S80_Gas = 0x01, 41 | Volvo_V50_Diesel = 0x02 42 | }; 43 | 44 | class CanThrottleConfiguration : public ThrottleConfiguration { 45 | public: 46 | uint16_t minimumLevel1, maximumLevel1; // values for when the pedal is at its min and max 47 | uint16_t carType; // the type of car, so we know how to interpret which bytes 48 | }; 49 | 50 | class CanThrottle: public Throttle, CanObserver { 51 | public: 52 | CanThrottle(); 53 | void setup(); 54 | void handleTick(); 55 | void handleCanFrame(CAN_FRAME *frame); 56 | DeviceId getId(); 57 | 58 | RawSignalData *acquireRawSignal(); 59 | void loadConfiguration(); 60 | void saveConfiguration(); 61 | 62 | protected: 63 | bool validateSignal(RawSignalData *); 64 | uint16_t calculatePedalPosition(RawSignalData *); 65 | 66 | private: 67 | CAN_FRAME requestFrame; // the request frame sent to the car 68 | RawSignalData rawSignal; // raw signal 69 | uint8_t ticksNoResponse; // number of ticks no response was received 70 | uint32_t responseId; // the CAN id with which the response is sent; 71 | uint32_t responseMask; // the mask for the responseId 72 | bool responseExtended; // if the response is expected as an extended frame 73 | }; 74 | 75 | #endif /* CAN_THROTTLE_H_ */ 76 | 77 | 78 | -------------------------------------------------------------------------------- /CodaMotorController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * CodaMotorController.h 3 | * 4 | * Note that the dmoc needs to have some form of input for gear selector (drive/neutral/reverse) 5 | * 6 | Copyright (c) 2014 Jack Rickard 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef CODA_H_ 30 | #define CODA_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "MotorController.h" 35 | #include "sys_io.h" 36 | #include "TickHandler.h" 37 | #include "CanHandler.h" 38 | 39 | /* 40 | * Class for Coda UQM Powerphase 100 specific configuration parameters 41 | */ 42 | class CodaMotorControllerConfiguration : public MotorControllerConfiguration { 43 | public: 44 | }; 45 | 46 | class CodaMotorController: public MotorController, CanObserver { 47 | 48 | 49 | 50 | public: 51 | virtual void handleTick(); 52 | virtual void handleCanFrame(CAN_FRAME *frame); 53 | virtual void setup(); 54 | 55 | CodaMotorController(); 56 | void timestamp(); 57 | DeviceId getId(); 58 | uint32_t getTickInterval(); 59 | 60 | 61 | virtual void loadConfiguration(); 62 | virtual void saveConfiguration(); 63 | 64 | private: 65 | byte online; //counter for whether DMOC appears to be operating 66 | byte alive; 67 | int activityCount; 68 | byte sequence; 69 | uint16_t torqueCommand; 70 | void sendCmd1(); 71 | void sendCmd2(); 72 | uint8_t genCodaCRC(uint8_t cmd, uint8_t torq_lsb, uint8_t torq_msb); 73 | 74 | }; 75 | 76 | #endif /* CODA_H_ */ 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /DCDCController.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Delphi DC-DC Converter Controller.cpp 3 | * 4 | * CAN Interface to the Delphi DC-DC converter - Handles sending of commands and reception of status frames to drive the DC-DC converter and set its output voltage. SB following. 5 | * 6 | Copyright (c) 2014 Jack Rickard 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | 30 | 31 | #include "DCDCController.h" 32 | template inline Print &operator <<(Print &obj, T arg) { obj.print(arg); return obj; } 33 | 34 | 35 | 36 | DCDCController::DCDCController() : Device() 37 | { 38 | prefsHandler = new PrefHandler(DCDC); 39 | //prefsHandler->setEnabledStatus(true); 40 | 41 | commonName = "Delphi DC-DC Converter"; 42 | 43 | } 44 | 45 | 46 | 47 | void DCDCController::handleCanFrame(CAN_FRAME *frame) 48 | { 49 | Logger::debug("DCDC msg: %X", frame->id); 50 | Logger::debug("DCDC data: %X%X%X%X%X%X%X%X", frame->data.bytes[0],frame->data.bytes[1],frame->data.bytes[2],frame->data.bytes[3],frame->data.bytes[4],frame->data.bytes[5],frame->data.bytes[6],frame->data.bytes[7]); 51 | } 52 | 53 | 54 | 55 | void DCDCController::setup() 56 | { 57 | TickHandler::getInstance()->detach(this); 58 | 59 | loadConfiguration(); 60 | Device::setup(); // run the parent class version of this function 61 | 62 | CanHandler::getInstanceCar()->attach(this, 0x1D5, 0x7ff, false); 63 | //Watch for 0x1D5 messages from Delphi converter 64 | TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_DCDC); 65 | } 66 | 67 | 68 | void DCDCController::handleTick() { 69 | 70 | Device::handleTick(); //kick the ball up to papa 71 | 72 | sendCmd(); //Send our Delphi voltage control command 73 | 74 | } 75 | 76 | 77 | /* 78 | 1D7 08 80 77 00 00 00 00 00 00 79 | For 13.0 vdc output. 80 | 81 | 1D7 08 80 8E 00 00 00 00 00 00 82 | For 13.5 vdc output. 83 | 84 | To request 14.0 vdc, the message was: 85 | 1D7 08 80 A5 00 00 00 00 00 00 86 | */ 87 | 88 | void DCDCController::sendCmd() 89 | { 90 | DCDCConfiguration *config = (DCDCConfiguration *)getConfiguration(); 91 | 92 | CAN_FRAME output; 93 | output.length = 8; 94 | output.id = 0x1D7; 95 | output.extended = 0; //standard frame 96 | output.rtr = 0; 97 | output.fid = 0; 98 | output.data.bytes[0] = 0x80; 99 | output.data.bytes[1] = 0x8E; 100 | output.data.bytes[2] = 0; 101 | output.data.bytes[3] = 0; 102 | output.data.bytes[4] = 0; 103 | output.data.bytes[5] = 0; 104 | output.data.bytes[6] = 0; 105 | output.data.bytes[7] = 0x00; 106 | 107 | CanHandler::getInstanceCar()->sendFrame(output); 108 | timestamp(); 109 | Logger::debug("Delphi DC-DC cmd: %X %X %X %X %X %X %X %X %X %d:%d:%d.%d",output.id, output.data.bytes[0], 110 | output.data.bytes[1],output.data.bytes[2],output.data.bytes[3],output.data.bytes[4],output.data.bytes[5],output.data.bytes[6],output.data.bytes[7], hours, minutes, seconds, milliseconds); 111 | } 112 | 113 | DeviceId DCDCController::getId() { 114 | return (DCDC); 115 | } 116 | 117 | uint32_t DCDCController::getTickInterval() 118 | { 119 | return CFG_TICK_INTERVAL_DCDC; 120 | } 121 | 122 | void DCDCController::loadConfiguration() { 123 | DCDCConfiguration *config = (DCDCConfiguration *)getConfiguration(); 124 | 125 | if (!config) { 126 | config = new DCDCConfiguration(); 127 | setConfiguration(config); 128 | } 129 | 130 | Device::loadConfiguration(); // call parent 131 | } 132 | 133 | void DCDCController::saveConfiguration() { 134 | Device::saveConfiguration(); 135 | } 136 | 137 | void DCDCController::timestamp() 138 | { 139 | milliseconds = (int) (millis()/1) %1000 ; 140 | seconds = (int) (millis() / 1000) % 60 ; 141 | minutes = (int) ((millis() / (1000*60)) % 60); 142 | hours = (int) ((millis() / (1000*60*60)) % 24); 143 | } 144 | 145 | 146 | -------------------------------------------------------------------------------- /DCDCController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DCDCController.h 3 | * 4 | * 5 | * 6 | Copyright (c) 2014 Jack Rickard 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef DCDC_H_ 30 | #define DCDC_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "Device.h" 35 | #include "sys_io.h" 36 | #include "TickHandler.h" 37 | #include "CanHandler.h" 38 | 39 | /* 40 | * Class for Delphi DCDC specific configuration parameters 41 | */ 42 | class DCDCConfiguration : public DeviceConfiguration { 43 | public: 44 | }; 45 | 46 | class DCDCController: public Device, CanObserver { 47 | public: 48 | virtual void handleTick(); 49 | virtual void handleCanFrame(CAN_FRAME *frame); 50 | virtual void setup(); 51 | 52 | DCDCController(); 53 | void timestamp(); 54 | DeviceId getId(); 55 | uint32_t getTickInterval(); 56 | 57 | virtual void loadConfiguration(); 58 | virtual void saveConfiguration(); 59 | 60 | private: 61 | int milliseconds ; 62 | int seconds; 63 | int minutes; 64 | int hours; 65 | void sendCmd(); 66 | }; 67 | 68 | #endif /* DCDC_H_ */ 69 | 70 | 71 | -------------------------------------------------------------------------------- /DMOC.txt: -------------------------------------------------------------------------------- 1 | This document explains a little bit of theory about the DMOC645 2 | motorcontroller object-module. 3 | 4 | The DMOC645 is a bit complicated in that you need to progressively establish 5 | operation in either speed mode or torque mode. We really don't use speed mode 6 | in vehicle applications. 7 | 8 | We control DMOC operation through two main variables and a torque command generated from our throttle: 9 | 10 | operationState= DISABLED = 0, 11 | STANDBY = 1, 12 | ENABLE = 2, 13 | POWERDOWN = 3 14 | 15 | selectedGear NEUTRAL =0 16 | DRIVE =1 17 | REVERSE=2 18 | ERROR=3 19 | 20 | 21 | The problem is, we have to allow some time for communications to establish, and then 22 | we have to progressively cycle from DISABLED to STANDBY to ENABLE. And we need acknowledgement from 23 | DMOC at each step. 24 | 25 | DMOC reports its state of operation via CAN and we hold that state in a variable titled activeState. 26 | 27 | We initialize as: 28 | selectedGear = NEUTRAL; 29 | operationState = DISABLED; 30 | actualState = DISABLED; 31 | 32 | We can set these values programmatically using two functions provided by our parent class MotorController. They are setOpState(operationState) and setSelectedGear(selectedGear). 33 | 34 | We can also set them via hardware input by activating the ENABLE input and the REVERSE input to any of the four digital inputs. 35 | When 12v is applied to the input designated as ENABLE, it will call setOpState(ENABLE). Likewise a 12v on the REVERSE input will cause a setSelectedGear(REVERSE) call. When they are in a low state, they actively setSelectedGear(DRIVE) and setOpState(DISABLED) 36 | 37 | 38 | The DMOC requires three different frames twice per second beginning very soon after power up or otherwise it faults out. 39 | 40 | We hold these in SENDCMD1, SENDCMD2, and SENDCMD3. 41 | 42 | SENDCMD1 sends a 0x232 frame we think of as the speed control frame. It is in speed mode. But we MUST transmit this frame even in torque mode. BYTE 5 is actually our ignition key state to get this thing running. Byte 6 is a bit map containing an ALIVE counter that increments by 2 from 0x00 to 0x0F. It also contains our selected gear and our requested operation state. We use the variable NEWSTATE for this. 43 | 44 | Examining our logic, if the DMOC reports, as it will initially, an activeState of DISABLED, if our operationState is DISABLED we will leave it there and in fact indicate a NEUTRAL gear selection as well, regardless of selectedGear. 45 | 46 | If DMOC reports DISABLED and we have an operationState of either STANDBY or ENABLE, we will set newstate to STANDBY and send that to the DMOC. This will continue UNTIL we receive an activeState BACK from the DMOC indicating STANDBY. 47 | 48 | Once we receive an actualState of STANDBY from the DMOC, on our next transmitted 232 frame, if our operationState is ENABLE we will send a newstate of ENABLE. 49 | 50 | Thereafter, if we receive an activeState indication from DMOC of ENABLE and our operationState is ENABLE, we continue to send ENABLE. 51 | 52 | Of course, if operationState goes to DISABLED, we will send a DISABLED to the DMOC and have to start the sequence all over again if we return to ENABLE on the operationState. 53 | 54 | IF we have a newstate of ENABLE, we also send our selectedGear instead of NEUTRAL. So the SpeedControl frame 232 is actually key to properly cycling through the DISABLED, STANDBY, and ENABLE states AND advising DMOC of our selectedGear. 55 | 56 | SENDCMD2 sends a 233 frame containing our torque command in bytes 0 and 1 and again in 2 and 3. It sends a STANDBy torque command in bytes 4 and 5. Byte 6 contains the SAME alive value as the 232 frame. 57 | 58 | Our torque command is calculated by multiplying our maximum allowed torque variable by our throttle percentage. Throttle runs from -1000 to +1000 as a percentage and is calculated by comparing the received analog values in the range of x1 to x2 to our throttle map of regen and forward torques. We multiply our throttle position x maximum torque and divide by 1000 to get a torque value that is a percentage of maxium torque, but has the sign of regen (-) or forward(+). This is added to an offset of 30,000. Numbers below 30000 are regen torque and above 30000 are forward torque. 59 | 60 | The problem comes in in REVERSE gear. DMOC takes negative values as positive torque in the reverse direction. And it takes positive values as regen in the reverse direction. By inverting the value, we can provide control in a reversed direction. 61 | 62 | 63 | And so in normal operation, we can set our selectedGear and operationState at will, and the proper cycling will occur within these two frames automatically. 64 | 65 | The only issue is on startup. We want to wait until we have received and sent some frames to establish communications before doing all this. And so we have an activity counter that is incremented by frames received, and decremented by our tick handler. Once we have accumulated a surplus of 40 on the activity counter, we can set our gear to DRIVE and our opstate to ENABLE. 66 | 67 | IF we have selected an input for either REVERSE or ENABlE, we don't want to do that. We want to leave it in neutral and disabled and let this be done by hardware signal input. If we have NOT selected inputs for these, we of course want to go ahead and set them automatically. 68 | 69 | The RUNNING advisory on our web status panel only appears on receipt of DMOC CAN packets. In fact, if we lose our stream of packets and our activity counter is decremented below 40, it will go out as well. 70 | 71 | 72 | -------------------------------------------------------------------------------- /Device.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Device.cpp 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #include "Device.h" 28 | #include "DeviceManager.h" 29 | 30 | Device::Device() { 31 | deviceConfiguration = NULL; 32 | prefsHandler = NULL; 33 | //since all derived classes eventually call this base method this will cause every device to auto register itself with the device manager 34 | DeviceManager::getInstance()->addDevice(this); 35 | commonName = "Generic Device"; 36 | } 37 | 38 | //Empty functions to handle these callbacks if the derived classes don't 39 | 40 | void Device::setup() { 41 | } 42 | 43 | char* Device::getCommonName() { 44 | return commonName; 45 | } 46 | 47 | void Device::handleTick() { 48 | } 49 | 50 | uint32_t Device::getTickInterval() { 51 | return 0; 52 | } 53 | 54 | //just bubbles up the value from the preference handler. 55 | bool Device::isEnabled() { 56 | return prefsHandler->isEnabled(); 57 | } 58 | 59 | void Device::handleMessage(uint32_t msgType, void* message) { 60 | switch (msgType) { 61 | case MSG_STARTUP: 62 | this->setup(); 63 | break; 64 | } 65 | } 66 | 67 | DeviceType Device::getType() { 68 | return DEVICE_NONE; 69 | } 70 | 71 | DeviceId Device::getId() { 72 | return INVALID; 73 | } 74 | 75 | void Device::loadConfiguration() { 76 | } 77 | 78 | void Device::saveConfiguration() { 79 | } 80 | 81 | DeviceConfiguration *Device::getConfiguration() { 82 | return this->deviceConfiguration; 83 | } 84 | 85 | void Device::setConfiguration(DeviceConfiguration *configuration) { 86 | this->deviceConfiguration = configuration; 87 | } 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /Device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Device.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef DEVICE_H_ 28 | #define DEVICE_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "DeviceTypes.h" 33 | #include "eeprom_layout.h" 34 | #include "PrefHandler.h" 35 | #include "Sys_Messages.h" 36 | #include "FaultHandler.h" 37 | 38 | /* 39 | * A abstract class to hold device configuration. It is to be accessed 40 | * by sub-classes via getConfiguration() and then cast into its 41 | * correct sub-class. 42 | */ 43 | class DeviceConfiguration { 44 | 45 | }; 46 | 47 | /* 48 | * A abstract class for all Devices. 49 | */ 50 | class Device: public TickObserver { 51 | public: 52 | Device(); 53 | virtual void setup(); 54 | virtual void handleMessage(uint32_t, void* ); 55 | virtual DeviceType getType(); 56 | virtual DeviceId getId(); 57 | void handleTick(); 58 | bool isEnabled(); 59 | virtual uint32_t getTickInterval(); 60 | char* getCommonName(); 61 | 62 | virtual void loadConfiguration(); 63 | virtual void saveConfiguration(); 64 | DeviceConfiguration *getConfiguration(); 65 | void setConfiguration(DeviceConfiguration *); 66 | 67 | protected: 68 | PrefHandler *prefsHandler; 69 | char *commonName; 70 | 71 | private: 72 | DeviceConfiguration *deviceConfiguration; // reference to the currently active configuration 73 | }; 74 | 75 | #endif /* DEVICE_H_ */ 76 | 77 | 78 | -------------------------------------------------------------------------------- /DeviceManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DeviceManager.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef DEVICEMGR_H_ 27 | #define DEVICEMGR_H_ 28 | 29 | #include "config.h" 30 | #include "Throttle.h" 31 | #include "MotorController.h" 32 | #include "CanHandler.h" 33 | #include "Device.h" 34 | #include "Sys_Messages.h" 35 | #include "DeviceTypes.h" 36 | 37 | class MotorController; // cyclic reference between MotorController and DeviceManager 38 | 39 | class DeviceManager { 40 | public: 41 | static DeviceManager *getInstance(); 42 | void addDevice(Device *device); 43 | void removeDevice(Device *device); 44 | // void addTickObserver(TickObserver *observer, uint32_t frequency); 45 | // void addCanObserver(CanObserver *observer, uint32_t id, uint32_t mask, bool extended, CanHandler::CanBusNode canBus); 46 | void sendMessage(DeviceType deviceType, DeviceId deviceId, uint32_t msgType, void* message); 47 | void setParameter(DeviceType deviceType, DeviceId deviceId, uint32_t msgType, char *key, char *value); 48 | void setParameter(DeviceType deviceType, DeviceId deviceId, uint32_t msgType, char *key, uint32_t value); 49 | uint8_t getNumThrottles(); 50 | uint8_t getNumControllers(); 51 | uint8_t getNumBMS(); 52 | uint8_t getNumChargers(); 53 | uint8_t getNumDisplays(); 54 | Throttle *getAccelerator(); 55 | Throttle *getBrake(); 56 | MotorController *getMotorController(); 57 | Device *getDeviceByID(DeviceId); 58 | Device *getDeviceByType(DeviceType); 59 | void printDeviceList(); 60 | void updateWifi(); 61 | Device *updateWifiByID(DeviceId); 62 | 63 | protected: 64 | 65 | private: 66 | DeviceManager(); // private constructor 67 | static DeviceManager *deviceManager; 68 | 69 | Device *devices[CFG_DEV_MGR_MAX_DEVICES]; 70 | Throttle *throttle; 71 | Throttle *brake; 72 | MotorController *motorController; 73 | 74 | int8_t findDevice(Device *device); 75 | uint8_t countDeviceType(DeviceType deviceType); 76 | }; 77 | 78 | #endif 79 | 80 | 81 | -------------------------------------------------------------------------------- /DeviceTypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Device.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef DEVICE_TYPES_H_ 28 | #define DEVICE_TYPES_H_ 29 | 30 | enum DeviceType { 31 | DEVICE_ANY, 32 | DEVICE_MOTORCTRL, 33 | DEVICE_BMS, 34 | DEVICE_CHARGER, 35 | DEVICE_DISPLAY, 36 | DEVICE_THROTTLE, 37 | DEVICE_BRAKE, 38 | DEVICE_MISC, 39 | DEVICE_WIFI, 40 | DEVICE_NONE 41 | }; 42 | 43 | enum DeviceId { //unique device ID for every piece of hardware possible 44 | DMOC645 = 0x1000, 45 | BRUSA_DMC5 = 0x1001, 46 | CODAUQM = 0x1002, 47 | BRUSACHARGE = 0x1010, 48 | TCCHCHARGE = 0x1011, 49 | LEAR=0x1012, 50 | THROTTLE = 0x1030, 51 | POTACCELPEDAL = 0x1031, 52 | POTBRAKEPEDAL = 0x1032, 53 | CANACCELPEDAL = 0x1033, 54 | CANBRAKEPEDAL = 0x1034, 55 | EVICTUS = 0x4400, 56 | ICHIP2128 = 0x1040, 57 | DCDC = 0x1050, 58 | THINKBMS = 0x2000, 59 | FAULTSYS = 0x4000, 60 | SYSTEM = 0x5000, 61 | HEARTBEAT = 0x5001, 62 | MEMCACHE = 0x5002, 63 | PIDLISTENER = 0x6000, 64 | ELM327EMU = 0x650, 65 | INVALID = 0xFFFF 66 | }; 67 | 68 | #endif /* DEVICE_TYPES_H_ */ 69 | 70 | 71 | -------------------------------------------------------------------------------- /DmocMotorController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DmocMotorController.h 3 | * 4 | * Note that the dmoc needs to have some form of input for gear selector (drive/neutral/reverse) 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef DMOC_H_ 30 | #define DMOC_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "MotorController.h" 35 | #include "sys_io.h" 36 | #include "TickHandler.h" 37 | #include "CanHandler.h" 38 | 39 | /* 40 | * Class for DMOC specific configuration parameters 41 | */ 42 | class DmocMotorControllerConfiguration : public MotorControllerConfiguration { 43 | public: 44 | }; 45 | 46 | class DmocMotorController: public MotorController, CanObserver { 47 | public: 48 | 49 | enum Step { 50 | SPEED_TORQUE, 51 | CHAL_RESP 52 | }; 53 | 54 | enum KeyState { 55 | OFF = 0, 56 | ON = 1, 57 | RESERVED = 2, 58 | NOACTION = 3 59 | }; 60 | 61 | 62 | 63 | public: 64 | virtual void handleTick(); 65 | virtual void handleCanFrame(CAN_FRAME *frame); 66 | virtual void setup(); 67 | void setGear(Gears gear); 68 | 69 | DmocMotorController(); 70 | DeviceId getId(); 71 | uint32_t getTickInterval(); 72 | 73 | virtual void loadConfiguration(); 74 | virtual void saveConfiguration(); 75 | 76 | private: 77 | 78 | OperationState actualState; //what the controller is reporting it is 79 | int step; 80 | byte online; //counter for whether DMOC appears to be operating 81 | byte alive; 82 | int activityCount; 83 | uint16_t torqueCommand; 84 | void timestamp(); 85 | 86 | void sendCmd1(); 87 | void sendCmd2(); 88 | void sendCmd3(); 89 | void sendCmd4(); 90 | void sendCmd5(); 91 | byte calcChecksum(CAN_FRAME thisFrame); 92 | 93 | }; 94 | 95 | #endif /* DMOC_H_ */ 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /ELM327Processor.cpp: -------------------------------------------------------------------------------- 1 | #include "ELM327Processor.h" 2 | 3 | ELM327Processor::ELM327Processor() { 4 | obd2Handler = OBD2Handler::getInstance(); 5 | } 6 | 7 | String ELM327Processor::processELMCmd(char *cmd) { 8 | String retString = String(); 9 | String lineEnding; 10 | if (bLineFeed) lineEnding = String("\r\n"); 11 | else lineEnding = String("\r"); 12 | 13 | if (!strncmp(cmd, "at", 2)) { 14 | 15 | if (!strcmp(cmd, "atz")) { //reset hardware 16 | retString.concat(lineEnding); 17 | retString.concat("ELM327 v1.3a"); 18 | } 19 | else if (!strncmp(cmd, "atsh",4)) { //set header address 20 | //ignore this - just say OK 21 | retString.concat("OK"); 22 | } 23 | else if (!strncmp(cmd, "ate",3)) { //turn echo on/off 24 | //could support echo but I don't see the need, just ignore this 25 | retString.concat("OK"); 26 | } 27 | else if (!strncmp(cmd, "ath",3)) { //turn headers on/off 28 | if (cmd[3] == '1') bHeader = true; 29 | else bHeader = false; 30 | retString.concat("OK"); 31 | } 32 | else if (!strncmp(cmd, "atl",3)) { //turn linefeeds on/off 33 | if (cmd[3] == '1') bLineFeed = true; 34 | else bLineFeed = false; 35 | retString.concat("OK"); 36 | } 37 | else if (!strcmp(cmd, "at@1")) { //send device description 38 | retString.concat("ELM327 Emulator"); 39 | } 40 | else if (!strcmp(cmd, "ati")) { //send chip ID 41 | retString.concat("ELM327 v1.3a"); 42 | } 43 | else if (!strncmp(cmd, "atat",4)) { //set adaptive timing 44 | //don't intend to support adaptive timing at all 45 | retString.concat("OK"); 46 | } 47 | else if (!strncmp(cmd, "atsp",4)) { //set protocol 48 | //theoretically we can ignore this 49 | retString.concat("OK"); 50 | } 51 | else if (!strcmp(cmd, "atdp")) { //show description of protocol 52 | retString.concat("can11/500"); 53 | } 54 | else if (!strcmp(cmd, "atdpn")) { //show protocol number (same as passed to sp) 55 | retString.concat("6"); 56 | } 57 | else if (!strcmp(cmd, "atd")) { //set to defaults 58 | retString.concat("OK"); 59 | } 60 | else if (!strncmp(cmd, "atm", 3)) { //turn memory on/off 61 | retString.concat("OK"); 62 | } 63 | else if (!strcmp(cmd, "atrv")) { //show 12v rail voltage 64 | //TODO: the system should actually have this value so it wouldn't hurt to 65 | //look it up and report the real value. 66 | retString.concat("14.2V"); 67 | } 68 | else { //by default respond to anything not specifically handled by just saying OK and pretending. 69 | retString.concat("OK"); 70 | } 71 | } 72 | else { //if no AT then assume it is a PID request. This takes the form of four bytes which form the alpha hex digit encoding for two bytes 73 | //there should be four or six characters here forming the ascii representation of the PID request. Easiest for now is to turn the ascii into 74 | //a 16 bit number and mask off to get the bytes 75 | if (strlen(cmd) == 4) { 76 | uint32_t valu = strtol((char *) cmd, NULL, 16); //the pid format is always in hex 77 | uint8_t pidnum = (uint8_t)(valu & 0xFF); 78 | uint8_t mode = (uint8_t)((valu >> 8) & 0xFF); 79 | Logger::debug(ELM327EMU, "Mode: %i, PID: %i", mode, pidnum); 80 | char out[7]; 81 | char buff[10]; 82 | if (obd2Handler->processRequest(mode, pidnum, NULL, out)) { 83 | if (bHeader) { 84 | retString.concat("7E8"); 85 | out[0] += 2; //not sending only data bits but mode and pid too 86 | for (int i = 0; i <= out[0]; i++) { 87 | sprintf(buff, "%02X", out[i]); 88 | retString.concat(buff); 89 | } 90 | } 91 | else { 92 | mode += 0x40; 93 | sprintf(buff, "%02X", mode); 94 | retString.concat(buff); 95 | sprintf(buff, "%02X", pidnum); 96 | retString.concat(buff); 97 | for (int i = 1; i <= out[0]; i++) { 98 | sprintf(buff, "%02X", out[i+2]); 99 | retString.concat(buff); 100 | } 101 | } 102 | } 103 | } 104 | } 105 | 106 | retString.concat(lineEnding); 107 | retString.concat(">"); //prompt to show we're ready to receive again 108 | 109 | return retString; 110 | } 111 | 112 | 113 | -------------------------------------------------------------------------------- /ELM327Processor.h: -------------------------------------------------------------------------------- 1 | #ifndef ELMPROC_H_ 2 | #define ELMPROC_H_ 3 | 4 | #include 5 | #include "config.h" 6 | #include "constants.h" 7 | #include "Sys_Messages.h" 8 | #include "DeviceTypes.h" 9 | #include "OBD2Handler.h" 10 | 11 | class ELM327Processor { 12 | public: 13 | ELM327Processor(); 14 | String processELMCmd(char *cmd); 15 | private: 16 | OBD2Handler *obd2Handler; 17 | char buffer[30]; // a buffer for various string conversions 18 | bool bLineFeed; 19 | bool bHeader; 20 | }; 21 | 22 | #endif 23 | 24 | 25 | -------------------------------------------------------------------------------- /ELM327_Emu.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ELM327_Emu.cpp 3 | * 4 | * Class emulates the serial comm of an ELM327 chip - Used to create an OBDII interface 5 | * 6 | * Created: 3/18/2014 7 | * Author: Collin Kidder 8 | */ 9 | 10 | /* 11 | Copyright (c) 2013-2014 Collin Kidder, Michael Neuweiler, Charles Galpin 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining 14 | a copy of this software and associated documentation files (the 15 | "Software"), to deal in the Software without restriction, including 16 | without limitation the rights to use, copy, modify, merge, publish, 17 | distribute, sublicense, and/or sell copies of the Software, and to 18 | permit persons to whom the Software is furnished to do so, subject to 19 | the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included 22 | in all copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 27 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 28 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 29 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 30 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | */ 32 | 33 | #include "ELM327_Emu.h" 34 | 35 | 36 | /* 37 | * Constructor. Assign serial interface to use for comm with bluetooth adapter we're emulating with 38 | */ 39 | ELM327Emu::ELM327Emu() { 40 | prefsHandler = new PrefHandler(ELM327EMU); 41 | 42 | uint8_t sys_type; 43 | sysPrefs->read(EESYS_SYSTEM_TYPE, &sys_type); 44 | if (sys_type == 3 || sys_type == 4) 45 | serialInterface = &Serial2; 46 | else //older hardware used this instead 47 | serialInterface = &Serial3; 48 | 49 | commonName = "ELM327 Emulator over Bluetooth"; 50 | } 51 | 52 | /* 53 | * Constructor. Pass serial interface to use 54 | */ 55 | ELM327Emu::ELM327Emu(USARTClass *which) { 56 | prefsHandler = new PrefHandler(ELM327EMU); 57 | serialInterface = which; 58 | } 59 | 60 | 61 | /* 62 | * Initialization of hardware and parameters 63 | */ 64 | void ELM327Emu::setup() { 65 | 66 | Logger::info("add device: ELM327 emulator (id: %X, %X", ELM327EMU, this); 67 | 68 | TickHandler::getInstance()->detach(this); 69 | 70 | tickCounter = 0; 71 | ibWritePtr = 0; 72 | serialInterface->begin(9600); 73 | 74 | elmProc = new ELM327Processor(); 75 | 76 | //this isn't a wifi link but the timer interval can be the same 77 | //because it serves a similar function and has similar timing requirements 78 | TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_WIFI); 79 | } 80 | 81 | /* 82 | * Send a command to ichip. The "AT+i" part will be added. 83 | */ 84 | void ELM327Emu::sendCmd(String cmd) { 85 | serialInterface->write("AT"); 86 | serialInterface->print(cmd); 87 | serialInterface->write(13); 88 | loop(); // parse the response 89 | } 90 | 91 | /* 92 | 93 | */ 94 | void ELM327Emu::handleTick() { 95 | 96 | } 97 | 98 | /* 99 | * Handle a message sent by the DeviceManager. 100 | */ 101 | void ELM327Emu::handleMessage(uint32_t messageType, void* message) { 102 | Device::handleMessage(messageType, message); 103 | 104 | switch (messageType) { 105 | case MSG_SET_PARAM: { 106 | break; 107 | } 108 | case MSG_CONFIG_CHANGE: 109 | break; 110 | case MSG_COMMAND: 111 | sendCmd((char *)message); 112 | break; 113 | } 114 | } 115 | 116 | /* 117 | * Called in the main loop (hopefully) in order to process serial input waiting for us 118 | * from the wifi module. It should always terminate its answers with 13 so buffer 119 | * until we get 13 (CR) and then process it. 120 | * But, for now just echo stuff to our serial port for debugging 121 | */ 122 | 123 | void ELM327Emu::loop() { 124 | int incoming; 125 | while (serialInterface->available()) { 126 | incoming = serialInterface->read(); 127 | if (incoming != -1) { //and there is no reason it should be -1 128 | if (incoming == 13 || ibWritePtr > 126) { // on CR or full buffer, process the line 129 | incomingBuffer[ibWritePtr] = 0; //null terminate the string 130 | ibWritePtr = 0; //reset the write pointer 131 | 132 | if (Logger::isDebug()) 133 | Logger::debug(ELM327EMU, incomingBuffer); 134 | processCmd(); 135 | 136 | } else { // add more characters 137 | if (incoming != 10 && incoming != ' ') // don't add a LF character or spaces. Strip them right out 138 | incomingBuffer[ibWritePtr++] = (char)tolower(incoming); //force lowercase to make processing easier 139 | } 140 | } else 141 | return; 142 | } 143 | } 144 | 145 | /* 146 | * There is no need to pass the string in here because it is local to the class so this function can grab it by default 147 | * But, for reference, this cmd processes the command in incomingBuffer 148 | */ 149 | void ELM327Emu::processCmd() { 150 | String retString = elmProc->processELMCmd(incomingBuffer); 151 | 152 | serialInterface->print(retString); 153 | if (Logger::isDebug()) { 154 | char buff[30]; 155 | retString.toCharArray(buff, 30); 156 | Logger::debug(ELM327EMU, buff); 157 | } 158 | 159 | } 160 | 161 | DeviceType ELM327Emu::getType() { 162 | return DEVICE_MISC; 163 | } 164 | 165 | DeviceId ELM327Emu::getId() { 166 | return (ELM327EMU); 167 | } 168 | 169 | void ELM327Emu::loadConfiguration() { 170 | ELM327Configuration *config = (ELM327Configuration *)getConfiguration(); 171 | 172 | if (prefsHandler->checksumValid()) { //checksum is good, read in the values stored in EEPROM 173 | Logger::debug(ELM327EMU, "Valid checksum so using stored elm327 emulator config values"); 174 | //TODO: implement processing of config params for WIFI 175 | // prefsHandler->read(EESYS_WIFI0_SSID, &config->ssid); 176 | } 177 | } 178 | 179 | void ELM327Emu::saveConfiguration() { 180 | ELM327Configuration *config = (ELM327Configuration *) getConfiguration(); 181 | 182 | //TODO: implement processing of config params for WIFI 183 | // prefsHandler->write(EESYS_WIFI0_SSID, config->ssid); 184 | // prefsHandler->saveChecksum(); 185 | } 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /ELM327_Emu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ELM327_Emu.h 3 | * 4 | * Class emulates the serial comm of an ELM327 chip - Used to create an OBDII interface 5 | * 6 | * Created: 3/18/2014 7 | * Author: Collin Kidder 8 | */ 9 | 10 | /* 11 | Copyright (c) 2013-2014 Collin Kidder, Michael Neuweiler, Charles Galpin 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining 14 | a copy of this software and associated documentation files (the 15 | "Software"), to deal in the Software without restriction, including 16 | without limitation the rights to use, copy, modify, merge, publish, 17 | distribute, sublicense, and/or sell copies of the Software, and to 18 | permit persons to whom the Software is furnished to do so, subject to 19 | the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included 22 | in all copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 27 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 28 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 29 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 30 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 | */ 32 | 33 | /* 34 | List of AT commands to support: 35 | AT E0 (turn echo off) 36 | AT H (0/1) - Turn headers on or off - headers are used to determine how many ECU√≠s present (hint: only send one response to 0100 and emulate a single ECU system to save time coding) 37 | AT L0 (Turn linefeeds off - just use CR) 38 | AT Z (reset) 39 | AT SH - Set header address - seems to set the ECU address to send to (though you may be able to ignore this if you wish) 40 | AT @1 - Display device description - ELM327 returns: Designed by Andy Honecker 2011 41 | AT I - Cause chip to output its ID: ELM327 says: ELM327 v1.3a 42 | AT AT (0/1/2) - Set adaptive timing (though you can ignore this) 43 | AT SP (set protocol) - you can ignore this 44 | AT DP (get protocol by name) - (always return can11/500) 45 | AT DPN (get protocol by number) - (always return 6) 46 | AT RV (adapter voltage) - Send something like 14.4V 47 | */ 48 | 49 | 50 | #ifndef ELM327_H_ 51 | #define ELM327_H_ 52 | 53 | #include 54 | #include "config.h" 55 | #include "constants.h" 56 | #include "DeviceManager.h" 57 | #include "Sys_Messages.h" 58 | #include "DeviceTypes.h" 59 | #include "ELM327Processor.h" 60 | 61 | extern PrefHandler *sysPrefs; 62 | 63 | /* 64 | * The extended configuration class with additional parameters for ichip WLAN 65 | */ 66 | class ELM327Configuration : public DeviceConfiguration { 67 | public: 68 | }; 69 | 70 | class ELM327Emu : public Device { 71 | public: 72 | 73 | ELM327Emu(); 74 | ELM327Emu(USARTClass *which); 75 | void setup(); //initialization on start up 76 | void handleTick(); //periodic processes 77 | void handleMessage(uint32_t messageType, void* message); 78 | DeviceType getType(); 79 | DeviceId getId(); 80 | void loop(); 81 | void sendCmd(String cmd); 82 | 83 | void loadConfiguration(); 84 | void saveConfiguration(); 85 | 86 | private: 87 | USARTClass *serialInterface; //Allows for retargetting which serial port we use 88 | ELM327Processor *elmProc; 89 | char incomingBuffer[128]; //storage for one incoming line 90 | int tickCounter; 91 | int ibWritePtr; 92 | int currReply; 93 | char buffer[30]; // a buffer for various string conversions 94 | 95 | void processCmd(); 96 | }; 97 | 98 | #endif 99 | 100 | 101 | -------------------------------------------------------------------------------- /EVIC.h: -------------------------------------------------------------------------------- 1 | /* 2 | * EVIC.h 3 | * 4 | * * Class to interface with the Electric Vehicle Interface Controller EVIC by Andromeda Interfaces. This Class will extract operating data from the GEVCU and send to EVIC via CAN message for display. 5 | * 6 | * 7 | * Created: 1/28/2015 8 | * Author: Jack Rickard 9 | 10 | Copyright (c) 2015 Jack Rickard 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included 21 | in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 27 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 28 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 29 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | */ 31 | 32 | #ifndef EVIC_H_ 33 | #define EVIC_H_ 34 | 35 | #include 36 | #include "config.h" 37 | #include "constants.h" 38 | #include "Device.h" 39 | #include "TickHandler.h" 40 | #include "CanHandler.h" 41 | #include "DeviceManager.h" 42 | #include "Sys_Messages.h" 43 | #include "DeviceTypes.h" 44 | 45 | extern PrefHandler *sysPrefs; 46 | 47 | 48 | class EVICConfiguration: public DeviceConfiguration { 49 | public: 50 | //uint8_t capacity; 51 | }; 52 | 53 | 54 | class EVIC: public Device, CanObserver { 55 | public: 56 | 57 | EVIC(); 58 | //EVIC(USARTClass *which); 59 | virtual void handleTick(); 60 | virtual void handleCanFrame(CAN_FRAME *frame); 61 | 62 | virtual void setup(); //initialization on start up 63 | void timestamp(); 64 | DeviceType getType(); 65 | DeviceId getId(); 66 | 67 | char *getTimeRunning(); 68 | void loadConfiguration(); 69 | void saveConfiguration(); 70 | int16_t getdcVoltage(); 71 | int16_t getdcCurrent(); 72 | uint16_t getAH(); 73 | uint8_t getCapacity(); 74 | void setCapacity(uint8_t capacity); 75 | uint8_t getSOC(); 76 | int16_t getPower(); 77 | int16_t getkWh(); 78 | int16_t getTemperatureMotor(); 79 | int16_t getTemperatureInverter(); 80 | int16_t getRPM(); 81 | uint8_t getCellTemp1(); 82 | uint8_t getCellTemp2(); 83 | uint8_t getCellTemp3(); 84 | uint8_t getCellTemp4(); 85 | uint8_t getCellHi(); 86 | uint8_t getCello(); 87 | 88 | unsigned long timemark; 89 | unsigned long timemark2; 90 | int16_t torqueActual; 91 | int16_t speedActual; 92 | int16_t dcVoltage; 93 | int16_t dcCurrent; 94 | uint16_t nominalVolt; 95 | uint16_t AH; 96 | uint8_t capacity; 97 | uint8_t SOC; 98 | int16_t Power; 99 | int16_t kWh; 100 | int16_t temperatureMotor; 101 | int16_t temperatureInverter; 102 | int16_t rpm; 103 | uint8_t celltemp1; 104 | uint8_t celltemp2; 105 | uint8_t celltemp3; 106 | uint8_t celltemp4; 107 | uint8_t CellHi; 108 | uint8_t Cello; 109 | 110 | private: 111 | void sendTestCmdCurtis(); 112 | void sendTestCmdOrion(); 113 | void sendCmdCurtis(); 114 | void sendCmdOrion(); 115 | 116 | double AHf; 117 | double milliAH; 118 | float SOCf; 119 | int milliseconds ; 120 | int seconds; 121 | int minutes; 122 | int hours ; 123 | unsigned long elapsedtime; 124 | int16_t DCV; 125 | int16_t DCA; 126 | int8_t TEMPM; 127 | int8_t TEMPI; 128 | 129 | int tickCounter; 130 | char buffer[30]; // a buffer for various string conversions 131 | uint32_t lastSentTime; 132 | boolean weHave505; 133 | boolean testMode; 134 | 135 | 136 | }; 137 | 138 | #endif 139 | 140 | -------------------------------------------------------------------------------- /FaultCodes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * config.h 3 | * 4 | * Defines the allowable fault codes 5 | 6 | Copyright (c) 2014 Collin Kidder, Michael Neuweiler, Charles Galpin, Jack Rickard 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | */ 28 | 29 | #ifndef FAULTCODES_H_ 30 | #define FAULTCODES_H_ 31 | 32 | /* 33 | Format these fault codes in DTC format. 34 | DTC uses 16 bits to store a code 35 | Byte A is the first byte, B is the second byte 36 | A7-6 = Which fault system (00=P=PowerTrain, 01=C=Chassis, 10=B=Body, 11=U=Network) 37 | A5-4 = First Digit (0-3) 38 | A3-0 = Second Digit (0-F) 39 | B7-4 = Third Digit (0-F) 40 | B3-0 = Last / Fourth Digit (0-F) 41 | 42 | Many codes are already used in ICE vehicles but rarely with hex digits so exclusively use 43 | codes with hex digits to avoid overlap 44 | */ 45 | 46 | enum FAULTCODE { 47 | FAULT_NONE = 0, 48 | 49 | //The A throttle seems to be stuck low 50 | FAULT_THROTTLE_LOW_A = 0x0F01, //P0F01 51 | 52 | //The A throttle seems to be stuck high 53 | FAULT_THROTTLE_HIGH_A = 0x0F02, //P0F02 54 | 55 | //The B throttle seems to be stuck low 56 | FAULT_THROTTLE_LOW_B = 0x0F06, //P0F06 57 | 58 | //The B throttle seems to be stuck high 59 | FAULT_THROTTLE_HIGH_B = 0x0F07, //P0F07 60 | 61 | //The C throttle seems to be stuck low 62 | FAULT_THROTTLE_LOW_C = 0x0F0A, //P0F0A 63 | 64 | //The C throttle seems to be stuck high 65 | FAULT_THROTTLE_HIGH_C = 0x0F0B, //P0F0B 66 | 67 | //Throttles A and B do not match 68 | FAULT_THROTTLE_MISMATCH_AB = 0x0F11, //P0F11 69 | 70 | //Throttles A and C do not match 71 | FAULT_THROTTLE_MISMATCH_AC = 0x0F12, //P0F12 72 | 73 | //Throttles B and C do not match 74 | FAULT_THROTTLE_MISMATCH_BC = 0x0F13, //P0F13 75 | 76 | //There was a general fault in the throttle 77 | FAULT_THROTTLE_MISC = 0x0F40, //P0F40 78 | 79 | //There was a problem communicating with an external throttle module 80 | FAULT_THROTTLE_COMM = 0x0F60, //P0F60 81 | 82 | //The brake input seems to be stuck low 83 | FAULT_BRAKE_LOW = 0x0B01, //P0B01 84 | 85 | //The brake input seems to be stuck high 86 | FAULT_BRAKE_HIGH = 0x0B02, //P0B02 87 | 88 | //There was a problem communicating with an external brake module 89 | FAULT_BRAKE_COMM = 0x0B60, //P0B60 90 | 91 | //The +12V battery or DC/DC system seems to have excessively high voltage 92 | FAULT_12V_BATT_HIGH = 0x0A01, //P0A01 93 | 94 | //The +12V battery or DC/DC system seems to have excessively low voltage 95 | FAULT_12V_BATT_LOW = 0x0A02, //P0A02 96 | 97 | //The HV battery has too high of a voltage 98 | FAULT_HV_BATT_HIGH = 0x0A11, //P0A11 99 | 100 | //The HV battery has too low of a voltage 101 | FAULT_HV_BATT_LOW = 0x0A12, //P0A12 102 | 103 | //A request has been made for more current than allowable from the HV battery 104 | FAULT_HV_BATT_OVERCURR = 0x0A30, //P0A30 105 | 106 | //The HV battery is too cold 107 | FAULT_HV_BATT_UNDERTEMP = 0x0A50, //P0A50 108 | 109 | //The HV battery is too hot 110 | FAULT_HV_BATT_OVERTEMP = 0x0A51, //P0A51 111 | 112 | //There is a problem with isolation of HV from the chassis 113 | FAULT_HV_BATT_ISOLATION = 0x0A70, //P0A70 114 | 115 | //A cell in the HV pack is too high of a voltage 116 | FAULT_HV_CELL_HIGH = 0x0AA1, //P0AA1 117 | 118 | //A cell in the HV pack is too low of a voltage 119 | FAULT_HV_CELL_LOW = 0x0AA2, //P0AA2 120 | 121 | //A cell in the HV pack is too cold 122 | FAULT_HV_CELL_UNDERTEMP = 0x0AB0, //P0AB0 123 | 124 | //A cell in the HV pack is too hot 125 | FAULT_HV_CELL_OVERTEMP = 0x0AB1, //P0AB1 126 | 127 | //BMS failed to initialize properly 128 | FAULT_BMS_INIT = 0xCC10, //U0C10 129 | 130 | //There was a problem communicating with the BMS 131 | FAULT_BMS_COMM = 0xCC60, //U0C60 132 | 133 | //There was a general fault at the BMS 134 | FAULT_BMS_MISC = 0xCC40, //U0C40 135 | 136 | //The motor is too hot 137 | FAULT_MOTOR_OVERTEMP = 0x0D50, //P0D50 138 | 139 | //The motor controller is too hot 140 | FAULT_MOTORCTRL_OVERTEMP = 0x0D80, //P0D80 141 | 142 | //There was a problem communicating with the motor controller 143 | FAULT_MOTORCTRL_COMM = 0x0D60, //P0D60 144 | 145 | //There was a general fault in the motor controller 146 | FAULT_MOTORCTRL_MISC = 0x0D40, //P0D40 147 | 148 | //The motor and controller cannot satisfy the torque request 149 | FAULT_MOTORCTRL_INSUFF_TORQUE = 0x0D10, //P0D10 150 | 151 | //The motor is spinning faster that it should be 152 | FAULT_MOTORCTRL_EXCESSIVE_SPEED = 0x0D20, //P0D20 153 | 154 | //The motor is providing more torque than it should be (didn't request this much) 155 | FAULT_MOTORCTRL_EXCESSIVE_TORQUE = 0x0D25, //P0D25 156 | 157 | //It seems that we cannot enable the motor controller though we've tried. 158 | FAULT_MOTORCTRL_CANT_ENABLE = 0x0DA0, //P0DA0 159 | 160 | //It seems we cannot go into drive even though we asked to go into drive 161 | FAULT_MOTORCTRL_CANT_DRIVE = 0x0DA4, //P0DA4 162 | 163 | //It seems we cannot go into reverse even though we asked to go into reverse 164 | FAULT_MOTORCTRL_CANT_REVERSE = 0x0DA8, //P0DA8 165 | 166 | //there was a request for power from the motor but the controller is not in a state to provide power 167 | FAULT_MOTORCTRL_POWERREQ_INV = 0x0DB0 //P0DB0 168 | }; 169 | 170 | 171 | #endif 172 | 173 | 174 | -------------------------------------------------------------------------------- /FaultHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FaultHandler.h 3 | * 4 | * Creates a universal fault handling system that stores faults in EEPROM and can create, return, and clear 5 | * fault data. Could be the basis for an OBDII compliant fault database or could be used on its own 6 | * 7 | * Technically, one can't clear or erase faults. They get acknowledged and quit showing up 8 | * 9 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining 12 | a copy of this software and associated documentation files (the 13 | "Software"), to deal in the Software without restriction, including 14 | without limitation the rights to use, copy, modify, merge, publish, 15 | distribute, sublicense, and/or sell copies of the Software, and to 16 | permit persons to whom the Software is furnished to do so, subject to 17 | the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included 20 | in all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 27 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | 32 | #ifndef FAULT_H_ 33 | #define FAULT_H_ 34 | 35 | #include 36 | #include "config.h" 37 | #include "Logger.h" 38 | #include "FaultCodes.h" 39 | #include "MemCache.h" 40 | 41 | extern MemCache *memCache; 42 | 43 | //structure to use for storing and retrieving faults. 44 | //Stores the info a fault record will contain. 45 | typedef struct { 46 | uint32_t timeStamp; //number of 47 | uint16_t device; //which device is generating this fault 48 | uint16_t faultCode; //set by the device itself. There is a universal list of codes 49 | uint8_t ack : 1; ////whether this fault has been acknowledged or not 1 = ack'd 50 | uint8_t ongoing : 1; //whether fault still seems to be happening currently 1 = still going on 51 | } FAULT; //should be 9 bytes because the bottom two are bit fields in a single byte 52 | 53 | 54 | class FaultHandler : public TickObserver { 55 | public: 56 | FaultHandler(); //constructor 57 | uint16_t raiseFault(uint16_t device, uint16_t code, bool ongoing); //raise a new fault. Returns the fault # where this was stored 58 | void cancelOngoingFault(uint16_t device, uint16_t code); //if this fault was registered as ongoing then cancel it (set not ongoing) otherwise do nothing 59 | bool getNextFault(FAULT*); //get the next un-ack'd fault. Will also get first fault if the first call and you forgot to call getFirstFault 60 | bool getFault(uint16_t fault, FAULT*); 61 | uint16_t getFaultCount(); 62 | void handleTick(); 63 | void setup(); 64 | 65 | uint16_t setFaultACK(uint16_t fault); //acknowledge the fault # - returns fault # if successful (0xFFFF otherwise) 66 | uint16_t setFaultOngoing(uint16_t fault, bool ongoing); //set value of ongoing flag - returns fault # on success 67 | 68 | private: 69 | void loadFromEEPROM(); 70 | void saveToEEPROM(); 71 | void writeFaultToEEPROM(int faultnum); 72 | 73 | uint16_t faultWritePointer; //fault # we're up to for writing. Location in EEPROM is start + (fault_ptr * sizeof(FAULT)) 74 | uint16_t faultReadPointer; //fault # we're at when reading. 75 | FAULT faultList[CFG_FAULT_HISTORY_SIZE]; //store up to 50 faults for a long history. 50*9 = 450 bytes of EEPROM 76 | uint32_t globalTime; //how long the unit has been running in total (across all start ups). 77 | uint32_t baseTime; //the time loaded at system start up. millis() / 100 is added to this to get the above time 78 | }; 79 | 80 | extern FaultHandler faultHandler; 81 | 82 | #endif /* FAULT_H_ */ 83 | 84 | 85 | -------------------------------------------------------------------------------- /GEVCU.h: -------------------------------------------------------------------------------- 1 | /* 2 | * GEVCU.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef GEVCU_H_ 28 | #define GEVCU_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "Device.h" 33 | #include "Throttle.h" 34 | #include "CanThrottle.h" 35 | #include "CanBrake.h" 36 | #include "PotThrottle.h" 37 | #include "PotBrake.h" 38 | #include "BatteryManager.h" 39 | #include "ThinkBatteryManager.h" 40 | #include "MotorController.h" 41 | #include "DmocMotorController.h" 42 | #include "BrusaMotorController.h" 43 | #include "Heartbeat.h" 44 | #include "sys_io.h" 45 | #include "CanHandler.h" 46 | #include "MemCache.h" 47 | #include "ThrottleDetector.h" 48 | #include "DeviceManager.h" 49 | #include "SerialConsole.h" 50 | #include "ELM327_Emu.h" 51 | #include "ichip_2128.h" 52 | #include "Sys_Messages.h" 53 | #include "CodaMotorController.h" 54 | #include "FaultHandler.h" 55 | #include "DCDCController.h" 56 | #include "EVIC.h" 57 | 58 | #ifdef __cplusplus 59 | extern "C" { 60 | #endif 61 | void loop(); 62 | void setup(); 63 | 64 | #ifdef __cplusplus 65 | } // extern "C" 66 | #endif 67 | 68 | #define SYSTEM_PROTO 1 69 | #define SYSTEM_DUED 2 70 | #define SYSTEM_GEVCU3 3 71 | 72 | #endif /* GEVCU_H_ */ 73 | 74 | 75 | -------------------------------------------------------------------------------- /GEVCU.kdev4: -------------------------------------------------------------------------------- 1 | [Project] 2 | Name=GEVCU 3 | Manager=KDevCMakeManager 4 | VersionControl=kdevgit 5 | -------------------------------------------------------------------------------- /GEVCU.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GEVCU", "GEVCU.vcxproj", "{6BFAB833-3C53-4597-9B31-C33D5EA78172}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {6BFAB833-3C53-4597-9B31-C33D5EA78172}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {6BFAB833-3C53-4597-9B31-C33D5EA78172}.Debug|Win32.Build.0 = Debug|Win32 14 | {6BFAB833-3C53-4597-9B31-C33D5EA78172}.Release|Win32.ActiveCfg = Release|Win32 15 | {6BFAB833-3C53-4597-9B31-C33D5EA78172}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Heartbeat.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Heartbeat.c 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #include "Heartbeat.h" 28 | 29 | Heartbeat::Heartbeat() { 30 | led = false; 31 | throttleDebug = false; 32 | } 33 | 34 | void Heartbeat::setup() { 35 | TickHandler::getInstance()->detach(this); 36 | 37 | TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_HEARTBEAT); 38 | } 39 | 40 | void Heartbeat::setThrottleDebug(bool debug) { 41 | throttleDebug = debug; 42 | } 43 | 44 | bool Heartbeat::getThrottleDebug() { 45 | return throttleDebug; 46 | } 47 | 48 | void Heartbeat::handleTick() { 49 | // Print a dot if no other output has been made since the last tick 50 | if (Logger::getLastLogTime() < lastTickTime) { 51 | SerialUSB.print('.'); 52 | if ((++dotCount % 80) == 0) { 53 | SerialUSB.println(); 54 | } 55 | } 56 | lastTickTime = millis(); 57 | 58 | if (led) { 59 | digitalWrite(BLINK_LED, HIGH); 60 | } else { 61 | digitalWrite(BLINK_LED, LOW); 62 | } 63 | led = !led; 64 | 65 | if (throttleDebug) { 66 | MotorController *motorController = DeviceManager::getInstance()->getMotorController(); 67 | Throttle *accelerator = DeviceManager::getInstance()->getAccelerator(); 68 | Throttle *brake = DeviceManager::getInstance()->getBrake(); 69 | 70 | Logger::console(""); 71 | if (motorController) { 72 | Logger::console("Motor Controller Status-> isRunning: %T isFaulted: %T", motorController->isRunning(), motorController->isFaulted()); 73 | } 74 | 75 | Logger::console("AIN0: %d, AIN1: %d, AIN2: %d, AIN3: %d", getAnalog(0), getAnalog(1), getAnalog(2), getAnalog(3)); 76 | Logger::console("DIN0: %d, DIN1: %d, DIN2: %d, DIN3: %d", getDigital(0), getDigital(1), getDigital(2), getDigital(3)); 77 | Logger::console("DOUT0: %d, DOUT1: %d, DOUT2: %d, DOUT3: %d,DOUT4: %d, DOUT5: %d, DOUT6: %d, DOUT7: %d", getOutput(0), getOutput(1), getOutput(2), getOutput(3),getOutput(4), getOutput(5), getOutput(6), getOutput(7)); 78 | 79 | if (accelerator) { 80 | Logger::console("Is throttle currently faulted: %T Throttle level: %i", accelerator->isFaulted(), accelerator->getLevel()); 81 | RawSignalData *rawSignal = accelerator->acquireRawSignal(); 82 | Logger::console("Throttle rawSignal1: %d, rawSignal2: %d", rawSignal->input1, rawSignal->input2); 83 | } 84 | if (brake) { 85 | Logger::console("Brake Output Level: %i", brake->getLevel()); 86 | RawSignalData *rawSignal = brake->acquireRawSignal(); 87 | Logger::console("Brake rawSignal1: %d", rawSignal->input1); 88 | } 89 | } 90 | } 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /Heartbeat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Heartbeat.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef HEARTBEAT_H_ 28 | #define HEARTBEAT_H_ 29 | 30 | #include "config.h" 31 | #include "TickHandler.h" 32 | #include "DeviceManager.h" 33 | #include "sys_io.h" 34 | 35 | class Heartbeat: public TickObserver { 36 | public: 37 | Heartbeat(); 38 | void setup(); 39 | void handleTick(); 40 | void setThrottleDebug(bool debug); 41 | bool getThrottleDebug(); 42 | 43 | protected: 44 | 45 | private: 46 | bool led; 47 | bool throttleDebug; 48 | int dotCount; 49 | uint32_t lastTickTime; 50 | }; 51 | 52 | #endif /* HEARTBEAT_H_ */ 53 | 54 | 55 | -------------------------------------------------------------------------------- /Logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Logger.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef LOGGER_H_ 28 | #define LOGGER_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "DeviceTypes.h" 33 | #include "constants.h" 34 | 35 | class Logger { 36 | public: 37 | enum LogLevel { 38 | Debug = 0, Info = 1, Warn = 2, Error = 3, Off = 4 39 | }; 40 | static void debug(char *, ...); 41 | static void debug(DeviceId, char *, ...); 42 | static void info(char *, ...); 43 | static void info(DeviceId, char *, ...); 44 | static void warn(char *, ...); 45 | static void warn(DeviceId, char *, ...); 46 | static void error(char *, ...); 47 | static void error(DeviceId, char *, ...); 48 | static void console(char *, ...); 49 | static void setLoglevel(LogLevel); 50 | static LogLevel getLogLevel(); 51 | static uint32_t getLastLogTime(); 52 | static boolean isDebug(); 53 | private: 54 | static LogLevel logLevel; 55 | static uint32_t lastLogTime; 56 | 57 | static void log(DeviceId, LogLevel, char *format, va_list); 58 | static void logMessage(char *format, va_list args); 59 | static void printDeviceName(DeviceId); 60 | }; 61 | 62 | #endif /* LOGGER_H_ */ 63 | 64 | 65 | -------------------------------------------------------------------------------- /MemCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MemCache.h 3 | * 4 | * Handles caching of EEPROM pages to RAM 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef MEM_CACHE_H_ 30 | #define MEM_CACHE_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "TickHandler.h" 35 | #include 36 | 37 | //Total # of allowable pages to cache. Limits RAM usage 38 | #define NUM_CACHED_PAGES 16 39 | 40 | //maximum allowable age of a cache 41 | #define MAX_AGE 128 42 | 43 | /* # of system ticks per aging cycle. There are 128 aging levels total so 44 | // multiply 128 by this aging period and multiple that by system tick duration 45 | // to determine how long it will take for a page to age out fully and get written 46 | // if dirty. For instance, 128 levels * 500 aging period * 10ms (100Hz tick) = 640 seconds 47 | // EEPROM handles about 1 million write cycles. So, a flush time of 100 seconds means that 48 | // continuous writing would last 100M seconds which is 3.17 years 49 | // Another way to look at it is that 128 aging levels * 40ms tick is 5.12 seconds to flush for 50 | // each aging period below. Adjust acccordingly. 51 | */ 52 | #define AGING_PERIOD 60 53 | 54 | //Current parameters as of Sept 7 2014 = 128 * 40ms * 60 = 307.2 seconds to flush = about 10 years EEPROM life 55 | 56 | class MemCache: public TickObserver { 57 | public: 58 | void setup(); 59 | void handleTick(); 60 | void FlushSinglePage(); 61 | void FlushAllPages(); 62 | void FlushPage(uint8_t page); 63 | void FlushAddress(uint32_t address); 64 | void InvalidatePage(uint8_t page); 65 | void InvalidateAddress(uint32_t address); 66 | void InvalidateAll(); 67 | void AgeFullyPage(uint8_t page); 68 | void AgeFullyAddress(uint32_t address); 69 | 70 | boolean Write(uint32_t address, uint8_t valu); 71 | boolean Write(uint32_t address, uint16_t valu); 72 | boolean Write(uint32_t address, uint32_t valu); 73 | boolean Write(uint32_t address, void* data, uint16_t len); 74 | 75 | //It's sort of weird to make the read function take a reference but it allows for overloading 76 | boolean Read(uint32_t address, uint8_t* valu); 77 | boolean Read(uint32_t address, uint16_t* valu); 78 | boolean Read(uint32_t address, uint32_t* valu); 79 | boolean Read(uint32_t address, void* data, uint16_t len); 80 | 81 | MemCache(); 82 | 83 | private: 84 | typedef struct { 85 | uint8_t data[256]; 86 | uint32_t address; //address of start of page 87 | uint8_t age; // 88 | boolean dirty; 89 | } PageCache; 90 | 91 | PageCache pages[NUM_CACHED_PAGES]; 92 | boolean isWriting(); 93 | uint8_t cache_hit(uint32_t address); 94 | void cache_age(); 95 | uint8_t cache_findpage(); 96 | uint8_t cache_readpage(uint32_t addr); 97 | boolean cache_writepage(uint8_t page); 98 | uint8_t agingTimer; 99 | }; 100 | 101 | #endif /* MEM_CACHE_H_ */ 102 | 103 | 104 | -------------------------------------------------------------------------------- /MotorController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MotorController.h 3 | * 4 | * Parent class for all motor controllers. 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef MOTORCTRL_H_ 30 | #define MOTORCTRL_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "Device.h" 35 | #include "Throttle.h" 36 | #include "DeviceManager.h" 37 | #include "sys_io.h" 38 | 39 | #define MOTORCTL_INPUT_DRIVE_EN 3 40 | #define MOTORCTL_INPUT_FORWARD 4 41 | #define MOTORCTL_INPUT_REVERSE 5 42 | #define MOTORCTL_INPUT_LIMP 6 43 | 44 | class MotorControllerConfiguration : public DeviceConfiguration { 45 | public: 46 | uint16_t speedMax; // in rpm 47 | uint16_t torqueMax; // maximum torque in 0.1 Nm 48 | uint16_t torqueSlewRate; // for torque mode only: slew rate of torque value, 0=disabled, in 0.1Nm/sec 49 | uint16_t speedSlewRate; // for speed mode only: slew rate of speed value, 0=disabled, in rpm/sec 50 | uint8_t reversePercent; 51 | uint16_t kilowattHrs; 52 | uint16_t prechargeR; //resistance of precharge resistor in tenths of ohm 53 | uint16_t nominalVolt; //nominal pack voltage in tenths of a volt 54 | uint8_t prechargeRelay; //# of output to use for this relay or 255 if there is no relay 55 | uint8_t mainContactorRelay; //# of output to use for this relay or 255 if there is no relay 56 | uint8_t coolFan; 57 | uint8_t coolOn; 58 | uint8_t coolOff; 59 | uint8_t brakeLight; 60 | uint8_t revLight; 61 | uint8_t enableIn; 62 | uint8_t reverseIn; 63 | uint8_t capacity; 64 | 65 | }; 66 | 67 | class MotorController: public Device { 68 | 69 | public: 70 | enum Gears { 71 | NEUTRAL = 0, 72 | DRIVE = 1, 73 | REVERSE = 2, 74 | ERROR = 3, 75 | }; 76 | 77 | enum PowerMode { 78 | modeTorque, 79 | modeSpeed 80 | }; 81 | 82 | enum OperationState { 83 | DISABLED = 0, 84 | STANDBY = 1, 85 | ENABLE = 2, 86 | POWERDOWN = 3 87 | }; 88 | 89 | MotorController(); 90 | DeviceType getType(); 91 | void setup(); 92 | void handleTick(); 93 | uint32_t getTickInterval(); 94 | 95 | void loadConfiguration(); 96 | void saveConfiguration(); 97 | 98 | void coolingcheck(); 99 | void checkBrakeLight(); 100 | void checkReverseLight(); 101 | void checkEnableInput(); 102 | void checkReverseInput(); 103 | void checkPrecharge(); 104 | 105 | void brakecheck(); 106 | bool isReady(); 107 | bool isRunning(); 108 | bool isFaulted(); 109 | bool isWarning(); 110 | 111 | uint32_t getStatusBitfield1(); 112 | uint32_t getStatusBitfield2(); 113 | uint32_t getStatusBitfield3(); 114 | uint32_t getStatusBitfield4(); 115 | 116 | uint32_t statusBitfield1; // bitfield variable for use of the specific implementation 117 | uint32_t statusBitfield2; 118 | uint32_t statusBitfield3; 119 | uint32_t statusBitfield4; 120 | uint32_t kiloWattHours; 121 | 122 | 123 | 124 | 125 | void setPowerMode(PowerMode mode); 126 | PowerMode getPowerMode(); 127 | void setOpState(OperationState op) ; 128 | OperationState getOpState() ; 129 | void setSelectedGear(Gears gear); 130 | Gears getSelectedGear(); 131 | 132 | int16_t getThrottle(); 133 | int8_t getCoolFan(); 134 | int8_t getCoolOn(); 135 | int8_t getCoolOff(); 136 | int8_t getBrakeLight(); 137 | int8_t getRevLight(); 138 | int8_t getEnableIn(); 139 | int8_t getReverseIn(); 140 | int16_t getselectedGear(); 141 | int16_t getprechargeR(); 142 | int16_t getnominalVolt(); 143 | int8_t getprechargeRelay(); 144 | int8_t getmainContactorRelay(); 145 | int16_t getSpeedRequested(); 146 | int16_t getSpeedActual(); 147 | int16_t getTorqueRequested(); 148 | int16_t getTorqueActual(); 149 | int16_t getTorqueAvailable(); 150 | int preMillis(); 151 | 152 | uint16_t getDcVoltage(); 153 | int16_t getDcCurrent(); 154 | uint16_t getAcCurrent(); 155 | uint32_t getKiloWattHours(); 156 | int16_t getMechanicalPower(); 157 | int16_t getTemperatureMotor(); 158 | int16_t getTemperatureInverter(); 159 | int16_t getTemperatureSystem(); 160 | 161 | 162 | int milliseconds ; 163 | int seconds; 164 | int minutes; 165 | int hours ; 166 | int premillis; 167 | uint16_t nominalVolts; //nominal pack voltage in 1/10 of a volt 168 | uint8_t capacity; 169 | 170 | 171 | protected: 172 | bool ready; // indicates if the controller is ready to enable the power stage 173 | bool running; // indicates if the power stage of the inverter is operative 174 | bool faulted; // indicates a error condition is present in the controller 175 | bool warning; // indicates a warning condition is present in the controller 176 | bool coolflag; 177 | bool testenableinput; 178 | bool testreverseinput; 179 | 180 | 181 | Gears selectedGear; 182 | 183 | PowerMode powerMode; 184 | OperationState operationState; //the op state we want 185 | 186 | int16_t throttleRequested; // -1000 to 1000 (per mille of throttle level) 187 | int16_t speedRequested; // in rpm 188 | int16_t speedActual; // in rpm 189 | int16_t torqueRequested; // in 0.1 Nm 190 | int16_t torqueActual; // in 0.1 Nm 191 | int16_t torqueAvailable; // the maximum available torque in 0.1Nm 192 | 193 | uint16_t dcVoltage; // DC voltage in 0.1 Volts 194 | int16_t dcCurrent; // DC current in 0.1 Amps 195 | uint16_t acCurrent; // AC current in 0.1 Amps 196 | int16_t mechanicalPower; // mechanical power of the motor 0.1 kW 197 | int16_t temperatureMotor; // temperature of motor in 0.1 degree C 198 | int16_t temperatureInverter; // temperature of inverter power stage in 0.1 degree C 199 | int16_t temperatureSystem; // temperature of controller in 0.1 degree C 200 | 201 | 202 | 203 | uint16_t prechargeTime; //time in ms that precharge should last 204 | uint32_t milliStamp; //how long we have precharged so far 205 | bool donePrecharge; //already completed the precharge cycle? 206 | bool prelay; 207 | uint32_t skipcounter; 208 | }; 209 | 210 | #endif 211 | 212 | 213 | -------------------------------------------------------------------------------- /OBD2Handler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OBD2Handler.h - Handles OBD2 PID requests 3 | * 4 | Copyright (c) 2013-14 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef OBD2_H_ 28 | #define OBD2_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "Throttle.h" 33 | #include "MotorController.h" 34 | #include "BatteryManager.h" 35 | #include "DeviceManager.h" 36 | #include "TickHandler.h" 37 | #include "CanHandler.h" 38 | #include "constants.h" 39 | 40 | class OBD2Handler { 41 | public: 42 | bool processRequest(uint8_t mode, uint8_t pid, char *inData, char *outData); 43 | static OBD2Handler *getInstance(); 44 | 45 | protected: 46 | 47 | private: 48 | OBD2Handler(); //it's not right to try to directly instantiate this class 49 | bool processShowData(uint8_t pid, char *inData, char *outData); 50 | bool processShowCustomData(uint16_t pid, char *inData, char *outData); 51 | 52 | static OBD2Handler *instance; 53 | MotorController* motorController; 54 | Throttle* accelPedal; 55 | Throttle* brakePedal; 56 | BatteryManager *BMS; 57 | }; 58 | 59 | #endif 60 | 61 | 62 | -------------------------------------------------------------------------------- /PotBrake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PotBrake.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef POT_BRAKE_H_ 28 | #define POT_BRAKE_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "PotThrottle.h" 33 | #include "sys_io.h" 34 | #include "TickHandler.h" 35 | #include "Logger.h" 36 | #include "DeviceManager.h" 37 | 38 | #define THROTTLE_INPUT_BRAKELIGHT 2 39 | 40 | /* 41 | * The extended configuration class with additional parameters for PotBrake 42 | * 43 | * NOTE: Because of ThrottleDetector, this currently MUST be the same as PotThrottleConfiguratin !!! 44 | */ 45 | class PotBrakeConfiguration: public PotThrottleConfiguration { 46 | public: 47 | }; 48 | 49 | class PotBrake: public Throttle { 50 | public: 51 | PotBrake(); 52 | void setup(); 53 | void handleTick(); 54 | DeviceId getId(); 55 | DeviceType getType(); 56 | 57 | RawSignalData *acquireRawSignal(); 58 | 59 | void loadConfiguration(); 60 | void saveConfiguration(); 61 | 62 | protected: 63 | bool validateSignal(RawSignalData *); 64 | uint16_t calculatePedalPosition(RawSignalData *); 65 | int16_t mapPedalPosition(int16_t); 66 | 67 | private: 68 | RawSignalData rawSignal; 69 | }; 70 | 71 | #endif /* POT_BRAKE_H_ */ 72 | 73 | 74 | -------------------------------------------------------------------------------- /PotThrottle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PotThrottle.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef PEDAL_POT_H_ 28 | #define PEDAL_POT_H_ 29 | 30 | #include 31 | #include "config.h" 32 | #include "Throttle.h" 33 | #include "sys_io.h" 34 | #include "TickHandler.h" 35 | #include "Logger.h" 36 | #include "DeviceManager.h" 37 | #include "FaultHandler.h" 38 | #include "FaultCodes.h" 39 | 40 | #define THROTTLE_INPUT_BRAKELIGHT 2 41 | 42 | /* 43 | * The extended configuration class with additional parameters for PotThrottle 44 | */ 45 | class PotThrottleConfiguration: public ThrottleConfiguration { 46 | public: 47 | /* 48 | * Allows subclasses to have sub types for their pedal type 49 | * 0 - unknown type (prefs will return 0 if never set) 50 | * 1 - standard linear potentiometer (low-high). If 2 pots, both are low-high and the 2nd mirrors the 1st. 51 | * 2 - inverse potentiometer (high-low). If 2 pots, then 1st is low-high and 2nd is high-low) 52 | */ 53 | uint8_t throttleSubType; 54 | uint16_t minimumLevel1, maximumLevel1, minimumLevel2, maximumLevel2; // values for when the pedal is at its min and max for each input 55 | uint8_t numberPotMeters; // the number of potentiometers to be used. Should support three as well since some pedals really do have that many 56 | uint8_t AdcPin1, AdcPin2; //which ADC pins to use for the throttle 57 | }; 58 | 59 | class PotThrottle: public Throttle { 60 | public: 61 | PotThrottle(); 62 | void setup(); 63 | void handleTick(); 64 | DeviceId getId(); 65 | RawSignalData *acquireRawSignal(); 66 | 67 | void loadConfiguration(); 68 | void saveConfiguration(); 69 | 70 | protected: 71 | bool validateSignal(RawSignalData *); 72 | uint16_t calculatePedalPosition(RawSignalData *); 73 | 74 | private: 75 | RawSignalData rawSignal; 76 | }; 77 | 78 | #endif /* POT_THROTTLE_H_ */ 79 | 80 | 81 | -------------------------------------------------------------------------------- /PrefHandler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PrefHandler.cpp 3 | * 4 | * Abstracts away the particulars of how preferences are stored. 5 | * Transparently supports main and "last known good" storage and retrieval 6 | * 7 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included 18 | in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | */ 29 | 30 | #include "PrefHandler.h" 31 | 32 | PrefHandler::PrefHandler() { 33 | lkg_address = EE_MAIN_OFFSET; //default to normal mode 34 | base_address = 0; 35 | } 36 | 37 | bool PrefHandler::isEnabled() 38 | { 39 | return enabled; 40 | } 41 | 42 | void PrefHandler::setEnabledStatus(bool en) 43 | { 44 | uint16_t id; 45 | 46 | enabled = en; 47 | 48 | if (enabled) { 49 | id |= 0x8000; //set enabled bit 50 | } 51 | else { 52 | id &= 0x7FFF; //clear enabled bit 53 | } 54 | 55 | memCache->Write(EE_DEVICE_TABLE + (2 * position), id); 56 | } 57 | 58 | 59 | void PrefHandler::initDevTable() 60 | { 61 | uint16_t id; 62 | 63 | memCache->Read(EE_DEVICE_TABLE, &id); 64 | if (id == 0xDEAD) return; 65 | 66 | Logger::debug("Initializing EEPROM device table"); 67 | 68 | //initialize table with zeros 69 | id = 0; 70 | for (int x = 1; x < 64; x++) { 71 | memCache->Write(EE_DEVICE_TABLE + (2 * x), id); 72 | } 73 | 74 | //write out magic entry 75 | id = 0xDEAD; 76 | memCache->Write(EE_DEVICE_TABLE, id); 77 | } 78 | 79 | //Given a device ID we must search the 64 entry table found in EEPROM to see if the device 80 | //has a spot in EEPROM. If it does not then 81 | PrefHandler::PrefHandler(DeviceId id_in) { 82 | uint16_t id; 83 | 84 | enabled = false; 85 | 86 | initDevTable(); 87 | 88 | for (int x = 1; x < 64; x++) { 89 | memCache->Read(EE_DEVICE_TABLE + (2 * x), &id); 90 | if ((id & 0x7FFF) == ((int)id_in)) { 91 | base_address = EE_DEVICES_BASE + (EE_DEVICE_SIZE * x); 92 | lkg_address = EE_MAIN_OFFSET; 93 | if (id & 0x8000) enabled = true; 94 | position = x; 95 | Logger::info("Device ID: %X was found in device table at entry: %i", (int)id_in, x); 96 | return; 97 | } 98 | } 99 | 100 | //if we got here then there was no entry for this device in the table yet. 101 | //try to find an empty spot and place it there. 102 | for (int x = 1; x < 64; x++) { 103 | memCache->Read(EE_DEVICE_TABLE + (2 * x), &id); 104 | if (id == 0) { 105 | base_address = EE_DEVICES_BASE + (EE_DEVICE_SIZE * x); 106 | lkg_address = EE_MAIN_OFFSET; 107 | enabled = false; //default to devices being off until the user says otherwise 108 | id = (int)id_in; 109 | memCache->Write(EE_DEVICE_TABLE + (2*x), id); 110 | position = x; 111 | Logger::info("Device ID: %X was placed into device table at entry: %i", (int)id, x); 112 | return; 113 | } 114 | } 115 | 116 | //we found no matches and could not allocate a space. This is bad. Error out here 117 | base_address = 0xF0F0; 118 | lkg_address = EE_MAIN_OFFSET; 119 | Logger::error("PrefManager - Device Table Full!!!"); 120 | } 121 | 122 | //A special static function that can be called whenever, wherever to turn a specific device on/off. Does not 123 | //attempt to do so at runtime so the user will still have to power cycle to change the device status. 124 | //returns true if it could make the change, false if it could not. 125 | bool PrefHandler::setDeviceStatus(uint16_t device, bool enabled) 126 | { 127 | uint16_t id; 128 | for (int x = 1; x < 64; x++) { 129 | memCache->Read(EE_DEVICE_TABLE + (2 * x), &id); 130 | if ((id & 0x7FFF) == (device & 0x7FFF)) { 131 | Logger::debug("Found a device record to edit"); 132 | if (enabled) { 133 | id |= 0x8000; 134 | } 135 | else { 136 | id &= 0x7FFF; 137 | } 138 | Logger::debug("ID to write: %X", id); 139 | memCache->Write(EE_DEVICE_TABLE + (2 * x), id); 140 | return true; 141 | } 142 | } 143 | return false; 144 | } 145 | 146 | PrefHandler::~PrefHandler() { 147 | } 148 | 149 | void PrefHandler::LKG_mode(bool mode) { 150 | if (mode) lkg_address = EE_LKG_OFFSET; 151 | else lkg_address = EE_MAIN_OFFSET; 152 | } 153 | 154 | bool PrefHandler::write(uint16_t address, uint8_t val) { 155 | if (address >= EE_DEVICE_SIZE) return false; 156 | return memCache->Write((uint32_t)address + base_address + lkg_address, val); 157 | } 158 | 159 | bool PrefHandler::write(uint16_t address, uint16_t val) { 160 | if (address >= EE_DEVICE_SIZE) return false; 161 | return memCache->Write((uint32_t)address + base_address + lkg_address, val); 162 | } 163 | 164 | bool PrefHandler::write(uint16_t address, uint32_t val) { 165 | if (address >= EE_DEVICE_SIZE) return false; 166 | return memCache->Write((uint32_t)address + base_address + lkg_address, val); 167 | } 168 | 169 | bool PrefHandler::read(uint16_t address, uint8_t *val) { 170 | if (address >= EE_DEVICE_SIZE) return false; 171 | return memCache->Read((uint32_t)address + base_address + lkg_address, val); 172 | } 173 | 174 | bool PrefHandler::read(uint16_t address, uint16_t *val) { 175 | if (address >= EE_DEVICE_SIZE) return false; 176 | return memCache->Read((uint32_t)address + base_address + lkg_address, val); 177 | } 178 | 179 | bool PrefHandler::read(uint16_t address, uint32_t *val) { 180 | if (address >= EE_DEVICE_SIZE) return false; 181 | return memCache->Read((uint32_t)address + base_address + lkg_address, val); 182 | } 183 | 184 | uint8_t PrefHandler::calcChecksum() { 185 | uint16_t counter; 186 | uint8_t accum = 0; 187 | uint8_t temp; 188 | for (counter = 1; counter < EE_DEVICE_SIZE; counter++) { 189 | memCache->Read((uint32_t)counter + base_address + lkg_address, &temp); 190 | accum += temp; 191 | } 192 | return accum; 193 | } 194 | 195 | //calculate the current checksum and save it to the proper place 196 | void PrefHandler::saveChecksum() { 197 | uint8_t csum; 198 | csum = calcChecksum(); 199 | memCache->Write(EE_CHECKSUM + base_address + lkg_address, csum); 200 | } 201 | 202 | bool PrefHandler::checksumValid() { 203 | //get checksum from EEPROM and calculate the current checksum to see if they match 204 | uint8_t stored_chk, calc_chk; 205 | 206 | memCache->Read(EE_CHECKSUM + base_address + lkg_address, &stored_chk); 207 | calc_chk = calcChecksum(); 208 | Logger::info("Stored Checksum: %X Calc: %X", stored_chk, calc_chk); 209 | 210 | return (stored_chk == calc_chk); 211 | } 212 | 213 | void PrefHandler::forceCacheWrite() 214 | { 215 | memCache->FlushAllPages(); 216 | } 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /PrefHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PrefHandler.h 3 | * 4 | * header for preference handler 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef PREF_HANDLER_H_ 30 | #define PREF_HANDLER_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "eeprom_layout.h" 35 | #include "MemCache.h" 36 | #include "DeviceTypes.h" 37 | #include "Logger.h" 38 | 39 | //normal or Last Known Good configuration 40 | #define PREF_MODE_NORMAL false 41 | #define PREF_MODE_LKG true 42 | 43 | extern MemCache *memCache; 44 | 45 | class PrefHandler { 46 | public: 47 | 48 | PrefHandler(); 49 | PrefHandler(DeviceId id); 50 | ~PrefHandler(); 51 | void LKG_mode(bool mode); 52 | bool write(uint16_t address, uint8_t val); 53 | bool write(uint16_t address, uint16_t val); 54 | bool write(uint16_t address, uint32_t val); 55 | bool read(uint16_t address, uint8_t *val); 56 | bool read(uint16_t address, uint16_t *val); 57 | bool read(uint16_t address, uint32_t *val); 58 | uint8_t calcChecksum(); 59 | void saveChecksum(); 60 | bool checksumValid(); 61 | void forceCacheWrite(); 62 | bool isEnabled(); 63 | void setEnabledStatus(bool en); 64 | static bool setDeviceStatus(uint16_t device, bool enabled); 65 | 66 | private: 67 | uint32_t base_address; //base address for the parent device 68 | uint32_t lkg_address; 69 | bool use_lkg; //use last known good config? 70 | bool enabled; 71 | int position; //position within the device table 72 | void initDevTable(); 73 | }; 74 | 75 | #endif 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GEVCU 2 | ===== 3 | 4 | Note - If you have pulled this code between July and Sept of 2016 then you received commits that have been 5 | removed from this repo. It has been decided to move development of GEVCU6 code over to the GEVCU6 repo. 6 | If you have the commits from that multi-month window then point your origin to the GEVCU6 repo instead 7 | and everything will still be there and be correct. Sorry for any inconvenience this causes. 8 | 9 | Generalized Electric Vehicle Control Unit 10 | 11 | Our website can be found at : http://www.gevcu.org 12 | 13 | A project to create a fairly Arduino compatible ECU firmware 14 | to interface with various electric vehicle hardware over canbus 15 | (and possibly other comm channels) 16 | 17 | The project now builds in the Arduino IDE. So, use it to compile, send the firmware to the Arduino, and monitor serial. It all works very nicely. 18 | 19 | The master branch of this project is now switched to support the Due. The master branch is sparsely updated and only when the source tree is in stable shape. 20 | 21 | The older Macchina code has been moved to its own branch. This code is now *VERY* old but should work to control a DMOC645. 22 | 23 | ArduinoDue branch is more experimental than the master branch and includes the work of Michael Neuweiler. 24 | 25 | The WIP branch is sync'd to EVTV's official changes and as such could be considered as a testing ground for the official source code distribution. 26 | 27 | You will need the following to have any hope of compiling and running the firmware: 28 | - A GEVCU board. Versions from 2 and up are supported. 29 | - Arduino IDE 1.5.4 - Do not use newer versions of the IDE 30 | - due_can library - There is a repo for this under Collin80 31 | - due_rtc library - Also under Collin80 32 | - due_wire library - once again 33 | - DueTimer library - and again 34 | 35 | All libraries belong in %USERPROFILE%\Documents\Arduino\libraries (Windows) or ~/Arduino/libraries (Linux/Mac). 36 | You will need to remove -master or any other postfixes. Your library folders should be named as above. 37 | 38 | The canbus is supposed to be terminated on both ends of the bus. If you are testing with a DMOC and GEVCU then you've got two devices, each on opposing ends of the bus. So, both really should be terminated but for really short canbus lines you will probably get away with terminating just one side. 39 | 40 | If you are using a custom board then add a terminating resistor. 41 | 42 | If you are using the new prototype shield then it should already be terminated. The DMOC can be terminated by soldering a 120 ohm resistor between the canbus lines. I did this on my DMOC and hid the resistor inside the plug shroud. 43 | 44 | This software is MIT licensed: 45 | 46 | Copyright (c) 2014 Collin Kidder, Michael Neuweiler, Charles Galpin, Jack Rickard 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of this software and associated documentation files (the 50 | "Software"), to deal in the Software without restriction, including 51 | without limitation the rights to use, copy, modify, merge, publish, 52 | distribute, sublicense, and/or sell copies of the Software, and to 53 | permit persons to whom the Software is furnished to do so, subject to 54 | the following conditions: 55 | 56 | The above copyright notice and this permission notice shall be included 57 | in all copies or substantial portions of the Software. 58 | 59 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 60 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 61 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 62 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 63 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 64 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 65 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 66 | 67 | -------------------------------------------------------------------------------- /SerialConsole.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SerialConsole.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | */ 26 | 27 | #ifndef SERIALCONSOLE_H_ 28 | #define SERIALCONSOLE_H_ 29 | 30 | #include "config.h" 31 | #include "Heartbeat.h" 32 | #include "MemCache.h" 33 | #include "config.h" 34 | #include "sys_io.h" 35 | #include "PotThrottle.h" 36 | #include "DeviceManager.h" 37 | #include "MotorController.h" 38 | #include "DmocMotorController.h" //TODO: direct reference to dmoc must be removed 39 | #include "ThrottleDetector.h" 40 | #include "ichip_2128.h" 41 | 42 | class SerialConsole { 43 | public: 44 | SerialConsole(MemCache* memCache); 45 | SerialConsole(MemCache* memCache, Heartbeat* heartbeat); 46 | void loop(); 47 | void printMenu(); 48 | 49 | protected: 50 | enum CONSOLE_STATE 51 | { 52 | STATE_ROOT_MENU 53 | }; 54 | 55 | private: 56 | Heartbeat* heartbeat; 57 | MemCache* memCache; 58 | bool handlingEvent; 59 | char cmdBuffer[80]; 60 | int ptrBuffer; 61 | int state; 62 | int loopcount; 63 | bool cancel; 64 | 65 | 66 | void init(); 67 | void serialEvent(); 68 | void handleConsoleCmd(); 69 | void handleShortCmd(); 70 | void handleConfigCmd(); 71 | void resetWiReachMini(); 72 | void getResponse(); 73 | }; 74 | 75 | #endif /* SERIALCONSOLE_H_ */ 76 | 77 | 78 | -------------------------------------------------------------------------------- /Sys_Messages.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Sys_Messages.h 3 | * 4 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included 15 | in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #ifndef SYSMSG_H_ 27 | #define SYSMSG_H_ 28 | 29 | 30 | enum SystemMessage { 31 | MSG_STARTUP = 0x3000, 32 | MSG_SOFT_FAULT = 0x3100, 33 | MSG_HARD_FAULT = 0x3150, 34 | MSG_DISABLE = 0x3200, 35 | MSG_ENABLE = 0x3300, 36 | MSG_SET_PARAM = 0x4000, 37 | MSG_CONFIG_CHANGE = 0x4001, 38 | MSG_COMMAND = 0x4002 39 | }; 40 | 41 | #endif 42 | 43 | 44 | -------------------------------------------------------------------------------- /ThinkBatteryManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ThinkBatteryManager.cpp 3 | * 4 | * Interface to the BMS which is within the Think City battery packs 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #include "ThinkBatteryManager.h" 30 | 31 | ThinkBatteryManager::ThinkBatteryManager() : BatteryManager() { 32 | prefsHandler = new PrefHandler(THINKBMS); 33 | allowCharge = false; 34 | allowDischarge = false; 35 | commonName = "Think City BMS"; 36 | } 37 | 38 | void ThinkBatteryManager::setup() { 39 | TickHandler::getInstance()->detach(this); 40 | 41 | Logger::info("add device: Th!nk City BMS (id: %X, %X)", THINKBMS, this); 42 | 43 | BatteryManager::setup(); // run the parent class version of this function 44 | 45 | //Relevant BMS messages are 0x300 - 0x30F 46 | CanHandler::getInstanceEV()->attach(this, 0x300, 0x7f0, false); 47 | 48 | TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_BMS_THINK); 49 | } 50 | 51 | /*For all multibyte integers the format is MSB first, LSB last 52 | */ 53 | void ThinkBatteryManager::handleCanFrame(CAN_FRAME *frame) { 54 | int temp; 55 | switch (frame->id) { 56 | case 0x300: //Start up message 57 | //we're not really interested in much here except whether init worked. 58 | if ((frame->data.bytes[6] & 1) == 0) //there was an initialization error! 59 | { 60 | faultHandler.raiseFault(THINKBMS, FAULT_BMS_INIT, true); 61 | allowCharge = false; 62 | allowDischarge = false; 63 | } 64 | else 65 | { 66 | faultHandler.cancelOngoingFault(THINKBMS, FAULT_BMS_INIT); 67 | } 68 | break; 69 | case 0x301: //System Data 0 70 | //first two bytes = current, next two voltage, next two DOD, last two avg. temp 71 | //readings in tenths 72 | packVoltage = (frame->data.bytes[0] * 256 + frame->data.bytes[1]); 73 | packCurrent = (frame->data.bytes[2] * 256 + frame->data.bytes[3]); 74 | break; 75 | case 0x302: //System Data 1 76 | if ((frame->data.bytes[0] & 1) == 1) //Byte 0 bit 0 = general error 77 | { 78 | faultHandler.raiseFault(THINKBMS, FAULT_BMS_MISC, true); 79 | allowDischarge = false; 80 | allowCharge = false; 81 | } 82 | else 83 | { 84 | faultHandler.cancelOngoingFault(THINKBMS, FAULT_BMS_MISC); 85 | } 86 | if ((frame->data.bytes[2] & 1) == 1) //Byte 2 bit 0 = general isolation error 87 | { 88 | faultHandler.raiseFault(THINKBMS, FAULT_HV_BATT_ISOLATION, true); 89 | allowDischarge = false; 90 | allowCharge = false; 91 | } 92 | else 93 | { 94 | faultHandler.cancelOngoingFault(THINKBMS, FAULT_HV_BATT_ISOLATION); 95 | } 96 | //Min discharge voltage = bytes 4-5 - tenths of a volt 97 | //Max discharge current = bytes 6-7 - tenths of an amp 98 | temp = (S16)(frame->data.bytes[6] * 256 + frame->data.bytes[7]); 99 | if (temp > 0) allowDischarge = true; 100 | break; 101 | case 0x303: //System Data 2 102 | //bytes 0-1 = max charge voltage (tenths of volt) 103 | //bytes 2-3 = max charge current (tenths of amp) 104 | temp = (S16)(frame->data.bytes[2] * 256 + frame->data.bytes[3]); 105 | if (temp > 0) allowCharge = true; 106 | //byte 4 bit 1 = regen braking OK, bit 2 = Discharging OK 107 | //byte 6 bit 3 = EPO (emergency power off) happened, bit 5 = battery pack fan is on 108 | break; 109 | case 0x304: //System Data 3 110 | //Byte 2 lower 4 bits = highest error category 111 | //categories: 0 = no faults, 1 = Reserved, 2 = Warning, 3 = Delayed switch off, 4 = immediate switch off 112 | //bytes 4-5 = Pack max temperature (tenths of degree C) - Signed 113 | //byte 6-7 = Pack min temperature (tenths of a degree C) - Signed 114 | lowestCellTemp = (S16)(frame->data.bytes[4] * 256 + frame->data.bytes[5]); 115 | highestCellTemp = (S16)(frame->data.bytes[6] * 256 + frame->data.bytes[7]); 116 | break; 117 | case 0x305: //System Data 4 118 | //byte 2 bits 0-3 = BMS state 119 | //0 = idle state, 1 = discharge state (contactor closed), 15 = fault state 120 | //byte 2 bit 4 = Internal HV isolation fault 121 | //byte 2 bit 5 = External HV isolation fault 122 | break; 123 | case 0x306: //System Data 5 124 | //bytes 0-1 = Equiv. internal resistance in milliohms 125 | //not recommended to rely on so probably just ignore it 126 | break; 127 | //technically there is a specification for frames 0x307 - 0x30A but I have never seen these frames 128 | //sent on the canbus system so I doubt that they are used. 129 | /* 130 | case 0x307: //System Data 6 131 | case 0x308: //System Data 7 132 | case 0x309: //System Data 8 133 | case 0x30A: //System Data 9 134 | //do we care about the serial #? Probably not. 135 | case 0x30E: //Serial # part 1 136 | case 0x30B: //Serial # part 2 137 | */ 138 | } 139 | } 140 | 141 | void ThinkBatteryManager::handleTick() { 142 | BatteryManager::handleTick(); //kick the ball up to papa 143 | 144 | sendKeepAlive(); 145 | 146 | } 147 | 148 | //Contactors in pack will close if we sent these two frames with all zeros. 149 | void ThinkBatteryManager::sendKeepAlive() 150 | { 151 | CAN_FRAME output; 152 | output.length = 3; 153 | output.id = 0x310; 154 | output.extended = 0; //standard frame 155 | output.rtr = 0; 156 | for (int i = 0; i < 8; i++) output.data.bytes[i] = 0; 157 | CanHandler::getInstanceEV()->sendFrame(output); 158 | 159 | output.id = 0x311; 160 | output.length = 2; 161 | CanHandler::getInstanceEV()->sendFrame(output); 162 | } 163 | 164 | DeviceId ThinkBatteryManager::getId() 165 | { 166 | return (THINKBMS); 167 | } 168 | 169 | bool ThinkBatteryManager::hasPackVoltage() 170 | { 171 | return true; 172 | } 173 | 174 | bool ThinkBatteryManager::hasPackCurrent() 175 | { 176 | return true; 177 | } 178 | 179 | bool ThinkBatteryManager::hasTemperatures() 180 | { 181 | return true; 182 | } 183 | 184 | bool ThinkBatteryManager::isChargeOK() 185 | { 186 | return allowCharge; 187 | } 188 | 189 | bool ThinkBatteryManager::isDischargeOK() 190 | { 191 | return allowDischarge; 192 | } 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /ThinkBatteryManager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * BatteryManager.h 3 | * 4 | * Parent class for battery management / monitoring systems 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | #ifndef THINKBATT_H_ 30 | #define THINKBATT_H_ 31 | 32 | #include 33 | #include "config.h" 34 | #include "Device.h" 35 | #include "DeviceManager.h" 36 | #include "BatteryManager.h" 37 | #include "CanHandler.h" 38 | 39 | class ThinkBatteryManager : public BatteryManager, CanObserver 40 | { 41 | public: 42 | ThinkBatteryManager(); 43 | void setup(); 44 | void handleTick(); 45 | void handleCanFrame(CAN_FRAME *frame); 46 | DeviceId getId(); 47 | bool hasPackVoltage(); 48 | bool hasPackCurrent(); 49 | bool hasTemperatures(); 50 | bool isChargeOK(); 51 | bool isDischargeOK(); 52 | protected: 53 | private: 54 | void sendKeepAlive(); 55 | }; 56 | 57 | #endif 58 | 59 | 60 | -------------------------------------------------------------------------------- /Throttle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Throttle.h 3 | * 4 | * Parent class for all throttle controllers, be they canbus or pot or hall effect, etc 5 | * This class is virtually totally virtual. The derived classes redefine most everything 6 | * about this class. It might even be a good idea to make the class totally abstract. 7 | 8 | 9 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining 12 | a copy of this software and associated documentation files (the 13 | "Software"), to deal in the Software without restriction, including 14 | without limitation the rights to use, copy, modify, merge, publish, 15 | distribute, sublicense, and/or sell copies of the Software, and to 16 | permit persons to whom the Software is furnished to do so, subject to 17 | the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included 20 | in all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 27 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | #ifndef THROTTLE_H_ 33 | #define THROTTLE_H_ 34 | 35 | #include 36 | #include "config.h" 37 | #include "Device.h" 38 | 39 | /* 40 | * Data structure to hold raw signal(s) of the throttle. 41 | * E.g. for a three pot pedal, all signals could be used. 42 | */ 43 | struct RawSignalData { 44 | int32_t input1; // e.g. pot #1 or the signal from a can bus throttle 45 | int32_t input2; // e.g. pot #2 (optional) 46 | int32_t input3; // e.g. pot #3 (optional) 47 | }; 48 | 49 | /* 50 | * A abstract class to hold throttle configuration parameters. 51 | * Can be extended by the subclass. 52 | */ 53 | class ThrottleConfiguration: public DeviceConfiguration { 54 | public: 55 | uint16_t positionRegenMaximum, positionRegenMinimum; // throttle position where regen is highest and lowest 56 | uint16_t positionForwardMotionStart, positionHalfPower; // throttle position where forward motion starts and the mid point of throttle 57 | uint8_t maximumRegen; // percentage of max torque allowable for regen at maximum level 58 | uint8_t minimumRegen; // percentage of max torque allowable for regen at minimum level 59 | uint8_t creep; // percentage of torque used for creep function (imitate creep of automatic transmission, set 0 to disable) 60 | }; 61 | 62 | /* 63 | * Abstract class for all throttle implementations. 64 | */ 65 | class Throttle: public Device { 66 | public: 67 | enum ThrottleStatus { 68 | OK, 69 | ERR_LOW_T1, 70 | ERR_LOW_T2, 71 | ERR_HIGH_T1, 72 | ERR_HIGH_T2, 73 | ERR_MISMATCH, 74 | ERR_MISC 75 | }; 76 | 77 | Throttle(); 78 | virtual int16_t getLevel(); 79 | void handleTick(); 80 | virtual ThrottleStatus getStatus(); 81 | virtual bool isFaulted(); 82 | virtual DeviceType getType(); 83 | 84 | virtual RawSignalData *acquireRawSignal(); 85 | void loadConfiguration(); 86 | void saveConfiguration(); 87 | 88 | protected: 89 | ThrottleStatus status; 90 | virtual bool validateSignal(RawSignalData *); 91 | virtual uint16_t calculatePedalPosition(RawSignalData *); 92 | virtual int16_t mapPedalPosition(int16_t); 93 | uint16_t normalizeAndConstrainInput(int32_t, int32_t, int32_t); 94 | int32_t normalizeInput(int32_t, int32_t, int32_t); 95 | 96 | private: 97 | int16_t level; // the final signed throttle level. [-1000, 1000] in permille of maximum 98 | }; 99 | 100 | #endif 101 | 102 | 103 | -------------------------------------------------------------------------------- /ThrottleDetector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ThrottleDetector.h 3 | * 4 | * This class can detect up to two potentiometers and determine their min/max values, 5 | * whether they read low to high or high to low, and if the second potentiometer is 6 | * the inverse of the first. 7 | * 8 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining 11 | a copy of this software and associated documentation files (the 12 | "Software"), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included 19 | in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | */ 30 | 31 | #ifndef THROTTLE_DETECTOR_H_ 32 | #define THROTTLE_DETECTOR_H_ 33 | 34 | #include "PotThrottle.h" 35 | #include "Logger.h" 36 | #include "DeviceManager.h" 37 | 38 | class Throttle; 39 | 40 | class ThrottleDetector : public TickObserver { 41 | 42 | public: 43 | ThrottleDetector(Throttle *throttle); 44 | ~ThrottleDetector(); 45 | void handleTick(); 46 | void detect(); 47 | 48 | private: 49 | enum DetectionState { 50 | DoNothing, 51 | DetectMinWait, 52 | DetectMinCalibrate, 53 | DetectMaxWait, 54 | DetectMaxCalibrate 55 | }; 56 | 57 | void detectMinWait(); 58 | void detectMinCalibrate(); 59 | void detectMaxWait(); 60 | void detectMaxCalibrate(); 61 | void displayCalibratedValues(bool minPedal); 62 | void resetValues(); 63 | void readThrottleValues(); 64 | int checkLinear(uint16_t, uint16_t); 65 | int checkInverse(uint16_t, uint16_t); 66 | uint16_t normalize(uint16_t sensorValue, uint16_t sensorMin, uint16_t sensorMax, uint16_t constrainMin, uint16_t constrainMax); 67 | 68 | Throttle *throttle; 69 | PotThrottleConfiguration *config; 70 | DetectionState state; 71 | unsigned long startTime; 72 | int potentiometerCount; // the number of potentiometers detected 73 | uint16_t throttle1Min; // the minimum value of throttle1 74 | uint16_t throttle1Max; // the maximum value of throttle1 75 | uint16_t throttle2Min; // the minimum value of throttle2 76 | uint16_t throttle2Max; // the maximum value of throttle2 77 | uint8_t throttleSubType; // the throttle sub type 78 | bool throttle1HighLow; // true if throttle1 ranges from highest to lowest value as the pedal is pressed 79 | bool throttle2HighLow; // true if throttle2 ranges from highest to lowest value as the pedal is pressed 80 | bool throttle2Inverse; // true if throttle2 values are the opposite of the throttle1 values. 81 | int throttle1MinRest; // minimum sensor value at rest 82 | int throttle1MaxRest; // minimum sensor value at rest 83 | int throttle2MinRest; // minimum sensor value at rest 84 | int throttle2MaxRest; // maximum sensor value at rest 85 | int throttle1MinFluctuationPercent; 86 | int throttle1MaxFluctuationPercent; 87 | int throttle2MinFluctuationPercent; 88 | int throttle2MaxFluctuationPercent; 89 | int maxThrottleReadingDeviationPercent; 90 | // stats/counters when sampling 91 | static const int maxSamples = 300; 92 | int sampleCount; 93 | int linearCount; 94 | int inverseCount; 95 | uint16_t throttle1Values[maxSamples]; 96 | uint16_t throttle2Values[maxSamples]; 97 | 98 | }; 99 | 100 | #endif /* THROTTLE_DETECTOR_H_ */ 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /TickHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TickHandler.h 3 | * 4 | * Class where TickObservers can register to be triggered 5 | * on a certain interval. 6 | * 7 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included 18 | in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | */ 29 | 30 | #ifndef TICKHANDLER_H_ 31 | #define TICKHANDLER_H_ 32 | 33 | #include "config.h" 34 | #include 35 | #include "Logger.h" 36 | 37 | #define NUM_TIMERS 9 38 | 39 | class TickObserver { 40 | public: 41 | virtual void handleTick(); 42 | }; 43 | 44 | 45 | class TickHandler { 46 | public: 47 | static TickHandler *getInstance(); 48 | void attach(TickObserver *observer, uint32_t interval); 49 | void detach(TickObserver *observer); 50 | void handleInterrupt(int timerNumber); // must be public when from the non-class functions 51 | #ifdef CFG_TIMER_USE_QUEUING 52 | void cleanBuffer(); 53 | void process(); 54 | #endif 55 | 56 | protected: 57 | 58 | private: 59 | struct TimerEntry { 60 | long interval; // interval of timer 61 | TickObserver *observer[CFG_TIMER_NUM_OBSERVERS]; // array of pointers to observers with this interval 62 | }; 63 | TimerEntry timerEntry[NUM_TIMERS]; // array of timer entries (9 as there are 9 timers) 64 | static TickHandler *tickHandler; 65 | #ifdef CFG_TIMER_USE_QUEUING 66 | TickObserver *tickBuffer[CFG_TIMER_BUFFER_SIZE]; 67 | volatile uint16_t bufferHead, bufferTail; 68 | #endif 69 | 70 | TickHandler(); 71 | int findTimer(long interval); 72 | int findObserver(int timerNumber, TickObserver *observer); 73 | }; 74 | 75 | void timer0Interrupt(); 76 | void timer1Interrupt(); 77 | void timer2Interrupt(); 78 | void timer3Interrupt(); 79 | void timer4Interrupt(); 80 | void timer5Interrupt(); 81 | void timer6Interrupt(); 82 | void timer7Interrupt(); 83 | void timer8Interrupt(); 84 | 85 | #endif /* TICKHANDLER_H_ */ 86 | 87 | 88 | -------------------------------------------------------------------------------- /constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * constants.h 3 | * 4 | * Defines the global / application wide constants 5 | * 6 | 7 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included 18 | in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 24 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | * Author: Michael Neuweiler 28 | */ 29 | 30 | #ifndef CONSTANTS_H_ 31 | #define CONSTANTS_H_ 32 | 33 | namespace Constants { 34 | // misc 35 | static const char* trueStr = "true"; 36 | static const char* falseStr = "false"; 37 | static const char* notAvailable = "n/a"; 38 | static const char* ichipCommandPrefix = "AT+i"; 39 | static const char* ichipErrorString = "I/ERROR"; 40 | 41 | // configuration 42 | 43 | static const char* numThrottlePots = "numThrottlePots"; 44 | static const char* throttleSubType = "throttleSubType"; 45 | static const char* throttleMin1 = "throttleMin1"; 46 | static const char* throttleMin2 = "throttleMin2"; 47 | static const char* throttleMax1 = "throttleMax1"; 48 | static const char* throttleMax2 = "throttleMax2"; 49 | static const char* throttleRegenMax = "throttleRegenMax"; 50 | static const char* throttleRegenMin = "throttleRegenMin"; 51 | static const char* throttleFwd = "throttleFwd"; 52 | static const char* throttleMap = "throttleMap"; 53 | static const char* throttleMinRegen = "throttleMinRegen"; 54 | static const char* throttleMaxRegen = "throttleMaxRegen"; 55 | static const char* throttleCreep = "throttleCreep"; 56 | static const char* brakeMin = "brakeMin"; 57 | static const char* brakeMax = "brakeMax"; 58 | static const char* brakeMinRegen = "brakeMinRegen"; 59 | static const char* brakeMaxRegen = "brakeMaxRegen"; 60 | static const char* brakeLight = "brakeLight"; 61 | static const char* revLight = "revLight"; 62 | static const char* enableIn = "enableIn"; 63 | static const char* reverseIn = "reverseIn"; 64 | 65 | static const char* speedMax = "speedMax"; 66 | static const char* torqueMax = "torqueMax"; 67 | static const char* logLevel = "logLevel"; 68 | 69 | // status 70 | static const char* timeRunning = "timeRunning"; 71 | static const char* torqueRequested = "torqueRequested"; 72 | static const char* torqueActual = "torqueActual"; 73 | static const char* throttle = "throttle"; 74 | static const char* brake = "brake"; 75 | static const char* motorMode = "motorMode"; 76 | static const char* speedRequested = "speedRequested"; 77 | static const char* speedActual = "speedActual"; 78 | static const char* dcVoltage = "dcVoltage"; 79 | static const char* nominalVolt = "nominalVolt"; 80 | static const char* dcCurrent = "dcCurrent"; 81 | static const char* acCurrent = "acCurrent"; 82 | static const char* kiloWattHours = "kiloWattHours"; 83 | static const char* bitfield1 = "bitfield1"; 84 | static const char* bitfield2 = "bitfield2"; 85 | static const char* bitfield3 = "bitfield3"; 86 | static const char* bitfield4 = "bitfield4"; 87 | static const char* running = "running"; 88 | static const char* faulted = "faulted"; 89 | static const char* warning = "warning"; 90 | static const char* gear = "gear"; 91 | static const char* tempMotor = "tempMotor"; 92 | static const char* tempInverter = "tempInverter"; 93 | static const char* tempSystem = "tempSystem"; 94 | static const char* mechPower = "mechPower"; 95 | static const char* prechargeR = "prechargeR"; 96 | static const char* prechargeRelay = "prechargeRelay"; 97 | static const char* mainContactorRelay = "mainContactorRelay"; 98 | static const char* coolFan = "coolFan"; 99 | static const char* coolOn = "coolOn"; 100 | static const char* coolOff = "coolOff"; 101 | static const char* validChecksum = "Valid checksum, using stored config values"; 102 | static const char* invalidChecksum = "Invalid checksum, using hard coded config values"; 103 | static const char* valueOutOfRange = "value out of range: %l"; 104 | static const char* normalOperation = "normal operation restored"; 105 | } 106 | 107 | #endif /* CONSTANTS_H_ */ 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/Design Drawings.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/docs/Design Drawings.vsd -------------------------------------------------------------------------------- /docs/GEVCU pinout.txt: -------------------------------------------------------------------------------- 1 | Pin 1 - +12V Input 2 | Pin 3 - +12V output for first digital input 3 | Pin 7 - EXT GND connection to chassis ground / Battery - (in my case) 4 | Pins 9 & 10 - First canbus 5 | Pin 19 - Gnd connection for first and second analog inputs (Throttle) 6 | Pin 20 - First analog input (Throttle) 7 | Pin 21 - Second analog input (Throttle) 8 | Pin 22 - Third analog input (brake / testing input for me) 9 | Pin 23 - Fourth analog input (test pot on my wires) 10 | Pin 24 - +5V power for first and second analog inputs (Throttle) 11 | Pin 26 - +5V power for third and fourth analog inputs (test pots for me, 12 | probably brake transducer for you) 13 | Pin 30 - Gnd connection for third and fourth analog inputs (Brake / Testing) 14 | Pin 32 - First digital input. Tied to pin 3 above through a switch 15 | 16 | I used a gnd at pin 19 for one of the gnds. It really doesn't matter 17 | which one you use. All four (19,29,30,31) are equivalent. 18 | -------------------------------------------------------------------------------- /docs/GEVCU-35pinout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/docs/GEVCU-35pinout.jpg -------------------------------------------------------------------------------- /docs/GEVCU1-1.03.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/docs/GEVCU1-1.03.docx -------------------------------------------------------------------------------- /docs/ThrottleFiltering.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/docs/ThrottleFiltering.xlsx -------------------------------------------------------------------------------- /docs/UQMplug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/docs/UQMplug.jpg -------------------------------------------------------------------------------- /docs/gevcumanual403.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/docs/gevcumanual403.docx -------------------------------------------------------------------------------- /docs/howtocreatemodule.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/docs/howtocreatemodule.docx -------------------------------------------------------------------------------- /gearsandopstates.txt: -------------------------------------------------------------------------------- 1 | running = true if we have completed settup 2 | online = true if we are receiving CAN from DMOC 3 | alive 4 | 5 | activitycount = increments with each major frame received from DMOc 6 | 7 | operationState= DISABLED = 0, 8 | STANDBY = 1, 9 | ENABLE = 2, 10 | POWERDOWN = 3 11 | void setOpState(OperationState op) ; operationState 12 | OperationState getOpState() ; operationState 13 | 14 | OperationState operationState; We set and get this one, either in DMOC or in Motor 15 | OperationState actualState This can be checked directly - it is actually set by DMOC645 16 | 17 | 18 | selectedGear NEUTRAL =0 19 | DRIVE =1 20 | REVERSE=2 21 | ERROR=3 22 | 23 | void setSelectedGear(Gears gear); sets selectedGear motorcontroller version 24 | 25 | Gears getSelectedGear(); 26 | setGear(Gears gear) - sets selectedGear - DMOC version 27 | Gears selectedGear; 28 | Gears actualGear; 29 | 30 | 31 | 32 | GearSwitch GS_NEUTRAL, 33 | GS_FORWARD, 34 | GS_REVERSE, 35 | GS_FAULT 36 | 37 | getGearSwitch() 38 | setGear() 39 | 40 | 41 | we do send alive, opstate, and gear information to DMOC645 as part of SendCmd1. -------------------------------------------------------------------------------- /ichip_2128.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ichip_2128.h 3 | * 4 | * Class to interface with the ichip 2128 based wifi adapter we're using on our board 5 | * 6 | * Created: 4/18/2013 8:10:00 PM 7 | * Author: Collin Kidder 8 | */ 9 | 10 | /* The wifi adapter must be able to either create an adhoc network or connect to an existing network 11 | * the EEPROM has three entries for storing networks we'd like to be able to automatically join 12 | * If none of those networks can be found then the device will automatically try to form an 13 | * adhoc network with the 4th entry which is dedicated to that purpose. 14 | * All commands to the wifi start with "AT+i" and end with CR (ascii 13) 15 | * 16 | * Commands: 17 | * RP11 - get list of access points in range 18 | * RP7 - Status report (bit 10 if remote has changed a param) 19 | * RP8 - get system time 20 | * WWW - turn on HTTP server 21 | * WNXT - get next changed parameter (returns = or blank line at end) 22 | * WLTR - get/set transfer rate WIFI (0=max, 1=slow - 13 = max) 23 | * WRFU - turn on WIFI 24 | * WRFD - turn off wifi 25 | * WLBM - B wifi mode 26 | * WLGM - G wifi mode 27 | * AWPS - activate WPS mode 28 | * DIP - default IP address (set to 0.0.0.0 for DHCP client) 29 | * IPG - gateway address 30 | * SNET - subnet mask 31 | * DNS1 - DNS server 32 | * IPA - our IP address 33 | * DPSZ - DHCP server pool size (0 to disable server) 34 | * DSLT - DHCP server lease time 35 | * NTOD=1 - turn on time client (NTP) 36 | * WLCH - set WIFI channel 37 | * WLSI - SSID 38 | * WLWM - WEP MODE (0=disabled 1=64bit 2=128bit) 39 | * WLKx - WEP key 40 | * WLPP - WPA-PSK key 41 | * WSEC - 0 = TKIP 1 = AES 42 | * WSIx - x=0-9 = set SSIDs to associate with 43 | * WPPx - x=0-9 WPA pass phrases 44 | * WKYx - x=0-9 WEP keys 45 | * WSTx - x=0-9 security type = (0=none, 1=wep64, 2=WEP128,3=WPA/TKIP 4=WPA2 46 | * 47 | * 48 | * Web Parameters getting/setting 49 | * = set 50 | * ? get 51 | * 52 | 53 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 54 | 55 | Permission is hereby granted, free of charge, to any person obtaining 56 | a copy of this software and associated documentation files (the 57 | "Software"), to deal in the Software without restriction, including 58 | without limitation the rights to use, copy, modify, merge, publish, 59 | distribute, sublicense, and/or sell copies of the Software, and to 60 | permit persons to whom the Software is furnished to do so, subject to 61 | the following conditions: 62 | 63 | The above copyright notice and this permission notice shall be included 64 | in all copies or substantial portions of the Software. 65 | 66 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 67 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 68 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 69 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 70 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 71 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 72 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 73 | 74 | */ 75 | 76 | #ifndef ICHIP2128_H_ 77 | #define ICHIP2128_H_ 78 | 79 | #include 80 | #include "config.h" 81 | #include "constants.h" 82 | #include "DeviceManager.h" 83 | #include "PotThrottle.h" 84 | #include "Sys_Messages.h" 85 | #include "DeviceTypes.h" 86 | #include "ELM327Processor.h" 87 | //#include "sys_io.h" 88 | 89 | 90 | extern PrefHandler *sysPrefs; 91 | 92 | enum ICHIP_COMM_STATE {IDLE, GET_PARAM, SET_PARAM, START_TCP_LISTENER, GET_ACTIVE_SOCKETS, POLL_SOCKET, SEND_SOCKET, GET_SOCKET}; 93 | 94 | /* 95 | * The extended configuration class with additional parameters for ichip WLAN 96 | */ 97 | class WifiConfiguration : public DeviceConfiguration { 98 | public: 99 | }; 100 | 101 | /** 102 | * Cache of param values to avoid sending an update unless changed 103 | */ 104 | struct ParamCache { 105 | uint32_t timeRunning; 106 | int16_t torqueRequested; 107 | int16_t torqueActual; 108 | int16_t throttle; 109 | int16_t brake; 110 | bool brakeNotAvailable; 111 | int16_t speedRequested; 112 | int16_t speedActual; 113 | MotorController::PowerMode powerMode; 114 | int16_t dcVoltage; 115 | int16_t dcCurrent; 116 | int16_t acCurrent; 117 | int16_t nominalVolt; 118 | int16_t kiloWattHours; 119 | uint32_t bitfield1; 120 | uint32_t bitfield2; 121 | uint32_t bitfield3; 122 | uint32_t bitfield4; 123 | bool running; 124 | bool faulted; 125 | bool warning; 126 | MotorController::Gears gear; 127 | int16_t tempMotor; 128 | int16_t tempInverter; 129 | int16_t tempSystem; 130 | int16_t mechPower; 131 | int16_t prechargeR; 132 | int8_t prechargeRelay; 133 | int8_t mainContactorRelay; 134 | int8_t coolFan; 135 | int8_t coolOn; 136 | int8_t coolOff; 137 | int8_t brakeLight; 138 | int8_t revLight; 139 | int8_t enableIn; 140 | int8_t reverseIn; 141 | }; 142 | 143 | struct SendBuff { 144 | String cmd; 145 | ICHIP_COMM_STATE state; 146 | }; 147 | 148 | class ICHIPWIFI : public Device { 149 | public: 150 | 151 | ICHIPWIFI(); 152 | ICHIPWIFI(USARTClass *which); 153 | void setup(); //initialization on start up 154 | void handleTick(); //periodic processes 155 | void handleMessage(uint32_t messageType, void* message); 156 | DeviceType getType(); 157 | DeviceId getId(); 158 | void loop(); 159 | char *getTimeRunning(); 160 | 161 | 162 | void loadConfiguration(); 163 | void saveConfiguration(); 164 | void loadParameters(); 165 | 166 | 167 | private: 168 | ELM327Processor *elmProc; 169 | USARTClass* serialInterface; //Allows for retargetting which serial port we use 170 | char incomingBuffer[128]; //storage for one incoming line 171 | int ibWritePtr; //write position into above buffer 172 | SendBuff sendingBuffer[64]; 173 | int psWritePtr; 174 | int psReadPtr; 175 | int tickCounter; 176 | int currReply; 177 | char buffer[30]; // a buffer for various string conversions 178 | ParamCache paramCache; 179 | ICHIP_COMM_STATE state; 180 | bool didParamLoad; 181 | bool didTCPListener; 182 | int listeningSocket; 183 | int activeSockets[4]; //support for four sockets. Lowest byte is socket #, next byte is size of data waiting in that socket 184 | uint32_t lastSentTime; 185 | String lastSentCmd; 186 | ICHIP_COMM_STATE lastSentState; 187 | 188 | void getNextParam(); //get next changed parameter 189 | void getParamById(String paramName); //try to retrieve the value of the given parameter 190 | void setParam(String paramName, String value); //set the given parameter with the given string 191 | void setParam(String paramName, int32_t value); 192 | void setParam(String paramName, int16_t value); 193 | void setParam(String paramName, uint32_t value); 194 | void setParam(String paramName, uint16_t value); 195 | void setParam(String paramName, uint8_t value); 196 | void setParam(String paramName, float value, int precision); 197 | void sendCmd(String cmd); 198 | void sendCmd(String cmd, ICHIP_COMM_STATE cmdstate); 199 | void sendToSocket(int socket, String data); 200 | void processParameterChange(char *response); 201 | 202 | 203 | }; 204 | 205 | #endif 206 | 207 | 208 | -------------------------------------------------------------------------------- /readme.eclipse.txt: -------------------------------------------------------------------------------- 1 | How to get the Eclipse IDE running with GEVCU: 2 | 3 | * Install 32-bit or 64-bit version of Java JRE/JDK and "Eclipse IDE for C/C++ Developers Eclipse IDE for C/C++ Developers" (do not mix 32/64bit versions) 4 | * Start eclipse with a new workspace and 32-bit or 64-bit JRE/JDK respectively ("eclipse -vm /bin") 5 | * Install Arduino plug-in from http://www.baeyens.it/eclipse/V2 (Important: un-check "Group items by category" to see the plugin) 6 | * Restart eclipse if asked 7 | * Window -> Preferences -> C/C++ -> File Types -> New -> Pattern: *.ino Type: C++ Source File 8 | * Window -> Preferences -> Arduino: verify the Arduino IDE path (must point to 1.5.5) and 9 | the Private Library path (where you store additional libs), don't check the "Disable RTXT" checkbox 10 | * Copy the file ".project.copy" and rename the copy to ".project" (.project is in .gitignore which will prevent any upstream changes due to absolute paths in it) 11 | * File -> Import... -> General -> Existing Projects into Workspace -> enter GEVCU source directory as root directory 12 | * Right click the imported project -> Properties -> Arduino -> Change board and port (if necessary) -> OK 13 | This will cause the absolute paths to be corrected in the .project file 14 | * Select the project and click on "Verify". The project should compile. 15 | 16 | Note 1: In case you want to re-compile the entire souce tree, just delete the entire "Release" directory. 17 | It will be recreated automatically. 18 | 19 | Note 2: If the editor shows some errors in the code which should not be or if code completion doesn't 20 | complete as desired, right click the project -> Index -> Rebuild and open the file in the browser. 21 | -------------------------------------------------------------------------------- /sys_io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sys_io.h 3 | * 4 | * Handles raw interaction with system I/O 5 | * 6 | Copyright (c) 2013 Collin Kidder, Michael Neuweiler, Charles Galpin 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining 9 | a copy of this software and associated documentation files (the 10 | "Software"), to deal in the Software without restriction, including 11 | without limitation the rights to use, copy, modify, merge, publish, 12 | distribute, sublicense, and/or sell copies of the Software, and to 13 | permit persons to whom the Software is furnished to do so, subject to 14 | the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included 17 | in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | */ 28 | 29 | 30 | #ifndef SYS_IO_H_ 31 | #define SYS_IO_H_ 32 | 33 | #include 34 | #include "config.h" 35 | #include "eeprom_layout.h" 36 | #include "PrefHandler.h" 37 | 38 | typedef struct { 39 | uint16_t offset; 40 | uint16_t gain; 41 | } ADC_COMP; 42 | 43 | void setup_sys_io(); 44 | uint16_t getAnalog(uint8_t which); //get value of one of the 4 analog inputs 45 | uint16_t getDiffADC(uint8_t which); 46 | uint16_t getRawADC(uint8_t which); 47 | boolean getDigital(uint8_t which); //get value of one of the 4 digital inputs 48 | void setOutput(uint8_t which, boolean active); //set output high or not 49 | boolean getOutput(uint8_t which); //get current value of output state (high?) 50 | void setupFastADC(); 51 | void sys_io_adc_poll(); 52 | void sys_early_setup(); 53 | void sys_boot_setup(); 54 | 55 | #endif 56 | 57 | 58 | -------------------------------------------------------------------------------- /util/BBESAB0801.IMF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/util/BBESAB0801.IMF -------------------------------------------------------------------------------- /util/MultiSerial/MultiSerial.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Transmit serial data back and forth between two ports 3 | in order to flash new firmware to ichip with the ichip config tool. 4 | 5 | Note: Steps 1-5 have to be completed within 30 seconds (30000ms) 6 | 7 | Steps: 8 | 1) reset arduino (e.g. power cycle) 9 | 2) start ichip software 10 | 3) menu "serial ports", select com port of ardiuno, set baud rate to 9600 11 | 4) click on "ichip uploader via serial" 12 | 5) select EBI flash 16 Megabit (if window doesn't appear, start over, act faster) 13 | 6) Click FW Update, select .imf file and wait until finished, close ichip program 14 | 7) power cycle arduino/gevcu and wait 20-30sec 15 | 8) menu "serial ports", set baud rate to 115200 16 | 9) go to configuration page 17 | 18 | check-out http://www.youtube.com/watch?v=vS60htz6h1g at 00:35:00 19 | 20 | */ 21 | 22 | bool flag = true; 23 | void setup() { 24 | SerialUSB.begin(9600); // use SerialUSB only as the programming port doesn't work 25 | Serial2.begin(9600); // use Serial3 for GEVCU2, use Serial2 for GEVCU3+4 26 | /* pinMode(43, OUTPUT); 27 | digitalWrite(43,HIGH); 28 | delay(3000); 29 | digitalWrite(43,LOW); 30 | pinMode(18, OUTPUT); 31 | digitalWrite(18, LOW);*/ 32 | } 33 | 34 | void loop() { 35 | while (Serial2.available()) { 36 | SerialUSB.write(Serial2.read()); 37 | } 38 | while (SerialUSB.available()) { 39 | Serial2.write(SerialUSB.read()); 40 | } 41 | 42 | //// if (millis() > 6000) { 43 | // digitalWrite(18, HIGH); 44 | // } 45 | 46 | //if (flag && millis() > 30000) { 47 | // SerialUSB.begin(115200); 48 | // Serial2.begin(115200); 49 | // flag = false; 50 | //} 51 | } 52 | -------------------------------------------------------------------------------- /util/connectTOap/connectTOap.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Transmit serial data back and forth between two ports 3 | in order to flash new firmware to ichip with the ichip config tool. 4 | 5 | Note: Steps 1-5 have to be completed within 30 seconds (30000ms) 6 | 7 | Steps: 8 | 1) reset arduino (e.g. power cycle) 9 | 2) start ichip software 10 | 3) menu "serial ports", select com port of ardiuno, set baud rate to 9600 11 | 4) click on "ichip uploader via serial" 12 | 5) select EBI flash 16 Megabit (if window doesn't appear, start over, act faster) 13 | 6) Click FW Update, select .imf file and wait until finished, close ichip program 14 | 7) power cycle arduino/gevcu and wait 20-30sec 15 | 8) menu "serial ports", set baud rate to 115200 16 | 9) go to configuration page 17 | 18 | check-out http://www.youtube.com/watch?v=vS60htz6h1g at 00:35:00 19 | 20 | */ 21 | char inbyte; 22 | bool flag = true; 23 | void setup() { 24 | SerialUSB.begin(9600); // use SerialUSB only as the programming port doesn't work 25 | Serial2.begin(9600); // use Serial3 for GEVCU2, use Serial2 for GEVCU3+4 26 | // pinMode(43, INPUT); 27 | pinMode(42, OUTPUT); 28 | digitalWrite(42, LOW); 29 | } 30 | 31 | void loop() { 32 | while (Serial2.available()) { 33 | SerialUSB.write(Serial2.read()); 34 | } 35 | while (SerialUSB.available()) { 36 | inbyte=SerialUSB.read(); 37 | if (inbyte=='~'){sendcommandlist();} 38 | else {Serial2.write(inbyte);} 39 | } 40 | 41 | if (millis() > 6000) { 42 | digitalWrite(42, HIGH); 43 | } 44 | 45 | 46 | } 47 | 48 | void sendcommandlist() 49 | { 50 | SerialUSB.println("Sending commands...."); 51 | 52 | sendmessage("AT+iFD");//Clear all options 53 | sendmessage("AT+iHIF=1");//Host connection set to serial port 54 | sendmessage("AT+iBDRA");//Automatic baud rate on host serial port 55 | sendmessage("AT+iRP1");//Automatic baud rate on host serial port 56 | 57 | //sendmessage("AT+iWRST");//Wireless chip reset 58 | //sendmessage("AT+iWLBM"); //Set to 802.11b 59 | //sendmessage("AT+iWEBP=80");//Website port number 60 | //sendmessage("AT+iWLCH=3"); //Wireless channel 61 | sendmessage("AT+iWLSI=riverhouse");//SSID 62 | sendmessage("AT+iDIP=192.168.1.46");//default ip 63 | //sendmessage("AT+iSNET=255.255.255.0");//subnet 64 | //sendmessage("AT+iDPSZ=6");//DHCP pool size 65 | //sendmessage("AT+iWST0=0");//Connection security wap/wep/wap2 66 | //sendmessage("AT+iWLPW=14");//Max radio power 67 | //sendmessage("AT+iWRFU"); //Radio on 68 | 69 | sendmessage("AT+iRPG=secret"); 70 | sendmessage("AT+iWPWD=secret"); 71 | sendmessage("AT+iAWS=1");//Website on 72 | //sendmessage("AT+iSTAP=1");//Act as AP 73 | sendmessage("AT+iDOWN");//Powercycle reset 74 | 75 | SerialUSB.println("Command list completed...."); 76 | } 77 | 78 | void sendmessage(char* message) 79 | { 80 | Serial2.println(message); 81 | delay(700); 82 | while (Serial2.available()) {SerialUSB.write(Serial2.read());} 83 | 84 | } 85 | -------------------------------------------------------------------------------- /util/connectasAP/connectasAP.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Transmit serial data back and forth between two ports 3 | in order to flash new firmware to ichip with the ichip config tool. 4 | 5 | Note: Steps 1-5 have to be completed within 30 seconds (30000ms) 6 | 7 | Steps: 8 | 1) reset arduino (e.g. power cycle) 9 | 2) start ichip software 10 | 3) menu "serial ports", select com port of ardiuno, set baud rate to 9600 11 | 4) click on "ichip uploader via serial" 12 | 5) select EBI flash 16 Megabit (if window doesn't appear, start over, act faster) 13 | 6) Click FW Update, select .imf file and wait until finished, close ichip program 14 | 7) power cycle arduino/gevcu and wait 20-30sec 15 | 8) menu "serial ports", set baud rate to 115200 16 | 9) go to configuration page 17 | 18 | check-out http://www.youtube.com/watch?v=vS60htz6h1g at 00:35:00 19 | 20 | */ 21 | char inbyte; 22 | bool flag = true; 23 | void setup() { 24 | SerialUSB.begin(9600); // use SerialUSB only as the programming port doesn't work 25 | Serial2.begin(9600); // use Serial3 for GEVCU2, use Serial2 for GEVCU3+4 26 | // pinMode(43, INPUT); 27 | //pinMode(18, OUTPUT); 28 | //digitalWrite(18, LOW); 29 | } 30 | 31 | void loop() { 32 | while (Serial2.available()) { 33 | SerialUSB.write(Serial2.read()); 34 | } 35 | while (SerialUSB.available()) { 36 | inbyte=SerialUSB.read(); 37 | if (inbyte=='~'){sendcommandlist();} 38 | else {Serial2.write(inbyte);} 39 | } 40 | 41 | //if (millis() > 6000) { 42 | // digitalWrite(18, HIGH); 43 | // } 44 | 45 | 46 | } 47 | 48 | void sendcommandlist() 49 | { 50 | SerialUSB.println("Sending commands...."); 51 | 52 | //sendmessage("AT+iFD");//Clear all options 53 | sendmessage("AT+iHIF=1");//Host connection set to serial port 54 | sendmessage("AT+iBDRA");//Automatic baud rate on host serial port 55 | 56 | sendmessage("AT+iRPG=secret"); 57 | sendmessage("AT+iWPWD=secret"); 58 | //sendmessage("AT+iWRST");//Wireless chip reset 59 | //sendmessage("AT+iWLBM"); //Set to 802.11b 60 | //sendmessage("AT+iWEBP=80");//Website port number 61 | //sendmessage("AT+iWLCH=3"); //Wireless channel 62 | sendmessage("AT+iWLSI=GEVCU");//SSID 63 | sendmessage("AT+iSTAP=1");//Act as AP 64 | sendmessage("AT+iDIP=10.0.0.1");//default ip 65 | //sendmessage("AT+iSNET=255.255.255.0");//subnet 66 | sendmessage("AT+iDPSZ=8");//DHCP pool size 67 | //sendmessage("AT+iWST0=0");//Connection security wap/wep/wap2 68 | //sendmessage("AT+iWLPW=14");//Max radio power 69 | //sendmessage("AT+iWRFU"); //Radio on 70 | 71 | sendmessage("AT+iAWS=1");//Website on 72 | //sendmessage("AT+iSTAP=1");//Act as AP 73 | sendmessage("AT+iDOWN");//Powercycle reset 74 | 75 | SerialUSB.println("Command list completed...."); 76 | } 77 | 78 | void sendmessage(char* message) 79 | { 80 | Serial2.println(message); 81 | delay(700); 82 | while (Serial2.available()) {SerialUSB.write(Serial2.read());} 83 | 84 | } 85 | -------------------------------------------------------------------------------- /util/connectsetup/connectsetup.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Transmit serial data back and forth between two ports 3 | in order to flash new firmware to ichip with the ichip config tool. 4 | 5 | Note: Steps 1-5 have to be completed within 30 seconds (30000ms) 6 | 7 | Steps: 8 | 1) reset arduino (e.g. power cycle) 9 | 2) start ichip software 10 | 3) menu "serial ports", select com port of ardiuno, set baud rate to 9600 11 | 4) click on "ichip uploader via serial" 12 | 5) select EBI flash 16 Megabit (if window doesn't appear, start over, act faster) 13 | 6) Click FW Update, select .imf file and wait until finished, close ichip program 14 | 7) power cycle arduino/gevcu and wait 20-30sec 15 | 8) menu "serial ports", set baud rate to 115200 16 | 9) go to configuration page 17 | 18 | check-out http://www.youtube.com/watch?v=vS60htz6h1g at 00:35:00 19 | 20 | */ 21 | char inbyte; 22 | bool flag = true; 23 | void setup() { 24 | SerialUSB.begin(9600); // use SerialUSB only as the programming port doesn't work 25 | Serial2.begin(9600); // use Serial3 for GEVCU2, use Serial2 for GEVCU3+4 26 | // pinMode(43, INPUT); 27 | pinMode(18, OUTPUT); 28 | digitalWrite(18, LOW); 29 | } 30 | 31 | void loop() { 32 | while (Serial2.available()) { 33 | SerialUSB.write(Serial2.read()); 34 | } 35 | while (SerialUSB.available()) { 36 | inbyte=SerialUSB.read(); 37 | if (inbyte=='~'){sendcommandlist();} 38 | else {Serial2.write(inbyte);} 39 | } 40 | 41 | if (millis() > 6000) { 42 | digitalWrite(18, HIGH); 43 | } 44 | 45 | 46 | } 47 | 48 | void sendcommandlist() 49 | { 50 | SerialUSB.println("Sending commands...."); 51 | 52 | sendmessage("AT+iFD"); 53 | sendmessage("AT+iHIF=1"); 54 | sendmessage("AT+iBDRA"); 55 | sendmessage("AT+iWLCH=8"); 56 | sendmessage("AT+iWLSI=GEVCU1"); 57 | sendmessage("AT+iDIP=192.168.1.46"); 58 | sendmessage("AT+iSNET=255.255.255.0"); 59 | sendmessage("AT+iDPSZ=8"); 60 | sendmessage("AT+iWST0=4"); 61 | sendmessage("AT+iWPP0="); 62 | sendmessage("AT+iRPG=secret"); 63 | sendmessage("AT+iWPWD=secret"); 64 | 65 | sendmessage("AT+iAWS=1"); 66 | sendmessage("AT+iSTAP=1"); 67 | sendmessage("AT+iDOWN"); 68 | 69 | SerialUSB.println("Command list completed...."); 70 | } 71 | 72 | void sendmessage(char* message) 73 | { 74 | Serial2.println(message); 75 | delay(500); 76 | while (Serial2.available()) {SerialUSB.write(Serial2.read());} 77 | 78 | } 79 | -------------------------------------------------------------------------------- /util/i2128d810d35BCOM.IMF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/util/i2128d810d35BCOM.IMF -------------------------------------------------------------------------------- /util/i2128d810d35BCOM.IMZ: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/util/i2128d810d35BCOM.IMZ -------------------------------------------------------------------------------- /website/README.txt: -------------------------------------------------------------------------------- 1 | The GEVCU uses the Mini Socket iWifi module from ConnectOne. Documentation can be found at 2 | 3 | http://www.connectone.com/?page_id=217 4 | 5 | To update the website on the iChip, you have to use their packing tool which is part of their iChipConfig utility and only runs on Windows XP. If you use Windows 7 you can use Windows XP mode: 6 | 7 | http://windows.microsoft.com/en-us/windows7/install-and-use-windows-xp-mode-in-windows-7 8 | 9 | Download and install the following: 10 | 11 | http://www.connectone.com/wp-content/uploads/2012/06/iChipConfigExternal_2.4.95_setup7.zip 12 | 13 | Then to update the website after changes, 14 | 15 | 1. Launch iChipConfig, click through warnings about not having the com port and limited functionality 16 | 2. Choose the "Site Pack" tool 17 | 3. Browse to the website/src dir, select the index.htm as default 18 | 4. Select "C02128" as the platform and click "Pack". At this point the parameters should show. 19 | 5. Select all the parameters, enter 20 for the max length value to fill and click "Fill" 20 | 6. Click "Save" and point it to website.img 21 | 22 | At this point you upload the image to the GEVCU using http://192.168.3.10/ichip and power cycle the GEVCU to have it activated. 23 | -------------------------------------------------------------------------------- /website/src/about.htm: -------------------------------------------------------------------------------- 1 |

ABOUT GEVCU 5.220

2 |

3 | 4 |

5 | The Generalized Electric Vehicle Control Unit - GEVCU is an open source 6 | software and hardware project to develop a Vehicle Control Unit (VCU) specifically 7 | for electric vehicles. 8 |

9 | The purpose of GEVCU is to handle throttle control, regenerative 10 | braking, forward, reverse, and such peculiarities as precharge, cooling system control, 11 | instrumentation etc. - essentially the driver interface of the car. 12 |

13 | GEVCU then manages torque and speed commands to the power electronics 14 | via CAN bus to actually operate the vehicle in response to driver input. 15 |

16 | But it also provides outputs to instrumentation, brake lights, reverse lights, cooling systems, and other controls specific to that vehicle. 17 |

18 | GEVCU is both open-source and object-oriented allowing easy addition of 19 | additional C++ object modules to incorporate multiple standard power components. 20 | It is easily modified using the Arduino IDE to incorporate additional features 21 | peculiar to any specific electric car conversion or build. 22 |

23 | For most operations, it is easily configurable by non-programmers through 24 | simple web and serial port interfaces to adapt to a wide variety of power 25 | components and vehicle applications. 26 |

27 | GEVCU was originally conceived of and proposed by Jack Rickard of 28 | Electric Vehicle Television (http://EVtv.me) who wrote the original 29 | design specification. 30 |

31 | The main source of the program was developed and is maintained by Collin Kidder 32 | and the latest version is always available at http:/github.com/collin80/GEVCU. 33 | A list of major contributors to the project is maintained there. 34 |

35 | Hardware was designed and developed by Ed Clausen and Paulo Jorge Pires de Almeida 36 | based on the Arduino Due. 37 |

38 | GEVCU is open source hardware and software and is presented as EXPERIMENTAL - USE AT YOUR 39 | OWN RISK. It is offered strictly for experimental and educational 40 | purposes and is NOT intended for actual use in any commercial product 41 | or for any specific useful purpose. 42 | -------------------------------------------------------------------------------- /website/src/annunciator.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
READYRUNNINGERRORWARNINGOVERTEMP INVERTER
PRECHARGE RELAYMAIN CONTACTOROUTPUT 0OUTPUT 1OUTPUT 2
OUTPUT 3OUTPUT 4OUTPUT 5OUTPUT 6OUTPUT 7
INPUT 0INPUT 1INPUT 2INPUT 3REVERSEENABLE
36 | -------------------------------------------------------------------------------- /website/src/annunciator.js: -------------------------------------------------------------------------------- 1 | var FieldClass = { 2 | off : "annunciatorOff", 3 | warn : "annunciatorWarn", 4 | error : "annunciatorError", 5 | ok : "annunciatorOk" 6 | }; 7 | 8 | var Status = { /* statusBitfield1 */ 9 | out0 : 1 << 0, 10 | out1 : 1 << 1, 11 | out2 : 1 << 2, 12 | out3 : 1 << 3, 13 | out4 : 1 << 4, 14 | out5 : 1 << 5, 15 | out6 : 1 << 6, 16 | out7 : 1 << 7, 17 | torqueLimitation : 1 << 8, 18 | errorFlag : 1 << 9, 19 | warningFlag : 1 << 10, 20 | slewRateLimitation : 1 << 12, 21 | motorTemperatureLimitation : 1 << 13, 22 | stateRunning : 1 << 14, 23 | stateReady : 1 << 15 24 | }; 25 | 26 | var Warning = { /* statusBitfield2 */ 27 | din0 : 1 << 0, 28 | din1 : 1 << 1, 29 | din2 : 1 << 2, 30 | din3 : 1 << 3, 31 | driverShutdownPathActive : 1 << 10, 32 | powerMismatchDetected : 1 << 11, 33 | speedSensorSignal : 1 << 12, 34 | hvUndervoltage : 1 << 13, 35 | maximumModulationLimiter : 1 << 14, 36 | temperatureSensor : 1 << 15, 37 | res1 : 1 << 16, 38 | res2 : 1 << 17, 39 | res3 : 1 << 18, 40 | res4 : 1 << 19 41 | }; 42 | 43 | var Error = { /* statusBitfield3 */ 44 | speedSensorSupply : 1 << 0, 45 | speedSensor : 1 << 1, 46 | canLimitMessageInvalid : 1 << 2, 47 | canControlMessageInvalid : 1 << 3, 48 | canLimitMessageLost : 1 << 4, 49 | overvoltageSkyConverter : 1 << 5, 50 | voltageMeasurement : 1 << 6, 51 | shortCircuit : 1 << 7, 52 | canControlMessageLost : 1 << 8, 53 | overtemp : 1 << 9, 54 | overtempMotor : 1 << 10, 55 | overspeed : 1 << 11, 56 | undervoltage : 1 << 12, 57 | overvoltage : 1 << 13, 58 | overcurrent : 1 << 14, 59 | initalisation : 1 << 15, 60 | analogInput : 1 << 16, 61 | driverShutdown : 1 << 22, 62 | powerMismatch : 1 << 23, 63 | canControl2MessageLost : 1 << 24, 64 | motorEeprom : 1 << 25, 65 | storage : 1 << 26, 66 | enablePinSignalLost : 1 << 27, 67 | canCommunicationStartup : 1 << 28, 68 | internalSupply : 1 << 29, 69 | acOvercurrent : 1 << 30, 70 | osTrap : 1 << 31 71 | }; 72 | 73 | function updateAnnunciatorFields(name, bitfield) { 74 | switch (name) { 75 | case 'bitfield1': 76 | updateField("out0", FieldClass.ok, bitfield & Status.out0); 77 | updateField("out1", FieldClass.ok, bitfield & Status.out1); 78 | updateField("out2", FieldClass.ok, bitfield & Status.out2); 79 | updateField("out3", FieldClass.ok, bitfield & Status.out3); 80 | updateField("out4", FieldClass.ok, bitfield & Status.out4); 81 | updateField("out5", FieldClass.ok, bitfield & Status.out5); 82 | updateField("out6", FieldClass.ok, bitfield & Status.out6); 83 | updateField("out7", FieldClass.ok, bitfield & Status.out7); 84 | updateField("torqueLimitation", FieldClass.warn, bitfield & Status.torqueLimitation); 85 | updateField("errorFlag", FieldClass.error, bitfield & Status.errorFlag); 86 | updateField("warningFlag", FieldClass.warn, bitfield & Status.warningFlag); 87 | updateField("slewRateLimitation", FieldClass.warn, bitfield & Status.slewRateLimitation); 88 | updateField("motorTemperatureLimitation", FieldClass.warn, bitfield & Status.motorTemperatureLimitation); 89 | updateField("stateRunning", FieldClass.ok, bitfield & Status.stateRunning); 90 | updateField("stateReady", FieldClass.ok, bitfield & Status.stateReady); 91 | break; 92 | case 'bitfield2': 93 | updateField("din0", FieldClass.ok, bitfield & Warning.din0); 94 | updateField("din1", FieldClass.ok, bitfield & Warning.din1); 95 | updateField("din2", FieldClass.ok, bitfield & Warning.din2); 96 | updateField("din3", FieldClass.ok, bitfield & Warning.din3); 97 | updateField("driverShutdownPathActive", FieldClass.warn, bitfield & Warning.driverShutdownPathActive); 98 | updateField("powerMismatchDetected", FieldClass.warn, bitfield & Warning.powerMismatchDetected); 99 | updateField("speedSensorSignal", FieldClass.warn, bitfield & Warning.speedSensorSignal); 100 | updateField("hvUndervoltage", FieldClass.warn, bitfield & Warning.hvUndervoltage); 101 | updateField("maximumModulationLimiter", FieldClass.warn, bitfield & Warning.maximumModulationLimiter); 102 | updateField("temperatureSensor", FieldClass.warn, bitfield & Warning.temperatureSensor); 103 | updateField("res1", FieldClass.ok, bitfield & Warning.res1); 104 | updateField("res2", FieldClass.ok, bitfield & Warning.res2); 105 | updateField("res3", FieldClass.ok, bitfield & Warning.res3); 106 | updateField("res4", FieldClass.ok, bitfield & Warning.res4); 107 | break; 108 | case 'bitfield3': 109 | updateField("speedSensorSupply", FieldClass.error, bitfield & Error.speedSensorSupply); 110 | updateField("speedSensor", FieldClass.error, bitfield & Error.speedSensor); 111 | updateField("canLimitMessageInvalid", FieldClass.error, bitfield & Error.canLimitMessageInvalid); 112 | updateField("canControlMessageInvalid", FieldClass.error, bitfield & Error.canControlMessageInvalid); 113 | updateField("canLimitMessageLost", FieldClass.error, bitfield & Error.canLimitMessageLost); 114 | updateField("overvoltageSkyConverter", FieldClass.error, bitfield & Error.overvoltageSkyConverter); 115 | updateField("voltageMeasurement", FieldClass.error, bitfield & Error.voltageMeasurement); 116 | updateField("shortCircuit", FieldClass.error, bitfield & Error.shortCircuit); 117 | updateField("canControlMessageLost", FieldClass.error, bitfield & Error.canControlMessageLost); 118 | updateField("overtemp", FieldClass.error, bitfield & Error.overtemp); 119 | updateField("overtempMotor", FieldClass.error, bitfield & Error.overtempMotor); 120 | updateField("overspeed", FieldClass.error, bitfield & Error.overspeed); 121 | updateField("undervoltage", FieldClass.error, bitfield & Error.undervoltage); 122 | updateField("overvoltage", FieldClass.error, bitfield & Error.overvoltage); 123 | updateField("overcurrent", FieldClass.error, bitfield & Error.overcurrent); 124 | updateField("initalisation", FieldClass.error, bitfield & Error.initalisation); 125 | updateField("analogInput", FieldClass.error, bitfield & Error.analogInput); 126 | updateField("driverShutdown", FieldClass.error, bitfield & Error.driverShutdown); 127 | updateField("powerMismatch", FieldClass.error, bitfield & Error.powerMismatch); 128 | updateField("canControl2MessageLost", FieldClass.error, bitfield & Error.canControl2MessageLost); 129 | updateField("motorEeprom", FieldClass.error, bitfield & Error.motorEeprom); 130 | updateField("storage", FieldClass.error, bitfield & Error.storage); 131 | updateField("enablePinSignalLost", FieldClass.error, bitfield & Error.enablePinSignalLost); 132 | updateField("canCommunicationStartup", FieldClass.error, bitfield & Error.canCommunicationStartup); 133 | updateField("internalSupply", FieldClass.error, bitfield & Error.internalSupply); 134 | updateField("acOvercurrent", FieldClass.error, bitfield & Error.acOvercurrent); 135 | updateField("osTrap", FieldClass.error, bitfield & Error.osTrap); 136 | break; 137 | case 'bitfield4': 138 | break; 139 | } 140 | } 141 | 142 | function updateField(id, fieldClass, flag) { 143 | var target = document.getElementById(id); 144 | if (target) 145 | target.className = (flag == 0 ? FieldClass.off : fieldClass); 146 | } -------------------------------------------------------------------------------- /website/src/config.htm: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
82 | 83 | 84 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 |

Throttle

Number of Throttle Pots Throttle Type
Minimum Signal Level 1Pedal Position Regen Maximum %
Maximum Signal Level 1Pedal Position Regen Minimum %
Minimum Signal Level 2Pedal Position Forward Motion Start %
Maximum Signal Level 2Pedal Position 50% throttle %
Creep Level %Minimum Throttle Regen %
Maximum Throttle Regen %
Your browser does not support the HTML5 canvas tag.

Brake

Minimum Signal LevelMinimum Brake Regen %
Maximum Signal LevelMaximum Brake Regen %

85 | Motor Control

Maximum Speed rpmMaximum Torque Nm
Motor Mode

System

Log LevelBattery Voltage vdc
120 |
121 |
122 | 123 | 124 |
125 |
126 | 127 | 128 | -------------------------------------------------------------------------------- /website/src/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ~numThrottlePots~ 4 | ~throttleSubType~ 5 | ~throttleMin1~ 6 | ~throttleMin2~ 7 | ~throttleMax1~ 8 | ~throttleMax2~ 9 | ~throttleRegenMax~ 10 | ~throttleRegenMin~ 11 | ~throttleFwd~ 12 | ~throttleMap~ 13 | ~throttleMinRegen~ 14 | ~throttleMaxRegen~ 15 | ~throttleCreep~ 16 | ~brakeMin~ 17 | ~brakeMax~ 18 | ~brakeMinRegen~ 19 | ~brakeMaxRegen~ 20 | ~speedMax~ 21 | ~torqueMax~ 22 | ~motorMode~ 23 | ~logLevel~ 24 | ~nominalVolt~ 25 | 26 | -------------------------------------------------------------------------------- /website/src/dashboard.htm: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | Your browser does not support the HTML5 canvas tag. 5 | 6 | 7 | 8 | Your browser does not support the HTML5 canvas tag. 9 | 10 | 11 | Your browser does not support the HTML5 canvas tag. 12 | 13 | 14 | 15 | Your browser does not support the HTML5 canvas tag. 16 |
17 | 18 |
19 | 20 |
21 | 22 | Your browser does not support the HTML5 canvas tag. 23 | 24 | 25 | Your browser does not support the HTML5 canvas tag. 26 | 27 | 28 | 29 | Your browser does not support the HTML5 canvas tag. 30 | 31 | 32 | 33 | Your browser does not support the HTML5 canvas tag. 34 | 35 | 36 | Your browser does not support the HTML5 canvas tag. 37 |
38 |
39 | -------------------------------------------------------------------------------- /website/src/dashboard.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ~tempMotor~ 4 | ~tempInverter~ 5 | ~throttle~ 6 | ~torqueActual~ 7 | ~speedActual~ 8 | ~dcVoltage~ 9 | ~dcCurrent~ 10 | ~kiloWattHours~ 11 | ~mechPower~ 12 | 13 | -------------------------------------------------------------------------------- /website/src/devices.htm: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 29 | 30 | 31 | 35 | 36 | 40 | 41 | 42 | 46 | 47 | 51 | 52 | 53 | 54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 78 | 79 | 83 | 84 | 85 | 86 | 87 | 91 | 92 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 108 | 109 | 110 | 111 | 112 |

Device Selection/Activation

.

Motor Controllers/Inverters

Throttle and Brake

Azure Dynamics DMOC645Potentiometer/Hall Effect Throttle
UQM Powerphase 100Potentiometer/Hall Effect Brake
Brusa DMC5CAN bus Throttle
CAN bus Brake

.

Communication Interfaces

Battery Chargers and Management

ConnectOne WiReach WiFiDelphi DC-DC Converter
ELM327 OBDII WirelessTHINK Systems BMS
Andromeda EVIC Display
113 |
114 |
115 |
116 |

To activate selections, click SAVE and power cycle GEVCU

117 | 118 |
119 |
120 | 121 | 122 | -------------------------------------------------------------------------------- /website/src/devices.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ~x1000~ 5 | ~x1001~ 6 | ~x1002~ 7 | ~x1031~ 8 | ~x1032~ 9 | ~x1033~ 10 | ~x1034~ 11 | ~x1040~ 12 | ~x1050~ 13 | ~x650~ 14 | ~x6000~ 15 | ~x4400~ 16 | ~x1010~ 17 | ~x1011~ 18 | ~x1012~ 19 | ~x2000~ 20 | 21 | -------------------------------------------------------------------------------- /website/src/fonts/digital-7-mono.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/website/src/fonts/digital-7-mono.eot -------------------------------------------------------------------------------- /website/src/fonts/digital-7-mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/website/src/fonts/digital-7-mono.ttf -------------------------------------------------------------------------------- /website/src/index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GEVCU 5.220 6 | 7 | 8 | 9 | 10 | 11 | 12 | 28 | 29 | 30 | 31 | 32 |

GEVCU 5.220

33 |
34 | Status 35 | Dashboard 36 | Throttle 37 | Outputs 38 | Inputs 39 | Devices 40 | About 42 |
43 | 44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | 54 | 55 | -------------------------------------------------------------------------------- /website/src/inputs.htm: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |

Digital Inputs - DIN0 to DIN3

Enable Input
Reverse Input
41 |
42 | 43 | 44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /website/src/inputs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ~enableIn~ 4 | ~reverseIn~ 5 | 6 | -------------------------------------------------------------------------------- /website/src/outputs.htm: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | 72 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 102 |

Digital Outputs - DOUT0 to DOUT7

Fan OutputFan ON Temp °CFan OFF Temp °C
Precharge OutputPrecharge Delay milliseconds
Main Contactor Output
Brake Light Output
Reverse Light Output
103 |
104 |
105 |
106 | 107 |
108 |
109 | 110 | 111 | -------------------------------------------------------------------------------- /website/src/outputs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ~coolOn~ 4 | ~coolOff~ 5 | ~coolFan~ 6 | ~prechargeRelay~ 7 | ~mainContactorRelay~ 8 | ~prechargeR~ 9 | ~brakeLight~ 10 | ~revLight~ 11 | -------------------------------------------------------------------------------- /website/src/status.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 |

Motor Control

Throttle / Brake

Running:      Operating Time:      Throttle Level: raw value
Fault: Warning: Brake Level: raw value
Gearswitch:
Motor Temperature: °CInverter Temperature: °C
Requested Torque: NmActual Torque: Nm
Battery Voltage: VoltBattery Current: AmperePower: kW

ANNUNCIATORS

83 | 84 |
85 | -------------------------------------------------------------------------------- /website/src/status.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ~timeRunning~ 4 | ~running~ 5 | ~faulted~ 6 | ~warning~ 7 | ~tempMotor~ 8 | ~tempInverter~ 9 | ~tempSystem~ 10 | ~throttle~ 11 | ~brake~ 12 | ~gear~ 13 | ~torqueRequested~ 14 | ~torqueActual~ 15 | ~speedRequested~ 16 | ~speedActual~ 17 | ~dcVoltage~ 18 | ~dcCurrent~ 19 | ~kiloWattHours~ 20 | ~mechPower~ 21 | ~bitfield1~ 22 | ~bitfield2~ 23 | ~bitfield3~ 24 | ~bitfield4~ 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /website/src/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #ffffff; 3 | font-family: arial, verdana, sans-serif; 4 | background: #0F0F0F; 5 | background: linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 6 | background: -o-linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 7 | background: -moz-linear-gradient(bottom, rgb(2, 44, 84), rgb(15, 15, 16) 70%); 8 | background: -webkit-linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 9 | background: -ms-linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 10 | background-attachment: fixed; 11 | } 12 | 13 | div.tabHeader { 14 | height: 32px; 15 | overflow: hidden; 16 | } 17 | 18 | div.tabHeader a { 19 | float: left; 20 | display: block; 21 | width: 120px; 22 | text-align: center; 23 | height: 28px; 24 | padding-top: 3px; 25 | vertical-align: middle; 26 | border: 1px solid #555599; 27 | border-bottom-width: 0; 28 | text-decoration: none; 29 | font-weight: 500; 30 | color: #8888ff; 31 | } 32 | 33 | div.tabHeader a:hover,div.tabHeader a.Active { 34 | background-color: #ffff55; 35 | background: linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 36 | background: -o-linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 37 | background: -moz-linear-gradient(bottom, rgb(2, 44, 84), rgb(15, 15, 16) 70%); 38 | background: -webkit-linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 39 | background: -ms-linear-gradient(bottom, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 40 | } 41 | 42 | div.tabHeader a.on { 43 | color: #ffffff; 44 | background: linear-gradient(top, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 45 | background: -o-linear-gradient(top, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 46 | background: -moz-linear-gradient(top, rgb(2, 44, 84), rgb(15, 15, 16) 70%); 47 | background: -webkit-linear-gradient(top, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 48 | background: -ms-linear-gradient(top, rgb(2, 44, 84) 1%, rgb(15, 15, 16) 70%); 49 | } 50 | 51 | div.tabs { 52 | clear: both; 53 | border: 1px solid #555599; 54 | overflow: hidden; 55 | } 56 | 57 | table.annunciators { 58 | background: #080808; 59 | border-collapse: collapse; 60 | border-spacing: 0px; 61 | } 62 | 63 | table.annunciators td { 64 | text-align: center; 65 | border: 4px solid #000000; 66 | height: 30px; 67 | width: 110px; 68 | font-size: 75%; 69 | color: #303030; 70 | } 71 | 72 | .annunciatorOff { 73 | color: #303030; 74 | } 75 | 76 | .annunciatorWarn { 77 | color: #ffbb00; 78 | } 79 | 80 | .annunciatorError { 81 | color: #ff2200; 82 | } 83 | 84 | .annunciatorOk { 85 | color: #22ee22; 86 | } 87 | 88 | input[type=range] { 89 | padding: 0 5px; 90 | width: 200px; 91 | } 92 | 93 | a { 94 | color: #5555ff; 95 | } 96 | 97 | h1 { 98 | color: #9999dd; 99 | font-size: 2.5em; 100 | margin-top: 5px; 101 | margin-bottom: 5px; 102 | } 103 | 104 | h2 { 105 | color: #bbbbff; 106 | margin-top: 10px; 107 | margin-bottom: 5px; 108 | padding: 0px 0px 0px 0px; 109 | } 110 | 111 | /* for safari */ 112 | input[type="range"]{ 113 | -webkit-appearance:none !important; 114 | background: rgb(FF, FF, FF); 115 | width: 200px; 116 | height: 6px; 117 | border-radius: 8px; 118 | -moz-border-radius: 8px; 119 | -wekkit-border-radius: 8px; 120 | -webkit-box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 0, 0.9), 0px 1px 1px 0px rgba(255, 255, 255, 0.13); 121 | -moz-box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 0, 0.9), 0px 1px 1px 0px rgba(255, 255, 255, 0.13); 122 | box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 0, 0.9), 0px 1px 1px 0px rgba(255, 255, 255, 0.13); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /website/website.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/collin80/GEVCU/8a06011344b8e8840a7ac3f6d97b264d14bbe2bf/website/website.img -------------------------------------------------------------------------------- /workinprogress.txt: -------------------------------------------------------------------------------- 1 | A textfile with various notes to whoever else is interested 2 | in what's coming down the pike and possibly what they could do: 3 | 4 | Much of what was in here has been done or rendered moot. Instead here is the current 5 | lay of the land: 6 | 7 | -There are observers for ticks and canbus but canbus is not yet done. So, one thing 8 | on the agenda is to complete canbus observer (This has now been submitted but 9 | is being held back from master until after EVCCON.) 10 | 11 | -The new board has wifi but we're not using it. A big problem currently is that 12 | we have no good way to set parameter so, while EEPROM is working, it is worthless 13 | because the only way to set it is to change code. So, why use it? For this reason 14 | we don't really read much of anything from EEPROM right now. Suitable code and 15 | webpages need to be constructed to make this all work. 16 | 17 | Allow Wifi to remote control all sorts of stuff, connect to internet and send 18 | notifications, etc. 19 | 20 | --------------------------------------------------------------------------------