
O programu
Program může být ve spolupráci se serverem MyPower.CZ ideálním pomocníkem pro člověka, který se vyzná v elektrooboru, dokáže si najít odpovídající proudové senzory, dokáže si spočítat odpovídající odporové děliče, dokáže si libovolné veličiny převést na rozsah 0-5V a takto uzpůsobené senzory připojit k analogovým pinům arduina.
Pro zprovoznění stačí stáhnout zdrojový kód uvedený níže, otevřít ho v Arduino IDE, nastavit základní parametry a provést upload programu do Arduina. Arduino je tímto připraveno pro odesílání hodnot na MyPower.CZ, kde se z těchto dat dají realizovat libovolné další výstupy, například grafy, statistiky výroby/spotřeby, přepočty, prognózy, odhady, grafické přehledy a podobně.
K jedinečné identifikaci vašeho měření slouží jedinečný název měření, který se v programu nastavuje jako parametr FVEID. Toto FVEID je nutno dohodnout například napsáním soukromé zprávy (mě), nebo zasláním mailu na info@mypower.cz. FVEID bude přiděleno, měření i na straně serveru nastaveno.
Pak můžete vše u vás zapojit a poté sdělit co je k jakému analogovému vstupu připojeno a jaký to má rozsah, tedy co znamená 0V a co znamená 5V. Například 0V = -30 ampér, 5V = 30 ampér, 2.5V = 0 ampér a tak dále.
Podporovaný hardware
Program po kompilaci zabírá kolem 19kB místa v paměti arduina.
Program je vhodný pro použití v kombinaci s Ethernet Shieldem s
Arduino Uno (max 6 analogových vstupů),
Arduino Fio (max 8 analogových vstupů),
Arduino Micro (max 12 analogových vstupů),
Arduino Leonardo (max 12 analogových vstupů),
Arduino Mega a vyšší (max 16 analogových vstupů),
nebo
Arduino Ethernet (max 6 analogových vstupů), bez nutnosti použití Ethernet Shieldu.
Zdrojový kód programu
Zdrojový kód programu je níže nebo ke stažení v příloze.
Kód: Vybrat vše
#include <SPI.h>
#include <Ethernet.h>
#include <utility/w5100.h>
// ---------------------------------------------------
const int liveLedPin = 7;
const int sendInterval = 120; // sec
const int sendRetry = 30; // sec
const int maxErrors = 3;
const char MPWfveid[] = "mojefve";
const char MPWhost[] = "log.mypower.cz";
byte NETmac[] = { 0xF6, 0x88, 0x00, 0x00, 0x00, 0x01 };
const int serialLog = 1;
// ---------------------------------------------------
byte lxLed=0;
byte lxTime=0;
long lxSeconds=0;
long lxSendIndex=0;
byte lxHttpOk=0;
byte lxHttpErrors=0;
// ---------------------------------------------------
void setup()
{
Serial.begin(9600);
pinMode(liveLedPin, OUTPUT);
SetLiveLed(HIGH);
pinMode(10, OUTPUT);
XLog("MyPower MicroLOG starting.");
digitalWrite(10,HIGH);
XLog("Trying DHCP.");
int xret=Ethernet.begin(NETmac);
W5100.setRetransmissionTime(0x07FF);
W5100.setRetransmissionCount(2);
if (xret == 0) {
XLog("No dhcp.");
FlashError(4);
}
else
{
char xtext[100];
IPAddress xaddr;
xaddr=Ethernet.localIP();
sprintf(xtext,"IP: %d.%d.%d.%d",xaddr[0],xaddr[1],xaddr[2],xaddr[3]);
XLog(xtext);
xaddr=Ethernet.subnetMask();
sprintf(xtext,"MASK: %d.%d.%d.%d",xaddr[0],xaddr[1],xaddr[2],xaddr[3]);
XLog(xtext);
xaddr=Ethernet.gatewayIP();
sprintf(xtext,"GW: %d.%d.%d.%d",xaddr[0],xaddr[1],xaddr[2],xaddr[3]);
XLog(xtext);
xaddr=Ethernet.dnsServerIP();
sprintf(xtext,"DNS: %d.%d.%d.%d",xaddr[0],xaddr[1],xaddr[2],xaddr[3]);
XLog(xtext);
}
XLog("Done.");
}
void loop()
{
FlashLiveLed();
CalculateSeconds();
SendDataToMyPower();
//delay(3000);
}
void softReset() { asm volatile (" jmp 0"); }
void XLog(char * xmsg) { if (serialLog==1) Serial.println(xmsg); }
void XLogRam() { if (serialLog==1) { Serial.print("> RAM:"); Serial.println(freeRam()); } }
void XLog2(char * xmsg,char * xpre) { if (serialLog==1) { Serial.print(xpre);Serial.println(xmsg);} }
void SetLiveLed(byte xs) { digitalWrite(liveLedPin,xs); }
void FlashLiveLed()
{
unsigned long i=((millis()/100)%10);
byte qlxLed=( ((i==1)) ||
((lxHttpOk==2) && ( (i==3) || (i==5) )) )?HIGH:LOW;
if (qlxLed!=lxLed) { digitalWrite(liveLedPin,qlxLed); lxLed=qlxLed; }
}
void CalculateSeconds()
{
byte smx=0x0F;
byte qlxTime=(millis()/1000)&smx;
if (qlxTime!=lxTime) {
lxSeconds+=(lxTime>qlxTime)?(qlxTime+smx-lxTime):(qlxTime-lxTime);
lxTime=qlxTime;
}
}
void SendDataToMyPower()
{
char xtext[200];
int xsi=sendInterval;
int xsiorig=xsi;
int xsr=sendRetry;
if (lxHttpOk==2) xsi=xsr;
if (xsi<30) xsi=30;
long qlxSendIndex=lxSeconds;
if ((lxSendIndex+xsi<=qlxSendIndex) || (lxHttpOk==0))
{
lxHttpOk=2;
lxSendIndex=lxSeconds;
EthernetClient client;
SetLiveLed(HIGH);
XLogRam();
XLog("> Connecting");
if ( (client.connect(MPWhost, 80)) && (client.connected()) )
{
XLog("> Connected");
sprintf(xtext,"GET / HTTP/1.0\r\nHost: %s\r\nUser-Agent: MPWmicrolog\r\nCookie: fveid=%s; ",
MPWhost, MPWfveid);
client.write((byte*)xtext,strlen(xtext));
strcpy(xtext,"AIN=");
boolean xf=false;
char p[10];
for (int xpin=0;xpin<NUM_ANALOG_INPUTS;xpin++) {
if (xf) strcat(xtext,"."); else xf=true;
sprintf(p,"%d",analogRead(xpin));
strcat(xtext,p);
}
client.write((byte*)xtext,strlen(xtext));
strcpy(xtext,"\r\n\r\n");
client.write((byte*)xtext,strlen(xtext));
int lbufpos=0;
boolean ishead=true;
xtext[0]=0;
unsigned long xmstart=millis();
while (client.connected())
{
if (millis()-xmstart>3000) { break; }
if (client.available())
{
byte qbuf[200];
int qlen=client.readBytes((char*)qbuf,sizeof(qbuf)-2);
for (int i=0;i<qlen;i++) {
char c = qbuf[i];
if (c=='\n') {
if (xtext[0]=='\r') ishead=false; else
if (!ishead) ParseHTTPResult(xtext);
lbufpos=0;
xtext[0]=0;
}
else {
if (lbufpos<sizeof(xtext)-2) {
xtext[lbufpos]=c; lbufpos++; xtext[lbufpos]=0;
}
}
}
}
}
if (lbufpos>0) ParseHTTPResult(xtext);
client.stop();
}
if (lxHttpOk==1)
{
XLog("> OK");
lxHttpErrors=0;
sprintf(xtext,"> Waiting (%d seconds) ...",xsiorig);
XLog(xtext);
}
else
{
lxHttpErrors++;
sprintf(xtext,"> ERR (%d/%d)",lxHttpErrors,maxErrors);
XLog(xtext);
if (lxHttpErrors>=maxErrors) FlashError(3);
else
sprintf(xtext,"> Retry after %d seconds ...",xsr);
XLog(xtext);
}
SetLiveLed(LOW);
}
}
void ParseHTTPResult(char * xtext) {
if (strcmp(xtext,"result:OK")==0) lxHttpOk=1;
XLog2(xtext,"# ");
}
void FlashError(byte xcount)
{
char xtext[50];
sprintf(xtext,"Error %d.",xcount);
XLog(xtext);
XLog("Flashing error (10x), then restarting.");
xcount*=2;
for (int i=0;i<10;i++) {
byte x=0;
for (int i=0;i<xcount;i++) {
digitalWrite(liveLedPin,(!((x++)&1))?HIGH:LOW);
delay(250);
}
delay(1000);
}
XLog("Restarting.");
XLog("---");
delay(1000);
softReset();
}
int freeRam()
{
extern unsigned int __heap_start;
extern void *__brkval;
int free_memory;
int stack_here;
if (__brkval == 0)
free_memory = (int) &stack_here - (int) &__heap_start;
else
free_memory = (int) &stack_here - (int) __brkval;
return (free_memory);
}
V programu se dají nastavit následující konstanty:
const int liveLedPin = 7;
Digitální PIN na kterém je připojena informační stavová LED. Ve výchozím stavu je to digitální pin 7. Pin 13 (onboard led) nelze použít kvůli kolizi s ethernetshieldem. Používá také PIN13 a tak se tato led integrovaná na desce arduina stává pro tyto účely nepoužitelnou. Při připojení led doporučuji postupovat podle obrázků uvedených zde, tedy klasika - leddioda + rezistor do serie. Význam stavů leddiody popíšu níže.
const int sendInterval = 120; // sec
Interval v sekundách, po kterém se periodicky odesílají data na MyPower.CZ
const int sendRetry = 30; // sec
Interval v sekundách, po kterém se program znovu pokouší data odeslat v případě předchozího neúspěšného odeslání.
const int maxErrors = 3;
Maximální tolerovaný počet chyb přenosu a pokusů o znovuodeslání. Poté program provede "zdravotní" restart.
const char MPWfveid[] = "mojefve";
Nastavení FVEID - viz informace o získání FVEID výše. Program funguje i bez přiděleného FVEID. Server tak pouze vrací to, co program odesílá a tak je možno i před přidělením FVEID zkontrolovat, zdali vše funguje. Pokud se zobrazí informace ze serveru a stavová informace "> OK", znamená to, že na vaší straně je program připraven a teď už je to pouze na administrátorovi serveru MyPower.CZ až vše nastaví a přidělí vám FVEID, pokud o něho požádáte.
const char MPWhost[] = "log.mypower.cz";
Nastavení logovacího serveru MyPower.CZ
byte NETmac[] = { 0xF6, 0x88, 0x00, 0x00, 0x00, 0x01 };
Nastavení síťové mac adresy. Pokud bude na jedné lokální síti běžet více arduin, je nutno každé jednotce nastavit unikátní mac adresu. Jednoduše poslední číslo nastavte pokaždé různé. Například { 0xF6, 0x88, 0x00, 0x00, 0x00, 0x01 }, { 0xF6, 0x88, 0x00, 0x00, 0x00, 0x02 }, { 0xF6, 0x88, 0x00, 0x00, 0x00, 0x03 } atd.
const int serialLog = 1;
Povolení (1) nebo zakázání (0) vypisování ladících informací do seriové konzoly. Čistě pro účely už nastaveného a rozchozeného měření je možno vypisování ladících informací vypnout. K informaci v jakém stavu se program nachází postačí stavová signalizační LED. Vypnutí (zakázání) vypisování ladících informací do seriové konzoly zrychlí o něco málo běh programu a také zkompilovaný program bude o něco menší.
Připojení k internetu
Pro připojení k internetu připojte arduino pomocí ethernet shieldu standardním ethernetovým kabelem do vašeho routeru/switche. Na switchi/routeru, nebo na síti se musí vyskytovat DHCP server, který programu přidělí parametry sítě, jako IP adresa, maska sítě, DNS server a brána (gateway).
Zdali vaše Arduino odesílá data na MyPower.CZ můžete ověřit zde.
Seriová konzole
Pokud je nastavení serialLog rovno 1, pak dochází k výpisu ladících informací do sériové konzoly. Tu je možno zapnout ikonkou lupy v Arduino IDE a sledovat co program zrovna dělá.
Typický výpis na konzoli může vypadat například takto:
Kód: Vybrat vše
MyPower MicroLOG starting.
Trying DHCP.
IP: 192.168.1.220
MASK: 255.255.255.0
GW: 192.168.1.20
DNS: 192.168.1.100
Done.
> RAM:6332
> Connecting
> Connected
# Nezname FVEID: 'mojefve'
# Pro prideleni FVEID napiste na info@mypower.cz
#
# server:log.mypower.cz
# time:2013-03-27 03:25:28
# fveid:mojefve
# AIN:1023.1023.724.565.481.422.398.382.315.308.294.279.283.282.282.300
# result:OK
> OK
> Waiting (120 seconds) ...
> RAM:6332
> Connecting
> Connected
# Nezname FVEID: 'mojefve'
# Pro prideleni FVEID napiste na info@mypower.cz
#
# server:log.mypower.cz
# time:2013-03-27 03:27:35
# fveid:mojefve
# AIN:1023.1023.704.551.470.410.386.358.304.298.285.270.275.275.273.291
# result:OK
> OK
> Waiting (120 seconds) ...
> RAM:6332
> Connecting
> Connected
# Nezname FVEID: 'mojefve'
# Pro prideleni FVEID napiste na info@mypower.cz
#
# server:log.mypower.cz
# time:2013-03-27 03:29:43
# fveid:mojefve
# AIN:1023.1023.703.549.468.407.383.356.301.296.282.268.272.272.271.289
# result:OK
> OK
> Waiting (120 seconds) ...
V tomto případě znamená níže uvedený výpis informaci ze serveru (jeden typický odesílací cyklus), že nastavené FVEID není zaregistrováno a že se máte ozvat s žádostí o přidělení FVEID. Zároveň server posílá svou identifikaci, tedy že se jedná o log.mypower.cz, posílá aktuální čas na serveru pro kontrolu, posílá FVEID, které program odeslal a také hodnoty všech pinů, které program odeslal. Takto vypadá ukázkový výpis pokud je vše připraveno ke zprovoznění a potvrzeno, že internetové spojení funguje.
Kód: Vybrat vše
> RAM:6332
> Connecting
> Connected
# Nezname FVEID: 'mojefve'
# Pro prideleni FVEID napiste na info@mypower.cz
#
# server:log.mypower.cz
# time:2013-03-27 03:25:28
# fveid:mojefve
# AIN:1023.1023.724.565.481.422.398.382.315.308.294.279.283.282.282.300
# result:OK
> OK
> Waiting (120 seconds) ...
Stavová led
Stavovou led připojte k digitálnímu pinu 7 (dle výchozího nastavení), sériově s rezistorem (D7 -> LED -> REZISTOR -> GND). Inspiraci pro připojení můžete nalézt například na obrázcích na této stránce. Na odkazované stránce je nakresleno připojení k pinu 13, my však diodu pro naše účely připojíme ne k pinu 13, ale k pinu 7 a dle toho také patřičně nastavíme v programu nastavení hodnoty liveLedPin
Kód: Vybrat vše
const int liveLedPin = 7;
Pokud dojde k chybovému stavu, tento je nevratný. Leddioda 10x zopakuje probliknutí chybového stavu a poté program provede restart.

Chybové stavy:
3x pomalejší bliknutí + 1 vteřina pauza.
Nastalo více chyb v přenosu než nastavený maximální počet chyb, program toto hlášení 10x zopakuje a provede restart.
Mnemotechnická pomůcka: 3x protože 3 chyby
4x pomalejší bliknutí + 1 vteřina pauza.
Po startu nebyl nalezen DHCP server, program toto hlášení 10x zopakuje a provede restart.
Mnemotechnická pomůcka: 4x protože D H C P (4 písmena)
Provozní stavy:
1x rychlejší bliknutí opakované každou vteřinu.
Program běží v pořádku, spojení na internet funguje, poslední přenos se zdařil, čeká se na uplynutí časového intervalu pro odeslání dalšího vzorku měření.
3x rychlejší bliknutí opakované každou vteřinu.
Došlo k chybě v přenosu, zatím se program pokouší o opakování přenosu. Pokud se zdaří, přejde se do standardního provozního režimu (1x rychlejší bliknutí) a vynuluje se čítač chyb.
Leddioda trvale svítí
Start programu, nebo komunikace po internetu.
Závěr
Snad bude tento MicroLog k užitku.




Příklad odporového děliče s U_vst <= 52V a U_vyst <=5V. U_vyst připojíme k Arduinu na analogový pin a U_vst například k 24V baterii čímž můžeme s rezevou měřit 24V baterii.

Tip: Vaše měření na MyPower.CZ samostatně?





