Ubuntu16.04でホスト名を変更した時の手順メモ。 1. /etc/hostnameの編集 /etc/hostnameに変更したいホスト名をエディタ等で書く $ sudo vim /etc/hostname 2. /etc/hostsの編集 /etc/hostsで、現在のホスト名が書かれている箇所を変更したいホスト名に修正する $ sudo vim /etc/hosts 3. 再起動 rebootする $ sudo reboot 再ログイン後、ホスト名が変わっている
======= 1. 背景 ======= (1)SOEM 1.3.0の Windowsバージョン simple_test.cは、とりあえず デジタルIOスレーブでLEDがピカピカが光ってキレイでした。 (2)ところが、Linuxバージョンのsimple_test.cでは、この 「キレイ」が発生しません。 ======== 2. 対応 ======== 2つのsimple_test.cを比較したら、"IOmap[0]++" が見あたらな かった。 また Linuxの方は、コールバック関数は使っていない(様子) ======== 3. 改良 ======== (1) 改良後 void ecatcheck( void *ptr ) { int slave; while(1) { IOmap[0]++; // ← この1行を加えるだけ if( inOP && ((wkc < expectedWKC) || ec_group[currentgroup].docheckstate)) ============= 4. コンパイル ============= >cd SOEM-1.3.1 >source ./setup.sh linux >make all (詳しいことは、SOEM-1.3.1\READMEに記載がある) ============= 5. 結果 ============= >cd SOEM-1.3.1/test/linux/simple_test >sudo ./simple_test enx001d73e6ec5e(これはslaveinfoから取ってくるNICの情報) デジタルIOスレーブでLEDがピカピカが光ってキレイになりました。
Tera Termでアクセス → 設定 → ウィンドウ →カラー → 背景 → 反転 とすると、emacsの文字が見えるようになる
(Step.1) http://download.rt-labs.com/ethercat/slaveeditor/ から、Windows(64bit)をダウンロード (Step.2)slaveeditor-win32.win32.x86_64.zipをダウンロードしたら、 適当に展開(ここでは、C:\Users\yrl-user\Downloads\slaveeditor-win32.win32.x86_64とした) (Step.3)eclipsec.exeすると、"EtherCAT Slave Editor"が立ち上がる (Step.4)後は、"http://download.rt-labs.com/ethercat/slaveeditor/ethercat_slaveeditor_howto.pdf"の 解説書通りのことをやる
http://download.cnet.com/Synergy/3001-2072_4-10714570.htmlから、ダウンロードできる。
バイナリは、synergy-1.4.18-r2250-Windows-x86.msi
/* g++ -g struct.cpp -o struct */ #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct bus_od{ int a; int func(){ int b = a + 1; return b; }; } BUS_OD; int main() { BUS_OD *new_p_bus_od = (BUS_OD *)malloc(sizeof(BUS_OD)); new_p_bus_od->a = 3; int c = new_p_bus_od->func(); printf("c=%d\n",c); return 0; }
/* ライブラリして使用するので gcc -g -c -o tools.o tools.cpp でコンパイルして下さい。 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "c-anemone2.h" const int hhmm_size = sizeof("HH:MM"); // "HH:MM"の文字列確保サイズ == 6 double div_by_zero(double a, double b) { if (b == 0){ return 0.0; } return a / b; }; // 実数値(6.2)を時刻表記("06:12")に変換する void real_to_HHMM(double a, char* str) { // char* strの実体は、メインで5バイト以上確保していなかったら // 動作は保証しない int HH = (int)a; int MM = (int)((a - (int)a) * 60); sprintf(str, "%02d:%02d",HH,MM); // この"%02d"で、1→01と表記してくれる } // 時刻表記("06:12")を実数値(6.2)に変換する double HHMM_to_real(char* str) { char s2[] = ":"; char *tok; char s1[hhmm_size]; memcpy(s1, str, hhmm_size); tok = strtok(s1, s2); double a = atof(tok); tok = strtok(NULL, s2); // 文字列 strがヌル終端されていない場合、tok もヌル終端されてない状態になる。 double b = atof(tok); // atofは、ヌル終端ありきの動作。 return (a + b / 60.0 ); }
「light ethercat slave」のカーネルモードをラズパイ3(ubuntu 16.04)で作ろうとしていたのですが、これが上手くいきませんでした(makeに失敗する)。
ようやく動くようになったので、以下やり方を残しておきます。
(Step.1) まず、"http://eetimes.jp/ee/articles/1506/22/news017_5.html"に記載されている通りのことをします。
が、このままではsudo makeに失敗します。("4.1.19-7v"がない、とか言われます)
>sudo apt-get install raspberrypi-kernel-headers >sudo apt-get update >sudo apt-cache search linux-headers >sudo rpi-update f406502f5628d32e6ca5dadac34ff7ca59f8e27f >sudo apt-get install linux-headers-4.1.19-v7+
てなことをやったのですが、改善ありませんでした。
Step.2) https://tiryoh.com/blog/archives/1086を参考に環境作ってみた
>mkdir -p ~/tmp >cd ~/tmp >wget http://phil.lavin.me.uk/downloads/linux-headers-rpi/linux-headers-4.1.19-v7%2B_4.1.19-v7%2B-2_armhf.deb >sudo apt install dkms >sudo apt install gcc-4.7 >sudo apt-get install -f >sudo dpkg -i linux-headers-4.1.19-v7+_4.1.19-v7+-2_armhf.deb >sudo chmod -R o+r /usr/src/linux-headers-4.1.19-v7+/* >sudo chmod -R g+r /usr/src/linux-headers-4.1.19-v7+/*
(Step.3) sudo make 再び
>sudo make
をすると、kernel/ecslave.ko が完成しました。
>sudo apt-get install openssh-server /etc/ssh/sshd_config の portの番号を替える。 >sudo service ssh restart
SOES v1.0.0
|
ここを見よtutorial.txt
SOESはC言語で記載されたEtherCATスレーブのスタックで、学習と使用の両方を目的としたものです。 このソースを勉強することで、どのようにEtherCATスレーブが動いているのが分かるででしょう。
バージョン1.0.01の概要は以下の通りです。
SOES Simple Open EtherCAT Slave
Copyright (C) 2007-2013 Arthur Ketels
Copyright (C) 2012-2013 rt-labs
SOES is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation.
SOES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
As a special exception, if other files instantiate templates or use macros or inline functions from this file, or you compile this file and link it with other works to produce a work based on this file, this file does not by itself cause the resulting work to be covered by the GNU General Public License. However the source code for this file must still be made available in accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License.
The EtherCAT Technology, the trade name and logo "EtherCAT" are the intellectual property of, and protected by Beckhoff Automation GmbH.
SOES v1.0.0
|
SOESは、マイクロコントローラユーザアプリケーションに、以下のEtherCATフィールドバス通信環境を提供するライブラリです
メールボックスとプロトコルのサポートは、典型的なサンプルであり、あなたがEtherCATのアプリケーションレイヤをコントロールする為のスレーブスタックが必要となる時に役に立ちます。これらのアプリケーションで使用されるPDIは、SPIかいくつかのマイクロコントローラのインターフェースです。
以下は、どのようにSOESを立ち上げ起動させるかの幾つかの基本的なサンプルとなり、かつ、あなたがスレーブを設定するときの簡単なサンプルにもなります。全てのコードはアプリケーションの為のローカル変数またはグローバル変数で記述されています。必要なら修正や改良しても良いです。
ターゲットアプリケーションは以下の通りです
SOESの上位での、翻訳または実装(?)
最初にスタートアップコードを見て下さい。このサンプルは、どのようにメイン関数を追加するかを示しており、スタートアップコードによって呼ばれることになります。このサンプルでは、mainの唯一の目的は、2つの新しいタスクを生み出すことです。一つはSOESを実行することで、もうひとつはエラーLEDをコントロールすることです。いくつかのESCは、エラーLEDの為のイベント用にRUN LED用のPINを提供しています。それがなければ、スレーブのマイクロコントローラから、それらをコントロールできます。以下SOESタスクに注力します。
int main (void) { rprintp ("SOES (Simple Open EtherCAT Slave)\nsoes test\n");
SOESの機能は、EtherCATスレーブデバイスであり、3つの部分に分割することができます。「ハードウェアの初期化」「ソフトウェア」「アプリケーションの初期化ループ」です。では、「ハードウェアの初期化」から説明します。
_ task_delay (tick_from_ms (200));
_ // wait until ESC is started up
while ((ESCvar.DLstatus & 0x0001) == 0)
{
ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus,
sizeof (ESCvar.DLstatus), (void *) &ESCvar.ALevent);
ESCvar.DLstatus = etohs (ESCvar.DLstatus);
}
void soes (void *arg) { ... while ((ESCvar.DLstatus & 0x0001) == 0) { ESC_read (ESCREG_DLSTATUS, (void *) &ESCvar.DLstatus, sizeof (ESCvar.DLstatus), (void *) &ESCvar.ALevent); ESCvar.DLstatus = etohs (ESCvar.DLstatus); }
Up until the now we're using the SOES protocol stack without any application specific calls. Next up we'll look at the application Code, here named DIG_process ().
void soes (void *arg) { ... // application run loop while (1) { if((ESCvar.ALstatus & 0x0f) == ESCinit) { txpdomap = DEFAULTTXPDOMAP; rxpdomap = DEFAULTRXPDOMAP; txpdoitems = DEFAULTTXPDOITEMS; rxpdoitems = DEFAULTTXPDOITEMS; } ESC_read (ESCREG_LOCALTIME, (void *) &ESCvar.Time, sizeof (ESCvar.Time), (void *) &ESCvar.ALevent); ESCvar.Time = etohl (ESCvar.Time);
_ ESC_ALevent();
The function DIG_process is the User part of the application and could be joined by more cyclic User functions for executing other parts of the application. The example code can be split in 2 parts
To run application data through EtherCAT processdata we need to describe for the fieldbus what data we have and will read/write. For this we have 3 objects, the ESI file, SII-EEPROM and CoE Object Dictionary. The first 2 are mandatory and the third is a very convenient way of describing complex slaves.
Our strategy is to keep the ESI file and the SII-EEPROM as thin as possible to avoid duplication of data that need to be maintained. Both will hold the bare minimum of mandatory + optional data to pass CTT. Optional data will be included to tell EtherCAT that detailed information can be retrieved via CoE from the OD stored in the slave it self.
Snapshot from SII information matrix from EtherCAT communication slides.
Snapshot from ESI tree from EtherCAT communication slides.
To briefly give a hint what are describe in the ESI and SII we're listing a set of included elements marked M for mandatory and O for optional.
- Vendor (M) , Describes the identity. - Id (M), Hex, EtherCAT Vendor ID, OD 1018.01 - Name (M), NameType, Expedient vendor name - Descriptions (M), Describes the EtherCAT device(s) using elements. - Groups (M), Similar devices can be assigned to one group. - Group (M), One group groups similar devices with slightly different features - Type (M), A reference handle corresponding to the GroupType value in Description:Devices:Device:Group - Name (M), Name for this group show by a configuration tool - Devices (M), Element devices may describe one or several devices with their EtherCAT features such as SyncManagers, FMMUs and Dictionaries - Device (O), Holds all information about the device like syncmanagers and FMMU, object dictionary, data types and the PDO mapping and assign description - Device ATT: Physics (M),string, Physics at individual ports - Type (M), Device identity - Type ATT:ProductCode="#x98123467" - Type ATT:RevisionNo="#x00000001" - Name (M), Detailed name of device shown by a configuration tool (not used for identification) - GroupType (M), Reference to a group (described in element Groups) to which this device should be assigned to. Name of the handle used in element Groups:Group:Type - Fmmu (O), String to describe function, Outputs -> RxPDO, Inputs -> TxPDO , MBoxState -> FMMU is used to poll Input Mailbox - Sm (O), Description of SyncManager including start address and direction. - MBoxOut Mailbox Data Master -> Slave - MBoxIn Mailbox Data Slave -> Master - Outputs Process Data Master -> Slave - Inputs Process Data Slave -> master - Sm ATT:DefaultSize="128" , Size - Sm ATT:StartAddress="#x1000" , Start address - Sm ATT:ControlByte="#x26" , Settings , Bit [1][0] = 10, Operation mode Mailbox, 00 Buffered 3. - Sm ATT:Enable="1", Enabled - Mailbox (O), Description of available mailbox protocols - Mailbox ATT: DataLinkLayer="true", Support of Mailbox Data Link Layer is mandatory. - CoE (O), Device support CoE - CoE (O) ATT: SdoInfo="true" , SDO Information Service - CoE (O) ATT: CompleteAccess="false" , SDO complete access not supported - CoE (O) ATT: PdoUpload="true", PDO description uploaded from the slave's object dictionary and SyncManager length calculated based on the same - Dc (O), describes synchronization modes supported by the device. - OpMode (O), Definition of supported operation modes - Name (M), Internal Handle of operation mode - Desc (O(M)), description of operation mode, recommended, Free Run (no sync), SM Synchronous, DC Synchronous - AssignActive (M), Value of Latch and Sync Control registers - Eeprom (O, use is mandatory) - Data (M) Or - ByteSize (M), Byte Size of connected EEPROM device - ConfigData (M), First 7 words of EEPROM, Configuration Areas - BootStrap (O), Start address and length of mailboxes for BootStrap
So to describe the application we use CoE and Object Dictionary. The mapping between Object Dictionary and the User Application are done via local variables defined as user types. The Object Dictionary itself is stored in a matrix where all the indexes are listed. Every index then have a submatrix with its subindex.
The Object Dictionary used as example follow the CANopen DS301 ranges.
RxPDO , 0x1600 - 0x17FF TxPDO , 0x1A00 - 0x1BFF
Example, on how the the OD index are linked. Top index, SyncManagers Communication Types. In index 0 the 0x04 indicates we have 4 SyncManagers defined. Every SyncManager is assigned a type, in index 1-4, we have standard settings SM0 = 1, SM1 = 2, SM2 = 3, SM3 = 4 from ETG 1000.6, 5.6.7.4.
objectlist.h FLASHSTORE _objectlist SDOobjects[] = ... {0x1C00, OTYPE_ARRAY, 4, 0, &acName1C00[0], &SDO1C00[0]}, FLASHSTORE _objd SDO1C00[] = { {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x04, nil}, {0x01, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_01[0], 0x01, nil}, {0x02, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_02[0], 0x02, nil}, {0x03, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_03[0], 0x03, nil}, {0x04, DTYPE_UNSIGNED8, 8, ATYPE_R, &acName1C00_04[0], 0x04, nil}
SyncManagers channels 0-31 are listed in SDO1C10-SDO1C2F. If we look at SyncManager channel 2, we see.
It got one RxPDO index 0x1600 connected, and the submatrix for 0x1600 link one PDO object index 0x7000 subindex 1. The output object 0x70000108 give you the index 0x7000, subindex 1 and PDO object length 1(byte).
objectlist.h FLASHSTORE _objd SDO1C12[] = { {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x01, nil}, {0x01, DTYPE_UNSIGNED16, 16, ATYPE_R, &acNameMO[0], 0x1600, nil} }; FLASHSTORE _objd SDO1600[] = { {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x01, nil}, {0x01, DTYPE_UNSIGNED32, 32, ATYPE_R, &acNameMO[0], 0x70000108, nil} };
At PDO level we make the connection between the local application and the object dictionary. For all subindex in the PDO the last element is the address to the local variable.
objectlist.h FLASHSTORE _objd SDO7000[] = { {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x01, nil}, {0x01, DTYPE_UNSIGNED8, 8, ATYPE_RW, &acName7000_01[0], 0, &(Wb.LED)} };
Beside SyncManager to PDO mapping we also have mandatory data as
0x1000 Device Type 0x1018 Object Identity 0x10C0 SyncManager Communication Type, as we used as top index when figuring out our PDOs in the Object Dictionary.
For a complete description of the object dictionary you can get guidance by the ETG1000.6 EcatAlProtocols
A useful feature is the Asynchronous use of SDO parameters. In the example we have Parameter set holding an encoder scale value, just for show we also have a read only mirror value of the encoder scale. Parameters defined as a RW SDO parameter and can be written/read by SDO Download or Upload. In addition there is a ESC_objecthandler Hook on SDO Download where you can add additional logic, ex. we execute the mirror of the encoder scale value by assigning the encoder scale value to the mirror.
objectlist.h FLASHSTORE _objd SDO7100[] = { {0x00, DTYPE_UNSIGNED8, 8, ATYPE_R, &acNameNOE[0], 0x02, nil}, {0x01, DTYPE_UNSIGNED32, 32, ATYPE_RW, &acName7100_01[0], 0, &(encoder_scale)}, {0x02, DTYPE_UNSIGNED32, 32, ATYPE_R, &acName7100_02[0], 0, &(encoder_scale_mirror)} };
This tutorial is just one way of doing it. Enjoy and happy coding!
Andreas Karlsson, rt-labs AB, www.rt-labs.com
設定>その他の設定>表示 で以下を設定
INDEX | 色名 | R | G | B | |
---|---|---|---|---|---|
Color_0* | 黒 | Black | 0 | 0 | 0 |
Color_1 | 赤 | Red | 255 | 0 | 0 |
Color_2 | 緑(明) | Lime | 0 | 255 | 0 |
Color_3 | 黄 | Yellow | 255 | 255 | 0 |
Color_4 | 青 | Blue | 0 | 0 | 255 |
Color_5 | 赤紫 | Magenta | 255 | 0 | 255 |
Color_6 | 水 | Cyan | 0 | 255 | 255 |
Color_7* | 白 | White | 255 | 255 | 255 |
Color_8 | 灰 | Gray | 128 | 128 | 128 |
Color_9* | 赤(暗) | Maroon | 128 | 0 | 0 |
Color_10* | 緑 | Green | 0 | 128 | 0 |
Color_11* | 茶 | Olive | 128 | 128 | 0 |
Color_12* | 青(暗) | Navy | 0 | 0 | 128 |
Color_13* | 紫 | Purple | 128 | 0 | 128 |
Color_14* | 藍 | Teal | 0 | 128 | 128 |
Color_15 | 灰(明) | Silver | 192 | 192 | 192 |
[問題点]クライアント(Windows)からサーバに接続してEmacsを利用する場合、Altキーを押してもTeraTermが受け取ってしまい接続先のEmacsにMetaキーが渡せない。
[解決法] 「設定」-「キーボード」から"Metaキー → ON"とする。
;; shellの文字化けを回避 (add-hook 'shell-mode-hook (lambda () (set-buffer-process-coding-system 'utf-8-unix 'utf-8-unix) ))
/* 大規模シミュレータを作る時に、私は、動的メモリのリスト構造体を大量に使う。 Linuxカーネルにも、この仕組みがあるらしく、ユーザプログラムでも使う方法が 解説されていた。 http://qiita.com/chromabox/items/ea9720422d7a974f6ce c言語でリストを使う時に、役に立ちそうだったので、自分のコメントを付けた ものを写させて頂いている。 なお、"list.h"は、kobore.net/list.h.htmlに置いてあり。 */ /* gcc -g list_demo.c -o list_demo */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "list.h" typedef struct _tag_datas { int number; char name[64]; list_head _list; }type_line; const char *ndata[]= { "beagle", "cupcake", "donut", "eclair", "froyo", "gingerbread", "honeycomb", "icecleam", "jellybean", "kitkat", NULL, }; // 渡されたリストのエントリが最後かどうか調べる #define list_is_entry_last(pos, head, member) \ &pos->member == (head) int main(int argc,char *argv[]) { LIST_HEAD(mylist); // mylist は リスト変数の宣言と初期化 int nums=1,i; type_line *data = NULL; type_line *dend = NULL; // Listへ要素の追加 for(i=0;ndata[i] != NULL;i++){ data = (type_line *)malloc(sizeof(type_line)); // インスタンスを生成 INIT_LIST_HEAD(&data->_list); // 先頭アドレスを指定(というか「決める」) data->number = nums; // 構造体にデータを投入 strcpy(data->name,ndata[i]); // 同上 nums++; list_add_tail(&data->_list, &mylist); // リスト末尾に追加、リスト先頭に追加する場合はlist_add()を使う } // Listを順にたぐる list_for_each_entry(data,&mylist,_list){ // "_list"は構造体の一つ、mylistは先頭のアドレス printf("%d: %s\n",data->number,data->name); } // Listを順にたぐりつつ、探す (基本的には上記と同じ) list_for_each_entry(data,&mylist,_list){ if(strcmp(data->name,ndata[4]) == 0){ // ndata[4]と同じ文字列なら、引き出す printf("found ! %d: %s\n",data->number,data->name); break; } } // Listが最後まで来たかどうか if(list_is_entry_last(data,&mylist,_list)){ printf("not found\n"); }else{ printf("continue print\n"); // 探せたらそこから順にたどる // list_for_each_entry_continue だと今dataが示しているところの次から // list_for_each_entry_from だと今dataが示しているところになります list_for_each_entry_continue(data,&mylist,_list){ printf("%d: %s\n",data->number,data->name); } } // 後始末 list_for_each_entry_safe(data,dend,&mylist,_list){ list_del(&data->_list); free((void *)data); } return 0; }
kernel/ecat_protocols.c の中の ec_process_datagrams()