Restart hub scans that find nothing
A Legoino scan that never locates its hub ends quietly - isConnecting() never goes true, so the old code left 'initialised' set and never touched retryAt. That hub then sat on a dead scan until the board was power cycled, which is why first connects needed several attempts. Adds scanExpiresAt per hub and restarts the scan after 12s. Also documents the startup order and the LED grounding in the header.
This commit is contained in:
+30
-5
@@ -17,11 +17,19 @@
|
|||||||
* TX GPIO17 -> RX GPIO16 on transmitter
|
* TX GPIO17 -> RX GPIO16 on transmitter
|
||||||
* GND -> GND (mandatory - common ground)
|
* GND -> GND (mandatory - common ground)
|
||||||
*
|
*
|
||||||
* LED circuits (see LED_1_PIN / LED_2_PIN below):
|
* LED circuits - both on THIS board, returning to THIS board's GND:
|
||||||
* GPIO25 -> resistor -> LED pair -> GND
|
* GPIO25 -> resistor -> LED pair -> GND
|
||||||
* GPIO26 -> resistor -> LED pair -> GND
|
* GPIO26 -> resistor -> LED pair -> GND
|
||||||
* Pins output 3.3V, not 3V. ~12mA per pin is comfortable, 40mA is the hard
|
* Pins output 3.3V, not 3V. ~12mA per pin is comfortable, 40mA is the hard
|
||||||
* limit. Anything drawing more than ~20mA per circuit needs a transistor.
|
* limit. Anything drawing more than ~20mA per circuit needs a transistor.
|
||||||
|
* Do not tap the LED return off the UART ground wire to the other board -
|
||||||
|
* that reference needs to stay clean.
|
||||||
|
*
|
||||||
|
* STARTUP ORDER:
|
||||||
|
* Wake BOTH hubs with their green buttons and check both are blinking,
|
||||||
|
* THEN power this board. hub1 is only serviced once hub0 is connected, so a
|
||||||
|
* sleeping hub0 blocks the whole sequence. Hubs stop advertising after a
|
||||||
|
* couple of minutes idle.
|
||||||
*
|
*
|
||||||
* ARMS ARE POSITION CONTROLLED:
|
* ARMS ARE POSITION CONTROLLED:
|
||||||
* The triggers set an ANGLE, not a power level. Trigger released holds the
|
* The triggers set an ANGLE, not a power level. Trigger released holds the
|
||||||
@@ -125,6 +133,10 @@ static const unsigned long HUB_MIN_GAP_MS = 25; // per hub, ~40 cmd/sec
|
|||||||
static const unsigned long LINK_TIMEOUT_MS = 400; // failsafe
|
static const unsigned long LINK_TIMEOUT_MS = 400; // failsafe
|
||||||
static const unsigned long RECONNECT_GAP_MS = 2000;
|
static const unsigned long RECONNECT_GAP_MS = 2000;
|
||||||
|
|
||||||
|
// A Legoino scan that never finds its hub expires silently, leaving the hub
|
||||||
|
// stuck waiting forever. This is how long we give it before starting over.
|
||||||
|
static const unsigned long SCAN_TIMEOUT_MS = 12000;
|
||||||
|
|
||||||
static const int LINK_RX_PIN = 16;
|
static const int LINK_RX_PIN = 16;
|
||||||
static const int LINK_TX_PIN = 17;
|
static const int LINK_TX_PIN = 17;
|
||||||
static const long LINK_BAUD = 115200;
|
static const long LINK_BAUD = 115200;
|
||||||
@@ -139,7 +151,8 @@ struct HubLink {
|
|||||||
const char *label;
|
const char *label;
|
||||||
bool initialised;
|
bool initialised;
|
||||||
unsigned long retryAt;
|
unsigned long retryAt;
|
||||||
unsigned long lastCmdAt; // per-hub rate limit, shared across its ports
|
unsigned long lastCmdAt; // per-hub rate limit, shared across ports
|
||||||
|
unsigned long scanExpiresAt; // when to give up on the current scan
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PortState {
|
struct PortState {
|
||||||
@@ -161,8 +174,8 @@ struct Frame {
|
|||||||
// ================================================================= globals
|
// ================================================================= globals
|
||||||
|
|
||||||
static HubLink gHubs[2] = {
|
static HubLink gHubs[2] = {
|
||||||
{Lpf2Hub(), HUB0_ADDR, "hub0", false, 0, 0},
|
{Lpf2Hub(), HUB0_ADDR, "hub0", false, 0, 0, 0},
|
||||||
{Lpf2Hub(), HUB1_ADDR, "hub1", false, 0, 0},
|
{Lpf2Hub(), HUB1_ADDR, "hub1", false, 0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Indexes follow physical ports, not functions:
|
// Indexes follow physical ports, not functions:
|
||||||
@@ -280,6 +293,10 @@ static void stopEverything() {
|
|||||||
// immediately afterwards isConnected() and isConnecting() are both still
|
// immediately afterwards isConnected() and isConnecting() are both still
|
||||||
// false. Guarding on those alone re-enters NimBLEDevice::init() thousands of
|
// false. Guarding on those alone re-enters NimBLEDevice::init() thousands of
|
||||||
// times a second and the Bluetooth controller aborts.
|
// times a second and the Bluetooth controller aborts.
|
||||||
|
//
|
||||||
|
// The scanExpiresAt deadline exists because a scan that finds nothing just
|
||||||
|
// ends quietly - isConnecting() never goes true, so without a timeout the hub
|
||||||
|
// sits on a dead scan until the board is power cycled.
|
||||||
static void serviceHub(HubLink &hl) {
|
static void serviceHub(HubLink &hl) {
|
||||||
if (hl.hub.isConnected()) return;
|
if (hl.hub.isConnected()) return;
|
||||||
|
|
||||||
@@ -296,10 +313,18 @@ static void serviceHub(HubLink &hl) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hl.initialised && millis() >= hl.scanExpiresAt) {
|
||||||
|
Serial.printf("[%s] scan timed out, restarting\n", hl.label);
|
||||||
|
hl.initialised = false;
|
||||||
|
hl.retryAt = millis() + RECONNECT_GAP_MS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!hl.initialised && millis() >= hl.retryAt) {
|
if (!hl.initialised && millis() >= hl.retryAt) {
|
||||||
Serial.printf("[%s] scanning for %s\n", hl.label, hl.addr);
|
Serial.printf("[%s] scanning for %s\n", hl.label, hl.addr);
|
||||||
hl.hub.init(std::string(hl.addr));
|
hl.hub.init(std::string(hl.addr));
|
||||||
hl.initialised = true;
|
hl.initialised = true;
|
||||||
|
hl.scanExpiresAt = millis() + SCAN_TIMEOUT_MS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +446,7 @@ void setup() {
|
|||||||
digitalWrite(LED_2_PIN, LOW);
|
digitalWrite(LED_2_PIN, LOW);
|
||||||
|
|
||||||
Serial.println("LEGO hub receiver starting (Johnny 5 Evolved)");
|
Serial.println("LEGO hub receiver starting (Johnny 5 Evolved)");
|
||||||
Serial.println("Both arms must be DOWN before hub1 connects");
|
Serial.println("Wake both hubs first. Both arms must be DOWN.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
Reference in New Issue
Block a user