Každý, kdo programuje a sestavuje dohromady nějaký systém, kde komunikuje navzájem více zařízení, se setká se situací, kdy při nějaké kombinaci dat například z připojených čidel se celý systém nechová korektně. Například některý snímač poskytuje neplatná data, nebo dojde k neočekávané kombinaci dat. Další situací je případ, kdy ladíte vlastní CAN bus HW a nemáte 100 procentní jistotu že čtete správně data, tedy nenastane například overflow přijímacího bufferu. Pak je třeba data kontrolovat na CANu nezávisle.
Pokud se tyto chyby vyskytují velmi sporadicky / v provozu v zásadně na noční směně :-) / a je těžké je zachytit aby se situace mohla analyzovat, není moc praktické se spolehnout na logování CAN sběrnice a zpětnou analýzu. Dat je mnoho a jejich procházení je náročné. Mnohem praktičtější je použít program PP2CAN a CAN skript, který bude například neplatné kombinace dat nebo jejich hodnoty logovat samostatně.
Skript nám může navíc pomoci i v tom, že může například provést restart zařízení nebo jinou akci (odeslat data na CAN) a tím situaci nouzově vyřešit. Nemusíme tak upravovat například program v PLC a neměníme tím tak chování systému. Záleží jen na důvtipu autora skriptu.
V našem příkladu si ukážeme jednoduchý skript, který čte dvě hodnoty, v našem případě nějakého hypotetického tlaku. Pokud obě hodnoty překročí hodnotu 1000, událost se uloží do souboru CSV, který lze snadno importovat například do Excelu.
Tento příklad nám ukáže zejména 2 praktické funkce, které jsou součástí skriptovacího jazyka.
První funkcí je metoda get_value objektu CANovské zprávy, který dovoluje snadno dekódovat data z CAN zprávy zadáním prvního bitu a bitové délky. Data tak nemusejí mít násobek 8 bitů a mohou začínat libovolným bitem a mít libovolnou bitovou délku.
Druhou funkcí je objekt CSV souboru, který dovoluje s těmito soubory snadno pracovat. Ve skriptech jej lze použít jak pro načtení dat, tak i pro jejich zápis, což použije náš skript.
Také tu vidíme použití sekce shutdown skriptu, která se volá během jeho ukončeni. V našem případě zde skript provede uložení CSV,
Popis funkce skriptu je součástí komentářů v kódu skriptu. Celý skript je možné stáhnout zde.
script:
//Skript spousten pri prichodu CAN zpravy
type = CAN_FUNCTION;
end
// Definice promennych
variables:
unsigned i;
string filename;
string time;
double pressure_1;
double pressure_2;
bool b;
end
// Definice objektu
objects:
//Objekt csvfile je urceny pro cteni nebo ukladani dat z/do souboru CSV
obj_csvfile file;
obj_can_msg can_msg;
end
init:
//Vytvoreni nazvu souboru podle aktualniho data a casu kdy byl skript spusten
//date_y - vraci aktualni rok
//i2str - konverze int na string
filename = i2str(date_y());
filename = filename + "_";
//date_m - vraci mesic
filename = filename + i2str(date_m());
filename = filename + "_";
//date_d - vraci den
filename = filename + i2str(date_d());
filename = filename + "-";
//time_h - vraci hodinu
filename = filename + i2str(time_h());
filename = filename + "_";
//time_m - vraci minutu
filename = filename + i2str(time_m());
filename = filename + ".csv";
//Rezervuji misto v prazdnem CSC - 10 radku a 5 sloupcu
file.reserve(10,5,"");
//Zapisu hlavicku dat na prvni radek
b = file.set(0,0,"Cas udalosti");
b = file.set(0,1,"Info");
b = file.set(0,2,"Tlak 1");
b = file.set(0,3,"Tlak 2");
//Hlaseni pokud nastala chyba CSV
if(b==false)
{
prints("Chyba zapisu do CSV");
}
i=1;
end
body:
//Nacteni prijate CAN zpravy do objektu
can_msg.load();
//Kontroluji zda je to zprava s 11 bitovym identifikatorem
if(can_msg.stext==false && can_msg.rtr==false)
{
//Podle ID vykonam akci - dekoduji data
switch(can_msg.id1)
{
//Id 100 dekadicky
case 100:
//Dekodovani dat, data zacinaji od 8 bitu a maji delku 14 bitu
//Jsou ve formatu little endian a jsou typu unsigned
pressure_1 = can_msg.get_value(8, 14, false, false);
//Meritkovani - rozliseni bitu je 0.5 Pa
pressure_1 = pressure_1 * 0.5;
//Vypis pro ucely ladeni
printd(pressure_1);
break;
//Id 110
case 110:
pressure_2 = can_msg.get_value(8, 14, false, false);
pressure_2 = pressure_2 * 0.5;
printd(pressure_2);
break;
}
}
//Chyba nastava, pokud jsou oba tlaky vetsi nez 1000Pa
//Pressure je typu double, proto musim porovnavat s typem double (zadat desetinnou tecku)
if((pressure_1>1000.0) && (pressure_2>1000.0))
{
//Vypis do logu
prints("Prekroceni tlaku");
//Zapisuji do CSV
b = file.set(i,1,"Chyba");
if(b==false)
{
//Hlasim chybu zapisu do CSV
prints("Chyba zapisu do CSV");
}
else
{
//V prvnim sloupci je cas vyskytu chyby - vytvorim retezec s casem
time = i2str(time_h());
time = time + ":";
time = time + i2str(time_m());
time = time + ":";
time = time + i2str(time_s());
//Zapisu cas
b=file.set(i,0,time);
//Zapisu hodnoty tlaku
b=file.set(i,2,d2str(pressure_1));
b=file.set(i,3,d2str(pressure_2));
//Citac radku v CSV
i=i+1;
//Pocet radku - size_r
if(i>=file.size_r())
{
//CSV musi mit nastavenou velikost, v pripade potreby jej zvetsim
file.reserve(file.size_r()+10,5,"");
}
}
}
end
// Shutdown sekce skriptu
shutdown:
//Ulozim CSV soubor pri ukonceni skriptu
file.write(filename);
end
Další díly seriálu:
- Díl 1: Periodické generování dat na CAN sběrnici.
- Díl 2: Uživatelské prvky pro řízení skriptu
- Díl 3: Simulace joysticku dle SAE J1939
- Díl 4: Monitorování a zápis událostí do souboru CSV
- Díl 5: Měření periody a zápis do CSV pomocí přiřazení objektu
- Díl 6: Komunikace pomocí TCP
- Díl 7: Komunikace pomocí sériové linky
- Díl 8: PID regulátor
- Díl 9: Výpočet CRC a objekt obj_dataset
- Díl 10: Volání funkce z externí DLL
- Díl 11: Odeslání emailu s hlášením
