-
Notifications
You must be signed in to change notification settings - Fork 56
Extending GEVCU
So, you want to make a new device class to support something GEVCU doesn't currently do.
- The first thing to ask yourself is "which base class do I use?"
- MotorController is the base for all inverters and motor driving hardware.
- Throttle is the base for all devices that regulate drive power. This includes cruise control and braking systems.
- BatteryManager is the base for all battery monitoring and management systems.
- If you aren't adding one of the above you're out of luck. The base classes for chargers, displays, etc do not exist. However, hope is not lost. Device can be used as a base class for any device support. It includes the most important functionality for creating a device that can integrate into the GEVCU system.
- Secondly, do you need to gain access to CANBus?
- CANBus support can be added to your class by also inheriting from CanObserver.
So, let's say you want to add support for a new canbus controlled inverter. You might declare your class like this: class MyMotorController: public MotorController, CanObserver {}; The rest of this wiki page will assume we're still adding a canbus controlled motor controller. The methods included here are applicable to any device however. If you do not need canbus then just ignore any reference to canbus setup and handling.
Now, what do you need to do to properly setup and run your device code?
- First of all, you should implement the void setup(); method. This method is automatically called for you shortly after your class is instantiated by the system. In this method all the other callbacks and handlers should be set up. Let's look at an example:
void MyMotorController::setup() {
TickHandler::getInstance()->detach(this);
MotorController::setup(); // run the parent class version of this function
// register ourselves as observer of 0x23x and 0x65x can frames
CanHandler::getInstanceEV()->attach(this, 0x230, 0x7f0, false);
CanHandler::getInstanceEV()->attach(this, 0x650, 0x7f0, false);
TickHandler::getInstance()->attach(this, CFG_TICK_INTERVAL_MOTOR_CONTROLLER);
}
First of all, this method makes sure to remove any tick handlers that might already exist for this class. There certainly shouldn't be any yet but it is good form to make sure. A tick handler allows your class to receive periodic callbacks so that it can do some activities at regular intervals. Next the base class version of this method is called. This method does handle some activities and so should always be called unless you really know of a reason not to. Next, if you need to accept canbus frames then you'll have to let the system know which frames you are interested in. There are two canbus networks on the GEVCU. They can be accessed as CanHandler::getInstanceEV() and CanHandler::getInstanceCar(). The traditional network to use (and the first network) is the EV instance. attach takes 4 parameters: first, the class that is registering for frames. You will probably nearly always want to use "this". The second parameter specifies the ID you want to match against. The third parameter specifies the mask to use. The fourth parameter specifies whether to filter for extended IDs or not. It is worth a quick explanation about how IDs and masks work in this context. Let's say you need to accept frames with an ID of 0x230 through 0x23F. That's 16 different IDs but all in a row. The ids are all identical except for their last 4 bits. So, we could match just the upper 7 bits of the 11 bit ID since those are the same. That's what the line in the above example does. 0x7F0 masks out the bottom 4 bits of the incoming id. So, if a frame with id 0x23A comes in it will become 0x230 after the mask. Then this new value is compared against the ID set. They match and so you would receive the frame. However, if 0x24A came in it would resolve to 0x240 after the mask and not be forwarded to your class. Lastly, if you want to receive ticks then you must register with the tick handler and tell it how often you want to receive ticks. There are many preexisting tick values defined in config.h It is desirable that existing values be used where possible as there are a finite number of timers that can be used to track ticks. All values are in microseconds (millionths of a second). So, a tick interval of 40000 (the default for motor controllers) means a tick every 40ms or 25 ticks per second.