Prisijungti

pyserial biblioteka

  • 17 Geg '12

Sveiki,
niekur forume neradau temos, apie pyserial biblioteką, tad nauja tema.

Mėginu su wxPython sukurti GUI, skirtą atvaizduoti per COM portą ateinantiems duomenims. Kol kas duomenys generuojami PROTEUS ISIS programoje (PIC mikrovaldiklio Analogas-skaicius keitiklis generuoja 12 bitų naudingų duomenų. Keitiklio įėjime veikia sinusinis signalas, daznis 1Hz. Min reiksmė 0V (0 = 0x000), max 5V (4095 = 0xFFF)). Reiksmę nuskaitau ir išsiunčiu per Com portą 3 baitus informacijos. Pirmi du baitai tie 12 bitukų, trečias baitas - STOP simbolis. Kodas tiems trims baitams nuskaityti ir atvaizduoti Shell'e atrodytų: taip.

Dėja, kartais gaunu tokius EROR'us: pvz1;pvz2. Nesuprantu kas jį iššaukia, nes jis nepriklauso nuo keitiklyje pamatuotos vertės, o juo labiau, klaviatūra galiu nusiųsti bet kokius du baitus informacijos (0x001 {CTRL+A}; 0x000 {CTRL+SHIFT+@}; 0x002 {CTRL+B}; ir t.t.) ir gaunu vertę be EROR'o. Dabar pagalvojęs mąstau kad tai gali būti RS232 sąsajoje atsiradę iškraipymai, neteisingai perduodantys informacijos baitus. Gal galėtumėte pasiūlyti būdų, kaip valdyti tą EROR, pvz.: jei toks EROR, tai spausdintu paskutinę reikšmę. Ačiū už pastangas.

  • 18 Geg '12

Klaidoje rašo IndexError, greičiausiai dėl to kad "data" gražino stringą su vienu char'u, arba išvis tuščia. Prieš naudojant d[0], d[1] patikrink ar liste "d" yra pakankamai (šiuo atveju 2) elementų.

  • 18 Geg '12

Ačiū už atsakymą. Tikrai pagelbėjo. ERROR'as atsiranda, kai COM portu perduodama STOP reikšmė ("$"), neužpildžius d[0] ir d[1] listo elementų. Pavyzdyje matoma, kaip nuskaitomos reikšmės (0x69A, 0x673, 0x64C, ERROR). Iš gautų verčių aišku kad nuskaitymo žingsnis būna 39 arba 40 vnt. Tai pamažinus vertę 0x64C skaičiumi 39 = 0x27 arba 40 = 0x28; gaunu kad ERROR'o metu atsiunčiama vertė yra atitinkamai 0x625 arba 0x624. Kadangi mano STOP char vertė 0x24, tai antruoju atveju, kai COM portas turėtų priimti vertę 0x624, jis sustoja ties 0x24, nes priėmęs STOP char mėgina daryti skaičiavimus. Čia postas sau atsiminimui
Klausimas:
Gal turite kokių pasiūlymų, kokiu eiliškumu nuskaityti, kad neatsirastų ERROR'as? Siunčiamus duomenis galiu modifikuoti kaip tinkamas, bet siekiamybė - kuo labiau sumažinti perduodamų simbolių kiekį, nes kiekvieno simbolio perdavimui gaištamas laikas. Iš esmės naudingųjų duomenų yra 2 baitai, o STOP Char rodo kad jau priimta 2baitai naudingųjų duomenų. Problema yra tame, kad naudingieji duomenys gali įgyti visas vertes nuo 0 iki 255, tai nelabai išeina parinkti kokį STOP char'ą. Kaip patartumėte tai spręsti?

  • 18 Geg '12

Reiktų apsibrėžti, kada "$" yra STOP, o kada naudinga info. Jei naudinga info yra tol kol 2 baitai neužpildyti, tuomet reiktų perašyti read_until funkcija, kad prieš nutraukiant skaityma patikrintų į kelintą baitą "$" bus kišamas.

  • 18 Geg '12

Tikriausiai nepadoru prašyti, bet gal galėtumėte pavyzdėlį numesti, nes mano mėginimai (labai menkos programavimo žinios) baigiasi ne kokiu rezultatu.

  • 18 Geg '12

Pavyzdžio nebūtų gaila, bet su portais ir baitais neteko dirbt, tai man neaišku kokiu formatu duomenys ateina su com.read().

Jei ten tiesiog char'ai, o iš "buffer" tikiesi jog jis bus dviejų charų ilgis tuomet reiktų nurodyti:
while not buffer.endswith(expected) and len(buffer) < 2:Bet tokiu atveju kyla klausimas kam išvis reikalingas buffer.endswith("$"). Jei tau būtinai reikia užpildyto buffer'io tai tiesiog suki cikla kol jį užpildai. Iš paskutinio tavo screeno matosi, kad 0x24 eina per visus. Jei tiksliai žinai, kad tavo duomenys bus 2 baitai, tau spec stop simbolio nereikia.

  • 19 Geg '12

Ačiū už pasiūlymą.
Dėl com.read(), tai jis turėtų išduoti Char reikšmę, nes per RS-232 sąsaja duomenys siunčiami 8 bitų porcijomis.
Iš esmės man tas STOP char kaip ir nereikalingas, bet..iš tų dviejų naudingųjų duomenų baitų reikia lipdyti 16 bitų int reikšmę, kad ją paversti dešimtainiu skaičiumi. Pavadinkime naudingųjų duomenų baitus LoB ir HiB, o 16bitų skaičių ADCv. To sulipdyto 16 bitų int reikšmės LoB ir HiB atsiduria skaičiaus 0x-### vertėje vietoje grotelių. LoB tupėtų 0x--**, o HiB būtų 0x-*-- vertės. Taigi, man svarbu eiliškumas. Nenaudojant jokio sinchronizacinio simbolio gali iškilti tokia problema: duomenys iš esmės siunčiami tokia tvarka: HiB, LoB, HiB, LoB, HiB, LoB. Tokiu atveju, jei siunčiamų duomenų eilėje pasirinktu laiko momentu pašaliname nors vieną LoB arba HiB, jo vietą užima paskui sekantis, ir iš jų suliejamas neteisingas ADCv. Ir tai tęsiasi tiek laiko, kol neperkraunama sistema, kad atstatyti teisinga duomenų seką. Tuo atveju kai naudojamas STOP simbolis seka atrodo taip: HiB, LoB, STOP, HiB, LoB, STOP, HiB, LoB, STOP. Tuomet dingsta problema dėl teisingo verčių identifikavimo, nes aiškiai žinoma pozicija ir neteisingas ADCv skaičiaus suliejimas tęsiasi tik tol kol nepriimta kita STOP simbolio vertė.

Taigi problemą matyt reikėtų spręsti taip: STOP simbolį identifikuoti kaip START ir po jo laukti kol užpildomas dviejų baitų listas "d[]". Tik nelabai sekasi teisingą skriptą sukurti. Ai, ir dar..šiuo atveju visgi išlieka problema, kad, jei nutiktų taip, kad naudingųjų duomenų vertė LoB arba HiB ilgą laiką būtų STOP/START simbolio vertės, tuomet ADCv vertė paskaičiuojama vėlgi neteisingai. Taigi, išvada tokia, kad nežinau kokį protokolą, ar kaip čia pavadinti, naudoti teisingam duomenų suliejimui, juos priėmus.

  • 20 Geg '12

Yra keli variantai.

  1. Variantas nenaudojantis STOP ir START baitu.
    Visu pirma galetum keitiklyje pasinaudoti tuo kad pas tave yra laisvi 4 bitai kuriuos gali panaudoti kaip identifikacinius numerius. Tai yra tarkime high bitas savo 2 bitus panaudos tarkime 0x01 ir 0x2 (dvi galimos reiksmes), o low bitas (0x0 ir 0x3). Tai yra tokiu atveju tu generuodamas duomenis kaskart atitinkamai padidinsi high arba low bito counterius (savaime suprantama duomenys tures buti atitinkamai perstumemia per bitu reiksmeles kad visi duomenys pilnai uzimtu 0x0000 isskaidytus i 0x00). Tokiu atveju pirmas siunciamas duomuo tures savo pirmame baite duomenys + identifikacinis 2 bitu reiksme nurodanti ar tai low ar tai high bei jo galima numeri (tai yra 0x1(High baitas) ir 0x0(low baitas)), kiti duomenu porcija jau tures (0x2(High) ir 0x3(Low)), tokiu atveju jei netycia tarpinis duomuo iskristu tarkime kompiuteris gaus 0x1(High), 0x2(High), 0x3(Low) tu zinosi kad prapuole kazkur vienas low baitas. Taciau visada zinosi kuris baitas yra low ir kuris high gaunamu duomenu sraute.

Visur kur as rasiau 0x02 ar ten 0x03 reiktu suprasti kad cia tiktai baito pirmieji bitai, sekanciu bitu kurie butu jau duomenys as nerasiau, realiai turetum greiciausiai tarkime 0b10111010 (High) ir 0b11011111 (LOW) vienai duomenu porcijai ir 0b11110101(High) 0b11010000(LOW) sekanciai einanciai duomenu (dvieju baitu) porcijai su realiais duoemnimis. Savaime suprantama gali naudoti paskutinius ar pirmus baito bitus identifikacijai priklausomai kas yra lengviau realizuoti, nelauzant sau pernelyg galvos. Visa sia duomenu transformacija aisku tures buti atliekama keitiklio pries jam issiunciant tuos duomenis per com porta.

  1. Variantas Naudojam unikalius START ir STOP, bei identifikacinius LOW HIGH.
    Kitas variantas yra vis delto panaudoti pries tai parodyta varianta kur yra panaudojamos 2 bitu reiksmes High ir Low baitu identifikacijoms. O kiti 2 galimos reiskmes (turim laisvus 4 bitus per 2 baitus informacijos) nurodo ar tai STOP ar START. Tai yra:
    0x00(START), 0x03(STOP), o duomenys 0bXXXXXX10 - high baitui ir 0bXXXXXX01 low baitui.
    Tokiu atveju žinosi ar gavai tikrai pilna duomenu porcija ir zinosi identifikacinius duomenu ar tai high ar low numerius. Ir jei duomenys kazkaip bus prarasti tarkime gautum START HIGH LOW HIGH LOW STOP arba START HIGH HIGH LOW STOP arba HIGH LOW STOP, visada galesi interpretuoti rezultatus juos atmesdamas arba galbut tolimesniuose zingsniuose galbut interpoliuodamas.

  2. Variantas naudojam HIGH LOW idenfitifkacijas duomenu masyvui, bei i STOP ir START baitus papildomai idedam informacija tarp kokiu duomenu jie yra.
    Tai yra siunciami duomenys atrodytu jei viskas gerai taip START HIGH LOW STOP, taciau START baitas savo laisvuose 6 bituose turetu tuos pacius duomenis kaip ir HIGH baitas savo 6 bituose, o STOP ta pati ka ir LOW, tokiu atveju tu galetum patikrinti ar tikrai yra gauti duomenys patikimi nes jei tarkime START 6 bitu reiksmes skirsis nuo HIGH 6 bitu duomenu reiksmes reiskias buvo perduoti netikslus duomenys ir jie arba pasimete kazkur arba siaip atsitiko kazkas negerai.
    Ta pati gali isplesti ir toliau tarp START ir STOP bitu imesdamas daugiau duomenu HIGH LOW HIGH LOW .. etc, ir START + STOP = 12 bituose uzkoduoti tam tikra informacija kuri leistu mums spresti ar perduotuose duomenyse visi duomeyns yra tikslus kazkas panasaus i primityvu cheka - paprasciausiu atveju tiesiog tarkime nurodysi kiek yra vienetuku, kiek HIGH turetu buti ir dar kazka...


Programos kodas keityklyje kuris atliktu situos pakeitimus nelabai zinau bet ideja butu panasi kazkur i tokia
A = nuskaitytas LOW baitas
B = nuskaitytas HIGH baitas %% Maksimali kiek supratau reiksme galima yra 0x0F %%
MASK_HIGH = 0b11111110
MASK_LOW = 0b11111101

C = A AND 0b11000000 %% nuskaitome virsutinius A bitus kuriuos veliau perkelsime i B %%
A = A 4 %% perstumiame A per 2 bitus i kaire %%
A = A AND MASK_LOW %% Uzrasome koks cia bus siuncimas baitas LOW ar HIGH %%
B = (B
8) OR (C/64) %% perstumiame B per 4 bitus i kaire, o C perstumiame per 6 bitus i desine %%
B = B AND MASK_HIGH

Savaime suprantama visus situos bitu perstumimus tures atlikti keitiklis. Ir koki varianta noresi naudoti, jau nuo taves priklauso. Greiciausiai yra daugiau variantu bet kadangi as tuo neuzsiimu sitie pirmi yra sove man i galva.

Bet manau tolimesniam pamastymui daviau ideju.

  • 20 Geg '12

@windows rašė:
...

Ačiū už išsakytas idėjas.
Gal būt nederėtų jų kritikuoti, bet deja privalau tai padaryti. Pirmiausiai paaiškinsiu, kodėl negaliu naudoti variante Nr.1 išsakytų sprendimų, o jei negaliu naudoti Var. Nr.1 siūlomų sprendimų, akivaizdu, kad antrasis tai pat atpuola, nes jis yra pirmojo pasiūlymo modifikacija.
Kadangi pas mane keitiklis 12bit, tai tuo atveju, kai keitiklis išduoda skaičių, tarkime 4095 = 0x0FFF. Paaiškėja kad LoB gali įgyti visas vertes nuo 0x00 iki 0xFF, o atveju kai sk.: 4095, LoB skaičius kaip tik būna 0xFF, taigi jame nebėra vietos jūsų siūlomai korekcijai.

Pas mane ADC keitiklis turi 4 aktyvius kanalus. Pamatavusio kanalo numerį nusako du HiB skaičiaus vyriausių skilčių bitai. Žemiau HiB žodžio formatas. K-kanalo numeris, V - pamatuota vertė. Tuo atveju, kai skaičius 4095, vertė būna 0x0F.

| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| K | K | 0 | 0 | V | V | V | V |
```Priklausomai nuo 4 kanalų **HiB**, kai keitiklyje pamatuota vertė 4095, gali būti:

K - 0, ---> 0x0F
K - 1, ---> 0x4F
K - 2, ---> 0x8F
k - 3, ---> 0xCF
```
Čia aš kaltas, kad iškart nepasakiau to reikalo su kanalais. Kaip matome, tenka lipti į kitą baitą (STOP/START simboliai).
Idėja, kad STOP/START baite įrašyti vienetukų skaičių man patiko. Mėginsiu įgivendinti.

  • 20 Geg '12

Tai kaip suprantu tu i com porta perduoti vis delto ne 12 bitu informacijos esancios dviejuose baituose bet 14 bitu informacijos (12 bitu vertei + 2 bitai kanalo numeris)

Tokiu atveju mes turime aisku laisvus ne 4 o tik 2 bitus su kuriais galime pazaisti. Jeigu paziureti i 1. mano pasiulyta varianta, tai tiesiog tavo siunciami 14 bitu informacijos bus isskyrstyti per du baitus ( tai yra vienas baitas tures 7 bitus informacijos ir kitas baitas (high) irgi 7), o like po 1 bita bus panaudojami nusakyti ar cia yra HIGH ar LOW.

tai yra

K K 0 0 V V V V      V V V V V V V V  taptu
1 K K V V V V V      0 V V V V V V V

tai yra baite vyriausias bitas nurodys koks cia yra baitas (ar HIGH baitas (1) su kanalo numeriu ir papildomi bitu is LOW baito) - HIGH tures viriausiaji bita visada 1, o LOW tures vyriausiaji bita visada 0.

Aisku vis tiek atsirastu problema nustatant eiliskuma, tai yra mes nezinosime kada is tikru atejo HIGH o kada LOW tai yra HIGH,LOW,HIGH,LOW - tai yra negalime nustatyti ar mums reiketu tokiu atveju nuskaityti HIGH + LOW, ar galbut LOW + HIGH. Problema ispresti galima butu Vietoj HIGH ir LOW tuose bituose koduoti START STOP su vel 14 bituose esancia kita informacija apie tarp situ START STOP siunciamu duomenu kazkoki ivertinima. Tiesiog as nelabai sinau kaip ten tas tavo com portas tuos duomenis siuncia ir tu juos nuskaitai visada paeiliui, tai yra jei keitiklis issiunte 0, 1, 2, 3, 4, 5 baitus tau ir gausi 0, 1, 2, 3, 4, 5 su pythonu, o ne tarkime 0, 5, 1, 2, 3, 4

Taciau jeigu tu i kompiuteri per com porta vis delto siunti 12 bitu naudingos informacijos, tokiu atveju mano pasiulyti variantai galioja. Tiesiog tu nesupratai kad as ta 12 bitu informacija po lygiai padalinu dviem baitams. Tai yra vienas baitas gauna 6 bitus ir kitas 6 bitus informacijos, o like 2 bitai kiekvienam baite yra identifikaciniai.

Taciau as is tavo pythono pavyzdzio matau kad tu vis delto siunti tiktais 12 bitu naudingos informacijos ir like 4 bitai (d[1] & 0xf) yra isvis net nenaudojami.

Valdiklis 4 registruose tau pateikia
7 6 5 4 3 2 1 0     7 6 5 4 3 2 1 0
0 0 0 0 V V V V     V V V V V V V V  - 1 kanalas
0 1 0 0 V V V V     V V V V V V V V  - 2 kanalas
1 0 0 0 V V V V     V V V V V V V V  - 3 kanalas
1 1 0 0 V V V V     V V V V V V V V  - 4 kanalas

?


Taciau pakolkas savo pythono kode kanalo duomenu nenaudoji.

?

  • 20 Geg '12
K K 0 0 V V V V      V V V V V V V V  taptu
X K K V V V V V      X V V V V V V V

kur X galetu koduoti tarkim 
Jei siunciami duomenys (HIGH ir LOW) tai X = 0 visada
Jeigu siunciame START arba STOP tai X = 1 visada
START - 1 0 L L L L L L
STOP - 1 1 L L L L L L
Cia jau START ir STOP bus visada galima atskirti nuo normaliu duomenu nes pas juos vyriausias bitas yra visada 1, o like duomenis pvz 7 bitas START bus visada 0, o STOP atveju visada 0, o like L L L L L L gales koduoti kazkokia naudinga patikrinimui skirta informacija, pvz kelintas cia eina paketas, kad galetum gauti/patikrinti paketus pagal eiliskuma, bei dar kokia nors informacija...
  • 20 Geg '12

@windows rašė:
...

Išties labai dėkui už išsakytas mintis. Tikrai davėte peno apmąstymams.

Pateiktame PYTHON kode neįdėjau mechanizmo, kuris duomenis išskirsto priklausomai nuo kanalo ir apie tokią būtinybę neužsiminiau. Čia jau mano kaltė. Dabar mėginsiu padirbėti prie optimalaus kodavimo mechanizmo. Optimalus - kaip įmanoma greitesnis ir kaip įmanoma patikimesnis užkodavimo / iškodavimo požiūriu.

@windows rašė:
Tiesiog as nelabai sinau kaip ten tas tavo com portas tuos duomenis siuncia ir tu juos nuskaitai visada paeiliui, tai yra jei keitiklis issiunte 0, 1, 2, 3, 4, 5 baitus tau ir gausi 0, 1, 2, 3, 4, 5 su pythonu, o ne tarkime 0, 5, 1, 2, 3, 4

Keitiklis yra PIC mikrovaldiklio sudedamoji dalis, o MV per UART'ą (universal asynchronus receiver/transmiter) siunčia paeiliui pradėdamas LSB (least significant bit). Pythono pyserial biblioteka, grubiai tariant, identiška "HyperTerminal" veikimui. Kiek atlikau testų, tai labiausiai tikėtina, kad priėmimo buferis yra FIFO tipo. Pagal išsiųstas/priimtas vertes tikrinant, verta kalbėti apie atvejį 0, 1, 2, 3, 4, 5, 6, 7.

Prie viso šito aptarto reikalo (2 bitai kanalams + 12 bit ADC vertei) programoje reikės įkoduoti dar tokį reikalą, kaip atpažinimą kuris Mikrovaldiklis siunčia. Iš esmės sistema tokia: prie PC prikabintas tinklo koordinatorius, o aplink jį išsibarstę ADC verčių siuntėjai, turintys po 4 kanalus. ADC vertės siuntėją vadinsiu nutolusiu duomenų rinkimo moduliu, arba tiesiog moduliu. Taigi modulis (jų bus max 15) bevieliu būdu koordinatoriui pasiunčia vieno iš savo aktyvių kanalų ADC vertę. Koordinatorius priima ir nedelsiant perduoda kompiuteriui, prie tos (2 bitai kanalams + 12 bit ADC vertė) vertės prikabindamas modulio MAC. Modulio MAC yra 16 bit ilgio. Šitoje vietoje darbo imasi python pyserial biblioteka. Ji nuskaito per COM portą gautą vertę (kaip matome, turime jau 4 B info: 2B naudingųjų duomenų + 2B MAC) ir perduoda tolimesnei identifikacijai ir apdorojimui. Tolimesnė programa identifikuoja iš kurio modulio ir kurio modulio kanalo atėjo vertė ir ją atvaizduoja pasirinktame grafike.

Šiuo metu, dėl jūsų pateiktų patarimų pasistūmėjau į priekį su kodavimo ir teisingu iššifravimu. Dabar mastau mechanizmą, kuris sugebėtų visą laiką skirtingas atsiunčiamas vertes vaizduoti užduotuose grafikuose.

Atsakyti