High side regulation of current for proportional valve
The flyback current should be inside the current sense loop.  This is a legitimate part of the solenoid current.  Not measuring it gives bad input to the controller.

Another source of non-linearity with respect to the supply voltage is due to the D1 voltage drop.  This fixed voltage introduces a non-linear element since it doesn't scale with supply voltage.  At higher supply voltage, the PWM off time will be less, so the diode on more, making even a larger difference.


D1 should be a Schottky diode.  These have about half the voltage drop of a normal silicon diode.  The non-linearity will still be there, but less prominent.

The FET switch makes no sense as shown.  You don't want to drive the coil from a source follower, as you are doing now.  The coil common mode voltage can float arbitrarily, so it makes more sense to use a low side switch between the coil and ground.  This gives you real PWM, with the full supply voltage across the coil when the switch is on.

A little feed-forward would probably help.  Have the control loop compute a normalized PWM at a fixed supply voltage.  Then do the divide using the actual measured supply voltage to determine the actual PWM duty cycle to load into the hardware.  This removes supply voltage compensation from the control loop, which then sees a more consistent plant response.  The control loop then just handles the little non-linearity that making the duty cycle inversely proportional to the supply voltage doesn't take care of.

I did this with a proportional valve once that had to run from 8 to 20 V supply and it worked very well.

500 Hz seems very low for the PWM frequency.  You want the solenoid current to not decay much during the PWM off time.  Think of the solenoid current as the average DC with AC PWM ripple on it.  Only the former moves the solenoid.  The latter just causes wasted power and heating, and adds noise to your current measurement.

The R3 and C1 filter don't make sense considering the 500 Hz PWM frequency you are using.  You want to measure the average solenoid current, so the PWM frequency should be strongly attenuated.  Your filter rolls off at 4.1 kHz, so isn't going to do much of anything to reduce the 500 Hz PWM ripple.  A higher PWM frequency also helps with this.

The only way that what you have would be acceptable is if you're sampling the current at well beyond 1 kHz rate and then doing significant filtering in the firmware.  1 kHz is the absolute minimum just to keep the PWM fundamental frequency from aliasing.  However, the PWM signal will have significant harmonics, which is why you would need to sample significantly higher than 1 kHz to get a reasonable picture of the current.

Again, use much faster PWM and much lower filter rolloff.  Switching to a Schottky diode as already noted reduces the magnitude of the PWM frequency in the current signal.  Even with all that, you may still need to sample at high speed, then digitally filter and decimate.