hiro yamamoto works

マイコンハード、ソフトを作ったりしています。
お家や現場のお困りごと解決に!
内容利用は自己責任でお願いします。

CANバスモジュールを使ってデータ送受信する(受信側復習)

2023-11-02 17:35:32 | CAN通信

しばらく放置していたら、自分の書いたスケッチがわからなくなったので、
ブログ投稿しながら復習することにしました。
送信側 SAMD XIAOとMCP2515 受信側 Arduino MKRZERO(SAMD)とMCP2515の組み合わせです。
私が使うための最低限の情報だけなので、もっと掘り下げたい方は詳しいサイトを探して下さい。
※テストしてわかったこと※
 理由はわからないが、送信側で、1byteの中で7bitしか使えない事がわかった。
受信側は送信側の7bitに合わせるしかありません。


Amazonで購入したCANバスモジュール
CANコントローラ(MCP2515)とトランシーバ(TJA1050)のICが載っています。

loop()関数中スケッチ抜粋

int packetSize = mcp.parsePacket();
  if (packetSize) {
    if (mcp.packetId() == packetId11) { //送信側IDと一致(packetId11)
      id11_value = 0;
      byte receivedData[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
      while (mcp.available()) { 
        for (int i = 0; i <= 7; i++) {//受信した0~8byteを配列に入れていく
          receivedData[i] = (byte)mcp.read();
        }//for
      }//while
      //receivedData[0]~[8]配列内のデータを処理して送信元データへ復元する
      for (int i = 0; i <= 7; i++) {//配列を順に呼んで
        id11_value |= (uint32_t)(receivedData[i] << (7 * i));//1byteの1〜7bitを使う時
        //配列内データを7bitビットずつシフトして、ビット単位のOR演算する
        //forループを8回(i=0から7)繰り返すと56bit復元される。
        //送信元データサイズに合わせてループ回数を決めれば良いと思う。
        //id11_value |= (uint32_t)(receivedData[i] << (8 * i));//1byteの1〜8bitを使う時
      }
      Serial.print("Value11 ");
Serial.println(id11_value);
    }


これで使えるかと思いますが、もっとシンプルなスケッチに出来るかもしれません。
間違いがあるかもしれませんのでご注意を

復習完了か?


CANバスモジュールを使ってデータ送受信する(送信側復習)

2023-10-28 17:37:28 | CAN通信

しばらく放置していたら、自分の書いたスケッチがわからなくなったので、
ブログ投稿しながら復習することにしました。
送信側 SAMD XIAOとMCP2515 受信側 Arduino MKRZERO(SAMD)とMCP2515の組み合わせです。
私が使うための最低限の情報だけなので、もっと掘り下げたい方は詳しいサイトを探して下さい。
※テストしてわかったこと※
 理由はわからないが、1byteの中で7bitしか使えない事がわかった


Amazonで購入したCANバスモジュール
CANコントローラ(MCP2515)とトランシーバ(TJA1050)のICが載っています。

MCP2515 CANコントローラについて
マイクロコントローラとの接続インターフェース:SPI(10MHz)
1秒間に送受信可能なデータ量(Mb/s):1Mb/s
(Mbyte/秒(メガバイト/秒)1byteは8bit 1Mb/sは8Mbpsに相当
 Mbpsとは、1秒間でのデータの転送速度 bit/秒)

CAN通信について(かんたんに)
データの中に”ID(識別子)を付加して送信する”
データ受信側は、IDにより「どのようなデータなのか?」判断できる。
IDは通信調停の優先順位決定にも使われる。
標準フォーマット:11ビット長でIDを構成、IDの範囲0x0~0x7FF 2048種類の識別可能
(拡張フォーマット:ID(ベースID)と拡張IDの18ビット長で構成)
1回に送信できるデータ量が最大8byte
ひとつのIDで8byte送れる。(と思っていたが実際は1byte(8bit)の中で7bitしか使えなかった)
8byteのデータを送れるということは、つまり64bitのデータを送れるということになる。
(前述の通り7bitなので7x8=56bitと思われる)

6個のデータを送りたい
データごとにIDをつける。
1個のデータは32bit(0〜4294967295)4byteぐらいの数値を送れるようにしておく。
32bit(4byte)のデータを、8bit(1byte)7bit毎に分割して、
送信データへ入れていく\


mcp.beginPacket(packetid);//packetidは任意のID
  for (int i = 0; i <= 7; i++) { // data1の配列を順に切り替えていくため
  //Value1は分割する前のデータ(bit単位で取り扱う)
  //8とiを積を求めてその分のbit右シフトをする
  //iが増加する毎に、bit単位のValue1を1byteづつ取り出せるようにする
  //0xFFとbit単位のAND演算をして1byte取り出す
  //配列に入れる
  //data1[i] = (byte)(Value1 >> (i * 8)) & 0xFF;//1byteの8bit使用
    data[i] = (byte)(Value1 >> (i * 7)) & 0x7F;//1byteの7bitを使用
mcp.write(data1[i]);//データを組み立てていく感じ?
  }//for文の閉じ括弧
mcp.endPaket();//準備したデータを送る感じ?


今日はここまで

補足
前述のスケッチはloop関数中の記述抜粋です。
beginPacketのIDを変えて複数記述すれば、複数のデータを送ることが出来ます。(たぶん)
6個のデータは正常に送ることが出来ました。
実は正しく送れないデータ範囲がありました。スケッチ修正箇所あります。
1byte(8bit)の7bitしか使えなかったのはSAMDマイコンとRP2040でしたので注意して下さい。


CANバスモジュールを使ってデータ送受信する(RP2040使用を断念)

2023-10-21 16:30:54 | CAN通信

RP2040マイコンを使ってCANバスでデータの送受信テストをしてきましたが、
不可解な現象に悩まされていました。残念ながら私のスキルでは解決できず、
XIAO SAMDへ変更することにしました。

こんなことが起こります。
ID毎に1つのデータを割り当てて、6個のデータ(6個のID)を送った時、
特定の1個のIDが消失してしまう。

うまくいかなかったやつの 構成・仕様(参考)
SPI接続CANバスモジュール(送信、受信各1個)
(コントローラ:MCP2515、トランシーバ:TJA1050)
マイクロコントローラ:AE-RP2040(送信、受信各1個)
送受信データ:6個(データ毎に1つづつIDを割り当て)
データログ&HTTPサーバ:ESP32
動作概要
複数のデータそれぞれにID番号を割り当てて
送信側:数値をばらしてバイト配列に入れて送る。
受信側:バイト配列を組み立ててもとの数値へ戻す。

難点(RP2040が悪いわけではありません!)
・ArduinoUNO、ESP32で動いていたライブラリがRP2040で動かない。
・RP2040マイコンに完全対応したCANコントローラのライブラリが見つからなかった。
(2023年9月時点)
・Adafruitの MCP2515ライブラリで制約があるが動く( RP2040非対応を自己責任で使う)
 制約について
 送信データの1バイトに入る数値
 0x00〜0xFF(B11111111)のはずが、最上位bitが使えず0x00〜0x7F(B1111111)
 送信8バイトをフルに使うことはないので使えると判断した。
 ところがさらに進めていくと、不可解現象”特定IDの消失”で悩まされる。

作業が進んだら投稿します。


CAN通信開発中RaspberryPiではセルフパワーUSBハブで安定

2023-07-30 12:46:44 | CAN通信

RaspberryPi 4Bを使ってArduinoIDE動かしています。
ESP32の起動失敗やSDのファイルオープン失敗など不安定な現象が発生していました。
USB延長ケーブルとブレットボード接触甘めで電源電圧低下していたようです。

ブレットボード用ジャンパーワイヤをやめてブレッドボードにピンヘッダを挿してはんだ付け
さらにセルフパワーのUSBハブを導入しました。
不安定な挙動は全くなくなりました。


CANバスモジュールを使ってデータ送受信する。(RP2040 受信)

2023-07-15 14:27:40 | CAN通信

受信側スケッチです。改善の余地あり(ちょっと直しました。)
ChatGPT先生にいっぱいヒントを頂きました。
参考:コンパイル途中に次のようなメッセージ表示されていました。
警告:ライブラリAdafruit_CANはアーキテクチャsamdに対応したものであり、
アーキテクチャrp2040で動作するこのボードとは互換性がないかもしれません。
AdafruitのMCP2515ライブラリからのメッセージと思われます。

/*   Adafruit MCP2515_CAN_Receiver_Exampleを改変しています。
一部省略 転記ミスや表示されてない記号があるかも <は半角に直して */
#include<Adafruit_MCP2515.h>
#define CS_PIN    20
// Set CAN bus baud rate
#define CAN_BAUDRATE (250000)
Adafruit_MCP2515 mcp(CS_PIN);
byte receivedData[8];
uint32_t id1_value = 0;
uint32_t id2_value = 0;
uint32_t id3_value = 0;
void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);
  Serial.println("MCP2515 Receiver test!");
  if (!mcp.begin(CAN_BAUDRATE)) {
    Serial.println("Error initializing MCP2515.");
    while (1) delay(10);
  }
  Serial.println("MCP2515 chip found");
}
void loop() {
// try to parse packet
//このスケッチは受信側Receiver(read)
int packetSize = mcp.parsePacket();
if (packetSize) {
if (mcp.packetId() == 0x11) {
Serial.print(mcp.packetId(), HEX); Serial.print(" ");
id1_value = 0;
while (mcp.available()) { //8byte固定 このスケッチは受信側Receiver(read)
for (int i = 0; i <= 7; i++) {
          receivedData[i] = mcp.read();
        }
/*receivedData[0] = mcp.read();
receivedData[1] = mcp.read();
receivedData[2] = mcp.read();
receivedData[3] = mcp.read();
receivedData[4] = mcp.read();
receivedData[5] = mcp.read();
receivedData[6] = mcp.read();
receivedData[7] = mcp.read();*/
}
for (int i = 0; i <= 7; i++) {
id1_value |= (uint32_t)(receivedData[i] << (7 * i));
}
Serial.print("timeValue0 "); Serial.println(id1_value);
}else if (mcp.packetId() == 0x12) {
Serial.print(mcp.packetId(), HEX); Serial.print(" ");
id2_value = 0;
while (mcp.available()) {
for (int i = 0; i <= 7; i++) {
          receivedData[i] = mcp.read();
        }/*
receivedData[0] = mcp.read();
receivedData[1] = mcp.read();
receivedData[2] = mcp.read();
receivedData[3] = mcp.read();
receivedData[4] = mcp.read();
receivedData[5] = mcp.read();
receivedData[6] = mcp.read();
receivedData[7] = mcp.read();*/
}
for (int i = 0; i <= 7; i++) {
id2_value |= (uint32_t)(receivedData[i] << (7 * i));
}
Serial.print("timeValue1 ");
Serial.println(id2_value);
}else if (mcp.packetId() == 0x13) {
Serial.print(mcp.packetId(), HEX); Serial.print(" ");
id3_value = 0;
while (mcp.available()) {
for (int i = 0; i <= 7; i++) {
          receivedData[i] = mcp.read();
        }/*receivedData[0] = mcp.read();
receivedData[1] = mcp.read();
receivedData[2] = mcp.read();
receivedData[3] = mcp.read();
receivedData[4] = mcp.read();
receivedData[5] = mcp.read();
receivedData[6] = mcp.read();
receivedData[7] = mcp.read();*/
}
for (int i = 0; i <= 7; i++) {
id3_value |= (uint32_t)(receivedData[i] << (7 * i));
}
Serial.print("timeValue2 ");
Serial.println(id3_value);
}
}
}