Doufám, že to tady nebude vadit, že si z toho tady udělám s vůj blog. Sice to píšu pro sebe, ale třeba by se to mohlo hodit i někomu jinému. Tento přízpěvek je opravdu typu od "lamy pro lamy".
Když jsem položil tady v tomto vláknu svůj dotaz, tak jsem myslel, že na něj nikdo nereaguje, protože se zrovna nikomu nechce odpovídat.
Jelikož, když něco tvořím, tak mi to většinou nefunguje na poprvé, tak abych mohl řešit problémy, rozhodl jsem se pro samostudium. Když jsem pak zjistil, co můj dotaz obnáší, tak jsem pochopil, že by mi musel odpovědět nějaký sadomasochysta, co neví co s časem. Moje otázka je opravdu obsáhlá.
Rozhodl jsem se, že popíšu jednu z cest, jak se dostane jedem Byte z Arduina do HAL componenty.
1. Krok - nejdřív musí v CPU mikrokontroléru ten Byte vzniknout
Tudíž napišme si jednoduchý program pro Arduino v programu Arduino IDE.
Kód: Vybrat vše
void setup() {
Serial.begin(9600, SERIAL_8N1);
// otevreni serioveho portu a nastaveni
// rychlost = 9600 bps:
// velikost zpravy 8 bitu
// N - neni kontrola parity
// 1 koncovy bit
Serial.print('Z');
// poslani znaku ASCII 'Z'
// binarni zapis 01011010
}
void loop() {
// funkce loop zde zustava, aby mohla probehnout kompilace
}
Tento program funguje tak, že po zapnutí arduina pošle znak Z po sérivé lince. Pro nás je výhodné, že každé Arduino má tlačítko Reset, kterým můžeme způsobit, že po jeho stisknutí se nám odlešle náš Byte 'Z'.
Tak a teď aby se dostal program do Arduina je potřeba připojit desku Arduino s mikrokontrolérem do PC přes USB. Nejdřív dáme program ověřit a pak ho pošleme do Arduina. Udělám teď malou odbočku s tím, jak je to s tím jazykem Wiring. Často se píše, že jazyk Wiring vychází z jazyka c++. Jednou jsem na netu našel, že někdo psal, že je to špatně, že programovací jazyk Wiring je defakto c++. Ovšem už to nerozepsal. Jak to myslel?
Pokud chceme napsat nějaký program v jazyce c++ nebo c, tak potřebujeme 2 věci. Něco v čem ho napíšeme a něco co z napsaného souboru vytvoří spustitelný soubor(zkompiluje). Ta první věc může být poznámkový blok, v GNU linuxu Mousepad, vim. Ta druhá věc je kompilátor. Pro jazyk c se jmenuje gcc a pro jazyk c++ g++. Teoreticky bychom mohli vše řešit z terminálu napsat program v programu vim, uložit ho do souboru a pak programem (kompilátorem) g++ ho zkompilovat. V praxi se ovšem používá nějaké IDE(já používám Geany), což je program který tuto činost zjednodušuje, ale dělá úplně to samé, co jsem psal výše.
U programu Arduino IDE, je to podobné, ale jsou tam rozdíly. První rozdíl je ten, že zdrojový kód, který máte uložený v souboru Byte_to_HAL.ino je modifikován.
Byte_to_HAL.ino.cpp
Kód: Vybrat vše
#include <Arduino.h>
#line 1 "/home/pi/0S01/pokusy-c/Byte_to_HAL/Byte_to_HAL.ino"
#line 1 "/home/pi/0S01/pokusy-c/Byte_to_HAL/Byte_to_HAL.ino"
void setup();
#line 12 "/home/pi/0S01/pokusy-c/Byte_to_HAL/Byte_to_HAL.ino"
void loop();
#line 1 "/home/pi/0S01/pokusy-c/Byte_to_HAL/Byte_to_HAL.ino"
void setup() {
Serial.begin(9600, SERIAL_8N1);
// otevreni serioveho portu a nastaveni
// rychlost = 9600 bps:
// velikost zpravy 8 bitu
// N - neni kontrola parity
// 1 koncovy bit
Serial.print('Z');
}
void loop() {
// funkce loop zde zustava, aby mohla probehnout kompilace
}
V tomto případě těch změn není moc, ale můžete si to zkusit i u jiných projektů. Změna, která je ale důležitá, že přibyla knihovna #include <Arduino.h>. Bez ní by to nefungovalo. Další rozdíl oproti výše popisovanému příkladu tvorby programu je změna kompilátoru. Arduino používá kompilátor avr-g++, který je určen pro mikrokontroléry AVR. Dále umí Arduino IDE poslat po sériové lince zdrojový kód do mikrokontroléru.
2. Krok - Byte 'Z' z CPU mikrokontroléru jde na sběrnici Data bus
https://cs.wikipedia.org/wiki/Datov%C3%A1_sb%C4%9Brnice . Stále jsme uvnitř mikrokontroléru. Jedná se o paralelní sběrnici(zde jsem si jistý, zda je paralelní - jen na 90%) a v případě 8-bitového mikrokontroléru se jedná o 8-sminásobnou, žílovou.
3. Krok - dále pokračuje Byte 'Z' na UART (budu se na něj dále odkazovat jako na UART v mikrokontroléru). Slovem UART jsou často myšlené dvě věci. První věc je vlastní hardware, které informaci z paralelní sběrnice převede na sběrnici sériovou. Druhou věcí, kterou si někteří lidé představí pod pojmem UART je vlastní protokol, čili způsob jak se stane z poslaného Bytu stane posílaná zpráva. Říká se, že RS232, RS422, RS485 je podskupina UARTu. Podrobnosti naleznete třeba zde:
http://www.tajned.cz/2016/09/usart-u-av ... cky-popis/ .
Co je důležité si z tohoto kroku odnést:
- sériová zpráva vznikla hardwarově (pokud jsme nepoužily softwarovou emulaci).
- programátor programu neřeší tvorbu prvního, paritního ani koncového/koncových bitů
- UART lze sice parametrizovat (velikost zprávy, rychlost komunikace, parita, 1 nebo 2 koncové bity), ale ostatní věci jsou pevně dané (například máme jen jeden start bit, začínáme logickou nulou, končíme logickou jedničkou atd.)
- UART toho umí hodně, kontrolovat paritu, vytvářet paritní bit, bufferovat, často umí i synchroní režim proto je obvod nazýván USART a jen funguje v režimu UART
4. Krok - teprve teď Byte 'Z' leze sériově ven z mikrokontroléru na piny RX TX. Jakmile Byte 'Z' v našem případě vyleze ven z pinu TX, tak pokud se poškodí, nebo ztratí, nebo ho prostě nestihneme zachytit, tak mikrokontrolér o tom neví. Nemůže to vědět, nemá žádnou zpětnou vazbu. Tohle je pro mě důležitá informace, kvůli které jsem začal se svým samostudiem a bádáním.
5. Krok - signál, který nese Byte 'Z' + počáteční, paritní a koncový bit(y) je na napěťové úrovni 5V vůči GND. Tento signál můžeme (ale nemusíme) hardwarově pomocí převodníků změnit např. na RS232, RS422, RS485. Ovšem jedná se pouze o elektrickou změnu signálu. U RS232 je to změna napěťová u RS422 se stane z nediferenciálního signálu signál diferenciální, RS485 do toho vnáší ještě možnost poloduplexní komunikace. Z tohoto kroku si odneseme, že informace signálu se nemění. Pokud do převodníku vlezl signál 00101101001 , tak z něj opět vyleze signál 00101101001 . Dále pokud se informace poškodí např. elektromagnetickým rušením, špatným kontaktem a ze signálu 00101101001 se stane 0011000, nebo 00111111100, tak sběrnici je to jedno. Nepozná to a nic s tím neudělá. (Existuje zde paritní bit, ale to by bylo na dýl, není to 100% kontrola)
6. Krok - teď se Byte 'Z' musí vrátit do druhého UARTu, který signál opět zpracuje. Samozřejmně to musíme provést elektricky kompatibilně. Nemůžeme zapojit RS232 na 12Voltech třeba přímo na piny RX TX dalšího arduina. V našem případě se omezíme na to, že budeme používat USB sběrnici. Momentálně jsme buď neustále na desce Arduina, nebo jsme se rozhodli použít převodník třeba na RS485
https://www.gme.cz/modul-sbernice-rs-485 a jsme s vodiči u PC. Ať už využijeme převodník "serial TT - USB" v arduinu nebo použijeme převodník RS485 - USB, je seriová komunikace převedena na komunikaci USB. Do kompletního studia sběrnice USB jsem se nepouštěl. Vystačíme s článkem třeba tímto
https://pcworld.cz/hardware/usb-jak-to- ... guje-15227 . Každopádně ve srovnáním s předchozími zmíněnými linkami/sběrnicemi USB hraje jinou ligu. Obsahuje interní kontrolu přenášené informace, buffery atd. Důležité je si z tohoto kroku odnést:
- v převodníku "serial TT - USB" nebo "RS485 - USB" je druhý UART (budu se na něj dále odkazovat jako na UART v převodníku)
7. Nyní náš Byte 'Z' putuje buď přes jeden nebo více USB hubů do PCI nebo PCIe sběrnice a pak do procesoru.
Tak a to je po elektronické stránce všechno. Nyní se pustíme do popisu softwarového. Pokud chceme, aby nám sériová komunikace fungovala, musí být oba UARTy nastavené stejně. Nikdy si sériová komunikace druhý konec sama "neošahá". Pokud nastavíme na každém UARTu jinou rychlost, tak se UARTy nedomluví. Začneme ze strany mikrokontroléru. Tady je to jednoduché. Využíváme projekt Arduino, který se tak nějak stará o všechno sám. Jediné co po nás chce, abychom nastavili rychlost komunikace a ještě k tomu nás většina examplů navádí na to, aby to bylo 9600 Baudů. Takže to vypadá takto:
Tímto dojde k nastavení UARTu v mikrokontroléru. Ve skutečnosti toho lze nastavit více
https://www.arduino.cc/reference/en/lan ... ial/begin/
Pokud na to půjdeme ze strany PC, tak když Arduino desku připojíme, tak se USB postará o to, aby si našlo driver k převodníku, nastavilo ho a aktivovalo ho. Že k tou došlo, ověříme:
Kód: Vybrat vše
pi@linuxcnc:~ $ lsusb -v
Bus 001 Device 005: ID 2341:0042 Arduino SA Mega 2560 R3 (CDC ACM)
Couldn't open device, some information will be missing
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 2 Communications
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x2341 Arduino SA
idProduct 0x0042 Mega 2560 R3 (CDC ACM)
bcdDevice 0.01
iManufacturer 1
iProduct 2
iSerial 220
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x003e
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xc0
Self Powered
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 1 AT-commands (v.25ter)
iInterface 0
CDC Header:
bcdCDC 10.01
CDC ACM:
bmCapabilities 0x06
sends break
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 255
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0
bInterfaceProtocol 0
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 1
Tyto informace se netýkají mikrokontroléru, ale převodníku. Abychom mohli s informacemi z převodníku nějak pracovat, tak rozhraní pro nás bude znakový soubor ttyACM0 .
https://cs.wikipedia.org/wiki/Za%C5%99% ... D_(soubor)
Odpojme, počkejme a znovu připojme Arduino desku do PC a podíváme se na nastavení UARTu+převodníku:
Kód: Vybrat vše
pi@linuxcnc:~ $ stty -F /dev/ttyACM0
speed 115200 baud; line = 0;
eof = ^A; min = 1; time = 0;
-brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke
Nyní spustíme Arduino IDE a v něm spustíme Serial Monitor a poté ho zavřeme.
Podíváme se na nastavení UARTu v převodníku znovu:
Kód: Vybrat vše
speed 9600 baud; line = 0;
eof = ^A; min = 0; time = 0;
-brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke
Vidíme, že se "opravila" rychlost komunikace z 115200 na 9600. Tohle zařídil Serial Monitor. Až budeme dělat nějaký vlastní program, tak toto budeme muset zařídit taky.
Zkusíme si ještě komunikovat s příkazem "cat". Aby nám fungoval musíme nastavit UART+převodník pro příkaz cat:
Kód: Vybrat vše
stty 9600 -F /dev/ttyACM0 raw -echo
Nyní spustíme:
A v binární zápise to bude vypadat
Mimochodem jedná se o moji první vytvořenou rouru.
https://cs.wikipedia.org/wiki/Roura_(Unix)
Pokračování příště.
Pokud bude ochotný mě někdo ze zkušenějších v něčem opravit budu rád.