Arduino Manager Development for All

I didn’t think about that until just now. You need it to at least develop the software or double check that what’s in that git repo actually works. It probably isn’t a linear scale and i doubt anyone has a spec sheet for it.

The code is using a lookup table to determine whether it is lean or rich.
Based on the analog amp reading from the sensor as defined:
https://www.google.com/url?sa=t&source=web&rct=j&opi=89978449&url=https://www.bosch-motorsport.com/content/downloads/Raceparts/Resources/pdf/Data%20sheet_69034379_Lambda_Sensor_LSU_4.9.pdf&ved=2ahUKEwiyqYTuu8iGAxUqkokEHcTsHtwQFnoECCUQAQ&usg=AOvVaw2tXBwxyM8Tnj4Aq-BMG8RK

This also explains a bunch of the code… And i see why Matt’s head was spinning

3 Likes

I was trying to read this topic in order. Im still back on post 50… but i kept seeing new posts pop up so i jumped to the end, glad i did. All relevent info for what i need to do.
Ill have to go back and finish reading but at least now im in the loop and will save me from asking a question over on my topic that was already covered here.

6 Likes

Cody, the throttle bodies im using are out of early 2000 honda civics. I went back and looked, i thought i had pictures of the wiring harness on them but didnt see it at a quick glance. They have a 6 pin connector on them.
12- motor
12+ motor
Feedback pot A
Feedback pot B
5v+ pot
5v- pot

The motor itself is just that, 12 volt motor designed to overcome the spring return.

The way i understand it, the car uses both feedback potentiometers as redundant “feedback signals” to control the throttle body.

I am driving the TB motor with an H bridge motor driver and only using one of the feedback pots to refrence what position the valve is in.

This H bridge is a L298N, they are 2 channel/2 amps. They are a bit smaller than i would like, but have been working fine so far. I’m just carful how hard i push them in the programing and also run a cooling fan on them.

Because of the feedback pot there is no need to calibrate you always know where they are.

So not as easy/clean as using servo code. But i can accomplish the same results. I just code the throttle body to always search out and stay at target value of the feedback pot. Then mapped out the feedback pot value to a percentage value. So i simply request a specific percentage (Target value) and TB responds by opening to that value.

If i were to remove the springs in the TB they would move much more freely(no resistance). This would help the H bridges to not have to work(draw) so hard. But i never took the time to figure out if i could disasemble the TBs in order to remove the spring. (Probably because I’m lazy)
I did see the value of the TB defaulting to closed…at least on the woodgas valves…maybe not so much the air valves. (Thinking in terms of a system failure and needing to bypass to run on dino fuel. For as it stands now. When i turn the key my air valves both open fully to drive on dino, if i ever had a system failure i could not drive home on dino fuel unless i removed the TB or forced them open with something.)

6 Likes

Nice system! I can’t tell from the photo, is the motor a brush motor with a belt or gear train, or an electromagnetic thing like a voice coil or hard drive actuator?

2 Likes

I wish i would have taken a picture of the TB when i had it opend up. The motor spins a gear or two to drive the flapper. It can produce a fair bit of torque.

Not positive on motor type as i didnt disassemble it that far.

I am driving the L298N with a PWM signal. There is an enable pin and two directional input pins per channel to determin direction. Typicly the TB are pulling anywhere from .8-1.3-5 amps depending… if i where to try and force the flapper out of position the will draw quite a bit more power and in time damage the H-bridge due to heat. They can get very warm. I am running a cooling fan on them as well.

4 Likes

Don’t remove the sprint. I believe it is a safety feature so the power is removed vehicle shuts off by itself, and I think that is why there is also a second encoder. if one malfunctions there is another.

And honestly, I am not sure what the difference is between a servo motor and a dc motor with a position feedback sensor.

3 Likes

I concur.
In my research i did come across that info regarding the redundant sensors and spring return being an added safety measures for the throttle by wire systems.

The reasoning for me not using second feedback sensor was I didnt want to burn up another four inputs on my controller. (Nore do i remember if i even had them to spare)

I also agree spring return makes sense for the main throttle body on a vehicle. In my case that is the stock throttle body on the 318.

These TBs are strictly for getting the correct mixture and have nothing to do with causing a runaway sinario.
In that case removing the springs will allow you to drive the motors on the TB with less resistance therfore drawing less amps threw the motor drivers. i.e. less heat to dissipate.

3 Likes

Correct me if I’m wrong but i would say thats all a servo is, is a motor w/gear reduction with feedback sensor… it just has the circuitry built in so you can control it with pwm.

Where as a motor and feedback sensor independently needs a microcontroller to add that functionality.

6 Likes

The redundancy in the sensors, is because the sensors can go bad. The motor can also go bad, or loose broken wiring. The second reason for the spring, is that it zero’s it at close. But you really don’t want to have it go bad and have it freely swinging around in rush hour traffic. Honestly, it is probably all required by law because of previous accidents.

Ahh that is right, the pwm signal speed controls the direction and position. :slight_smile:

you could look at a BTS7960 and you will probably want a heatsink on that as well, but it handles more current then the l298, and honestly you just need a mosfet that is optocoupled because you are sending the pwm signal. And optocoupling just means it is optically isolated so you aren’t getting current sent back through the signal pin and blow up your controller.

This is overkill because it will handle 4 channels/servos, and you still may need a heatsink on the mosfet. I really didn’t look that hard, just an example.
https://www.amazon.com/3-7-27VDC-4-Channel-Driver-Amplifier-Circuit/dp/B07QGXY7F3/ref=asc_df_B07QGXY7F3/

3 Likes

Good point about the optocouplers. That added layer of protection would be beneficial.

1 Like

I’m no programer and deffinatly not an electrical engineer, everything i accomplish has to be researched, studied, tried and tested, then correct all the bugs that i mistakenly input into the code… but thats how i learn as well. My code isnt pretty, loaded with comments and notes so i can remember my thought process at the time.
I also learn my asking dumb questions. And am not afraid to be corrected… so i appreciate being able to discuss and be part of the conversations on this forum.

/
/
/
/
/
Sean, the 4 channel amp you posted would be good for switching high load circuits on and off. ( actually i could see myself using it for my bilge blowers and such, i hardwired mine up in a three way fashion. So i can turn them on from inside the cab or from the flat bed. But i dont have any indicators to let me know if they are on or off in the cab, only in the flat bed. Yesterday i didnt relize i left one on, couldnt hear it over the engine noise. It would be better to have momentary buttons in both locations with feedback lights. Or even better soft buttons on a touchscreen in the cab, that way i could reconfigure without any phisical change.)

Wouldn’t it take all 4 mosfets to create a true H bridge in order to control a forward/reversing motor or TB like the ones im using.
In that case probably best to use the BTS7960 you suggested for each TB… unless thinking sidways you where thinking of using the 4 channel mosfet board because you only intended in driving the TB one way and relying on the spring tention to do the reversing rotation.( i believe i contemplated this but decided against if for reasons i know cant remember. Maybe because the flapper moved faster when it had more spring tension and slower closer to the closed position…:man_shrugging:)

Sorry, rambling then my self diagnosed ADHD kicks in and i start going sideways.

8 Likes

You need 4 mosfets to create a H-bridge, yes. If that is a servo motor, you only need one mosfet. There is a control pin that takes a pwm signal. you vary the lengths to control the position as described like this:

They have two servos with a position sensor, one is basically a potentiometer, but the wipers on them deteriorate over time. The other has a magnetic disk which doesn’t deteriorate. I would guess the one you have has the pots as those can go bad. And you can over rotate it and break it.

For a DC motor, you need the h-bridge to reverse the current, and you pwm for speed control.

instead of the 4 channel, you can buy them on individual boards. Something kind of like this:
https://www.aliexpress.us/item/3256806775128980.html?

make sure the trigger voltage works with what you are using as a controller.

IF you just need pwm, you can do the ‘analog’ 555 chip and a potentiometer. There are all sorts of circuit examples and online calculators to get you in the ballpark. But microcontrollers are almost as cheap and easier to add stuff.

they make a DPST relay that you can trigger with a microcontroller which is the same a 3 way switch. But the soft push buttons, you would more likely just use the mosfet or a relay and a low voltage wire to the buttons read them on the controller and control the mosfet. And you could program it to time out after x amount of time if it hasn’t been turned off with a button. The only advantage of the mosfet in this case would be speed control, and maybe cost. :slight_smile:

4 Likes

Okay @Matt , I’ve got everything put together sans O2 sensor but I’m using another 10k pot to simulate it.

The code uploaded to the board successfully but when I turn it on the servo doesn’t move no matter which pot I turn or activate the manual.

1 Like

By default it will be in manual mode. So the manual pot pin should move the servo. Could have a bad pot, bad servo, need to check wiring.

Also note you may need to add a pull down resistor the manual mode input pin. Also all grounds must be grounded together. If you have seperate power supply for the servo and it does not have a shared ground with the controller; nothing will work.

4 Likes

Also note, when you put it into automix mode. The servo is not going to zip one way or the other, even when its responding fast, it will still look very slow. You dont want or need this to be that fast these parameters dont change abruptly, they change over time as gasifier changes. The engine or the load has zero effect on AFR. Once the AFR is set to a static gas energy density thats it. If you pull a load this mixture is not going to change. The engine is not going to pull in more gas than oxygen or vice versa its going to pull evenenly on both. You want your gas input as far open as your system will allow and then match an air valve ( roughly 75%) of the gas hose. This will give you good resolution 50% will get you more resolution but may limit you as it can only open so far. But the idea is you want to use the full range of the air mixer valve not just just a small window of the valve. For instance if the valve is sitting at around 30% open the magority of the time, then you may want to step that down to a smaller valve to get better resolution. Meaning you can move a lot farther in ajdustment without things suddenly going south.

2 Likes

Cody, when trouble shooting, working out errors in code/ hardware/wireing (in this case we know code is good) you can use

Serial.print() or Serial.println() functions: ( this has to be enabled in the setup loop…this may alread have been in matts code, i still havent dove into it yet)

As long as ur computer is still hooked up you can tell microcontroller to print values of specific veriables to the serial bus.

This is very useful, you could easily see what values your controler is seeing from, say, your 10k pots. Easily confirming if they are good or bad.

1 Like

This is the latest and gratest. I dont know when the lasttime Ive copied the code here. But I know this code works as its the code in our manufacturing folder and we have built and tested this code last year.

#include <Servo.h> 
Servo AFR_Servo;  // create servo object to control a servo 


//VG 02 Wide Band Mixture Controller V1.3
//Craeted by Matt Ryder, Vulcan Gasifier LLC / Thrive Energy Systems May 5, 2015
//website; https://www.thriveoffgrid.net/
 //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 = A4;    // pin that the O2 sensor is attached to
const int ModePin = A2;   //Pin Auto Mode Switch is attached to
const int AFR_ManPin = A3; // Reads the O2 Manual Adjust Potentiometer on pin A1
const int ModeLED = 02; // Output pin to uliminate Mode button LED Status

// 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 = 525; // Threshold limit for Rich gas condition
const int LeanCon1 = 625; //Threshold limit for lean gas condition
//
const int MinTuningServoPosition = 40;  // never fully close the valve in O2 loop mode
const int MaxTuningServoPosition = 140; // 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 ModeStatus = 0;    // variable for reading the Fuel Mixer Mode status

void setup() 
{ 
  //analogReference(INTERNAL);
  AFR_Servo.attach(06);     // attaches the servo on pin 9 to the servo object 
  pinMode(ModeLED, OUTPUT);  //ModeLED Status assinged as ouput pin

  Serial.begin(9600);
    
  // Need to create a set point for servo start position after manual tuning
  {
    val = analogRead(AFR_ManPin);  // reads the value of the potentiometer (value between 0 and 1023) 
    val = map(val, 0, 1023, 40, 140);     // scale it to use it with the servo (value between 0 and 180) 
    AFR_Servo.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:
  //ModeStatus = digitalRead(ModePin);
  // read the value of the O2 sensor:
 //Todd - read the O2 sensor once for this loop and store in sensorReading
  int sensorReading = analogRead(O2SensePin);
  int ModePin = digitalRead(A2);




  //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 (ModePin == HIGH) {
    ModeStatus = ModeStatus +1;
    Serial.println(ModeStatus);
    delay(100);
 } else { 
    if ( ModeStatus >= 2) {
       ModeStatus = 0;
       Serial.println(ModeStatus);    
       delay(100);    
    }     
   }

  if (ModeStatus == 0) {
    mode = Mode_Override;
    digitalWrite(ModeLED, LOW);
  } else {      
    if ( sensorReading <= RichCon1 ) {
      mode = Mode_Rich;
      digitalWrite(ModeLED, HIGH);
    }
    if (sensorReading >= LeanCon1 ) {
       mode = Mode_Lean;
       digitalWrite(ModeLED, HIGH);     

    }
  }

  switch (mode) {
    case Mode_Override:
      val = analogRead(AFR_ManPin);           // reads the value of the potentiometer (value between 0 and 1023)
      val = map(val, 0, 1023, 45, 135);      // scale it to use it with the servo (value between 0 and 180) 
  AFR_Servo.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
  AFR_Servo.write (lastpos);                          // tell the servo where to go
  val = map(sensorReading, 0, RichCon1, 50, 300);  // Richer mixtures get shorter delay
  val = constrain( val, 50, 300);                  // Keep values between 100 and 400 ms
  delayms = val + 300;                              // increase delay so minimum is 500 ms - max is 800 ms
  break;
  
case Mode_Stoichiometric:
  delayms = 2000;                                    // 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
  AFR_Servo.write (lastpos);                            // tell the servo where to go
  val = map(sensorReading, 1023, LeanCon1, 650, 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 + 500;
  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
}
1 Like

If anyone knows of a particular throttle body (vehicle make and modle) that have servos in them instead of motors and only require pwm signals i would be interested.
That would make my future mixing valves a lot simpler and require less hardware.

1 Like

Ok, yep i see the
Serial.begin(9600) in the setup loop

1 Like

Okay this is odd. I have it wired exactly as the tutorial says. It works with the old code, but does not with the last two latest versions. I’m just testing it on the bench so everything is sharing a ground, etc etc.

2 Likes