Motor Control Theory
Gas motor rpm is tied to voltage output of the dc motor. There is a linear relationship. In order to control voltage, it may be possible to hold voltage within ranges by controlling the gas motor throttle.
There are two conditions to consider regarding motor control: 1. No Load and 2. Max Load. An example of No Load would be while standing still waiting for a stoplight with the motor running. Max Load would be at start up from a stop while using full electric hubmotor throttle.
It is possible that the system would work adequately with a static throttle position. However, the throttle would have to be set so that the target voltage is achieved at No Load condition. Under Max Load, the actual voltage would likely sag. There may be some optimization to achieve by increasing gas motor throttle under load.
No Load
The goal at No Load is to hold but not exceed the fast charge rate voltage. For my 48V lead acid system, the target voltage for fast charge is 57.5V. This is based on lead acid battery chemistry. I do not want to exceed this voltage in order to avoid battery damage. I want to maintain the target voltage to maximize charging into the battery system. No Load gas motor throttle position -> Target Throttle Position -> TTP. TTP is the throttle position where the generator system provides 57.5V.
Max Load
Assuming TTP at Max Load, the electric hubmotor draws current and voltage sags. Initial power used to power the electric hubmotor comes from the generator system. However generator power is limited and is less than the electric hubmotor load. Generator voltage will sag until battery voltage (about 51V, depending on charge level) is reached, and batteries would then provide power. As voltage continues to sag under load, gas motor rpm will be reduced due to the load. Voltage would continue to sag under battery power until available battery current and electric wheel power "equalize".
If it were possible to increase the gas motor throttle to work against the voltage sag under load, the power draw from the batteries would be reduced and range would be increased. Any time that the generator voltage remains above battery voltage, battery charging is occurring. This allows a longer run time under electric power only, no gas motor, meaning the gas motor might run for less time.
While the generator is operating, generator and battery systems are at the same potential (voltage). A controller could be designed to measure the generator voltage and adjust a servo to increase gas motor throttle when the generator voltage drops below the fast charge voltage.
The programmable Arduino is a kit that is intended to help people learn about electronics, but is also robust enough to be used in real life applications.
The Arduino can measure voltage from 0V to 5V and will provide a reference number for control of other devices. The Arduino can be programmed to control a servo of the type used in RC (hobby remote control) applications.
In order to measure voltage, a voltage divider could be used to reduce system voltage (about 50V - 58V) to Arduino sensor voltage (between 0V and 5V).
See:
http://en.wikipedia.org/wiki/Voltage_divider
Voltage Divider Calculation
The Arduino requires very little current to measure voltage. A voltage divider will alway draw a certain amount of current to the ground. For the hybrid bike system, I would accept about 10mA of loss for the voltage divider.
58V / 10 mA = 5800 ohms (total voltage divider resistance)
My target voltage for the Arduino is 3V (roughly midrange 0V - 5V).
3V / 58V * 5800 ohms = 300 ohms
5800 ohms - 300 ohms = 5500 ohms
About 300 ohms of resistance would have to be on the ground side of the Arduino sensor, and 5500 ohms would have to be on the generator positive side of the Arduino.
Actually I would probably use a 10k ohm potentiometer, which would allow me to fine adjust the voltage level, at least at first. When an optimal resistance is found with the potentiometer, I would then measure the resistances and use resistors instead of a potentiometer in order to prevent voltage creep due to vibration or bumping the potentiometer.
The result of the voltage divider would be to provide an approximate 3V to the Arduino sensor, with the voltage varying together with the generator output voltage. The Arduino changes the input voltage to a reference number. In the case of 3V, the Arduino reference number would be about 615. As the reference number rises and falls, a servo can be controlled through the Arduino programmable interface.
Arduino Servo Control
Below is an example servo control script for the Arduino. It allow the user to move the servo by adjusting a potentiometer. This script has not been changed to control a gas motor throttle based on sensor voltage, but it could be modified to do so.
Code:
// Generator Servo Voltage Control
// Sample voltage, adjust throttle with servo to regulate voltage
// Futaba FP-528, pulse range 250 to 2300 milliseconds, over 180 degrees throw
// Static variables
int servoPin = 2; // Control pin for servo motor
int minPulse = 250; // Minimum servo position
int analogPin = 0; // voltage sensor pin, between 0V an 5V
int refreshTime = 20; // the time in between pulses, servo speed adjustment
// Dynamic variables
int pulse = 0; // Servo pulse holder, adjusts servo angle
long lastPulse = 0; // the time in milliseconds since the last pulse
int analogValue = 0; // the value returned from the analog sensor, 0 to 1023
// Calculated values and adjustments
// Adjust the throw angle as shown in the pulse line below
// Adjust the servo motor speed with the refreshTime variable above
// Voltage at analogPin 0 changes analogPin value,
// at 0V -> 0, 1V -> 207, 2V -> 408, 3V -> 615, 4V -> 822, 5V -> 1023
void setup() {
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
pulse = minPulse; // Set the motor position value to the minimum
Serial.begin(9600);
}
void loop() {
analogValue = analogRead(analogPin); // read the analog input, 0 to 1023
pulse = (analogValue*2.0) + minPulse;
// 2.0 is a value that gives about 180 degrees throw on the Futaba servo
// Reduce 2.0 value to reduce throw, also can recalculate 2.0 value:
// 1023 * X + minPulse = maxPulse, where X = new 2.0 value in above line
// and maxPulse is the pulse value that gives the desired max throw angle
// pulse the servo again after refresh time (20 ms)
if (millis() - lastPulse >= refreshTime) {
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulse); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
// Print pulse and analogValue to screen
Serial.print("pulse: ");
Serial.print(pulse);
Serial.print("; analogValue: ");
Serial.println(analogValue);
}
}