Skip to content

Commit 933bc29

Browse files
committed
Handle motor stalls and fix run_to_position properly for real
1 parent 46e47b4 commit 933bc29

File tree

9 files changed

+196
-256
lines changed

9 files changed

+196
-256
lines changed

include/device.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,10 @@ extern int device_push_mode(PyObject *self, int mode);
9595
/* Restore the previously pushed mode */
9696
extern int device_pop_mode(PyObject *self);
9797

98+
/* Ensures that the initialisation that cannot be done in the background
99+
* has in fact been done.
100+
*/
101+
extern int device_ensure_mode_info(PyObject *self);
102+
98103

99104
#endif /* RPI_STRAWBERRY_DEVICE_H_INCLUDED */

include/motor-settings.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@
3434
#define MOTOR_STOP_HOLD 2
3535
#define MOTOR_STOP_USE_DEFAULT 3
3636

37-
#define DIRECTION_CLOCKWISE 0
38-
#define DIRECTION_ANTICLOCKWISE 1
39-
#define DIRECTION_SHORTEST 2
40-
4137
/* Values passed to the cmd functions */
4238
#define STOP_FLOAT 0
4339
#define STOP_HOLD 126

include/motor.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define PY_SSIZE_T_CLEAN
2020
#include <Python.h>
2121

22+
#include <stdint.h>
2223
#include "device.h"
2324

2425
extern int motor_modinit(void);
@@ -42,9 +43,24 @@ extern void motor_detach(PyObject *self);
4243
(dt) == ID_STONE_GREY_MOTOR_MEDIUM || \
4344
(dt) == ID_STONE_GREY_MOTOR_LARGE)
4445

45-
/* Read the position of the motor */
46-
extern int motor_get_position(PyObject *self,
47-
long *ppos_from_zero,
48-
long *ppos_from_preset);
46+
/* Read the position of the motor relative to the preset mark */
47+
extern int motor_get_position(PyObject *self, long *pposition);
48+
49+
/* Set the "preset" marker position relative to zero */
50+
extern int motor_set_preset(PyObject *self, long position);
51+
52+
/* Updates the "preset" marker (for MotorPair.preset()) */
53+
extern void motor_update_preset(PyObject *self, long position);
54+
55+
/* Ensure foregrounded initialisation is done (for MotorPairs) */
56+
extern int motor_ensure_mode_info(PyObject *self);
57+
58+
/* Get the offset to use when determining absolute motor positions */
59+
/* NB: the mode information must have been acquired at some point
60+
* before calling this. This is taken care of at init time for
61+
* MotorPairs, but if you call this function from any other situation
62+
* you should first call motor_ensure_mode_info()
63+
*/
64+
extern int32_t motor_get_position_offset(PyObject *self);
4965

5066
#endif /* RPI_STRAWBERRY_MOTOR_H_INCLUDED */

include/port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ extern PyObject *port_get_device(PyObject *port);
7373
extern PyObject *ports_get_value_dict(PyObject *portset);
7474
extern PyObject *port_get_motor(PyObject *port); /* Returns new reference */
7575
extern int port_is_motor(PyObject *port); /* True if a motor is connected */
76+
extern int port_set_motor_preset(PyObject *port, long position);
7677

7778
/* The following are called only from the callback thread */
7879
extern int port_handle_callback(uint8_t port_id, uint8_t event);

src/cmd.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -625,33 +625,36 @@ static int wait_for_complete_feedback(uint8_t port_id, uint8_t *response)
625625
free(buffer);
626626
return -1;
627627
}
628-
if (buffer[0] != 5 ||
629-
buffer[2] != TYPE_PORT_OUTPUT_FEEDBACK ||
630-
buffer[3] != port_id)
631-
{
632-
free(buffer);
633-
PyErr_SetString(hub_protocol_error,
634-
"Unexpected reply to Output command");
635-
return -1;
636-
}
637628
if (buffer[2] == TYPE_GENERIC_ERROR)
638629
{
639630
handle_generic_error(TYPE_PORT_OUTPUT, buffer);
640631
free(buffer);
641632
return -1;
642633
}
643-
if ((buffer[4] & 0x04) != 0)
634+
if (buffer[0] == 5 &&
635+
buffer[2] == TYPE_PORT_OUTPUT_FEEDBACK &&
636+
buffer[3] == port_id)
644637
{
645-
/* "Current Command(s) Discarded" bit set */
646-
free(buffer);
647-
PyErr_SetString(hub_protocol_error, "Port busy");
648-
return -1;
649-
}
650-
if ((buffer[4] & 0x02) != 0)
651-
{
652-
/* "Current command(s) Complete" bit set */
653-
free(buffer);
654-
return 0;
638+
if ((buffer[4] & 0x20) != 0)
639+
{
640+
/* The motor has stalled! */
641+
free(buffer);
642+
PyErr_SetString(hub_protocol_error, "Motor stalled");
643+
return -1;
644+
}
645+
if ((buffer[4] & 0x04) != 0)
646+
{
647+
/* "Current Command(s) Discarded" bit set */
648+
free(buffer);
649+
PyErr_SetString(hub_protocol_error, "Port busy");
650+
return -1;
651+
}
652+
if ((buffer[4] & 0x02) != 0)
653+
{
654+
/* "Current command(s) Complete" bit set */
655+
free(buffer);
656+
return 0;
657+
}
655658
}
656659
free(buffer);
657660
}

src/device.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "device.h"
2323
#include "port.h"
24+
#include "motor.h"
2425

2526
/**
2627
@@ -258,6 +259,11 @@ static default_mode_t default_modes[NUM_DEFAULT_MODES] = {
258259
#undef MODE
259260

260261

262+
/* Forward declarations */
263+
static int get_value(DeviceObject *self);
264+
static int extract_value(DeviceObject *self, uint8_t index, long *pvalue);
265+
266+
261267
static default_mode_t *
262268
get_default_mode(uint16_t id)
263269
{
@@ -526,21 +532,40 @@ get_mode_info(DeviceObject *device, uint8_t port_id)
526532
default_mode->mode_mask) == default_mode->mode_mask)
527533
{
528534
/* This has all the modes we need */
529-
return set_combi_mode(device, combi_index,
530-
default_mode->mode_list,
531-
default_mode->num_modes);
535+
if (set_combi_mode(device, combi_index,
536+
default_mode->mode_list,
537+
default_mode->num_modes) < 0)
538+
return -1;
539+
break;
532540
}
533541
}
534-
/* We can't find a suitable combi-mode. Oh well */
542+
543+
/* Assert that any formally recognised motor is set up to Get
544+
* the Speed, Position, Absolute Position and Power, and needs
545+
* to have its delta (preset) calculated.
546+
*/
547+
if (motor_is_motor(device->type_id))
548+
{
549+
long position_from_zero;
550+
551+
if (get_value(device) < 0)
552+
return -1;
553+
if (extract_value(device, 2, &position_from_zero) < 0)
554+
return -1;
555+
if (port_set_motor_preset(device->port, position_from_zero) < 0)
556+
return -1;
557+
}
535558
}
536559

537560
return 0;
538561
}
539562

540563

541-
static int
542-
ensure_mode_info(DeviceObject *device)
564+
int
565+
device_ensure_mode_info(PyObject *self)
543566
{
567+
DeviceObject *device = (DeviceObject *)self;
568+
544569
if ((device->flags & DO_FLAGS_GOT_MODE_INFO) == 0)
545570
return get_mode_info(device, port_get_id(device->port));
546571

@@ -562,7 +587,7 @@ Device_mode(PyObject *self, PyObject *args)
562587
}
563588
if (!PyArg_ParseTuple(args, "|OO:mode", &arg1, &arg2))
564589
return NULL;
565-
if (ensure_mode_info(device) < 0)
590+
if (device_ensure_mode_info(device) < 0)
566591
return NULL;
567592

568593
if (arg1 == NULL)
@@ -946,7 +971,7 @@ Device_get(PyObject *self, PyObject *args)
946971
}
947972
}
948973

949-
if (ensure_mode_info(device) < 0)
974+
if (device_ensure_mode_info(device) < 0)
950975
return NULL;
951976
if (!device->is_unreported)
952977
{
@@ -1530,7 +1555,7 @@ int device_is_in_mode(PyObject *self, int mode)
15301555
DeviceObject *device = (DeviceObject *)self;
15311556
uint8_t i;
15321557

1533-
if (ensure_mode_info(device) < 0)
1558+
if (device_ensure_mode_info(device) < 0)
15341559
return -1;
15351560
if (device->current_mode == mode)
15361561
return 1;
@@ -1608,7 +1633,7 @@ int device_push_mode(PyObject *self, int mode)
16081633
{
16091634
DeviceObject *device = (DeviceObject *)self;
16101635

1611-
if (ensure_mode_info(device) < 0)
1636+
if (device_ensure_mode_info(device) < 0)
16121637
return -1;
16131638

16141639
if (mode < 0 || mode >= device->num_modes)
@@ -1638,7 +1663,7 @@ int device_pop_mode(PyObject *self)
16381663
{
16391664
DeviceObject *device = (DeviceObject *)self;
16401665

1641-
if (ensure_mode_info(device) < 0)
1666+
if (device_ensure_mode_info(device) < 0)
16421667
return -1;
16431668

16441669
if (device->saved_current_mode == MODE_IS_COMBI)

0 commit comments

Comments
 (0)