Proxymow Mower Modules

schematic.py

As described in setup, this module defines all the pins that the hardware is connected to. In essence, the Proxymow Mower is a very simple machine. It uses 2 output pins per motor to send Pulse Width Modulated signals to the L298N Motor Driver. It uses the i2c bus to control 2 cutter relays, and monitors battery voltage on the lone ADC channel.

Wiring Diagram

As mentioned elsewhere, no additional hardware is required to get a Hybrid Mower up and running. Just connect the micro-USB socket to USB on a PC and follow the setup instructions.

Floating Device

main.py

This is a very simple module that gets called at power-up. It imports schematic to stabilise the io pins, allocates some buffer space for exceptions, and finally imports mower.

mower.py

This module is responsible for listening out for commands from the server. It recognises synchronous commands that start with a '>' like >get_telemetry(), and asynchronous commands like sweep(). Synchronous commands block while the command is executing, awaiting the results to send back as a response. Asynchronous commands are non-blocking. They reply with an ACK acknowledgement, before carrying out their function at leisure. Multiple commands separated by a '!' are supported.

The mower module does not implement any api command functions itself, but passes them onto umotion_lib. It does however implement a self-watchdog feature. As a robot mower it expects to be sent regular commands to tell it what to do. If it does not receive these commands in a timely manner, then either it has competed its job, or there is a communications problem. In such situations the module will initially perform checks for better Wi-Fi before finally resetting itself.

The status of the mower listener loop is exposed with the led() library function, which by default is wired to the internal led, but can be reflected to an external led on GPIO16 (D0) if required.

umotion_lib.py

This module is responsible for implementing the command api of the mower. For compatibility with Proxymow Server, it implements the following functions:

  • sweep()
  • get_telemetry()
  • cutter()
  • stop()
  • set_priority_essid()

sweep(left_speed, right_speed, duration)

Proxymow Mower only works with 2-wheeled robots employing differential steering. sweep is the universal movement function that propels the robot forwards, backwards and rotates it clockwise and counter-clockwise. The implementation of sweep is the responsibility of the artic.py module.

get_telemetry()

The purpose of this function is to assemble key data about the state of the mower, and return it as a json dictionary.

{"analogs": [305, 295, -1], "cutter1": 0, "cutter2": 0, "ssid": "vssid", "rssi": -25, "dist": 5, "free-mb": 100, "last-update": 297201222.9516506, "last-cmd": -1}

The following items are included:

  • analogs - a variable length list, but typically...
    • adc - current reading
    • loaded - minimum powered reading
  • cutters
    • cutter1 - cutter 1 state
    • cutter2 - cutter 2 state
  • timing
    • last-update - mower's current timestamp
  • Wi-Fi
    • priority-essid - any enrolled hotspot name
    • essid - current hotspot
    • rssi - Received Signal Strength Indicator
    • dist - estimated distance from rssi
    • last-scan - last time Wi-Fi scan was completed
    • qual-essids - any better qualifying hotspots
  • memory
    • free-mb

cutter(addr, mode)

Proxymow Mower supports up to 2 cutters. Experiments with various robot form factors suggest that rotation is inefficient. For up-to-the-edge mowing the best approach is to shuttle back and forth across a rectangular lawn, or shuttle the spokes of an irregular shaped lawn. This requires 2 cutters, although only one needs to be active at any time.

The cutter function is optimised to control one or both cutters in one execution. If the mode is set to -1, then addr is a binary address i.e. 00, 01, 10, 11. This allows any combination of on/off for both cutters. If the mode is set to 0 then the addr represents a mask that is used to clear either or both cutters. If the mode is set to 1 then the addr represents a mask that is used to set either or both cutters.

For example, at the start of a shuttle path we need to turn on 1 and turn off 2:

    cutter( 1, -1 )

At the end of a shuttle path we need to turn on 2 and turn off 1:

    cutter( 2, -1 )

The Proxymow Server needs to control cutter 1 independently:

    cutter( 1, 1 ) and cutter( 0, 1 )

stop()

This is a composite command that turns off the cutters and halts any motion. It is used for Emergency Stop purposes.

set_priority_essid(essid)

The default value for PRIORITY_ESSID is None, but if this function is called with the name of a hotspot, then the mower will disconnect from its current hotspot and switch to the one supplied, providing it is a qualifying name from PREFERRED_ESSIDS. This is only a temporary measure, until the next power cycle.

artic.py

This module is responsible for interpreting the sweep commands and powering the drive motors. Sweep operations are split up into chunks, orchestrated with a periodic timer. There are a number of reasons for this:

  • Multi-threading is avoided without blocking
  • New sweep commands can be accepted, whilst existing one is running
  • Same architecture supports Hybrid mowers that need fine-grained location tracking
  • Future proofing for enhancements such as wheel encoders and a gyroscope

sweep determines what pwm objects it needs from the relative speeds, and then calls activate(). activate splits up the duration into chunks, starts the motion, and initialises the periodic timer. The timer callback function is motivate(), which updates the pwm duties or terminates the motion as appropriate.

shared_utils.py

This module contains functions that calculate the new pose based on incoming sweep commands. This functionality is only needed for Hybrid mowers. The module is mirrored with the same in Proxymow Server, which requires the same calculations.

utils.py

This module manages communications, primarily locating and connecting to a Wi-Fi hotspot. Good Wi-Fi coverage of the mowing arena is key to successful operation, whether that is provided by Wi-Fi extenders or the Server Node itself. Mowers may be utilised on multiple lawns, and will probably need to connect to different hotspots. Devices have a penchant for remembering their connection details, and re-connecting when powered up.

To resolve this dilemma, utils uses pattern matching of hotspot names. Providing the hotspot identifier starts with the PREFERRED_ESSIDS entry then the hotspot will qualify. This means that hotspots HotSpot-001, HotSpot-002, etc. will all qualify if the PREFERRED_ESSIDS entry is 'HotSpot', but they would have to have the same password.

The best way to see what decisions the application is making when connecting to Wi-Fi is to view the REPL trace, which prints a table of Hotspots. Make sure LOG_PRINT_ENABLED is True and there aren't any active clients sending commands to the mower. Then the self-watchdog will trigger a scan of available Wi-Fi Access Points and the results will be tabulated.

Hotspot Table