feelfree69 / pps5330

Reverse-Engineered Firmware for the ELV PPS5330 Power Supply
GNU General Public License v3.0
1 stars 0 forks source link

Spannungsdrift #5

Open rolfdegen opened 5 months ago

rolfdegen commented 5 months ago

Hallöchen.. Hab noch ein kleines Problem in der neuen Firmware entdeckt. Bei Belastung sinkt die Ausgangsspannung stetig. Am Original ELV Netzteil (schwarz) stabilisiert sich die Ausgangspannung nach einer Weile (siehe Video).

Video: https://youtu.be/FvQBmEi_dog

feelfree69 commented 5 months ago

Da ist in der Original-Firmware halt eine Nachregelung drin. Sowas war in deiner Firmware auch drin, aber weil damals die Messung nicht kalibriert war, hat die quasi vom Sollwert weggeregelt und alles nur schlimmer gemacht. Deshalb hab' ich die Regelung damals komplett rausgeschmissen. Bei der extrem geringen Abweichungen (ca. 1mV/500mA) ist eine Ausregelung auch kaum sinnvoll möglich, weil wir ja sowieso nur in 1.8mV Schritten einstellen können. Wenn allerdings die Temperaturkompensation noch mit betrachtet wird, wäre es vermutlich sinnvoller, tatsächlich nur die gemessene Spannung als Regelgröße zu nehmen und damit sowohl Temperatur- als auch belastungsbedingten Spannungsdrift auszugleichen.

rolfdegen commented 5 months ago

Ja das wäre besser. Die Temperatursensoren sind doch sehr ungenau.

feelfree69 commented 5 months ago

Hier ist deine Original-Regelung: https://github.com/feelfree69/pps5330/commit/9723ca5162b6b279fba508813a22ca6f669393b0#diff-c2204c550690d09c2033de7ba07cfbf3cb9c3adb34b3baa610a9a632b2520c5eR457

Wobei ich da nur die Hälfte verstehe:

Da die Messung aber nur auf 12bit, also 7mV genau ist, kann die Regelung eigentlich im 1mV Bereich nicht vernünftig funktionieren.

Edit: Nochmal nachgedacht:

rolfdegen commented 5 months ago

Hallo Klaus Ich habe die Belastungsmessungen immer mit 5.00V gemacht. Da scheint es ein kleines Problem mit dem Nachregeln Spannung zu geben. Die Spannungsanzeige zeigt trotz Belastung immer 5.00V and. Wenn ich die Messung z.B mit 6.00V mache funktioniert die Spannungsregelung und die Anzeige zeigt den korrekten Wert an.

feelfree69 commented 5 months ago

Sorry, Ich verstehe nichts... Es gibt keine Regelung in meiner Firmware.

rolfdegen commented 5 months ago

Ok Ich mach nocheinmal ein Video. Wie gesagt, im 5.00V Bereich verhält sich das Netzteil sehr merkwürdig. Stelle ich das Netzteil auf eine andere Spannung z.B. 6.00V funktioniert es und die Spannungsdrift ist sehr klein.

feelfree69 commented 5 months ago

Ist es dein umgebautes?

Die Firmware stellt einmal die PWM ein und rührt dann nix mehr an. Schon gar nicht abhängig von der eingestellten Spannung.

Und in deinem oben verlinkten Video arbeitest du sehr wohl mit 5V, und merkwürdig ist da nichts.

rolfdegen commented 5 months ago

Das regelt ja eigentlich die Hardware. Wie gesagt im 5.00V Bereich gibts Probleme. Vielleicht liegts an den OCR Registern ?

Neues Video. Zuerst 5.00V/2.5A und dann 6.00V/2.5 Einstellung Link: https://youtu.be/1WIm6SWlFUY

feelfree69 commented 5 months ago

Geregelt wird nur im Analogteil, da hat die Firmware nichts mit zu tun. Du hast dein Netzteil ja umgebaut, das verhält sich vermutlich anders als ein Originales.

rolfdegen commented 5 months ago

Das Video zeigt das Problem etwas genauer. Bei genau 5.00V wird die Ausgangsspannung nicht korrekt angezeigt. Bei anderen Spannungseinstellungen z.B. 5.10V ist die Spannungsanzeige annähernd richtig.

Video: https://youtu.be/SqReOx2EAOY

feelfree69 commented 5 months ago

Bei 5.00V und 25.00V wird die Spannungsmessung kalibriert und stimmt deshalb dort besonders genau.

rolfdegen commented 5 months ago

Im Vergleich zu den anderen eingestellten Spannungswerten stimmen die angezeigten 5.00V aber nicht mit der tatsächlichen gemessenen Ausgangsspannung überein.

feelfree69 commented 5 months ago

Ok. Ich halte einen Firmware-Bug der sich nur an einer Spannung bemerkbar macht für nahezu ausgeschlossen, aber freue mich natürlich trotzdem über jeden der Fehler sucht und fixed.

rolfdegen commented 5 months ago

Hallo Klaus Hab jetzt die Spannungsregelung in deinem Code implementiert. Funktioniert :) Aber vielleicht hast du eine bessere Idee oder einen anderen Vorschalg.

`// // U-I-P-T Measurement // void Measurement(void) { static uint8_t counter = 0;

// Abort when a measuring phase is running -----------------------
if (Timer2_running)
{
    return;
}

// clear integrator ----------------- ----------------------------
if (Meas_phase == MEAS_PHASE_CLEAR_INTEGRATOR)
{
    Meas_phase = MEAS_PHASE_LOAD_INTEGRATOR;

    // clear ADC
    PORTD = (PORTD & ~AD_Input_Mask) | AD_input_Clear;
    start_Measurement_timer();
    return;
}

// load integrator -----------------------------------------------
if (Meas_phase == MEAS_PHASE_LOAD_INTEGRATOR)
{
     Meas_phase = MEAS_PHASE_MEASURE_INTEGRATOR;

    // set AD input
    if (Meas_type == MEAS_TYPE_U)
    {
        PORTD = (PORTD & ~AD_Input_Mask) | AD_input_U;
    }
    if (Meas_type == MEAS_TYPE_I)
    {
        PORTD = (PORTD & ~AD_Input_Mask) | AD_input_I;
    }   
    if (Meas_type == MEAS_TYPE_T_TRANSFORMER)
    {
        PORTD = (PORTD & ~AD_Input_Mask) | AD_input_T_Transformer;
    }
    if (Meas_type == MEAS_TYPE_T_HEATSINK)
    {
        PORTD = (PORTD & ~AD_Input_Mask) | AD_input_T_Heatsink;
    }

    start_Measurement_timer();
    return;
}

// measurement integrator ----------------------------------------
if (Meas_phase == MEAS_PHASE_MEASURE_INTEGRATOR)
{
    Meas_phase = MEAS_PHASE_READ_RESULT;
    // start ADC measurement
    PORTD = (PORTD & ~AD_Input_Mask) | AD_input_Minus_2V5;
    start_Measurement_timer();
    return;
}

// print measurement result ---------------------------------------
if (Meas_phase == MEAS_PHASE_READ_RESULT)
{
    // read timer value for measurements
    uint16_t meas_time = ((OCR2B << 8) | TCNT2);

    ADW_flag = 0;

    if (!displaySettingsActive)
    {
        if (enc_changed == FALSE && Hold_time == 0)
        {
            if (Meas_type == MEAS_TYPE_U)
            {
                print_U_result(meas_time);

                if (Standby_flag == FALSE)
                {
                    static int16_t U_offset = 0;
                    uint16_t U_mess = ( (int32_t) ( (int32_t)meas_time - meas_counts_offset_0V) * 20000 + meas_counts_per_20V/2)  / meas_counts_per_20V;

                    if (U_mess < Ulimit)
                    {
                        U_offset++;
                        set_Usoll(Ulimit + U_offset);
                    }
                    else if (U_mess > Ulimit)
                    {
                        U_offset--;
                        set_Usoll(Ulimit + U_offset);
                    }
                }

            }

            if (Meas_type == MEAS_TYPE_I)
            {
                print_I_result(meas_time);
            }
        }
    }

    if (Meas_type == MEAS_TYPE_T_TRANSFORMER)
    {
        print_T_transformer_result(meas_time);
    }

    if (Meas_type == MEAS_TYPE_T_HEATSINK)
    {
        print_T_heatsink_result(meas_time);
    }

    // Get next measurement type; it doesn't make sense to read temperatures that often
    counter++;
    if (counter%50 == 0)
    {
        Meas_type = MEAS_TYPE_T_TRANSFORMER;
    } 
    else if (counter%25 == 0)
    {
        Meas_type = MEAS_TYPE_T_HEATSINK;
    }
    else if (counter%2 == 0)            
    {
        Meas_type = MEAS_TYPE_U;
    }
    else
    {
        Meas_type = MEAS_TYPE_I;
    }                        

    // clear flags
    Meas_phase = MEAS_PHASE_CLEAR_INTEGRATOR;
    Timer2_running = FALSE;

    // set UI-Limits
    set_UI_Limits();

    if (Hold_time > 0)  Hold_time--;
    if (flash_time > 0) flash_time--;
}

}`

usbman01 commented 5 months ago

kleine Optimierung damit set_Usoll() immer ausgeführt wird.

....
if (U_mess < Ulimit)
{
    U_offset++;
}
else if (U_mess > Ulimit)
{
    U_offset--;
}
set_Usoll(Ulimit + U_offset);
....

Ich bin übrigens der Meinung dass U_offset global sein müsste und nicht static. Dann könnte man bei Drehgeber Änderungen den Offset erst mal auf 0 setzen.

rolfdegen commented 5 months ago

Ja das ist eine gute Idee. Die Abfrage von Standby_flag habe ich aus diesem Grund gemacht, weil sonst der Spannungswert auch im Standby im Display angezeigt wird.