Grade control


What do you mean with the “automatic cut line creation algorithm”? Would it be calculating the red line on your figures based on the survey or a 3D map? I’ve just followed opengrade threads and I feel everything is there already except something free to replace OptiSurface to create a 2D map (3D plot) from survey data. Even a partly manual approach should be fine for those who consider OptiSurface too expensive. Say manually pick up a decent number of reference points from the survey map, perhaps some 2D low pass filtering and a bit of iteration if the calculated map does not look acceptable. Could calculate the cubic metres of soil to be moved?

Welcome to the Open Grade thread. I think it would be good if at some point the different versions of OG were melded into 1 version. Im uncertain what the differences are on yours. What is the difference from pipe to ditch the picture looks the same accept for the button

1 Like

Hi welcome to the forum!

It’s great to see other users of OpenGrade!

That’s great, currently this was only discussed, as far as I know no one is working on it right now.
If you don’t mind, I would like to take a look at your source code.

Remember that there are 2 separate software discussed on this tread:
OpenGrade, like yours,
some upgrades from original:
com port for tool control
adjustable grading distance from survey line
adjustable view distance under and above ground with reference lines.
ability the reverse the survey line, to survey in either direction for tile plow.
ability to move the whole target line up and down.
ability to save multiple swaths for future reference.
Probably some other features I forgot!

OpenGrade3D, that works in a completely other manner, it can take survey of a whole field and with a third party software (like Optisurface) you design the map then back in OG3D you can grade the whole field.


I will be focusing primarily on the original version as that is what is needed for our farm, for the Auto Reference feature I am working on would act the same way as the slope IQ used by ditch assist. minimizing dirt moved and maintaining the minimum slope. In doing this I would also like to check to see if the proposed path could be done by either a tile plow or ditching machine in one pass and warn users if the line they have created is even possibly to attain before they start the cut. Once finding this forum I took a look at your application Pat (V2.1.3Beta) and realized we had implemented ALOT of the same things, just in a little different way. I like your idea of the saved swaths and have been thinking about doing something with it since I started on this project this week. I will take a look at your source today and see how I can implement it. I guess I should learn how to use Github For Sharing so I can allow other users to look through my source.


I think I may have gotten the auto drain working!

public void AutoDrain()
    vec2 temp = new vec2();
    double distFromLastPlot = 0;
    int drawPts;
    int ptCnt = ct.ptList.Count;
    double minDeltaHt = 0;
    double angle = (vehicle.minSlope) * 180;
    int startPt = 0;
    int endPt = -1;
    int lowestPt = 0;
    int upCnt = 0;

    int MaxUpcount = 2; //can be set higher or lower 

    //check to find the first low point and call it the start point        
    for (int k = 1; k < ptCnt; k++)
        if (ct.ptList[k].altitude <= ct.ptList[k-1].altitude)
            lowestPt = k;
        if (upCnt == 2)
            startPt = lowestPt;                    
    for (int i = startPt; i < ptCnt; i++)
        // check to see if drawlist has any points 
        drawPts = ct.drawList.Count;       
        if (drawPts > 0)
            //calculate the distance from point i to last tempPt
            for (int h = (int)ct.drawList[drawPts -1].easting; h < i; h++)  // calculate distance from last point if first point is set
                distFromLastPlot += ct.ptList[h].distance;  // add distance all distances from lastPt to hPt 
            // add first point
            temp.easting = i;   // (double)ct.ptList[i].easting;                            
            temp.northing = ((double)ct.ptList[i].altitude);
            drawPts = ct.drawList.Count;                                                        
        minDeltaHt = (Math.Tan((angle * (Math.PI / 180))) * distFromLastPlot);                 
        temp.easting = i;
        temp.northing = ((double)ct.ptList[i].altitude);                    
        if (ct.ptList[i].altitude) < ct.drawList[drawPts - 1].northing + minDeltaHt) 
        distFromLastPlot = 0;        
    endPt = drawPts -1;

To anyone who is interested in the AutoDrain Function here it is! Just add it to the OpenGl.Designer.cs file and call it whenever you please. One simple option is to add it to a button so that you can both draw it manually or auto route the cut line at the press of a button.

For those who have used hydraulic prop valves vs standard on off valves in the past, what would recommend and why? On off seems simple and cheap, whereas prop would have more fine control?


Cool I will take a look at your code!
I was thinking or an “autodrain” btn, each press give an other line, like one near the minimum depth ,one with the ideal depth average and one near the max depth.

For the valve I would say prop is the way to go. This give fast response for big corrections but can also make fine corrections near the line.

If you have JD or CIH 4wd with electric SVC you can use the tractor remote directly. See the earlier posts.


Like Pat said above, in addition if you have electrohydraulic CAN valves you and plug into the harness and use them directly on the tractor as well.


Wondering how your tests on the 6022 turned out if you had a chance to play with them at all. I am using a 4275 as it is what I had on hand to try, I rewrote a good portion of the Arduino code and implemented a PID function that seems to be quite responsive. But I now have run into the same problem as you with the 4375 not being able to get to the max 5V, is the op amp just for isolation from the tractor system, as the DAC is capable of putting out 5V on its own, or function to smooth out DAC irregularities? I am not very familiar with electrical components, enough to get by and that’s about where my knowledge ends.

For those interested in the CNH Pinout and how they are controlled-
In our T9** Tractors the CNH input system works the same as the Deere with:

Max<< Retract±-----------------+Extend>>Max

Pin 1 Controls Valve 1 (#1 Laser/remotePOT sense)
Pin 4 Controls Valve 3 (#3 Laser sense)
Pin 5 is +5V (Laser +5V Source)
Pin 6 is GND (Laser ground)

We are out of the fields due to mud.

My thinking for the opamp was to make sure the dac didn’t get burnt up, I’m not sure what the current draw is for the tractor, so it was protection.

It should function the same with a lm358 or a 6022, except toward 5v… iirc the 358 limits to something like 3.2v when fed a 5v source. And I’m sure that’s what you are running into as well…

Not familiar with case but determine the current draw to the pot pin and if it’s less than the dac it should work.

I am curious to see your implementation of pid… I started reading on it, but for some reason I can’t wrap my head around how to code it yet…

/// Variables needed 
byte deltaDir;   // 0 is down 1 is up 3 is off cut
byte cutDelta;  // byte of cut delta sent from Open grade 0-255
float Kp,Ki,Kd;   // PID Constants Sent from OpenGrade
float delta_previous_error, delta_error; // used for error tracking
float deltaSetpoint; // likely zero

/// PID Output Function 

void SetOutput() {
  analogOutput1 = 2048;  
  if (deltaDir == 0){
    cut1 = -(int)cutDelta;
  else {
    cut1 = (int)cutDelta;

  delta_error = (delta_setpoint) - cut1;

  PID_p = Kp * delta_error;// calculate the P errror  
  PID_d = Kd*((delta_error - delta_previous_error)/LOOP_TIME);// calculate the d error
  if(-3 < delta_error && delta_error < 3){  // 3 cm deadband for i
    PID_i = PID_i + (Ki * delta_error);//calculate the i error
    PID_i = 0;

  PID_total = PID_p + PID_i + PID_d;

  if (PID_total >  2300) PID_total = 2300;      
  if (PID_total <  -2300) PID_total = -2300;

  if (deltaDir == 1){ // Delta is Positive need to lower IMP
    analogOutput1 = map(PID_total, 0.0, -2300, 2048, 0);

  else if (deltaDir == 0){// Delta is Negative need to raise IMP
    analogOutput1 = map(PID_total,  0.0, 2300, 2048, 4096);
  if (analogOutput1 > 4096) analogOutput1 = 4096; // do not exceed 4096
  if (analogOutput1 < 0) analogOutput1 = 5; // do not write negative numbers 

  voltage = ((double)analogOutput1/4096) * 5.0;
  if (cutDelta > deadband){ 
        Dac1.setVoltage(analogOutput1, false); 

  delta_previous_error = delta_error;  

It essentially error tracks your path a bigger error requires a bigger reaction, in this case the valve position, to correct it.

It would be curious to run a simple sketch with basic gain vs one with pid…

My train of thought goes like this.

We can set gain and hyd flow from the cab. Using those we can amplify or retard the “jump” of the blade.

When we go through the field the number is always changing, vs what is typically used for pid control (heating to a setpoint), all examples I found are using a static “goal post”.

That is why I wonder if the pid method is best. I admit to being pretty dumb about pid usages.

In this case the goal post is delta 0 which never changes. It is always working to get to delta zero as quickly and precisely as possible. Or at least that is the plan

That makes sense to set the goal as zero… That was the biggest hurdle for me to understand.

  1. How do we go about setting the pid constants? As far as knowing what numbers to use.

  2. How are we suppose to remove the tractor dead band? What I mean is I am using the pid min and max to remove the machine dead band while keeping the controller dead band…

The deadband resides from roughly 2.25v → 2.75v
Min .5v and max 4.5v

As far as I can tell setting PID constants is trial and error, I have written it into OG to communicate those values to to ESP-32 so you can update them as you get your machine calibrated. P is the biggest factor for change so would start with that

I only have the CNH on farm and didn’t notice much for deadband but if there is just map it to your dead max and min instead of to dead Center

1 Like

The way I got around the machine dead band was to use the pwm min max functions in Pat-I’s opengrade3d

Maybe something to consider…

I’m waiting on computer parts so I can start learning the code and looking for a free alternative to optisurface.

Currently im using EZIGrade which is $1200 usd.

But there is a tool from NRCS which might be able to do what we want it just doesn’t import/export well.

The other option is to do some python coding into QGIS to work up slope and smoothing.

1 Like

If anyone wants to have a look through the Code I have finally figured out how to use GitHub.

Ps. Have not however figured out how to update the installer so if you try and install that way, you will end up the in original Opengrade, just run the exe file instead.

1 Like

So Ive got control of my Case 550 quads #1 SCV thru OG. WHen i hit my 1 button on armrest auto takes over. Seemed a little slow to react in my first (driveway) test. Any initial setting recomendations? Maybe tomorrow ill go out and cutt some dirt!

Be sure your minPWM is high enough.
In theory 25 should be enough to make it move very slowly.

If it don’t react fast enough near the line crank the minPWM, if it don’t move fast far from the line crank the Gain.

If when coming to the line it overshot, crank the Overshot Red.

1 Like