Arduino mätning av växelspänning 220V. Analoga mätningar med Arduino

Schema hemgjord enhet baserad Arduino Uno, som är designad för att mäta frekvens och spänning vid ett uttag och visa resultaten på 1602A-skärmen. Enheten är mycket lätt att tillverka, tack vare användningen av färdiga ARDUINO modul UNO.

Schematiskt diagram

Indikatorn är en 1602A typ LCD-skärm, den är standard, baserad på HD44780-kontrollern. Beteckningen 1602A betyder egentligen att den står på två rader med 16 tecken per rad.

Grunden för enheten är ARDUINO UNO, det är en relativt billig färdig modul - liten tryckt kretskort, på vilken ATMEGA328-mikrokontrollern är placerad, såväl som all dess "sele" som är nödvändig för dess drift, inklusive en USB-programmerare och strömförsörjning.

Enheten drivs från elnätet och mäter ovanstående parametrar. Strömkällan fungerar samtidigt som en sensor för att få data om frekvens och spänning i det elektriska nätverket. Strömförsörjningen är gjord på basis av en lågeffekt färdig transformator T1, som har två identiska 9V-lindningar AC spänning varje.

Ris. 1. Schematiskt diagram frekvensmätare och spänningsvärde i elnätet, Arduino Uno och 1602A användes.

En lindning tjänar till att ta emot matningsspänning. Växelspänningen från den matas till likriktarbryggan med hjälp av dioderna VD1-VD4. Kondensator C3 jämnar ut krusningarna i den likriktade spänningen.

På C3 visar det sig konstant tryck ca 12V, som går till kontakten för att mata ström till ARDUINO UNO-kortet, till ingången på 5V-spänningsregulatorn på detta kort, som driver hela kortet och H1-indikatorn.

Transformatorns andra sekundärlindning fungerar som en sensor för mätning av kraftnätsparametrar. Växelspänningen från den genom R1 tillförs en pulsformare vid nätfrekvensen, gjord på transistor VT1 enligt en switchkrets. Dessa pulser skickas till digital port D10 på ARDUINO UNO-kortet.

Nätverkets växelspänning mäts med hjälp av en likriktare som använder diod VD5 och kondensator C2. Storleken på växelspänningen i nätverket bestäms av storleken på likspänningen på denna kondensator och, via en justerbar delare på motstånden R4 och R5, tillförs den analoga ingången A1 på ARDUINO UNO-kortet.

Program

C++-programmet med detaljerade kommentarer ges i Tabell 1. För att mäta frekvensen, använd pulseln-funktionen, som mäter i mikrosekunder varaktigheten av den positiva eller negativa flanken av ingångspulsen.

Bord 1.

Ris. 2. Källa program för att mäta frekvens och spänning i elnätet.

Så för att ta reda på perioden måste du lägga till varaktigheten av de positiva och negativa halvcyklerna, och för att ta reda på frekvensen i hertz måste du dividera 1 000 000 med den beräknade perioden.

Att mäta varaktigheten av en period består av två delar, först mäts varaktigheterna för de positiva och negativa halvvågorna i linjerna:

Htime=pulseln(10,HÖG);

Ltime=pulseln(10,LOW);

Sedan beräknas hela perioden på raden:

Ttime=Htime+Ltime ;

Och sedan, beräkna frekvensen i raden:

frekvens=1000000/Ttid;

Spänningsmätprogrammets åtgärd är baserad på att läsa data från den analoga ingången och beräkna mätresultatet. Utgång analog port omvandlar mikrokontroller ADC i digital form. För att få resultatet i voltenheter måste du multiplicera det med 5 (med referensspänningen, det vill säga med mikrokontrollerns matningsspänning) och dividera med 1024.

För att kunna mäta spänningar större än 5V, eller snarare, större än mikrokontrollerns matningsspänning, eftersom den faktiska spänningen vid utgången av 5-voltsstabilisatorn på ARDUINO UNO-kortet kan skilja sig från 5V, och vanligtvis en lite lägre måste du använda konventionella resistiva delare vid ingången. Här är det en spänningsdelare över motstånden R5 och R4.

Dessutom spelar användningen av en transformator en roll, liksom skillnaden mellan värdet på likspänning och växelspänning. Därför läggs den ursprungliga divisionsfaktorn på 0,016 till. Läsning av data från den analoga porten sker i raden:

vout=analogRead(analogInput);

Sedan beräknas den faktiska spänningen med hänsyn till divisionsförhållandet för inspänningsdelaren:

volt=vout*5,0/1024,0/0,016;

På denna rad är siffran 5.0 spänningen vid utgången av stabilisatorn på ARDUINO UNO-kortet. Helst ska det vara 5V, men för exakt arbete Med hjälp av en voltmeter måste denna spänning först mätas.

Anslut en 12V-strömkälla och mät +5V-spänningen vid POWER-kontakten på kortet med en ganska exakt voltmeter. Vad händer, skriv sedan in på den här raden istället för 5.0, till exempel, om det finns 4.85V, kommer linjen att se ut så här:

volt=vout*4,85/1024,0/0,016;

Därefter visas mätresultaten på LCD-skärmen. Spänningen anges i den första raden på displayen och frekvensen i den andra. Måttenheterna indikeras som "V" och "Hz". När det gäller frekvensmätning krävs ingen justering alls. Men för att mäta spänningen måste du kalibrera enheten enligt standarden genom att justera motståndet R5.

Karavkin V. RK-10-17.

Den här artikeln ger ett intressant diagram för dem som gillar att experimentera och Arduino. Det presenterar en enkel digital voltmeter, som säkert kan mäta DC-spänning i intervallet 0 till 30 V. Arduino-kortet i sig kan drivas från en standard 9 V-matning.



Som du vet kan du med den analoga ingången Arduino mäta spänning från 0 till 5 V (med en standardreferensspänning på 5 V). Men detta intervall kan utökas genom att använda en spänningsdelare.


Avdelaren minskar den uppmätta spänningen till en nivå som är acceptabel för den analoga ingången. Därefter beräknar specialskriven kod den faktiska spänningen.



Den analoga sensorn i Arduino känner av spänningen vid den analoga ingången och omvandlar den till digitalt format, uppfattas av mikrokontrollern. TILL analog ingång A0 ansluter vi en spänningsdelare bildad av motstånden R1 (100K) och R2 (10K). Med dessa resistansvärden kan upp till 55 V matas till Arduino, eftersom divisionskoefficienten är I detta fall det visar sig vara 11, så 55V/11=5V. För att vara säker på att mätningarna är säkra för kortet är det bättre att mäta spänningen i området från 0 till 30 V.



Om displayens värden inte stämmer överens med de verifierade voltmetervärdena, använd en digital precisionsmultimeter för att hitta exakta värden R1 och R2. I det här fallet måste du i koden ersätta R1=100000.0 och R2=10000.0 med dina egna värden. Då bör du kontrollera strömförsörjningen genom att mäta spänningen på kortet mellan 5V och GND. Spänningen kan vara 4,95 V. Då behöver du i koden vout = (värde * 5,0) / 1024,0 ersätta 5,0 med 4,95. Det är tillrådligt att använda precisionsmotstånd med ett fel på högst 1%. Observera att spänningar över 55V kan orsaka Arduino-bräda ur funktion!



#omfatta LiquidCrystal lcd(7, 8, 9, 10, 11, 12); int analogInput = 0; float vout = 0,0; float vin = 0,0; float R1 = 100000,0; // motstånd R1 (100K) float R2 = 10000,0; // motstånd R2 (10K) int värde = 0; void setup())( pinMode(analogInput, INPUT); lcd.begin(16, 2); lcd.print("DC VOLTMETER"); ) void loop())( // läs det analoga värdet värde = analogRead(analogInput vout = (värde * 5,0) / 1024,0 vin = vout / (R2/(R1+R2));<0.09) { vin=0.0;// обнуляем нежелательное значение } lcd.setCursor(0, 1); lcd.print("INPUT V= "); lcd.print(vin); delay(500); }


Element som används:


Arduino Uno-bräda
Motstånd 100 KOhm
Motstånd 10 KOhm
100 ohm motstånd
Potentiometer 10 KOhm
LCD-skärm 16×2
  • Handledning

Introduktion

Hej alla! Efter att ha slutfört cykeln på sensorer fanns det olika frågor om att mäta förbrukningsparametrarna för hushållsapparater och inte särskilt elektriska apparater. Vem konsumerar hur mycket, hur man kopplar vad man ska mäta, vilka finesser som finns osv. Det är dags att avslöja alla kort i detta område.
I den här artikelserien kommer vi att titta på ämnet att mäta elparametrar. Det finns faktiskt ett väldigt stort antal av dessa parametrar, som jag gradvis kommer att försöka prata om i små serier.
Hittills är det tre serier planerade:
  • Elmätning.
  • Strömkvalitet.
  • Apparater för mätning av elparametrar.
Under analysprocessen kommer vi att lösa vissa praktiska problem på mikrokontroller tills resultatet är uppnått. Naturligtvis kommer det mesta av den här serien att ägnas åt att mäta växelspänning och kan vara användbar för alla som gillar att styra de elektriska apparaterna i sitt smarta hem.
Utifrån resultatet av hela cykeln kommer vi att ta fram någon sorts smart elmätare med internetuppkoppling. Fullständiga fans av att styra de elektriska apparaterna i sitt smarta hem kan ge all möjlig hjälp med att implementera kommunikationsdelen på en bas, till exempel MajorDomo. Låt oss göra OpenSource till ett bättre smart hem så att säga.
I denna tvådelade serie kommer vi att utforska följande frågor:
  • Anslutning av ström- och spänningssensorer i DC-enheter, såväl som enfasiga och trefasiga AC-kretsar;
  • Mätning av effektiva värden för ström och spänning;
  • Effektfaktormätning;
  • Total, aktiv och reaktiv effekt;
  • Elförbrukning;
Genom att klicka nedan hittar du svaren på de två första frågorna i denna lista. Jag berör medvetet inte frågorna om noggrannhet vid mätning av indikatorer och från den här serien är jag bara nöjd med resultaten som erhållits med en noggrannhet på plus eller minus en bastsko. Jag kommer definitivt att ägna en separat artikel åt detta nummer i den tredje serien.

1. Ansluta sensorer


I den senaste serien om spännings- och strömsensorer pratade jag om typerna av sensorer, men pratade inte om hur man använder dem och var man ska placera dem. Det är dags att fixa det
Anslutning av DC-sensorer
Det är klart att hela serien kommer att ägnas åt AC-system, men låt oss snabbt gå över DC-kretsar, eftersom detta kan vara användbart för oss när vi utvecklar DC-strömförsörjning. Ta till exempel en klassisk PWM buck-omvandlare:


Figur 1. PWM Buck Converter
Vår uppgift är att tillhandahålla en stabiliserad utspänning. Dessutom, baserat på information från strömsensorn, är det möjligt att styra driftsläget för induktor L1, förhindra dess mättnad, och även implementera strömskydd för omvandlaren. Och för att vara ärlig, det finns egentligen inga alternativ för att installera sensorer.
En spänningssensor i form av en resistiv delare R1-R2, som är den enda som kan arbeta med likström, är installerad vid omvandlarens utgång. Som regel har en specialiserad omvandlarmikrokrets en återkopplingsingång och gör allt för att säkerställa att denna ingång (3) har en viss spänningsnivå specificerad i dokumentationen för mikrokretsen. Till exempel 1,25V. Om vår utspänning matchar denna nivå är allt bra - vi applicerar direkt utspänningen på denna ingång. Om inte, ställ in avdelaren. Om vi ​​behöver tillhandahålla en utspänning på 5V, måste delaren ge en divisionsfaktor på 4, det vill säga till exempel R1 = 30k, R2 = 10k.
Strömgivaren är vanligtvis installerad mellan strömförsörjningen och omvandlaren och på chipet. Baserat på potentialskillnaden mellan punkterna 1 och 2, och med en känd resistans för motstånden Rs, är det möjligt att bestämma strömvärdet för strömmen i vår induktor. Att installera en strömsensor mellan källorna och lasten är inte en bra idé, eftersom filterkondensatorn kommer att stängas av av ett motstånd från pulsströmförbrukarna. Att installera ett motstånd i gapet på den gemensamma ledningen bådar inte heller gott - det kommer att finnas två marknivåer som det kommer att vara ett nöje att mixtra med.
Spänningsfallsproblem kan undvikas genom att använda beröringsfria strömsensorer - såsom hallsensorer:


Figur 2. Beröringsfri strömsensor
Det finns dock ett smartare sätt att mäta ström. När allt kommer omkring sjunker spänningen över transistorn på exakt samma sätt och samma ström flyter genom den som induktansen. Följaktligen kan strömvärdet för strömmen också bestämmas av spänningsfallet över den. Ärligt talat, om du tittar på den interna strukturen hos omvandlarchips, till exempel från Texas Instruments, så är den här metoden lika vanlig som de tidigare. Noggrannheten för denna metod är naturligtvis inte den högsta, men det är tillräckligt för att strömbrytaren ska fungera.


Fig 3. Transistor som strömsensor
Vi gör samma sak i andra kretsar med liknande omvandlare, oavsett om det är boostande eller inverterande.
Det är dock nödvändigt att separat nämna transformatorns fram- och tillbakagångsomvandlare.


Figur 4. Anslutning av strömsensorer i flyback-omvandlare
De kan också använda antingen ett externt motstånd eller en transistor i sin roll.
Det är här vi är klara med att koppla sensorer till DC-omvandlare. Har du förslag på andra alternativ kompletterar jag gärna artikeln med dem.
1.2 Anslutning av sensorer till enfas AC-kretsar
I AC-kretsar har vi ett mycket större urval av möjliga sensorer. Låt oss överväga flera alternativ.
Det enklaste är att använda en resistiv spänningsdelare och en strömshunt.


Figur 5. Anslutning av motståndssensorer
Det har dock ett par betydande nackdelar:
För det första kommer vi antingen att tillhandahålla en betydande amplitud av signalen från den aktuella shunten genom att allokera en stor mängd effekt till den, eller så kommer vi att nöja oss med en liten amplitud av signalen och därefter förstärka den. Och för det andra skapar motståndet en potentialskillnad mellan nätverksneutral och enhetsneutral. Om enheten är isolerad spelar det ingen roll, men om enheten har en jordningsterminal riskerar vi att lämnas utan en signal från den aktuella sensorn, eftersom vi kommer att kortsluta den. Det kan vara värt att prova sensorer som fungerar på andra principer.
Till exempel kommer vi att använda ström- och spänningstransformatorer, eller en Halleffektströmsensor och en spänningstransformator. Det finns mycket fler möjligheter att arbeta med utrustning, eftersom den neutrala ledningen inte har några förluster, och viktigast av allt, i båda fallen finns det galvanisk isolering av mätutrustningen, vilket ofta kan vara användbart. Det är dock nödvändigt att ta hänsyn till att transformatorström- och spänningssensorer har en begränsad frekvensgång och om vi vill mäta den harmoniska sammansättningen av distorsioner så är det inte ett faktum att det kommer att fungera.


Figur 6. Anslutning av transformator och beröringsfria ström- och spänningsgivare
1.3 Anslutning av sensorer till flerfas växelströmskretsar
I flerfasnät är vår förmåga att ansluta strömsensorer något mindre. Detta beror på att det inte kommer att vara möjligt att använda en strömshunt alls, eftersom potentialskillnaden mellan fasshuntarna kommer att fluktuera inom hundratals volt och jag känner inte till någon generell styrenhet vars analoga ingångar kan motstå sådant övergrepp.
Naturligtvis finns det ett sätt att använda strömshuntar - för varje kanal behöver du göra en galvaniskt isolerad analog ingång. Men det är mycket lättare och mer pålitligt att använda andra sensorer.
I min kvalitetsanalysator använder jag resistiva spänningsdelare och fjärrstyrda halleffektströmsensorer.

Figur 7. Strömgivare i ett trefasnät
Som du kan se på bilden använder vi en fyrtrådsanslutning. Naturligtvis kan du istället för Hall-effektströmsensorer använda strömtransformatorer eller Rogowski-slingor.
Istället för resistiva delare kan spänningstransformatorer användas, både för fyrtrådiga och tretrådiga system.
I det senare fallet är spänningstransformatorernas primärlindningar anslutna med en triangel, och sekundärlindningarna med en stjärna, vars gemensamma punkt är den gemensamma punkten för mätkretsen


Figur 8.Användning av spänningstransformatorer i ett trefasnät

2 RMS-värde för ström och spänning


Det är dags att lösa problemet med att mäta våra signaler. Av praktisk betydelse för oss är först och främst det effektiva värdet av ström och spänning.
Låt mig påminna dig om utrustningen från serien om sensorer. Med hjälp av ADC på vår mikrokontroller kommer vi att registrera det momentana spänningsvärdet med jämna mellanrum. Under mätperioden kommer vi alltså att ha en rad data om nivån på det momentana spänningsvärdet (för ström är allt liknande).


Figur 9. Serie av momentana spänningsvärden
Vår uppgift är att beräkna det effektiva värdet. Låt oss först använda integralformeln:
(1)
I ett digitalt system måste vi begränsa oss till ett visst kvantum av tid, så vi går vidare till summan:
(2)
Var är samplingsperioden för vår signal, och är antalet sampel under mätperioden. Någonstans här i videon börjar jag prata strunt om områdens jämlikhet. Jag borde ha sovit lite den dagen. =)
I MSP430FE4252 mikrokontroller, som används i enfas Mercury elmätare, görs 4096 räkningar under en mätperiod på 1, 2 eller 4 sekunder. Vi kommer att förlita oss på T=1c och N=4096 i det följande. Dessutom kommer 4096 punkter per sekund att tillåta oss att använda snabba Fourier-transformeringsalgoritmer för att bestämma övertonsspektrumet upp till den 40:e övertonen, som krävs av GOST. Men mer om det i nästa avsnitt.
Låt oss skissa på en algoritm för vårt program. Vi måste säkerställa en stabil lansering av ADC var 1/8192 sekund, eftersom vi har två kanaler och vi kommer att mäta dessa data omväxlande. För att göra detta, ställ in en timer och avbrottssignalen kommer automatiskt att starta om ADC:n. Alla ADC:er kan göra detta.
Vi kommer att skriva det framtida programmet på arduino, eftersom många har det till hands. För närvarande är vårt intresse rent akademiskt.
Med en systemkvartsfrekvens på 16 MHz och en 8-bitars timer (så att livet inte ser ut som honung), måste vi se till att alla timeravbrott fungerar med en frekvens på 8192 Hz.
Vi är ledsna över att 16 MHz inte delas så mycket som vi behöver och den slutliga arbetsfrekvensen för timern är 8198 Hz. Vi blundar för felet på 0,04% och läser fortfarande 4096 prover per kanal.
Vi är ledsna att bräddavbrottet i arduino är upptaget med att beräkna tid (ansvarig för millis och fördröjning, så det kommer att sluta fungera normalt), så vi använder jämförelseavbrottet.
Och vi inser plötsligt att signalen som kommer till oss är bipolär och att msp430fe4252 klarar den perfekt. Vi nöjer oss med en unipolär ADC, så vi sätter ihop en enkel bipolär till unipolär signalomvandlare med hjälp av en operationsförstärkare:


Fig 10. Bipolär till unipolär signalomvandlare
Dessutom är vår uppgift att säkerställa att vår sinusform oscillerar i förhållande till halva referensspänningen - då kommer vi antingen subtrahera halva intervallet eller aktivera alternativet i ADC-inställningarna och få signerade värden.
Arduino har en 10-bitars ADC, så vi kommer att subtrahera hälften från det osignerade resultatet i intervallet 0-1023 och få -512-511.
Vi kontrollerar modellen monterad i LTSpiceIV och ser till att allt fungerar som det ska. I videomaterialet verifierar vi detta ytterligare experimentellt.


Figur 11. Simuleringsresultat. Grönt är källsignalen, blått är utsignalen.

Skiss för Arduino för en kanal

void setup() ( autoadcsetup(); DDRD |=(1<

Programmet är skrivet i miljön Arduino IDE för ATmega1280 mikrokontroller. På mitt felsökningskort dirigeras de första 8 kanalerna för kortets interna behov, så ADC8-kanalen används. Det är möjligt att använda den här skissen för en tavla med ATmega168, men du måste välja rätt kanal.
Inne i avbrotten förvränger vi ett par servicestift för att tydligt se den fungerande digitaliseringsfrekvensen.
Några ord om varifrån koefficienten 102 kom. Vid första starten tillfördes en signal med olika amplituder från generatorn, det effektiva spänningsvärdet avlästes från oscilloskopet och det beräknade värdet i absoluta ADC-enheter togs från konsolen. .

Umax, V Urms, B Räknat
3 2,08 212
2,5 1,73 176
2 1,38 141
1,5 1,03 106
1 0,684 71
0,5 0,358 36
0,25 0,179 19

Genom att dividera värdena i den tredje kolumnen med värdena för den andra får vi ett genomsnitt på 102. Detta kommer att vara vår "kalibrering" koefficient. Du kan dock märka att när spänningen minskar så sjunker noggrannheten kraftigt. Detta beror på den låga känsligheten hos vår ADC. Faktum är att 10 siffror för korrekta beräkningar är katastrofalt litet, och om det är fullt möjligt att mäta spänningen i ett uttag på det här sättet, kommer det att vara ett brott mot metrologin att använda en 10-bitars ADC för att mäta strömmen som förbrukas av lasten .

Vid det här laget tar vi en paus. I nästa del kommer vi att överväga de andra tre frågorna i den här serien och kommer smidigt att gå vidare till att skapa själva enheten.

Du hittar den presenterade firmwaren, såväl som annan firmware för denna serie (eftersom jag filmar videomaterial snabbare än jag förbereder artiklar) i arkivet på GitHub.

Om du är mycket orolig för förbrukningen av elektrisk energi och verkligen vill lista ut den skyldige, är det här din dag. Vi kommer att montera en strömsensor och skriva enkel logik för att bearbeta ingångsvärdena för att omvandla värdena till kilowatt/timme.

För montering använde jag ett Arduino nanokort (ingen hindrar dig från att använda samma kod för ESP- eller STM-kort), LCD-skärm, 56 Ohm motstånd, 100 kOhm motstånd, 10 uF kondensator, CT-strömsensor - Talema AC103 (med nominellt mått 30A och max 75A).

Vad är en strömsensor?


Strömgivaren är en magnetisk krets med ett gap och en kompensationslindning, samt en inbyggd Hall-givare och styrkort. Hall-sensorn placeras i gapet i magnetkretsen och reagerar på magnetfältet som skapas av spolen. Ju starkare magnetfältstyrkan är, desto starkare producerar Hall-sensorn en signal som förstärks av styrkortet.
Strömgivare finns för mätning av växelström och likström. Vår - CT-Talema AC103 - för alternerande.

Låt oss montera vår enhet enligt diagrammet:


LCD-skärmen har redan stift för att ansluta våra analoga portar för signalmätning - och det är bekvämt.
Den enda fasingångskabeln måste föras genom strömsensorn pga Ofta når inte all spänning den neutrala ledningen - en del kan gå igenom jordning.


Glöm inte att vi behöver kalibrera belastningsmotståndet R3. Beräkningsformel R = V / I - R = 2,5 / 0,042 = 59,5 Ohm där 2,5 är referensspänningen på kortet, och 42mA är kortets förbrukning. Därför accepterar vi det närmaste motståndet i nominellt värde - 56 Ohm.
För att dela nätspänningen till referensen 5/2 måste du installera två identiska motstånd R1 och R2.

Allt som återstår är att ladda upp exempelkoden till Arduino:

//Michael Klements //The DIY Life //27 oktober 2014 #inkludera int currentPin = 1; //Tilldela CT-ingång till stift 1 dubbelkilo = 0; int peakPower = 0; LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Tilldela LCD-skärmstift, enligt kraven på LCD-skärmen void setup() ( lcd.begin(16,2); // kolumner, rader. använd 16,2 för en 16x2 LCD, etc. lcd.clear(); lcd .setCursor(0,0); // ställ in markören på kolumn 0, rad 0 (den första raden) lcd.print("Kör" ) void loop() ( int ström = 0; int maxström = 0; int minström = 1000 ; för (int i=0 ; i<=200 ; i++) //Monitors and logs the current input for 200 cycles to determine max and min current { current = analogRead(currentPin); //Reads current input and records maximum and minimum current if(current >= maxström) maxström = ström; annat om (aktuell<= minCurrent) minCurrent = current; } if (maxCurrent <= 517) { maxCurrent = 516; } double RMSCurrent = ((maxCurrent - 516)*0.707)/11.8337; //Calculates RMS current based on maximum value int RMSPower = 220*RMSCurrent; //Calculates RMS Power Assuming Voltage 220VAC, change to 110VAC accordingly if (RMSPower >peakPower) ( peakPower = RMSPower; ) kilos = kilos + (RMSPower * (2.05/60/60/1000)); //Beräkna använda kilowattimmars fördröjning (2000); lcd.clear(); lcd.setCursor(0,0); // Visar all aktuell data lcd.print(RMSCurrent); lcd.print("A"); lcd.setCursor(10,0); lcd.print(RMSPower); lcd.print("W"); lcd.setCursor(0,1); lcd.print(kilos); lcd.print("kWh"); lcd.setCursor(10,1); lcd.print(peakPower); lcd.print("W"); )

Den sista touchen av vår installation kommer att vara kalibrering. Det är bäst att utföra det med en referensbelastning med känd ström påslagen. Kraftfulla glödlampor är väl lämpade för detta. Låt oss ta en 100 Watt lampa. Vi slår på tavlan och beräknar korrektionsfaktorn:
Dubbel RMSCurrent = ((maxCurrent - 516) * 0,707) /11,8337 där 11,8337 är den valda koefficienten för att kompensera för avvikelser i mätningar.

Analoga ingångar på Arduino-kortet.

Arduino UNO-kortet innehåller 6 analoga ingångar designade för att mäta spänningssignaler. Det skulle vara mer korrekt att säga att kortets 6 stift kan fungera i både diskret utgång och analog ingångsläge.

Dessa stift är numrerade 14 till 19. De är initialt konfigurerade som analoga ingångar och kan nås med namnen A0-A5. De kan konfigureras till diskret utgångsläge när som helst.

pinMode(A3, OUTPUT); // ställa in det diskreta utgångsläget för A3
digitalWrite(A3, LÅG); // inställningsutgång A3 låg

För att återgå till analogt ingångsläge:

pinMode(A3, INPUT); // ställa in det analoga ingångsläget för A3

Analoga ingångar och pull-up motstånd.

Pull-up-motstånd är anslutna till de analoga ingångsstiften, såväl som till de diskreta stiften. Dessa motstånd slås på med kommandot

digitalWrite(A3, HIGH); // slå på pull-up-motståndet till ingång A3

Kommandot måste tillämpas på ett stift som är konfigurerat i inmatningsläge.

Man måste komma ihåg att motståndet kan påverka nivån på den analoga insignalen. Strömmen från 5V-strömförsörjningen, genom pull-up-motståndet, kommer att orsaka ett spänningsfall över signalkällans interna motstånd. Så det är bättre att koppla bort motståndet.

Analog-till-digital-omvandlare av Arduino-kort.

Själva spänningsmätningen vid ingångarna utförs av en analog-till-digital-omvandlare (ADC) med omkopplare för 6 kanaler. ADC:n har en upplösning på 10 bitar, vilket motsvarar koden vid omvandlarens utgång 0...1023. Mätfelet är inte mer än 2 enheter av den minst signifikanta siffran.

För att bibehålla maximal noggrannhet (10 bitar) är det nödvändigt att signalkällans inre resistans inte överstiger 10 kOhm. Detta krav är särskilt viktigt när man använder motståndsdelare anslutna till kortets analoga ingångar. Resistansen hos delarmotstånden får inte vara för hög.

Analog ingångsmjukvarufunktioner.

int analogRead(port)

Läser spänningsvärdet vid den angivna analoga ingången. Ingångsspänningen sträcker sig från 0 till nivån för referensspänningen (ofta 5 V) omvandlas till en kod från 0 till 1023.

Med en referensspänning på 5 V är upplösningen 5 V / 1024 = 4,88 mV.

Omvandlingen tar cirka 100 μs.

int inputCod; // ingångsspänningskod
float inputVoltage; // ingångsspänning i V

inputCod= analogRead(A3); // avläser spänning på ingång A3
inputVoltage= ((float)inputCod * 5. / 1024.); // konvertering av kod till spänning (V)

void analogReference(typ)

Ställer in referensspänningen för ADC. Den definierar den maximala analoga inspänningen som ADC:n korrekt kan omvandla. Värdet på referensspänningen bestämmer också omvandlingsfaktorn för kod till spänning:

Ingångsspänning = ADC-kod * referensspänning / 1024.

Typargumentet kan ha följande värden:

  • DEFAULT – referensspänningen är lika med styrenhetens matningsspänning (5 V eller 3,3 V). För Arduino UNO R3 – 5 V.
  • INTERN – intern referensspänning 1,1 V för kort med ATmega168 och ATmega328 styrenheter, för ATmega8 – 2,56 V.
  • INTERNAL1V1 – intern 1,1 V referensspänning för Arduino Mega-kontroller.
  • INTERNAL2V56 – intern 2,56 V referensspänning för Arduino Mega-kontroller.
  • EXTERN – extern referensspänningskälla, ansluten till AREF-ingången.

analogReference(INTERNAL); // referensspänningen är 1,1 V

Tvåkanals voltmeter på Arduino.

Som ett exempel på att använda analoga ingångsfunktioner, låt oss skapa ett projekt för en enkel digital voltmeter på Arduino. Enheten måste mäta spänningar vid två analoga ingångar på kortet och överföra de uppmätta värdena till datorn via en seriell port. Med detta projekt som exempel kommer jag att visa principerna för att skapa enkla mät- och informationsinsamlingssystem.

Låt oss bestämma att voltmetern ska mäta spänningen inom intervallet minst 0...20 V och utveckla en krets för att ansluta voltmeteringångarna till Arduino UNO-kortet.

Om vi ​​ställer in referensspänningen till 5 V, så kommer de analoga ingångarna på kortet att mäta spänningen inom 0...5 V. Och vi behöver minst 0...20 V. Det betyder att vi måste använda en spänningsdelare.

Spänningen vid ingången och utgången av delaren är relaterad av relationen:

Uoutput = (Uinput / (R1 + R2)) * R2

Överföringsförhållande:

K = Uoutput / Uinput = R2 / (R1 + R2)

Vi behöver ett överföringsförhållande på 1/4 (20 V * 1/4 = 5 V).

För att bibehålla maximal noggrannhet (10 bitar) är det nödvändigt att signalkällans inre resistans inte överstiger 10 kOhm. Därför väljer vi motstånd R2 lika med 4,22 kOhm. Vi beräknar resistansen för motståndet R1.

0,25 = 4,22 / (R1 + 4,22)
R1 = 4,22 / 0,25 – 4,22 = 12,66 kOhm

Jag hittade motstånd med ett motstånd på 15 kOhm med det närmaste värdet. Med motstånd R1 = 15 kOhm och R2 = 4,22:

5 / (4,22 / (15 + 4,22)) = 22,77 V.

Den Arduino-baserade voltmeterkretsen kommer att se ut så här.

Två spänningsdelare är anslutna till analoga ingångar A0 och A1. Kondensatorerna C1 och C2 bildar tillsammans med delningsmotstånd lågpassfilter som tar bort högfrekvent brus från signalerna.

Jag monterade den här kretsen på en brödbräda.

Jag kopplade den första ingången på voltmetern till en reglerad strömkälla och den andra till 3,3 V-strömförsörjningen på Arduino-kortet. För att övervaka spänningen kopplade jag en voltmeter till den första ingången. Allt som återstår är att skriva programmet.

Ett program för att mäta spänning med ett Arduino-kort.

Algoritmen är enkel. Nödvändig:

  • läs ADC-koden två gånger per sekund;
  • omvandla den till spänning;
  • skicka uppmätta värden via seriell port till en dator;
  • Arduino IDE-portmonitorprogrammet visar de erhållna spänningsvärdena på datorskärmen.

Jag ger dig en komplett skiss av programmet direkt.

// spänningsmätningsprogram
// på analoga ingångar A0 och A1

#omfatta

mätperiod tid
#define R1 15. // motståndet hos motståndet R1
#define R2 4.22 // motstånd för motstånd R2


flyta u1, u2; // uppmätta spänningar

void setup() (
Serial.begin(9600); //

MsTimer2::start(); // avbryta aktivera
}

void loop() (

// period 500 ms
if (timeCount >= MEASURE_PERIOD) (
timeCount= 0;

//

// läsa kanal 2-kod och konvertera till spänning
u2= ((float)analogRead(A1)) * 5. / 1024. / R2 * (R1 + R2);

// dataöverföring via seriell port
Serial.print("U1 = "); Serial.print(u1, 2);
Serial.print(" U2 = "); Serial.println(u2, 2);
}
}

// avbryta bearbetning 1 ms
void timerInterrupt() (
timeCount++;
}

Låt mig förklara raden där ADC-koden omvandlas till spänning:

// läsa kanal 1-kod och konvertera till spänning
u1= ((float)analogRead(A0)) * 5. / 1024. / R2 * (R1 + R2);

  • ADC-koden läses: analogRead(A0) .
  • Explicit konverterad till flyttalsformat: (flytande) .
  • Omvandlat till spänning på den analoga ingången: * 5. / 1024. Punkten i slutet av siffrorna indikerar att detta är ett flyttal.
  • Delningsöverföringskoefficienten beaktas: / R2 * (R1 + R2).

Låt oss ladda programmet till kortet och starta serieportmonitorn.

Två löpande staplar visar värdena för de uppmätta spänningarna. Allt fungerar.

Mätning av det genomsnittliga signalvärdet.

Låt oss ansluta den första kanalen i vår voltmeter till en spänningskälla med hög rippelnivå. Vi kommer att se den här bilden på monitorn.

Spänningsvärdena för den första kanalen på skärmen rycker och hoppar konstant. Och avläsningarna av kontrollvoltmetern är ganska stabila. Detta beror på att referensvoltmetern mäter signalens medelvärde, medan Arduino-kortet läser individuella sampel var 500:e ms. Naturligtvis faller ögonblicket som ADC läser vid olika punkter i signalen. Och vid en hög nivå av pulsationer är amplituden vid dessa punkter annorlunda.

Dessutom, om signalen läses i separata glesa sampel, kan eventuellt impulsbrus introducera ett signifikant fel i mätningen.

Lösningen är att ta flera frekventa prover och medelvärdet av det uppmätta värdet. För detta:

  • i avbrottshanteraren läser vi ADC-koden och summerar den med föregående sampel;
  • räkna medelvärdesberäkningstiden (antal medelvärdesbildande prover);
  • när det angivna antalet sampel har uppnåtts sparar vi det totala värdet av ADC-koderna;
  • För att få medelvärdet, dividera summan av ADC-koder med antalet medelvärdesbildande sampel.

Problem från en lärobok i matematik i årskurs 8. Här är en skiss av programmet, en två-kanals medelvärdesvoltmeter.

// mellanspänningsmätningsprogram
// på analoga ingångar A0 och A1

#omfatta

#define MEASURE_PERIOD 500 // mätperiod tid
#define R1 15. // motståndet hos motståndet R1
#define R2 4.22 // motstånd för motstånd R2

int timeCount; // tidsräknare
lång summaU1, sumU2; // variabler för att summera ADC-koder
lång medelvärdeU1, medelvärdeU2; // summan av ADC-koder (medelvärde * 500)
boolesk flaggaKlar; // indikator på beredskap för mätdata

void setup() (
Serial.begin(9600); // initiera porten, hastighet 9600
MsTimer2::set(1, timerInterupt); // timeravbrott, period 1 ms
MsTimer2::start(); // avbryta aktivera
}

void loop() (

if (flagReady == sant) (
flagReady= false;
// omvandling till spänning och överföring till dator
Serial.print("U1 = ");
Serial.print((float)avarageU1 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
Serial.print(" U2 = ");
Serial.println((float)avarageU2 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
}
}

// avbryta bearbetning 1 ms
void timerInterrupt() (

timeCount++; // +1 genomsnittlig provräknare
sumU1+= analogRead(A0); // summera ADC-koder
sumU2+= analogRead(A1); // summera ADC-koder

// kontrollera antalet medelvärdesberäkningar
if (timeCount >= MEASURE_PERIOD) (
timeCount= 0;
medelU1= summaU1; // medelvärde överbelastning
medelU2= summaU2; // medelvärde överbelastning
sumU1= 0;
summaU2= 0;
flagReady= sant; // teckenmätresultatet är klart
}
}

I formeln för att konvertera ADC-koden till spänning lades /500 till - antalet prover. Ladda, starta portmonitorn (Cntr+Shift+M).

Nu, även med en betydande nivå av pulsering, ändras avläsningarna med hundradelar. Detta beror bara på att spänningen inte är stabiliserad.

Antalet prover måste väljas med hänsyn till:

  • antalet prover bestämmer mättiden;
  • Ju större antal prover, desto mindre blir interferensen.

Huvudkällan till störningar i analoga signaler är 50 Hz-nätverket. Därför är det tillrådligt att välja en medelvärdestid som är en multipel av 10 ms – halvcykeltiden för ett 50 Hz-nätverk.

Optimering av beräkningar.

Flyttalsberäkningar förbrukar helt enkelt resurserna hos en 8-bitars mikrokontroller. Alla flyttalsoperationer kräver mantissavnormalisering, fixpunktsoperation, mantissnormalisering, orderkorrigering... Och alla operationer med 32-bitars tal. Därför är det nödvändigt att minimera användningen av flyttalsberäkningar. Jag ska berätta hur du gör detta i de följande lektionerna, men låt oss åtminstone optimera våra beräkningar. Effekten blir betydande.

I vårt program skrivs omvandlingen av ADC-koden till spänning enligt följande:

(flytande)medelvärdeU1 / 500. * 5. / 1024. / R2 * (R1 + R2)

Det finns så många beräkningar här, alla med flyttal. Men de flesta av beräkningarna är operationer med konstanter. En del av raden:

/ 500. * 5. / 1024. / R2 * (R1 + R2)

(float)avarageU1 * 0,00004447756

Smarta kompilatorer känner själva igen beräkningar med konstanter och beräknar dem i kompileringsstadiet. Jag har en fråga om hur smart Andruinos kompilator är. Jag bestämde mig för att kolla upp det.

Jag skrev ett kort program. Den utför en cykel på 10 000 omgångar och sänder sedan exekveringstiden för dessa 10 000 cykler till datorn. De där. det låter dig se exekveringstiden för operationer placerade i slingans kropp.

// beräkningsoptimeringskontroll

int x= 876;
flyta y;
osignerad int count;
unsigned long timeCurrent, timePrev;

void setup() (
Serial.begin(9600);
}

void loop() (
räkna++;
// y= (flytande)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);
// y= (flytande)x * 0,00004447756 ;

if (antal >= 10 000) (
antal= 0;
timeCurrent= millis();
Serial.println(timeCurrent - timePrev);
timePrev= timeCurrent;
}
}

I det första alternativet, när flyttalsoperationer i slingan kommenteras och inte exekveras, gav programmet ett resultat på 34 ms.

De där. 10 000 tomma slingor är klara på 34 ms.

Sedan öppnade jag raden:

y= (flytande)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);

upprepar våra beräkningar. Resultat av 10 000 pass på 922 ms eller

(922 – 34) / 10 000 = 88,8 µs.

De där. denna rad med flyttalsberäkningar tar 89 µs att slutföra. Jag trodde att det skulle bli fler.

Nu stängde jag den här raden med en kommentar och öppnade nästa, multiplicerade med en förberäknad konstant:

y= (flytande)x * 0,00004447756;

Resultat av 10 000 pass på 166 ms eller

(166 – 34) / 10 000 = 13,2 µs.

Underbart resultat. Vi sparade 75,6 μs per linje. Vi klarade det nästan 7 gånger snabbare. Vi har 2 sådana rader Men det kan finnas mycket fler av dem i programmet.

Slutsats - beräkningar med konstanter måste göras själv på en miniräknare och användas i program som färdiga koefficienter. Arduino-kompilatorn kommer inte att beräkna dem vid kompileringsstadiet. I vårt fall bör vi göra så här:

#define ADC_U_COEFF 0,00004447756 // omvandlingsfaktor av ADC-kod till spänning

Serial.print((float)avarageU1 * ADC_U_COEFF, 2);

Det optimala alternativet för prestanda är att överföra ADC-koden till datorn, och tillsammans med det alla flyttalsberäkningar. I det här fallet måste datorn ta emot data specialiserat program. Portmonitorn från Arduino IDE kommer inte att fungera.

Jag kommer att prata om andra sätt att optimera Arduino-program i framtida lektioner efter behov. Men utan att lösa detta problem är det omöjligt att utveckla komplexa program på en 8-bitars mikrokontroller.

Ytterligare en lektion har dykt upp på sajten (