Ja, du hast recht, das mit der Differenz führt zu Fehlern. Anderer Vorschlag: Ringpuffer und die ADC Werte mitteln. Falls ADC Wert kleiner als das Mittel, den ausgeben, sonst das Mittel. (Verbraucht aber deutlich mehr Rechenpower)
Wenn jemand eine Lösung OHNE das Speichern alter Werte hat, dann wäre ich darauf gespannt wie ein Fuchs.

EDIT: Ich habe den Fehler gefunden: (hoffentlich!)
Code:
16 Bit variablen:
currentadcval: Momentaner ADC wert
preadcval: ADC wert vom Vorherigen durchlauf
diff: Differenz der Werte

void pwm_output(currentadcval){
if(currentadcval>preadcval){
diff=currentadcval-PWM;
PWM+=diff/4; // Faktor entsprend skalieren, aber nicht zu groß machen und immer Potenzen von 2 verwenden! (Hät den Code klein!)
}else{
PWM=currentadcval;
}
preadcval=currentadcval;
}