Canberry

Posted: 2016-04-18 in Darbeliai
Žymos:, , ,

Canberry: CAN bus, Raspberry Pi, Linux | Darau, blėKadangi po truputuką kurpiu savo mistinį CAN magistralės projektą, tai po truputuką pradėjau artėti ir prie to galo, kuris viską kaip ir valdys (ar, tiksliau, konfigūruos ir stebės). Tas galas, be abejo, kažkuris tai Raspberry Pi kompiuteriukas. Kadangi „RS Components“ atstovai man padovanojo trečiąją Avietę, tai pagalvojau, kad arba ją, arba kurį nors kitą daiktą panaudosiu būtent šiam poreikiui patenkinti.

O kaip dabar Raspberry Pi prijungti prie CAN tinklo? Jou. Geras klausimas, į kurį aš jau turu atsakymą sau — Canberry. Tiesa, aš užsisakiau neizoliuotą versiją, bo pigesnė, bet ir šiaip galvos dėl to per daug nesuku. Tai dabar tą daiktą pabandysime ir užkurti.

Pirmiausia tai apie pačią plokštę:

Canberry plokštė Raspberry Pi | Darau, blė

Tai — „Industrial Berry“ sukurtas Avietės skydelis su SPI-CAN konverteriu MCP2515 ir CAN signalo generatoriumi MCP2551. Plokštėje taip pat dar yra DS3231 realaus laiko laikrodukas (tas geresnis) prijungtas per I²C ir lizdas baterijai laiko išsaugojimui. Du viename, trumpai tariant. Labai džiugu.

Canberry plokštė Raspberry Pi | Darau, blė

Visi komponentai iš apatinės pusės. Viršujė tik terminalas:

Canberry plokštė Raspberry Pi | Darau, blė

Deja, prie trečiosios Avietės su jos dėžute tiko nelabai, teko prarankioti gabaliukų (o tam ši dėžutė puikiai tinka):

Canberry plokštė Raspberry Pi | Darau, blė

Dabar yra keli variantai, kaip reikalą užkurti. Vienas — susikonfigūruoti branduolį su atitinkamu CAN moduliu beigi pasidaryti laikroduko konfigūraciją. Antras — parsitįsti jau paruoštą Raspbian Jessie kopiją iš „Industrial Berry“. Kadangi laiką švaistyti turiu kur linksmiau, tai nusprendžiau naudotis antruoju variantu. Kas toliau?

Parsitįsiau atvaizdėlį, sukišau kortelėn. Tiksliau, paleidau kištis, o tuo tarpu įsijungiau lituoklį. Ant šitos plokštės yra SMD trumpiklis, kuris reikalingas galutiniam CAN mazgui, užtrumpina 120 Ω rezistoriuką:

Canberry paviršinis SMD trumpiklis CAN magistralės galutiniam mazgui | Darau, blė

Užkrėčiau biškį lydmetalio, vis tiek Avietė mano tinklo dizaine bus ant galo:

Jau užlituotas Canberry paviršinis SMD trumpiklis CAN magistralės galutiniam mazgui | Darau, blė

Tiunintas Raspbianas tuo tarpu susikišo į korčikę. Pasileidau, atlikau visus pradinius derinimus, einu ieškoti toliau.

Naminiame kataloge yra can-start.sh skriptukas. Jame viskas užkomentuota (nes branduolio modulis jau paruoštas) ir esminė likus tik viena eilutė:

ip link set can0 up type can bitrate 1000000

Čia, manau, viskas aišku — paleidžiamas can0 tinklo interfeisas su nurodyta CAN sparta. Kadangi aš naudoju 10 kbps, tai porą nuliukų nutrinu ir paleidžiu.

O toliau yra toks smagumas, kad CAN įrenginys atvaizduojamas kaip tinklo sąsaja:

~ $ ifconfig 
can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 
 UP RUNNING NOARP MTU:16 Metric:1
 RX packets:0 errors:0 dropped:0 overruns:0 frame:0
 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:10 
 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

Kažkuris elektrodas, regis, GPIO 22, dar prikabintas ir kaip CAN pertraukimas (kai žinelė ateina), candump utėliukė tuo naudojasi.

Nagi dabar reikia išsiaiškinti, kaip su kažkokiom kitom programinėm priemonėm gauti ir siųsti CAN pranešimukus, pageidautina būtų Python, bet gali sueiti ir C — pasidaryti Python moduliuką yzy pyzy.

Pradžiai bandau prisijungti šitą daiGtą prie savo dabar turimo minimalaus CAN „tinklo“ su dviem devbordukais. Tam nuo vienos CAN plokštelės nulitavau tąjį 120 Ω rezistorių, kad galėtų būti tarpiniu mazgu tinkle:

Nulituotas 120 Ω rezistorius nuo CAN signalo konverterio | Darau, blė

Dar viena smulkmena, šita plokštė yra padaryta pagal Raspberry HAT specifikacijas, tai ji turi ir visas skylutes, kaip Raspberry Pi B+, B2 ir B3 Aviečių. Na, ir dar ten kažkokį identifikuojantį EEPROMą turėtų turėti, bet ar turi — nežinau.

Visgi paskui nusprendžiau Avietę iš dėžutės išsipakuoti. Kad plokštė nesilaikytų vien ant GPIO elektrodų, įsukau vieną varžčiuką su keliom veržlikėm:

Canberry plokštė Raspberry Pi | Darau, blė

Neturiu nailoninių kaištukų tam reikalui, tai išsisukau šitaip.

Toliau priartėjau prie tos vietos, kai reikia patikrinti, ar Avietė gali matyti CAN pranešimukus. Sujungiau viską taip, kaip reikia: vienam gale bandomasis CAN aparatas su FreeRTOS, per vidurį primityvus dviejų pranešimukų siuntikas, o antram gale — Avietė:

CAN tinklas iš trijų mazgų su Canberry ir Raspberry Pi 3 | Darau, blė

Jungiam candump ir žiūrom, kas bus.

Deja, pirmuoju bandymu nesėkmė. Pranešimukai tarp mano įrenginių skraido, o Avietė nieko nerodo 😦 Prijungiau dar ir bendrą žemę dėl visa ko — nieko. Ką gi, ne taip viskas paprasta, kaip norėtųsi, blė…

Atsisėdau nagrinėti problemų. Pirmoji buvo susijusi su tiuninto Raspbiano konfigūracija. Jiems gal ir suveikė, o man su 4.1.7 (o paskui ir su 4.1.21) kerneliu kažkaip ne viskas buvo taip, kaip pavyzdžiuose. Po paskaitymų savo /boot/config.txt failą kiek pakeičiau. O būtent eilutę:

dtoverlay=mcp2515-can0-overlay,oscillator=16000000,interrupt=22

pakeičiau cielomis trimis:

dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=22
dtoverlay=spi-bcm2835-overlay
dtoverlay=spi-dma-overlay

Visaip landžiodamas ir knaisiodamasis netyčiukais aptikau vieną dalyką: ogi nežinau, koks visgi tiksliai yra mano CAN magistralės greitis. Taip, aš nusistatęs kažkur tai prescalerį, pakopijuotą iš Standard Peripherals pavyzdukų… bet pasižiūrėjau, kad neaišku, kokie parinkti SJW, BS1 ir BS2 vienetai.

Kas čia per keiksmažodžiai? Nagi, šiaip iš pirmo žvilgsnio atrodo velniškai sudėtingai, bet aš padariau šį darbą už jumis, tai tik skaitykit ir kramtykit.

Kad CAN magistrale nutekėtų vienas bitukas, laidais nuskrenda krūvelė impulsų. Jų gali būti nuo varganų 3 iki cielų 28. Na, čia ribiniai atvejai, paprastai būna 8, 10 ar 16 — bent jau tokius rekomenduoja visokios gudrios lentelės. Taigi, sakykim, kad pas mus yra 8 pirstelėjimai vienam bitukui. Jeigu duomenų perdavimo greitis 1 MBps, tai CAN laidukai dirba 8 MHz dažniu. Aišku?

Tikiuosi, kad aišku. Nes čia ateina įdomioji dalis. Kad gautumėm 8 MHz CAN laidukų dažnį, reikia paskaičiuoti prescalerį, kuris tuos 8 MHz mums padarys nuo kažkokio tai sisteminio laikroduko. O koks jis yra?

STM32F10x procesoriukų atveju tai yra sisteminė magistralė APB1. Konkrečiai mano STM32F103 procesoriuko atveju ji dirba ant pusės procesoriaus dažnio. T.y. procesoriaus branduolys sukasi ant 72 MHz, o APB1 — ant 36 MHz.

Norim 1 MBps, reikia 8 MHz nešančiojo dažnio. Koks prescaleris? 36/8 = 4,5. Šūds, prescaleriai gali būti tik sveiko skaičiaus. O jei bitukui pernešti padarysim 9 pirstelėjimus? Tai valio, 36/9 = 4.

Aha, o dabar problema — pas mane irgi 9 pirstelėjimai, bet prescaleriai yra 6 pagrindo. Todėl pas mane vietoj 10000 kbps (prescaleris 600) gaunasi nei šioks nei toks greitis: 6666 bps. Dėl to Canberry su mano mikrovaldikliais ir nesusišnekėjo. Nustačiau šitą greitį ant savo Avietės:

~ $ ifconfig can0 down
~ $ ip link set can0 up type can bitrate 6666

Ir viskas suveikė! Siunčiu pranešimuką iš Avietės:

~ $ cansend can0 123#DEADBEEF

O mano mikrovaldiklis išspjauna į USART1 išskerstą CAN pranešimuką:

Received CAN2B message:
 ID: 00000123
 IDE: 00
 RTR: 00
 DLC: 04
 Data: DE AD BE EF 
 FMI: 00

Va taip va, blė!

Dabar dar truputuką apie tuos prescalerius ir kitus reikalus. Štai diagrama iš legendinio RM0008 dokumento:

CAN bit timing STM32F10x | Darau, blė

Va ten viršuje yra laiko diagrama vienam bitukui koduoti. „Sample point“ yra ta vieta, ties kuria bitukas nuskaitomas ir įvertinamas ar jis vienetukas, ar nuliukas. Visas šitas „Nominal bit time“ užima kažkiek tai laiko kvantų (pirstelėjimų), tq. „Nominal bit time“ naudojant Standard Peripherals konfigūruojamas šitaip:

CAN_InitTypeDef  can_init;
...
can_init.CAN_SJW = CAN_SJW_1tq;
can_init.CAN_BS1 = CAN_BS1_3tq;
can_init.CAN_BS2 = CAN_BS2_5tq;

SJW dalis yra Synchronization Jump Width — pirmas pirstelėjimas. Jis dažniausiai yra 1 tq pločio. Toliau eina BS1 (bit segment), jam duodama nuo 1 iki 16 tq. Paskutinioji dalis — BS2, nuo 1 iki 8 tq.

Taigi pas mane vienas bitukas padarytas iš 9 kvantų, o prescaleris 600. Su aukščiau aprašytais dažniais gaunasi 6666 bps… Bandysiu perdaryti šitą reikalą, kad būtų „tikri“ 10 kbps.

Persiskaičiavau, persidariau. Štai ir Canberry įrenginio statistika, žinutės tik skraido ant tų 10 kbps:

~ $ ip -d -s link show can0
3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can state ERROR-ACTIVE restart-ms 0 
	  bitrate 10000 sample-point 0.875 
	  tq 6250 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
	  mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
	  clock 8000000
	  re-started bus-errors arbit-lost error-warn error-pass bus-off
	  0          0          0          0          0          0         
    RX: bytes  packets  errors  dropped overrun mcast   
    175        35       0       1       0       0      
    TX: bytes  packets  errors  dropped carrier collsns 
    37         23       0       0       0       0

Žiauriai palengvėjo gyvenimas testavimosi prasme. Nes iki šiol tai buvo taip: vienas įrenginukas bando įgyvendinti logiką, o kitam vis sukompiliuoju firmwarę su keliom CAN žinutėm, kad susimuliuotų mano norimą situaciją. Lėtas ir nepatogus procesas. O dabar galiu siuntinėti žinutes iš komandinės eilutės ir prisidaryti krūveles shell skriptukų testavimui. Tam yra komandos cansend ir candump.

Sakykim, noriu nusiųsti žinelę įrenginiui, kad jis man atgal atsiųstų savo serijinį numerį. Šast:

~ $ cansend can0 01000000#R

Čia pirma dalis yra ExtId (ID A + ID B), o R — RTR bitukas, atseit, Request Frame. Užklausa. O candump man parodo visas — tiek išsiųstas, tiek gautas žinutes:

~ $ candump can0
  can0  01000000   [0]  remote request
  can0  01000000   [6]  48 FF 6A 06 01 01

Va, įrenginys pasipasakojo apie save: pirmi keturi duomenukai yra jo šešioliktainis serijinis numeris Little Endian formatu 0x066AFF48, toliau įrenginio tipas 0x01 ir taip pat jam logiškai priskirtas „adresas“ 0x01. Šita logika čia mano saviems poreikiams sugalvota.

Taip gražiai Linuxe galime turkštis su CAN. Yra toks CAN draiverių rinkinys Linuxui, vadinamas SocketCAN, ten viskas labai gražiai sugalvota, bent jau mano nuomone. Kadangi man reikės CAN pasiekti iš Python kodo, tai greitai pasidomėjęs radau ir python-can. Ši biblioteka veikia dviem būdais, vienas iš jų yra per minėtąjį SocketCAN, pats efektyviausias ir greičiausiu keliu iki Linux branduolio. Susiinstaliavau python-can:

~ $ sudo pip3 install python-can

Tada išsikepiau tokį greituką, candump analogą:

import can

can_interface = 'can0'
bus = can.interface.Bus(can_interface, bustype='socketcan_native')
while 1:
	message = bus.recv(1.0)
	if message is not None:
		print(message)

Išsaugojau, paleidau, žinutes rodo:

~ $ python3 read-can.py 
1460488707.050592    01000000    110    0
1460488707.102897    01000000    010    6    48 ff 6a 06 01 00
1460488868.652569    01040000    010    5    48 ff 6a 06 01
1460488879.215949    01000000    110    0
1460488879.267428    01000000    010    6    48 ff 6a 06 01 01

Na va, kaip viskas gražu ir paprasta, kai prescaleriai teisingai sureguliuoti, blė 😀 Grynas malonums.

Komentarai
  1. kamiccolo1 parašė:

    Teensy 3.1, berods, CAN’ui kojas turi. Perpus pigiau (~19USD)

    • Darau, Blė parašė:

      Na, palaukit, gerbiamasai. Jūs kažką ne taip supratote, arba į mano egzistencinio nerimo kupinus klyksmus neįsiskaitėte. Tokių Teensių pas mane pilnas stalčius — ir po $2. Juos aš ir jungiu į tinklą. Bet man reikia ir CAN „serverio“ su Linuxu, ant kurio kažką būtų galima pakurt, kokį nors frontendą su blizgučiais ir kaspinėliais.

      CAN mikruškės tai iš viso centus kainuoja, bet aš tingiu gaišti laiką ir pasiėmiau gatavą bei gerą produktą. Dar ir atrodo gražiai, kur kas geriau nei koks PiCan 😀

    • Darau, Blė parašė:

      Ai beje, €24 / 2 < $19.

Parašykite komentarą

Įveskite savo duomenis žemiau arba prisijunkite per socialinį tinklą:

WordPress.com Logo

Jūs komentuojate naudodamiesi savo WordPress.com paskyra. Atsijungti /  Pakeisti )

Facebook photo

Jūs komentuojate naudodamiesi savo Facebook paskyra. Atsijungti /  Pakeisti )

Connecting to %s

Brukalų kiekiui sumažinti šis tinklalapis naudoja Akismet. Sužinokite, kaip apdorojami Jūsų komentarų duomenys.