UdonLibrary
1.0.0
機械システム研究部 C++ ライブラリ
Toggle main menu visibility
読み取り中…
検索中…
一致する文字列を見つけられません
Im920Normal.hpp
[詳解]
1
//
2
// 通常 IM920
3
//
4
// Copyright (c) 2022 udonrobo
5
//
6
7
//
8
// Sender --[UART]--> IM920 ~~[920MHz]~~> IM920 --[UART]--> Receiver
9
// ^^^^^^ ^^^^^^^^
10
//
11
12
#pragma once
13
14
#include "
IIm920.hpp
"
15
16
#include <
Udon/Algorithm/BitPack.hpp
>
17
#include <
Udon/Types/Optional.hpp
>
18
#include <
Udon/Utility/Printf.hpp
>
19
#include <
Udon/Types/ArrayView.hpp
>
20
21
namespace
Udon
22
{
23
25
class
Im920
26
:
public
IIm920
27
{
28
HardwareSerial& uart;
29
30
Im920Node
* txNode;
31
Im920Node
* rxNode;
32
33
bool
twoWayNum;
34
uint32_t sendMitMs;
35
uint32_t receiveDeadTime;
36
37
public
:
38
Im920
(HardwareSerial& uart,
bool
twoWayNum =
false
)
39
: uart(uart)
40
, twoWayNum(twoWayNum)
41
, sendMitMs()
42
, receiveDeadTime()
43
{
44
}
45
48
operator
bool()
const override
49
{
50
switch
(getTransmitMode())
51
{
52
case
TransmitMode::Send:
53
return
uart && (millis() - sendMitMs < 1000);
54
case
TransmitMode::Receive:
55
return
uart && (millis() - receiveDeadTime < 1000);
56
case
TransmitMode::TwoWay:
57
return
uart && (2 * millis() - (sendMitMs + receiveDeadTime) < 1000);
58
default
:
59
return
false
;
60
}
61
}
62
65
void
begin
(uint8_t channel);
66
67
void
update
()
68
{
69
switch
(getTransmitMode())
70
{
71
case
TransmitMode::Send:
72
sendUpdate();
73
break
;
74
case
TransmitMode::Receive:
75
receiveUpdate();
76
break
;
77
case
TransmitMode::TwoWay:
78
twoWayUpdate();
79
break
;
80
default
:
81
break
;
82
}
83
}
84
86
void
show
()
87
{
88
if
(
operator
bool
())
89
{
90
Serial.print(
"IM920: OK "
);
91
}
92
else
93
{
94
Serial.print(
"IM920: NG "
);
95
}
96
97
switch
(getTransmitMode())
98
{
99
case
TransmitMode::Send:
100
Serial.print(
"SendMode "
);
101
break
;
102
case
TransmitMode::Receive:
103
Serial.print(
"ReceiveMode "
);
104
break
;
105
case
TransmitMode::TwoWay:
106
Serial.print(
"TwoWayMode "
);
107
break
;
108
case
TransmitMode::Empty:
109
Serial.print(
"Empty "
);
110
break
;
111
}
112
}
113
116
void
joinTx
(
Im920Node
& node)
override
{ txNode = &node; }
117
119
void
joinRx
(
Im920Node
& node)
override
{ rxNode = &node; }
120
121
private
:
122
enum class
TransmitMode
123
{
124
Send,
125
Receive,
126
TwoWay,
127
Empty,
128
};
129
131
TransmitMode getTransmitMode()
const
132
{
133
if
(txNode)
134
{
135
if
(rxNode)
136
{
137
return
TransmitMode::TwoWay;
138
}
139
else
140
{
141
return
TransmitMode::Send;
142
}
143
}
144
else
if
(rxNode)
145
{
146
return
TransmitMode::Receive;
147
}
148
else
149
{
150
return
TransmitMode::Empty;
151
}
152
}
153
154
void
sendUpdate()
155
{
156
uart.print(
"TXDA "
);
157
158
Udon::BitPack
(txNode->data, txNode->data + txNode->size, [
this
](uint8_t data)
159
{ uart.write(data); });
160
161
uart.print(
"\r\n"
);
162
}
163
164
bool
receiveUpdate()
165
{
166
// header = [Dummy: 2byte] + [,] + [Node number: 4byte] + [,] + [RSSI: 2byte] + [:]
167
constexpr
int
HeaderSize = 2 + 1 + 4 + 1 + 2 + 1;
168
169
// footer = [\r] + [\n]
170
constexpr
int
FooterSize = 1 + 1;
171
172
// FrameSize = header + data + footer
173
const
int
FrameSize = HeaderSize +
Udon::BitPackedSize
(rxNode->size) + FooterSize;
174
175
// 受信バッファにデータがない場合は何もしない
176
if
(uart.available() < FrameSize)
177
{
178
return
false
;
179
}
180
181
// ヘッダー読み捨て
182
for
(
int
i = 0; i < HeaderSize; ++i)
183
{
184
uart.read();
185
}
186
187
// データ読み込み
188
if
(not
Udon::BitUnpack
(rxNode->data, rxNode->data + rxNode->size, [
this
]() -> uint8_t
189
{ return uart.read(); }))
190
{
191
// 先頭バイトの MSB が 1 でない場合はデータが壊れているので読み捨て
192
while
(uart.available())
193
{
194
uart.read();
195
}
196
return
false
;
197
}
198
199
// フッター読み捨て
200
for
(
int
i = 0; i < FooterSize; ++i)
201
{
202
uart.read();
203
}
204
205
// バッファに残っているデータを読み捨て
206
while
(uart.available())
207
{
208
uart.read();
209
}
210
211
rxNode->transmitMs = millis();
212
213
return
true
;
214
}
215
216
void
twoWayUpdate()
217
{
218
// transTime =[内部処理時間:10~20ms]+[キャリアセンス:初回5.2ms 連続通信時0.5ms]+[不要データの通信:3.2ms]+[バイトごとの送信時間:0.16ms]
219
const
double
sendTime = 10.0 + 5.2 + 3.2 + txNode->size * 0.16;
220
const
double
receiveTime = 10.0 + 5.2 + 3.2 + rxNode->size * 0.16;
221
222
if
(twoWayNum)
223
{
224
if
(2 * millis() - (sendMitMs + receiveDeadTime) > sendTime + receiveTime)
225
{
// 時間経過により再送信
226
sendUpdate();
227
}
228
if
(receiveUpdate())
229
{
230
sendUpdate();
231
}
232
}
233
else
234
{
235
if
(receiveUpdate())
236
{
237
sendUpdate();
238
}
239
}
240
}
241
};
242
inline
void
Im920::begin
(uint8_t channel)
243
{
244
// ボーレート設定
245
uart.begin(115200);
246
247
// チャンネル設定
248
Udon::Printf
(uart,
"STCH %02d\r\n"
, channel);
249
delay(100);
250
251
// 送信出力[10mW]
252
uart.print(
"STPO 3\r\n"
);
253
delay(100);
254
255
// 高速通信モード[50kbps]
256
uart.print(
"STRT 1\r\n"
);
257
delay(100);
258
259
// キャラクタ入出力モード
260
uart.print(
"ECIO\r\n"
);
261
delay(1000);
262
}
263
}
// namespace Udon
ArrayView.hpp
BitPack.hpp
IIm920.hpp
Optional.hpp
Printf.hpp
Udon::IIm920
IM920のインターフェース
Definition
IIm920.hpp:31
Udon::Im920::update
void update()
Definition
Im920Normal.hpp:67
Udon::Im920::begin
void begin(uint8_t channel)
通信開始
Definition
Im920Normal.hpp:242
Udon::Im920::joinRx
void joinRx(Im920Node &node) override
受信ノードを登録
Definition
Im920Normal.hpp:119
Udon::Im920::joinTx
void joinTx(Im920Node &node) override
送信ノードを登録
Definition
Im920Normal.hpp:116
Udon::Im920::Im920
Im920(HardwareSerial &uart, bool twoWayNum=false)
Definition
Im920Normal.hpp:38
Udon::Im920::show
void show()
バスの状態を表示
Definition
Im920Normal.hpp:86
Udon
Definition
Bit.hpp:12
Udon::BitPack
void BitPack(const InputIterator begin, const InputIterator end, Functor callback)
バイト列のMSB(最上位ビット)を抽出し、7bitごとに分割してコールバック関数に渡す
Definition
BitPack.hpp:23
Udon::Printf
void Printf(const char *format, Args... args)
Definition
Printf.hpp:44
Udon::BitUnpack
bool BitUnpack(OutputIterator begin, OutputIterator end, Functor callback)
7bit分割されたデータを結合する
Definition
BitPack.hpp:70
Udon::BitPackedSize
constexpr size_t BitPackedSize(size_t size)
ビットパックされたデータのサイズを取得する
Definition
BitPack.hpp:132
Udon::Im920Node
IM920ノード
Definition
IIm920.hpp:20