PROIECT DE DIZERTA łIE [622440]
Universitatea Tehnic ă "Gh. Asachi" Ia și
Facultatea de Electronic ă, Telecomunica Ńii și Tehnologia Informa Ńiei
PROIECT DE DIZERTA łIE
Coordonator:
Conf. dr. ing. Adrian Brezulianu
Masterand: [anonimizat] "Gh. Asachi" Ia și
Facultatea de Electronic ă, Telecomunica Ńii și Tehnologia Informa Ńiei
Sec Ńia Sisteme Electronice Inteligente și Informatic ă Industrial ă
SISTEM DE COMUNICA łIE PE CAN
Interfa Ńă de citire a valorilor de la senzori și
transmitere pe magistral ă
Coordonator:
Conf. dr. ing. Adrian Brezulianu
Masterand: [anonimizat], 2011
Cuprin s
– 1 –
CUPRINS
Capitolul I: Introducere………………………………… …………………………………………… ………………………..3
I.1 Tema de proiect………………………….. …………………………………………… ……………………………………..4
I.2 Memoriu justificativ……………………… …………………………………………… ……………………………………5
Capitolul II: Introducere în CAN…………………………… …………………………………………… ………………..6
II.1 Principiul schimbului de date…………….. …………………………………………… ……………………………….7
II.2 Codificarea semnalelor…………………… …………………………………………… ………………………………….8
II.3 Structura mesajului de CAN……………….. …………………………………………… ………………………………8
II.4 Semnalizarea și detec Ńia erorilor…………………………………. …………………………………………… …….10
Capitolul III: Descrierea comunica Ńiei de CAN prin fi șierul DBC…………………………………… ………12
Capitolul IV: Descrierea blocului RTICANMM Main Block……….. …………………………………………17
IV.1 Caracteristicile I/O ale blocului RTICANMM…. …………………………………………… ………………..18
IV.2 Parcurgerea fi șierului descriere de CAN……………………… …………………………………………… ……20
IV.3 OpŃiuni de trigerare a mesajelor transmise………… …………………………………………… ………………21
Capitolul V: Pachetul software PCAN Basic…………………. …………………………………………… ………..23
V.1 Tipuri de date utilizate………………….. …………………………………………… …………………………………24
V.2 Ini Ńializarea unui canal PCAN…………………….. …………………………………………… ……………………28
V.3 Dezini Ńializarea unui canal PCAN…………………….. …………………………………………… ………………29
V.4 Configurarea parametrilor unui canal PCAN…… …………………………………………… ………………….29
V.5 Configurarea filtrului de mesaje recep Ńionate……………………………………… ……………………………30
V.6 Preluarea de informa Ńii de pe un canal PCAN……………………….. …………………………………………31
V.7 Preluarea statusului magistralei de CAN de pe u n canal PCAN………………………………… ………..31
V.8 Returnarea unui text descriptiv pentru un cod d e eroare……………………………………. ……………….32
V.9 Recep Ńionarea unui mesaj de CAN de pe un canal PCAN…… …………………………………………… ..32
V.10 Transmiterea unui mesaj de CAN pe un canal PCA N………………………………………….. ………….33
V.11 Resetarea unui canal PCAN………………… …………………………………………… ………………………….34
V.12 Definirea valorilor posibile a parametrilor un ui canal PCAN……………………………….. ………….35
Capitolul VI: Interfa Ńa grafic ă PCAN………………………………………. …………………………………………..3 6
VI.1 Ini Ńializarea canalului PCAN……………………… …………………………………………… ……………………38
VI.2 Citirea instantanee a valorilor de la senzori. …………………………………………… ……………………….39
VI.3 Citirea ciclic ă a valorilor de la senzori……………………. …………………………………………… ………..43
VI.4 Trimiterea de mesaje pe magistrala de CAN….. …………………………………………… ………………….47
Cuprin s
– 2 –
Capitolul VII: Concluzii………………………………….. …………………………………………… ……………………51
VII.1 Rezumat……………………………….. …………………………………………… ……………………………………..52
VII.2 Concluzii asupra proiectului…………….. …………………………………………… …………………………….52
Referin Ńe bibliografice …………………………………………… …………………………………………… …………….54
Anexe …………………………………………… …………………………………………… ……………………………………..56
Capitolul I Introducere
– 3 –
CAPITOLUL I
INTRODUCERE
Capitolul I Introducere
– 4 –
I. Introducere
Controlerul în arie de re Ńea (Controller Area Network) CAN este un protocol d e re Ńea ce
permite comunica Ńia eficient ă între mai multe procesoare. La începutul anilor ’8 0 procesoarele au
devenit suficient de mici și puternice încât au început s ă se r ăspândeasc ă în toate domeniile tehnice.
Sistemele electronice de injec Ńie a combustibilului ce au înlocuit carburatoarele, sistemele de anti-
blocare a frânelor, sistemele de airbag sau centuri le de siguran Ńă utilizeaz ă microprocesoare rapide
pentru luarea deciziilor în frac Ńiuni de secund ă. Pe m ăsur ă ce tot mai multe sisteme electronice au
fost ad ăugate în ma șini, nevoia de a le face s ă comunice între ele a fost tot mai crescut ă. Ast ăzi
protocolul CAN este standardul de mare vitez ă și control în timp real pentru multe aplica Ńii [ref.3].
Protocolul CAN face posibil ca toate aceste microp rocesoare din cadrul unui sistem s ă
trimit ă și s ă recep Ńioneze mesaje f ără a avea nevoie de un mecanism de control centraliza t.
Deasemenea sistemele bazate pe CAN prezint ă o simplitate și o flexibilitate mai mare la
mentenan Ńă . Componentele hardware din cadrul unui sistem de C AN pot fi înlocuite, ad ăugate sau
scoase f ără a fi afectate celelalte componente ale re Ńelei [ref.3].
Un sistem de CAN trimite mesaje folosind o magistr al ă serial ă. Fiecare nod din re Ńea are
acela și statut cu oricare altul din cadrul re Ńelei. Orice nod poate transmite un mesaj catre oric are
altul, iar daca unul dintre nodurile re Ńelei este compromis, restul sistemului nu este afec tat, celelalte
noduri r ămase putând comunica între ele în continuare. Proto colul de CAN a fost dezvoltat pentru
mesaje scurte, nu mai lungi de opt octe Ńi. Se utilizeaz ă în general pentru trimiterea de semnale ce
trigereaz ă diverse evenimente cum ar fi blocarea centurilor d e siguran Ńă în cazul frân ării puternice,
sau diverse masur ători, de temperatur ă sau presiune. Protocolul de CAN nu întrerupe nicio dat ă o
transmisie în desf ăș urare, dar asigneaz ă priorit ăŃi mesajelor pentru prevenirea conflictelor și pentru
a asigura intâietate mesajelor urgente la transmite re. Chiar și a șa sistemele CAN sunt foarte rapide,
fiind capabile s ă transmit ă 7600 de mesaje cu lungimea de 8 octe Ńi pe secund ă sau 18000 de
semnale de trigerare pe secund ă [ref.3].
Robert Bosch a introdus no Ńiunea de magistral ă de CAN în anul 1986 în cadrul congresului
SAE (Society of Automotive Engineers) din Detroit. Conceptul se numea “Automotive Serial
Controller Area Network” deoarece sistemele CAN au fost dezvoltate ini Ńial având ca Ńint ă industria
auto. În prezent aplica Ńii ale sistemului de comunica Ńie CAN se reg ăsesc în mai toate domeniile
tehnice, în sistemele de eleva Ńie ale cl ădirilor înalte, b ărci de toate felurile, trenuri, avioane, în
echipamente medicale, automate de cafea, etc. Ast ăzi, toate ma șinile noi construite în Europa con Ńin
cel pu Ńin un sistem de comunica Ńie CAN, devenind astfel un standard în sistemele de comunica Ńie
din industria automotive [ref.3].
Produc ătorii de microprocesoare Intel și Phillips Semiconductors au dezvoltat primele
integrate cu func Ńionalit ăŃi dedicate de CAN în anul 1987. Ace știa au fost urma Ńi de Motorola si
NEC, în prezent existând zeci de mari produc ători de circuite dedicate de CAN. În anul 1993
Organiza Ńia Interna Ńional ă pentru Standardizare (ISO) a publicat standardul 1 1898 pentru definirea
sistemului CAN de uz industrial în general [ref.3].
I.1 Tema de proiect
Tema prezentului proiect o constituie realizarea un ei aplica Ńii de cost redus prin intermediul
căreia utilizatorul s ă fie capabil s ă se conecteze la o magistral ă de CAN și s ă citeasc ă valorile
furnizate de un nod al re Ńelei de la o serie de senzori de orice natur ă, la un mesaj de comand ă
transmis de acesta.
Identificatorii mesajelor ce con Ńin semnalele cu valorile senzorilor și respectiv
identificatorul mesajului comand ă de citire sunt impuse. Formatul mesajelor prin int ermediul c ărora
se realizeaz ă comunica Ńia sunt de tip standard, cu o lungime a identificat orului de 11 bi Ńi și o
lungime a câmpului de date fix ă de 8 octe Ńi.
Deasemenea utilizatorul va putea configura parametr ii unui mesaj de CAN și va avea
posibilitatea de transmitere a mesajului pe magistr al ă o singur ă dat ă (kickout) sau periodic (cyclic),
pentru trigerarea a diferite evenimente. Utilizator ul trebuie s ă fie capabil s ă configureze
Capitolul I Introducere
– 5 – identificatorul mesajului, tipul mesajului (standar d sau extins), lungimea și valorile câmpului de
date și valoarea perioadei de timp la care mesajul va fi transmis pe magistral ă.
Aplica Ńia va dispune de un mecanism de afi șare a mesajelor corespunz ătoare fiec ărei
opera Ńiuni efectuate, comand ă de citire sau transmisie pe magistral ă, precum și afi șarea de mesaje
descriptive în cazul apari Ńiei unei erori de comunica Ńie.
I.2 Memoriu justificativ
Odat ă cu progresul tehnologic au fost dezvoltate sisteme care s ă u șureze via Ńa omului,
sisteme de care acesta a devenit dependent odat ă cu trecerea timpului. În era informa Ńiei oamenii
tind s ă Ńin ă pasul cu progresul știin Ńific, fiind practic imposibil a se renun Ńa la mijloacele
tehnologice care ne fac via Ńa mai u șoar ă și mai sigur ă zi de zi.
Cele mai de succes inven Ńii de-a lungul timpului au fost cele care au implic at un anumit grad
de automatism și totodat ă cele care au reu șit s ă u șureze via Ńa operatorului uman. Astfel, odat ă cu
apari Ńia sistemelor automatizate, a robo Ńilor industriali, a calculatorului, tehnologia a fo st în
continu ă expansiune, operatorul uman fiind scutit de o seri e întreag ă de opera Ńii care ar fi trebuit
realizate prin mijloace învechite cu un consum enor m de resurse și timp. De aici reiese și
importan Ńa existen Ńei unui sistem de comand ă și control de la distan Ńă al obiectelor și proceselor in
jurul nostru mai ales în cazul în care distan Ńa dintre echipamente este considerabil ă și, mai mult, în
cazul în care exist ă anumite riscuri la care operatorul uman ar trebui s ă fie supus.
Prin acest proiect se propune dezvoltarea unei apl ica Ńii software prin intermediul c ăreia
operatorul uman sa poat ă citi diferite valori furnizate de o serie de senzo ri afla Ńi la o distan Ńă
considerabil ă prin intermediul unei magistrale de CAN și deasemenea s ă fie capabil s ă transmit ă în
re Ńea semnale de comand ă pentru declan șarea a diferite evenimente pe baza informa Ńiilor
recep Ńionate de la senzori.
Pentru punerea în practic ă a aplica Ńiei s-a optat pentru pachetul gratuit PCAN Basic
dezvoltat de Peak System, pachet ce ofer ă o colec Ńie de drivere și libr ării cu acces la o diversitate de
func Ńii utile pentru dezvoltarea de aplica Ńii de interfa Ńare CAN în mai multe limbaje de programare.
Driverele oferite sunt compatibile cu dispozitivele hardware de interfa Ńare fizic ă cu magistrala de
CAN comercializate de Peak System. Pentru o mai bun ă viziune asupra proiectului se propune
figura urm ătoare:
Figura 1. Vederea de ansamblu a re Ńelei de CAN
Astfel utilizatorul va transmite un mesaj de coman d ă în re Ńea, iar nodul ce de Ńine valorile
senzorilor va recunoa ște mesajul ce i se adreseaz ă și va transmite la rândul s ău mesajele
corespunz ătoare pe magistral ă.
Pentru simularea re Ńelei de CAN incluzând nodul ce furnizeaz ă valorile de la senzori s-a
utilizat un model de Matlab cu libr ăriile de CAN aferente, înc ărcat și rulat în timp real pe un sistem
MicroAutoBox de la dSpace.
Capitolul II Introducere în CAN
– 6 –
CAPITOLUL II
INTRODUCERE ÎN CAN
Capitolul II Introducere în CAN
– 7 –
II. Introducere în CAN
CAN (Controller Area Network) este un sistem de com unica Ńie pe magistral ă serial ă,
dezvoltat ini Ńial pentru aplica Ńii în cadrul industriei auto la începutul anilor 19 80. CAN presupune o
serie de servicii de comunicare, dintre care transm iterea de mesaje prin date organizate în frame-uri
și cererea de mesaje prin transmisie remote. Restul serviciilor oferite de sistemul de comunica Ńie
CAN sunt ascunse utilizatorului fiind realizate aut omat și presupun semnalarea erorilor și
retransmiterea mesajelor semnalate cu erori. Sistem ul CAN folose ște o magistral ă de tip broadcast,
în câmpul de date al mesajului neexistând în mod ex plicit o adres ă a destinatarului. Toate nodurile
re Ńelei recep Ńioneaz ă mesajul care circul ă pe magistral ă la un moment dat și nodurile vor deduce
dac ă mesajul le este adresat. Ierarhia sistemului este una de tip multimaster ce permite func Ńionarea
sistemului chiar și în condi Ńiile unuia sau a mai multor noduri defecte din re Ńea.
În figura urm ătoare este prezentat un exemplu simplu de re Ńea CAN, constând în dou ă fire
(CAN-H și CAN-L) ce interconecteaz ă fiecare membru al magistralei [ref.4]:
Figura 1. Exemplu de re Ńea CAN [ref.4]
Magistrala de date propriuzis ă este format ă dintr-o pereche r ăsucit ă de cabluri prev ăzute cu
rezistori terminali, 120 Ohmi în cazul firelor UTP de exemplu. Fiecare nod al re Ńelei este prev ăzut
cu un CAN transceiver ce asigur ă interfa Ńarea fizic ă cu magistrala.
II.1 Principiul schimbului de date
Protocolul CAN func Ńioneaz ă pe baza unui mecanism de comunica Ńie de tip broadcast ce
const ă într-un protocol de transmisie prin intermediul me sajelor. Astfel se va defini con Ńinutul
mesajelor și nu adresele sta Ńiilor. Fiecare mesaj con Ńine un identificator unic în întreaga re Ńea pe
baza c ăruia se define ște prioritatea mesajului. Cu cât valoarea numeric ă a identificatorului este mai
mic ă, cu atât prioritatea mesajului respectiv este mai mare în cadrul re Ńelei. Prioritatea mesajelor
devine important ă în momentul în care mai multe noduri ale re Ńelei doresc simultan accesul la
transmisie pe magistral ă [ref.5].
În cadrul aplica Ńiilor în timp real exist ă semnale ce trebuiesc transmise mai frecvent pe
magistrală și cu întârzieri mai pu Ńine, con Ńinând informa Ńii vitale bunei func Ńion ări a sistemului,
cum ar fi valoarea actual ă a curen Ńilor pe fazele unui motor electric, o cerere brusc ă de cuplu în
cazul unui motor termic, sau o cerere de deschidere a airbag-ului în cazul unui accident auto. Astfel
este necesar ă o prioritizare a informa Ńiilor care circul ă pe magistral ă [ref.5].
Rezolvarea conflictelor de acces la magistrala de date sunt realizate printr-un mecanism de
arbitrare la nivel de bit, fiind compara Ńi bit cu bit identificatorii mesajelor ce se doresc a fi trasmise.
Astfel nodurile pierz ătoare devin automat receptoare ale mesajului câ știg ător și nu vor reîncerca
retransmiterea p ănă când magistrala nu este disponibil ă din nou. Arbitrarea se face dup ă
urm ătoarele reguli [ref.1]:
– Orice nod poate accesa magistrala doar atunci când aceasta este libera, și anume atunci
când este în starea recesiv ă 1 logic;
– Dac ă mai multe noduri acceseaz ă magistrala exact în acela și moment de timp, mesajul
cu cei mai mul Ńi bi Ńi dominan Ńi 0 logic în câmpul destinat identificatorului va c â știga
accesul la magistrala de date.
– Nodurile care pierd arbitrarea curent ă vor trebui s ă încerce retransmiterea mesajului
imediat dup ă terminarea transmisiei în curs.
Capitolul II Introducere în CAN
– 8 –
Figura 2. Arbitrarea mesajelor pe magistral ă
Acest mecanism de arbitrare func Ńioneaz ă la nivelul fiec ărui nod din re Ńea și asigur ă faptul
că transmi Ńă torul cu prioritatea mai mic ă va abandona transmisia cel mult la sfâr șitul câmpului de
identificare, neexistând într-o re Ńea dou ă noduri cu acela și identificator. Mecanismul permite
evitarea tuturor coliziunilor între pachetele de da te.
II.2 Codificarea semnalelor
Nivelul fizic al protocolului CAN este responsabil cu transferul bi Ńilor de date între diferitele
noduri ale re Ńelei. La acest nivel se define ște modul în care se transmit datele, se trateaz ă
problemele legate de codare și sincronizare a șirurilor de date [ref.5].
Datele sunt codificate NRZ prin dou ă nivele de tensiune pe magistral ă, recesiv (1 logic) și
dominant (0 logic). Nivelul recesiv corespunde st ării de repaus a magistralei și are o valoare a
tensiunii de aproximativ 2.5V fa Ńă de mas ă. Nivelul dominant corespunde st ării active și are
valoarea de aproximativ 3.5V pe linia high a magist ralei (CANH) și respectiv 1.5V pe linia low
(CANL). Toate nodurile sunt conectate la magistral ă într-o func Ńie ȘI cablat. Astfel valoarea
tensiunii pe magistral ă va fi cea corespunz ătoare nivelului dominant 0 logic atunci când mai mu lte
noduri încearc ă s ă transmit ă simultan câte un bit de valoare diferit ă [ref.5].
În codarea de bit de tip non-return-to-zero nivelu l semnalului r ămâne constant pe toat ă
durata de bit. Nivelul semnalului poate r ămâne constant pe durata mai multor perioade de bit în
cazul în care se transmit date ce necesit ă mai mul Ńi bi Ńi consecutivi de aceea și valoare. Acest lucru
poate conduce la pierderea sincroniz ării și din acest motiv este utilizat ă metoda bit-stuffing, tehnic ă
ce presupune introducerea unui bit complementar dup ă cinci bi Ńi consecutivi de aceea și valoare
logic ă. Nodul c ăruia i se adreseaz ă mesajul trebuie s ă fie capabil s ă despacheteze corect mesajul
recep Ńionat și s ă extrag ă informa Ńia corect ă prin înl ăturarea bi Ńilor insera Ńi prin bit-stuffing [ref.5].
Figura 3. Codarea NRZ. Bit stuffing
II.3 Structura mesajului CAN
Protocolul CAN poate suporta dou ă tipuri de formate ale mesajelor și anume formatul de
baz ă și respectiv formatul CAN extins. Diferen Ńa dintre cele dou ă formate se rezum ă la lungimea
câmpului destinat identificatorului.
[ref.1] Formatul de baz ă începe cu bitul de start al mesajului SOF, întotde auna fiind de tip
dominant 0 logic, care marcheaz ă începutul mesajului. Bitul de start este urmat de câmpul de
Capitolul II Introducere în CAN
– 9 – arbitrare alc ătuit din identificatorul mesajului și bitul cerere de date RTR (remote transmission
request). Bitul RTR deosebe ște un mesaj de date de unul tip cerere de date. Ast fel dac ă bitul RTR
este de valoare logic ă 0, acesta indic ă faptul c ă mesajul este unul de date, iar dac ă este de valoare 1
logic atunci mesajul curent este unul de tip remote frame, o cerere de date emis ă de unul dintre
nodurile re Ńelei c ătre toate celelalte noduri.
Urmeaz ă apoi câmpul de control alc ătuit din doi bi Ńi dominan Ńi rezerva Ńi pentru dezvolt ări
ulterioare ale protocolului și câmpul DLC (data length code) de patru bi Ńi care indic ă num ărul
octe Ńilor de date ce urmeaz ă a fi transmi și.
Câmpul de date poate avea o lungime cuprins ă între 0 și 8 octe Ńi. În cadrul mesajelor de tip
remote, câmpul de date are 0 octe Ńi, nefiind transmis ă nici o dat ă.
Integritatea mesajului este garantat ă de câmpul CRC (cyclic redundancy check) care are o
lungime de 16 bi Ńi, dar din care numai 15 bi Ńi semnific ă suma de control propriuzis ă, al 16-lea bit
având rol de delimitare cu valoarea 1 logic.
Câmpul de acknowledge ACK are o lungime de 2 bi Ńi. Primul bit este transmis cu valoarea 1
logic recesiv, dar nodurile ce recep Ńioneaz ă mesajul vor for Ńa valoarea logic ă a magistralei în 0 logic
dominant pe durata acestui bit pentru a confirma re cep Ńia. Cel de-al doilea bit din câmpul de
confirmare este întotdeauna de tip recesiv 1 logic și are rolul de delimitare.
Câmpul ce marcheaz ă sfâr șitul mesajului EOF este alc ătuit din 7 bi Ńi de 1 logic. Dup ă
încheierea mesajului, magistrala este p ăstrat ă în starea recesiv ă 1 logic pe durata a înc ă 3 bi Ńi INT
dup ă care aceasta se consider ă liber ă și poate fi accesat ă iara și de c ătre orice nod al re Ńelei [ref.1].
Figura 4. Structura mesajului de baz ă CAN [ref.1]
[ref.1] În cazul formatului extins de mesaj, câmpu l de arbitrare prezint ă în plus bitul SRR
(substitute remote request) care este întotdeauna r ecesiv, plasat în locul bitului RTR din cazul
formatului standard pentru a permite implementarea unor re Ńele mixte cu noduri standard cât și
extinse. Astfel este posibil ca un nod standard s ă emit ă în acela și timp cu unul extins, situa Ńie în care
prioritatea o va avea mesajul transmis de c ătre nodul standard. Urmeaz ă apoi un bit IDE (identifier
extension bit) care transmis cu valoarea 0 logic se mnific ă un mesaj în format standard, iar transmis
cu valoarea 1 logic va semnifica un mesaj în format extins. Bitul IDE este urmat de un al doilea
câmp de identificare de 18 bi Ńi, astfel lungimea identificatorului în formatul ex tins fiind de 29 de
bi Ńi.
Figura 5. Structura mesajului extins CAN [ref.1]
Capitolul II Introducere în CAN
– 10 – [ref.5] Un nod al re Ńelei CAN poate ini Ńia o cerere de date de la alte noduri ale re Ńelei prin
transmiterea unui mesaj de tip remote. Un astfel de mesaj este alc ătuit dintr-un bit de start al
mesajului SOF, urmat de câmpul de arbitrare alc ătuit ca și în cazul unui mesaj de date din
identificator și bit RTR, câmpul de control, câmpul sum ă de control CRC, câmpul de confirmare a
recep Ńion ării ACK și bitul de sfâr șit al mesajului EOF. Spre deosebire de un mesaj de date, cel de
tip remote are bitul RTR (remote transmission reque st) de tip regresiv semnaliâand astfel tipul
mesajului cerere de date. Deasemenea câmpul de date nu este prezent în structura mesajului remote.
Figura 6. Structura mesajului remote [ref.5]
Pe lâng ă mesajele de date sau cerere de date, mai exist ă mesaje de tip eroare. Acestea au o
structur ă special ă și sunt emise numai atunci când o eroare de comunica re a fost detectat ă. Acest tip
de mesaj este alc ătuit dintr-un semnalizator de eroare de 6 bi Ńi consecutivi pe 0 logic în cazul unui
semnalizator activ sau 1 logic în cazul pasiv. Ace ști 6 bi Ńi sunt urma Ńi de un câmp delimitator de 8
bi Ńi consecutivi de 1 logic. Un semnalizator de eroare activ încalc ă regula impus ă prin tehnica bit
stuffing și astfel toate nodurile re Ńelei vor recep Ńiona mesajul de eroare și vor emite deasemenea
mesaje de eroare. Astfel la o detec Ńie de eroare, magistrala CAN va sta în starea domin ant ă timp de
12 perioade de bit [ref.1].
II.4 Semnalizarea și detec Ńia erorilor
Pentru detec Ńia erorilor protocolul CAN are implementate o serie de mecanisme la nivel de
mesaj și anume [ref.2]:
– CRC (cyclic redundancy check) prin care la sfâr șitul transmisiei secven Ńei de informa Ńie
i se asociaz ă o secven Ńă de verificare FCS (frame check sequence). La recep Ńie secven Ńa
FCS este recalculat ă pe baza datelor recep Ńionate și dac ă nu corespunde cu cea calculat ă
la transmisie atunci înseamn ă c ă a avut loc o eroare CRC.
– Frame Check prin care structura mesajului și dimensiunea sunt comparate cu un format
fix. Erorile astfel detectate sunt definite ca eror i de format.
– Erorile de confirmare sunt declan șate de c ătre nodurile transmi Ńă toare atunci când
nodurile receptoare nu confirm ă mesajele recep Ńionate.
Deasemenea protocolul CAN implementeaz ă și o serie de mecanisme de detec Ńie a erorilor
la nivel de bit [ref.2]:
– Prin monitorizarea magistralei, fiecare nod transmi Ńă tor are capacitatea de a detecta
erorile prin compararea nivelului logic al magistra lei cu ceea ce transmite de fapt.
– Erorile de bit stuffing sunt semnalate în cazul în care un receptor identific ă secven Ńe de
mai mult de cinci bi Ńi consecutivi de acela și nivel loigc.
Dac ă cel pu Ńin una dintre aceste erori este detectat ă de c ătre cel pu Ńin un nod al re Ńelei atunci
transmisia curent ă este întrerupt ă și un mesaj de eroare este transmis pe magistral ă. Acest mesaj de
eroare va împiedica celelalte noduri s ă accepte mesajul eronat detectat, p ăstrându-se corectitudinea
datelor pe toat ă magistrala.
Capitolul II Introducere în CAN
– 11 –
Figura 7. Structura mesajului de eroare [ref.1]
Momentul de timp la care transmisia mesajului de er oare începe depinde de tipul erorii
detectate. Astfel dac ă a fost detectat ă o eroare de bit, de confirmare, de structur ă sau de bit stuffing,
transmisia semnalizatorului de eroare începe cu per ioada de bit urm ătoare detect ării erorii. În cazul
erorilor de CRC, mesajul de eroare va fi transmis î ncepand cu perioada de bit urm ătoare secven Ńei
de confirmare ACK. Dup ă transmiterea mesajului de eroare, nodul emi Ńă tor va retransmite automat
ultimul mesaj [ref.1].
Protocolul CAN are implementat și un mecanism de detec Ńie a erorilor permanente
determinate de avarierea unui nod din cadrul re Ńelei. Fiecare nod al re Ńelei este capabil s ă-și
monitorizeze singur starea de bun ă func Ńionare, iar în cazul unei defec Ńiuni acesta va intra într-un
mod de func Ńionare în care restul re Ńelei s ă nu fie afectat ă. Astfel se deosebesc urm ătoarele moduri
de operare ale nodurilor dintr-o re Ńea [ref.5]:
– Error active: stare de func Ńionare normal ă. În acest mod de operare nodul poate transmite
și recep Ńiona mesaje și totodat ă poate participa la semnalarea erorilor detectate.
– Error passive: în aceast ă stare nodul poate transmite și recep Ńiona mesaje, dar dupa
finalizarea unei transmisii nodul are nevoie, pentr u a putea reîncepe o transmisie, de un
interval de opt perioade de bit plus o perioad ă de intermission constituit ă din trei bi Ńi
regresivi. Semnalizarea erorilor se face prin emite rea unui semnalizator de eroare pasiv
care va fi sesizat de celelalte noduri doar dac ă acesta transmite. Un nod al re Ńelei va intra
în acest mod de operare atunci când are probleme fr ecvente la emisia sau recep Ńia
mesajelor.
– Buss-off: în aceast ă stare nodul nu poate transmite sau recep Ńiona. Controller-ul CAN al
nodului va informa microcontrollerul de starea în c are se afla, care va genera un reset al
controller-ului
Capitolul III Descrierea comunica Ńiei de CAN prin fi șierul DBC
– 12 –
CAPITOLUL III
DESCRIEREA COMUNICA łIEI DE CAN
PRIN FI ȘIERUL DBC
Capitolul III Descrierea comunica Ńiei de CAN prin fi șierul DBC
– 13 –
III. Descrierea comunica Ńiei CAN prin fi șierul dbc (CAN database container)
Fi șierul dbc descrie comunica Ńia unei singure re Ńele de CAN. Informa Ńiile con Ńinute în fi șier
sunt suficiente pentru a monitoriza și a analiza re Ńeaua CAN precum și simularea nodurilor de re Ńea
care nu sunt disponibile fizic. Fi șierul dbc poate fi utilizat și în dezvoltarea aplica Ńiilor de
comunica Ńie CAN a unor ECU-uri (electronic control unit) ce vor fi parte din re Ńeaua CAN.
Avantajul major al unei descrieri de CAN în format dbc este acela c ă numeroase aplica Ńii de analiza
CAN (ex. CANalyzer, CANoe, CANape, Matlab, Peak sau ControlDesk) au încorporate mecanisme
de parsare automat ă a unor astfel de fi șiere. Descrierea fi șierului dbc s-a realizat utilizând CANdb
Database Editor de la Vector Software. Utilizarea e ditorului CANdb are avantajul interfe Ńei grafice
și garan Ńia unui format al fi șierului dbc f ără erori [ref.6].
Crearea descrierii CAN în formatul dbc presupune tr ei etape: descrierea nodurilor de re Ńea,
descrierea mesajelor și asocierea acestora nodurilor corespunz ătoare, descrierea semnalelor și
asocierea acestora mesajelor corespunz ătoare.
Schema bloc a sistemului CAN ce se dore ște a fi descris este prezentat ă în figura urm ătoare:
Figura 1. Schema bloc a sistemului CAN
În prezenta aplica Ńie s-a dorit ca la ini Ńierea unui semnal de comand ă dinspre nodul PCAN,
nodul AutoBox s ă preia valorile semnalelor de la un set de senzori externi și să trimit ă informa Ńia
înapoi c ătre PCAN. Astfel se vor defini dou ă noduri în cadrul re Ńelei de CAN, nodul Peak PCAN
(denumit uController), dinspre care se va ini Ńia comunica Ńia, și nodul AutoBox (denumit uAutoBox)
ce va prelua informa Ńiile de la senzori și le va transmite c ătre nodul PCAN.
Figura 2. Definirea nodurilor re Ńelei CAN
Odat ă definite nodurile re Ńelei, se vor defini mesajele ce vor circula în re Ńea și se vor asocia
nodurilor corespunz ătoare. Astfel se define ște mesajul de comand ă ce va fi transmis de c ătre nodul
PCAN și se va adresa nodului AutoBox. Valorile senzorilor vor fi furnizate de c ătre nodul AutoBox
nodului PCAN prin transmiterea a trei mesaje, fieca re corespunz ănd unuia din senzorii citi Ńi.
Capitolul III Descrierea comunica Ńiei de CAN prin fi șierul DBC
– 14 –
Figura 3. Definirea mesajelor de CAN
Mesajul de comand ă transmis de
PCAN (denumit uCCommand_Message1)
este configurat cu urm ătorii parametri:
– identificatorul mesajului: 0x200;
– formatul cadrului: standard
(lungimea identificatorului de 11
bi Ńi);
– lungimea câmpului de date de 8
octe Ńi (data length code);
– perioada de 10 milisecunde;
– metoda de transmitere: ciclic.
Figura 4. Definirea mesajului de comand ă
În interiorul mesajului se va
transmite un semnal de comand ă (denumit
uC_Signal1), configurat cu urm ătorii
parametri:
– lungimea câmpului de date de 8
bi Ńi;
– ordinea bi Ńilor de date de tipul
Motorola;
– offset: 0
– factor: 1
– valoare minim ă: 0
– valoare maxim ă: 255
Figura 5. Definirea semnalului de comand ă
Nodul AutoBox va transmite c ătre PCAN valorile preluate de la senzori prin inter mediul a
câte un semnal ce con Ńine valoarea a câte unui senzor. Fiecare semnal în parte este asociat câte unui
mesaj de CAN. Astfel nodul PCAN va trebui s ă recep Ńioneze trei mesaje diferite fiecare con Ńinând
câte un semnal cu informa Ńiile preluate de la câte unul din cei trei senzori.
Astfel se vor defini trei mesaje de CAN și anume:
Mesajul TX_Message1 r ăspuns
transmis de c ătre nodul AutoBox este
configurat cu urm ătorii parametri:
– identificatorul mesajului: 0x100;
– formatul cadrului: standard
(lungimea identificatorului de 11
bi Ńi);
– lungimea câmpului de date de 8
octe Ńi (data length code);
– perioada de 100 milisecunde;
– metoda de transmitere: ciclic.
Figura 6. Definirea mesajului r ăspuns TX_Message1
Capitolul III Descrierea comunica Ńiei de CAN prin fi șierul DBC
– 15 – În interiorul mesajului TX_Message1
se define ște semnalul TX_Signal1 ce con Ńine
valoarea preluat ă de la senzorul 1. Semnalul
este configurat cu urm ătorii parametri:
– lungimea câmpului de date de 8
bi Ńi;
– ordinea bi Ńilor de date de tipul
Motorola;
– offset: 0
– factor: 1
– valoare minim ă: 0
– valoare maxim ă: 255
Figura 7. Definirea semnalului r ăspuns TX_Signal1
Mesajul TX_Message2 r ăspuns
transmis de c ătre nodul AutoBox este
configurat cu urm ătorii parametri:
– identificatorul mesajului: 0x110;
– formatul cadrului: standard
(lungimea identificatorului de 11
bi Ńi);
– lungimea câmpului de date de 8
octe Ńi (data length code);
– perioada de 100 milisecunde;
– metoda de transmitere: ciclic.
Figura 8. Definirea mesajului r ăspuns TX_Message2
În interiorul mesajului TX_Message2
se define ște semnalul TX_Signal2 ce con Ńine
valoarea preluat ă de la senzorul 2. Semnalul
este configurat cu urm ătorii parametri:
– lungimea câmpului de date de 8
bi Ńi;
– ordinea bi Ńilor de date de tipul
Motorola;
– offset: 0
– factor: 1
– valoare minim ă: 0
– valoare maxim ă: 255
Figura 9. Definirea semnalului r ăspuns TX_Signal2
Mesajul TX_Message3 r ăspuns
transmis de c ătre nodul AutoBox este
configurat cu urm ătorii parametri:
– identificatorul mesajului: 0x120;
– formatul cadrului: standard
(lungimea identificatorului de 11
bi Ńi);
– lungimea câmpului de date de 8
octe Ńi (data length code);
– perioada de 100 milisecunde;
– metoda de transmitere: ciclic.
Figura 10. Definirea mesajului r ăspuns TX_Message3
Capitolul III Descrierea comunica Ńiei de CAN prin fi șierul DBC
– 16 – În interiorul mesajului TX_Message3
se define ște semnalul TX_Signal3 ce con Ńine
valoarea preluat ă de la senzorul 3. Semnalul
este configurat cu urm ătorii parametri:
– lungimea câmpului de date de 8
bi Ńi;
– ordinea bi Ńilor de date de tipul
Motorola;
– offset: 0
– factor: 1
– valoare minim ă: 0
– valoare maxim ă: 255
Figura 11. Definirea semnalului r ăspuns TX_Signal3
Odat ă definite toate semnalele de interes, acestea vor f i asociate nodurilor din re Ńea. Astfel
semnalul de comand ă uC_Signal1 con Ńinut în mesajul uCCommand_Message1 va fi transmis d e
către nodul uController (PCAN) și recep Ńionat de c ătre nodul uAutoBox. Odat ă recep Ńionat
semnalul de comand ă, nodul uAutoBox va transmite semnalele TX_Signal1, TX_Signal2 și
TX_Signal3 con Ńinute în mesajele TX_Message1, TX_Message2 și respectiv TX_Message3,
acestea fiind recep Ńionate de c ătre nodul uController.
Figura 12. Asocierea semnalelor definite fiec ărui nod din re Ńeaua CAN
În formatul text, fi șierul dbc con Ńine
o serie de cuvinte cheie dup ă care sunt
identificate diferite obiecte în momentul
pars ării fi șierului [ref.6].
Cuvinte cheie Semnifica Ńie
BU_ Noduri de re Ńea
BO_ Mesaje
SG_ Semnale
EV_ Variabile
Dup ă descrierea fi șierului dbc cu ajutorul interfe Ńei CANdb Editor, acesta va avea forma:
BU_: uAutoBox uController ## descrierea nodurilor de re Ńea
BO_ 512 uCCommand_Message1: 8 uController ## descri erea mesajului de comand ă
SG_ uC_Signal1 : 7|8@0+ (1,0) [0|255] "" uAutoBox
BO_ 256 TX_Message1: 8 uAutoBox ## descrierea mesa jelor r ăspuns
SG_ TX_Signal1 : 7|8@0+ (1,0) [0|255] "" uControll er
BO_ 272 TX_Message2: 8 uAutoBox
SG_ TX_Signal2 : 7|8@0+ (1,0) [0|255] "" uControll er
BO_ 288 TX_Message3: 8 uAutoBox
SG_ TX_Signal3 : 7|8@0+ (1,0) [0|255] "" uControll er
Capitolul IV Descrierea blocului RTICANMM M ain Block
– 17 –
CAPITOLUL IV
DESCRIEREA BLOCULUI
RTICANMM MAIN BLOCK
Capitolul IV Descrierea blocului RTICANMM M ain Block
– 18 –
IV. Descrierea blocului RTICANMM MainBlock
În cadrul modelului Matlab Simulink, pentru config urarea unei comunica Ńii CAN se va
utiliza blocul multi-mesaj de timp real (real-time interface multimessage main block). Acesta
permite configurarea întregii comunica Ńii a unui controler de CAN de pe o plac ă de CAN dSpace.
Configurarea comunica Ńiei se va face pe baza unui fi șier .dbc (CAN database container) ce are
definit ă întreaga structur ă a comunica Ńiei dorite, nodurile re Ńelei simulate, mesajele asociate fiec ărui
nod din re Ńea, semnalele componente ale fiec ărui mesaj și propriet ăŃile acestora.
Figura 1. Blocul CAN multi-mesaj de timp real [ref. 8]
Pentru identificarea semnalelor de CAN, blocul RTI CANMM afi șeaz ă numele acestora
împreun ă cu numele mesajelor corespunz ătoare din care ele fac parte: MessageName.SignalNam e.
Pentru fiecare bloc multi-mesaj utilizat se va gene ra câte o func Ńie simulink, care împreun ă cu
func Ńia corespunz ătoare controlerului vor fi incluse în procesul de b uild al modelului de Matlab. La
fiecare regenerare a func Ńiei blocului multi-mesaj, un fi șier .trc va fi automat creat. Acest fi șier
con Ńine map ările tuturor resurselor CAN rezultate în urma gener ării func Ńiei blocului multi-mesaj.
Cu ajutorul acestui fi șier se vor vedea toate resursele disponibile prin c are se vor putea analiza
mesaje recep Ńionate sau modifica diferi Ńi parametri din cadrul mesajelor transmise. În urma
gener ării modelului de Matlab, un fi șier model.sdf (system description file) este creat în mod
automat. Acesta con Ńine toate informa Ńiile necesare ce vor fi înc ărcate în fiecare component ă a
platformei de simulare. Dac ă fi șierul cu descrierea sistemului este deschis din Con trolDesk, se vor
reg ăsi toate resursele blocului RTICANMM [ref.8]:
Figura 2. Resursele configura Ńiei de CAN [ref.8]
IV.1 Caracteristicile I/O ale blocului RTICANMM
În tabelul urm ător sunt descrise intr ările disponibile ale blocului [ref.8]:
Intr ări Simulink Interval Tipul de date Descriere
GlobalEnable 0 … 1 Boolean Activeaz ă sau dezactiveaz ă
întreaga comunica Ńie CAN a
controlerului pentru care este definit.
(op Ńiunea este disponibil ă doar dac ă
Capitolul IV Descrierea blocului RTICANMM M ain Block
– 19 – GlobalEnable este selectat în pagina de
op Ńiuni de triggering a RTICANMM)
GlobalEnableTX 0 … 1 Boolean Activeaz ă sau dezactiveaz ă
transmisia tuturor mesajelor definite.
(op Ńiunea este disponibil ă doar dac ă
GlobalEnableTX este selectat în pagina
de op Ńiuni de triggering a RTICANMM)
Triggering
(struct array) – Depinde de structur ă:
– Cyclic : Boolean
– Enable : Boolean
– Kickout : Boolean
– Cycle time : Double
– Delay time : Double
– ECUEnable : Boolean Define ște op Ńiunile de triggering:
enable , cyclic sau kickout separat
pentru fiecare mesaj definit ca TX.
Deasemenea define ște periodicitatea
(cycle time) și întârzierea (delay time)
mesajelor de transmis.
TX Data
(struct array) – Depinde de structur ă Define ște toate semnalele TX ce
vor fi trimise dinspre modelul Matlab.
(op Ńiunea este disponibil ă doar dac ă cel
pu Ńin un semnal este selectat ca semnal
TX de model în pagina Model Signals
TX a RTICANMM)
TX Data Gateway
(struct array) – Depinde de structur ă Define ște semnale de tip gateway
(pentru comunica Ńii între magistrale
diferite) de la alt bloc RTICANMM.
(op Ńiunea este disponibil ă dac ă cel pu Ńin
un mesaj gateway este selectat pe pagina
Gateway Signals a RTICANMM)
În tabelul urm ător sunt descrise ie șirile disponibile din blocul RTICANMM [ref.8]:
Ie șiri Simulink Interval Tipul de date Descriere
Enable 0 … 1 Boolean Furnizeaz ă statusul curent al
controlerului CAN. Ie șirea va fi 1 dac ă
condi Ńia GlobalEnable este adevarat ă și
dac ă blocul RTICANMM este activ.
(op Ńiunea este disponibil ă doar dac ă în
prealabil s-a selectat op Ńiunea de creare
a ie șirii odat ă cu generarea blocului,
op Ńiune disponibil ă din pagina de
Peripheral Options)
RX Data
(struct array) – Depinde de structur ă:
– RX Stat us: Boolean
– TX Status : Boolean Aduce în model mesajele definite
ca RX. Furnizeaz ă statusurile și erorile
atat a mesajelor transmise cât și a celor
recep Ńionate.
(op Ńiunea este disponibil ă doar
dac ă cel pu Ńin un semnal este selectat ca
fiind de tip RX model din pagina Model
Signals RX sau dac ă cel pu Ńin unul din
um ătoarele porturi sunt activate:
– TX Status Ports
– RX Status and Time Ports
– RX Raw Data Ports
– RX Error Ports)
Capitolul IV Descrierea blocului RTICANMM M ain Block
– 20 – IV.2 Parcurgerea fi șierului descriere CAN
Dup ă generarea fi șierului .dbc (database container) cu descrierea com unica Ńiei CAN, acesta
poate fi utilizat la generarea blocului multi-mesaj . Blocul RTICANMM are implementat propriul
mecanism de parcurgere a descrierii CAN, ce permite selectarea și înc ărcarea fi șierului dbc. În
tabelul urm ător sunt prezentate atributele din fi șierul dbc ce sunt recunoscute de mecanismul de
parcurgere automat ă încorporat în blocul RTICANMM [ref.9]:
Atribut dbc Structura Descriere
J1939Mapping
GenMsgCycleTime
GenMsgDelayTime
GenMsgBaseTime
GenMsgUpdateTime
GenMsgSendType
GenSigStartValue dbcdata
dbcdata.Message(x).
– J1939Mapping
– MsgCycleTime
– MsgDelayTime
– MsgBaseTime
– MsgUpdateTime
– MsgSendTypenal
Signal(x).
– InitialValue Structura complet ă CAN
Mapare J1939
Valoarea perioadei mesajului
Valoarea întârzierii mesajului
Valoarea bazei de timp a mesajului
Valoarea timpului de update a mesajului
Modalitatea de trimitere a mesajului
(cyclic sau triggered)
Structura semnalului
Valoarea ini Ńial ă a semnalului
Blocul multi-mesaj are implementat și un mecanism de parcurgere a unei descrieri CAN
dintr-un fisier .mat. Structura fi șierului .mat va fi ca în tabelul urm ător [ref.9]:
Structura Interval Tipul de date Descriere
dbcdata – Struct Structura complet ă a descrierii
CAN
dbcdata.Message(m)
. m = 1 … Struct Structura complet ă a mesajului
CAN
MsgName – String Numele mesajului
MsgId – Valoare numeric ă Identificatorul mesajului în
format decimal
MsgIdFormat 0 … 1 Valoare numeric ă Formatul identificatorului de
mesaj:
0: identificator standard
1: identificator extins
MsgLength 0 … 8 Valoare numeric ă Num ărul de octe Ńi a mesajului
curent
ECU – String Numele ECU ce trimite
mesajul curent
MsgComment – String Comentariu ata șat mesajului
curent
MsgCycleTime 0 … Valoare numeric ă Valoarea perioadei mesajului
MsgDelayTime 0 … Valoare numeric ă Valoarea întârzierii mesajului
MsgBaseTime 0 … Valoare numeric ă Valoarea bazei de timp a
mesajului
MsgUpdateTime 0 … Valoare numeric ă Valoarea timpului de update a
mesajului
MsgSendType – String Tipul de trimitere a mesajului :
– cyclic
– triggered
MsgStartValue ‘0000000000000000h
’ … “ffffffffffffffffh” String Valoarea de start a mesajului
Capitolul IV Descrierea blocului RTICANMM M ain Block
– 21 – J1939active 0 … 1 Valoare numeric ă 0 – neconform standardului
J1939
1 – conform J1939
J1939PGPrio 0 … 7 Valoare numeric ă Prioritatea mesajului J1939
J1939PGDest 0 … 255 Valoare numeric ă Nodul destina Ńie al mesajului
J1939
J1939PGSrc 0 … 255 Valoare numeric ă Nodul surs ă al mesajului J1939
J1939Mapping – String Maparea surs ă-destina Ńie a
mesajului J1939
SendECU – String Nodul (ECU) surs ă
ReceiveECU – String Nodul destina Ńie
Signal(s). s = 1 … 64 Struct Structura semnalului
SgnName – String Numele semnalului
SgnStartBit 0 … 63 Valoare numeric ă Bitul de start al semnalului
SgnLength 1 … 64 Valoare numeric ă Lungimea semnalului
ByteLayout 1 … 2 Valoare numeric ă 1: little endian (LSB primul)
2: big endian (MSB primul)
Factor 1 … Valoare numeric ă Factor de scalare a semnalului
Offset – Valoare numeric ă Valoare de offset a semnalului
SgnComment – String Comentariu pentru semnalul
curent
SgnUnit – String Unitatea de masur ă a
semnalului
Min – Valoare numeric ă Valoare fizic ă minim ă
Max – Valoare numeric ă Valoare fizic ă maxim ă
ReceiveECUs – String Noduri (ECU-uri) ce
recep Ńioneaz ă acest semnal
DataType 0 … 1 Valoare numeric ă 0: unsigned int
1: signed int
InitialValue – Valoare numeric ă Valoarea ini Ńial ă a semnalului
SgnErrorValue [] sau valoare de
eroare Întreg Valoarea semnalului în caz de
eroare. []: nici o valoare
IV.3 Op Ńiuni de trigerare a mesajelor transmise
Blocul multi-mesaj RTICANMM ofer ă o diversitate de op Ńiuni de trigerare a mesajelor
transmise cum sunt [ref.10]:
– condi Ńii globale:
o GlobalEnable: activarea global ă a comunica Ńiei pe CAN per ansamblu
o GlobalEnableTX: activarea global ă a transmisiei pe CAN
– condi Ńii specifice nodurilor (ECU-urilor):
o ECUEnable: activarea transmisiei mesajelor de la un anumit nod al re Ńelei
– condi Ńii specifice mesajelor:
o Enable: activarea anumitor mesaje dintr-un nod
o Timeout: activarea mecanismului de timeout pentru a numite mesaje transmise
o Kickout: transmiterea imediat ă a unui mesaj
o Cyclic: activarea transmisiei periodice a unui anum it mesaj
Condi Ńiile globale de trigerare a mesajelor se aplic ă întregului controler de CAN și nu sunt
aplicabile pe anumite mesaje în parte. Numai condi Ńiile specifice pe mesaje sunt aplicabile pe
fiecare mesaj în parte. În figura urm ătoare sunt prezentate conexiunile logice între toat e condi Ńiile
de trigerare ale mesajelor [ref.10]:
Capitolul IV Descrierea blocului RTICANMM M ain Block
– 22 –
Figura 3. Condi Ńii de trigerare a mesajelor transmise [ref.10]
Fiecare condi Ńie de trigerare poate fi accesat ă atât din interiorul fi șierului .trc dac ă aceasta
este inlus ă, cât și din interiorul modelului dup ă generarea blocului multi-message.
Pentru activarea global ă a comunica Ńiei pe
CAN, condi Ńia GlobalEnable poate fi inclus ă în
fi șierul trc și/sau poate fi scoas ă ca și intrare a
blocului. Dac ă condi Ńia global ă este prezent ă atât în
fi șierul .trc cât și în model, atunci se poate evalua
condi Ńia și dup ă opera Ńia logic ă AND/OR.
Op Ńiunea 1 din figura alaturat ă devine
activ ă (check-button activ) doar atunci când
op Ńiunea a 2-a este bifat ă. Altfel check-ul 1 va fi
inactiv. Dac ă nu este selectat, valoarea implicit ă
este 0.
Figura 4. Condi Ńia de activare global ă [ref.10]
Atunci când op Ńiunea a 2-a este selectat ă, un parametru nou corespunz ător
GlobalEnable_TRC va fi disponibil în fi șierul trc. Dac ă nici una din op Ńiunile 2 sau 5 nu sunt bifate,
atunci valoarea implicit ă a ie șirii din poarta logic ă va fi 1, comunica Ńia pe CAN fiind întotdeauna
activ ă. Alegerea opera Ńiei logice AND sau OR este posibil ă doar dac ă atât op Ńiunea 2 cât și 5 sunt
selectate. Aceasta ofer ă posibilitatea de a alege opera Ńia logic ă între GlobalEnable din fi șierul trc și
GlobalEnable de la intrarea blocului multi-mesaj di n model. Aceea și logic ă este utilizat ă pentru
toate condi Ńiile de trigerare prezentate în figura 3, atât la n ivel global al întregii comunica Ńii pe CAN
cât și la nivel de nod sau mesaj [ref.10].
Capitolul V Pach etul software PCAN Basic
– 23 –
CAPITOLUL V
PACHETUL SOFTWARE
PCAN BASIC
Capitolul V Pach etul software PCAN Basic
– 24 –
V. PCAN Basic
Pachetul PCAN-Basic permite dezvoltarea de aplica Ńii CAN simple pentru comunicarea cu
unul dintre echipamentele hardware oferite de Peak- System (în cadrul aplica Ńiei curente s-a utilizat
adaptorul PCAN-USB). Pachetul ofer ă o colec Ńie de drivere ce încorporeaz ă toate func Ńiile necesare
dezvolt ării de aplica Ńii CAN în timp real. PCAN Basic permite utilizarea a mai multor canale de
CAN în cadrul acelea și aplica Ńii.
Întregul proces de comunica Ńie este împ ărŃit în trei faze: ini Ńializarea, interac Ńionarea și
finalizarea. Pentru a realiza o comunica Ńie CAN pe un canal, este necesar ca acesta s ă fie întâi
ini Ńializat. Dup ă ini Ńializarea canalului, acesta este pregatit pentru co munica Ńia cu magistrala CAN
conectat ă în prealabil la un slot USB al calculatorului prin intermediului echipamentului hardware
extern PCAN-USB. În acest moment se vor putea trans mite sau recep Ńiona mesaje pe magistral ă.
Dup ă finalizarea comunica Ńiei, canalul utilizat trebuie dezini Ńializat pentru a elibera resursele
alocate acestuia și pentru a putea fi utilizat pentru aplica Ńii viitoare [ref.11].
În cele ce urmeaz ă se va discuta pe baza modulului Peak.Can.Basic car e con Ńine diferite
tipuri și clase pentru utilizarea pachetului PCAN-Basic sub limbajul de programare Python.
Astfel este definit ă clasa PCANBasic: class PCANBasi c, care încorporeaz ă toate metodele
disponibile pentru realizarea de aplica Ńii CAN. Se definesc structurile pentru definirea un ui mesaj
de CAN (TPCANMsg) precum și definirea etichetei de timp a unui mesaj de CAN
(TPCANTimestamp). Indexul de timp a unui mesaj de C AN va reprezenta valoarea în
microsecunde de când sistemul de operare a pornit [ ref.11].
from ctypes import *
class TPCANMsg (Structure):
_fields_ = [("ID", c_ulong), ## ID – identificat orul mesajului (11/29 biti)
("MSGTYPE", TPCANMessageType), ## MSGTYPE – tipul mesajului
("LEN", c_ubyte), ## LEN – lun gimea secven Ńei de date (DLC: 0 … 8)
("DATA", c_ubyte * 8 )] ## DATA – câmpul de date (DATA[0] … DATA[7])
class TPCANTimestamp (Structure):
_fields_ = [("millis", c_ulong), ## millis – valo area etichetei de timp în milisecunde
("millis_overflow", c_ushort), ## millis_overflow – overflow counter
("micros", c_ushort)] ## micros – valoarea etiche tei de timp în microsecunde
V.1 Tipuri de date utilizate
Sunt definite urm ătoarele tipuri [ref.11]: TPCANStatus = int ## cod de eroare sau de status.
Python Descriere
PCAN_ERROR_OK = TPCANStatus(0x00000) Nici o eroare
PCAN_ERROR_XMTFULL = TPCANStatus(0x00001) Bufferul de transmisie din controlerul
CAN este plin.
PCAN_ERROR_OVERRUN = TPCANStatus(0x00002 Controlerul CAN a fost citit prea
târziu
PCAN_ERROR_BUSLIGHT = TPCANStatus(0x00004) Eroare de bus: error counter “light”
PCAN_ERROR_BUSHEAVY = TPCANStatus(0x00008) Eroare de bus: error counter “heavy”
PCAN_ERROR_BUSOFF = TPCANStatus(0x00010) Eroare de bus: controlerul de CAN e în
starea bus-off
PCAN_ERROR_ANYBUSERR =
TPCANStatus(PCAN_ERROR_BUSLIGHT |
PCAN_ERROR_BUSHEAVY | PCAN_ERROR_BUSOFF) Eroare de bus: una din cele 3 erori
anterioare este activ ă
PCAN_ERROR_QRCVEMPTY = TPCANStatus(0x00020) Coad ă recep Ńionat ă goal ă.
PCAN_ERROR_QOVERRUN = TPCANStatus(0x00040) Coad ă recep Ńionat ă citit ă prea târziu
PCAN_ERROR_QXMTFULL = TPCANStatus(0x00080) Coad ă transmis ă plin ă
Capitolul V Pach etul software PCAN Basic
– 25 – PCAN_ERROR_REGTEST = TPCANStatus(0x00100) Testul regi ștrilor hardware a
controlerului CAN a e șuat
PCAN_ERROR_NODRIVER = TPCANStatus(0x00200) Driverul nu este înc ărcat
PCAN_ERROR_HWINUSE = TPCANStatus(0x00400) PCAN-Hardware este deja folosit de
către un nod
PCAN_ERROR_NETINUSE = TPCANStatus(0x00800) Un client PCAN este deja conectat la
nod
PCAN_ERROR_ILLHW = TPCANStatus(0x01400) Handle PCAN-Hardware invalid
PCAN_ERROR_ILLNET = TPCANStatus(0x01800) Handle PCAN-Net invalid
PCAN_ERROR_ILLCLIENT = TPCANStatus(0x01C00) Handle PCAN-Client invalid
PCAN_ERROR_ILLHANDLE =
TPCANStatus(PCAN_ERROR_ILLHW |
PCAN_ERROR_ILLNET | PCAN_ERROR_ILLCLIENT) Una dintre erorile de handle este activ ă
PCAN_ERROR_RESOURCE = TPCANStatus(0x02000) Resursele nu pot fi alocate
PCAN_ERROR_ILLPARAMTYPE =
TPCANStatus(0x04000) Parametru invalid
PCAN_ERROR_ILLPARAMVAL =
TPCANStatus(0x08000) Valoare invalid ă a parametrului
PCAN_ERROR_UNKNOWN = TPCANStatus(0x10000) Eroare necunoscut ă
PCAN_ERROR_INITIALIZE = TPCANStatus(0x40000) Canalul nu a fost ini Ńializat
TPCANDevice = c_ubyte ## reprezint ă un dispozitiv PCAN
Python Descriere
PCAN_NONE = TPCANDevice(0x00) Nedefinit
PCAN_PEAKCAN = TPCANDevice(0x01) Dispozitiv non-plug and play
PCAN_ISA = TPCANDevice(0x02) PCAN-ISA, PCAN-PC/104
PCAN_DNG = TPCANDevice(0x03) PCAN-Dongle
PCAN_PCI = TPCANDevice(0x04) PCAN-PCI
PCAN_USB = TPCANDevice(0x05) PCAN-USB
PCAN_PCC = TPCANDevice(0x06) PCAN-PC Card
TPCANParameter = c_ubyte ## reprezint ă un parametru PCAN ce poate fi setat sau o
valoare ce poate fi citit ă.
Python Descriere
PCAN_DEVICE_NUMBER = TPCANParameter(0x01) Num ărul dispozitivului PCAN-USB
PCAN_5VOLTS_POWER = TPCANParameter(0x02) Tensiune 5V PCAN-PC Card
PCAN_RECEIVE_EVENT = TPCANParameter(0x03) Parametru eveniment recep Ńie
PCAN_MESSAGE_FILTER = TPCANParameter(0x04) Parametru filtru mesaj
PCAN_API_VERSION = TPCANParameter(0x05) Versiune PCAN-Basic
PCAN_CHANNEL_VERSION = TPCANParameter(0x06) Versiune canal PCAN
PCAN_BUSOFF_AUTORESET =
TPCANParameter(0x07) Parametru de reset la bus-off
PCAN_LISTEN_ONLY = TPCANParameter(0x08) Parametru de ascultare magistral ă
PCAN_LOG_LOCATION = TPCANParameter(0x09) Cale către fi șierul de log
PCAN_LOG_STATUS = TPCANParameter(0x0A) Status log activ
PCAN_LOG_CONFIGURE = TPCANParameter(0x0B) Configurare informa Ńii log
PCAN_LOG_TEXT = TPCANParameter(0x0C) Inserare text în fi șierul de log
PCAN_CHANNEL_CONDITION =
TPCANParameter(0x0D) Disponibilitatea canalului
PCAN_HARDWARE_NAME = TPCANParameter(0x0E) Nume PCAN Hardware
Capitolul V Pach etul software PCAN Basic
– 26 – PCAN_DEVICE_NUMBER – parametru este utilizat pentr u hardware-ul PCAN-USB
pentru a deosebi între dou ă sau mai multe dispozitive externe conectate la ace la și calculator.
Valoarea parametrului o dat ă setat ă se p ăstreaz ă și dup ă reconectarea dispozitivului. Parametrul
poate lua valori intre 0 – 255.
PCAN_5VOLTS_POWER – parametru utilizat pentru har dware-ul PCAN-PC Card pentru
activarea sursei de tensiune de 5V pe conectorul D- Sub de pe slotul PC. Acest parametru poate lua
una din valorile ON sau OFF. Orice alt ă valoare este considerat ă invalid ă.
PCAN_RECEIVE_EVENT – parametru utilizat pentru not ificarea aplica Ńiilor asupra
faptului c ă exist ă mesaje în coada de citire.
PCAN_MESSAGE_FILTER – parametru ce permite utiliza torului să configureze filtrele de
mesaje pe un canal PCAN. Parametrul poate fi setat ca deschis sau închis. Atunci când este citit este
posibil ca o a treia valoare s ă fie primit ă, PCAN_FILTER_CUSTOM ce indic ă faptul c ă este setat
un filtru cu un anumit interval de ID-uri.
PCAN_API_VERSION – parametru utilizat pentru a pre lua informa Ńii cu privire la
versiunea de PCAN Basic utilizat ă. Valoarea returnat ă de acesta este un string cu informa Ńii
referitoare la versiunea curent ă.
PCAN_CHANNEL_VERSION – parametru utilizat pentru a prelua informa Ńii cu privire la
versiunea driverului unui canal PCAN. Valoarea retu rnat ă este un string.
PCAN_BUSOFF_AUTORESET – parametru utilizat pentru a instrui driverul PCAN s ă
reseteze automat controlerul de CAN a unui canal PC AN atunci când starea bus-off a fost detectat ă.
Parametrul poate lua una din valorile ON sau OFF, i ar orice alt ă valoare este considerat ă invalid ă.
PCAN_LISTEN_ONLY- parametru ce permite utilizatoru lui să seteze un dispozitiv CAN în
modul de ascultare. Atunci când acest mod este acti vat, controlerul de CAN nu ia parte la
evenimentele active (ex. transmiterea de mesaje pe magistral ă) ci st ă doar într-un mod pasiv, de
monitorizare în care poate analiza traficul de pe m agistrala de CAN. Acest parametru poate lua doar
una din valorile ON/OFF, orice alta valoare fiind c onsiderat ă invalid ă. Acest parametru poate fi
utilizat atât pe un canal ini Ńializat cât și pe unul neini Ńializat. Configurând parametrul f ără a
ini Ńializa întâi canalul, se realizeaz ă o preini Ńializare a canalului utilizat. Canalul va fi setat în starea
de ascultare cât mai curând posibil, imediat dup ă conectare.
PCAN_LOG_LOCATION – parametru utilizat pentru prec izarea directorului destina Ńie
pentru fi șierul log în care este înregistrat ă activitatea pe magistral ă. Setarea parametrului conduce la
startarea automat ă a înregistr ării.
PCAN_LOG_STATUS – parameru utilizat pentru a contr ola statusul înregistr ării activit ăŃii
pe magistrala de CAN. Dac ă statusul înregistr ării este setat ON f ără a avea stabilit ă în prealabil
loca Ńia fi șierului de înregistrare sau f ără a configura informa Ńia ce trebuie înregistrat ă, atunci
sesiunea de înregistrare va porni cu valorile impli cite.
PCAN_LOG_CONFIGURE – parametru utilizat pentru con figurarea informa Ńiei ce se
dore ște a fi monitorizat ă și înregistrat ă pe durata unei sesiuni de debug. Parametru poate l ua una sau
o combina Ńie din urm ătoarele valori:
– LOG_FUNCTION_DEFAULT: define ște informa Ńia implicit ă pentru monitorizare, cum
ar fi o excep Ńie nea șteptat ă sau o violare a unei zone de memorie. Dup ă configurarea
unei sesiuni cu mai multe op Ńiuni, aceast ă valoare poate fi setata pentru a reveni la starea
implicit ă. În fi șierul de log, o astfel de înregistrare va fi marcat ă cu “EXCEPTION”.
– LOG_FUNCTION_ENTRY: aceast ă valoare conduce la o scriere în fi șierul de
înregistrare de fiecare dat ă când o func Ńie PCAN Basic este apelat ă. În fi șierul de log,
aceast ă înregistrare va fi marcat ă cu “ENTRY”.
– LOG_FUNCTION_PARAMETERS: valoare ce genereaz ă o înregistrare în fi șierul de
log de fiecare dat ă când o func Ńie PCAN Basic este apelat ă, înregistrând totodat ă și
numele parametrilor cu care func Ńia a fost apelat ă. Înregistrarea va fi marcat ă în fi șierul
de log cu “PARAMETERS”.
Capitolul V Pach etul software PCAN Basic
– 27 – – LOG_FUNCTION_LEAVE: valoare ce genereaz ă o înregistrare în fi șierul de log de
fiecare dat ă când o funcŃie PCAN Basic este abandonat ă. Acest tip de înregistrare este
marcat ă în fi șierul de log cu “EXIT”.
– LOG_FUNCTION_WRITE: valoare ce genereaz ă o înregistrare în fi șierul de log de
fiecare dat ă când este transmis un mesaj de CAN. Aceasta va fi marcat ă în fișierul de log
cu “CHANNEL 0xXX (OUT)”.
– LOG_FUNCTION_READ: valoare ce genereaz ă o înregistrare de fiecare dat ă când este
recep Ńionat un mesaj de CAN. Acest tip de înregistrare va fi marcat ă în fi șierul de log cu
“CHANNEL 0xXX (IN)”.
PCAN_LOG_TEXT – parametru utilizat pentru a insera informa Ńii în fi șierul de înregistrare
în timpul unei sesiuni de debug. Setarea acestui pa rametru conduce la startarea automat ă a sesiunii
de debug.
PCAN_CHANNEL_CONDITION – parametru utilizat pentru verificarea și detectarea de
dispozitive hardware PCAN disponibile pe sta Ńia de lucru. Parametrul poate lua una din valorile
UNAVAILABLE, AVAILABLE sau OCCUPIED.
PCAN_HARDWARE_NAME – parametru utilizat pentru a re turna numele unui dispozitiv
hardware reprezentat printr-un canal PCAN.
TPCANMessageType = c_ubyte ## reprezint ă tipul unui mesaj de CAN.
Python Descriere
PCAN_MESSAGE_STANDARD = TPCANMessageType(0x00) Format standard (11 bi Ńi)
PCAN_MESSAGE_RTR = TPCANMessageType(0x01) Cerere de date
PCAN_MESSAGE_EXTENDED = TPCANMessageType(0x02) Format extins (29 bi Ńi)
PCAN_MESSAGE_STATUS = TPCANMessageType(0x80) Mesaj de tip status
TPCANType = c_ubyte ## reprezint ă tipul de hardware PCAN (non-plug and play) ce
urmeaz ă a fi ini Ńializat.
Python Descriere
PCAN_TYPE_ISA = TPCANType(0x01) PCAN-ISA 82C200
PCAN_TYPE_ISA_SJA = TPCANType(0x09) PCAN-ISA SJA1000
PCAN_TYPE_ISA_PHYTEC = TPCANType(0x04) PHYTEC ISA
PCAN_TYPE_DNG = TPCANType(0x02) PCAN-Dongle 82C200
PCAN_TYPE_DNG_EPP = TPCANType(0x03) PCAN-Dongle EPP 82C200
PCAN_TYPE_DNG_SJA = TPCANType(0x05) PCAN-Dongle SJA1000
PCAN_TYPE_DNG_SJA_EPP = TPCANType(0x06) PCAN-Dongle EPP SJA1000
TPCANMode = c_ubyte ## reprezint ă tipul de filtru dup ă formatul cadrelor (standard sau
extinse).
Python Valoare Descriere
PCAN_MODE_STANDARD = PCAN_MESSAGE_STANDARD 0 Mod standard(11 bi Ńi)
PCAN_MODE_EXTENDED = PCAN_MESSAGE_EXTENDED 2 Mod extins(29 bi Ńi)
TPCANBaudrate = c_ushort ## reprezint ă valoarea ratei de transmisie pe magistral ă.
Python Descriere
PCAN_BAUD_1M = TPCANBaudrate(0x0014) 1 MBit/s
PCAN_BAUD_800K = TPCANBaudrate(0x0016) 800 KBit/s
PCAN_BAUD_500K = TPCANBaudrate(0x001C) 500 KBit/s
Capitolul V Pach etul software PCAN Basic
– 28 – PCAN_BAUD_250K = TPCANBaudrate(0x011C) 250 KBit/s
PCAN_BAUD_125K = TPCANBaudrate(0x031C) 125 KBit/s
PCAN_BAUD_100K = TPCANBaudrate(0x432F) 100 KBit/s
PCAN_BAUD_95K = TPCANBaudrate(0xC34E) 95,238 KBit/s
PCAN_BAUD_83K = TPCANBaudrate(0x4B14) 83,333 KBit/s
PCAN_BAUD_50K = TPCANBaudrate(0x472F) 50 KBit/s
PCAN_BAUD_47K = TPCANBaudrate(0x1414) 47,619 KBit/s
PCAN_BAUD_33K = TPCANBaudrate(0x1D14) 33,333 KBit/s
PCAN_BAUD_20K = TPCANBaudrate(0x532F) 20 KBit/s
PCAN_BAUD_10K = TPCANBaudrate(0x672F) 10 KBit/s
PCAN_BAUD_5K = TPCANBaudrate(0x7F7F) 5 KBit/s
Metodele definite pentru clasa PCANBasic sunt împa r Ńite în patru categorii în func Ńie de
func Ńionalitate dup ă cum urmeaz ă [ref.11]:
– Conexiune:
o Ini Ńializarea unui canal PCAN: Initialize
o Dezini Ńializarea unui canal PCAN: Uninitialize
– Configurare :
o Setarea unei configura Ńii sau a unui parametru pentru un canal PCAN: SetValue
o Configurarea unui filtru la recep Ńie pentru un canal PCAN: FilterMessages
– Informa Ńie :
o Preluarea de informa Ńii de pe un canal PCAN: GetValue
o Preluarea statusului curent al busului de pe un can al PCAN: GetStatus
o Returnarea unui text descriptiv pentru coduri de er oare: GetErrorText
– Comunica Ńie:
o Citirea unui mesaj de CAN din coada recep Ńionat ă pe un canal PCAN: Read
o Transmiterea unui mesaj CAN pe un canal PCAN: Write
o Resetarea cozii recep Ńionate sau transmise pe un canal PCAN: Reset
V.2 Ini Ńializarea unui canal PCAN
Metoda de ini Ńializare este definit ă astfel [ref.11]:
– def Initialize(self, Channel, Btr0Btr1) în cazul unui device plug and play, având ca
parametri canalul de PCAN și viteza de comunica Ńie (baud rate).
# canalul PCAN USB1 va fi ini Ńializat
objPCAN = PCANBasic()
result = objPCAN.Initialize(PCAN_USBBUS1, PCAN_BAUD _500K)
if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
– def Initialize(self, Channel, Btr0Btr1, HwType = TPCANType(0), IOPort = c_uint(0),
Interrupt = c_ushort(0)) în cazul unui device de tip non-plug and play, ce are ca parametri canalul
de PCAN ce se dore ște a fi ini Ńializat, viteza de comunica Ńie, tipul de hardware și modul de operare
(de tipul TPCANMode – standard sau extended), adres a I/O a portului paralel, num ărul de
întreruperi a portului paralel.
objPCAN = PCANBasic()
result = objPCAN.Initialize(PCAN_DNGBUS1, PCAN_BAUD _500K, PCAN_TYPE_DNG_SJA,
0x378, 7)
Capitolul V Pach etul software PCAN Basic
– 29 – if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
Valoarea returnat ă este una de tipul TPCANStatus. În cazul în care in i Ńializarea s-a realizat
cu succes atunci se va returna valoarea PCAN_ERROR_ OK. Erorile tipice ce pot ap ărea la
ini Ńializare sunt [ref.11]:
– PCAN_ERROR_ILLHANDLE: canalul PCAN nu este disponib il.
– PCAN_ERROR_INITIALIZE: canalul nu poate fi conectat fiind deja utilizat.
– PCAN_ERROR_NETINUSE: canalul este utilizat cu o vit ez ă de transmisie diferit ă.
– PCAN_ERROR_HWINUSE: canalul este deja utilizat.
– PCAN_ERROR_NODRIVER: driverul necesar pentru conect area canalului nu este
conectat.
– PCAN_ERROR_REGTEST: în cazul dispozitivelor de tip non-plug and play, indic ă
probleme cu verificarea hardware, în mod normal dat orit ă unor valori eronate în
câmpurile HwType, IOPort sau Interrupt.
Prin apelarea metodei se dore ște ini Ńializarea unui canal, preg ătirea acestuia pentru
comunica Ńie în cadrul re Ńelei din care face parte. Apelarea altor metode va conduce la erori dac ă
sunt apelate pentru un canal ce nu a fost ini Ńializat în prealabil. Fiecare canal trebuie dezini Ńializat
dup ă terminarea comunica Ńiei. Ini Ńializarea unui canal presupune: rezervarea canalulu i pentru
metodele ce urmeaz ă a fi apelate, alocarea resurselor necesare cum ar fi alocarea de cozi pentru
recep Ńia și transmiterea mesajelor, conectarea dispozitivelor hardware, deschiderea filtrelor de
mesaje și setarea diferi Ńilor parametri la valorile implicite [ref.11].
Ini Ńializarea unui canal va e șua în cazul în care acela și canal a fost ini Ńializat în prealabil în
cadrul aceleeași aplica Ńii.
V.3 Dezini Ńializarea unui canal PCAN
Metoda de dezini Ńializare este definit ă astfel [ref.11]: def Uninitialize(self, Channel) având
ca parametru canalul PCAN ce se dore ște a fi dezini Ńializat.
# canalul PCAN_USBBUS1 este eliberat
result = objPCAN.Uninitialize(PCAN_USBBUS1)
if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
Valoarea returnat ă este una de tip TPCANStatus. Dac ă eliberarea canalului se realizeaz ă cu
succes atunci valoarea returnat ă va fi PCAN_ERROR_OK. Eroarea tipic ă în cazul unei
dezini Ńializ ări e șuate este PCAN_ERROR_INITIALIZE, canalul ce se dore ște a fi dezini Ńializat se
reg ăse ște în lista de canale rezervate a aplica Ńiei [ref.11].
V.4 Configurarea parametrilor unui canal PCAN
Metoda de setare a unei configura Ńii pentru un canal PCAN se define ște astfel [ref.11]:
def SetValue(self, Channel, Parameter, Buffer) având ca parametri de intrare canalul PCAN
ce se dore ște a fi configurat, parametrul ce se dore ște a fi setat, de tipul TPCANParameter și
valoarea dorit ă a parametrului.
## configurarea c ăii unde fi șierul de log va fi salvat în urma unei sesiuni de d ebug
strBuffer = "C:\Users\Admin\Desktop"
result = objPCAN.SetValue(PCAN_USBBUS1, PCAN_LOG_LO CATION, strBuffer)
Capitolul V Pach etul software PCAN Basic
– 30 – if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
Valoarea returnat ă va fi una de tipul TPCANStatus. Erorile uzual retu rnate pot fi [ref.11]:
– PCAN_ERROR_ILLPARAMVAL – indic ă faptul c ă parametrii da Ńi ca intrare sunt
invalizi. Parametrul ‘Buffer’ trebuie s ă fie de tipul suportat de parametrul a c ărui valoare
se dore ște a fi configurat ă.
– PCAN_ERROR_INITIALIZE – canalul PCAN nu se reg ăse ște în lista de canale
ini Ńializate în cadrul aplica Ńiei curente.
– PCAN_ERROR_ILLPARAMTYPE – parametrul ce se dore ște a fi configurat nu este
aplicabil canalului PCAN pentru care este setat. Ex ist ă parametri ce nu pot fi configura Ńi
pentru toate tipurile de canale PCAN sau valoarea p arametrului nu este disponibil ă
pentru aceste canale.
Metoda SetValue poate fi utilizat ă pentru a configura diferite informa Ńii sau parametri
specifici canalelor PCAN, parametri ca filtre de me saje recep Ńionate sau înregistr ări în fi șiere de log
pe durata unor sesiuni de debug.
V.5 Configurarea filtrului de mesaje recep Ńionate
Metoda de configurare a unui filtru de mesaje se de fine ște astfel [ref.11]:
def FilterMessages(self, Channel, FromID, ToID, Mod e) având ca parametri de intrare
canalul PCAN pentru care se dore ște configurarea filtrului de recep Ńie, intervalul de identificatori ce
se doresc a fi filtra Ńi, interval definit prin capetele acestuia, și tipul de mesaje pentru care se dore ște
a fi configurat filtrul, de tipul TPCANMode (format ul standard sau extins).
## filtrul trebuie închis înainte de configurare
result = objPCAN.SetValue(PCAN_USBBUS1, PCAN_MESSAG E_FILTER,
PCAN_FILTER_CLOSE)
if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
else:
# filtrul de recep Ńie este configurat s ă recep Ńioneze ID-urile 2, 3, 4 și 5 pe PCAN_USBBUS1
result = objPCAN.FilterMessages(PCAN_USBBUS1, 2, 5, PCAN_MODE_STANDARD)
if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
Valoarea returnat ă în urma apel ării metodei va fi una de tipul TPCANStatus. Eroarea tipic ă
în cazul e șuării configur ării filtrului este PCAN_ERROR_INITIALIZE, canalul P CAN nefiind g ăsit
în lista de canale ini Ńializate în cadrul aplica Ńiei curente [ref.11].
Apelarea metodei nu seteaz ă filtrul între limitele definite ca parametri de in trare, ci l ărge ște
filtrul. Imediat dup ă ini Ńializarea unul canal PCAN, filtrul canalului este d eschis în întregime
permi Ńând recep Ńionarea tuturor mesajelor. Astfel dac ă se define ște un interval mic de identificatori
ce se doresc a fi recep Ńiona Ńi, metoda nu va avea efectul dorit deoarece se vor recep Ńiona și restul
mesajelor a c ăror identificatori sunt înafara intervalului specif icat Din acest motiv filtrul trebuie
închis înainte de configurarea și definirea unui interval de identificatori [ref.11 ].
Capitolul V Pach etul software PCAN Basic
– 31 – Prin parametrul de intrare ‘Mode’ se va specifica t ipul de identificatori utiliza Ńi pentru
definirea intervalului de filtrare. Valorile posibi le ale acestui parametru sunt ‘Standard’ (pentru
formatul cu identificator de 11 bi Ńi) sau ‘Extended’ (identificatori de 29 bi Ńi) [ref.11].
V.6 Preluarea informa Ńiilor de pe un canal PCAN
Metoda de preluare a informa Ńiilor de pe un canal se define ște astfel [ref.11]:
def GetValue(self, Channel, Parameter) având ca parametri de intrare canalul PCAN de pe
care se dore ște preluarea informa Ńiilor și parametrul care se vrea preluat.
## preluarea informa Ńiilor cu privire la filtrul configurat pe canalul P CAN_USBBUS1
result = objPCAN.GetValue(PCAN_USBBUS1,PCAN_MESSAGE _FILTER)
if result[0] != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result
else:
# afi șeaz ă statusul curent al filtrului configurat
if result[1] == PCAN_FILTER_OPEN:
print "Filtrul de mesaje recep Ńionate al PCAN_USBBUS1 este deschis"
elif result[1] == PCAN_FILTER_CLOSE:
print "Filtrul de mesaje recep Ńionate al PCAN_USBBUS1 este închis"
elif result[1] == PCAN_FILTER_CUSTOM:
print "Filtrul de mesaje recep Ńionate al PCAN_USBBUS1 este configurat pe un
anumit interval de identificatori"
Valoarea returnat ă prin apelarea metodei va fi o tupl ă din care primul element al acesteia va
fi codul de eroare returnat în cazul apel ării metodei, iar al doilea element va fi valoarea
parametrului pentru care s-a ini Ńiat apelarea metodei de preluarea a informa Ńiilor. În cazul apel ării
cu succes a metodei, codul returnat va fi PCAN_ERRO R_OK, iar în cazul unei apel ări eronate
codurile de eroare posibile ce vor fi returnate sun t [ref.11]:
– PCAN_ERROR_ILLPARAMVAL – parametrii cu care metoda a fost apelat ă sunt
invalizi.
– PCAN_ERROR_INITIALIZE – canalul PCAN de pe care se face preluarea de
informa Ńii nu se reg ăse ște în lista de canale ini Ńializate în cadrul aplica Ńiei curente.
– PCAN_ERROR_ILLPARAMTYPE – informa Ńiile ce se doresc a fi preluate nu sunt
disponibile pentru canalul dorit. Tipul informa Ńiilor ce pot fi preluate difer ă în func Ńie de
tipul canalului.
V.7 Preluarea statusului magistralei de pe un canal PCAN
Metoda de preluare a statusului magistralei de CAN se define ște astfel [ref.11]:
def GetStatus(self, Channel) – primind ca parametru canalul de pe care se dore ște a fi preluat
statusul magistralei.
## se cite ște statusul magistralei de pe canalul PCAN_USBBUS1
result = objPCAN.GetStatus(PCAN_USBBUS1)
if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
Valoarea returnat ă este una de tipul TPCANStatus și poate fi una din urm ătoarele [ref.11]:
Capitolul V Pach etul software PCAN Basic
– 32 – – PCAN_ERROR_INITIALIZE – canalul PCAN dat ca paramet ru nu se reg ăse ște în lista
de canale ini Ńializate în cadrul aplica Ńiei curente.
– PCAN_ERROR_BUSLIGHT – indic ă o eroare pe canalul dat ca parametru, counterul de
erori este “light”.
– PCAN_ERROR_BUSHEAVY – indic ă o eroare pe canalul PCAN, counter de errori
fiind “heavy”.
– PCAN_ERROR_BUSOFF – indic ă o eroare pe canalul PCAN, controlerul de CAN este
în starea bus-off.
– PCAN_ERROR_OK – indic ă faptul ca statusul canalului dat ca parametru este ok.
Când dispozitivul hardware este în starea bus-off, comunica Ńia nu mai are loc. O metoda de
a reseta erorile de tipul bus-off, bus-light sau bu s-heavy este prin deazini Ńializare și reini Ńializarea
canalului PCAN.
V.8 Returnarea unui text descriptiv pentru un cod d e eroare
Metoda de preluare a textului corespunz ător codului de eroare se define ște astfel [ref.11]:
def GetErrorText(self, Error, Language = 0) având ca parametri de intrare codul de eroare
pentru care se preia textul descriptiv și identificatorul corespunz ător limbii.
# preluarea descrierii text a codului de eroare PCA N_ERROR_INITIALIZE în limba spaniol ă
objPCAN = PCANBasic()
result = objPCAN.GetErrorText(PCAN_ERROR_INITIALIZE , 10)
if result[0] != PCAN_ERROR_OK:
print "Eroare aparut ă în timpul prelu ării textului descriptiv"
else:
print result[1]
Valoarea returnat ă prin apelarea metodei este o tupl ă bidimensional ă. Primul element al
tuplei îl reprezint ă o valoare de tipul TPCANStatus. Dac ă apelarea metodei s-a f ăcut cu succes
atunci va fi returnat PCAN_ERROR_OK, iar dac ă apelarea e șueaz ă atunci eroarea tipic ă ce poate fi
returnat ă este PCAN_ERROR_ILLPARAMVAL ce indic ă faptul c ă parametrii da Ńi la intrarea
metodei sunt invalizi. Al doilea element al tuplei va fi textul descriptiv corespunz ător codului de
tipul TPCANStatus [ref.11].
Identificatorii de limb ă sunt coduri utilizate de sistemul de operare Windo ws. Urm ătorii
identificatori de limb ă sunt suporta Ńi de PCAN Basic [ref.11]:
Limba Identificator
Implicit (în func Ńie de limba primar ă a OS) 00h (0)
Englez ă 09h (9)
German ă 07h (7)
Francez ă 0Ch (12)
Italian ă 10h (16)
Spaniol ă 0Ah (10)
V.9 Recep Ńionarea unui mesaj CAN de pe un canal PCAN
Metoda de citire a unui mesaj de pe un canal PCAN s e define ște astfel [ref.11]:
def Read(self, Channel) și are ca parametru de intrare canalul PCAN de pe ca re se dore ște a
se face recep Ńionarea de mesaje.
readResult = PCAN_ERROR_OK,
while (readResult[0] & PCAN_ERROR_QRCVEMPTY) != PCA N_ERROR_QRCVEMPTY:
# verific ă mesaje recep Ńionate în coada de recep Ńie
readResult = objPCAN.Read(PCAN_USBBUS1)
Capitolul V Pach etul software PCAN Basic
– 33 – if readResult[0] == PCAN_ERROR_OK:
# procesare mesaj recep Ńionat
print "Un mesaj a fost recep Ńionat"
# o func Ńie de procesare poate fi apelat ă aici: ProcessMessage(readResult[1],
readResult[2])
else:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(readResult[0])
print result[1]
Valoarea returnat ă dup ă apelarea metodei de citire a unui mesaj este o tup l ă tridimensional ă.
Primul element al tuplei este un cod de eroare de t ip TPCANStatus. Valoarea PCAN_ERROR_OK
va fi returnat ă în cazul în care recep Ńia s-a realizat cu succes. Erorile tipice ce pot ap ărea sunt
urm ătoarele [ref.11]:
– PCAN_ERROR_ILLPARAMVAL – indic ă faptul ca parametrii da Ńi ca intrare sunt
invalizi.
– PCAN_ERROR_INITIALIZE – canalul PCAN pe care se dor e ște recep Ńionarea
mesajelor nu se reg ăse ște în lista de canale ini Ńializate în cadrul aplica Ńiei curente.
– PCAN_ERROR_BUSLIGHT – indic ă o eroare de bus pe canalul PCAN pe care se face
recep Ńia. Dispozitivul hardware este în starea bus-light.
– PCAN_ERROR_BUSHEAVY– indic ă o eroare de bus pe canalul PCAN pe care se face
recep Ńia. Dispozitivul hardware este în starea bus-heavy.
– PCAN_ERROR_BUSOFF – indic ă o eroare de bus pe canalul PCAN pe care se face
recep Ńia. Dispozitivul hardware este în starea bus-off.
– PCAN_ERROR_QRCVEMTY – coada de recep Ńie corespunz ătoare canalului PCAN
este goal ă.
Al doilea element al tuplei returnate este o struct ur ă de tipul TPCANMsg descriind mesajul
recep Ńionat. Din structur ă pot fi preluate informa Ńiile de identificator (msg.ID), tipul mesajului
(format standard sau extins – msg.MSGTYPE), lungime a câmpului de date (DLC – msg.LEN) și
câmpul de date al mesajului recep Ńionat (msg.DATA[0] … msg.DATA[7]) [ref.11].
Al treilea element al tuplei este o structur ă de tipul TPCANTimestamp din care se vor prelua
informa Ńiile cu privire la momentul de timp al recep Ńion ării mesajului [ref.11].
Sunt dou ă modalit ăŃi de citire a mesajelor recep Ńionate din coada unui canal PCAN. Prima
modalitate este prin citire ciclic ă apelând periodic metoda de citire. În mod uzual în cadrul
aplica Ńiilor se utilizeaz ă un timer care va apela la o anumit ă perioad ă metoda de citire din coada de
recep Ńie a canalului, pân ă când coada nu mai con Ńine nici un mesaj sau pân ă când o alt ă eroare de
recep Ńionare apare. O a doua modalitate de citire este pr in intermediul evenimentelor. Driverul
PCAN poate fi configurat s ă notifice prezen Ńa unui nou mesaj în coada de recep Ńie a canalului.
Astfel în cadrul aplica Ńiei nu mai este necesar s ă se verifice sistematic coada de recep Ńie, iar timpul
de recep Ńionare al mesajelor se va diminua considerabil [ref .11].
În cazul în care apare o eroare de tip bus-off, can alul PCAN nu mai poate fi utilizat pentru
comunica Ńie în cadrul aplica Ńiei curente pân ă când controlerul de CAN este resetat. Resetarea
controlerului nu se poate face manual, dar se poate face automat prin configurarea parametrului
PCAN_BUSOFF_AUTORESET. O alt ă metod ă de a reseta erori de tip bus-off, bus-light sau bu s-
heavy este prin dezini Ńializarea și reini Ńializarea canalului PCAN [ref.11].
V.10 Transmiterea unui mesaj CAN pe un canal PCAN
Metoda de transmitere a unui mesaj CAN se define ște astfel [ref.11]:
def Write(self, Channel, MessageBuffer) având ca parametri de intrare canalul PCAN pe
care se dore ște transmisia de mesaje și o structur ă de tipul TPCANMsg cu descrierea mesajului ce
se dore ște a fi transmis pe canal. În cadrul structurii de tip TPCANMsg se vor defini identificatorul
Capitolul V Pach etul software PCAN Basic
– 34 – mesajului, tipul (standard sau extins), lungimea câ mpului de date (DLC) și datele ce se doresc a fi
transmise.
# configurarea mesajului de CAN
msg = TPCANMsg()
msg.ID = 0x100
msg.MSGTYPE = PCAN_MESSAGE_STANDARD
msg.LEN = 3
msg.DATA[0] = 1
msg.DATA[1] = 2
msg.DATA[2] = 3
# transmiterea mesajului pe canalul PCAN_USBBUS1
result = objPCAN.Write(PCAN_USBBUS1, msg)
if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result
else:
print "Mesaj transmis cu succes."
Valoare returnat ă la apelarea metodei de scriere este una de tip TPC ANStatus. Valoarea
PCAN_ERROR_OK va fi returnat ă în cazul în care mesajul a fost transmis cu succes . Erorile
posibile ce pot ap ărea sunt [ref.11]:
– PCAN_ERROR_ILLPARAMVAL – indic ă faptul c ă parametrii da Ńi ca intrare sunt
invalizi. Parametrul ‘MessageBuffer’ trebuie s ă indice către o structur ă de tipul
TPCANMsg în care s-au definit în prealabil identifi catorul, tipul mesajului, lungimea
câmpului de date și datele de transmis.
– PCAN_ERROR_INITIALIZE – canalul PCAN pe care se dor este transmiterea
mesajului nu se regase ște în lista canalelor ini Ńializate în cadrul aplica Ńiei curente.
– PCAN_ERROR_BUSOFF – indic ă o eroare de bus. Dispozitivul hardware se afla în
starea bus-off.
– PCAN_ERROR_QXMTFULL – coada de transmisie a canalul ui este plin ă.
V.11 Resetarea unui canal PCAN
Metoda de resetare este definit ă [ref.11]: def Reset(self, Channel) și are ca parametru canalul
PCAN ce se dore ște a se reseta.
## canalul PCAN_USBBUS1 este resetat
result = objPCAN.Reset(PCAN_USBBUS1)
if result != PCAN_ERROR_OK:
# dac ă apare o eroare se va afi șa textul descriptiv corespunz ător
result = objPCAN.GetErrorText(result)
print result[1]
Valoarea returnat ă va fi una de tip TPCANStatus. Dac ă resetarea canalului se face cu succes
atunci va fi returnat PCAN_ERROR_OK. Eroarea cea ma i comun ă ce poate fi returnat ă în caz de
eșuare este PCAN_ERROR_INITIALIZE, canalul PCAN nefii nd g ăsit în lista de canale deja
ini Ńializate în cadrul aplica Ńiei curente. Apelarea acestei metode șterge doar cozile corespunz ătoare
canalului. Nu se realizeaz ă o resetare a controlerului de CAN [ref.11].
Capitolul V Pach etul software PCAN Basic
– 35 – V.12 Definirea valorilor posibile a parametrilor PC AN
Valori de activare [ref.11]:
Constanta Valoare Descriere
PCAN_ERROR_OFF 0 Parametrul PCAN nu este setat.
PCAN_ERROR_ON 1 Parametrul PCAN activat.
Valori de configurare a filtrelor [ref.11]:
Constanta Valoare Descriere
PCAN_FILTER_CLOSE 0 Filtrul PCAN este închis. Nici un mesaj nu va fi
recep Ńionat.
PCAN_FILTER_OPEN 1 Filtrul PCAN este deschis. Toate mesajele vor fi
recep Ńionate.
PCAN_FILTER_CUSTOM 2 Filtrul PCAN este configurat. Numai mesajele ce
corespund criteriilor de filtrare vor fi recep Ńionate.
Disponibilitatea unui canal PCAN [ref.11]:
Constanta Valoare Descriere
PCAN_CHANNEL_UNAVAILABLE 0 Canalul PCAN definit nu exist ă sau dispozitivul
hardware corespunz ător nu este disponibil.
PCAN_CHANNEL_AVAILABLE 1 Canalul PCAN este conectat corespunz ător și
ini Ńializat. Pentru dispozitive de tip plug-and-play,
semnificaŃia este c ă hardware-ul este conectat.
PCAN_CHANNEL_OCCUPIED 2 Canalul PCAN este valid și momentan este utilizat.
Valori de configurare a unei sesiuni de debug [ref. 11]:
Constanta Valoare Descriere
LOG_FUNCTION_DEFAULT 0x00 Sunt înregistrate erorile și excep Ńiile ap ărute în
timpul comunica Ńiei. Logurile definite de c ătre
utilizator sunt deasemenea înregistrate.
LOG_FUNCTION_ENTRY 0x01 Sunt înregistrate apelurile c ătre metodele specifice
PCAN Basic.
LOG_FUNCTION_PARAMETERS 0x02 Sunt înregistrate numele parametrilor da Ńi ca intr ări
în apelarea metodelor specifice PCAN Basic.
LOG_FUNCTION_LEAVE 0x04 Sunt înregistrate ie șirile din func Ńiile specifice
PCAN Basic.
LOG_FUNCTION_WRITE 0x08 Sunt înregistrate mesajele CAN transmise prin
apelarea metodei Write.
LOG_FUNCTION_READ 0x10 Sunt înregistrate mesajele CAN recep Ńionate prin
apelarea metodei Read.
Capitolul VI Interfa Ńa grafic ă PCAN
– 36 –
CAPITOLUL VI
INTERFA łA GRAFIC Ă PCAN
Capitolul VI Interfa Ńa grafic ă PCAN
– 37 –
VI. Interfa Ńa grafic ă PCAN
Prin prezenta aplica Ńie s-a dorit implementarea unei interfe Ńe grafice prin intermediul c ăreia
utilizatorul să poat ă citi în timp real valorile actuale ale unor senzor i furnizate pe o magistral ă de
CAN. Prin extindere, aplica Ńia curent ă poate fi utilizat ă cu succes în cazul citirii de informa Ńii pe CAN
de la senzori de orice natura și mai departe informa Ńiile recep Ńionate pot fi procesate în func Ńie de
specificul aplica Ńiei dorite. Avantajul major al aplica Ńiei îl constituie costul redus al echipamentelor
necesare. Schema bloc a aplica Ńiei este prezentat ă în figura urm ătoare:
Figura 1. Schema bloc a proiectului
Prin intermediul interfe Ńei grafice, utilizatorul va fi capabil s ă realizeze o serie de opera Ńiuni de
transmisie și recep Ńie pe magistrala de CAN. Dispozitivul hardware PCAN USB de la Peak Systems
va realiza interfa Ńa cu mediul hardware al magistralei. În cadrul apli caŃiei re Ńeaua de CAN este
reprezentat ă prin dou ă noduri de re Ńea, nodul MicroAutoBox și nodul PCAN, dar dispozitivul
hardware PCAN USB poate fi conectat la orice re Ńea CAN disponibil ă realizând interfa Ńarea cu orice
calculator personal. Astfel posibilit ăŃile devin nelimitate, fiind posibil ă recep Ńionarea și transmisia de
orice informa Ńii în cadrul re Ńelei, simularea de noduri de re Ńea, analiz ă și sesiuni de debug în cadrul
re Ńelei de CAN.
Interfa Ńa grafic ă a aplica Ńiei este împ ărŃit ă în dou ă sec Ńiuni, o parte de comand ă, în care
utilizatorul poate efectua comenzi de citire a valo rilor furnizate de oricare din senzori sau poate
transmite manual orice informa Ńii pe CAN. Este posibil ă selectarea independent ă a senzorilor pentru
citirea valorilor actuale instantaneu sau ciclic pr in configurarea perioadei de timp la care se dore ște
preluarea datelor. În partea de transmisie de mesaj e pe CAN, utilizatorul are posibilitatea de a
configura orice parametru al mesajelor de CAN trans mise: identificatorul mesajulul, formatul cadrului
de tipul standard sau extins, lungimea câmpului de date și configurarea datelor ce urmeaz ă a fi
transmise. Mesajele se pot transmite o singur ă dat ă sau ciclic prin configurarea unei perioade de timp
la care mesajul va fi transmis pe magistral ă.
Cea de-a doua sec Ńiune a interfe Ńei grafice este destinat ă afi șă rii valorilor furnizate de senzori
la comanda utilizatorului și a momentului de timp la care datele au fost prelu ate, precum și
informa Ńiile referitoare la opera Ńiunile executate prin intermediul aplica Ńiei sau afi șarea erorilor
corespunz ătoare opera Ńiunilor e șuate.
Interfa Ńa grafic ă a aplica Ńiei este prezentat ă în figura urm ătoare:
Capitolul VI Interfa Ńa grafic ă PCAN
– 38 –
Figura 2. Interfa Ńa grafic ă PCAN
VI.1 Ini Ńializarea canalului PCAN
Dupa conectarea unui dispozitiv hardware PCAN USB, singurul canal de CAN ce va putea fi
accesat va fi PCAN_USBBUS1. Odat ă deschis ă aplica Ńia, indiferent de opera Ńiunea ce urmeaz ă a se
efectua, primul pas este acela de ini Ńializare a canalului PCAN_USBBUS1. Informa Ńia se reg ăse ște în
fereastra “Informations” de afi șare a detaliior privind opera Ńiunile efectuate, din partea de jos a
aplica Ńiei. Ac Ńiunea declan șat ă în momentul ac Ńion ării butonului de ini Ńializare este definit ă de func Ńia:
## define action for pcan channel initialization bu tton
def INITIALIZE(self):
## initialize PCAN_USBBUS1 channel
result_initialize = objPCAN.Initialize(PCAN _USBBUS1, PCAN_BAUD_500K)
Capitolul VI Interfa Ńa grafic ă PCAN
– 39 – if result_initialize != PCAN_ERROR_OK:
## if an error occurred, get a text des cribing the error and show it
result_initialize = objPCAN.GetErrorTex t(result_initialize)
self.fr72.lbxInfo.insert(END," – PCAN i nit: " + result_initialize[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – PCAN init: PCAN_USBBUS1 channel was initialized")
self.fr72.lbxInfo.yview_moveto(1)
Astfel canalul PCAN_USBBUS1 va fi ini Ńializat și configurat pentru o rat ă de transmie de 500
Kbit/s. În cazul în care ini Ńializarea canalului decurge f ără erori atunci mesajul afi șat va fi:
Figura 3. Ini Ńializarea canalului PCAN
În situa Ńia în care ini Ńializarea nu se poate realiza din diferite motive, atunci în fereastra de
informa Ńii va fi afi șat textul descriptiv al erorii. De exemplu dac ă dispozitivul hardware nu a fost
conectat sau nu este instalat, atunci mesajul de er oare afi șat va fi:
Figura 4. Mesaj de eroare la ini Ńializarea canalului PCAN
VI.2 Citirea instantanee a valorilor de la senzori
În sec Ńiunea de citire a informa Ńiilor, utilizatorul are posibilitatea de a selecta senzorii pentru
care dore ște preluarea datelor. Valorile vor fi preluate prin ac Ńionarea butonului de citire, dar nu
înainte de a ini Ńializa canalul.
Figura 5. Sec Ńiunea de citire a senzorilor
Ac Ńionarea butonului de citire a senzorilor determin ă transmiterea pe magistrala de CAN a
unui mesaj de comand ă. Func Ńia apelat ă va fi:
def READDATA(self):
## get the local time
starttime = time.localtime().tm_sec
## define TX message
txmsg = TPCANMsg()
txmsg.ID = 0x200
txmsg.MSGTYPE = PCAN_MESSAGE_STANDARD
txmsg.LEN = 8
Capitolul VI Interfa Ńa grafic ă PCAN
– 40 – Astfel este definit un mesaj de comand ă cu identificatorul 0x200 de tip standard, și cu
lungimea câmpului de date de 8 octe Ńi. În func Ńie de selec Ńia senzorilor, este definit și câmpul de date
astfel:
if (self.fr321_2.checkvar1.get() == 1 and self.fr32 1_2.checkvar2.get() == 0 and
self.fr321_2.checkvar3.get() == 0):
txmsg.DATA[0] = 1
elif (self.fr321_2.checkvar1.get() == 0 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 0):
txmsg.DATA[0] = 2
elif (self.fr321_2.checkvar1.get() == 1 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 0):
txmsg.DATA[0] = 3
elif (self.fr321_2.checkvar1.get() == 0 and self.fr321_2.checkvar2.get() == 0 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 4
elif (self.fr321_2.checkvar1.get() == 1 and self.fr321_2.checkvar2.get() == 0 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 5
elif (self.fr321_2.checkvar1.get() == 0 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 6
elif (self.fr321_2.checkvar1.get() == 1 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 7
else:
txmsg.DATA[0] = 0
Alegerea valorii trimise în câmpul de date a mesaj ului se face în coresponden Ńă cu algoritmul
implementat la nodul receptor c ăruia i se adreseaz ă mesajul. În cadrul aplica Ńiei s-a preferat logica
binar ă, astfel încât dac ă sunt selecta Ńi de exemplu spre citire senzorii 1 și 2 atunci valoarea datei
trimise pe CAN va fi 3 (2^0 + 2^1). Dac ă de exemplu se dore ște citirea tuturor celor trei senzori
atunci data trimis ă pe CAN va fi 7 (2^0 + 2^1 + 2^2).
Odat ă configura Ńi to Ńi parametrii mesajului, acesta este transmis pe mag istrala de CAN:
## The message is sent using the PCAN-USB Chann el 1
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
if result_write != PCAN_ERROR_OK:
## if an error occurred, get a text des cribing the error and show it
result_write = objPCAN.GetErrorText(res ult_write)
self.fr72.lbxInfo.insert(END, " – PCAN write: " + result_write[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – PCAN write: TX message sent successfully")
self.fr72.lbxInfo.insert(END, " – PCAN reading …")
self.fr72.lbxInfo.yview_moveto(1)
Daca transmisia mesajului pe magistral ă se realizeaz ă fără erori atunci un mesaj corespunz ător
va fi afi șat în fereastra de informa Ńii:
Figura 6. Ini Ńierea comenzii de citire a valorilor de la senzori
Capitolul VI Interfa Ńa grafic ă PCAN
– 41 – Odat ă ini Ńiat ă comanda de citire, se va citi continuu coada de re cep Ńie a canalului PCAN timp
de 500 de milisecunde, asteptând ca în condi Ńii normale de func Ńionare să fie recep Ńionate mesajele ce
con Ńin valorile senzorilor corespunz ători selec Ńiei efectuate la ini Ńierea comenzii. Timpul de citire
continuu a cozii de recep Ńiei este configurat la 500 de milisecunde în condi Ńiile în care mesajele ce
trebuie recep Ńionate au o periodicitate de 100 de milisecunde, ti mpul de a șteptare fiind suficient
pentru recep Ńionarea a 4-5 mesaje.
while (rxmsg1_status == 0 or rxmsg2_status == 0 or rxmsg3_status == 0):
readResult = objPCAN.Read(PCAN_USBB US1)
timeouttime = time.localtime().tm_s ec
if readResult[0] == PCAN_ERROR_OK:
## process the received message
self.ProcessMessage(readResult[ 1:])
else:
## if an error occurred, get a text describing the error and show it
result = objPCAN.GetErrorText(r eadResult[0])
Odat ă recep Ńionat un mesaj de pe canalul PCAN, func Ńia de procesare a mesajelor primite va fi
apelat ă:
def ProcessMessage(self, *args):
## split the arguments. [0] TPCANMsg, [1] T PCANTimestamp
rxmsg = args[0][0]
rxtimestamp = args[0][1]
global rxmsg1_status, rxmsg2_status, rxmsg3 _status
În cadrul acestei func Ńii mesajele recep Ńionate sunt procesate, fiind extrase informa Ńiile din
câmpul de date și cele legate de momentul de timp al recep Ńiei.
Dac ă mesajul recep Ńionat are unul din identificatorii recunoscu Ńi, atunci se recurge la
extragerea și afi șarea informa Ńiilor dorite.
if (rxmsg.ID == 256 and rxmsg1_status == 0):
## if message 0x100 is received
rxmsg1_timesec = time.localtime().tm_se c
rxmsg1_timemin = time.localtime().tm_mi n
rxmsg1_timehour = time.localtime().tm_h our
rxmsg1_status = 1
self.fr422.inst_text11.set(str(rxmsg.DA TA[0]))
self.fr423.inst_text12.set("h" + str(rx msg1_timehour) + " m" + str(rxmsg1_timemin) + " s" +
str(rxmsg1_timesec))
self.fr72.lbxInfo.insert(END, " – RX ms g from sensor 1: " + "Type: " + str(rxmsg.MSGTYPE)
+ ", " + "DLC: " + str(rxmsg.LEN) + ", " + "Data: " + str(rxmsg.DATA[0])+ " " +
str(rxmsg.DATA[1])+ " " + str(rxmsg.DATA[2])+ " " + str(rxmsg.DATA[3])+ " " +
str(rxmsg.DATA[4])+ " " + str(rxmsg.DATA[5])+ " " + str(rxmsg.DATA[6])+ " " +
str(rxmsg.DATA[7]) + ", " + "TimeStamp: " + str(rxt imestamp.millis))
self.fr72.lbxInfo.insert(END, " – RX Me ssage 1 reception time moment: " + "h" +
str(rxmsg1_timehour) + "m" + str(rxmsg1_timemin) + "s" + str(rxmsg1_timesec))
self.fr72.lbxInfo.yview_moveto(1)
Dac ă se recep Ńioneaz ă mesajul cu identificatorul 0x100 (256 decimal) atu nci se preia
momentul de timp actual al sistemului de operare și se extrag din mesajul recep Ńionat informa Ńiile din
câmpul de date și din eticheta de timp. Informa Ńiile vor fi afi șate în sec Ńiunea "Received data" a
interfe Ńei grafice. Totodat ă mesajul 0x100 va fi marcat ca recep Ńionat prin setarea statusului de
recep Ńie. Astfel se va ști c ă mesajul a fost recep Ńionat și se vor procesa mai departe doar restul
mesajelor a șteptate, dar numai pân ă la expirarea timpului de timeout de 500 de milisec unde.
Capitolul VI Interfa Ńa grafic ă PCAN
– 42 – ## define reading timeout value [seconds]
if ((timeouttime – starttime) >= 0. 5):
if (rxmsg1_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 1 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
if (rxmsg2_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 2 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
if (rxmsg3_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 3 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
break
Dup ă expirarea timpului de timeout, se verific ă statusurile de recep Ńie ale fiec ărui mesaj, iar în
cazul în care unul din mesaje nu a fost recep Ńionat, se va afi șa un mesaj de timeout în fereastra de
informa Ńii:
Figura 7. Recep Ńionarea mesajului corespunz ător senzorului 1
De exemplu dac ă a fost ini Ńiat ă comanda de citire a senzorului 1, atunci în fereas tra de
informa Ńii vor fi afi șate datele extrase din mesajul recep Ńionat corespunz ător, iar în conformitate cu
selec Ńia f ăcut ă, se vor afi șa mesajele de timeout corespunz ătoare senzorilor 2 și 3. Totodat ă vor fi
actualizate valorile de date și timp în sec Ńiunea de "Received data" corespunz ătoare senzorului 1:
Figura 8. Actualizarea valorilor pentru senzorul 1
Dup ă actualizarea valorilor citite, canalul PCAN pe car e s-a realizat transmisia datelor va fi
dezini Ńializat și astfel toate resursele alocate acestuia vor fi el iberate:
## uninitialize PCAN channel
objPCAN.Uninitialize(PCAN_USBBUS1)
self.fr72.lbxInfo.insert(END, " – PCAN unin it: PCAN_USBBUS1 channel was uninitialized")
self.fr72.lbxInfo.yview_moveto(1)
În cazul în care dezini Ńializarea canalului se realizeaz ă fără erori atunci un mesaj
corespunz ător va fi afi șat în fereastra de informa Ńii. În caz contrar se va afi șa un mesaj descriptiv al
erorii ap ărute.
Capitolul VI Interfa Ńa grafic ă PCAN
– 43 –
Figura 9. Dezini Ńializarea canalului PCAN
VI.3 Citirea ciclic ă a valorilor de la senzori
În sec Ńiunea de comenzi utilizatorul are și op Ńiunea de a citi periodic valorile senzorilor.
Astfel va fi configurat ă perioada dorit ă de citire și se va ac Ńiona butonul de citire automat ă, dar dup ă
ce canalul a fost ini Ńializat în prealabil.
Figura 10. Op Ńiunea de citire ciclic ă a senzorilor
Ac Ńionarea butonului de citire automat ă va determina apelarea func Ńiei:
## define action for 2nd selection (read data from sensors cyclically)
def READAUTO(self):
## disable AUTO button/ enable STOP button
self.fr322_4.Create1.configure(state = DISA BLED)
self.fr322_4.Create2.configure(state = NORM AL)
## get cycle time value
rxmsgcycletime_ms = int(self.fr322_3.inst_t ext_1.get())
rxmsgcycletime_s = rxmsgcycletime_ms / 1000
global readtimer
Perioada de citire definit ă de către utilizator în milisecunde este preluat ă și transformat ă în
secunde. Aceast ă valoare se va utiliza ca parametru de intrare în c adrul unui timer:
if (rxmsgcycletime_ms > 0):
## if cycle time valid value start time r
readtimer = RepeatTimer(rxmsgcycletime_ s, self.READTIMER)
self.fr72.lbxInfo.insert(END, " – PCAN read: Cyclic reading started")
self.fr72.lbxInfo.yview_moveto(1)
readtimer.start()
else:
## if cycle time invalid value start re peating timer at 5000 ms default value
readtimer = RepeatTimer(5, self.READTIM ER)
self.fr72.lbxInfo.insert(END, " – PCAN read: Invalid cycle time value; Cycle time set to 5 000
ms default value")
self.fr72.lbxInfo.yview_moveto(1)
readtimer.start()
Func Ńia de timer "RepeatTimer()" se va apela cu parametrii period ă de citire și respectiv
func Ńia ce va fi apelat ă și executat ă pe durata unei perioade a timerului. Func Ńia timer este definit ă
astfel:
Capitolul VI Interfa Ńa grafic ă PCAN
– 44 – # definirea clasei timer
class RepeatTimer(Thread):
#definirea metodei de ini Ńializare
def __init__(self, interval, function, iterati ons=0, args=[], kwargs={}):
Thread.__init__(self)
self.interval = interval
self.function = function
self.iterations = iterations
self.args = args
self.kwargs = kwargs
self.finished = Event()
#definirea metodei de start
def run(self):
count = 0
while not self.finished.is_set() and (self.iterat ions <= 0 or count < self.iterations):
self.finished.wait(self.interval)
if not self.finished.is_set():
self.function(*self.args, **self.kwargs)
count += 1
#definirea metodei de oprire
def cancel(self):
self.finished.set()
În cadrul timerului s-a folosit apelarea unui even iment Event() . Un obiect de tip eveniment
gestioneaz ă starea unui flag pe care îl poate seta prin apelar ea metodei set() sau îl poate reseta prin
apelarea metodei clear() . Deasemenea metoda wait() poate fi apelat ă pentru blocarea firului de
execu Ńie pân ă când flagul este setat sau pân ă când timpul de timeout expir ă în cazul în care metoda de
așteptare este apelat ă cu un parametru de timeout, de exemplu wait(5) . Metoda isSet() sau is_set() , în
func Ńie de versiunea de python utilizat ă, va returna adev ărat dac ă flagul intern este setat, sau fals în
caz contrar.
Odat ă apelat timerul prin metoda start() sau run() , cât timp flagul intern al evenimentului nu
este setat (comand ă de oprire a timerului) se va apela metoda de wait() ce va a ștepta pân ă la
terminarea timpului de timeout setat ca period ă de citire a senzorilor. Dup ă expirarea timpului de
timeout se va apela func Ńia dat ă ca al doilea parametru al timerului. Func Ńia apelat ă va fi
"READTIMER()" definit ă în mod similar cu func Ńia "READ()" de la citirea neperiodic ă a senzorilor.
Algoritmul de citire este similar, comanda de citir e fiind dat ă prin transmiterea pe magistrala de CAN
a unui mesaj cu identificatorul 0x200 con Ńinând în câmpul de date valoarea numeric ă decimal ă
corespunz ătoare combina Ńiei binare din selec Ńia senzorilor de citit. Timp de 500 de milisecunde sunt
citite toate mesajele recep Ńionate, iar dac ă mesajele a șteptate cu identificatorii 0x100, 0x110 sau
0x120 nu sunt recep Ńionate atunci se va afi șa în sec Ńiunea de informa Ńii câte un mesaj de timeout
corespunz ător mesajului nerecep Ńionat, iar valorile din câmpurile "Received data" vor fi actualizate în
conformitate:
Figura 11. Comanda de citire ciclic ă cu perioada de 10 secunde
Dac ă se dore ște de exemplu citirea periodic ă a tuturor celor trei senzori o data la 10 secunde
atunci pe magistrala de CAN se vor înregistra urm ătoarele mesaje:
Capitolul VI Interfa Ńa grafic ă PCAN
– 45 –
Figura 12. Traficul pe prima perioad ă de citire (comand ă de citire + recep Ńie)
Primul mesaj înregistrat va fi cel de comand ă transmis, cu identificatorul 0x200 și valoarea 7
în câmpul de date corespunzând selec Ńiei tuturor celor trei senzori (2^2 + 2^1 + 2^0). I mediat dup ă
transmiterea comenzii se vor recep Ńiona mesajele ce con Ńin valorile senzorilor și anume mesajul
corespunz ător primului senzor cu identificatorul 0x100 și valoarea 3 în câmpul de date, mesajul
corespunz ător senzorului al doilea cu identificatorul 0x110 și valoarea 5, respectiv mesajul cu
identificatorul 0x120 și valoarea 7 corespunzând senzorului al treilea. Du p ă recep Ńionarea tuturor
mesajelor dorite, o nou ă comand ă se va transmite pentru oprirea citirii pân ă la urm ătorul ciclu:
Figura 13. Transmiterea mesajului de oprire a citir ii
Mesajul de oprire a citirii va con Ńine în câmpul de date valoarea 0 pentru a semnala n odului
AutoBox finalizarea transmiterii mesajelor. În câmp urile corespunz ătoare senzorilor din sec Ńiunea
"Received data" parametrii recep Ńionati vor fi actualiza Ńi dup ă primul ciclu de citire:
Figura 14. Actualizarea datelor recep Ńionate în prima perioad ă de citire
Dup ă expirarea timpului de timeout de 10 secunde, timer ul va trece la executare perioadei
urm ătoare, iar mesajul de comand ă va fi automat transmis iara și pe magistral ă:
Figura 15. Traficul pe cea de-a doua perioad ă de citire (comand ă citire + recep Ńie)
La mesajele înregistrate dup ă primul ciclu de citire se vor ad ăuga mesajele înregistrate în cel
de-al doilea ciclu de citire, num ărul de mesaje "count" din figura 15 incrementându-s e înc ă o dat ă fa Ńă
de situa Ńia din primul ciclu de citire. Astfel pe înregistra re se va remarca o perioad ă a mesajelor
Capitolul VI Interfa Ńa grafic ă PCAN
– 46 – înregistrate de aproximativ 10 secunde. Dup ă recep Ńionarea mesajelor purt ătoare de informa Ńie de la
senzori, se va transmite mesajul comand ă de oprire cu valoarea 0 în câmpul de date:
Figura 16. Transmiterea mesajului de oprire a citir ii pe cel de-al doilea ciclu
Deasemenea câmpurile corespunz ătoare senzorilor din sec Ńiunea "Received data" se vor
actualiza în conformitate cu noile valori de date și timp:
Figura 17. Actualizarea datelor recep Ńionate în cea de-a doua perioad ă de citire
Citirea ciclic ă a valorilor senzorilor va continua pân ă când butonul de stop este ac Ńionat, iar
func Ńia de finalizare a citirii periodice "STOPAUTOREAD()" este apelat ă. Func Ńia de oprire a citirii se
define ște astfel:
## define stop auto reading action
def STOPAUTOREAD(self):
global readtimer, txmsg
## enable AUTO button/ disable STOP button
self.fr322_4.Create1.configure(state = NORM AL)
self.fr322_4.Create2.configure(state = DISA BLED)
## command for finished communication
txmsg.DATA[0] = 0
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
## timer stop
readtimer.cancel()
self.fr72.lbxInfo.insert(END, " – PCAN read : Cyclic reading stopped")
self.fr72.lbxInfo.yview_moveto(1)
## uninitialize PCAN channel
objPCAN.Uninitialize(PCAN_USBBUS1)
Se define ște valoarea 0 în câmpul de date al mesajului ce va fi transmis pentru comandarea
imediat ă a finaliz ării citirii de la senzori. Timerul este oprit prin apelarea metodei "cancel()" , iar
canalul PCAN este dezini Ńializat eliberându-se toate resursele alocate acest uia.
În ferestra de informa Ńii va fi afi șat mesajul corespunz ător finaliz ării ac Ńiunii de citire ciclic ă a
senzorilor:
Capitolul VI Interfa Ńa grafic ă PCAN
– 47 –
Figura 18. Finalizarea citirii periodice a valorilo r de la senzori
VI.4 Trimiterea de mesaje pe magistrala de CAN
În sec Ńiunea de comenzi utilizatorul va putea transmite or ice semnale pe magistrala de CAN,
periodic sau instantaneu. Astfel se vor putea confi gura fiecare parametri ai mesajului:
Figura 19. Op Ńiunea de transmitere de mesaje pe magistrala de CAN
Ac Ńionarea butonului de trimitere a mesajelor "SEND" v a apela func Ńia definit ă astfel:
def SENDDATA(self):
## disable SEND button/ enable STOP button
self.fr323_5.Create1.configure(state = DISABLED)
self.fr323_5.Create2.configure(state = NORMAL)
## define TX message
global txmsg, sendtimer
txmsg = TPCANMsg()
Dup ă definirea mesajului de tipul TPCANMsg() , vor fi preluate valorile pentru parametrii
configura Ńi ai mesajului, valoarea identificatorului, formatu l mesajului, lungimea câmpului de date,
valorile din câmpul de date și perioada semnalului:
txmsg.ID = int(self.fr323_2.inst_text_1.get()) ## get tx message id
txmsgtype = self.fr323_2.inst_text_2.get() ## get tx message type
if (txmsgtype == "standard"):
txmsg.MSGTYPE = PCAN_MESSAGE_STANDARD
elif (txmsgtype == "extended"):
txmsg.MSGTYPE = PCAN_MESSAGE_EXTENDED
else:
self.fr72.lbxInfo.insert(END, " – PCAN transmit: Invalid message type (valid types:
STANDARD or EXTENDED); MSGTYPE set to STANDARD")
txmsg.MSGTYPE = PCAN_MESSAGE_STANDARD
txmsg.LEN = int(self.fr323_2.inst_text_3.get()) ## get tx message length and tx data
txmsg.DATA[0] = int(self.fr323_3.inst_text_datavar 1.get())
…
txmsg.DATA[7] = int(self.fr323_3.inst_t ext_datavar8.get())
Capitolul VI Interfa Ńa grafic ă PCAN
– 48 – Dac ă perioada mesajului este definit ă la 0 milisecunde atunci mesajul va fi transmis o s ingur ă
dat ă. Dac ă perioada mesajului are o valoare negativ ă atunci aceasta se va considera invalid ă, iar
perioada va fi definit ă implicit la 0 milisecunde.
## get tx message cycle time value
txmsgcycletime_ms = int(self.fr323_4.inst_text_1.g et())
txmsgcycletime_s = txmsgcycletime_ms / 1000
if (txmsgcycletime_ms == 0):
## kickout message
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
Dac ă perioada mesajului este mai mare de 0 atunci mesaj ul va transmis ciclic cu perioada
configurat ă. Perioada definit ă de utilizator este preluat ă și transformat ă în secunde și folosit ă ca
parametru de intrare pentru aceea și func Ńie timer "RepeatTimer()" ca și în cazul citirii periodice a
valorilor de la senzori.
elif (txmsgcycletime_ms > 0):
## if cycletime valid value, start repeating time r
sendtimer = RepeatTimer(txmsgcycletime_s, self.SE NDTIMER)
self.fr72.lbxInfo.insert(END, " – PCAN transmit: Cyclic sending started")
self.fr72.lbxInfo.yview_moveto(1)
sendtimer.start()
Func Ńia dat ă ca parametru de intrare al timerului pentru execu Ńia ciclic ă este "SENDTIMER()"
și este definit ă astfel:
def SENDTIMER(self):
global txmsg
## get latest data
txmsg.DATA[0] = int(self.fr323_3.inst_text_datavar 1.get())
…
txmsg.DATA[7] = int(self.fr323_3.inst_text_datavar 8.get())
## send tx message on can bus
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
Fie situa Ńia în care utilizatorul ini Ńializeaz ă canalul PCAN și configureaz ă parametrii mesajului
de transmis astfel:
Figura 20. Transmiterea de mesaje pe magistrala de CAN
Astfel pe magistrala de CAN se va înregistra mesaj ul transmis o dat ă la num ărul de
milisecunde configurat de c ătre utilizator:
Figura 21. Înregistrare pe magistrala de CAN dup ă 30 de secunde
Capitolul VI Interfa Ńa grafic ă PCAN
– 49 – Dup ă 30 de secunde de transmisie periodic ă la 10 secunde, pe înregistrare va ap ărea mesajul
transmis cu identificatorul 0x400 (decimal 1024), a vând counterul incrementat la 3 și perioada
detectat ă de aproximativ 10 secunde. Dac ă transmisia decurge f ără erori atunci în fereastra de
informa Ńii vor fi afi șate mesajele corespunz ătoare unei transmisii realizate cu succes:
Figura 22. Transmisie pe magistrala de CAN f ără erori
Mesajul definit se va transmite periodic pe magist rala de CAN pân ă când utilizatorul va
ac Ńiona butonul de oprire a transmisiei "STOP". Func Ńia apelat ă și executat ă la ac Ńionarea butonului de
stop este definit ă astfel:
## define stop sending data action
def STOPSENDDATA(self):
## enable SEND button/ disable STOP button
self.fr323_5.Create1.configure(state = NORMAL)
self.fr323_5.Create2.configure(state = DISABLED)
global sendtimer
## timer stop
sendtimer.cancel()
self.fr72.lbxInfo.insert(END, " – PCAN transmit: Cyclic sending stopped")
self.fr72.lbxInfo.yview_moveto(1)
## uninitialize PCAN channel
objPCAN.Uninitialize(PCAN_USBBUS1)
Timerul de execu Ńie ciclic ă este oprit prin apelarea metodei "cancel()" . Totodat ă canalul
PCAN pe care s-a realizat transmisia este dezini Ńializat pentru eliberarea resurselor, iar în fereas tra de
informa Ńii vor fi afi șate mesajele descriptive corespunz ătoare unei dezini Ńializ ări reu șite:
Figura 23. Finalizarea transmisiei de mesaje pe mag istrala de CAN
Pentru p ărăsirea aplica Ńiei utilizatorul va ac Ńiona butonul de ie șire "Release PCAN_USBBUS1
AND EXIT". Ac Ńionarea acestuia va conduce la apelarea și execu Ńia func Ńiei de p ărăsire a aplica Ńiei
Capitolul VI Interfa Ńa grafic ă PCAN
– 50 – unde se realizeaz ă dezini Ńializarea canalului PCAN, urmat ă de închiderea ferestrei de aplica Ńie.
Func Ńia de ie șire din aplica Ńie se define ște astfel:
## define action for RELEASE AND EXIT button
def EXIT(self):
objPCAN.Uninitialize(PCAN_USBBUS1)
self.fr72.lbxInfo.insert(END, " – PCAN uninit: PC AN_USBBUS1 channel was
uninitialized")
tkMessageBox.showinfo(title = "Info", message = " PCAN_USBBUS1 CHANNEL IS
RELEASED")
root.destroy()
În cazul unei dezini Ńializ ări reu șite un mesaj descriptiv va fi afi șat în fereastra de informa Ńii și
totodat ă o fereastr ă pop-up anun Ńând eliberarea canalului și p ărăsirea aplica Ńiei:
Figura 23. Finalizarea transmisiei de mesaje pe mag istrala de CAN
Capitolul VII Concluzii
– 51 –
CAPITOLUL VII
CONCLUZII
Capitolul VII Concluzii
– 52 –
VII.1 Rezumat
În primul capitol al lucr ării este prezentat un scurt istoric al protocolului de CAN, tema de
proiect și o vedere de ansamblu a aplica Ńiei practice.
Capitolul al doilea cuprinde o prezentare general ă a no Ńiunilor de baz ă ale protocolului de
comunica Ńie CAN, principiul dup ă care se realizeaz ă transmisia și recep Ńia datelor, modul de
codificare al semnalelor care circul ă pe magistral ă. Sunt descrise structurile cadrelor de CAN atât în
formatul standard cât și extins și structura mesajului de tip cerere de date. Deasem enea sunt
prezentate mecanismele de detec Ńie, semnalizare și tratare a erorilor de comunica Ńie.
În capitolul al treilea este prezentat modul de de scriere a unei comunica Ńii de CAN prin
intermediul fi șierului DBC, pentru ca mai apoi acesta s ă poat ă fi utilizat în simularea re Ńelei astfel
descrise. Fi șierul cu descrierea de CAN va putea fi citit printr -un mecanism de parcurgere
încorporat în blocul de Matlab RTICANMM Main Block descris în capitolul al patrulea, bloc ce va
realiza interfa Ńa dintre modelul re Ńelei de CAN și dispozitivul hardware PCAN USB al aplica Ńiei.
Capitolul al patrulea cuprinde o descriere a princi palelor caracteristici ale blocului
RTICANMM, modul de parcurgere al fi șierului descriere de comunica Ńie de CAN precum și
op Ńiunile de trigerare a mesajelor transmise pe magist rala de CAN.
Pe parcursul capitolului al cincilea sunt prezentat e principalele avantaje oferite de pachetul
PCAN Basic, tipurile de date utilizate și func Ńii ce pot fi utilizate pentru dezvoltarea de aplica Ńii de
CAN folosind limbajul de programare Python.
În cadrul capitolului al șaselea este prezentat ă aplica Ńia software PCAN Interface prin
intermediul c ăreia uilizatorul poate comanda citirea valorilor fu rnizate de o serie de senzori pe
magistrala de CAN, transmiterea de mesaje configura bile pe magistral ă, precum și mecanismele de
afi șare a descrierilor de eroare sau informa Ńiile corespunz ătoare fiec ărei ac Ńiuni în parte.
Capitolul al șaptelea cuprinde o scurt ă descriere a prezentei lucr ări, precum și o serie de
concluzii asupra proiectului.
VII.2 Concluzii asupra proiectului
Pachetul de drivere și func Ńii pus la dispozi Ńie de Peak System s-a dovedit extrem de
avantajos, iar costurile reduse implicate de dezvol tarea aplica Ńiei se justific ă numai prin necesitatea
achizi Ńion ării dispozitivului hardware PCAN USB de interfa Ńare a magistralei de CAN cu portul
USB al calculatorului.
Aplica Ńia este capabil ă de transmisii și recep Ńion ări de mesaje de pe magistrala de CAN cu o
periodicitate minim ă de pân ă la o milisecund ă. Etichetele de timp corespunz ătoare mesajelor
recep Ńionate au o acurate Ńe de ordinul microsecundelor, elemente ce fac ca ap lica Ńia s ă poat ă fi
Capitolul VII Concluzii
– 53 –
utilizat ă cu succes în cadrul unor sisteme de timp real, în care e necesar un volum impresionant de
date și o vitez ă mare de citire/ transmitere de date.
Unul din atuurile aplica Ńiei provine chiar din avantajele oferite de protoco lul de CAN, și
anume posibilitatea de conectare a dispozitivului h ardware PCAN USB oriunde de-a lungul unei
magistralei de CAN, neexistând posibilitatea de afe ctare a nodurilor deja existente.
Diversitatea func Ńiilor puse la dispozi Ńie pentru dezvoltarea de aplica Ńii de CAN în diverse
limbaje de programare, precum și flexibilitatea limbajului de programare Python în care aplica Ńia a
fost impementat ă, permit o dezvoltare ulterioar ă a interfe Ńei utilizatorului, în care acesta sa poat ă fi
capabil sa-și configureze singur identificatorii mesajelor de i nteres de pe magistrala de CAN,
op Ńiunea de filtrare a mesajelor recep Ńionate sau de înregistrare a fluxului de date de pe magistral ă
în cadrul unor sesiuni de debug, în vederea analize i și dezvolt ării de noi aplica Ńii.
Dezavantajul major al aplica Ńiei în constituie dependen Ńa de driverele și libr ăriile pachetului
PCAN Basic acestea fiind compatibile numai cu dispo zitivele hardware de interfa Ńare cu magistrala
fizic ă de CAN de la Peak System. Un singur device hardwar e PCAN USB asigur ă accesul pe un
singur canal de CAN, iar dezvoltarea unei aplica Ńii cu acces pe mai multe canale de CAN va atrage
cu sine necesitatea achizi Ńion ării mai multor device-uri hardware de interfa Ńare CAN – USB, și în
consecin Ńă necesitatea mai multor porturi de USB libere pe st a Ńia unde se va rula aplica Ńia. Exist ă
deasemenea solu Ńii mai simple, cu interfa Ńare CAN – PCI sau CAN – ISA, costurile adi Ńionale
crescând propor Ńional cu num ărul de canale PCAN dorite.
Scopul acestui proiect a fost atins și anume s-a dezvoltat o aplica Ńie prin care utilizatorul
poate transmite mesaje pe o magistral ă de CAN și poate recep Ńiona mesajele de interes. Prin
extinderea domeniului de aplicabilitate a proiectul ui, aplica Ńia poate fi configurat ă și utilizat ă cu
succes în recep Ńionarea și transmiterea oric ărui tip de date pe magistrala de CAN.
Referin Ńe bibliografice
– 54 –
Referin Ńe bibliografice:
CAN:
1. Dr. Ing. Susnea Ioan – Curs de "Comunica Ńii de date în sisteme distribuite" [curs 6], Catedr a de
Automatic ă și Informatic ă Industrial ă, Universitatea "Dun ărea de Jos" Gala Ńi.
(URL: http://isusnea.inginer.info/curs6.pdf)
2. Dr. Ing. Vornicu Liliana – Curs de "Sisteme cu c onectare multiplexat ă și control distribuit"
[cap.10], Catedra de Electronic ă Aplicat ă și Sisteme Inteligente, Universitatea "Gheorghe Asac hi"
Ia și.
3. Ing. Daniel Manisto – "An Overview of Controller Area Network (CAN) Technology", nov.
2003, Machine Bus Corporation, Evanston, Illinois.
(URL: http://www.parallax.com/dl/docs/prod/comm/can techovew.pdf)
4. dSpace GmbH Help Documentation – MicroAutoBox Im plementation Documents, Basics on
CAN, rev. iun. 2009. (URL: http://www.dspace.com/en /pub/home.cfm)
5. Ing. Miron Mandoiu – “Re Ńele pentru comunica Ńii industriale” [pg.34-47], Facultatea de
Electronic ă, Telecomunica Ńii și Ingineria Informa Ńiei, Universitatea Politehnic ă Bucure ști, 2007.
(URL: http://www.scribd.com/doc/55601175/Retele-Pen tru-Comunicatii-ale)
Fi șierul DBC:
6. Vector Informatik GmbH – DBC File Format Documen tation, vers. 01/2007.
7. Vector Informatik GmbH – Vector CANdb++ Help Doc umentation, CANdb++ Procedures –
Creating a CANdb Network File, vers.3.
(URL: http://www.vector.com/vi_candb_en.html)
Blocul RTICANMM:
8. dSpace GmbH Help Documentation – RTI CAN Referen ce, General information on
RTICANMM Main Block, Block Description, rev. iun. 2 009.
(URL: http://www.dspace.com/en/pub/home.cfm)
9. dSpace GmbH Help Documentation – RTI CAN Referen ce, Pages of RTICANMM MainBlock
(Dialog Tree), General Settings, rev. iun. 2009.
(URL: http://www.dspace.com/en/pub/home.cfm)
10. dSpace GmbH Help Documentation – RTI CAN Refere nce, Pages of RTICANMM MainBlock
(Dialog Tree), Triggering Options, rev. iun. 2009.
(URL: http://www.dspace.com/en/pub/home.cfm)
PCAN-Basic:
11. Peak-System Technik GmbH – PCAN-Basic API Docum entation, vers. 01/2011.
(URL: http://www.peak-system.com)
Referin Ńe bibliografice
– 55 –
Instrumente folosite:
1. dSpace MicroAutoBox – URL: http://www.dspace.de/en/pub/home/products/h w/micautob.cfm
2. Matlab – URL: http://www.mathworks.com/products/matlab/
3. Libr ării RTICAN – URL: http://www.dspace.com/en/ltd/home/support/p atches/suppatchsfc/
rtican_rls51_px.cfm
4. CANdb++ Editor – URL: https://www.vector.com/vi_downloadcenter_en .html
5. dSpace Control Desk – URL: http://www.dspace.com/en/ltd/home/support/s uptrain/controldesk.cfm
6. PCAN USB hardware interface – URL: http://www.peak-system.c om/Product-
Details.49+M578cbdb898b.0.html?&L=1&tx_commerce_pi1 [catUid]=6&tx_commerce_pi1[show
Uid]=16
7. Libr ării PCAN-Basic – URL: http://www.peak-system.com/Product-
Details.49+M52043c9f3c8.0.html?&L=1&tx_commerce_pi1 [catUid]=4&tx_commerce_pi1[show
Uid]=179
8. PCAN View – URL: http://www.peak-system.com/Product-
Details.49+M5d31ea5c82c.0.html?&L=1&tx_commerce_pi1 [catUid]=10&tx_commerce_pi1[sho
wUid]=32
9. Python Programming – URL: http://python.org/
10. Modulul grafic Tkinter – URL: http://www.python.org/doc//current/library/ tkinter.html
Anex e
– 56 –
ANEXE
Anex e
– 57 –
Codul surs ă al aplica Ńiei:
## All imports here
from Tkinter import *
import tkFileDialog
import shutil
import time
import os,sys
import string
import tkMessageBox
from threading import *
from ctypes import *
from PCANBasic import *
objPCAN = PCANBasic()
## define timer class
class RepeatTimer(Thread):
def __init__(self, interval, function, iteratio ns=0, args=[], kwargs={}):
Thread.__init__(self)
self.interval = interval
self.function = function
self.iterations = iterations
self.args = args
self.kwargs = kwargs
self.finished = Event()
## define start method
def run(self):
count = 0
try:
while not self.finished.is_set() and (s elf.iterations <= 0 or count < self.iterations):
self.finished.wait(self.interval)
if not self.finished.is_set():
self.function(*self.args, **sel f.kwargs)
count += 1
except:
while not self.finished.isSet() and (se lf.iterations <= 0 or count < self.iterations):
self.finished.wait(self.interval)
if not self.finished.isSet():
self.function(*self.args, **sel f.kwargs)
count += 1
## define stop method
def cancel(self):
self.finished.set()
## define application main class
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack(fill = BOTH, expand = TRUE)
self.CREATE()
self.CURRENTACTION()
Anex e
– 58 –
## define GUI interface method
def CREATE(self):
## define all frame widgets needed to organ ize the main GUI interface
self.fr1 = Frame(self)
self.fr1.pack(fill = BOTH, expand = TRUE)
self.fr1.configure(borderwidth="6")
self.fr1.configure(relief="groove")
self.fr2 = Frame(self.fr1)
self.fr2.pack(in_ = self.fr1)
self.fr2.configure(borderwidth="6")
self.fr2.configure(relief="groove")
self.fr2.pack(fill = BOTH)
self.fr6 = Frame(self.fr1)
self.fr6.pack(in_ = self.fr1)
self.fr6.configure(borderwidth="6")
self.fr6.configure(relief="groove")
self.fr6.pack(fill = BOTH)
self.fr3 = Frame(self.fr1)
self.fr3.pack(in_ = self.fr1)
self.fr3.configure(borderwidth="6")
self.fr3.configure(relief="groove")
self.fr3.pack(fill = BOTH)
self.fr31 = Frame(self.fr3)
self.fr31.pack(in_ = self.fr3)
self.fr31.configure(borderwidth="2")
self.fr31.configure(relief="groove")
self.fr31.pack(fill = BOTH)
self.fr32 = Frame(self.fr3)
self.fr32.pack(in_ = self.fr3)
self.fr32.configure(borderwidth="2")
self.fr32.configure(relief="groove")
self.fr32.pack(fill = BOTH)
self.fr321 = Frame(self.fr32)
self.fr321.pack(in_ = self.fr32)
self.fr321.configure(borderwidth="1")
self.fr321.configure(relief="groove")
self.fr321.pack(fill = BOTH, expand = TRUE)
self.fr321_1 = Frame(self.fr321)
self.fr321_1.pack(in_ = self.fr321)
self.fr321_1.configure(borderwidth="1")
self.fr321_1.configure(relief="groove")
self.fr321_1.pack(side = LEFT, fill = BOTH, expand = TRUE)
self.fr321_3 = Frame(self.fr321)
self.fr321_3.pack(in_ = self.fr321)
self.fr321_3.configure(borderwidth="1")
self.fr321_3.configure(relief="groove")
self.fr321_3.pack(side = RIGHT, fill = BOTH , expand = TRUE)
Anex e
– 59 – self.fr321_2 = Frame(self.fr321)
self.fr321_2.pack(in_ = self.fr321)
self.fr321_2.configure(borderwidth="1")
self.fr321_2.configure(relief="groove")
self.fr321_2.pack(side = TOP, fill = BOTH, expand = TRUE)
self.fr322 = Frame(self.fr32)
self.fr322.pack(in_ = self.fr32)
self.fr322.configure(borderwidth="1")
self.fr322.configure(relief="groove")
self.fr322.pack(fill = BOTH, expand = TRUE)
self.fr322_1 = Frame(self.fr322)
self.fr322_1.pack(in_ = self.fr322)
self.fr322_1.configure(borderwidth="1")
self.fr322_1.configure(relief="groove")
self.fr322_1.pack(side = LEFT, fill = BOTH, expand = TRUE)
self.fr322_4 = Frame(self.fr322)
self.fr322_4.pack(in_ = self.fr322)
self.fr322_4.configure(borderwidth="1")
self.fr322_4.configure(relief="groove")
self.fr322_4.pack(side = RIGHT, fill = BOTH , expand = TRUE)
self.fr322_2 = Frame(self.fr322)
self.fr322_2.pack(in_ = self.fr322)
self.fr322_2.configure(borderwidth="1")
self.fr322_2.configure(relief="groove")
self.fr322_2.pack(side = TOP, fill = BOTH, expand = TRUE)
self.fr322_3 = Frame(self.fr322)
self.fr322_3.pack(in_ = self.fr322)
self.fr322_3.configure(borderwidth="1")
self.fr322_3.configure(relief="groove")
self.fr322_3.pack(side = BOTTOM, fill = BOT H, expand = TRUE)
self.fr323 = Frame(self.fr32)
self.fr323.pack(in_ = self.fr32)
self.fr323.configure(borderwidth="1")
self.fr323.configure(relief="groove")
self.fr323.pack(fill = BOTH, expand = TRUE)
self.fr323_1 = Frame(self.fr323)
self.fr323_1.pack(in_ = self.fr323)
self.fr323_1.configure(borderwidth="1")
self.fr323_1.configure(relief="groove")
self.fr323_1.pack(side = LEFT, fill = BOTH, expand = TRUE)
self.fr323_5 = Frame(self.fr323)
self.fr323_5.pack(in_ = self.fr323)
self.fr323_5.configure(borderwidth="1")
self.fr323_5.configure(relief="groove")
self.fr323_5.pack(side = RIGHT, fill = BOTH , expand = TRUE)
self.fr323_2 = Frame(self.fr323)
self.fr323_2.pack(in_ = self.fr323)
self.fr323_2.configure(borderwidth="1")
Anex e
– 60 – self.fr323_2.configure(relief="groove")
self.fr323_2.pack(side = TOP, fill = BOTH, expand = TRUE)
self.fr323_3 = Frame(self.fr323)
self.fr323_3.pack(in_ = self.fr323)
self.fr323_3.configure(borderwidth="1")
self.fr323_3.configure(relief="groove")
self.fr323_3.pack(side = TOP, fill = BOTH, expand = TRUE)
self.fr323_4 = Frame(self.fr323)
self.fr323_4.pack(in_ = self.fr323)
self.fr323_4.configure(borderwidth="1")
self.fr323_4.configure(relief="groove")
self.fr323_4.pack(side = TOP, fill = BOTH, expand = TRUE)
self.fr33 = Frame(self.fr3)
self.fr33.pack(in_ = self.fr3)
self.fr33.configure(borderwidth="2")
self.fr33.configure(relief="groove")
self.fr33.pack(fill = BOTH)
self.fr4 = Frame(self.fr1)
self.fr4.pack(in_ = self.fr1)
self.fr4.configure(borderwidth="6")
self.fr4.configure(relief="groove")
self.fr4.pack(fill = BOTH)
self.fr41 = Frame(self.fr4)
self.fr41.pack(in_ = self.fr4)
self.fr41.configure(borderwidth="2")
self.fr41.configure(relief="groove")
self.fr41.pack(fill = BOTH)
self.fr42all = Frame(self.fr4)
self.fr42all.pack(in_ = self.fr4)
self.fr42all.configure(borderwidth="0")
self.fr42all.configure(relief="groove")
self.fr42all.pack(fill = BOTH)
self.fr42 = Frame(self.fr42all)
self.fr42.pack(in_ = self.fr42all)
self.fr42.configure(borderwidth="2")
self.fr42.configure(relief="groove")
self.fr42.pack(fill = BOTH, side = LEFT, ex pand = TRUE)
self.fr421 = Frame(self.fr42)
self.fr421.pack(in_ = self.fr42)
self.fr421.configure(borderwidth="1")
self.fr421.configure(relief="groove")
self.fr421.pack(fill = BOTH, expand = TRUE)
self.fr422 = Frame(self.fr42)
self.fr422.pack(in_ = self.fr42)
self.fr422.configure(borderwidth="1")
self.fr422.configure(relief="groove")
self.fr422.pack(fill = BOTH, expand = TRUE)
Anex e
– 61 – self.fr423 = Frame(self.fr42)
self.fr423.pack(in_ = self.fr42)
self.fr423.configure(borderwidth="1")
self.fr423.configure(relief="groove")
self.fr423.pack(fill = BOTH, expand = TRUE)
self.fr43 = Frame(self.fr42all)
self.fr43.pack(in_ = self.fr42all)
self.fr43.configure(borderwidth="2")
self.fr43.configure(relief="groove")
self.fr43.pack(fill = BOTH, side = LEFT, ex pand = TRUE)
self.fr431 = Frame(self.fr43)
self.fr431.pack(in_ = self.fr43)
self.fr431.configure(borderwidth="1")
self.fr431.configure(relief="groove")
self.fr431.pack(fill = BOTH, expand = TRUE)
self.fr432 = Frame(self.fr43)
self.fr432.pack(in_ = self.fr43)
self.fr432.configure(borderwidth="1")
self.fr432.configure(relief="groove")
self.fr432.pack(fill = BOTH, expand = TRUE)
self.fr433 = Frame(self.fr43)
self.fr433.pack(in_ = self.fr43)
self.fr433.configure(borderwidth="1")
self.fr433.configure(relief="groove")
self.fr433.pack(fill = BOTH, expand = TRUE)
self.fr44 = Frame(self.fr42all)
self.fr44.pack(in_ = self.fr42all)
self.fr44.configure(borderwidth="2")
self.fr44.configure(relief="groove")
self.fr44.pack(fill = BOTH, side = LEFT, ex pand = TRUE)
self.fr441 = Frame(self.fr44)
self.fr441.pack(in_ = self.fr44)
self.fr441.configure(borderwidth="1")
self.fr441.configure(relief="groove")
self.fr441.pack(fill = BOTH, expand = TRUE)
self.fr442 = Frame(self.fr44)
self.fr442.pack(in_ = self.fr44)
self.fr442.configure(borderwidth="1")
self.fr442.configure(relief="groove")
self.fr442.pack(fill = BOTH, expand = TRUE)
self.fr443 = Frame(self.fr44)
self.fr443.pack(in_ = self.fr44)
self.fr443.configure(borderwidth="1")
self.fr443.configure(relief="groove")
self.fr443.pack(fill = BOTH, expand = TRUE)
self.fr45 = Frame(self.fr4)
self.fr45.pack(in_ = self.fr4)
self.fr45.configure(borderwidth="2")
Anex e
– 62 – self.fr45.configure(relief="groove")
self.fr45.pack(fill = BOTH)
self.fr5 = Frame(self.fr1)
self.fr5.pack(in_ = self.fr1)
self.fr5.configure(borderwidth="6")
self.fr5.configure(relief="groove")
self.fr5.pack(fill = BOTH)
self.fr7 = Frame(self.fr1)
self.fr7.pack(in_ = self.fr1)
self.fr7.configure(borderwidth="6")
self.fr7.configure(relief="groove")
self.fr7.pack(fill = BOTH)
self.fr71 = Frame(self.fr7)
self.fr71.pack(in_ = self.fr7)
self.fr71.configure(borderwidth="2")
self.fr71.configure(relief="groove")
self.fr71.pack(fill = BOTH)
self.fr72 = Frame(self.fr7)
self.fr72.pack(in_ = self.fr7)
self.fr72.configure(borderwidth="2")
self.fr72.configure(relief="groove")
self.fr72.pack(fill = BOTH)
self.fr73 = Frame(self.fr7)
self.fr73.pack(in_ = self.fr7)
self.fr73.configure(borderwidth="2")
self.fr73.configure(relief="groove")
self.fr73.pack(fill = BOTH)
self.fr2.inst_label1 = Label(self.fr2, text = "PCAN INTERFACE", bg = 'lavender',
font=("Arial",9,"bold"))
self.fr2.inst_label1.pack(fill = BOTH, expa nd = TRUE)
## define gui button for initializing the P CAN channel
self.fr6.Create = Button(self.fr6, text = ' INITIALIZE PCAN_USBBUS1 CHANNEL', width = 10,
command = self.INITIALIZE)
self.fr6.Create.pack(fill = BOTH)
## define graphical user interface for TX d ata
self.fr31.inst_label1 = Label(self.fr31, te xt = "TRANSMITTED DATA", bg = 'azure',
font=("Arial",9,"bold"))
self.fr31.inst_label1.pack(fill = BOTH, exp and = TRUE)
## 1st selection – read data from sensors
self.fr32.favorite = StringVar()
self.fr32.favorite.set("readnow")
Radiobutton(self.fr321_1, text = "READ DATA :", variable = self.fr32.favorite, value = "readnow ",
command = self.CURRENTACTION, height = 3, anchor = W).pack(side = LEFT)
## sensor selection (define check buttons f or each sensor)
self.fr321_2.inst_label_1 = Label(self.fr32 1_2, text = "SENSOR 1")
self.fr321_2.inst_label_1.pack(side = LEFT)
self.fr321_2.checkvar1 = IntVar()
Anex e
– 63 – self.fr321_2.checkbutton1 = Checkbutton(sel f.fr321_2, variable = self.fr321_2.checkvar1, onval ue = 1,
offvalue = 0)
self.fr321_2.checkbutton1.pack(side = LEFT)
self.fr321_2.inst_label_2 = Label(self.fr32 1_2, text = "SENSOR 2")
self.fr321_2.inst_label_2.pack(side = LEFT)
self.fr321_2.checkvar2 = IntVar()
self.fr321_2.checkbutton2 = Checkbutton(sel f.fr321_2, variable = self.fr321_2.checkvar2, onval ue = 1,
offvalue = 0)
self.fr321_2.checkbutton2.pack(side = LEFT)
self.fr321_2.inst_label_3 = Label(self.fr32 1_2, text = "SENSOR 3")
self.fr321_2.inst_label_3.pack(side = LEFT)
self.fr321_2.checkvar3 = IntVar()
self.fr321_2.checkbutton3 = Checkbutton(sel f.fr321_2, variable = self.fr321_2.checkvar3, onval ue = 1,
offvalue = 0)
self.fr321_2.checkbutton3.pack(side = LEFT)
## define gui button for sensor reading
self.fr321_3.Create = Button(self.fr321_3, text = 'READ', width = 10, command = self.READDATA)
self.fr321_3.Create.pack(side = RIGHT)
## 2nd selection – read data from sensors c yclicaly (define check buttons for each sensor, def ine text
entry for cycle time input)
Radiobutton(self.fr322_1, text = "READ DATA :", variable = self.fr32.favorite, value = "polling ",
command = self.CURRENTACTION, height = 3, anchor = W).pack(side = LEFT)
self.fr322_2.inst_label_1 = Label(self.fr32 2_2, text = "SENSOR 1")
self.fr322_2.inst_label_1.pack(side = LEFT)
self.fr322_2.checkvar1 = IntVar()
self.fr322_2.checkbutton1 = Checkbutton(sel f.fr322_2, variable = self.fr322_2.checkvar1, onval ue = 1,
offvalue = 0)
self.fr322_2.checkbutton1.pack(side = LEFT)
self.fr322_2.inst_label_2 = Label(self.fr32 2_2, text = "SENSOR 2")
self.fr322_2.inst_label_2.pack(side = LEFT)
self.fr322_2.checkvar2 = IntVar()
self.fr322_2.checkbutton2 = Checkbutton(sel f.fr322_2, variable = self.fr322_2.checkvar2, onval ue = 1,
offvalue = 0)
self.fr322_2.checkbutton2.pack(side = LEFT)
self.fr322_2.inst_label_3 = Label(self.fr32 2_2, text = "SENSOR 3")
self.fr322_2.inst_label_3.pack(side = LEFT)
self.fr322_2.checkvar3 = IntVar()
self.fr322_2.checkbutton3 = Checkbutton(sel f.fr322_2, variable = self.fr322_2.checkvar3, onval ue = 1,
offvalue = 0)
self.fr322_2.checkbutton3.pack(side = LEFT)
self.fr322_3.inst_label_4 = Label(self.fr32 2_3, text = "CYCLETIME:")
self.fr322_3.inst_label_4.pack(side = LEFT)
self.fr322_3.inst_text_1 = StringVar()
self.fr322_3.inst_text_entry1 = Entry(self. fr322_3, width = 7, textvariable=self.fr322_3.inst_ text_1,
justify = CENTER)
self.fr322_3.inst_text_entry1.insert(0,"500 0")
self.fr322_3.inst_text_entry1.pack(side = L EFT)
self.fr322_3.inst_label_5 = Label(self.fr32 2_3, text = "[ms]")
self.fr322_3.inst_label_5.pack(side = LEFT)
## define gui button for cyclic sensor read ing
self.fr322_4.Create1 = Button(self.fr322_4, text = 'AUTO', width = 10, command = self.READAUTO )
self.fr322_4.Create1.pack(anchor = NE)
Anex e
– 64 – ## define gui button for stoping the cyclic sensor reading
self.fr322_4.Create2 = Button(self.fr322_4, text = 'STOP', width = 10, command =
self.STOPAUTOREAD)
self.fr322_4.Create2.pack(anchor = SE)
## 3rd selection – send data on CAN (define text entries for message id , type, length, data f ield and
cycle time)
Radiobutton(self.fr323_1, text = "SEND DATA :", variable = self.fr32.favorite, value = "sendnow ",
command = self.CURRENTACTION, height = 3, anchor = W).pack(side = LEFT)
self.fr323_2.inst_label_1 = Label(self.fr32 3_2, text = "ID: ")
self.fr323_2.inst_label_1.pack(side = LEFT)
self.fr323_2.inst_text_1 = StringVar()
self.fr323_2.inst_text_entry1 = Entry(self. fr323_2, width = 5, textvariable=self.fr323_2.inst_ text_1,
justify = CENTER)
self.fr323_2.inst_text_entry1.insert(0,"100 ")
self.fr323_2.inst_text_entry1.pack(side = L EFT)
self.fr323_2.inst_label_2 = Label(self.fr32 3_2, text = " TYPE:")
self.fr323_2.inst_label_2.pack(side = LEFT)
self.fr323_2.inst_text_2 = StringVar()
self.fr323_2.inst_text_entry2 = Entry(self. fr323_2, width = 12, textvariable=self.fr323_2.inst _text_2,
justify = CENTER)
self.fr323_2.inst_text_entry2.insert(0,"STA NDARD")
self.fr323_2.inst_text_entry2.pack(side = L EFT)
self.fr323_2.inst_label_3 = Label(self.fr32 3_2, text = " DLC:")
self.fr323_2.inst_label_3.pack(side = LEFT)
self.fr323_2.inst_text_3 = StringVar()
self.fr323_2.inst_text_entry3 = Entry(self. fr323_2, width = 3, textvariable=self.fr323_2.inst_ text_3,
justify = CENTER)
self.fr323_2.inst_text_entry3.insert(0,"8")
self.fr323_2.inst_text_entry3.pack(side = L EFT)
self.fr323_3.inst_label_4 = Label(self.fr32 3_3, text = "DATA:")
self.fr323_3.inst_label_4.pack(side = LEFT)
self.fr323_3.inst_label_5 = Label(self.fr32 3_3, text = "MS")
self.fr323_3.inst_label_5.pack(side = LEFT)
## define text entries for each data byte
## text entry for rx data[0]
self.fr323_3.inst_text_datavar1 = StringVar ()
self.fr323_3.inst_text_data1 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar1, justi fy = CENTER)
self.fr323_3.inst_text_data1.insert(0,"00")
self.fr323_3.inst_text_data1.pack(side = LE FT)
## text entry for rx data[1]
self.fr323_3.inst_text_datavar2 = StringVar ()
self.fr323_3.inst_text_data2 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar2, justi fy = CENTER)
self.fr323_3.inst_text_data2.insert(0,"00")
self.fr323_3.inst_text_data2.pack(side = LE FT)
## text entry for rx data[2]
self.fr323_3.inst_text_datavar3 = StringVar ()
self.fr323_3.inst_text_data3 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar3, justi fy = CENTER)
self.fr323_3.inst_text_data3.insert(0,"00")
self.fr323_3.inst_text_data3.pack(side = LE FT)
Anex e
– 65 – ## text entry for rx data[3]
self.fr323_3.inst_text_datavar4 = StringVar ()
self.fr323_3.inst_text_data4 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar4, justi fy = CENTER)
self.fr323_3.inst_text_data4.insert(0,"00")
self.fr323_3.inst_text_data4.pack(side = LE FT)
## text entry for rx data[4]
self.fr323_3.inst_text_datavar5 = StringVar ()
self.fr323_3.inst_text_data5 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar5, justi fy = CENTER)
self.fr323_3.inst_text_data5.insert(0,"00")
self.fr323_3.inst_text_data5.pack(side = LE FT)
## text entry for rx data[5]
self.fr323_3.inst_text_datavar6 = StringVar ()
self.fr323_3.inst_text_data6 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar6, justi fy = CENTER)
self.fr323_3.inst_text_data6.insert(0,"00")
self.fr323_3.inst_text_data6.pack(side = LE FT)
## text entry for rx data[6]
self.fr323_3.inst_text_datavar7 = StringVar ()
self.fr323_3.inst_text_data7 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar7, justi fy = CENTER)
self.fr323_3.inst_text_data7.insert(0,"00")
self.fr323_3.inst_text_data7.pack(side = LE FT)
## text entry for rx data[7]
self.fr323_3.inst_text_datavar8 = StringVar ()
self.fr323_3.inst_text_data8 = Entry(self.f r323_3, width = 3,
textvariable=self.fr323_3.inst_text_datavar8, justi fy = CENTER)
self.fr323_3.inst_text_data8.insert(0,"00")
self.fr323_3.inst_text_data8.pack(side = LE FT)
self.fr323_3.inst_label_6 = Label(self.fr32 3_3, text = "LS")
self.fr323_3.inst_label_6.pack(side = LEFT)
## define entry for cycle time value
self.fr323_4.inst_label_1 = Label(self.fr32 3_4, text = "CYCLETIME:")
self.fr323_4.inst_label_1.pack(side = LEFT)
self.fr323_4.inst_text_1 = StringVar()
self.fr323_4.inst_text_entry1 = Entry(self. fr323_4, width = 7, textvariable=self.fr323_4.inst_ text_1,
justify = CENTER)
self.fr323_4.inst_text_entry1.insert(0, "0" )
self.fr323_4.inst_text_entry1.pack(side = L EFT)
self.fr323_4.inst_label_2 = Label(self.fr32 3_4, text = "[ms]")
self.fr323_4.inst_label_2.pack(side = LEFT)
## define gui button for sending data
self.fr323_5.Create1 = Button(self.fr323_5, text = 'SEND', width = 10, command = self.SENDDATA )
self.fr323_5.Create1.pack(anchor = NE)
## define gui button for stop sending data
self.fr323_5.Create2 = Button(self.fr323_5, text = 'STOP', width = 10, command =
self.STOPSENDDATA)
self.fr323_5.Create2.pack(anchor = SE)
Anex e
– 66 –
self.fr33.inst_label1 = Label(self.fr33, bg = 'azure')
self.fr33.inst_label1.pack(fill = BOTH, exp and = TRUE)
## define graphical user interface for RX d ata
self.fr41.inst_label1 = Label(self.fr41, te xt = "RECEIVED DATA", bg = 'azure',
font=("Arial",9,"bold"))
self.fr41.inst_label1.pack(fill = BOTH, exp and = TRUE)
self.fr421.inst_label1 = Label(self.fr421, text = "SENSOR 1", height = 2, font=("Arial",9,"bol d"))
self.fr421.inst_label1.pack(side = LEFT)
## define widget for received data value (s ensor 1)
self.fr422.inst_label1 = Label(self.fr422, text = "RX VALUE: ", height = 2)
self.fr422.inst_label1.pack(side = LEFT)
self.fr422.inst_text11 = StringVar()
inst_text11 = Entry(self.fr422, width = 20, textvariable = self.fr422.inst_text11, state = "re adonly",
readonlybackground = "white", justify = CENTER)
inst_text11.pack(side = RIGHT)
## define widget for receiving time moment of data value (sensor 1)
self.fr423.inst_label1 = Label(self.fr423, text = "RX TIME: ", height = 2)
self.fr423.inst_label1.pack(side = LEFT)
self.fr423.inst_text12 = StringVar()
inst_text12 = Entry(self.fr423, width = 20, textvariable = self.fr423.inst_text12, state = "re adonly",
readonlybackground = "white", justify = CENTER)
inst_text12.pack(side = RIGHT)
self.fr431.inst_label1 = Label(self.fr431, text = "SENSOR 2", height = 2, font=("Arial",9,"bol d"))
self.fr431.inst_label1.pack(side = LEFT)
## define widget for received data value (s ensor 2)
self.fr432.inst_label1 = Label(self.fr432, text = "RX VALUE: ", height = 2)
self.fr432.inst_label1.pack(side = LEFT)
self.fr432.inst_text21 = StringVar()
inst_text21 = Entry(self.fr432, width = 20, textvariable = self.fr432.inst_text21, state = "re adonly",
readonlybackground = "white", justify = CENTER)
inst_text21.pack(side = RIGHT)
## define widget for receiving time moment of data value (sensor 2)
self.fr433.inst_label1 = Label(self.fr433, text = "RX TIME: ", height = 2)
self.fr433.inst_label1.pack(side = LEFT)
self.fr433.inst_text22 = StringVar()
inst_text22 = Entry(self.fr433, width = 20, textvariable = self.fr433.inst_text22, state = "re adonly",
readonlybackground = "white", justify = CENTER)
inst_text22.pack(side = RIGHT)
self.fr441.inst_label1 = Label(self.fr441, text = "SENSOR 3", height = 2, font=("Arial",9,"bol d"))
self.fr441.inst_label1.pack(side = LEFT)
## define widget for received data value (s ensor 3)
self.fr442.inst_label1 = Label(self.fr442, text = "RX VALUE: ", height = 2)
self.fr442.inst_label1.pack(side = LEFT)
self.fr442.inst_text31 = StringVar()
inst_text31 = Entry(self.fr442, width = 20, textvariable = self.fr442.inst_text31, state = "re adonly",
readonlybackground = "white", justify = CENTER)
inst_text31.pack(side = RIGHT)
Anex e
– 67 –
## define widget for receiving time moment of data value (sensor 3)
self.fr443.inst_label1 = Label(self.fr443, text = "RX TIME: ", height = 2)
self.fr443.inst_label1.pack(side = LEFT)
self.fr443.inst_text32 = StringVar()
inst_text32 = Entry(self.fr443, width = 20, textvariable = self.fr443.inst_text32, state = "re adonly",
readonlybackground = "white", justify = CENTER)
inst_text32.pack(side = RIGHT)
self.fr45.inst_label1 = Label(self.fr45, bg = 'azure')
self.fr45.inst_label1.pack(fill = BOTH, exp and = TRUE)
## define gui button for uninitializing the PCAN channel
self.fr5.Create = Button(self.fr5, text = ' RELEASE PCAN_USBBUS1 AND EXIT', width = 10, command
= self.EXIT)
self.fr5.Create.pack(fill = BOTH)
## define graphical user interface for disp layed informations
self.fr71.inst_label1 = Label(self.fr71, te xt = "INFORMATIONS", bg = 'azure', font=("Arial",9, "bold"))
self.fr71.inst_label1.pack(fill = BOTH)
self.fr72.yInfoScroll = Scrollbar(self.fr72 , orient=VERTICAL)
self.fr72.yInfoScroll.pack(fill = BOTH, sid e = RIGHT)
self.fr72.lbxInfo = Listbox(self.fr72, acti vestyle="none", yscrollcommand=self.fr72.yInfoScrol l.set)
self.fr72.lbxInfo.pack(fill = BOTH)
self.fr72.yInfoScroll['command'] = self.fr7 2.lbxInfo.yview
self.fr72.lbxInfo.insert(END," – Click 'INI TIALIZE PCAN_USBBUS1 CHANNEL' button.")
## define gui button for uninitializing the PCAN channel
self.fr73.Create = Button(self.fr73, text = 'CLEAR INFORMATION WINDOW', width = 10, command
= self.CLEARINFO)
self.fr73.Create.pack(fill = BOTH)
## define the corresponding action or each gui button
def CURRENTACTION(self):
if self.fr32.favorite.get() == "readnow":
## if 1st selection (read data from sen sors)
## enable corresponding gui part and di sable all rest
self.fr321_3.Create.configure(state = N ORMAL)
self.fr322_4.Create1.configure(state = DISABLED)
self.fr322_4.Create2.configure(state = DISABLED)
self.fr323_5.Create1.configure(state = DISABLED)
self.fr323_5.Create2.configure(state = DISABLED)
self.fr321_2.checkbutton1.config(state = NORMAL)
self.fr321_2.checkbutton2.config(state = NORMAL)
self.fr321_2.checkbutton3.config(state = NORMAL)
self.fr322_3.inst_text_entry1.config(st ate = DISABLED)
self.fr322_2.checkbutton1.config(state = DISABLED)
self.fr322_2.checkbutton2.config(state = DISABLED)
self.fr322_2.checkbutton3.config(state = DISABLED)
self.fr323_2.inst_text_entry1.config(st ate = DISABLED)
self.fr323_2.inst_text_entry2.config(st ate = DISABLED)
Anex e
– 68 – self.fr323_2.inst_text_entry3.config(st ate = DISABLED)
self.fr323_3.inst_text_data1.config(sta te = DISABLED)
self.fr323_3.inst_text_data2.config(sta te = DISABLED)
self.fr323_3.inst_text_data3.config(sta te = DISABLED)
self.fr323_3.inst_text_data4.config(sta te = DISABLED)
self.fr323_3.inst_text_data5.config(sta te = DISABLED)
self.fr323_3.inst_text_data6.config(sta te = DISABLED)
self.fr323_3.inst_text_data7.config(sta te = DISABLED)
self.fr323_3.inst_text_data8.config(sta te = DISABLED)
self.fr323_4.inst_text_entry1.config(st ate = DISABLED)
elif self.fr32.favorite.get() == "polling":
## if 2nd selection (read data from sen sors cyclically)
## enable corresponding gui part and di sable all rest
self.fr321_3.Create.configure(state = D ISABLED)
self.fr322_4.Create1.configure(state = NORMAL)
self.fr322_4.Create2.configure(state = DISABLED)
self.fr323_5.Create1.configure(state = DISABLED)
self.fr323_5.Create2.configure(state = DISABLED)
self.fr321_2.checkbutton1.config(state = DISABLED)
self.fr321_2.checkbutton2.config(state = DISABLED)
self.fr321_2.checkbutton3.config(state = DISABLED)
self.fr322_3.inst_text_entry1.config(st ate = NORMAL)
self.fr322_2.checkbutton1.config(state = NORMAL)
self.fr322_2.checkbutton2.config(state = NORMAL)
self.fr322_2.checkbutton3.config(state = NORMAL)
self.fr323_2.inst_text_entry1.config(st ate = DISABLED)
self.fr323_2.inst_text_entry2.config(st ate = DISABLED)
self.fr323_2.inst_text_entry3.config(st ate = DISABLED)
self.fr323_3.inst_text_data1.config(sta te = DISABLED)
self.fr323_3.inst_text_data2.config(sta te = DISABLED)
self.fr323_3.inst_text_data3.config(sta te = DISABLED)
self.fr323_3.inst_text_data4.config(sta te = DISABLED)
self.fr323_3.inst_text_data5.config(sta te = DISABLED)
self.fr323_3.inst_text_data6.config(sta te = DISABLED)
self.fr323_3.inst_text_data7.config(sta te = DISABLED)
self.fr323_3.inst_text_data8.config(sta te = DISABLED)
self.fr323_4.inst_text_entry1.config(st ate = DISABLED)
elif self.fr32.favorite.get() == "sendnow":
## if 3rd selection (send data on can)
## enable corresponding gui part and di sable all rest
self.fr321_3.Create.configure(state = D ISABLED)
self.fr322_4.Create1.configure(state = DISABLED)
self.fr322_4.Create2.configure(state = DISABLED)
self.fr323_5.Create1.configure(state = NORMAL)
self.fr323_5.Create2.configure(state = DISABLED)
self.fr321_2.checkbutton1.config(state = DISABLED)
self.fr321_2.checkbutton2.config(state = DISABLED)
self.fr321_2.checkbutton3.config(state = DISABLED)
self.fr322_3.inst_text_entry1.config(st ate = DISABLED)
self.fr322_2.checkbutton1.config(state = DISABLED)
Anex e
– 69 – self.fr322_2.checkbutton2.config(state = DISABLED)
self.fr322_2.checkbutton3.config(state = DISABLED)
self.fr323_2.inst_text_entry1.config(st ate = NORMAL)
self.fr323_2.inst_text_entry2.config(st ate = NORMAL)
self.fr323_2.inst_text_entry3.config(st ate = NORMAL)
self.fr323_3.inst_text_data1.config(sta te = NORMAL)
self.fr323_3.inst_text_data2.config(sta te = NORMAL)
self.fr323_3.inst_text_data3.config(sta te = NORMAL)
self.fr323_3.inst_text_data4.config(sta te = NORMAL)
self.fr323_3.inst_text_data5.config(sta te = NORMAL)
self.fr323_3.inst_text_data6.config(sta te = NORMAL)
self.fr323_3.inst_text_data7.config(sta te = NORMAL)
self.fr323_3.inst_text_data8.config(sta te = NORMAL)
self.fr323_4.inst_text_entry1.config(st ate = NORMAL)
## define processing function for received mess ages
def ProcessMessage(self, *args):
## split the arguments. [0] TPCANMsg, [1] T PCANTimestamp
rxmsg = args[0][0]
rxtimestamp = args[0][1]
global rxmsg1_status, rxmsg2_status, rxmsg3 _status
if (rxmsg.ID == 256 and rxmsg1_status == 0) :
## if message 0x100 is received
rxmsg1_timesec = time.localtime().tm_se c
rxmsg1_timemin = time.localtime().tm_mi n
rxmsg1_timehour = time.localtime().tm_h our
rxmsg1_status = 1
self.fr422.inst_text11.set(str(rxmsg.DA TA[0]))
self.fr423.inst_text12.set("h" + str(rx msg1_timehour) + " m" + str(rxmsg1_timemin) + " s" +
str(rxmsg1_timesec))
self.fr72.lbxInfo.insert(END, " – RX ms g from sensor 1: " + "Type: " + str(rxmsg.MSGTYPE) + ", " +
"DLC: " + str(rxmsg.LEN) + ", " + "Data: " + str(rx msg.DATA[0])+ " " + str(rxmsg.DATA[1])+ " " +
str(rxmsg.DATA[2])+ " " + str(rxmsg.DATA[3])+ " " + str(rxmsg.DATA[4])+ " " + str(rxmsg.DATA[5])+ "
" + str(rxmsg.DATA[6])+ " " + str(rxmsg.DATA[7]) + ", " + "TimeStamp: " + str(rxtimestamp.millis))
self.fr72.lbxInfo.insert(END, " – RX Me ssage 1 reception time moment: " + "h" +
str(rxmsg1_timehour) + "m" + str(rxmsg1_timemin) + "s" + str(rxmsg1_timesec))
self.fr72.lbxInfo.yview_moveto(1)
elif (rxmsg.ID == 272 and rxmsg2_status == 0):
## if message 0x110 is received
rxmsg2_timesec = time.localtime().tm_se c
rxmsg2_timemin = time.localtime().tm_mi n
rxmsg2_timehour = time.localtime().tm_h our
rxmsg2_status = 1
self.fr432.inst_text21.set(rxmsg.DATA[0 ])
self.fr433.inst_text22.set("h" + str(rx msg2_timehour) + " m" + str(rxmsg2_timemin) + " s" +
str(rxmsg2_timesec))
self.fr72.lbxInfo.insert(END, " – RX ms g from sensor 2: " + "Type: " + str(rxmsg.MSGTYPE) + ", " +
"DLC: " + str(rxmsg.LEN) + ", " + "Data: " + str(rx msg.DATA[0])+ " " + str(rxmsg.DATA[1])+ " " +
str(rxmsg.DATA[2])+ " " + str(rxmsg.DATA[3])+ " " + str(rxmsg.DATA[4])+ " " + str(rxmsg.DATA[5])+ "
" + str(rxmsg.DATA[6])+ " " + str(rxmsg.DATA[7]) + ", " + "TimeStamp: " + str(rxtimestamp.millis))
self.fr72.lbxInfo.insert(END, " – RX Me ssage 2 reception time moment: " + "h" +
str(rxmsg2_timehour) + "m" + str(rxmsg2_timemin) + "s" + str(rxmsg2_timesec))
self.fr72.lbxInfo.yview_moveto(1)
Anex e
– 70 – elif (rxmsg.ID == 288 and rxmsg3_status == 0):
## if message 0x120 is received
rxmsg3_timesec = time.localtime().tm_se c
rxmsg3_timemin = time.localtime().tm_mi n
rxmsg3_timehour = time.localtime().tm_h our
rxmsg3_status = 1
self.fr442.inst_text31.set(rxmsg.DATA[0 ])
self.fr443.inst_text32.set("h" + str(rx msg3_timehour) + " m" + str(rxmsg3_timemin) + " s" +
str(rxmsg3_timesec))
self.fr72.lbxInfo.insert(END, " – RX ms g from sensor 3: " + "Type: " + str(rxmsg.MSGTYPE) + ", " +
"DLC: " + str(rxmsg.LEN) + ", " + "Data: " + str(rx msg.DATA[0])+ " " + str(rxmsg.DATA[1])+ " " +
str(rxmsg.DATA[2])+ " " + str(rxmsg.DATA[3])+ " " + str(rxmsg.DATA[4])+ " " + str(rxmsg.DATA[5])+ "
" + str(rxmsg.DATA[6])+ " " + str(rxmsg.DATA[7]) + ", " + "TimeStamp: " + str(rxtimestamp.millis))
self.fr72.lbxInfo.insert(END, " – RX Me ssage 3 reception time moment: " + "h" +
str(rxmsg3_timehour) + "m" + str(rxmsg3_timemin) + "s" + str(rxmsg3_timesec))
self.fr72.lbxInfo.yview_moveto(1)
## define action for pcan channel initializatio n button
def INITIALIZE(self):
## initialize status of the rx messages
global rxmsg1_status, rxmsg2_status, rxmsg3 _status
rxmsg1_status = 0
rxmsg2_status = 0
rxmsg3_status = 0
## initialize PCAN_USBBUS1 channel
result_initialize = objPCAN.Initialize(PCAN _USBBUS1, PCAN_BAUD_500K)
if result_initialize != PCAN_ERROR_OK:
## if an error occurred, get a text des cribing the error and show it
result_initialize = objPCAN.GetErrorTex t(result_initialize)
self.fr72.lbxInfo.insert(END," – PCAN i nit: " + result_initialize[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – PCAN init: PCAN_USBBUS1 channel was initialized")
self.fr72.lbxInfo.yview_moveto(1)
## define action for 1st selection (read data f rom sensors)
def READDATA(self):
## get the local time
starttime = time.localtime().tm_sec
## define TX message
txmsg = TPCANMsg()
txmsg.ID = 0x200
txmsg.MSGTYPE = PCAN_MESSAGE_STANDARD
txmsg.LEN = 8
if (self.fr321_2.checkvar1.get() == 1 and s elf.fr321_2.checkvar2.get() == 0 and
self.fr321_2.checkvar3.get() == 0):
txmsg.DATA[0] = 1
elif (self.fr321_2.checkvar1.get() == 0 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 0):
txmsg.DATA[0] = 2
elif (self.fr321_2.checkvar1.get() == 1 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 0):
txmsg.DATA[0] = 3
elif (self.fr321_2.checkvar1.get() == 0 and self.fr321_2.checkvar2.get() == 0 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 4
Anex e
– 71 – elif (self.fr321_2.checkvar1.get() == 1 and self.fr321_2.checkvar2.get() == 0 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 5
elif (self.fr321_2.checkvar1.get() == 0 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 6
elif (self.fr321_2.checkvar1.get() == 1 and self.fr321_2.checkvar2.get() == 1 and
self.fr321_2.checkvar3.get() == 1):
txmsg.DATA[0] = 7
else:
txmsg.DATA[0] = 0
global rxmsg1_status, rxmsg2_status, rxmsg3 _status
## clear the information window
self.fr72.lbxInfo.delete(0, END)
## The message is sent using the PCAN-USB Channel 1
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
if result_write != PCAN_ERROR_OK:
## if an error occurred, get a text des cribing the error and show it
result_write = objPCAN.GetErrorText(res ult_write)
self.fr72.lbxInfo.insert(END, " – PCAN write: " + result_write[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – PCAN write: TX message sent successfully")
self.fr72.lbxInfo.insert(END, " – PCAN reading …")
self.fr72.lbxInfo.yview_moveto(1)
while (rxmsg1_status == 0 or rxmsg2_sta tus == 0 or rxmsg3_status == 0):
readResult = objPCAN.Read(PCAN_USBB US1)
timeouttime = time.localtime().tm_s ec
if readResult[0] == PCAN_ERROR_OK:
## process the received message
self.ProcessMessage(readResult[ 1:])
else:
## if an error occurred, get a text describing the error and show it
result = objPCAN.GetErrorText(r eadResult[0])
## define reading timeout value [se conds]
if ((timeouttime – starttime) >= 0. 5):
if (rxmsg1_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 1 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
if (rxmsg2_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 2 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
if (rxmsg3_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 3 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
break
## command for finished communication
txmsg.DATA[0] = 0
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
Anex e
– 72 – ## uninitialize PCAN channel
objPCAN.Uninitialize(PCAN_USBBUS1)
self.fr72.lbxInfo.insert(END, " – PCAN unin it: PCAN_USBBUS1 channel was uninitialized")
self.fr72.lbxInfo.yview_moveto(1)
## define action for 2nd selection (read data f rom sensors cyclically)
def READAUTO(self):
## disable AUTO button/ enable STOP button
self.fr322_4.Create1.configure(state = DISA BLED)
self.fr322_4.Create2.configure(state = NORM AL)
## get cycle time value
rxmsgcycletime_ms = int(self.fr322_3.inst_t ext_1.get())
rxmsgcycletime_s = rxmsgcycletime_ms / 1000
global readtimer
if (rxmsgcycletime_ms > 0):
## if cycle time valid value start time r
readtimer = RepeatTimer(rxmsgcycletime_ s, self.READTIMER)
self.fr72.lbxInfo.insert(END, " – PCAN read: Cyclic reading started")
self.fr72.lbxInfo.yview_moveto(1)
readtimer.start()
else:
## if cycle time invalid value start re peating timer at 5000 ms default value
readtimer = RepeatTimer(5, self.READTIM ER)
self.fr72.lbxInfo.insert(END, " – PCAN read: Invalid cycle time value; Cycle time set to 5 000 ms
default value")
self.fr72.lbxInfo.yview_moveto(1)
readtimer.start()
##define timer action
def READTIMER(self):
## get the local time
starttime = time.localtime().tm_sec
## define TX message
global txmsg
txmsg = TPCANMsg()
txmsg.ID = 0x200
txmsg.MSGTYPE = PCAN_MESSAGE_STANDARD
txmsg.LEN = 8
if (self.fr322_2.checkvar1.get() == 1 and s elf.fr322_2.checkvar2.get() == 0 and
self.fr322_2.checkvar3.get() == 0):
txmsg.DATA[0] = 1
elif (self.fr322_2.checkvar1.get() == 0 and self.fr322_2.checkvar2.get() == 1 and
self.fr322_2.checkvar3.get() == 0):
txmsg.DATA[0] = 2
elif (self.fr322_2.checkvar1.get() == 1 and self.fr322_2.checkvar2.get() == 1 and
self.fr322_2.checkvar3.get() == 0):
txmsg.DATA[0] = 3
elif (self.fr322_2.checkvar1.get() == 0 and self.fr322_2.checkvar2.get() == 0 and
self.fr322_2.checkvar3.get() == 1):
txmsg.DATA[0] = 4
elif (self.fr322_2.checkvar1.get() == 1 and self.fr322_2.checkvar2.get() == 0 and
self.fr322_2.checkvar3.get() == 1):
txmsg.DATA[0] = 5
Anex e
– 73 – elif (self.fr322_2.checkvar1.get() == 0 and self.fr322_2.checkvar2.get() == 1 and
self.fr322_2.checkvar3.get() == 1):
txmsg.DATA[0] = 6
elif (self.fr322_2.checkvar1.get() == 1 and self.fr322_2.checkvar2.get() == 1 and
self.fr322_2.checkvar3.get() == 1):
txmsg.DATA[0] = 7
else:
txmsg.DATA[0] = 0
global rxmsg1_status, rxmsg2_status, rxmsg3 _status
rxmsg1_status = 0
rxmsg2_status = 0
rxmsg3_status = 0
## initialize PCAN_USBBUS1 channel
objPCAN.Initialize(PCAN_USBBUS1, PCAN_BAUD_ 500K)
## the message is sent using the PCAN-USB Channel 1
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
if result_write != PCAN_ERROR_OK:
## if an error occurred, get a text des cribing the error and show it
result_write = objPCAN.GetErrorText(res ult_write)
self.fr72.lbxInfo.insert(END, " – PCAN write: " + result_write[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – PCAN write: TX message sent successfully")
self.fr72.lbxInfo.insert(END, " – PCAN cyclic reading …")
self.fr72.lbxInfo.yview_moveto(1)
while (rxmsg1_status == 0 or rxmsg2_sta tus == 0 or rxmsg3_status == 0):
readResult = objPCAN.Read(PCAN_USBB US1)
timeouttime = time.localtime().tm_s ec
if readResult[0] == PCAN_ERROR_OK:
## process the received message
self.ProcessMessage(readResult[ 1:])
else:
## if an error occurred, get a text describing the error and show it
result = objPCAN.GetErrorText(r eadResult[0])
## define reading timeout value [se conds]
if ((timeouttime – starttime) >= 0. 5):
if (rxmsg1_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 1 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
if (rxmsg2_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 2 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
if (rxmsg3_status == 0):
self.fr72.lbxInfo.insert(EN D, " – RX Message 3 timeout")
self.fr72.lbxInfo.yview_mov eto(1)
break
## command for finished communication
txmsg.DATA[0] = 0
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
## uninitialize PCAN channel
objPCAN.Uninitialize(PCAN_USBBUS1)
Anex e
– 74 –
## define stop auto reading action
def STOPAUTOREAD(self):
global readtimer, txmsg
## enable AUTO button/ disable STOP button
self.fr322_4.Create1.configure(state = NORM AL)
self.fr322_4.Create2.configure(state = DISA BLED)
## command for finished communication
txmsg.DATA[0] = 0
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
## timer stop
readtimer.cancel()
self.fr72.lbxInfo.insert(END, " – PCAN read : Cyclic reading stopped")
self.fr72.lbxInfo.yview_moveto(1)
## uninitialize PCAN channel
objPCAN.Uninitialize(PCAN_USBBUS1)
## define action for 3rd selection (send data o n can)
def SENDDATA(self):
## disable SEND button/ enable STOP button
self.fr323_5.Create1.configure(state = DISA BLED)
self.fr323_5.Create2.configure(state = NORM AL)
## define TX message
global txmsg, sendtimer
txmsg = TPCANMsg()
## get tx message id
txmsg.ID = int(self.fr323_2.inst_text_1.get ())
## get tx message type
txmsgtype = self.fr323_2.inst_text_2.get()
txmsgtype = txmsgtype.strip()
txmsgtype = txmsgtype.lower()
if (txmsgtype == "standard"):
txmsg.MSGTYPE = PCAN_MESSAGE_STANDARD
elif (txmsgtype == "extended"):
txmsg.MSGTYPE = PCAN_MESSAGE_EXTENDED
else:
self.fr72.lbxInfo.insert(END, " – PCAN transmit: Invalid message type (valid types: STANDA RD or
EXTENDED); MSGTYPE set to STANDARD")
self.fr72.lbxInfo.yview_moveto(1)
txmsg.MSGTYPE = PCAN_MESSAGE_STANDARD
## get tx message length and tx data
txmsg.LEN = int(self.fr323_2.inst_text_3.ge t())
if ((txmsg.LEN < 0) or (txmsg.LEN > 8)):
## if invalid value set DLC to default 8
txmsg.LEN = 8
self.fr72.lbxInfo.insert(END, " – PCAN transmit: Invalid message length; DLC set to 8")
self.fr72.lbxInfo.yview_moveto(1)
elif (txmsg.LEN == 0):
txmsg.DATA[0] = 0
txmsg.DATA[1] = 0
txmsg.DATA[2] = 0
Anex e
– 75 – txmsg.DATA[3] = 0
txmsg.DATA[4] = 0
txmsg.DATA[5] = 0
txmsg.DATA[6] = 0
txmsg.DATA[7] = 0
elif (txmsg.LEN == 1):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = 0
txmsg.DATA[2] = 0
txmsg.DATA[3] = 0
txmsg.DATA[4] = 0
txmsg.DATA[5] = 0
txmsg.DATA[6] = 0
txmsg.DATA[7] = 0
elif (txmsg.LEN == 2):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_t ext_datavar2.get())
txmsg.DATA[2] = 0
txmsg.DATA[3] = 0
txmsg.DATA[4] = 0
txmsg.DATA[5] = 0
txmsg.DATA[6] = 0
txmsg.DATA[7] = 0
elif (txmsg.LEN == 3):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_t ext_datavar2.get())
txmsg.DATA[2] = int(self.fr323_3.inst_t ext_datavar3.get())
txmsg.DATA[3] = 0
txmsg.DATA[4] = 0
txmsg.DATA[5] = 0
txmsg.DATA[6] = 0
txmsg.DATA[7] = 0
elif (txmsg.LEN == 4):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_t ext_datavar2.get())
txmsg.DATA[2] = int(self.fr323_3.inst_t ext_datavar3.get())
txmsg.DATA[3] = int(self.fr323_3.inst_t ext_datavar4.get())
txmsg.DATA[4] = 0
txmsg.DATA[5] = 0
txmsg.DATA[6] = 0
txmsg.DATA[7] = 0
elif (txmsg.LEN == 5):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_t ext_datavar2.get())
txmsg.DATA[2] = int(self.fr323_3.inst_t ext_datavar3.get())
txmsg.DATA[3] = int(self.fr323_3.inst_t ext_datavar4.get())
txmsg.DATA[4] = int(self.fr323_3.inst_t ext_datavar5.get())
txmsg.DATA[5] = 0
txmsg.DATA[6] = 0
txmsg.DATA[7] = 0
elif (txmsg.LEN == 6):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_t ext_datavar2.get())
txmsg.DATA[2] = int(self.fr323_3.inst_t ext_datavar3.get())
txmsg.DATA[3] = int(self.fr323_3.inst_t ext_datavar4.get())
txmsg.DATA[4] = int(self.fr323_3.inst_t ext_datavar5.get())
txmsg.DATA[5] = int(self.fr323_3.inst_t ext_datavar6.get())
Anex e
– 76 – txmsg.DATA[6] = 0
txmsg.DATA[7] = 0
elif (txmsg.LEN == 7):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_t ext_datavar2.get())
txmsg.DATA[2] = int(self.fr323_3.inst_t ext_datavar3.get())
txmsg.DATA[3] = int(self.fr323_3.inst_t ext_datavar4.get())
txmsg.DATA[4] = int(self.fr323_3.inst_t ext_datavar5.get())
txmsg.DATA[5] = int(self.fr323_3.inst_t ext_datavar6.get())
txmsg.DATA[6] = int(self.fr323_3.inst_t ext_datavar7.get())
txmsg.DATA[7] = 0
elif (txmsg.LEN == 8):
txmsg.DATA[0] = int(self.fr323_3.inst_t ext_datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_t ext_datavar2.get())
txmsg.DATA[2] = int(self.fr323_3.inst_t ext_datavar3.get())
txmsg.DATA[3] = int(self.fr323_3.inst_t ext_datavar4.get())
txmsg.DATA[4] = int(self.fr323_3.inst_t ext_datavar5.get())
txmsg.DATA[5] = int(self.fr323_3.inst_t ext_datavar6.get())
txmsg.DATA[6] = int(self.fr323_3.inst_t ext_datavar7.get())
txmsg.DATA[7] = int(self.fr323_3.inst_t ext_datavar8.get())
## get tx message cycle time value
txmsgcycletime_ms = int(self.fr323_4.inst_t ext_1.get())
txmsgcycletime_s = txmsgcycletime_ms / 1000
if (txmsgcycletime_ms == 0):
## kickout message
result_write = objPCAN.Write(PCAN_USBBU S1, txmsg)
if result_write != PCAN_ERROR_OK:
## if an error occurred, get a text describing the error and show it
result_write = objPCAN.GetErrorText (result_write)
self.fr72.lbxInfo.insert(END, " – P CAN write: " + result_write[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – P CAN transmit: TX message" + " " + str(txmsg.ID) + " " + "sent
successfully on CAN bus")
self.fr72.lbxInfo.yview_moveto(1)
if (txmsgcycletime_ms < 0):
## if invalid cycle time value set to 0 ms default value and kickout message
self.fr72.lbxInfo.insert(END, " – PCAN transmit: Invalid cycle time value; Cycle time set to 0 ms
default value")
self.fr72.lbxInfo.yview_moveto(1)
result_write = objPCAN.Write(PCAN_USBBU S1, txmsg)
if result_write != PCAN_ERROR_OK:
## if an error occurred, get a text describing the error and show it
result_write = objPCAN.GetErrorText (result_write)
self.fr72.lbxInfo.insert(END, " – P CAN write: " + result_write[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – P CAN transmit: TX message" + " " + str(txmsg.ID) + " " + "sent
successfully on CAN bus")
self.fr72.lbxInfo.yview_moveto(1)
elif (txmsgcycletime_ms > 0):
## if cycle ime valid value start repea ting timer
sendtimer = RepeatTimer(txmsgcycletime_ s, self.SENDTIMER)
self.fr72.lbxInfo.insert(END, " – PCAN transmit: Cyclic sending started")
self.fr72.lbxInfo.yview_moveto(1)
Anex e
– 77 – sendtimer.start()
## define timer action for cyclically sending o n can bus
def SENDTIMER(self):
global txmsg
## get latest data
txmsg.DATA[0] = int(self.fr323_3.inst_text_ datavar1.get())
txmsg.DATA[1] = int(self.fr323_3.inst_text_ datavar2.get())
txmsg.DATA[2] = int(self.fr323_3.inst_text_ datavar3.get())
txmsg.DATA[3] = int(self.fr323_3.inst_text_ datavar4.get())
txmsg.DATA[4] = int(self.fr323_3.inst_text_ datavar5.get())
txmsg.DATA[5] = int(self.fr323_3.inst_text_ datavar6.get())
txmsg.DATA[6] = int(self.fr323_3.inst_text_ datavar7.get())
txmsg.DATA[7] = int(self.fr323_3.inst_text_ datavar8.get())
## send tx message on can bus
result_write = objPCAN.Write(PCAN_USBBUS1, txmsg)
if result_write != PCAN_ERROR_OK:
## if an error occurred, get a text des cribing the error and show it
result_write = objPCAN.GetErrorText(res ult_write)
self.fr72.lbxInfo.insert(END, " – PCAN write: " + result_write[1])
self.fr72.lbxInfo.yview_moveto(1)
else:
self.fr72.lbxInfo.insert(END, " – PCAN transmit: TX message" + " " + str(txmsg.ID) + " " + "sent
successfully on CAN bus")
self.fr72.lbxInfo.yview_moveto(1)
## define stop sending data action
def STOPSENDDATA(self):
## enable SEND button/ disable STOP button
self.fr323_5.Create1.configure(state = NORM AL)
self.fr323_5.Create2.configure(state = DISA BLED)
global sendtimer
## timer stop
sendtimer.cancel()
self.fr72.lbxInfo.insert(END, " – PCAN tran smit: Cyclic sending stopped")
self.fr72.lbxInfo.yview_moveto(1)
## uninitialize PCAN channel
objPCAN.Uninitialize(PCAN_USBBUS1)
def CLEARINFO(self):
## the information contained in the Informa tion List-Box is cleared
self.fr72.lbxInfo.delete(0,END)
## define action for RELEASE AND EXIT button
def EXIT(self):
objPCAN.Uninitialize(PCAN_USBBUS1)
tkMessageBox.showinfo(title = "Info", messa ge = "PCAN_USBBUS1 CHANNEL IS RELEASED")
self.fr72.lbxInfo.insert(END, " – PCAN unin it: PCAN_USBBUS1 channel was uninitialized")
root.destroy()
root = Tk()
root.title("PCAN INTERFACE")
root.minsize(620, 682)
Application(root)
root.mainloop()
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: PROIECT DE DIZERTA łIE [622440] (ID: 622440)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
