vimの実際の使い方
vimを始めるうえでコマンド覚えるより大切なことかもしれない
おまけ
Arduinoで外部割込みとシリアル割り込み
・外部割込み
- Arduino の attachInterrupt() での割り込み処理
- Arduinoの概要
- 割り込みと ISR - 基礎からの IoT 入門
- Arduino入門:外部割り込み | easy labo
簡単なスケッチを
#define INT_PIN 2 void gpio_isr(){ Serial.println("warikomi"); } void setup() { Serial.begin(115200); pinMode(INT_PIN, INPUT); // 割り込みのためのピンを設定 attachInterrupt(digitalPinToInterrupt(INT_PIN), gpio_isr, FALLING); // 割り込み開始 } void loop(){ }
pinMode()で割り込みに使うピンを入力に設定
attachInterrupt() で割り込みに使うピンとコールバック関数とピンの状態がどういうときに割り込みを発生させるかを設定。
ピンは普通のピン番号と割り込みに使うピン番号は違うらしいのでdigitalPinToInterrupt() で変換
・シリアル割り込み
void serialEvent() { } という名前でやりたい処理の関数を定義します。
ただ、割り込みと言っても loop()関数が一周したあとにserialEvent() が実行されているだけなので、割り込みっぽくないです。
ArduinoとEthernetシールドを使ってTCP通信
ArduinoとEthernetシールドの互換品を使ってTCP通信をします。
今はEthernetシールド2というものがあるらしいですが、今回使用するのは1の方だと思います。(たぶん)
Ethernetシールド2の場合、使うライブラリやArduinoIDEのバージョンが変わってくるので注意してください。
ちなみに純正品はもう1も2も生産していないらしいです。
使ったシールドはこれ
ここを参考に。
- Ethernet Shield
- Arduinoリファレンス(Ethernet)
- Arduino - Ethernet
- TCP通信でPCからLED(on Arduino)の点滅を制御する
- ArduinoからLEDN41(LEDネットワークディスプレイ)を表示させてみた - テクノベインズ ブログ
- Arduino と Ethernet シールドを用いた LED 遠隔操作アプリの作成 - 基礎からの IoT 入門
- HTTP通信でArduinoを操作する(Ethernetシールド使用)
- イーサーネットシールド2 (Ethernet Shield 2)
- ブラウザからArduino Unoを制御│レーザー加工機・レーザーカッターのsmartDIYs
簡単なスケッチを。
#include <SPI.h> #include <Ethernet.h> // Enter a MAC address and IP address for your controller below. The IP address will be dependent on your local network: byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192, 168, 1, 177); // Initialize the Ethernet server library with the IP address and port you want to use (port 80 is default for HTTP): EthernetServer server(19227); EthernetClient client; char eth_recv_buf[128]; char eth_send_buf[37] = "M SD8 124 01 23 45 67 89 AB CD EF \r\n"; char eth_recv_len; char eth_send_len; void EthWrite(){ if (Serial.available()){ one_char = Serial.read(); if (one_char == 'M'){ serial_itr = 0; } serial_recv_buf[serial_itr] = one_char; if ((one_char == '\n') && (serial_itr == 35)){ client.write(serial_recv_buf, 36); } if ((++serial_itr) > 36) { serial_itr = 0; } } } void setup() { // Open serial communications and wait for port to open: Serial.begin(115200); while (!Serial) { ; } Ethernet.init(10); // Most Arduino shields Ethernet.begin(mac, ip); if (Ethernet.hardwareStatus() == EthernetNoHardware) { while (true) { delay(1); // do nothing, no point running without Ethernet hardware } } // start the server server.begin(); // listen相当 pinMode(8, OUTPUT); } char c; void loop() { // listen for incoming clients client = server.available(); // accept相当 if (client) { while (client.connected()) { if (eth_recv_len = client.available()) { digitalWrite(8, HIGH); c = client.read(eth_recv_buf, eth_recv_len); Serial.write(eth_recv_buf, eth_recv_len); } EthWrite(); digitalWrite(8, LOW); } delay(100); client.stop(); } }
Ethernet.init() はイーサネットシールドとのSPI通信につかうCSピンです。
server.available() でクライアントの接続を待ちます。
client.available() で受信したByte数を取得してそのByte数だけclient.read()で読み出します。
その他参考
- Arduino - EthernetServer
- やっと解決!Arduino Ethernet Shield2(シールド2)通信!
- Arduino イーサネットシールド2を使ってみた。
- 海外通販でArduino用Ethernetシールドを買った… - 記憶は人なり
- Arduinoを使ってWebサーバーをつくろう! | Device Plus - デバプラ
- WhiteBox
- ここも参考になるのかな?
- RXduino: クラス EthernetClient
- RXduino: クラス EthernetServer
TCPとUDPの違い
・TCP
送信したパケットは勝手に分割されて適当に結合されて受信される(データの境界保証なし)
つまり1回send() ≠1回recv()
- はてなブログ
- Socket通信でパケットを意図的に分割する: DOBON.NETプログラミング掲示板過去ログ
- ソケット通信メモ(Hishidama's TCP/UDP Socket Memo)
- python — Pythonソケットは大量のデータを受信します
送信したデータが受信されないと送信側はブロッキングする。
つまり、通信状況が悪いと送信タイミングのリアルタイム性が損なわれる。
・UDP
送信したパケットは勝手に分割されないが、あまりデータが大きいとIPフラグメンテーションされる可能性がある。(パケット分割とIPフラグメントは別物らしい)
その場合受信側でデータがすべて出揃うまで受信を完了しない。(データの境界保証あり)
つまり1回send() =1回recv()
また、データがいつまでたっても揃わなかったらそのデータは破棄される。
send()したデータの順番とrecv()したデータの順番が入れ替わる可能性がある。
送信側は受信側がちゃんと受信できたか確認しないで構わず送信し続けるため、
通信状況が悪くても送信タイミングのリアルタイム性が損なわれない。
- TCPとUDPの違いを10個挙げてみる - ikeas's blog
- 基礎から学ぶWindowsネットワーク - @IT
- UDP を使ってみよう (5)
- 第14回 TCPとUDP | 日経クロステック(xTECH)
MCP2515を使ってArduinoでCAN通信
MCP2515のモジュールを使ってArduinoでCAN通信をさせる。
ライブラリはMPC_CAN_libを使う。
スケッチの書き方は、MPC_CANのgithubのサンプルプログラムとヘッダを見るとわかりやすい。
- 【RaspberryPi】 RaspberryPiとArduinoをCAN通信させた - Yoshichiの日記
- 【RaspberryPi】 RaspberryPiとArduinoをCAN通信させた 2回目 - Yoshichiの日記
- OBD2(CAN)で自動車と通信(回路編) | Make.
- OBD2(CAN)で自動車と通信(スケッチ編) | Make.
- ArduinoでCAN-Busモニタ
- GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library
・ハマったところ1
MCP_CAN::begin() が変更されてて、引数にいろいろ指定しなければいけなくなっていた。
何を指定しなければいけないかはサンプルプログラムとヘッダを見て判断した。
第1引数:IDの種類
第2引数:canの通信速度
第3引数:モジュールとの通信レート(今回の場合はモジュールの水晶発振子の周波数)
・ハマったところ2
MCP_CAN::setMode() が抜けてた
簡単なArduinoスケッチ
以下のソースではif(!digitalRead(INT_PIN))の部分でモジュールからの割り込みをポーリングしているが、
モジュールの割り込み用ピンをArduinoの外部割込み(ハードウェア割り込み)に割り当てて、
割り込み処理したほうが効率がいいと思う。
// ライブラリヘッダのインクルード #include <mcp_can.h> #include <SPI.h> //設定値 #define CS_PIN (10) // CSを10ピンとする(変更可能) #define INT_PIN (9) // INTを9ピンとする(変更可能) long unsigned int rxId; unsigned char len = 0; unsigned char rxBuf[8]; MCP_CAN CAN0(CS_PIN); void setup() { Serial.begin(115200); CAN0.begin(CAN_STDID, CAN_500KBPS, MCP_8MHZ); // CANの通信速度を500kbpsにする pinMode(INT_PIN, INPUT); // 割り込みのためのピンを設定 CAN0.setMode(MCP_NORMAL); Serial.println("MCP2515 Library Receive Example..."); } byte data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; void loop(){ //受信 if(!digitalRead(INT_PIN)) { // 受信割り込みが発生したら、CANデータをReadする CAN0.readMsgBuf(&rxId, &len, rxBuf); Serial.print("ID: "); Serial.print(rxId, HEX); Serial.print(" Data: "); for(int i = 0; i<len; i++) { if(rxBuf[i] < 0x10) { Serial.print("0"); } Serial.print(rxBuf[i], HEX); Serial.print(" "); } Serial.println(); } //送信 byte sndStat = CAN0.sendMsgBuf(0x122, 0, 8, data); if (sndStat != CAN_OK) { Serial.println("Error Sending Message..."); } delay(100); // send data per 100ms } /********************************************************************************************************* END FILE *********************************************************************************************************/