Błąd pomiaru prądu przekładnikiem prądowym?

Na tym forum rozmawiamy o elektronice nie związanej bezpośrednio z tematem CNC

Autor tematu
oprawcafotografii
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 35
Posty: 6356
Rejestracja: 29 kwie 2009, 10:11
Lokalizacja: Kraków / Jaworzno / Kopanka

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#11

Post napisał: oprawcafotografii » 28 lip 2024, 16:04

Nie znam się, sam tego nie zrobię. A czy z ACS758 nie będzie podobnych problemów?


„Największym wrogiem wolności jest najedzony niewolnik.”


atom1477
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 29
Posty: 3780
Rejestracja: 21 kwie 2011, 10:58
Lokalizacja: ::

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#12

Post napisał: atom1477 » 28 lip 2024, 16:09

Będą. Do poprawnego pomiaru potrzeba odpowiedniego programu. Dość prosty no ale trzeba go mieć.
Jak byś programował w C to bym Ci podrzucił prawie gotowca.


Autor tematu
oprawcafotografii
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 35
Posty: 6356
Rejestracja: 29 kwie 2009, 10:11
Lokalizacja: Kraków / Jaworzno / Kopanka

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#13

Post napisał: oprawcafotografii » 28 lip 2024, 16:50

Pokaż w C, może coś podejrzę :)
„Największym wrogiem wolności jest najedzony niewolnik.”


atom1477
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 29
Posty: 3780
Rejestracja: 21 kwie 2011, 10:58
Lokalizacja: ::

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#14

Post napisał: atom1477 » 28 lip 2024, 17:25

Nie mogę znaleźć dla AVR. To masz trochę uproszczony dla STMa (to tylko na początek, żebyś zobaczył, potem trzeba będzie to trochę popoprawiać):

Kod: Zaznacz cały

int main(void)
{

    u_offset = 512;
    i_offset = 512;
    i_magnitude = 1022;
    u_magnitude = 3435;


        if (New_meassurments != 0)
            {
        	New_meassurments = 0;


        	Float = u_rms_irq;
        	Float = sqrtf(Float * 0.001) * (float)(u_magnitude);    //Bez mnożenia przez U_magnitude: 1854.862448 - 100V
        	u_rms = roundf(Float);
        	u_rms = u_rms >> 16;    //1000 - 100V

        	u_dc = (int64_t)((int64_t)(u_dc_irq) * (int64_t)(u_magnitude) * (int64_t)(67108)) >> 42;    //Bez mnożenia 1854862.448 - 100V
        	//u_dc = u_dc;    //1000 - 100V

        	u_max = (int64_t)((int64_t)(u_max_irq) * (int64_t)(u_magnitude)) >> 16;    //Bez mnożenia 1854.862448 - 100V
        	//u_max = u_max;    //1000 - 100V


            	Float = i_rms_irq;
            	Float = sqrtf(Float * 0.001) * (float)(i_magnitude);    //Bez mnożenia przez i_magnitude: 12057.48916 - 1A
            	i_rms = roundf(Float);
            	i_rms = i_rms >> 16;    //1000 - 1A



        		p_irq = p_irq;// >> 16;    //Bez przesówania o 16 bitów 22364983.86 - 100W. Z przesówaniem 341.26257110595703125 - 100W
        		p_irq = (p_irq * 1099571) >> 32;
            	p = (p_irq* (int64_t)(u_magnitude) * (int64_t)(i_magnitude)) >> 40;  //10 - 1W

            	if (p > 0)
            		p_energy += p;  //10 - 1J
            }
}



void TIM1_UP_IRQHandler(void)    //Co 100us
{
    static uint16_t Licznik_100ms = 10;         //Czas wykonywania 11/19us


    TIM1->SR = 0x0000;


    get_adc12(6 , 5 , (int16_t*)&ADC1_buffer[0], (int16_t*)&ADC2_buffer[0]);    //I1, U1

    i  = (ADC1_buffer[0] - i_offset);    //Wyjdzie z zakresu -511...511
    u  = (ADC2_buffer[0] - u_offset);    //Wyjdzie z zakresu -511...511



    u_rms_buffer = u_rms_buffer + (u * u);    //Wyjdzie z zakresu -67108864...67108864 (27 bitów)

    u_dc_buffer = u_dc_buffer + u;    //Wyjdzie z zakresu -512...512 (10 bitów)

    if (abs(u) > u_max_buffer)
    	u_max_buffer = abs(u);

    i_rms_buffer = i_rms_buffer + (i * i);    //Wyjdzie z zakresu -77577846784...77577846784 (37 bitów)

    p_buffer = p_buffer + (i * u);    //Wyjdzie z zakresu -2281701376...2281701376 (31 bitów)



    Licznik_100ms++;

    if (Licznik_100ms >= 1000)    //Co 100ms
		{
    	Licznik_100ms = 0;


		u_rms_irq = u_rms_buffer;    //Max 67108864000
		u_dc_irq = u_dc_buffer;   //Max 8192000
		u_max_irq = u_max_buffer; //Max 8192

		i_rms_irq = i_rms_buffer;  //Max 77577846784000

		p_irq = p_buffer;    //Max 2281701376000

		New_meassurments = 1;



		u_rms_buffer = 0;
		u_dc_buffer = 0;
		u_max_buffer = 0;

		i_rms_buffer = 0;

		p_buffer = 0;
		}


Autor tematu
oprawcafotografii
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 35
Posty: 6356
Rejestracja: 29 kwie 2009, 10:11
Lokalizacja: Kraków / Jaworzno / Kopanka

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#15

Post napisał: oprawcafotografii » 28 lip 2024, 18:54

Tu masz dużo lepszy przetwornik, to może mieć znaczenie?

Dodane 1 godzina 22 minuty 47 sekundy:
A jakby tak wyprostować to napięcie i wygładzić przed pomiarem? Jedna dioda i kondensator?
„Największym wrogiem wolności jest najedzony niewolnik.”


atom1477
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 29
Posty: 3780
Rejestracja: 21 kwie 2011, 10:58
Lokalizacja: ::

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#16

Post napisał: atom1477 » 28 lip 2024, 19:16

oprawcafotografii pisze:
28 lip 2024, 18:54
Tu masz dużo lepszy przetwornik, to może mieć znaczenie?
Na AVR też mierzyło całkiem dokładnie ale program jest bardzo stary i nie pamiętam gdzie (a kto wie czy nie był jeszcze w BASCOMie).
Ten program tak naprawdę jest bardzo prosty, tylko na potrzeby procesora bez FPU (a tym bardziej 8-bitowego) musi mieć wiele dodatkowych udziwnień.
oprawcafotografii pisze:
28 lip 2024, 18:54
A jakby tak wyprostować to napięcie i wygładzić przed pomiarem? Jedna dioda i kondensator?
To pomiar będzie bardzo niedokładny. Lepszy już będzie ten program z pierwszego postu, bo on przynajmniej ma "prostownik" idealny (bez spadku napięcia).

Decyzja należy do Ciebie.


atom1477
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 29
Posty: 3780
Rejestracja: 21 kwie 2011, 10:58
Lokalizacja: ::

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#17

Post napisał: atom1477 » 29 lip 2024, 11:15

A, miałem wenę:

Kod: Zaznacz cały

int16_t I1;    //zmierzone wartości chwilowe
int16_t I2;
int16_t I3;
int16_t U1;
int16_t U2;
int16_t U3;

int16_t UI_offset;  //zmierzony offset (napiecie 2.5V z dzielnika napiecia)

int32_t I1_buffer;    //akumulatory wartosci
int32_t I2_buffer;
int32_t I3_buffer;
int32_t U1_buffer;
int32_t U2_buffer;
int32_t U3_buffer;
int32_t P1_buffer;
int32_t P2_buffer;
int32_t P3_buffer;

int32_t I1_buffer_irq_main;    //zapamietywacze do przekazania wartosci do maina
int32_t I2_buffer_irq_main;
int32_t I3_buffer_irq_main;
int32_t U1_buffer_irq_main;
int32_t U2_buffer_irq_main;
int32_t U3_buffer_irq_main;
int32_t P1_buffer_irq_main;
int32_t P2_buffer_irq_main;
int32_t P3_buffer_irq_main;

float I_scaler;    //skalery koncowych wynikow
float U_scaler;

float I1_RMS;    //wartosci koncowe
float I2_RMS;
float I3_RMS;
float U1_RMS;
float U2_RMS;
float U3_RMS;

float P1_;    //moce czynne
float P2_;
float P3_;

float S1_;    //moce pozorne
float S2_;
float S3_;

float E1_;    //liczniki energii czynnej
float E2_;
float E3_;

int main(void)
{
    I_scaler = 1.232;  //to trzeba dopiero ustawic
    U_scaler = 2.22;


      if (New_meassurments != 0)
          {
        	New_meassurments = 0;


        	U1_RMS = U1_buffer_irq_main;
        	U1_RMS = sqrtf(U1_RMS * 0.001) * U_scaler;    //100 - 100V

        	U2_RMS = U2_buffer_irq_main;
        	U2_RMS = sqrtf(U2_RMS * 0.001) * U_scaler;    //100 - 100V

        	U3_RMS = U3_buffer_irq_main;
        	U3_RMS = sqrtf(U3_RMS * 0.001) * U_scaler;    //100 - 100V


        	I1_RMS = I1_buffer_irq_main;
        	I1_RMS = sqrtf(I1_RMS * 0.001) * I_scaler;    //1 - 1A

        	I2_RMS = I2_buffer_irq_main;
        	I2_RMS = sqrtf(I2_RMS * 0.001) * I_scaler;    //1 - 1A

        	I3_RMS = I3_buffer_irq_main;
        	I3_RMS = sqrtf(I3_RMS * 0.001) * I_scaler;    //1 - 1A


          P1_ = P1_buffer_irq_main * 0.001 * I_scaler * U_scaler;    //1 - 1W
          P2_ = P2_buffer_irq_main * 0.001 * I_scaler * U_scaler;
          P3_ = P3_buffer_irq_main * 0.001 * I_scaler * U_scaler;

          S1_ = I1_RMS * U1_RMS;    //1 - 1VA
          S2_ = I2_RMS * U2_RMS;
          S3_ = I3_RMS * U3_RMS;

          if (P1_ > 0)
              E1_ += P1_;    //1 - 1J
          if (P2_ > 0)
              E2_ += P2_;    //1 - 1J
          if (P3_ > 0)
              E3_ += P3_;    //1 - 1J

          LCD(line_1, row_1, U1_RMS);    //tu sobie wyswietlisz albo wyslesz wartosci po UARCie
          }
}



void TIM1_UP_IRQHandler(void)    //Co 125us
{
    static uint8_t Co_mierzyc = 0;
    static uint8_t Licznik_100ms = 0;


    TIM1->SR = 0x0000;    //to zamienic na odpowiednik z AVRa

    Co_mierzyc++;
    Co_mierzyc &= 0x07;

    switch (Co_mierzyc)
    {
        case 0:        //Pomiar UI_offset
            UI_offset = getadc(0);    //Wyjdzie z zakresu -511...511
        
            break;
        case 1:        //Pomiar I1
            I_1 = getadc(1) - UI_offset;    //Wyjdzie z zakresu -511...511
            I1_buffer = I1_buffer + (I_1 * I_1);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)
        
            break;
        case 2:        //Pomiar I2
            I_2 = getadc(2) - UI_offset;    //Wyjdzie z zakresu -511...511
             I2_buffer = I2_buffer + (I_2 * I_2);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)
        
             break;
        case 3:        //Pomiar I3
             I_3 = getadc(3) - UI_offset;    //Wyjdzie z zakresu -511...511
             I3_buffer = I3_buffer + (I_3 * I_3);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)
        
             break;
        case 4:        //Pomiar U1
             U_1 = getadc(4) - UI_offset;    //Wyjdzie z zakresu -511...511
             U1_buffer = U1_buffer + (U_1 * U_1);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)
             P1_buffer = P1_buffer + (I_1 * U_1);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)

             break;
        case 5:        //Pomiar U2
             U_2 = getadc(5) - UI_offset;    //Wyjdzie z zakresu -511...511
             U2_buffer = U2_buffer + (U_2 * U_2);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)
             P2_buffer = P2_buffer + (I_2 * U_2);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)

             break;
        case 6:        //Pomiar U3
             U_3 = getadc(6) - UI_offset;    //Wyjdzie z zakresu -511...511
             U3_buffer = U3_buffer + (U_3 * U_3);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)
             P3_buffer = P3_buffer + (I_3 * U_3);    //Wyjdzie z zakresu -26112100...26112100 (25 bitów)

             break;
        case 7:        //Pomiar U1
             Licznik_100ms++;

             if (Licznik_100ms >= 100)    //Co 100ms
		        {
    	                Licznik_100ms = 0;


		        I1_buffer_irq_main = I1_buffer;
		        I2_buffer_irq_main = I2_buffer;
		        I3_buffer_irq_main = I3_buffer;

		        U1_buffer_irq_main = U1_buffer;
		        U2_buffer_irq_main = U2_buffer;
		        U3_buffer_irq_main = U3_buffer;

		        P1_buffer_irq_main = P1_buffer;
		        P2_buffer_irq_main = P2_buffer;
		        P3_buffer_irq_main = P3_buffer;


		        New_meassurments = 1;


		        I1_buffer = 0;
		        I2_buffer = 0;
		        I3_buffer = 0;

		        U1_buffer = 0;
		        U2_buffer = 0;
		        U3_buffer = 0;

		        P1_buffer = 0;
		        P2_buffer = 0;
		        P3_buffer = 0;
		        }
        
             break;
    }
}
To ciągle niesprawdzony kod, ale już o wiele bliższy docelowego.


Autor tematu
oprawcafotografii
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 35
Posty: 6356
Rejestracja: 29 kwie 2009, 10:11
Lokalizacja: Kraków / Jaworzno / Kopanka

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#18

Post napisał: oprawcafotografii » 29 lip 2024, 15:10

Póki co szukam sposobu na szybszy analogRead();

Normalnie Arduino czyta pin analogowy niecałe 10.000x/s ale da się to zmienić - w poniższym przykładzie wychodzi około 30000x/s.

Kod: Zaznacz cały

#define FASTADC 1

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

int licznik = 0;
float msSTOPER_1 = 0; float msSTOPER_2 = 0;

void setup() 
{ 
  Serial.begin(115200);            //Start serial communication
  Serial.println("START");

  #if FASTADC
  // set prescale to 16
  sbi(ADCSRA,ADPS2) ;
  cbi(ADCSRA,ADPS1) ;
  cbi(ADCSRA,ADPS0) ;
  #endif

}

void loop()

  {

    licznik = 0;
    msSTOPER_1 = micros();

    while (micros() < msSTOPER_1 + 1000000)
      {
        analogRead(1);
        licznik++;
      }

    msSTOPER_2 = micros();

    Serial.print("Licznik: "); Serial.print(licznik); Serial.print(" Czas: "); Serial.println(msSTOPER_2-msSTOPER_1); 

    delay(1000);

  }
„Największym wrogiem wolności jest najedzony niewolnik.”


atom1477
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 29
Posty: 3780
Rejestracja: 21 kwie 2011, 10:58
Lokalizacja: ::

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#19

Post napisał: atom1477 » 29 lip 2024, 15:18

Najlepiej to napisać samemu. Wtedy można zrobić osobne funkcje na wyzwalanie pomiaru i na odczyt.
Czyli takie adc_start i adc_read. Procesor by wtedy nie tracił czasu na czekanie na wynik.


Autor tematu
oprawcafotografii
Lider FORUM (min. 2000)
Lider FORUM (min. 2000)
Posty w temacie: 35
Posty: 6356
Rejestracja: 29 kwie 2009, 10:11
Lokalizacja: Kraków / Jaworzno / Kopanka

Re: Błąd pomiaru prądu przekładnikiem prądowym?

#20

Post napisał: oprawcafotografii » 29 lip 2024, 15:52

Niestety moje umiejętności są zbyt ograniczone żeby samemu ognień wymyślać...
„Największym wrogiem wolności jest najedzony niewolnik.”

ODPOWIEDZ Poprzedni tematNastępny temat

Wróć do „Elektronika ogólna”