Arduino Yun - solpanel övervakningssystem (5 / 8 steg)
Steg 5: SOLPANEL övervakning – ARDUINO skiss
Skriva ett program för Arduino var en ny erfarenhet för mig. Bortskämd av Windows/Linux och även Android som har i princip ingen minnesgräns jag kör mycket snart problem med mycket begränsad kod och variabel utrymme på Arduino styrelser. Den Arduino Yun erbjuder endast 28,627 byte för kod och 2560 byte för globala variabler.
Vad jag lärde mig fort var att jag kan använda koden minne till 99,9%, men om jag använder mer än 60% av minnet för globala variabler skissen var inte längre arbetar tillförlitliga. Jag tror underlaying koden (bootloader,...) kräver lite utrymme int globala variabler minne. Så jag var tvungen att optimera min kod och begränsa användningen av globala variabler som möjligt. För själva koden delade jag den Arduino skissen i flera filer. Jag försökte kommentera koden så bra som möjligt, så det bör vara självförklarande.
spMonitor.ino = attrapp arkivera med beskrivning av den andra filer < br > spMonitor_a_definitions = > innehåller och globala variabler
spMonitor_b_utils = > nyttofunktioner
spMonitor_c_lightsensor = > gränssnitt till TSL2561 ljussensor
spMonitor_x_measurement = > mätfunktioner
spMonitor_y_setup = > Arduino setup-funktionen
spMonitor_z_loop = > Arduino loop funktion
Namnen på filerna följer ett specifikt system. Kompilatorn för skissen kräver att sub-funktioner som används måste deklareras innan de används. Filnamnen är så SKETCHNAME_index_MODUL. Med index får jag filerna skall sammanställas i rätt ordning.
SPMONITOR_A_DEFINITIONS
I den första delen ingår alla externa filer som behövs för olika funktioner.
Wire.h = > i2c kommunikation bibliotek < br > Adafruit_Sensor.h, Adafruit_TSL2561_U.h och pgmspace.h för ljussensorn
EmonLib.h för CT och spänning sensorer
FileIO.h att få tillgång till SD-kortet av Linux delen av styrelsen
YunServer.h och YunClient.h för webbkommunikation
AVR/WDT.h för watchdog genomförandet
Kalibreringsvärden:
/ ** iCal definition för CT 1 (solar) * / < br > #define iCal1 5,7
/ ** iCal definition för CT 2 (nätet) * /
#define iCal2 11,5
/ ** Fas SKIFT definition för spänning (solar) * /
#define pShift1 1.3
/ ** Fas SKIFT definition för spänning (nätet) * /
#define pShift2 6.1
/ ** vCal definition för spänningsmatning * /
#define vCal 255
Dessa värden är avgörande för mätningarna. Dessa värden är beroende på CT sensorer används, toleranser för de begagnade resistorer och kondensatorer och andra saker. För att få dessa värden korrekt, klev jag flera gånger genom guiden kalibrering av OpenEnergyMonitor byggblocket Kalibreringen. Tills du har rätt värden här blir alla dina mätningar mer eller mindre skit! För att möjliggöra kalibrering utan att skriva särskilda script ingår jag en "kalibrering läge" i Android ansökan. När kalibreringen-läget är aktiverat Android-program drar data från Arduino var 10 sekunder och visar detaljer om effektfaktorn, verkliga och påtagliga makt och uppmätt spänning. Kalibreringsvärden kan sedan ändras tills värdena är som förväntat (e.g. effektfaktorn nära 1.o).
De andra globala variablerna är väl kommenterade.
SPMONITOR_B_UTILS
Denna modul innehåller 2 funktioner används för att lagra inspelade värden.
Sträng getTimeStamp() returnerar dagens datum och aktuell tid för systemet. För att få det använder vi funktionen "bro" ".run" att köra ett kommando på Linux sida och ta emot produktionen över "bron".
/ ** Instans till Linino process * / < br > tid;
/ * datum är en befalla lina nytta att få datumet och tid * /
/ * i olika format beroende på parametern ytterligare * /
Time.BEGIN ("datum");
time.addParameter (+ %y, %m, % H: %M %d");
wdt_reset();
Time.Run(); / * kör kommandot * /
Möjligheten att starta kommandon och skript på en Linux-skal utökar funktionerna i Arduino styrelsen. Istället för problem att lägga till komplexa funktioner i begränsade program utrymmet av AVR styrenheten kan de delegeras till den Linux-delen.
void saveData () använder "bro" funktionerna samt skriva insamlade data i en databas, skicka det till en web molntjänst och lagra den för enkel åtkomst på Linux sidan.
Mätningarna görs varje sekund, men värdena lagras endast varje minut. De uppmätta värdena lagras i en ackumulator. Den kod delen
/ ** Ljus värde samlats in sedan senaste spara * /
långa ljus = 0;
om (collCount [2]! = 0) {
ljus = collLight / collCount [2].
}
/ ** Solenergi värde samlas sedan senaste spara * /
dubbel sol = collPower [0] / collCount [0];
/ ** Konsumeras power värde samlats in sedan senaste spara * /
dubbla nackdelar = collPower [1] / collCount [1].
beräknar medelvärdet av mätningarna gjort sedan senaste besparingen av värden.
Den kod delen
Bridge.Put ("L", sträng (ljus));
Bridge.Put ("S", sträng (solar));
Bridge.Put "C", sträng (nackdelar).
lagrar de uppmätta värdena på Linux-processorn med en nyckel/värde struktur. Dessa struktur kan hämtas som en JSON-sträng av enkla ringer "http://IPADDRESS//data/get". (IP-adress är IP-adressen tilldelats den Arduino Yun). Datan ser ut:
{
"värde":
{
"c": "2,56",
"L": "0",
"sv": "219.43",
"cv": "215.85",
"cp": "0.97",
"sa": "100.44",
"ca": "553.57",
"cr": "539.18",
"C": "596.05",
"s": "0.46",
"S": "0.00",
"sp": "0,20",
"l": "0",
"sr": "0.00"
},
"svar": "få"
}
Du kan se de data vi stå med den ovanstående kod delen i denna JSON-sträng.
L, S och C värdet uppdateras varje minut och används för att uppdatera UI i Android app. C, cv, cr... Värdena uppdateras efter varje mätcykeln (~ 1s) och kan användas under kalibrering-läget. De visas också på UI av Android app. Nästa kod del
/ ** Instans till Linino process * /
Processen sqLite;
timeString = getTimeStamp();
timeString.replace (',', '-');
dataString = "sqlite3 /mnt/sda1/s.db" in i s (d, s, c, l) värden (\ ""
+ timeString + "\" "
Sträng (solar) + ""
Sträng (nackdelar) + ""
+ Sträng (ljus) + ");" ";
sqLite.runShellCommand (dataString);
använder funktionen "bro" ".runShellCommand" för att skriva de uppmätta värdena i Sqlite-databasen. Därifrån kan de hämtas över det lokala nätverket med skriptet query.php.
Och den sista kod delen
/ ** Instans till Linino process * /
Processen emonCMS;
dataString = "curl \" http://emoncms.org/api/post?apikey=ENTER_YOUR_OWN_API_KEY_HERE & json = {s: ";
dataString += sträng (solar);
dataString += ", c:";
dataString += sträng (nackdelar);
dataString += ", l:";
dataString += sträng (ljus);
dataString += "} \" ";
emonCMS.runShellCommand (dataString);
använder också funktionen "bro" ".runShellCommand" för att skicka data till en webbtjänst i molnet. Detta moln web service emoncms.org erbjuder (just nu för gratis) möjligheten att lagra sensordata och visualisera dem på webben. Kolla deras tjänst, de drivs av OpenEnergyMonitor!
Jag la ett av visualisering alternativ till på bilderna ovan. Du kan se verklig förbrukning/produktion data i mitt hus i Min sol app för emoncms.org.
SPMONITOR_C_LIGHTSENSOR
Denna modul hanterar ljussensorn. Kommunikationen med ljussensorn sker inom den Adafruit_Sensor och Adafruit_TSL2561_U biblioteken. Dessa bibliotek finns tillgängliga som öppen källkod från Adafruit, tillverkaren av modulen ljussensor.
void configureSensor () initierar funktionen auto utbud av ljussensorn och ställer den integration tid till det högsta värdet.
void readLux () initierar en mätning på modulen ljussensor. För att anpassa till olika ljus intensitet är det nödvändigt att anpassa integration tiden av sensorn. Sensorn är inledningsvis den högsta integration tid som är bäst i svagt ljus. Men om ljuset blir ljusare, sensorn kommer att mätta och det är nödvändigt att byta till en kortare integration tid. Sensorn erbjuder 3 olika integration gånger. Den kod delen
/ * Visa resultatet (ljus mäts i lux) * /
om (event.light) {
/ ** Int värdet läsa från AD conv för solen mätning * /
accLux += event.light;
lightOk ++; / * Öka räknaren av lyckade mätningar * /
om (lightInteg == 1) {/ * vi är på medellång integration tid, prova en högre * /
tsl.setIntegrationTime (TSL2561_INTEGRATIONTIME_402MS); / * 16-bitars data men långsammast omvandlingar * /
lightInteg = 2;
} else om (lightInteg == 0) {/ * vi är på lägsta integration tid, prova en högre * /
tsl.setIntegrationTime (TSL2561_INTEGRATIONTIME_101MS); / * medelhög upplösning och hastighet * /
lightInteg = 1;
}
}
läser ett värde från sensorn. Om sensorn ger ett värde, växlar koden till en högre integration tid.
Men om sensorn är redan mättad, vi sänka integration tiden och försök igen att läsa från sensorn
} annat {
/ * Om event.light = 0 lux sensorn är förmodligen mättad
och några tillförlitliga uppgifter kunde genereras! */
om (lightInteg == 2) {/ * vi är på högsta integration tid, prova en lägre * /
tsl.setIntegrationTime (TSL2561_INTEGRATIONTIME_101MS); / * medelhög upplösning och hastighet * /
wdt_reset();
tsl.getEvent (& event);
om (event.light == 0) {/ * fortfarande mättade? * /
lightInteg = 0;
tsl.setIntegrationTime (TSL2561_INTEGRATIONTIME_13MS); / * snabbt men låg upplösning * /
wdt_reset();
tsl.getEvent (& event);
om (event.light! = 0) {/ * fick ett resultat nu? * /
accLux += event.light;
lightOk ++; / * Öka räknaren av lyckade mätningar * /
}
} annat {
lightInteg = 1;
accLux += event.light;
lightOk ++; / * Öka räknaren av lyckade mätningar * /
}
} else om (lightInteg == 1) {/ * vi är på medellång integration tid, prova en lägre * /
lightInteg = 0;
tsl.setIntegrationTime (TSL2561_INTEGRATIONTIME_13MS); / * snabbt men låg upplösning * /
wdt_reset();
tsl.getEvent (& event);
om (event.light! = 0) {/ * fick ett resultat nu? * /
accLux += event.light;
lightOk ++; / * Öka räknaren av lyckade mätningar * /
}
}
}
Denna loop upprepas 5 gånger att anpassa sig till ändrade ljus.
SPMONITOR_X_MEASUREMENT
Denna modul innehåller CT sensor mätning rutiner. Direkt mätning av ström och spänning är gjort av emonLib biblioteket. EmonLib är ett open source bibliotek som tillhandahålls av OpenEnergyMonitor.
void getCTValues (int index) uppmanar emonLib att inleda mätning av ström, spänning och beräkning av makt och effektfaktor. Parameterindex bestämmer den sensor som bör läsas. index = 0 startar en mätning av CT sensor kopplad till solpanel tråd, 1 börjar en mätning av CT sensor kopplad till den huvudsakliga kraftledningen.
/ * Få mätt strömmen från solpanelen * /
aftonen uppträder Emon [index] .calcVI (20, 2000).
/ ** Mätt makten i W * /
dubbel power = aftonen uppträder emon [index] .realPower;
De insamlade värdena lagras sedan i en ackumulator. Just nu är systemet kunna göra någon mätning runt varje sekund. De värden som lagras i ackumulatorn används för att beräkna ett genomsnitt värderar innan du sparar värdena i databasen, som sker var 60 sekunder.
collPower [index] = collPower [index] + makt;
collCount [index] + = 1;
På natten solpanelen producerar inte makt, men det är med en liten standby nuvarande. Vi eliminera denna standby ström med koden
/ ** Sensor 0 mäter solpanelen, om det är mindre än 20W då de som är standby nuvarande dras av växelriktare * /
om (aftonen uppträder emon [index]. IRMS < 0,55) {
Power = 0,0;
}
Detta sätt vi se till att vi spelar inte in en inte befintliga kraftproduktion under natten.
De uppmätta värdena sparas sedan på Linux sidan med funktionen "Bridge.put" som en nyckel/värde struktur. Nycklarna skapas med hjälp av prefixet s för värden från solar sensorn och prefix c för värden från stambanan sensorn.
Bridge.Put (prefix, sträng (aftonen uppträder emon [index]. IRMS)); Nuvarande
Bridge.Put (prefix + "r", sträng (power)); Verkliga makten
Bridge.Put (prefix + "v", sträng (aftonen uppträder emon [index]. Vrms)); Spänning
Bridge.Put (prefix + "a", sträng (aftonen uppträder emon [index] .apparentPower)); Skenbar effekt
Bridge.Put (prefix + "p", sträng (aftonen uppträder emon [index] .powerFactor)); Effektfaktor
SPMONITOR_Z_LOOP
Detta är huvudloop program. Den är igång hela tiden. Inuti loop funktionen vi millis() för att inleda mätningar och spara värden i specifika frekvenser.
Just nu initieras mätning varje sekund. Detta är möjligt eftersom ljussensorn inte används ännu. När ljussensorn är ansluten har frekvensen av mätningen skall minskas, som rutin för ljus mätning kan ta mer än 2 sekunder värsta fall.
/ ** Faktiska tid i millisekunder sedan början av spMonitor * /
osignerade långa nu = millis();
om (nu - lastMeasure > = measureFreq) {/ * initiera mätning var 1 sekund * /
lastMeasure = nu;
wdt_reset();
/ * Aktivitets-LED * /
digitalWrite (activityLED, hög);
wdt_reset();
/ * Få ljus mätning om en sensor fästas * /
readLux();
/ * Få mätt strömmen från solpanelen * /
getCTValues(0);
/ ** Få mätt strömmen från elnätet * /
getCTValues(1);
/ * Aktivitet ledde bort * /
digitalWrite (activityLED, låg);
}
Denna kod krävs mätning funktioner CT sensorer och ljussensorn. Själva mätcykeln är visualiseras genom en LED monterad på sensorn anslutning sköld.
Följande kod anropar funktionen för att spara värdena i databasen varje minut:
om (nu - lastSave > = 60000) {/ * spara data varje minut * /
lastSave = nu;
wdt_reset();
saveData();
}
Och slutligen har vi en kod del att kommunicera direkt via det lokala nätverket med en PC eller Android-enhet. När jag började med programmet, jag försökte alla kommunikation hanteras detta Arduino nummer, men på grund av minnesbegränsningar insåg jag att detta inte var möjligt. Så i slutet finns det bara en funktion kvar här. Som de flesta kommunikation delar delegeras direkt till det Linux med Arduino styrelsen hanteras endast funktionen status rapport här.
/ * Det finns en ny klient? */
om (client.available()) {
wdt_reset();
/ ** Karaktär håller kommandot som skickades * /
char kommando = client.read();
om (kommandot == "e") {/ * få faktiska inställningar * /
client.Print ("F" + sträng (measureFreq) + "s");
client.println ("V" + sträng (vCal));
client.Print ("C1" + sträng (iCal1, 1));
client.println ("C2" + sträng (iCal2, 1));
}
/ * Stäng anslutning och frigöra resurser. */
wdt_reset();
client.flush();
client.stop();
}
Status kan vara begäran av alla webbläsare eller program genom att helt enkelt ringa http://IPADDRESS/arduino/e
Svaret är
F 1000-TALS V 255
C1 5.7 C2 11,5
F är mätfrekvensen, V är spänningen kalibreringsvärde, C1 och C2 är CT sensor kalibrering värdena.
Denna funktion kommer att användas av Android ansökan för att hitta Arduino enheten i det lokala nätverket.
SPMONITOR_Y_SETUP
Denna rutin anropas en gång efter en återställning av Arduino styrelsen. Den innehåller initiering rutiner för nätverkskommunikation och sensorer 1 – ange porten för aktiviteten LED
/ * Ställ in pinkodsskydd att mata * /
pinMode (activityLED, produktionen);
2 – initiera nätverkskommunikation och tillgång till Linux filsystem.
/ * Initiera brygganslutning * /
Bridge.BEGIN();
/ * Lyssnar efter inkommande anslutning endast från localhost * /
/ * (ingen från det externa nätverket kan ansluta) * /
server.listenOnLocalhost();
Server.BEGIN();
/ * Initiera tillgång till SDcard * /
FileSystem.begin();
3-initieringen av ljus och CT sensorer
/ * Initiera räknare och ackumulatorer * /
collPower [0] = collPower [1] = 0,0;
collCount [0] = collCount [1] = collCount [2] = 0;
/ * Konfigurera YHDC SCT013-000 aktuella sensorer * /
/ * Initiera strömsensor 1 * /
aftonen uppträder Emon [0] .voltage (2, vCal, pShift1); AD2, Vcal = 255, fasförskjutning = 1,3
aftonen uppträder Emon [0] .current (0, iCal1); AD0, Ical = 5.7
/ * Initiera strömsensor 2 * /
aftonen uppträder Emon [1] .voltage (2, vCal, pShift2); AD2, Vcal = 255, fasförskjutning = 6.1
aftonen uppträder Emon [1] .current (1, iCal2); AD1, Ical = 11,5
/ * Få ursprungliga avläsningen till setup lågpassfilter * /
unsigned int jag = 0;
medan (jag < 50) {
/ * PÅ * /
digitalWrite (activityLED, hög);
aftonen uppträder Emon [0] .calcVI (20, 2000).
aftonen uppträder Emon [1] .calcVI (20, 2000).
/ * LEDDE bort * /
digitalWrite (activityLED, låg);
i ++;
}
4 – initiering av timern och vakthund
/ * Initiera kallar getMeasures och saveData varje 5 sekunder/60 sekunder * /
lastMeasure = lastSave = millis();
/ * Aktivera watchdog * /
wdt_enable(WDTO_8S);
När det gäller vakthund, kan du se
wdt_reset();
vanligt i källkoden. Med hjälp av watchdog se jag till att när programmet fastnat någonstans att en återställning av Arduino styrelsen inleds senast efter 8 sekunder. Detta ser till att programmet kan köras oövervakad under lång tid.
Detta avslutar den korta beskrivningen av Arduino källkoden. För att se alla detaljer, kolla in min databas på Github där du kan hitta full källkod.