I made an Arduino based throttle interface. It allows you to take 0-5v input from either Hall or Potentiometer throttles, and alter the output curve to anything you'd like. I'm using it to smooth out the throttle at the lower range.
You'll need an Arduino (Uno is what I used, Nano should work as well), a throttle and a MCP4725 Digital-To-Analog converter (DAC).
The currently programmed curve roughly follows this formula.
y = -0.0333(x)^4 + 0.2757(x)^3 - 0.468(x)^2 + 0.605(x)
Where x is the input voltage, and y is the output voltage. It looks like this.

Throttle Connection:
Arduino Side <> Throttle Side:
5V<>Throttle Positive
GND<>Throttle Ground
A0<> 0-5v Throttle Signal
MCP4725 DAC:
Arduino Side <> MCP4725 DAC Side
GND<>GND
5v<> VCC
A4<>SDA
A5<>SCL
THe MCP4725 OUT and GND will go to your controller.
How it works:
The Arduino A0 Pin is an analog to digital input, it can sense voltages 0-5v at 10 bit resolution, this means that it has available to it 1024 'steps' that represent 0.0049v each. The Arduino via the MCP library converts these steps into integers (numbers that range from 0-1023).
The MCP4725 has 12 bits of resolution, or 4096 steps of resolution, represented by integers 0-4095 @ 0.0012v per unit.
I used Excel to calculate the input/output for all 1024 possibilities of input, then found the closest integer that matches with 4096 scale. If you want to make your own curve, you'll need to plot some points and have Excel graph the trendline, give you the formula and you recalculate the appropriate output integers.
The Arduino can do this VERY quickly, there's no perceptible latency between input/output changes. However, I haven't measured what this latency actually is.
Future possibilities:
Throttle Smoothing
Minimum throttle movement to cause an output change
Feedback loop with other sensors (traction control module? Tip-over cut off, etc.)
NOTE:
Hall type throttles will output ~0.85v - ~4.3v with 5v input. A pot can get you closer to the full voltage range, so keep this in mind that your effective curve will be different between pot/hall throttles and what range of the curve you're subject to.
You'll need an Arduino (Uno is what I used, Nano should work as well), a throttle and a MCP4725 Digital-To-Analog converter (DAC).
The currently programmed curve roughly follows this formula.
y = -0.0333(x)^4 + 0.2757(x)^3 - 0.468(x)^2 + 0.605(x)
Where x is the input voltage, and y is the output voltage. It looks like this.

Throttle Connection:
Arduino Side <> Throttle Side:
5V<>Throttle Positive
GND<>Throttle Ground
A0<> 0-5v Throttle Signal
MCP4725 DAC:
Arduino Side <> MCP4725 DAC Side
GND<>GND
5v<> VCC
A4<>SDA
A5<>SCL
THe MCP4725 OUT and GND will go to your controller.
How it works:
The Arduino A0 Pin is an analog to digital input, it can sense voltages 0-5v at 10 bit resolution, this means that it has available to it 1024 'steps' that represent 0.0049v each. The Arduino via the MCP library converts these steps into integers (numbers that range from 0-1023).
The MCP4725 has 12 bits of resolution, or 4096 steps of resolution, represented by integers 0-4095 @ 0.0012v per unit.
I used Excel to calculate the input/output for all 1024 possibilities of input, then found the closest integer that matches with 4096 scale. If you want to make your own curve, you'll need to plot some points and have Excel graph the trendline, give you the formula and you recalculate the appropriate output integers.
The Arduino can do this VERY quickly, there's no perceptible latency between input/output changes. However, I haven't measured what this latency actually is.
Future possibilities:
Throttle Smoothing
Minimum throttle movement to cause an output change
Feedback loop with other sensors (traction control module? Tip-over cut off, etc.)
NOTE:
Hall type throttles will output ~0.85v - ~4.3v with 5v input. A pot can get you closer to the full voltage range, so keep this in mind that your effective curve will be different between pot/hall throttles and what range of the curve you're subject to.
Code:
/**************************************************************************/
/*!
Program takes in 0-5v linear input from Hall or Potentiometer throttle.
Output is 0-5v non-linear according to function:
y = -0.0333(x)^4 + 0.2757(x)^3 - 0.468(x)^2 + 0.605(x)
AnalogRead() has 10 bits of resolution, 0-1023 int, .0049v per unit @5v
dac.SetVoltage has 12 bits of resolution, 0-4095 int, .0012 per unit @5v
*/
/**************************************************************************/
#include <Wire.h>
#include <Adafruit_MCP4725.h>
Adafruit_MCP4725 dac;
int throttleInPin = A0;
int voltInInt = 0;
const int voltOutIntLUT[] PROGMEM = {0,3,5,8,10,13,15,17,20,22,24,27,29,31,33,36,38,40,42,44,46,48,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,80,82,84,86,88,90,91,93,95,97,99,100,102,104,106,107,109,111,112,114,116,117,119,121,122,124,125,127,129,130,132,133,135,136,138,139,141,142,144,145,147,148,150,151,153,154,156,157,159,160,161,163,164,166,167,168,170,171,172,174,175,177,178,179,181,182,183,185,186,187,189,190,191,192,194,195,196,198,199,200,202,203,204,205,207,208,209,210,212,213,214,216,217,218,219,221,222,223,224,226,227,228,229,231,232,233,234,236,237,238,240,241,242,243,245,246,247,248,250,251,252,254,255,256,257,259,260,261,263,264,265,266,268,269,270,272,273,274,276,277,278,280,281,282,284,285,286,288,289,291,292,293,295,296,298,299,300,302,303,305,306,307,309,310,312,313,315,316,318,319,321,322,324,325,327,328,330,331,333,334,336,338,339,341,342,344,346,347,349,350,352,354,355,357,359,360,362,364,365,367,369,371,372,374,376,378,379,381,383,385,387,389,390,392,394,396,398,400,402,404,405,407,409,411,413,415,417,419,421,423,425,427,429,431,433,435,438,440,442,444,446,448,450,452,455,457,459,461,464,466,468,470,473,475,477,479,482,484,486,489,491,494,496,498,501,503,506,508,511,513,516,518,521,523,526,528,531,533,536,539,541,544,547,549,552,555,557,560,563,566,568,571,574,577,580,582,585,588,591,594,597,600,603,606,609,612,615,618,621,624,627,630,633,636,639,642,645,648,652,655,658,661,664,668,671,674,677,681,684,687,691,694,697,701,704,708,711,715,718,722,725,729,732,736,739,743,746,750,753,757,761,764,768,772,775,779,783,787,790,794,798,802,806,810,813,817,821,825,829,833,837,841,845,849,853,857,861,865,869,873,877,881,886,890,894,898,902,906,911,915,919,923,928,932,936,941,945,949,954,958,963,967,972,976,980,985,989,994,999,1003,1008,1012,1017,1021,1026,1031,1035,1040,1045,1050,1054,1059,1064,1069,1073,1078,1083,1088,1093,1097,1102,1107,1112,1117,1122,1127,1132,1137,1142,1147,1152,1157,1162,1167,1172,1177,1182,1188,1193,1198,1203,1208,1213,1219,1224,1229,1234,1240,1245,1250,1256,1261,1266,1272,1277,1282,1288,1293,1299,1304,1310,1315,1321,1326,1332,1337,1343,1348,1354,1359,1365,1371,1376,1382,1388,1393,1399,1405,1410,1416,1422,1428,1433,1439,1445,1451,1457,1462,1468,1474,1480,1486,1492,1498,1504,1510,1515,1521,1527,1533,1539,1545,1551,1557,1564,1570,1576,1582,1588,1594,1600,1606,1612,1619,1625,1631,1637,1643,1650,1656,1662,1668,1674,1681,1687,1693,1700,1706,1712,1719,1725,1731,1738,1744,1751,1757,1763,1770,1776,1783,1789,1796,1802,1809,1815,1822,1828,1835,1841,1848,1854,1861,1867,1874,1881,1887,1894,1901,1907,1914,1920,1927,1934,1940,1947,1954,1961,1967,1974,1981,1987,1994,2001,2008,2015,2021,2028,2035,2042,2049,2055,2062,2069,2076,2083,2090,2096,2103,2110,2117,2124,2131,2138,2145,2152,2158,2165,2172,2179,2186,2193,2200,2207,2214,2221,2228,2235,2242,2249,2256,2263,2270,2277,2284,2291,2298,2305,2312,2319,2326,2333,2340,2348,2355,2362,2369,2376,2383,2390,2397,2404,2411,2418,2425,2433,2440,2447,2454,2461,2468,2475,2482,2489,2497,2504,2511,2518,2525,2532,2539,2546,2554,2561,2568,2575,2582,2589,2596,2604,2611,2618,2625,2632,2639,2646,2653,2661,2668,2675,2682,2689,2696,2703,2711,2718,2725,2732,2739,2746,2753,2760,2768,2775,2782,2789,2796,2803,2810,2817,2824,2831,2838,2846,2853,2860,2867,2874,2881,2888,2895,2902,2909,2916,2923,2930,2937,2944,2951,2958,2965,2972,2979,2986,2993,3000,3007,3014,3021,3028,3035,3042,3049,3056,3063,3069,3076,3083,3090,3097,3104,3111,3118,3124,3131,3138,3145,3152,3158,3165,3172,3179,3185,3192,3199,3206,3212,3219,3226,3232,3239,3246,3252,3259,3266,3272,3279,3285,3292,3298,3305,3312,3318,3325,3331,3338,3344,3350,3357,3363,3370,3376,3383,3389,3395,3402,3408,3414,3420,3427,3433,3439,3445,3452,3458,3464,3470,3476,3483,3489,3495,3501,3507,3513,3519,3525,3531,3537,3543,3549,3555,3561,3566,3572,3578,3584,3590,3596,3601,3607,3613,3618,3624,3630,3635,3641,3647,3652,3658,3663,3669,3674,3680,3685,3691,3696,3701,3707,3712,3717,3723,3728,3733,3738,3743,3749,3754,3759,3764,3769,3774,3779,3784,3789,3794,3799,3804,3808,3813,3818,3823,3828,3832,3837,3842,3846,3851,3855,3860,3864,3869,3873,3878,3882,3886,3891,3895,3899,3904,3908,3912,3916,3920,3924,3928,3932,3936,3940,3944,3948,3952,3956,3960,3963,3967,3971,3974,3978,3982,3985,3989,3992,3996,3999,4002,4006,4009,4012,4015,4019,4022,4025,4028,4031,4034,4037,4040,4043,4046,4049,4051,4054,4057,4059,4062,4065,4067,4070,4072,4074,4077,4079,4081,4084,4086,4088,4090,4092,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094,4094};
int voltOutInt = 0;
void setup(void) {
Serial.begin(19200); //test code
pinMode(throttleInPin,INPUT);
dac.begin(0x60); // *You'll need to update this to the I2C address for your MCP*
}
void loop(void) {
voltInInt = analogRead(throttleInPin);
voltOutInt = pgm_read_word(&voltOutIntLUT[voltInInt]);
dac.setVoltage(voltOutInt,false);
Serial.print("Vin: "); //test code
Serial.print(0.0049 * voltInInt); //test code
Serial.print(","); //test code
Serial.print ("Vout is: "); //test code
Serial.println (.0012 * voltOutInt); //test code
delay (1); //test code
}