Arduino Manager Development for All

Oh trust me I get it, that is why I said, if you can find it. Rato’s are chinese and assembled in the US, but that is all I know about them. I don’t know if they are as good as the honda clones.

1 Like

The biggest predator HF sells is 22hp, or 8 hp less then the 30hp kohler. What size do you have?

1 Like

This current system only has a 16 hp Vanguard, the 22 hp HF motor should make the 5 kW. However, on the ES systems these are DC inverter so we need more to cover power conversions. So we used the 30 hp engine just to make sure we had enough power. I still plan to use this on next generation systems, this is an excellent engine. Even though we could possibly get away with a smaller engine. But if in doubt over engineer it :fire:

Ive been looking over that code, It looks like he has a “running average” code I will need to add to my library. So here is a silly question…how does one add to their arduino library?

Also it looks like I will need to create code to control the sensors heater.

Edit: I found some info to do this

It warms up the sensor and polls the nernst cell in the sensor for you. The circuit from the schematic and the program with the arduino actually replaces a controller chip which you actually need in addition to the sensor. It is similar to the 4.2 sensor in that respect.

import library directions:
http://www.arduino.cc/en/guide/libraries

You need to import the pid() and the avg() libraries.

It might need some tweaking to get around the ifdefs if you don’t have an uno, I’m not super familiar with preprocessor directive values in sketch.

Ok I have the libraries loaded up :fire:

I did a bunch of research on the 02 sensors and it looks like I can eliminate the heater portion of the sensor and just use the engine heat for this. I will still want to use the 4 wire as this will have the broadest range. This supplies voltage for the signal and also has a ground wire vs using the body of the sensor. To eliminate the heater I just have to omit the ground wire for this. This will simplify the code and really isn’t all that important.

The heater is important for the reference cell, which is what the calculations are based on. The older sensors didn’t use a heater. but they are also narrowband sensors. I know it will affect accuracy, I don’t know by how much.

I dont think you have to even touch the code. minus get the right io pins. I haven’t looked at it in that much detail, but it seemed fairly straightforward. What are you having issues with?

This four wire Im going to use is a narrow band, the heater on this is just for start up. Once the engine is started and its warmed up, its no longer needed. (I think)

The input on the narrow band sensors is 0-1.1v with an operating range of 0.2v to 0.7. If I map this do you think it will work?

Well Ive had another revelation today, working on a different machine. I loaded up the program and on this machine I have the input wires backwards. So I took the opportunity to play with this using the pot in place of the sensor input. Low and behold the delay is still there. So I guess the sensor input is not as slow I thought.

So back to programing!!!

Im playing with a case switch program now that is more responsive to the directional changing. Ive played with this before but had a hard time getting other parts of it to work. But Ive learned quite a bit and now know what I was missing or doing wrong. Ill keep you posted

1 Like

Probably not super well. map() is linear… You probably want a lookup table like in the 4.9 sensor code.

I thought they had to run the whole time, and possibly they run on pulses like the 4.2 and 4.9 widebands do.

the case statement isn’t going to speed it up. plus it is a lot harder to roll through 1024 values, since you can’t do ranges.

the map function itself, might actually be causing the slowdown if you think it is programmatic

yeah im not sure on the heater on the narrow band sensors. From what I have read this is so these sensors can come on line very quick from a cold engine start up. The old single wire sensors had to heat up first before the ECM would use input from them. So during warm the runs in a open loop mode using other sensors to run.

The case code I have now is a lot more responsive, I dont know what the difference is really. It still has some delay when input changes drastically in the other direction, but it is now more tolerable. Even before the other code still worked, but recovery now has less engine bogging as it recovers. The case code also does not overshoot as bad as the if else code, I can run it a little faster than before.

Here is the case code after a little tweaking it dialed in pretty good.

#include <Servo.h> 


Servo myservo;  // create servo object to control a servo 

 //VG 02 Mixture Controller v0.6
//Craeted by Matt Ryder, Vulcan Gasifier LLC May 5, 2015
  //Last edit; May 21, 2015 

// 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

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 O2SwticthState = 0;         // variable for reading the Fuel Mixer Mode status

const int sensorMin = 0;      // sensor minimum, discovered through experiment
const int sensorMax = 1023;    // sensor maximum, discovered through experiment

void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  Serial.begin(9600); 
  
        // 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 
 
  }
} 
 
 
 void loop()
 {
       // read the state of the pushbutton value:
  O2SwticthState = digitalRead(O2SwtPin);
   // read the value of the O2 sensor:

   int sensorReading = analogRead(A1);

  if (O2SwticthState == LOW)
  {
  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 
  
  }
    else 
    {
         
         delay (10);
    
 
    }
   
     // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
Serial.println(analogRead(A0)); 
  
    int SensepinVal = map(sensorReading, sensorMin, sensorMax, 0, 20);
   switch (SensepinVal) {

    case 0:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(10); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  } 
    break;
    case 1:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(10); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 2:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(15); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 3:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(15); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 4:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(15); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 5:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(15); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 6:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(15); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break; 
    case 7:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(50); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;     
    case 8:    
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(50); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 9:    
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(50); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 10:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(300); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 11:
  {
         // we need to move the servo 1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
         lastpos = lastpos +1;
         myservo.write (lastpos); // Moves servo negative 1 degrees

   
         
         delay(400); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 12:
  {


   
         
         delay(500); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 13:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(500); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 14:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(450); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 15:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(400); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 16:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(350); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break; 
    case 17:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(300); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;
    case 18:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(250); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break; 
    case 19:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(150); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break; 
    case 20:
  {
         // we need to move the servo -1 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -1;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(15); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    break;     
  }
     delay(10);
}

Matt this little fellow cost about same as your Kohler.
102mm by 116 crank.
It was a custom build intended for dual fuel use.
In the years since I see its image recycled over and over on the websites of various Indian clone builders who had nothing to do with its fabrication.
I am kind of amused that MY clone is used on so many sights.
https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR3KprGjAP6bPfitEByw9R033MKrq3Aihwe8uHiEmyc49lUgYvxDw

Stay away from the precup listeroids.
GM90 is a better choice because of the direct injection head
The Petteroids are probably the best choice as a gas engine conversion though.

Yeah Im not to fond of the Lister, just its massive weight alone makes it hard to sell. To ship this overseas it will be an enormous cost and that is a deal breaker.

Delivered that engine cost me around 2000 about ??? 8-10 years ago.
Can’t recall what it weighs but I would guess around 450 to 500 pounds ( three crates of engine and parts ).
I bought extras enough to rebuild it two or three times.

At the time it was unique because of the heavyduty starter and ring gear on an electric flywheel.
There is a very similar PH in the Virgin Islands ( air cooled version ).

The Lister machine will weigh around 3500 lbs when complete. Its a beast!!

Hi Matt,

Forgive me if I’m repeating something already talked about. I kind of skimmed to catch up with this thread.
Most likely the IDE can make more efficient proto-functions with the case code as it is converting it into machine language… That will make it a little faster and more efficient. However, I doubt that is what you are observing.

I would think the main difference is less blocking time with the calls to the delay() function. These little processors can’t hyper-thread so if you are telling it to wait via the delay function, it literally stops dead-in-it’s-tracks and counts clock cycles until the function call expires. No sensor reads, no servo adjustments, just counting clock cycles. It would be worth the effort to limit or even eliminate delay calls.

I still think using the averaging code I suggested early on would be of value too. Probably even more so if you move toward the narrow band.

1 Like

Matt,
Nice! that is actually a pretty cool way to do the switch statement. I didn’t think of that. :smile:

in the <11 instance you have delay() values that are quite a bit smaller then the >11 instance which creep up to 400… and yet you are still only moving the servo 1 degree. if you are only going to move the servo 1 degree, you might just do one if statement. Ie value< ideal, (move +1)…value > ideal (move -1).

I have to look at this in a different editor, but it seems like 10 or 11 would be the ideal…
I would also break the map() into a multiple of 2, so like a range 8,16,32 ie 0-7. I am guessing that will perform faster, but I think the delay() is the actual problem.

I wonder if you didn’t see the rearrange of the if-else I did in the last one I posted since I had to flip the order of the ifs in the higher number ranges around to actually work correctly.

Joe thanks for the input, you guys are a great help in my learning process!! I will have to work on using averaging code, this will require me to go through some more learning. But I for sure give it whirl, Im building a small machine just so we have a little machine to play with a try out stuff like this. Thats the problem we dont get much time to play, its always work work work!!

Sean, that is a great idea with spitting the mapping, I didnt even I could do that. I will tinker with this.

So Im gathering from the both of you, to try and get rid of the delays and use the increments? Then maybe use a delay at the end?

I did see that you had did some arranging, I also did some of this as well; priorities first right!

I was trying to type quickly. I didn’t mean split the mapping persay, just use a range of numbers that are a 2 power of x (multiple was the wrong word too.). It can optimize it better because it is a bit shift rather then actual division. so like 2,4,8,16,32,64,128… the first map is 0-1023 which is 2^10. You currently have 0-20 so 0-15 or 0-31 would work better.

if you are only jumping 1 degree per reading, like you are doing right now with the case statement. This would probably be the more efficient:

if(sensorReading> (ideal +10))
{
lastpos-- ;
myservo.write (lastpos);
}
else if (sensorReading < (ideal -10) )
{
lastpos++;
myservo.write (lastpos);
}

delay(50) ;