Suhtlemine mitme serial-seadmega korraga
#1
On bussi peakontroller koos oma alluvate kontrolleritega. Side @115kb, RS485, minu oma protokoll, toimib.
Probleemse alluva kontrolleri küljes on 3 sidekanalit:
- sidesiin peakontrolleriga @115kb, päringuid esitab PK kõigile seadmetele järjest ja kui mõni neist keeldub vastamast, loetakse ta ajutisel koolnuks ning võetakse ette järgmine. Tulemusena jäävad eksinu mõned väljundid juhtimata (kui on muutusi);
- tööstuslik kontrolleriplokk koos puldiga. Minu plaat istub nende kahe vahel ja vahendab päringuid nagu parasjagu vaja on. Side @9600bd, pakett 8 baiti, iga baidi vahel kohustuslik >=3ms paus. Päringud tulevad masterilt siis ja nii kui ta tahab. Alati peab vastama või tuleb oodata ca 1s (lubamatu). Master (see tööstuslik) ei kuula esimest paketti mis tuleb peale timeout'i (kui ma ei jõua talle vastata). Timeout'i korral laseb ta kõik oma 1-e seatud väljundid lõdvalt 0-i (turvakaalutlustel ?);
- tööstusliku masteri pult @9600bd (juhtme otsas), ei ole kriitiline aga sama 8-baidise paketi baitide vahele nõutakse sama pausi ca 3ms.
Päringuid esitab minu kontroller aga selleks napib aega (tänu nendele kohustulikele viidetele).
Probleem: ma ei saa kuidagi rahuldada kõigi suhtlemisevajadusi korraga. Kui vastan katkestuse kestel peakontrolleri kõigile pakettidele viisakalt, tekib ajuti master-neegriga sideprobleem ja ta seab kõik väljundid nulli. Kui aga pean sidet temaga prioriteetseks, jäävad vahele peakontrolleri paketidd ning tulemusena juhitakse ainult master-neegri väljundeid 1-3, teiste puhul jõuab kätte timeout ja küsitlev kontroller jäetakse 1-ks viskeks vahele.
Peakontrolleri kood on minu mätcitud, saan muuta (nt. teha tea vähem pirtsakaks side suhtes aga siis võib viga siirduda lihtsalt järgmise väljundi juurde). Tolle "tööstusneegri" koodi ma muuta ei saa.

Mul pole ühtegi head ideed, kuidas probleemi lahendada või kas see üldse võimalik on.
Any ideas?
Vasta
#2
Kas FIFO-ga (First In, First Out) oled tuttav? Seda võib nimetada ka ringpuhvriks, sest softis tehtud FIFO on sisult ringpuhver. Nimi reedab olemuse - välja võetakse andmed samas järjekorras, mis nad sinna sisse pandi, ehk ingliskeelne otsetõlge - esimesena sisse ja esimesena välja.

Seda võib teha näiteks kolme muutuja:
Kood:
    head: byte            //  järgmine positsioon kirjutamiseks cbuffer-is.
    tail: byte            // järgmine positsioon lugemiseks cbuffer-is
    cbuffer: array of 256 bytes    // puhvri sisu
ja järgmiste definitsioonide abil (pseudokood):
Kood:
    // Kas FIFO on tyhi?
    is_empty:
        head = tail
    // Kas FIFO on täis?
    is_full:
        tail + 1 = head

    // Lisada täht FIFO-sse. NB! FIFO ei tohi olla täis!
    push char:
        cbuffer[head] <- char
        head <- (head + 1) % sizeof(cbuffer)

    // Eemaldada täht FIFO-st. NB! FIFO ei tohi olla tühi!
    pop:
        return_value <- cbuffer[tail]
        tail <- tail + 1
        return-value

Olgu näiteks kontrolleriplokile vaja saata baite 3ms vahedega. Kas poleks katkestuses
mugav kasutada alamfunktsiooni "slow_send (char)", mis char'i paneb kuskile nurka
oma aega ootama ja pöördub kiiresti tagasi, et katkestus saaks oma asjadega edasi tegelda?
Milal see "oma aeg" tuleb, seda saab aga määrata 3ms perioodiga taimeri katkestusega.
Selline alamfunktsioon, mis selle nurgana kasutab FIFO-t ja saatmiseks taimerit,
näeks pseudokoodis välja järgmine:
Kood:
    slow_send char:
        push char
    
    timer_at_3ms_interval:
        if not is_empty then
            char <- pop
            write_uart_data_register char
            // NB! kirjutamise lõppu ei pea ootama (3ms on niigi varu).
        end if

Peakontrolleri kaudu toimetamiseks on sarnane nipp, ainult et taimeri katkestamise asemel kasutatakse kahte UART-i enda geneeeritud "andmete puhver tühi" ja/või "kõik bitid saadetud" katkestust. See on veidi keerulisem, aga mitte liiga.
Vasta
#3
Tänud!

Ma proovin lahendada probleemi hetkel ainuvõimalikuna tunduval meetodil - saade ja vastuvõtt mõlemas suunas "peaaegu" paralleelselt.
Kuna peakontroller suhtleb tunduvalt kiiremini, seadsin tema side prioriteetsesse katkestusse: toimib. Plaadi suhtlemine kontrolleri ja tema juurde kuuluva puldiga käib aeglaselt (9600 bd), sisaldab mõlemas suunas alati 8baiti ja kontrolleri alustatud päringuid ei tohi maha magada (siis pikk timeout + muu jama). Samas pean sama aeglaselt saatma päringu puldile. Aega napib...
Seepärast ootan kontrollerist baiti ja saadan peale selle saamist kohe teisest puhvrist valmis päringubaidi puldile. Kui pakett kontrollerist käes, analüüsin seda ja muudan puhvrite sisu vastavalt. Ja siis sama teises järjekorras: ootan puldi vastust ja saadan samas baite kontrollerile. Loomulikult tuleb iga baidi järel porti ümber kommuteerida (sest on vaid 1 port selle sidekanali jaoks) aga õnneks on PICil selline tore asi nagu PPS ehk peripheral pin select.
Vaatame, kas hakkab nii tööle...
Vasta
#4
Kas ma sain õigesti aru, et mikrokontrolleris on järjestikporte vähem kui kasutuses olevaid sidekanaleid ja seega lülitad ühte porti kahe kanali vahel ringi?
Vasta
#5
(10-12-2012, 09:19 PM)andrei Kirjutas: Kas ma sain õigesti aru, et mikrokontrolleris on järjestikporte vähem kui kasutuses olevaid sidekanaleid ja seega lülitad ühte porti kahe kanali vahel ringi?
Kahjuks jah. Selles projektis ei peaks portide puudus siiski muret põhjustama - on ju "lüliti" prose sees olemas.
Vasta
#6
Felch, on aeg kapist välja tulla ning tunnistada, et sulle pakub rahuldust rauast 150% välja pigistada Smile
Ma mõistan sind, ainult et sellel on reeglina point suurseeriate puhul, üksikeksemplaridel kipub asi kahjumiks kiskuma Smile
Vasta
#7
Kui palju neid järjestikporte on? Vanasti oli neid mikrokontrolleris heal juhul 1, aga ma kardan, et Sa nii vana mudelit ei kasuta Smile
Vasta
#8
(11-12-2012, 02:29 PM)andrei Kirjutas: Kui palju neid järjestikporte on? Vanasti oli neid mikrokontrolleris heal juhul 1, aga ma kardan, et Sa nii vana mudelit ei kasuta Smile
2 füüsilist porti,neist ühte saab ringi lülitada. Sellega on hetkel probleeme aga eks tuleb asja uurida.
Jah, meeldib tõesti kivist rohkem välja pigistada. Antud juhul aga pean seda tegema - plaadid juba tehtud ja puha !
Vasta
#9
(12-12-2012, 08:47 AM)felch Kirjutas: 2 füüsilist porti,neist ühte saab ringi lülitada.
Kas ma nüüd õigesti aru sain, aga äkki annab ideid.

1. Kuna tööstusliku kontrolleriploki master ei kannata timeout'e, tuleb see otse uart'i porti ühendada. Kuna seade on kahe vahel, siis teine port peab olema muxitud uart ja kõige kõrgema prioriteediga - kui on vaja suhelda, siis saab seda ka tehtud.
2. Tööstusliku masteri pult, mis ei ole kriitiline, läheb ühe muxitud uart'i külge.
3. Kuna peakontroller on Su enda kirjutatud, siis see läheb muxitud uart'i, aga protokoll tuleb ringi teha veakindlaks. Näiteks nii, et peakontroller pärast iga baidi saatmist ootab kinnitust (võib olla kas või sama bait kajana või 0x55 vms.) ja kadude korral saadab baidi pärast lühikest timeout'i uuesti. Kuna samal siinil on ka teisi seadmeid, siis tuleb alluvaga suhtlemisel talle märku anda sideseansi algusest ja lõpust.
See sideliin on muxi küljes ja võib (aga ei pea) olla kõige madalama prioriteediga.

Selleks, et näha, kas ja kui palju pakette vasakule läheb, võib sidekanalite sisendid ühendada paralleelselt mõne falling edge peale katkestust andma konfigureeritud viiguga.
Vasta
#10
Tänud ideede eest, kood toimib nüüd. Suhtlen vaheldumisi, baithaaval mõlemas suunas, porti pidevalt ringi lülitades. Pause pole enam vaja (ise) pidada sest tööstuslik kontroller sünkroniseerib oma saadetiste ja pausidega kogu sidet ise. Peakontroller räägib nagunii kiiremini ja seetõttu on tema katkestus prioriteetne.
Kõik paketid tulevad läbi ja süsteem ei lähe sünkronismusest välja mitte kuidagi.
Vasta


Alamfoorumi hüpe:


Kasutaja, kes vaatavad seda teemat: 4 külali(st)ne