Arduino Manager Development for All

cool Im going to load this up right now. Here is the code Ive been tweaking on today. It is more stable; however, the differential between the close parameters and panic mode is not enough. It is either too responsive or too slow to react in the outer parameters.

Ill get this loaded up and start playing :smile:

#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
 
 //VG 02 Mixture Controller v0.2
//Craeted by Matt Ryder, Vulcan Gasifier LLC May 5, 2015
  //Last edit; May 12, 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


const int threshold1 = 600;   //Threshold limits for rich gas condition
const int threshold2 = 660;   
const int threshold3 = 690;

const int target1 = 710;      // Target Parameter for rich condition
const int target2 = 700;      // Target Parameter for lean condition
const int target3 = 790;       // Target Paremeter for extream Lean condition

const int threshold4 = 720;    //Threshold limits for lean gas condition
const int threshold5 = 750;

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

void setup() 
{ 
  myservo.attach(9);  // 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, 20, 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, 20, 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);
    
 
  }
  
  
   if  (sensorReading <= threshold3)
  {
         // we need to move the servo 10 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(200); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }        
 else  if  (sensorReading >= threshold4)
  {
         // we need to move the servo 2 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(200); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    else if  (sensorReading <= threshold2)
  {
         // 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 +10;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         
         delay(10); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    else if  (sensorReading <= threshold1)
  {
         // 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 +20;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         delay(10);  // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
  }
    else if  (sensorReading > threshold5)
  {
         // we need to move the servo 2 degrees in the POSITIVE
         // direction so we need to add ADD to the last known 
         // position.
        lastpos = lastpos -10;
         myservo.write (lastpos); // Moves servo negative 1 degrees
         delay(10);  // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
  }
    else {
         delay (400);
         }
         //might need a delay for the o2 sensor in general for everything to catch up.
         // delay (800);
}

“This application is a great example. It doesn’t really matter if you are a couple of milliseconds off trying to correct the valves, however, if you start adding a crankshaft sensor, and controlling the ignition timing, then certainly a microcontroller is a much better choice.”

You make a really excellent point madflower69.
I never considered the clock on the arduino being a problem

This thread has really impressed me with the creativity and inspired me to look into buying one of these kits to see if I can create my own PID loops to do this.
.

I wondered about that. Part of what I meant to add and didn’t get to yet (maybe tonight depending on time constraints) is what Joe_rich suggested. basically make adjustments based on an array and a moving average, which should smooth things out quite a bit.

I have part of it written, I just didn’t get it finished.

Matt:

I do not know how to program is C.
I am a fossil that only understands the simple mechanics of op codes and registers on antique micro controllers like the 6800 and Z80.
But from what I do understand I am expecting to see and not finding any code related to PID function.

I just did a quick scan and found this on the Arduino webpage.
Its not the same application but it uses a string of code that might improve your responsiveness and accuracy

1 Like

I may have stated it incorrectly in the post.

It isn’t a problem on the arduino since you are doing real time. :slight_smile:

The raspi has the issue because linux isn’t a real time operating system. You can run multiple programs at the same time sharing the processor time, and i think it actually can delay interrupt signals. which screws up -exact- timing.

Actually the code I posted I think I might be able to get to work. I trying some different things, I need to play with the thresholds a bit to see what ones are doing the work I think. I might be chasing my tail and only seeing the outer parameters functioning.

Hey Wallace, well im no expert here, im just winging it lol I know enough to be dangerous now.

OK yes that is whats going on. Just need to re tweak the parameters and get rid of the targets. Then just fine the delays. The inside parameters are too tight and especially the rich side is too close. So Im going to back off the parameters and give it some room.

Here is V0.3 I have this tuned in pretty good, one thing I changed is the out most extreme rich condition just does a rapid move to a set angle. This way it moves very quickly without delay or over shooting. Then the other parameters take over after it gets there.

#include <Servo.h> 
 
Servo myservo;  // create servo object to control a servo 
 
 //VG 02 Mixture Controller v0.3
//Craeted by Matt Ryder, Vulcan Gasifier LLC May 5, 2015
  //Last edit; May 16, 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


const int RichCon3 = 550;   //Threshold limits for rich gas condition
const int RichCon2 = 600;   
const int RichCon1 = 690;



const int LeanCon1 = 740;    //Threshold limits for lean gas condition
const int LeanCon2 = 900;

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

void setup() 
{ 
  myservo.attach(9);  // 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, 20, 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, 20, 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);
    
 
  }
  
       if  (sensorReading <= RichCon3)
  {
         // Extrean rich condition, moves servo to set position angle

       
         myservo.write (100); // Moves servo negative 1 degrees
         delay(50);  // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
  }
      else if  (sensorReading <= RichCon2)
  {
         // 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
                                   
  }
    else if  (sensorReading <= RichCon1)
  {
         // 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
                                   
  }        
  
   else  if  (sensorReading >= LeanCon1)
  {
         // 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(600); // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
                                   
  }
    else if  (sensorReading > LeanCon2)
  {
         // 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(100);  // Delay time between 1 degree movments
                                   // Decreasing the number = slower response time
  }
    else {
         delay (10);
         }
         //might need a delay for the o2 sensor in general for everything to catch up.
         
}

There is a way to get it to write to a serial port, so you can get some feedback from the unit. It is like serial.out() i think. Then you have to connect to it somehow… But it is worth it for debugging.

The over rich condition should probably set back to the original potentiometer reading… ie a variable and not a hard coded value.

Yup I already did that.

Matt
I hope you did not take my suggestion as being critical of your work.
On the contrary I am impressed.

Here is some interesting code for a PID

https://www.pdx.edu/nanogroup/sites/www.pdx.edu.nanogroup/files/2013_Arduino%20PID%20Lab_0.pdf

Madflowe69r:
I looked at the boards and some do not use a crystal for timing but a cap.
I don’t know how much this will cause frequency drift but I thought you were suggesting this might be a problem

Oh no not at all sir and thank you for the kind words. I didnt do this on my own, it was with help from great of folks like yourself, Shawn and others. So I owe much gratitude to all you that have helped me get here with this. So thank you to all that have helped to get this far :fire:

1 Like

Matt,
If you need/want more help, just ask. It is actually good for me to sharpen my programming skills which are much better then my welding skills. I just don’t have a good way to test it from here. And at this point, I am not sure exactly what you want done.

Just fyi, in case you didn’t realize it. Your next iteration, can probably just use the bosch lsu 4.2 sensor directly which can save a few bucks since you have logging working.

The last thing which I think you know is the scale of the sensor output, isn’t linear so the further you get away from the middle, the further off a linear calculation will be.

Wallace,
You are correct, you can get some drift. The point I was trying to make is the general purpose computer like the original raspi has 40 cycles for every 1 cycle of the arduino. If the raspi is off by a few cycles, it is kind of like drift. People are finding out the higher clock speed is removing the necessity of the lockstep precision the microcontroller like the arduino gives in a number of applications. Certainly not all applications, and there are pros and cons of both. You can actually hook them up together if you want to. :slight_smile:

Wouldn’t this require the signal to be reduced to 5v or is already done from the sensor? If we need to reduce the voltage how would we do this? This would be pretty cool If we could do it this way.

I ran again today, with a better fuel. Yesterday, the fuel we had was too wet and causing flow issues. So today we ran a better fuel that allowed us to run more linear. So more tuning, I reverted the extreme rich condition back to the original code. Having any set parameter would not work as nothing is linear and is the reason we want this type of control. So now that we had the gasser running good it was easier to tune the code. Im learning things about this system as I go and learning new things all the time. One thing that has had me chasing my tail is sometimes the signal from the sensor gauge I think is getting delayed and going into a reset mode. When it does this it really messes the thing up, so eliminating this using a direct signal from the sensor I think in the end will be the way to go.

Yes indeed I have new code to post, but I am going to wait a bit on this. This is the smoothest and most responsive yet, I now want to test with loading next. So tomorrow we will load it up, weld with it, lights, what ever we can through at it. I opened up the hopper for an extended period and this where this shines as it will automatically adjust for this and keep things going. :fire:

Video is coming Im going to post this on another thread as this is a new product.

1 Like

You should log the sensor readings.
Serial.println(val); // debug value

Also double check your connections, if the connection isn’t tight it can screw up stuff and give an unpredictable reading. I also wonder if you need a resistor of some sort in the circuit.

Everything is tight, Ive noticed this same reaction on all of these kits. So I think it has something with this sensor kit. Yes I did have to put in a pull down resistor for the switch to select the pot or the sensor. Would putting a resistor on the signal wire help things you think? Ive wondered about this myself.

Ill have to get a cable long enough; that would be great help to actually see what’s going on in there!!

I just read a thread, and it appears there is an issue with the sensor itself or the recalibration loop. They supposedly fixed at least part of it in the 4.9 wideband. but you might be able to fix part of it in software.

Now that I know about this and this is what is messing things up. I revisited the write to pot position but also in the extreme lean condition. This was missing before and is why it would not recover. We ran all day and it is running without missing a beat, weve done load testing today as well. Welded with it, ran grinders and our cook top. We tried getting up to 5 Kw but no go. This is about its peak and 4 kW is its running output power. Im ready to call this a success on this machine and can not wait to show this thing off at Argos. :fire:

2 Likes

I don’t know how much sensor skips around. You probably just have to log it and look at the data. I personally would already have it hooked to a raspi that I can connect to over wireless so I could watch it and tweak it, but that is me… You can use an old portable too. It doesn’t have to be much of one.

I would at the very minimum get a few readings to see where it is today, and see how much it deteriorates over time.

How big is the generator? 4kw seems like a really good number for a 6.5kw peak generator.

And congrats! I wish I could have helped more, but I am happy you have it working to your satisfaction. :slight_smile:

1 Like

I have a banana pi, but Im not that savvy yet :wink: