Throttle body control / air mixture / Drive by wire DIY

I looked for them, but could not find a suitable throttle with cable… :grin:
but i always can put a cable on the knob for the adjustment :grin:

Wayne, its actually after seen your AFR jumpin around that i decided to build this automation :wink:

Anyhow, i needed it anyway for my project, so why not share it here :stuck_out_tongue:

3 Likes

Hi Michael,

Yup, the auto adjustment at stop and go, the startup
Once this is made easier, more people will switch over or start to build.
If they see that there is a solution for some technical/mental hurdle…

I try to use these hurdle’s as a step stone, not a stumble stone…

3 Likes

Hello Koen .

Hey I’m all for it ! I have had one of those throttle bodes for several years but I didn’t know electronics enough to get it going. ( electronic challenged )

Thanks for showing the process .:relaxed:

3 Likes

Don, Kevin, Michael,

Don’t worry, if i can do, you can do it :grin:

2 Likes

How are you homing the stepper motor?

I have some new code Ill post in case you are interested modifying it. Its more responsive and reacts faster or slower according to how far out of the AFR parameters. This code uses a switch to go from manual pot switch adjust to automatic. Might be easy for you to adapt stepper code in place of the servo code.

There is another version of this that runs from I2C and the servo can be ran via a slider GUI widget or you can simply push full auto mode and it fires up the engine automatically; then it switches into auto adjust mode by itself. There is another control module that goes with it and you can run the entire machine in semi automatic or full auto. Between the two controller running over I2C and the GUI in full Auto mode the controller will take the machine from cold start up, switch all valving and fire the machine off. It can light the flare tube on its own and then go into engine run once it sees temp parameters are met. It also has a fail safe if the reactor temp fall below operating temperature it will shut down on its own. Yeah this is why Im so quiet ive been writing software for a solid four weeks :fire:

Edit: Ok Chris I give up it wont cooperate today haha.

#include <Servo.h>
Servo myservo; 
// create servo object to control a servo
//VG 02 Wide Band Mixture Controller V1.3
//Craeted by Matt Ryder, Vulcan Gasifier LLC May 5, 2015
//Prior edit; June 22, 2015 
//Change log
//April 30,2017 - Todd Harpster
// added contraint to calculated delays after mapping to keep them in range
// read the O2 sensor just once per loop
// add table of expected delays based upon O2 sensor value
//April 30, 2017 - Todd Harpster
// v2 control loop
// refactored code to use mode variable and switch statement to

// This code requires an AEM O2 sensor kit with LSU 4.9 sensor Part # 30-4110

// These constants won't change:
const int O2SensePin = A1; // pin that the O2 sensor is attached to
const int O2SwtPin = A2; //Pin Auto Mode Switch is attached to
const int O2ManPin = A0; // Reads the O2 Manual Adjust Potentiometer on pin A1

// constants for our mode values
const int Mode_Override = 1;
const int Mode_Rich = 2;
const int Mode_Stoichiometric = 3;
const int Mode_Lean = 4;

//tunable parameters below
const int RichCon1 = 700; // Threshold limit for Rich gas condition
const int LeanCon1 = 900; //Threshold limit for lean gas condition
//
const int MinTuningServoPosition = 10; // never fully close the valve in O2 loop mode
const int MaxTuningServoPosition = 180; // wide open

int mode = 0; // loop operating mode
int pos = 0; // variable to store the servo position
int val; // variable to read the value from the analog pin 
int lastpos = val; // variable to store the servo last position
int O2SwitchState = 0; // variable for reading the Fuel Mixer Mode status

void setup() 
{ 
myservo.attach(13); // attaches the servo on pin 9 to the servo object

// Need to create a set point for servo start position after manual tuning
{
val = analogRead(O2ManPin); // reads the value of the potentiometer (value between 0 and 1023) 
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180) 
myservo.write(val); // sets the servo position according to the scaled value 
lastpos = val; // sets lastpos to equal the position of the manually set position
delay(10); // waits for the servo to get there 
}
}

// 
// O2 Sensor Reading Delay
// ================= ====================
// Manual 10
// Rich 0 - 700 variable 500 - 800
// Stoichi 701-899 500
// Lean 900 - 1023 variable 800 - 450 
//

void loop() 
{
// read the state of the pushbutton value:
O2SwitchState = digitalRead(O2SwtPin);
// read the value of the O2 sensor:
//Todd - read the O2 sensor once for this loop and store in sensorReading
int sensorReading = analogRead(O2SensePin);

//variable to hold mode for this time through the loop
int mode = Mode_Stoichiometric; // assume O2 reading is not too rich or not too lean, just right
int delayms = 500; // 500 ms delay as a default value - it case it doesn't get changed below

if (O2SwitchState == LOW) {
mode = Mode_Override;
} else {
if ( sensorReading <= RichCon1 ) {
mode = Mode_Rich;
}
if (sensorReading >= LeanCon1 ) {
mode = Mode_Lean;
}
}

switch (mode) {
case Mode_Override:
val = analogRead(O2ManPin); // reads the value of the potentiometer (value between 0 and 1023) 
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180) 
myservo.write(val); // sets the servo position according to the scaled value 
lastpos = val; // sets lastpos to equal the position of the manually set position
delayms = 10; // waits for the servo to get there 
break;
      
    case Mode_Rich:
      // move the air mixture servo to lean out by adding air
      lastpos = constrain(lastpos+1, MinTuningServoPosition, MaxTuningServoPosition);  // add 1 but make sure it stays in range
      myservo.write (lastpos);                          // tell the servo where to go
      val = map(sensorReading, 0, RichCon1, 100, 400);  // Richer mixtures get shorter delay
      val = constrain( val, 100, 400);                  // Keep values between 100 and 400 ms
      delayms = val + 400;                              // increase delay so minimum is 500 ms - max is 800 ms
      break;
      
    case Mode_Stoichiometric:
      delayms = 500;                                    // no need to move servo set delay to check back in 500 ms
      break;
      
    case Mode_Lean:    
      // move the air mixture servo to decrease air to make richer
      lastpos = constrain(lastpos-1, MinTuningServoPosition, MaxTuningServoPosition);  // subtract 1 but make sure it stays in range
      myservo.write (lastpos);                            // tell the servo where to go
      val = map(sensorReading, 1023, LeanCon1, 450, 800); // the leaner the mixture the shorter the delay - need to adjust quickly
      val = constrain(val, 450, 800);                     // keep the delay between 450 and 800 ms
      delayms = val;
      break;
      
    otherwise:
      //this shouldn't happen
      break;
  }
  
  //wait for a little bit before doing this again
  delay(constrain(delayms,250,1250));                 // use contrain to be completely sure delay value is reasonable
}
3 Likes

Hi Matt,

Yep, your’s is servo, mine is stepper or PWM (i have both, different throttle body’s )

The automation/positioning, in my case, can be done with either return to manual defined spring ( position adjustable with a “wrench” ) or, more advanced , with a potentiometer allowing adjusting the AFR as desired from the cabin.

In shown case above, Stepper motor, the Analog 0 in, reads the voltage, 0-5V , from the Potentiometer.
The stepper follows according the voltage, the power from the stepper only set slightly higher then the return spring power in the throttle body. In the program i can modify the lenght off way for the stepper, the reaction time, the speed, and also the treshold to ignore low fluctuations.

If we determine the perfect AFR at position X, locking that mechanicaly with 2 springs ( mechanical zero )
Then the voltage from the AFR meter set ( 0-5V) will send the mixture valve in either direction as needed.
( to be build and tested before actual showing of )

If i compare with 2 analog reads , 1 from potentiometer, and another from AFR value
i can steer the Mixture valve according the Potentiometer setting.

The PWM set would be on the same basics, working on that now.

I hope to be able to split this topic into different builds/subtopics ,so things stay clear.

I will try your setup as a studycase for my learning, if i find something i will let you know.

Edit:
Picture with the output voltages from the AFR set i use

1 Like

Thats pretty cool, what i have found is 650 bytes to around 750 bytes is about write for wood gas. this is slightly leaner than the engine running on gasoline.

Ever tried a EGT readout at the same time as powerincrease and mixture control ?
I am working on that now to

Ive generally purchased the AEM kits and use the DRO on the gage. However, since Im running an Rpi with 7" touch screen those expensive kits will probably be going away and Ill map the sensor read out 0 - 18 and send over I2C to the display. It will have most engine vitals displayed this way as well. Oil pres, temp, alt/ batt voltage etc.

Id send some updated pics but really need to clean up the wireing first. looks like a rats nest right now. I will be installing shielded wire here soon as I wrap this thing up and clean all that up.

2 Likes

Hey Willus!!! Whacu talkn bout???

5 Likes

Thank you Koen and Matt.
Koen, since you have been dealing with both servos and steppers, do you feel that one type of butterfly driver is better suited to your task than the other?
I assume that you need to have (full?) power constantly applied to the stepper motor. Has this caused any heating or overheating problems so far?
And, to both of you:
Have you considered removing all of the return springs?

Pete Stanaitis

No I do not load the servos and make the valves as free as posible. No need for spring in my application. However, Im not controlling throttle position yet and that I may consider some sort of fail safe, I think Koen is on the right track of using the stepper motors but they are harder to control.

Hi Pete,

I deal with 3 kinds of actuators:
1: servo
2: stepper
3: DC motor drive with PWM

In the first video , in this topic, you’l see the DC motor drive with PWM ( throttle body Toyota 2JZ engine )
It contains a DC brushed motor where as the rotor coils work against the spring tension, the PWM regulates the coil power against the throttle spring.
As long you can use a balanced system, the heat is neglectable/normal range

In my next video above, you see the stepper motor with arduino ( Traction control Toyota )
I reduced the spring tension to be able to work with less current. Now pulling 250 mili amps on holding and 450 mili to step.
The coils in the stepper stator windings act as a electromagnets to either hold or flip the magnetic fields from the rotor.
if no electric is applied, the rotor can run free…

I focused on the 2 systems because i have them and they are standard in automotive.
The Servo’s i think is in good hands already with Matt, strange but i was thinking they where more difficult to handle :wink:

Maybe things can be done without the return springs, but i keep them for the moment to build with more ease / less electronics.
If no electric is applied, it returns to zero position, which can be a manual set fail safe / limp mode

3 Likes

Thanks, guys.
I have been working with one of the guys in our arduino group on a system to automatically detect turning on of any power tools in his wood shop “un-invasively”, turning on the dust collector, and then selecting the correct blast gate. He is using stepper motors to drive the blast gates. It was interesting to hear what he had to do to get the stepper to stop at the correct location without over-running. He also learned that (as Koen mentioned) that he could solve his (over)heating problems by significantly reducing power to the stepper once it got into its holding position.
(I was only doing the sensing part. I found some cheap, tiny CT’s (Current Transformers) that worked really well.)

Pete Stanaitis

2 Likes

The biggest issue I had with Stepper motors was trying to figure out how to home them and creating limits so they could not exceed wide open position or fully closed. Where as a servo is position oriented code, you basically tell it to write to a position any where from 0 to 180. If you want it to move on its own you tell it to add or subtract +1 / -1 to a “lastpos” variable and it will keep doing this over and over until it reaches 0 or 180 or you tell it to do something else. You can easily control its speed with delay and what I do to create speed ramping is map the delay to sensor input with a parameter set. So if my sensor reads 0 -1023 but in one situation “rich” parameter; meaning anything at 600 or below is out of the happy zone and we are running rich. I can map a delay to that parameter (0 to 600). So for instance the sensor reads 575 I can map the delay so it has a larger delay here. However, if the sensor reading goes way out of parameter say 150 the delay becomes much shorter and the servo waits less time between each movement pr position. So this map delay would look something like this;

//
if ( parameter < 600);
servo.write (lastpos +1); // here we need to add delay to ad time delay between each degree movement
val = map(sensorReading, 0, 600 , 100, 400);//Here we map 0 to 600 parameter to a number range
// to create a “val” we will reference in the delay function
delay(val); // So here we tell the code delay in between movements to our “val” variable created above

All the PWM does to move a servo is create a digital code for the servo to read. All the rest is done via the servos internal electronics. The limits are already set within the servo so nothing needs to be done there in code.

The stepper motors I had an additional issue with trying to get them to be slow enough as well. With air metering this is tricky and if movements are too fast its easy to overshoot. However, controlling a throttle position and having the spring return for a fail safe, the stepper motor I think is the way to go and the ramp speeds I think would be plenty slow enough for that application. The steppers should also be able to handle heat much better than your typical hobby servo. For homing you could install limit switches to break into the circuit but that adds some additional work and cost if this is required.

I have not done a whole lot with steppers so I do have more to learn. I some valves that the stepper motor maybe a better solution for those valves. They are just open or closed.

2 Likes

On the automotive and industrial stepper motor “position stop” drives that I have operated; once the system was un-powered - and memory lost; the operator has to intentionally drive it to limits for it to re-learn re-self-program the limits.
Later in maintenance I learned that the processor controller were actually pulse counting. Counting pulses OUT driven for intent. Counting back pulses sensed as achieved. And using current-up sensing for limits setting. Child/arm in power window stopping is done this way. Now with even auto reversing.
May seem super high-tech, but how virtually all power window, power sunroofs, power sliding doors have been done for nearly 15 years now. Most often this processor is built into the actual doors mounted switches assemblies.
Another possible durable engineered reperposable part.
Regards
Steve unruh

2 Likes

I have found 30 of these in my scrapyard warehouse… they have Steppermotors… :grin:

5 Likes

They probably have the matched controller boards too. Which get pretty expensive for something that size. That is a great find!!

If you find rails for them, you can probably make a farmbot.

1 Like