Skocz do zawartości

Zakłócenia SCT013 - Arduino


Pomocna odpowiedź

Napisano

Witam

Poproszę o pomoc w temacie.

Do portu analogowego (2) podłączyłem czujnik SCT013. Czujnik ma za zadanie sprawdzać napięcie i w razie wykrycia włączyć diodę plus w przyszłości wysłać SMS.

Program w teorii działa lecz w czasie włączenia Arduino Nano na porcie A2 pojawiają się śmieci które zakłócają pracę programu.

Czy jest sposób na zignorowanie fałszywych sygnałów?

Program zapala diodę i wysyła SMS mimo braku napięcia wykrytego przez czujnik SCT013.

W załączniku zachowanie programu po włączeniu

#include <SoftwareSerial.h>
SoftwareSerial mySerial(9, 10);        // Port TX, RX Do komunikacji z modułem SMS
#include "EmonLib.h"                   // Include Emon Library
EnergyMonitor emon1;                   // Create an instance Klema do wykrywania zamkniecia obwodu


int ledPinRed = 8; //Dioda dniagnostyczna
int a=0;   // zmienna "a" zlicza wystąpienia zamkniętego obwodu jesli =1 wyslij SMS 
int V; //Napiecie
void setup()
{
mySerial.begin(9600);
Serial.begin(9600);
pinMode (ledPinRed, OUTPUT);   

emon1.current(2, 111.1);             // Wykrywa zamkniecia obwodu Port Analogowy 2 kalibracja 111.1

 delay(500);
}

void loop()
{
 float Irms1 = emon1.calcIrms(1480);  // Calculate Irms only

    Serial.print(Irms1*230.0);         // Apparent power
     Serial.println(" ");
     V = Irms1*230;


 if (V >= 150 && a == 0){
     digitalWrite(ledPinRed, HIGH);

     Serial.print("SMS - OBWOD ZAMKNIETY!"); 

 Serial.println("Sending Text...OBWOD ZAMKNIETY!");
 mySerial.print("AT+CMGF=1\r"); // Set the shield to SMS mode
 delay(100);
  mySerial.print("AT+CMGS=\"+48XXXXXXXXXXX\"\r");  
 delay(200);
 mySerial.print("OBWOD ZAMKNIETY!");
 mySerial.print(V);
 mySerial.print(" napiecie");
 mySerial.print("\r"); //the content of the message
 delay(500);
 mySerial.print((char)26);//the ASCII code of the ctrl+z is 26 (required according to the datasheet)
 delay(100);
 mySerial.println();
 Serial.println("Text Sent.");
  delay(500);

 mySerial.println("ATD++48XXXXXXXX;");//dial the number, must include country code
 delay(100);
 mySerial.println();
 a++;
 }  else
 digitalWrite(ledPinRed, LOW);


Serial.print("A ");
Serial.println(a);

}



Na wejściach analogowych procesora nie pojawiają się żadne zakłócenia. Moim zdaniem winny jest sam sposób podłączenia tego czujnika do wejścia ADC, czy możesz pokazać schemat tego fragmentu? Jeżeli dobrze podejrzewam(*), to albo coś tam będziesz musiał zmienić - ale to może nie być wcale proste, albo zmień program na tyle, by po włączeniu pomijał i nie analizował kilku(nastu?) pierwszych pomiarów lub po prostu poczekał kilka sekund (zwykły delay w setup) na stabilizację warunków pracy czujnika.

Wywal do testu całe to wysyłanie na MySerial bo robi to tylko niepotrzebne opóźnienia i wypisuj bez żadnego kombinowania wyniki pomiarów Irms przez Serial. Zobacz po jakim czasie od włączenia zasilania wyniki się stabilizują na sensownej wartości i takie opóźnienie wstaw na początku programu. Wtedy pierwszy pomiar od razu będzie dobry.

Czy po resecie/restarcie procesora (ale bez wyłączania zasilania) pierwsze pomiary też są złe?

* - Ponieważ ten czujnik to zwykły transformator, oddaje sygnał bipolarny a tego ADC nie łyka bezpośrednio. Prawdopodobnie na wejściu wstawiono (wstawiłeś?) prosty układ dodawania składowej stałej oparty o dzielnik rezystorowy z kondensatorem. No i jak to filtr - filtruje, ale kosztem długiego ustalania warunków początkowych a Ty widzisz to jak wartości od czapy bo nikomu nie przyszło do głowy by mierzyć dwa kanały i odejmować tylko założył, że warunki pracy już się ustaliły.

Schemat i biblioteki wiozłem z LINK

Próbowałem z "delay" efekt ten sam.

Po restarcie bez wyłączenia zasilania również to samo.

#include "EmonLib.h"                   // Include Emon Library
EnergyMonitor emon1;                   // Create an instance Klema do wykrywania zamkniecia obwodu


int ledPinRed = 8; //Dioda dniagnostyczna
int V; //Napiecie
void setup()
{

Serial.begin(9600);
pinMode (ledPinRed, OUTPUT);   

emon1.current(2, 111.1);             // Wykrywa zamkniecia obwodu Port Analogowy 2 kalibracja 111.1

 delay(10000); //efekt z delay
}

void loop()
{
 float Irms1 = emon1.calcIrms(1480);  // Calculate Irms only

    Serial.print(Irms1*230.0);         // Apparent power
     Serial.println(" ");
     V = Irms1*230;

}

OK, masz tutaj dwa efekty. Pierwszy to ładowanie kondensatora o którym pisałem. Na szczęście "schemat" pokazuje, że ta stała czasowa nie jest długa. Jest tam 10k/2=5kΩ i 10uF (czy rzeczywiście masz tam 2x10k + 10uF?) co daje tylko 50ms więc po czasie powiedzmy 200-500ms od włączenia napięcie na wejściu ADC powinno być praktycznie ustalone. Gdyby to było tylko to, startowe opóźnienie tego rzędu powinno załatwić sprawę. Niestety następna kaszana leży w samej bibliotece a dokładnie w funkcji calcIrms:

//Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
//  then subtract this - signal is now centered on 0 counts.

   offsetI = (offsetI + (sampleI-offsetI)/1024);
   filteredI = sampleI - offsetI;

Wstawiono tu bardzo wolno narastający filtr dolnoprzepustowy IIR precyzujący wartość średnią pomiarów. Z jednej strony słusznie, bo to uniezależnia działanie biblioteki od dokładności dzielnika rezystorowego i w pewnym sensie wysokości zasilania, ale z drugiej jest właśnie przyczyną efektu powolnego "dociągania" wyników do poprawnego poziomu.

Jaki jest dokładnie to Twoje Arduino? Czy to wersja 3.3V?

Nie mam za bardzo i czasu żeby to rozkminiać, ale o ile dobrze rozumiem biblioteka na początku, w funkcji current() zakłada pewną wartość początkową zmiennej offsetI. Jeżeli nie trafi tutaj dobrze, poprawna wartość tej średniej ustala się właśnie bardzo długo, być może po tysiącach pomiarów ADC. Nie wiem z jakiego powodu połowa zakresu ADC jest złym wyborem początkowym (bo przecież dzielnik 2x10k daje właśnie Vcc/2), ale może w Twoim układzie jest jakoś inaczej..

Najlepiej gdybyś zmierzył napięcie (miernik na zakres 20V DC) na wejściu ADC i przeliczył to na odczyt ADC względem używanego napięcia odniesienia (prawdopodobnie Vcc). W najprostszym wypadku musisz eksperymentalnie zmienić wartość offsetu "zgadywaną" przez bibliotekę w funkcji current() na bardziej poprawną dla Twojego układu. A opóźnienie w setup zostaw na ok. 200-500ms - to moim zdaniem wystarczy by kondensator się naładował do Vcc/2 i nie psuł dodatkowo początku serii.

  • Lubię! 1

Tak Arduino Nano

Tak 2x10k + 10uF

Pomierzę wieczorem

Dzieliłem wartość na 2. Wynik poniżej

Na koniec wstawiłem "0" i zaczyna od 0.00

//Digital low pass filter extracts the 2.5 V or 1.65 V dc offset, 
//  then subtract this - signal is now centered on 0 counts. 

   offsetI = 0; 
   filteredI = sampleI - offsetI;

W sumie działa tak jak chciałem na razie nie rozumiem co dokładnie się stało 🙁

Nie możesz tego wstawić tutaj, bo filtr jest OK i powinien być, nie ogłupiaj go. Ważna jest wartość wstawiana do zmiennej offsetI na starcie, w funkcji current(), którą wołasz w setup. To tam jest "zgadywanie" ile napięcia jest bez sygnału na wejściu ADC i to z tej wartości offsetI "dociąga" do tego co jest naprawdę.

A teraz dlaczego 0? Moim zdaniem coś źle połączyłeś z tymi opornikami. Na kondensatorze 10uF musi być Vcc/2 i biblioteka zakłada właśnie połowę zakresu ADC, a jeśli jest 0V to i startować musisz od offsetI=0. Zerowy offset na wejściu oznacza też, że wszystkie ujemne połówki prądu/napięcia z czujnika nie są widoczne, bo poniżej zera Twój ADC nie mierzy.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...