-
Notifications
You must be signed in to change notification settings - Fork 16
/
arduino_parameters.ino
368 lines (274 loc) · 9.46 KB
/
arduino_parameters.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
//------------------------------
// The fastMavlink library
// (c) OlliW, OlliW42, www.olliw.eu
// https://github.com/olliw42/fastmavlink/
//------------------------------
// fastMavlink Example
// Parameters
// For details see fastMavlink github repo.
// For Arduino IDE.
//------------------------------
// Licence: This code is free and open and you can use it
// in whatever way you want. It is provided as is with no
// implied or expressed warranty of any kind.
//------------------------------
// Do this before you start:
// Copy the fastMavlink c_library folder into the sketch folder.
//------------------------------
//------------------------------
// Implement the interface assumed by the fastMavlink examples
//------------------------------
// Attention: The Arduino's buffer for serial write can be very limited (the docs say 64 bytes!),
// and can be too small for really doing MAVLink. The serial_has_space() function may hence trigger
// often and effectively block the code from working. In that case you may work around by letting it
// return true always
// Depending on board and core and setup, the main serial might be Serial, Serial1, ...
// Choose what's correct for you.
#define SERIAL Serial1
#define SERIAL_BAUD 57600 // 57600 or 115200 are usually good choices
uint16_t serial_available(void)
{
uint16_t available = SERIAL.available();
return (available > 0) ? available : 0;
}
void serial_read_char(uint8_t* c)
{
*c = SERIAL.read();
}
uint8_t serial_has_space(uint16_t count)
{
return (SERIAL.availableForWrite() >= count) ? 1 : 0;
}
void serial_write_buf(uint8_t* buf, uint16_t len)
{
for(uint16_t i = 0; i < len; i++) SERIAL.write(buf[i]);
}
uint32_t get_time_ms()
{
return millis();
}
// let's do this in addition, have a LED on a pin to visually see some action
#define BLINK_PIN PA0
uint8_t blink = 0;
#define LED_TOGGLE {digitalWrite(BLINK_PIN, (blink) ? HIGH : LOW); blink = (blink) ? 0 : 1;}
//------------------------------
// Include the fastMavlink library C code
//------------------------------
// For this example, common.xml is a good choice for the dialect,
// but choose whichever dialect you prefer.
// The "..../common/common.h" is the way how fastMavlink wants it to be.
// If you would do ".../common/mavlink.h" like you would for the pymavlink-mavgen
// library, you would enable fastMavlink's pymavlink-mavgen mimicry. The code would
// still work, but we want to do fastMavlink here :).
#include "c_library/common/common.h"
// Arduino IDE does some automatic changes to the code. This prevents it inserting
// a function prototype in the wrong place.
void handleMessage(fmav_message_t* msg);
//------------------------------
// Here it comes, the example code
//------------------------------
// Define the parameters
// FASTMAVLINK_PARAM_NUM and the fmav_param_list[] must be defined
// before fastmavlink_parameters.h is included.
// The parameters are not stored permanently, that's beyond the reach of this
// example.
uint8_t Pu8 = 100;
int8_t Ps8 = -2;
uint16_t Pu16 = 500;
int16_t Ps16 = 123;
uint32_t Pu32 = 500;
int32_t Ps32 = 123;
float Pf = 0.011;
// We use a macro generator to create fmav_param_list[]
#define FASTMAVLINK_PARAM_LIST \
X( Pu8, UINT8, P_U8)\
X( Ps8, INT8, P_S8)\
X( Pu16, UINT16, P_U16)\
X( Ps16, INT16, P_S16)\
X( Pu32, UINT32, P_U32)\
X( Ps32, INT32, P_S32)\
X( Pf, REAL32, P_FLOAT)\
#define UINT8 uint8_t
#define INT8 int8_t
#define UINT16 uint16_t
#define INT16 int16_t
#define UINT32 uint32_t
#define INT32 int32_t
#define REAL32 float
#define FASTMAVLINK_PARAM_NUM 7
const fmav_param_entry_t fmav_param_list[FASTMAVLINK_PARAM_NUM] = {
#define X(p,t,n) {(t*)&(p), MAV_PARAM_TYPE_##t, #n },
FASTMAVLINK_PARAM_LIST
#undef X
};
#include "c_library/lib/fastmavlink_parameters.h"
// Helpers to send the parameter list
uint8_t send_param_value = 0;
uint16_t send_param_value_index;
void param_send_param_value_trigger(uint16_t index)
{
send_param_value = 1;
send_param_value_index = index;
}
#define PARAM_SEND_STREAM_RATE_MS 200
uint16_t param_send_next_index = FASTMAVLINK_PARAM_NUM;
uint32_t param_send_tlast_ms = 0;
void param_send_stream_start(void)
{
param_send_next_index = 0;
param_send_tlast_ms = get_time_ms();
}
void param_send_stream_do(void)
{
if (param_send_next_index >= FASTMAVLINK_PARAM_NUM) return; // nothing to do
uint32_t tnow_ms = get_time_ms();
if ((tnow_ms - param_send_tlast_ms) > PARAM_SEND_STREAM_RATE_MS) {
param_send_param_value_trigger(param_send_next_index);
param_send_tlast_ms += PARAM_SEND_STREAM_RATE_MS;
param_send_next_index++;
}
}
// Set things up
// Much of this you have seen aleady in the example "One Link - One Component".
uint8_t my_sysid = 1; // match it to the sys id of your autopilot
uint8_t my_compid = MAV_COMP_ID_PERIPHERAL; // match it to what your component wants to be
fmav_status_t status;
fmav_message_t msg;
uint8_t tx_buf[296];
// some variables we need
uint8_t send_statustext = 0;
uint32_t tlast_ms = 0;
// send the "Hello World" STATUSTEXT message
// returns 1 if successful, 0 else
uint8_t sendStatustext(void)
{
fmav_statustext_t payload;
payload.severity = MAV_SEVERITY_INFO;
memset(&payload.text, 0, FASTMAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN);
memcpy(&payload.text, "Hello World", 11);
payload.id = 0;
payload.chunk_seq = 0;
uint16_t count = fmav_msg_statustext_encode_to_frame_buf(tx_buf, my_sysid, my_compid, &payload, &status);
if (serial_has_space(count)) {
serial_write_buf(tx_buf, count);
return 1; // we have successfully send it, so tell that
}
return 0;
}
// send a HEARTBEAT message
// returns 1 if successful, 0 else
uint8_t sendHeartbeat(void)
{
uint16_t count = fmav_msg_heartbeat_pack_to_frame_buf(
tx_buf, my_sysid, my_compid,
MAV_TYPE_GENERIC, MAV_AUTOPILOT_INVALID, MAV_MODE_FLAG_SAFETY_ARMED, 0, MAV_STATE_ACTIVE,
&status);
if (serial_has_space(count)) {
serial_write_buf(tx_buf, count);
return 1; // we have successfully send it, so tell that
}
return 0;
}
// send a PARAM_VALUE message
// returns 1 if successful, 0 else
uint8_t sendParamValue(uint16_t index)
{
// For sending a parameter entry it is most convenient to us the xxx_encode()
// set of functions.
fmav_param_value_t payload;
if (!fmav_param_get_param_value(&payload, index)) return 0;
uint16_t count = fmav_msg_param_value_encode_to_frame_buf(tx_buf, my_sysid, my_compid, &payload, &status);
if (serial_has_space(count)) {
serial_write_buf(tx_buf, count);
return 1;
}
return 0;
}
// our message handler
void handleMessage(fmav_message_t* msg)
{
switch (msg->msgid) {
case FASTMAVLINK_MSG_ID_HEARTBEAT: {
fmav_heartbeat_t payload;
fmav_msg_heartbeat_decode(&payload, msg);
// un-comment this if you want to detect the flight controller
// if (payload.autopilot != MAV_AUTOPILOT_INVALID && msg->compid == MAV_COMP_ID_AUTOPILOT1) {
// un-comment this if you want to detect the GCS
if (payload.autopilot == MAV_AUTOPILOT_INVALID && payload.type == MAV_TYPE_GCS) {
send_statustext = 1;
}
}break;
// Here they come, the handlers for the PARAM messages
case FASTMAVLINK_MSG_ID_PARAM_REQUEST_READ:{
fmav_param_request_read_t payload;
fmav_msg_param_request_read_decode(&payload, msg);
uint16_t index;
if (fmav_param_do_param_request_read(&index, &payload)) {
param_send_param_value_trigger(index);
}
}break;
case FASTMAVLINK_MSG_ID_PARAM_REQUEST_LIST: {
param_send_stream_start();
}break;
case FASTMAVLINK_MSG_ID_PARAM_SET:{
fmav_param_set_t payload;
fmav_msg_param_set_decode(&payload, msg);
uint16_t index;
if (fmav_param_do_param_set(&index, &payload)) {
fmav_param_set_value(index, payload.param_value);
param_send_param_value_trigger(index);
}
}break;
}
}
// this should be called repeatedly
void spinOnce(void)
{
// let's first check and do incoming messages
uint16_t available = serial_available();
for (uint16_t i = 0; i < available; i++) {
uint8_t c;
serial_read_char(&c);
uint8_t res = fmav_parse_to_msg(&msg, &status, c);
if (res == FASTMAVLINK_PARSE_RESULT_OK) {
if (fmav_msg_is_for_me(my_sysid, my_compid, &msg)) {
handleMessage(&msg);
}
}
}
// let's do params if stream requested
param_send_stream_do();
// let's now send PARAM_VALUE message, if it has been triggered, and no other message is pending
if (send_param_value) {
if (sendParamValue(send_param_value_index)) {
send_param_value = 0; // we have successfully send it, so clear that flag
}
}
// let's now send a STATUSTEXT message, if it has been triggered
if (send_statustext) {
if (sendStatustext()) {
send_statustext = 0; // we have successfully send it, so clear that flag
}
}
// let's now send a HEARTBEAT message, to tell the world we exist
uint32_t tnow_ms = get_time_ms();
if ((tnow_ms - tlast_ms) > 1000) {
if (sendHeartbeat()) {
tlast_ms += 1000; // we have successfully send it, so do it again later
LED_TOGGLE;
}
}
}
//------------------------------
// Default Arduino setup() and loop() functions
//------------------------------
void setup()
{
SERIAL.begin(SERIAL_BAUD);
pinMode(BLINK_PIN, OUTPUT);
fmav_init(); // let's always call it, even if it currently may not do anything
}
void loop()
{
spinOnce();
}