UdonLibrary 1.0.0
機械システム研究部 C++ ライブラリ
読み取り中…
検索中…
一致する文字列を見つけられません
CanBusTeensy.hpp
[詳解]
1//
2// CAN通信 Teensy用バスクラス 実装部
3//
4// Copyright (c) 2022-2024 udonrobo
5//
6
7namespace Udon
8{
9
10 template <CAN_DEV_TABLE Bus>
12 : config(config)
13 {
14 self = this;
15 }
16
18 template <CAN_DEV_TABLE Bus>
20 : config(other.config)
21 , bus(other.bus)
22 , txNodes(other.txNodes)
23 , rxNodes(other.rxNodes)
24 {
25 self = this;
26 }
27
29 template <CAN_DEV_TABLE Bus>
31 {
32 end();
33 }
34
36 template <CAN_DEV_TABLE Bus>
38 {
39 // バス初期化
40 bus.begin();
41 bus.setBaudRate(config.canBaudrate);
42
43 // 受信開始
44 if (rxNodes.size())
45 {
46 // 受信フィルタ設定 (ノード数が8以下の場合のみ)
47 if (rxNodes.size() <= 8)
48 {
49 bus.setFIFOFilter(REJECT_ALL);
50 for (size_t i = 0; i < rxNodes.size(); ++i)
51 {
52 bus.setFIFOUserFilter(
53 /* Filter */ i,
54 /* ID */ rxNodes[i].id,
55 /* Mask */ 0x7FF,
56 /* Frame type */ STD,
57 /* Remote frame */ NONE);
58 // 複数のフィルタを設定する関数が用意されているが、適切に受信できていなかったので1つずつ設定している (2023/08/19)
59 }
60 }
61 else
62 {
63 bus.setFIFOFilter(ACCEPT_ALL);
64 }
65
66 // FIFOバッファ有効化
67 bus.enableFIFO();
68 bus.enableFIFOInterrupt();
69
70 // 受信割り込み設定
71 bus.onReceive(
72 [](const CAN_message_t& msg)
73 {
74 self->rxBuffer.push_back(msg);
75 });
76 }
77 }
78
80 template <CAN_DEV_TABLE Bus>
82 {
83 bus.disableFIFOInterrupt();
84 bus.disableFIFO();
85 }
86
88 template <CAN_DEV_TABLE Bus>
90 {
91 onReceive();
92 if (txNodes.size() && millis() - transmitMs >= config.transmitInterval)
93 {
94 onTransmit();
95 transmitMs = millis();
96 }
97 }
98
99 template <CAN_DEV_TABLE Bus>
101 {
102 return not(txTimeout() or rxTimeout());
103 }
104
105 template <CAN_DEV_TABLE Bus>
107 {
108 if (txNodes.size())
109 return millis() - transmitMs >= config.transmitTimeout;
110 else
111 return false;
112 }
113
114 template <CAN_DEV_TABLE Bus>
115 bool CanBusTeensy<Bus>::rxTimeout() const
116 {
117 if (rxNodes.size())
118 return millis() - receiveMs >= config.receiveTimeout;
119 else
120 return false;
121 }
122
124 template <CAN_DEV_TABLE Bus>
126 {
127 Serial.print("CanBusTeensy\n");
128
129 for (auto&& node : txNodes)
130 {
131 Serial.print("\tTX ");
132
133 Serial.printf("0x%03x ", static_cast<int>(node.id));
134
135 Serial.printf("%2zu byte ", node.data.size());
136
137 Serial.print(node.data.size() > SingleFrameSize ? "(multi frame) " : "(single frame) ");
138
139 Serial.print("[");
140
141 for (const auto& data : node.data)
142 {
143 Serial.printf("%4d", data);
144 }
145
146 Serial.print(" ]");
147
148 Serial.println();
149 }
150
151 for (auto&& rxNode : rxNodes)
152 {
153 Serial.print("\tRX ");
154
155 Serial.printf("0x%03x ", static_cast<int>(rxNode.id));
156
157 Serial.printf("%2zu byte ", rxNode.data.size());
158
159 Serial.print(rxNode.data.size() > SingleFrameSize ? "(multi frame) " : "(single frame) ");
160
161 Serial.print("[");
162
163 for (const auto& data : rxNode.data)
164 {
165 Serial.printf("%4d", data);
166 }
167
168 Serial.print(" ]");
169
170 Serial.println();
171 }
172 }
173
176 template <CAN_DEV_TABLE Bus>
177 CanTxNode* CanBusTeensy<Bus>::createTx(uint32_t id, size_t length)
178 {
179 auto it = std::find_if(txNodes.begin(), txNodes.end(), [id](const CanTxNode& tx)
180 { return tx.id == id; });
181 if (it == txNodes.end())
182 {
183 txNodes.push_back({ id, std::vector<uint8_t>(length), 0 });
184 return &txNodes.back();
185 }
186 return &(*it);
187 }
188
191 template <CAN_DEV_TABLE Bus>
192 CanRxNode* CanBusTeensy<Bus>::createRx(uint32_t id, size_t length)
193 {
194 rxNodes.push_back({
195 id,
196 std::vector<uint8_t>(length),
197 nullptr,
198 nullptr,
199 0,
200 });
201 return &rxNodes.back();
202 }
203
205 template <CAN_DEV_TABLE Bus>
207 {
208 const auto ms = millis();
209
210 for (auto&& msg : rxBuffer)
211 {
212 // IDに対応する受信ノードを探す
213 auto rxNode = std::find_if(rxNodes.begin(), rxNodes.end(), [&msg](const CanRxNode& rx)
214 { return rx.id == msg.id; });
215 if (rxNode == rxNodes.end())
216 {
217 continue;
218 }
219
220 // 分割されたフレームを結合(マルチフレームの場合)
222 { msg.buf },
223 { rxNode->data },
224 SingleFrameSize);
225
226 // 登録されている受信クラスのコールバック関数を呼ぶ
227 // 最終フレームの到達時にコールバックを呼ぶため、受信中(完全に受信しきっていないとき)にデシリアライズすることを防いでいる。
228
229 if (rxNode->data.size() > SingleFrameSize)
230 {
231 // マルチフレーム
232 const auto frameCount = std::ceil(static_cast<double>(rxNode->data.size()) /( SingleFrameSize - 1 /*index*/) )- 1;
233
234 if (msg.buf[0] == frameCount)
235 {
236 rxNode->callback();
237 }
238 }
239 else
240 {
241 // シングルフレーム
242 rxNode->callback();
243 }
244
245 receiveMs = rxNode->transmitMs = ms;
246 }
247 rxBuffer.clear();
248 }
249
251 template <CAN_DEV_TABLE Bus>
252 void CanBusTeensy<Bus>::onTransmit()
253 {
254 const auto ms = millis();
255
256 for (auto&& node : txNodes)
257 {
258 CAN_message_t msg;
259 msg.id = node.id;
260 msg.len = SingleFrameSize;
261
262 // 一度に8バイトしか送れないため、分割し送信
263 Udon::Impl::Packetize({ node.data }, { msg.buf }, SingleFrameSize,
264 [this, &msg](size_t)
265 {
266 bus.write(msg);
267 delayMicroseconds(200);
268 });
269
270 node.transmitMs = ms;
271 }
272 }
273
274 template <CAN_DEV_TABLE Bus>
275 CanBusTeensy<Bus>* CanBusTeensy<Bus>::self;
276
277}; // namespace Udon
Teensy用 CANバスクラス
Definition CanBusTeensy.hpp:31
CanRxNode * createRx(uint32_t id, size_t length) override
受信ノードをバスに参加させる
Definition CanBusTeensy.hpp:192
void show() const
バス情報を表示する
Definition CanBusTeensy.hpp:125
void update()
バス更新
Definition CanBusTeensy.hpp:89
CanTxNode * createTx(uint32_t id, size_t length) override
送信ノードをバスに参加させる
Definition CanBusTeensy.hpp:177
void begin()
通信開始
Definition CanBusTeensy.hpp:37
CanBusTeensy(const Config &config={})
コンストラクタ
Definition CanBusTeensy.hpp:11
void end()
通信終了
Definition CanBusTeensy.hpp:81
~CanBusTeensy()
デストラクタ
Definition CanBusTeensy.hpp:30
void Packetize(Udon::ArrayView< const uint8_t > &&input, Udon::ArrayView< uint8_t > &&output, size_t singlePacketSize, Function func)
バイト列を複数のパケット、単一のパケットにパケット化する
Definition CanUtility.hpp:24
void Unpacketize(Udon::ArrayView< const uint8_t > &&input, Udon::ArrayView< uint8_t > &&output, size_t singlePacketSize)
複数のパケット、単一のパケットからバイト列にアンパケット化する
Definition CanUtility.hpp:83
Definition Bit.hpp:12
Definition CanBusTeensy.hpp:34
CAN受信ノード
Definition ICanBus.hpp:28
CAN送信ノード
Definition ICanBus.hpp:17