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