質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

1回答

3568閲覧

Arduinoを用いたCAN通信で連続的なメッセージを受け取り、処理する方法。

NKJSM

総合スコア58

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2021/09/21 03:30

編集2021/09/21 23:27

SparkFun CAN-Busというシールドとライブラリを使ってCAN通信を行いたいです。
通信相手が10ms間隔で連続する3つのメッセージを送信しており、1つ目と3つ目の信号は読めるのですが、1つ目の処理中に2つ目と3つ目が来て、2つ目が上書きされているのか読み出しができません。それともメールボックスが2つとも使われて3つ目が保存されないのか。
処理を早めようと極限まで内容を削って、通信速度を上げても無理でした。
3つの信号全てを受け取る方法をご教授願います。

P.S.
通信速度9600や19200の低速時はモニタに表示されるIDは282が殆どでたまに382、302が表示されていました(282が0.05秒に一回程度、382が0.5秒に一回程度、302が1.5秒に一回程度)
230400や500000のように高速にすると結果のように282と382のみが交互に表示されるようになりました。

また、送信タイミングは同時から変更できませんが、送信間隔を変更できまして、1秒間隔に変更しました場合、通信速度が9600でも500000でもIDは282と382のみが交互に表示され、302を一切確認できませんでした。

Arduino

1#include <Canbus.h> 2#include <defaults.h> 3#include <global.h> 4#include <mcp2515.h> 5#include <mcp2515_defs.h> 6 7//********************************Setup Loop*********************************// 8 9void setup() { 10 Serial.begin(230400); // For debug use 11 Serial.println("CAN Read - Testing receival of CAN Bus message"); 12 delay(1000); 13 14 if(Canbus.init(CANSPEED_500)) //Initialise MCP2515 CAN controller at the specified speed 15 Serial.println("CAN Init ok"); 16 else 17 Serial.println("Can't init CAN"); 18 19 delay(1000); 20} 21 22//********************************Main Loop*********************************// 23 24void loop(){ 25 tCAN message; 26if (mcp2515_check_message()){ 27 if (mcp2515_get_message(&message)){ 28 Serial.println(message.id,HEX); 29 30 /*/if(message.id == 0x302) 本来やりたいこと 31 { 32 33 Serial.print("ID: "); 34 Serial.print(message.id,HEX); 35 Serial.print(", Length: "); 36 Serial.print(message.header.length,DEC); 37 Serial.print(", Data: "); 38 for(int i=0;i<message.header.length;i++) 39    { 40 Serial.print(message.data[i],HEX); 41 Serial.print(" "); 42    } 43 Serial.println(""); 44 }*/ 45 46 } 47 } 48}

Arduino

1結果(本来は302も送信されている) 212:22:56.579 -> 282 312:22:56.579 -> 382 412:22:57.561 -> 282 512:22:57.561 -> 382 612:22:58.541 -> 282 712:22:58.588 -> 382 812:22:59.570 -> 282 912:22:59.570 -> 382 1012:23:00.556 -> 282 1112:23:00.556 -> 382 12

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2021/09/21 04:17

送信側が282, 302, 382を送信していることはどうやって確認しましたか?
NKJSM

2021/09/21 04:38 編集

送信側のマニュアルを読んだのと、282と382は結果のようにシリアルモニタで確認できました。302に関しましては通信速度を9600や19200程度にしてSerial.printの数を調整するとタイミングが合うのか、たまにシリアルモニタに出てくるので確認しました。本文の方も少し追記させていただきます。
guest

回答1

0

ベストアンサー

同時に複数の信号

「同時」ってことはないでしょう...コンピュータの世界では、10msってのは相当長い時間ですし、CanBUSってつまりは全二重のシリアル通信で一時には一つのデータしか送られてきませんよね?
(ここ勘違い。CANはデバイスが複数ぶら下がるんだった)

で、該当デバイスを使ったことがあるわけでもなく仕様書等をちょっと覗いただけですが、

使用しているライブラリがsparkfanのものだとすると、ライブラリのソースを覗いてみると割り込みを使っていないようですから、既存のライブラリに頼らず自分で割り込みを使ってプログラムを書けば取りこぼしに対策できるのではないでしょうか。

余談ですが、低速(といっていいかしら)でシリアル送信を行う場合、送信より早いペースで送信の関数(Serial.print()等)を呼ぶと送信バッファが一杯になって、関数に渡したデータが全てバッファに収まるまで関数から戻らなくなります。
9600bpsではざっくり1byteの送信に1msかかり、送信バッファはデフォルトでは64byteです。これを考慮せずにむやみにデータを沢山送ろうとするとプログラムの動作に影響が出てきます。
(今回はそういう使い方はしていないようですが)

投稿2021/09/21 12:57

編集2021/09/21 23:39
thkana

総合スコア7639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NKJSM

2021/09/22 00:32 編集

回答ありがとうございます。そうですね、今回の件においては同時ではないです。文章の方も連続に変更させていただきました。(おそらく)処理中に次のメッセージが来てるだろうことから同時と使ってしまいましたが、文法ミスですね、申し訳ございません。 コントローラ(mcp2515)のデータシートから読むと、バッファが2つしかないうえに処理も遅くて(恐らくSPIの転送速度が原因?)メッセージの処理よりも次のメッセージの受信完了の方が早く、今回の環境では余り使い物にならないなということがわかりました。処理を早められそうか探して、ダメそうなら他のインタフェースを探そうと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問