Arduino => HAL componenta

Odpovědět
Uživatelský avatar
zz912
Příspěvky: 1348
Registrován: 25. 5. 2008, 7:16

12. 10. 2020, 9:41

Zdravím,

pracuji na rozchození panelu s maticí tlačítek. Ovšem, mám to umístěný v "Ostatní elektronika"

viewtopic.php?t=37308&start=45

Umístil jsem ho zde, protože jsem chtěl vyřešit nejdřív elektro zapojení a pak pokračovat dále v dalším vlákně, ale ono to všechno patří tak nějak k sobě....

V názvu vlákna je zmíněná komponenta EasyCAT, ovšem rozhodl jsem se, prozatím odložit EasyCAT a zkusit to jen na zkoušku přes Arduino a jeho integrovanou komunikaci USB/RS232.

Našel jsem si vzorový příklad od ArcEye a ten jsem si odzkoušel. Dokonce jsem si jej upravil tak, aby byl ušitý přímo na můj panel, ale chtěl bych pochopit, jak to vlastně funguje.

Už vím, že data po sériový lince tečou do /dev/ttyACM0 a že je to znakový soubor.
Bohužel, často se stává, že se ttyACM0 změní na ttyACM1, nebo ho nějaký program nemůže najít a tak je internet zaplevelený dotazy, co s tím v těchto situacích.

Ovšem mě by zajímalo, jaká je vlastně tečou informace?
Mikrokontrolér Mega2560 => RS232 => převodník RS 232/USB => USB => Driver USB => Driver Arduino => ttyACM0 => HAL komponenta(v ní funkce open) => Realtime vlákno

U klasické RS232 mohou být ještě fyzické vodiče DTR(data terminal ready) a RTS (ready to send). Je to nějak softwarově řešeno někde v řetězci viz výše?

Existuje v řetězci výše nějaký buffer? Když si posílám něco ze "Sérového monitoru"(terminál v Arduino IDE), tak se pak v arduinu nejdřív ptám, jestli je něco v bufferu, a pak si to z něj vyčtu. Je toto možné i nějak v ttyACM0 ?

Předem děkuji za odpovědi.
LinuxCNC - MESA 7i96
zz912.webnode.cz
Uživatelský avatar
zz912
Příspěvky: 1348
Registrován: 25. 5. 2008, 7:16

28. 10. 2020, 4:17

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:

Kód: Vybrat vše

Serial.begin(9600);
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:

Kód: Vybrat vše

cat /dev/ttyACM0
A v binární zápise to bude vypadat

Kód: Vybrat vše

cat /dev/ttyACM0 | xxd -b -c1
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.
LinuxCNC - MESA 7i96
zz912.webnode.cz
Uživatelský avatar
zz912
Příspěvky: 1348
Registrován: 25. 5. 2008, 7:16

7. 11. 2020, 7:57

Tak, po čase jsem měl ještě trochu času si pohrát s Arduinem a LinuxemCNC. Jak jsem psal dříve, začal jsem s protokolem od ArcEye:
https://forum.linuxcnc.org/18-computer/ ... nc?start=0
Mex mi ho v jiném vláknu pomohl rozchodit, donutilo mě to si rozšířit základy jazyka C, abych jej pochopil. Musel jsem si nastudovat co to jsou souborové deskriptory atd.

Ovšem na tomto jednoduchém protokolu mi vadilo, že tu není kontrola poslaných dat. Myslím si, že pokud si budu posílat data s kontrolou, tak bych se pak nemusel bát elektromagnetického rušení. Když mi po jakékoliv lince, sběrnici dojde nesmysl a já budu vědět, že se jedná o nesmysl, tak se nic neděje. Možnosti jsem měl dvě, buď si napsat vlastní protokol, nebo použít něco co už léta funguje a je ověřené. Tudíž jsem šáhl po ModBusu.

Základní specifikaci ModBusu lze nalézt zde:
https://modbus.org/docs/Modbus_Applicat ... V1_1b3.pdf

No a abych si ještě více ulehčili cestu, tak lze využít usermod modulu mb2hal , což je zkratka ModBus to HAL. Tento modul není nutno nijak doinstalovávat, ten už v základní instalaci LinuxuCNC je. Abychom si s ním mohly hrát, je potřeba si stáhnout jeho zdrojáky, protože u něho jsou i examply.
https://github.com/LinuxCNC/linuxcnc/tr ... mps/mb2hal
A jako klika je, že je tam example i pro Arduino.

Něco málo o tomto examplu. Je tam zdroják pro Arduino (mb2hal_example_01_arduino.ino), který využívá knihovnu Modbusino. Pokud vám hlásí, při pokusu o kompilaci, že Vám tato knihovna chybí, je potřeba si ji přesunout do stejné složky,

Kód: Vybrat vše

pi@linuxcnc:~/linuxcnc/configs/ModBus-pokusy/mb2hal/examples/mb2hal_example_01_arduino $ ls
mb2hal_example_01_arduino.ino  Modbusino.cpp  Modbusino.h
a v kódu změnit:

Kód: Vybrat vše

#include <Modbusino.h>  na  #include "Modbusino.h"
Tento kód dělá pouze to, že to co příjme, to pošle nazpátek.
Jakmile máme nahráno do Arduina můžeme si hrát s LinuxCNC.

Nastavíme pracovní adresář na umístění ini souboru pro komponentu mb2hal. V mém případě takto:

Kód: Vybrat vše

cd /home/pi/linuxcnc/configs/ModBus-pokusy/mb2hal/examples
A spustíme nejjednodušší prostředí LinuxCNC:

Kód: Vybrat vše

halrun
Nyní načteme komponentu mb2hal v konfiguraci pro ten exmple na Arduinu:

Kód: Vybrat vše

loadusr -W mb2hal config=mb2hal_example_01_arduino.ini
a v druhém shellu můžeme spustit:

Kód: Vybrat vše

halshow
A pomocí "Test HAL command:" setp mb2hal.RegOut.00 10
nastavíme na výstup hodnotu 10 a objeví se nám i na výstupu:
halshow.jpg
No sice tento example nemá žádné praktické využití, ale věřím, že po jeho nastudování a prozkoumání tudy povede cesta dál.
LinuxCNC - MESA 7i96
zz912.webnode.cz
Grad
Příspěvky: 2073
Registrován: 13. 7. 2014, 9:32

7. 11. 2020, 8:16

Pěkné, a co bude cílem?
Něco takového?
Mex
Příspěvky: 10288
Registrován: 6. 2. 2014, 10:29

7. 11. 2020, 9:56

zz912 píše: 7. 11. 2020, 7:57 ...
No sice tento example nemá žádné praktické využití, ale věřím, že po jeho nastudování a prozkoumání tudy povede cesta dál.
Dostat do ruky Modbus na obou stranách je určitě do budoucna perspektivní.
Modbus je sice stará a pomalá sběrnice, ale je šíleně rozšířená a umí ji snad skoro každé zařízení. Mnohdy jako druhou možnost vedle nějaké své primární komunikace.
Takže je to něco jako angličtina mezi lidskými jazyky - je to sice taky blbý jazyk, ale domluvíš se s ním všude.
Uživatelský avatar
zz912
Příspěvky: 1348
Registrován: 25. 5. 2008, 7:16

8. 11. 2020, 6:32

Grad píše: 7. 11. 2020, 8:16 Pěkné, a co bude cílem?
Software pro tohle:
download/file.php?id=129242

Ono by to mel byt zaklad pro jakekoliv obecne periferie, kde neni potreba rychlost. Nechci se poustet do stepgenu, koncaku atd. Na to uz je proslapana cesta od Mesy.
LinuxCNC - MESA 7i96
zz912.webnode.cz
Odpovědět

Zpět na „LinuxCNC - drive pod nazvem EMC2“