36
36
37
37
#include < string.h>
38
38
39
- #define SAMPLING_TIMEOUT_US 500
39
+ #define SAMPLING_TIMEOUT_US 1000 // us
40
+ #define RESAMPLING_THRESHOLD 2500 // us, 400Hz freq = 2500us period
41
+ #define RESAMPLING_SWITCHING_THRESHOLD 200 // us
42
+ #define MODE_CHANGE_DELAY 100 // ms
40
43
41
44
static const stm32_usart_t fsUSART = {
42
45
.USARTx = FLYSKY_HALL_SERIAL_USART,
@@ -68,13 +71,14 @@ static uint8_t _fs_hall_command[8] __DMA;
68
71
static void * _fs_usart_ctx = nullptr ;
69
72
70
73
static volatile bool _fs_gimbal_detected;
71
- static uint8_t _fs_gimbal_version = GIMBAL_V1;
72
- static uint8_t _fs_gimbal_mode = V1_MODE;
73
- static uint8_t _fs_gimbal_mode_cmd = V1_MODE;
74
- static bool _fs_gimbal_read_finished = true ;
75
- static uint32_t _fs_lastReadTick = 0 ;
76
- static uint32_t _fs_readTick;
77
- static uint32_t _fs_sync_period = 0 ;
74
+ static uint8_t _fs_gimbal_version;
75
+ static uint8_t _fs_gimbal_mode;
76
+ static uint8_t _fs_gimbal_mode_change;
77
+ static uint32_t _fs_gimbal_last_mode_change_tick;
78
+ static bool _fs_gimbal_cmd_finished;
79
+ static uint32_t _fs_gimbal_lastReadTick;
80
+ static uint32_t _fs_gimbal_readTick;
81
+ static volatile uint32_t _fs_gimbal_sync_period;
78
82
79
83
static int _fs_get_byte (uint8_t * data)
80
84
{
@@ -146,6 +150,11 @@ static void _fs_parse(STRUCT_HALL *hallBuffer, unsigned char ch)
146
150
147
151
void _fs_send_cmd (uint8_t id, uint8_t payload)
148
152
{
153
+ if (!_fs_gimbal_cmd_finished) {
154
+ // Skip command when last command not finished
155
+ return ;
156
+ }
157
+
149
158
_fs_hall_command[0 ] = FLYSKY_HALL_PROTOLO_HEAD;
150
159
_fs_hall_command[1 ] = id;
151
160
_fs_hall_command[2 ] = 0x01 ;
@@ -156,7 +165,9 @@ void _fs_send_cmd(uint8_t id, uint8_t payload)
156
165
_fs_hall_command[4 ] = crc & 0xff ;
157
166
_fs_hall_command[5 ] = crc >>8 & 0xff ;
158
167
168
+ _fs_gimbal_cmd_finished = false ;
159
169
STM32SerialDriver.sendBuffer (_fs_usart_ctx, _fs_hall_command, 6 );
170
+ // TRACE("Flysky Gimbal: Sent command, id = %d, payload = %d", id, payload);
160
171
}
161
172
162
173
void _fs_cmd_get_version ()
@@ -166,12 +177,7 @@ void _fs_cmd_get_version()
166
177
167
178
void _fs_cmd_set_mode (V2_GIMBAL_MODE mode)
168
179
{
169
- if (_fs_gimbal_mode != _fs_gimbal_mode_cmd) {
170
- // Last command not responsed yet
171
- return ;
172
- }
173
-
174
- _fs_gimbal_mode_cmd = mode;
180
+ _fs_gimbal_mode_change = mode;
175
181
_fs_send_cmd (0x41 , mode);
176
182
}
177
183
@@ -202,12 +208,13 @@ static void flysky_gimbal_loop(void*)
202
208
case TRANSFER_DIR_RFMODULE:
203
209
int16_t * p_values = (int16_t *)HallProtocol.data ;
204
210
if (HallProtocol.hallID .hall_Id .packetID == FLYSKY_PACKET_CHANNEL_ID) {
211
+ _fs_gimbal_cmd_finished = true ;
205
212
uint16_t * adcValues = getAnalogValues ();
206
213
for (uint8_t i = 0 ; i < 4 ; i++) {
207
214
adcValues[i] = FLYSKY_OFFSET_VALUE - p_values[i];
208
215
}
209
- _fs_gimbal_read_finished = true ;
210
216
} else if (HallProtocol.hallID .hall_Id .packetID == FLYSKY_PACKET_VERSION_ID) {
217
+ _fs_gimbal_cmd_finished = true ;
211
218
uint16_t minorVersion = p_values[6 ];
212
219
uint16_t majorVersion = p_values[7 ];
213
220
if (majorVersion == 2 && minorVersion >= 1 ) {
@@ -216,7 +223,9 @@ static void flysky_gimbal_loop(void*)
216
223
_fs_cmd_set_mode (SYNC_RESAMPLING);
217
224
}
218
225
} else if (HallProtocol.hallID .hall_Id .packetID == FLYSKY_PACKET_MODE_ID) {
219
- _fs_gimbal_mode = _fs_gimbal_mode_cmd;
226
+ _fs_gimbal_cmd_finished = true ;
227
+ _fs_gimbal_mode = _fs_gimbal_mode_change;
228
+ TRACE (" Flysky Gimbal: Mode changed successfully, mode = %d" , _fs_gimbal_mode);
220
229
}
221
230
break ;
222
231
}
@@ -242,7 +251,15 @@ bool flysky_gimbal_init(bool force)
242
251
.polarity = ETX_Pol_Normal,
243
252
};
244
253
254
+ // Init variables
245
255
_fs_gimbal_detected = force;
256
+ _fs_gimbal_version = GIMBAL_V1;
257
+ _fs_gimbal_mode = V1_MODE;
258
+ _fs_gimbal_last_mode_change_tick = 0 ;
259
+ _fs_gimbal_cmd_finished = true ;
260
+ _fs_gimbal_lastReadTick = 0 ;
261
+ _fs_gimbal_sync_period = 0 ;
262
+
246
263
_fs_usart_ctx = STM32SerialDriver.init (REF_STM32_SERIAL_PORT (FSGimbal), &cfg);
247
264
STM32SerialDriver.setIdleCb (_fs_usart_ctx, flysky_gimbal_loop, 0 );
248
265
@@ -266,26 +283,33 @@ bool flysky_gimbal_init(bool force)
266
283
void flysky_gimbal_start_read ()
267
284
{
268
285
if (_fs_sync_enabled ()) {
269
- if (_fs_gimbal_read_finished) {
270
- _fs_gimbal_read_finished = false ;
271
- _fs_lastReadTick = _fs_readTick;
272
- _fs_readTick = timersGetUsTick ();
273
- if (_fs_lastReadTick != 0 ) {
274
- _fs_sync_period = _fs_readTick - _fs_lastReadTick;
286
+ _fs_gimbal_lastReadTick = _fs_gimbal_readTick;
287
+ _fs_gimbal_readTick = timersGetUsTick ();
288
+ if (_fs_gimbal_lastReadTick != 0 ) {
289
+ _fs_gimbal_sync_period = _fs_gimbal_readTick - _fs_gimbal_lastReadTick;
290
+ uint32_t tick = timersGetMsTick ();
291
+ if (tick - _fs_gimbal_last_mode_change_tick >= MODE_CHANGE_DELAY) {
292
+ // Prevent mode change too often
293
+ _fs_gimbal_last_mode_change_tick = tick;
294
+ if (_fs_gimbal_mode == SYNC_SAMPLING && _fs_gimbal_sync_period < RESAMPLING_THRESHOLD) {
295
+ _fs_cmd_set_mode (SYNC_RESAMPLING);
296
+ } else if (_fs_gimbal_mode == SYNC_RESAMPLING && _fs_gimbal_sync_period >= RESAMPLING_THRESHOLD + RESAMPLING_SWITCHING_THRESHOLD) {
297
+ _fs_cmd_set_mode (SYNC_SAMPLING);
298
+ }
275
299
}
276
- _fs_cmd_start_read ();
277
- }
300
+ }
301
+ _fs_cmd_start_read ();
278
302
}
279
303
}
280
304
281
305
void flysky_gimbal_wait_completion ()
282
306
{
283
307
if (_fs_sync_enabled ()) {
284
308
auto timeout = timersGetUsTick ();
285
- while (!_fs_gimbal_read_finished ) {
309
+ while (!_fs_gimbal_cmd_finished ) {
286
310
// busy wait
287
311
if ((uint32_t )(timersGetUsTick () - timeout) >= SAMPLING_TIMEOUT_US) {
288
- TRACE (" Gimbal timeout" );
312
+ // TRACE("Gimbal timeout");
289
313
return ;
290
314
}
291
315
}
0 commit comments