Keresés

Új hozzászólás Aktív témák

  • Gergosz2

    veterán

    válasz JozsBiker #19050 üzenetére

    Ennyit finomítanék a kódon :

    #include <Arduino.h>

    #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
    #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
    #define ADC_BUFFER_SIZE 20
    #define ADC_PIN A0
    #define ADC_OFFSET 512.0f
    #define ADC_GAIN 0.0f // be kell állítani
    #define RMS_GAIN 0.05f // delta_T/T

    volatile uint8_t bufferIterator = 0;
    volatile uint16_t ADC_BUFFER[ADC_BUFFER_SIZE];
    volatile bool CalcRMS = false;
    uint16_t ADC_BUFFER_CALC[ADC_BUFFER_SIZE];
    float RMS_Current;

    unsigned long SerialTimer = 0u;
    unsigned long SerialPrintTimeout = 1000;

    void setup()
    {
    //Gergosz2 2023
    Serial.begin(51200);
    setupPWMInterrupt();
    bufferIterator = 0;
    SerialTimer = millis();
    memset(ADC_BUFFER, (uint16_t)0, ADC_BUFFER_SIZE*sizeof(uint16_t));

    }

    void loop()
    {
    if (true == CalcRMS)
    {
    CalcRMS = false;
    memcpy(ADC_BUFFER_CALC, ADC_BUFFER, ADC_BUFFER_SIZE*sizeof(uint16_t));
    RMS_Current = 0.0f;
    int iterator = 0;
    for (iterator = 0; iterator < ADC_BUFFER_SIZE; iterator++)
    {
    float SI_val = (((float)ADC_BUFFER_CALC[iterator] - ADC_OFFSET)*ADC_GAIN);
    RMS_Current = RMS_Current + SI_val*SI_val* RMS_GAIN;
    }
    RMS_Current = sqrt(RMS_Current);
    }

    if ((millis() - SerialTimer) > SerialPrintTimeout)
    {
    SerialTimer = millis();
    Serial.println(RMS_Current);
    }
    }

    void setupPWMInterrupt()
    {
    noInterrupts(); // disable all interrupts
    TCCR2A = 0; // set entire TCCR2A register to 0
    TCCR2B = 0; // same for TCCR2B
    TCNT2 = 0; //initialize counter value to 0
    // set compare match register for 1khz increments
    OCR2A = 124; // = (16*10^6) / (2*1000*64) - 1 (must be <256)
    TCCR2A |= (1 << WGM21); // turn on CTC mode
    TCCR2B |= (1 << CS22); // Set CS01 and CS00 bits for 64 prescaler

    sbi(TIMSK2, OCIE2A); // enable timer compare interrupt

    interrupts(); // enable all interrupts
    }

    ISR(TIMER2_COMPA_vect)
    {
    ADC_BUFFER[bufferIterator] = analogRead(ADC_PIN);
    bufferIterator ++;

    if (bufferIterator > ( ADC_BUFFER_SIZE - 1u) )
    {
    CalcRMS = true;
    bufferIterator = 0u;
    }
    }

    Láttam hogy van szkópod szóval ezeket így lehetne kalibrálni:

    ADC_OFFSET : egyszerűen nulla terheléssel, értsd nincs rajta semmilyen fogyasztó, mekkora feszültség értéket ad vissza a szkóp? Tegyük fel, hogy 2.5V, akkor az ADC_OFFSET értéke (2.5/5)*1023 lesz, ami 512-re jön ki kerekítve.

    ADC_GAIN : ha megvan az ADC_OFFSET, akkor ismert terhelésre megkéne nézni mit ad vissza a mérőműszer a kimenetén. Ehhez kéne a szkóp és multiméter is. Célszerű itt egy sima izzót használni, semmi fancy LED dolgot. Tegyük fel hogy az ADC_OFFSET 2.5V lett és mondjuk 2A csúcs folyt izzón amit a multiméterről olvastál le, amire 3V csúcsfeszültséget mértél a szópon. Ilyenkor az ADC_GAIN nem lesz más mint (5/1023)* 2 /(3-2.5).

    Ha ezekről adsz képet és vagy mérési eredményt kiszámolom neked.

    RMS_GAIN : ehhez nem nyúlj, kivéve ha a megszakítást akarod változtatni.

    Az interrupt kezelő rész fontos bele ? Mit csinál tulajdonképpen ?
    1kHz mintavételezési időt valósít meg , így gyakorlatilag 20 mintát vesz 1 hálózati periódusból.

    [ Szerkesztve ]

    Nokia 6030 Hardcore User // I Panic Restaurant by Taito

Új hozzászólás Aktív témák