forked from collin80/GEVCU
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a test throttle and test inverter that can be used to test the …
…new BLE system without actual hardware or can be used for testing. Fixed up some BLE bugs.
- Loading branch information
Showing
9 changed files
with
606 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
Outline of how to handle bluetooth: | ||
|
||
Scan for BLE devices immediately when starting up. Get a list of them and then scan each one | ||
to see if it implements the 0x3100 service. If not then ignore it. Otherwise, pick | ||
the first one to implement the service and start using it to get the characteristics. | ||
|
||
Characteristics are: | ||
0x3101 - TimeRunning (in seconds) | ||
4 bytes unsigned - number of seconds since GEVCU has started. | ||
|
||
0x3102 - TrqReqAct | ||
2 bytes signed - Requested Torque in 0.1Nm increments | ||
2 bytes signed - Actual torque in 0.1Nm inc | ||
|
||
0x3103 - ThrBrkLevels | ||
2 bytes unsigned - Raw Throttle value (from ADC) | ||
2 bytes unsigned - Raw brake value (from ADC) | ||
|
||
0x3104 - Speed | ||
2 bytes unsigned - Requested RPM (always positive even for reverse) | ||
2 bytes unsigned - Actual RPM (always positive) | ||
|
||
0x3105 - Modes (Writable) | ||
1 byte - Power Mode (0 = Torque, 1 = Direct RPM control) | ||
1 byte - Gear (0 = Neutral, 1 = Drive, 2 = Reverse, 3 = Error) - Writes to this are ignored. | ||
1 byte - IsRunning (True if we're currently drive enabled) - Writes are ignored | ||
1 Byte - IsFaulted (obviously, true if there is a fault) - Writes ignored | ||
1 Byte - IsWarning (True is there is currently a warning in effect) - Writes Ignored | ||
1 Byte - LogLevel (0 = Debugging, 1 = Info, 2 = Warn 3 = Error 4 = Off) | ||
|
||
0x3106 - PowerStatus | ||
2 bytes unsigned - Bus Voltage in tenths of a volt | ||
2 bytes signed - Bus Current in tenths of an amp | ||
2 bytes signed - Motor Current in tenths of an amp | ||
2 bytes unsigned - Kilowatt hours left in the battery pack (in full kwh) | ||
2 bytes signed - Mechanical power in 0.1 kw increments | ||
|
||
0x3107 - Bitfields | ||
4 Bytes unsigned - Bitfield 1 - All these bitfields are set by the motor controller code | ||
4 Bytes unsigned - bitfield 2 - There doesn't seem to be any standardization here. | ||
4 Bytes unsigned - bitfield 3 - And, only the Brusa controller code even touches these. | ||
4 Bytes unsigned - bitfield 4 | ||
|
||
0x3108 - Temperature | ||
2 bytes signed - Motor temperature in 0.1C increment | ||
2 bytes signed - Inverter temperature in 0.1C increment | ||
2 bytes signed - System temperature in 0.1C increment | ||
|
||
0x3109 - DigitalIO (Writable) | ||
2 bytes unsigned - Precharge resistance in ohms (used to figure out how long the timing should be) | ||
1 byte - Which digital output to use for precharge | ||
1 byte - Which digital output to use for the main contactor | ||
1 byte - which digital output to use to actuate cooling fans | ||
1 byte - Temperature in C at which to turn on the cooling fans | ||
1 byte - Temperature in C at which to turn them off again | ||
1 byte - Which digital output to use for brake lights | ||
1 byte - Which digital output to use for reverse lights | ||
1 byte - Which digital input to use for enabling motor controller drive | ||
1 byte - which digital input to use for going into reverse (instead of drive) | ||
|
||
|
||
0x310A - ThrottleIO (Writable) | ||
1 Byte - Number of throttle inputs (only really relevant to POT based throttles). 1-3 inputs on ADC ports | ||
1 Byte - Throttle type (1 = Standard Pot, 2 = Inverse Pot) | ||
2 Bytes Unsigned - Throttle 1 Minimum Value | ||
2 Bytes Unsigned - Throttle 2 Minimum Value | ||
2 Bytes Unsigned - Throttle 1 Maximum Value | ||
2 Bytes Unsigned - Throttle 2 Maximum Value | ||
|
||
0x310B - ThrottleMap (Writable) | ||
2 Bytes unsigned - Pedal position (1/10 of a %) where regen is at its maximum | ||
2 bytes unsigned - Pedal position where regen is at its minimum | ||
2 bytes unsigned - Pedal position where forward motion starts | ||
2 bytes unsigned - Pedal position where 50% power is applied | ||
1 byte - Percentage of full torque to use for minimum regen | ||
1 byte - Percentage of full torque to use for maximum regen | ||
1 byte - percentage of full torque to use for creep | ||
|
||
0x310C - BrakeParam (Writable) | ||
2 bytes unsigned - ADC value for minimum brake signal | ||
2 bytes unsigned - ADC value for maximum brake signal | ||
1 byte - Percentage of full torque to use for minimum brake regen | ||
1 byte - Percentage of full torque to use for maximum brake regen | ||
|
||
|
||
0x310D - MaxParams (Writable) | ||
2 bytes unsigned - Nominal battery pack voltage (1/10 of a volt) | ||
2 bytes unsigned - Maximum RPM to allow | ||
2 bytes unsigned - Maximum torque to allow | ||
|
||
0x31D0 - Update counter (just for debugging) | ||
4 bytes unsigned - counter that increments as other updates happen. Probably shouldn't subscribe to this as a notification. But, useful for debugging |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* TestMotorController.cpp | ||
* | ||
* Fake motor controller that takes throttle input and pretends like it's driving a motor. | ||
* Used just for testing surrounding code (throttle input, status output, etc) | ||
* | ||
Copyright (c) 2016 Collin Kidder, Michael Neuweiler, Charles Galpin | ||
Permission is hereby granted, free of charge, to any person obtaining | ||
a copy of this software and associated documentation files (the | ||
"Software"), to deal in the Software without restriction, including | ||
without limitation the rights to use, copy, modify, merge, publish, | ||
distribute, sublicense, and/or sell copies of the Software, and to | ||
permit persons to whom the Software is furnished to do so, subject to | ||
the following conditions: | ||
The above copyright notice and this permission notice shall be included | ||
in all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
*/ | ||
|
||
#include "TestMotorController.h" | ||
|
||
TestMotorController::TestMotorController() : MotorController() { | ||
prefsHandler = new PrefHandler(TESTINVERTER); | ||
|
||
selectedGear = DRIVE; | ||
commonName = "Test Inverter"; | ||
} | ||
|
||
void TestMotorController::setup() { | ||
TickHandler::getInstance()->detach(this); | ||
|
||
Logger::info("add device: Test Inverter (id:%X, %X)", TESTINVERTER, this); | ||
|
||
loadConfiguration(); | ||
MotorController::setup(); // run the parent class version of this function | ||
|
||
running = true; | ||
setPowerMode(modeTorque); | ||
setSelectedGear(DRIVE); | ||
setOpState(ENABLE); | ||
|
||
TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_MOTOR_CONTROLLER_DMOC); | ||
} | ||
|
||
void TestMotorController::handleTick() { | ||
TestMotorControllerConfiguration *config = (TestMotorControllerConfiguration *)getConfiguration(); | ||
|
||
MotorController::handleTick(); //kick the ball up to papa | ||
|
||
dcVoltage = 3600; //360v nominal voltage scaled up 10x | ||
|
||
//use throttleRequested to produce some motor like output. | ||
//throttleRequested ranges +/- 1000 so regen is possible here if the throttle has it set up. | ||
|
||
if (powerMode == modeSpeed) | ||
{ | ||
torqueRequested = 0; | ||
if (throttleRequested > 0 && operationState == ENABLE && selectedGear != NEUTRAL) | ||
speedRequested = (((long) throttleRequested * (long) config->speedMax) / 1000); | ||
else | ||
speedRequested = 0; | ||
|
||
speedActual = ((speedActual * 8) + (speedRequested * 2)) / 10; | ||
torqueActual = speedActual / 20; | ||
|
||
//generate some baseline holding current to maintain the speed. | ||
dcCurrent = speedRequested / 66; | ||
//Then add some accelerating current for the difference between target and actual | ||
dcCurrent += (speedRequested - speedActual) / 10; | ||
} | ||
else | ||
{ | ||
if (selectedGear == DRIVE) | ||
torqueRequested = (((long) throttleRequested * (long) config->torqueMax) / 1000L); | ||
if (selectedGear == REVERSE) | ||
torqueRequested = (((long) throttleRequested * -1 *(long) config->torqueMax) / 1000L); | ||
|
||
torqueActual = ((torqueActual * 7) + (torqueRequested * 3)) / 10; | ||
speedActual = torqueActual * 2; | ||
if (speedActual < 0) speedActual = 0; | ||
|
||
speedRequested = 0; | ||
|
||
//generate some baseline holding current to maintain the speed. | ||
dcCurrent = torqueRequested / 3; | ||
//Then add some accelerating current for the difference between target and actual | ||
dcCurrent += (torqueRequested - torqueActual) * 2; | ||
|
||
} | ||
|
||
acCurrent = (dcCurrent * 40) / 30; //A bit more current than DC bus | ||
|
||
//Both dc current and dc voltage are scaled up 10, mech power should be in 0.1kw increments | ||
//current*voltage = watts but there is inefficiency to deal with. and it's watts but we're scaled up 100x | ||
//because of multipliers so need to scale down 100x to get to watts then by 100x again to get to 0.1kw | ||
//100x100 = 10000 but inefficiency should make it even worse | ||
mechanicalPower = (dcCurrent * dcVoltage) / 12000; | ||
|
||
//Heat up or cool motor and inverter based on mechanical power being used. | ||
//Assume ambient temperature is 18C | ||
//These numbers are horrifically off from realistic physics at this point | ||
//but we're trying to aid debugging, not making a perfect physics model. | ||
temperatureMotor = 180 + abs(mechanicalPower); | ||
temperatureInverter = 190 + abs(mechanicalPower); | ||
temperatureSystem = (temperatureInverter + temperatureMotor) / 2; | ||
|
||
Logger::debug(TESTINVERTER, "PowerMode: %i, Gear: %i", powerMode, selectedGear); | ||
Logger::debug(TESTINVERTER, "TorqueReq: %i, SpeedReq: %i", torqueRequested, speedRequested); | ||
Logger::debug(TESTINVERTER, "dcCurrent: %i, mechPower: %i", dcCurrent, mechanicalPower); | ||
|
||
} | ||
|
||
void TestMotorController::setGear(Gears gear) { | ||
selectedGear = gear; | ||
//if the gear was just set to drive or reverse and the DMOC is not currently in enabled | ||
//op state then ask for it by name | ||
if (selectedGear != NEUTRAL) { | ||
operationState = ENABLE; | ||
} | ||
//should it be set to standby when selecting neutral? I don't know. Doing that prevents regen | ||
//when in neutral and I don't think people will like that. | ||
} | ||
|
||
DeviceId TestMotorController::getId() { | ||
return (TESTINVERTER); | ||
} | ||
|
||
uint32_t TestMotorController::getTickInterval() | ||
{ | ||
return CFG_TICK_INTERVAL_MOTOR_CONTROLLER_DMOC; | ||
} | ||
|
||
void TestMotorController::loadConfiguration() { | ||
TestMotorControllerConfiguration *config = (TestMotorControllerConfiguration *)getConfiguration(); | ||
|
||
if (!config) { | ||
config = new TestMotorControllerConfiguration(); | ||
setConfiguration(config); | ||
} | ||
|
||
MotorController::loadConfiguration(); // call parent | ||
} | ||
|
||
void TestMotorController::saveConfiguration() { | ||
MotorController::saveConfiguration(); | ||
} |
Oops, something went wrong.