Skip to content
This repository has been archived by the owner on Jun 11, 2021. It is now read-only.
/ MiP-Capi Public archive

C API for the WowWee MiP self-balancing robot.

Notifications You must be signed in to change notification settings

adamgreen/MiP-Capi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Archived - June 10th, 2021

This project is no longer under active development.

MiP C API

The MiP C API was created to give a C language abstraction for the operations supported by the WowWee MiP Mobile self-balancing Inverted Pendulum robot protocol. The transport (Bluetooth Low Energy or UART) being used will be abstracted behind this API as much as possible. This means that a developer could for example start development on an OS X machine using the BLE transport and later migrate to a microcontroller connected directly to the MiP's UART.

Supported Transports

  • OS X - Bluetooth Low Energy - This is the initial transport currently being developed.

OS X - Bluetooth Low Energy Notes

On a platform like OS X it would be typical to write a Cocoa UI application that responds to events. The Official WowWee iOS SDK is an example of a framework that works in such an environment. Since one of the purposes of this MiP C API is to allow easier migration to microcontrollers for complete autonomy, this API attempts to hide that event driven behavior from the developer. It accomplishes this by having the main thread call osxMiPInitAndRun() which runs the main NSApplication event loop and starts up a worker thread to execute the developer's code in a more sequential manner. The developer just needs to implement robotMain() to provide the code to be run in that worker thread. It is expected that the developer's OS X applications are written to be console applications. For OS X GUI based applications, it would be better to create an OS X port of the Official WowWee iOS SDK and use it instead.

OS X Example

#include <stdio.h>
#include "mip.h"
#include "osxble.h"


int main(int argc, char *argv[])
{
    // Initialize the Core Bluetooth stack on this the main thread and start the worker robot thread to run the
    // code found in robotMain() below.
    osxMiPInitAndRun();
    return 0;
}

void robotMain(void)
{
    int                result = -1;
    MiPSoftwareVersion softwareVersion;
    MiPHardwareInfo    hardwareInfo;
    MiP*               pMiP = mipInit(NULL);

    printf("\tExample - Use mipGetSoftwareVersion() & mipGetHardwareInfo() functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipGetSoftwareVersion(pMiP, &softwareVersion);
    result = mipGetHardwareInfo(pMiP, &hardwareInfo);

    printf("software version: %u-%u-%u.%u\n",
           softwareVersion.year,
           softwareVersion.month,
           softwareVersion.day,
           softwareVersion.uniqueVersion);
    printf("hardware info\n");
    printf("  voice chip version: %u\n", hardwareInfo.voiceChip);
    printf("    hardware version: %u\n", hardwareInfo.hardware);

    mipUninit(pMiP);
}

Reference

Error Codes

Error Value Description
MIP_ERROR_NONE 0 Success
MIP_ERROR_CONNECT 1 Connection to MiP failed
MIP_ERROR_PARAM 2 Invalid parameter passed to API
MIP_ERROR_MEMORY 3 Out of memory
MIP_ERROR_NOT_CONNECTED 4 No MiP robot connected
MIP_ERROR_NO_REQUEST 5 Not waiting for a response from a request
MIP_ERROR_TIMEOUT 6 Timed out waiting for response
MIP_ERROR_EMPTY 7 The queue was empty
MIP_ERROR_BAD_RESPONSE 8 Unexpected response from MiP

API by Function

Function API
Initialization mipInit
mipUninit
Connection mipConnectToRobot
mipDisconnectFromRobot
Discovery mipStartRobotDiscovery
mipGetDiscoveredRobotCount
mipGetDiscoveredRobotName
mipStopRobotDiscovery
Modes mipSetGestureRadarMode
mipGetGestureRadarMode
LEDs mipSetChestLED
mipFlashChestLED
mipGetChestLED
mipSetHeadLEDs
mipGetHeadLEDs
Motion mipContinuousDrive
mipDistanceDrive
mipTurnLeft
mipTurnRight
mipDriveForward
mipDriveBackward
mipStop
mipFallDown
mipGetUp
Sound mipPlaySound
mipGetVolume
mipSetVolume
Odometer mipReadOdometer
mipResetOdometer
Status mipGetStatus
mipGetLatestStatusNotification
Radar mipGetLatestRadarNotification
Gesture mipGetLatestGestureNotification
Shake mipGetLatestShakeNotification
Weight mipGetWeight
mipGetLatestWeightNotification
Clap mipGetClapSettings
mipEnableClap
mipSetClapDelay
mipGetLatestClapNotification
Version Info mipGetSoftwareVersion
mipGetHardwareInfo
Raw mipRawSend
mipRawReceive
mipRawReceiveNotification

API by Name

mipConnectToRobot
mipContinuousDrive
mipDisconnectFromRobot
mipDistanceDrive
mipDriveBackward
mipDriveForward
mipEnableClap
mipFallDown
mipFlashChestLED
mipGetChestLED
mipGetClapSettings
mipGetDiscoveredRobotCount
mipGetDiscoveredRobotName
mipGetGestureRadarMode
mipGetHardwareInfo
mipGetHeadLEDs
mipGetLatestClapNotification
mipGetLatestGestureNotification
mipGetLatestRadarNotification
mipGetLatestShakeNotification
mipGetLatestStatusNotification
mipGetLatestWeightNotification
mipGetSoftwareVersion
mipGetStatus
mipGetUp
mipGetVolume
mipGetWeight
mipInit
mipPlaySound
mipRawReceive
mipRawReceiveNotification
mipRawSend
mipReadOdometer
mipResetOdometer
mipSetChestLED
mipSetClapDelay
mipSetGestureRadarMode
mipSetHeadLEDs
mipSetVolume
mipStartRobotDiscovery
mipStop
mipStopRobotDiscovery
mipTurnLeft
mipTurnRight
mipUninit

mipInit

MiP* mipInit(const char* pInitOptions);
Is the first mip*() function that should be called by the developer. It allocates and returns the MiP* pointer used as the first parameter in all subsequent mip*() function calls.

Parameters:

  • pInitOptions: A character string which originates with the user. It is transport specific. At this point all supported transports ignore the parameter so it can be set to NULL.

Returns:

  • NULL on error.
  • A valid pointer to a MiP object otherwise. This pointer is used as the first parameter in all subsequent mip*() function calls.

mipUninit

void mipUninit(MiP* pMiP);
Is the last mip*() function that should be called by the developer. It is used to cleanly shutdown the transport and any other resources used by the MiP API.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.

mipConnectToRobot

int mipConnectToRobot(MiP* pMiP, const char* pRobotName);
Called to connect to the desired MiP robot.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pRobotName: The name of the robot to which a connection should be made. This parameter can be NULL to indicate the default robot should be used.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

OS X BLE Transport Notes:

  • If pRobotName is set to NULL then connect to the first MiP robot discovered by BLE.
  • A list of valid names for pRobotName can be found through the use of the mipStartRobotDiscovery(), mipGetDiscoveredRobotCount(), mipGetDiscoveredRobotName(), and mipStopRobotDiscovery() functions.
  • Sometimes OS X successfully connects to a MiP but the MiP doesn't respond to commands or switch the chest LED to be lit green. It acts like the BLE device in the MiP is connected to OS X but the main processor within the MiP was too busy when the connection occurred so it doesn't switch state properly. Future MiP C API calls which expect a response from the MiP will receive MIP_ERROR_TIMEOUT errors. The developer could detect these errors and force a disconnect and a new connection.

Example:

void robotMain(void)
{
    int result = -1;
    MiP* pMiP = mipInit(NULL);

    printf("\tConnect.c - Connect and disconnect from default MiP.\n"
           "\tShould see chest LED turn green on successful connection and\n"
           "\tswitch back to blue shortly after once disconnected.\n");

    // Connect to default MiP robot.
    result = mipConnectToRobot(pMiP, NULL);

    // Do stuff with the MiP robot.

    // Disconnect and shutdown the application.
    result = mipDisconnectFromRobot(pMiP);
    mipUninit(pMiP);
}

mipDisconnectFromRobot

int mipDisconnectFromRobot(MiP* pMiP);
Called to disconnect from the current MiP robot.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • Doesn't need to be called for a clean shutdown as mpiUninit() will take care of disconnecting from any active robots as part of the transport layer cleanup.
  • This API exists incase the developer wants to explicitly disconnect from a MiP during execution and connect to another.

Example:

void robotMain(void)
{
    int result = -1;
    MiP* pMiP = mipInit(NULL);

    printf("\tConnect.c - Connect and disconnect from default MiP.\n"
           "\tShould see chest LED turn green on successful connection and\n"
           "\tswitch back to blue shortly after once disconnected.\n");

    // Connect to default MiP robot.
    result = mipConnectToRobot(pMiP, NULL);

    // Do stuff with the MiP robot.

    // Disconnect and shutdown the application.
    result = mipDisconnectFromRobot(pMiP);
    mipUninit(pMiP);
}

mipStartRobotDiscovery

int mipStartRobotDiscovery(MiP* pMiP);
Starts the process of discovering MiP robots to which a connection can be made. This discovery process will continue until mipStopRobotDiscovery() is called.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The discovery process is only used with BLE transports to find nearby MiP robots. If connecting directly to the MiP via the UART transport then discovery isn't necessary.
  • Once the discovery process has started, the mipGetDiscoveredRobotCount() and mipGetDiscoveredRobotName() functions can be called to query the current list of robots. Those functions can still be called after calling mipStopRobotDiscovery() but no new robots will be added to the list.

Example:

void robotMain(void)
{
    int         result = -1;
    size_t      robotCount = 0;
    const char* pRobotName = NULL;
    MiP*        pMiP = mipInit(NULL);

    printf("\tDiscovery.c - Discover MiP robots to which a connection can be made.\n"
           "\tShould see first MiP robot be listed when it is powered up near\n"
           "\tthe test machine.\n");
    result = mipStartRobotDiscovery(pMiP);
    do
    {
        result = mipGetDiscoveredRobotCount(pMiP, &robotCount);
    } while (robotCount == 0);
    result = mipGetDiscoveredRobotName(pMiP, 0, &pRobotName);
    printf("\tDiscovered %s\n", pRobotName);
    result = mipStopRobotDiscovery(pMiP);

    mipUninit(pMiP);
}

mipGetDiscoveredRobotCount

int mipGetDiscoveredRobotCount(MiP* pMiP, size_t* pCount);
Query how many MiP robots the discovery process has found so far.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pCount: A pointer to where the current count of robots should be placed. Shouldn't be NULL.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The discovery process is only used with BLE transports to find nearby MiP robots. If connecting directly to the MiP via the UART transport then discovery isn't necessary.
  • The discovery process should be started by calling mipStartRobotDiscovery() before calling this function.
  • The count returned by this function can increase (if more and more robots are discovered over time) until mipStopRobotDiscovery() is called.

Example:

void robotMain(void)
{
    int         result = -1;
    size_t      robotCount = 0;
    const char* pRobotName = NULL;
    MiP*        pMiP = mipInit(NULL);

    printf("\tDiscovery.c - Discover MiP robots to which a connection can be made.\n"
           "\tShould see first MiP robot be listed when it is powered up near\n"
           "\tthe test machine.\n");
    result = mipStartRobotDiscovery(pMiP);
    do
    {
        result = mipGetDiscoveredRobotCount(pMiP, &robotCount);
    } while (robotCount == 0);
    result = mipGetDiscoveredRobotName(pMiP, 0, &pRobotName);
    printf("\tDiscovered %s\n", pRobotName);
    result = mipStopRobotDiscovery(pMiP);

    mipUninit(pMiP);
}

mipGetDiscoveredRobotName

int mipGetDiscoveredRobotName(MiP* pMiP, size_t robotIndex, const char** ppRobotName);
Query the name of a specific MiP robot which the discovery process has found.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • robotIndex: The index of the robot for which the name should be obtained. It must be >= 0 and < the count returned by mipGetDiscoveredRobotCount().
  • ppRobotName: A pointer to where the robot name should be placed. Shouldn't be NULL.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The discovery process is only used with BLE transports to find nearby MiP robots. If connecting directly to the MiP via the UART transport then discovery isn't necessary.
  • The discovery process should be started by calling mipStartRobotDiscovery() before calling this function.
  • This function is used to index into the list of discovered robots to obtain its name. This name can be later used as the pRobotName parameter of the mipConnectToRobot() function.

Example:

void robotMain(void)
{
    int         result = -1;
    size_t      robotCount = 0;
    const char* pRobotName = NULL;
    MiP*        pMiP = mipInit(NULL);

    printf("\tDiscovery.c - Discover MiP robots to which a connection can be made.\n"
           "\tShould see first MiP robot be listed when it is powered up near\n"
           "\tthe test machine.\n");
    result = mipStartRobotDiscovery(pMiP);
    do
    {
        result = mipGetDiscoveredRobotCount(pMiP, &robotCount);
    } while (robotCount == 0);
    result = mipGetDiscoveredRobotName(pMiP, 0, &pRobotName);
    printf("\tDiscovered %s\n", pRobotName);
    result = mipStopRobotDiscovery(pMiP);

    mipUninit(pMiP);
}

mipStopRobotDiscovery

int mipStopRobotDiscovery(MiP* pMiP);
Stops the process of discovering MiP robots to which a connection can be made.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The discovery process is only used with BLE transports to find nearby MiP robots. If connecting directly to the MiP via the UART transport then discovery isn't necessary.
  • The discovery process is started with a call to mipStartRobotDiscovery() and stops when this function is called.
  • MiP robots which were found between these two calls can be listed through the use of the mipGetDiscoveredRobotCount() and mipGetDiscoveredRobotName() functions.

Example:

void robotMain(void)
{
    int         result = -1;
    size_t      robotCount = 0;
    const char* pRobotName = NULL;
    MiP*        pMiP = mipInit(NULL);

    printf("\tDiscovery.c - Discover MiP robots to which a connection can be made.\n"
           "\tShould see first MiP robot be listed when it is powered up near\n"
           "\tthe test machine.\n");
    result = mipStartRobotDiscovery(pMiP);
    do
    {
        result = mipGetDiscoveredRobotCount(pMiP, &robotCount);
    } while (robotCount == 0);
    result = mipGetDiscoveredRobotName(pMiP, 0, &pRobotName);
    printf("\tDiscovered %s\n", pRobotName);
    result = mipStopRobotDiscovery(pMiP);

    mipUninit(pMiP);
}

mipSetGestureRadarMode

int mipSetGestureRadarMode(MiP* pMiP, MiPGestureRadarMode mode);
Used to enable gesture or radar mode.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • mode: Which mode should be enabled: MIP_GESTURE_RADAR_DISABLED (disables both gesture and radar modes), MIP_GESTURE (enables gesture mode), or MIP_RADAR (enables radar mode).

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • When the mode is set to MIP_GESTURE, the MiP will start sending gesture notifications. These notifications can be queried via mipGetLatestGestureNotification().
  • When the mode is set to MIP_RADAR, the MiP will start sending radar notifications. These notifications can be queried via mipGetLatestRadarNotification().
  • These gesture/radar notifications will be suppressed while the MiP is executing long running commands. Shorter commands like mipContinuousDrive() do allow the MiP to send the notifications in a timely fashion.
  • These gesture/radar notifications will only be sent when the MiP is actively balancing. They will be suppressed if the MiP is laying back on its kickstand for example.

Example:

void robotMain(void)
{
    int                  result = -1;
    MiPGestureRadarMode  mode = MIP_GESTURE_RADAR_DISABLED;
    MiP*                 pMiP = mipInit(NULL);

    printf("\tGestureRadarMode.c - Use mipSet/GetGestureRadarMode() functions.\n"
           "\tShould switch into radar mode.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    printf("Enable radar mode\n");
    do
    {
        // Keep trying until it goes through.
        result = mipSetGestureRadarMode(pMiP, MIP_RADAR);
        result = mipGetGestureRadarMode(pMiP, &mode);
    } while (mode != MIP_RADAR);
    printf("Radar mode enabled\n");

    mipUninit(pMiP);
}

mipGetGestureRadarMode

int mipGetGestureRadarMode(MiP* pMiP, MiPGestureRadarMode* pMode);
Requests the current gesture or radar mode setting from the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pMode: A pointer into which the current MiP gesture/radar mode should be placed. The returned mode setting will be one of: MIP_GESTURE_RADAR_DISABLED (both gesture and radar modes are disabled), MIP_GESTURE (gesture mode is enabled), or MIP_RADAR (radar mode is enabled).

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if MiP doesn't return a valid mode.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int                  result = -1;
    MiPGestureRadarMode  mode = MIP_GESTURE_RADAR_DISABLED;
    MiP*                 pMiP = mipInit(NULL);

    printf("\tGestureRadarMode.c - Use mipSet/GetGestureRadarMode() functions.\n"
           "\tShould switch into radar mode.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    printf("Enable radar mode\n");
    do
    {
        // Keep trying until it goes through.
        result = mipSetGestureRadarMode(pMiP, MIP_RADAR);
        result = mipGetGestureRadarMode(pMiP, &mode);
    } while (mode != MIP_RADAR);
    printf("Radar mode enabled\n");

    mipUninit(pMiP);
}

mipSetChestLED

int mipSetChestLED(MiP* pMiP, uint8_t red, uint8_t green, uint8_t blue);
Sets the colour of the RGB LED in the MiP's chest.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • red: The intensity of the red colour channel (0 - 255).
  • green: The intensity of the green colour channel (0 - 255).
  • blue: The intensity of the blue colour channel (0 - 255).

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int           result = -1;
    MiP*          pMiP = mipInit(NULL);
    const uint8_t red = 0xff;
    const uint8_t green = 0x00;
    const uint8_t blue = 0xff;

    printf("\tSetChestLED.c - Use mipSetChestLED() function.\n"
           "\tShould switch chest LED to magenta.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipSetChestLED(pMiP, red, green, blue);

    sleep(3);

    mipUninit(pMiP);
}

mipFlashChestLED

int mipFlashChestLED(MiP* pMiP, uint8_t red, uint8_t green, uint8_t blue, uint16_t onTime, uint16_t offTime);
Sets the colour and flashing period of the RGB LED in the MiP's chest.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • red: The intensity of the red colour channel (0 - 255).
  • green: The intensity of the green colour channel (0 - 255).
  • blue: The intensity of the blue colour channel (0 - 255).
  • onTime: Is the time in milliseconds that the LED should remain on with the specified colour. This parameter can be set to a value between 0 and 5100 milliseconds.
  • offTime: Is the time in milliseconds that the LED should remain off before turning on again with the specified colour. This parameter can be set to a value between 0 and 5100 milliseconds.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The MiP only supports a granularity of 20 milliseconds for the onTime and offTime parameters.

Example:

void robotMain(void)
{
    int            result = -1;
    const uint8_t  red = 0xff;
    const uint8_t  green = 0x00;
    const uint8_t  blue = 0x00;
    const uint16_t onTime = 1000;    // 1000 msecs / sec
    const uint16_t offTime = 1000;   // 1000 msecs / sec
    MiPChestLED    chestLED;
    MiP*           pMiP = mipInit(NULL);

    printf("\tFlashChestLED.c - Use mipFlashChestLED() and mipGetChestLED() functions.\n"
           "\tShould flash chest LED red.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipFlashChestLED(pMiP, red, green, blue, onTime, offTime);

    sleep(4);

    result = mipGetChestLED(pMiP, &chestLED);
    printf("chestLED\n");
    printf("red: %u\n", chestLED.red);
    printf("green: %u\n", chestLED.green);
    printf("blue: %u\n", chestLED.blue);
    printf("on time: %u milliseconds\n", chestLED.onTime);
    printf("off time: %u milliseconds\n", chestLED.offTime);

    mipUninit(pMiP);
}

mipGetChestLED

int mipGetChestLED(MiP* pMiP, MiPChestLED* pChestLED);
Requests the current setting for the colour and flashing period of the RGB LED in the MiP's chest.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pChestLED: Points to the MiPChestLED structure to be filled in by this call. This structure contains red, green, and blue fields indicating the intensity (0 - 255) of each colour channel when the chest LED is on. The structure also contains onTime and offTime fields indicating the time in milliseconds the LED should be turned on and off for the flashing pattern.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if MiP doesn't return a valid mode.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The MiP only supports a granularity of 20 milliseconds for the onTime and offTime fields in the MiPChestLED structure.

Example:

void robotMain(void)
{
    int            result = -1;
    const uint8_t  red = 0xff;
    const uint8_t  green = 0x00;
    const uint8_t  blue = 0x00;
    const uint16_t onTime = 1000;    // 1000 msecs / sec
    const uint16_t offTime = 1000;   // 1000 msecs / sec
    MiPChestLED    chestLED;
    MiP*           pMiP = mipInit(NULL);

    printf("\tFlashChestLED.c - Use mipFlashChestLED() and mipGetChestLED() functions.\n"
           "\tShould flash chest LED red.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipFlashChestLED(pMiP, red, green, blue, onTime, offTime);

    sleep(4);

    result = mipGetChestLED(pMiP, &chestLED);
    printf("chestLED\n");
    printf("red: %u\n", chestLED.red);
    printf("green: %u\n", chestLED.green);
    printf("blue: %u\n", chestLED.blue);
    printf("on time: %u milliseconds\n", chestLED.onTime);
    printf("off time: %u milliseconds\n", chestLED.offTime);

    mipUninit(pMiP);
}

mipSetHeadLEDs

int mipSetHeadLEDs(MiP* pMiP, MiPHeadLED led1, MiPHeadLED led2, MiPHeadLED led3, MiPHeadLED led4);
Sets the state of the four LEDs on the MiP's head.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • led1: The state of led1 on the MiP's head. Valid states are MIP_HEAD_LED_OFF, MIP_HEAD_LED_ON, MIP_HEAD_LED_BLINK_SLOW, MIP_HEAD_LED_BLINK_FAST.
  • led2: The state of led2 on the MiP's head. Valid states are MIP_HEAD_LED_OFF, MIP_HEAD_LED_ON, MIP_HEAD_LED_BLINK_SLOW, MIP_HEAD_LED_BLINK_FAST.
  • led3: The state of led3 on the MiP's head. Valid states are MIP_HEAD_LED_OFF, MIP_HEAD_LED_ON, MIP_HEAD_LED_BLINK_SLOW, MIP_HEAD_LED_BLINK_FAST.
  • led4: The state of led4 on the MiP's head. Valid states are MIP_HEAD_LED_OFF, MIP_HEAD_LED_ON, MIP_HEAD_LED_BLINK_SLOW, MIP_HEAD_LED_BLINK_FAST.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The 4 head LEDs are numbered from left to right, with led1 being the leftmost and led4 being the rightmost.

Example:

void robotMain(void)
{
    int         result = -1;
    MiPHeadLEDs headLEDs;
    MiP*        pMiP = mipInit(NULL);

    printf("\tHeadLEDs.c - Use head LED functions.\n"
           "\tShould set each head LED to different state.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipSetHeadLEDs(pMiP, MIP_HEAD_LED_OFF, MIP_HEAD_LED_ON, MIP_HEAD_LED_BLINK_SLOW, MIP_HEAD_LED_BLINK_FAST);

    sleep(4);

    result = mipGetHeadLEDs(pMiP, &headLEDs);
    printf("Head LEDs\n");
    printf("led1: %s\n", headLEDString(headLEDs.led1));
    printf("led2: %s\n", headLEDString(headLEDs.led2));
    printf("led3: %s\n", headLEDString(headLEDs.led3));
    printf("led4: %s\n", headLEDString(headLEDs.led4));

    mipUninit(pMiP);
}

static const char* headLEDString(MiPHeadLED led)
{
    switch (led)
    {
    case MIP_HEAD_LED_OFF:
        return "Off";
    case MIP_HEAD_LED_ON:
        return "On";
    case MIP_HEAD_LED_BLINK_SLOW:
        return "Blink Slow";
    case MIP_HEAD_LED_BLINK_FAST:
        return "Blink Fast";
    default:
        return "";
    }
}

mipGetHeadLEDs

int mipGetHeadLEDs(MiP* pMiP, MiPHeadLEDs* pHeadLEDs);
Requests the current setting for the MiP's four head LEDs.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pHeadLEDs: Points to the MiPHeadLEDs structure to be filled in by this call. This structure contains led1, led2, led3, and led4 fields indicating the state of each head LED. Supported states are MIP_HEAD_LED_OFF, MIP_HEAD_LED_ON, MIP_HEAD_LED_BLINK_SLOW, MIP_HEAD_LED_BLINK_FAST.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if MiP doesn't return a valid state.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The 4 head LEDs are numbered from left to right, with led1 being the leftmost and led4 being the rightmost.

Example:

void robotMain(void)
{
    int         result = -1;
    MiPHeadLEDs headLEDs;
    MiP*        pMiP = mipInit(NULL);

    printf("\tHeadLEDs.c - Use head LED functions.\n"
           "\tShould set each head LED to different state.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipSetHeadLEDs(pMiP, MIP_HEAD_LED_OFF, MIP_HEAD_LED_ON, MIP_HEAD_LED_BLINK_SLOW, MIP_HEAD_LED_BLINK_FAST);

    sleep(4);

    result = mipGetHeadLEDs(pMiP, &headLEDs);
    printf("Head LEDs\n");
    printf("led1: %s\n", headLEDString(headLEDs.led1));
    printf("led2: %s\n", headLEDString(headLEDs.led2));
    printf("led3: %s\n", headLEDString(headLEDs.led3));
    printf("led4: %s\n", headLEDString(headLEDs.led4));

    mipUninit(pMiP);
}

static const char* headLEDString(MiPHeadLED led)
{
    switch (led)
    {
    case MIP_HEAD_LED_OFF:
        return "Off";
    case MIP_HEAD_LED_ON:
        return "On";
    case MIP_HEAD_LED_BLINK_SLOW:
        return "Blink Slow";
    case MIP_HEAD_LED_BLINK_FAST:
        return "Blink Fast";
    default:
        return "";
    }
}

mipContinuousDrive

int mipContinuousDrive(MiP* pMiP, int8_t velocity, int8_t turnRate);
Instruct the MiP to drive in a particular direction.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • velocity: The forward/reverse velocity. This parameter can have a value between -32 and 32, where -32 is maximum reverse velocity and 32 is maximum forward velocity. A velocity of 0 indicates that no forward/reverse motion is desired at this time.
  • turnRate: The amount of left/right turn rate. This parameter can have a value between -32 and 32, where -32 is maximum left turn rate and 32 is maximum right turn velocity. A turn rate of 0 indicates that no left/right turning is desired at this time.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • This command must be sent at regular intervals to keep the MiP robot moving in the desired direction. This interval should be 50 milliseconds.
  • When sent at longer intervals the MiP's motion will become more jerky as it thinks that there will not be another motion command coming so it starts to stop all motion and then starts moving again once the next command does finally arrive.
  • If your robot code is constantly sensing it's environment and using those ongoing sensor readings to make decisions on which direction the robot should be currently headed, then this command will be the most useful for updating the MiP's motion vector in real time.

Example:

void robotMain(void)
{
    int   result = -1;
    int   i = 0;
    MiP*  pMiP = mipInit(NULL);

    printf("\tContinuousDrive.c - Use mipContinuousDrive() function.\n"
           "\tDrive forward with right turn and then backward with left turn.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    for (i = 0 ; i < 40 ; i++)
    {
        // Drive forward at half-speed and turn right at quarter rate.
        result = mipContinuousDrive(pMiP, 16, 8);
        // Pace out the continuous drive commands by 50 msec.
        usleep(50000);
    }
    for (i = 0 ; i < 40 ; i++)
    {
        // Drive backward at half-speed and turn left at quarter rate.
        result = mipContinuousDrive(pMiP, -16, -8);
        // Pace out the continuous drive commands by 50 msec.
        usleep(50000);
    }

    mipUninit(pMiP);
}

mipDistanceDrive

int mipDistanceDrive(MiP* pMiP, MiPDriveDirection driveDirection, uint8_t cm, MiPTurnDirection turnDirection, uint16_t degrees);
Used to queue up a drive/turn command to the MiP robot.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • driveDirection: Specifies the direction the robot should drive: MIP_DRIVE_FORWARD or MIP_DRIVE_BACKWARD.
  • cm: Specifies the number of cm (centimeters) the robot should proceed in driveDirection. This parameter can have a value between 0 and 255 cm. Can be set to 0 if only a turn is desired.
  • turnDirection: Specifies the direction the robot should turn: MIP_TURN_LEFT or MIP_TURN_RIGHT.
  • degrees: The number of degrees the robot should turn. This parameter can have a value between 0 and 360 degrees. Can be set to 0 if only a forward/reverse drive is desired.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • It is possible to queue up to 20 of these distance drive commands in the MiP's memory.
  • I have found that there should be at least 0.5 seconds between queueing calls or the MiP may drop the command rather than queueing it up.
  • There is no way to specify the speed to be used for driving and/or turning.
  • The distance travelled isn't super accurate. Usually it travels further than commanded.
  • Queued up commands will continue to be executed by the MiP even after calling mipDisconnectFromRobot() and/or mipUninit().

Example:

void robotMain(void)
{
    int                result = -1;
    MiP*               pMiP = mipInit(NULL);

    printf("\tDistanceDrive.c - Use mipDistanceDrive function.\n"
           "\tDrive forward, turn 360 degrees in each direction and backward.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    // Queue up multiple commands to run in sequence.
    result = mipDistanceDrive(pMiP, MIP_DRIVE_FORWARD, 30, MIP_TURN_RIGHT, 0);
    // Don't queue up multiple commands too fast.
    usleep(500 * 1000);
    result = mipDistanceDrive(pMiP, MIP_DRIVE_FORWARD, 0, MIP_TURN_LEFT, 360);
    usleep(500 * 1000);
    result = mipDistanceDrive(pMiP, MIP_DRIVE_FORWARD, 0, MIP_TURN_RIGHT, 360);
    usleep(500 * 1000);
    result = mipDistanceDrive(pMiP, MIP_DRIVE_BACKWARD, 30, MIP_TURN_RIGHT, 0);
    usleep(500 * 1000);

    mipUninit(pMiP);
}

mipTurnLeft

int mipTurnLeft(MiP* pMiP, uint16_t degrees, uint8_t speed);
Commands the MiP robot to turn left the desired number of degrees at the desired speed.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • degrees: The number of degrees the robot should turn. This parameter can have a value between 0 and 1275 degrees.
  • speed: The speed at which the turn should take place. The speed can have a value between 0 and 24 with 0 being the slowest rate and 24 the fastest.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int   result = -1;
    MiP*  pMiP = mipInit(NULL);

    printf("\tTurnLeftRight.c - Use mipTurnLeft & mipTurnRight() functions.\n"
           "\tTurn 180 degrees to left and then 180 degrees to right.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipTurnLeft(pMiP, 180, 12);
    sleep(2);
    result = mipTurnRight(pMiP, 180, 12);
    sleep(2);

    mipUninit(pMiP);
}

mipTurnRight

int mipTurnRight(MiP* pMiP, uint16_t degrees, uint8_t speed);
Commands the MiP robot to turn right the desired number of degrees at the desired speed.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • degrees: The number of degrees the robot should turn. This parameter can have a value between 0 and 1275 degrees.
  • speed: The speed at which the turn should take place. The speed can have a value between 0 and 24 with 0 being the slowest rate and 24 the fastest.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int   result = -1;
    MiP*  pMiP = mipInit(NULL);

    printf("\tTurnLeftRight.c - Use mipTurnLeft & mipTurnRight() functions.\n"
           "\tTurn 180 degrees to left and then 180 degrees to right.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipTurnLeft(pMiP, 180, 12);
    sleep(2);
    result = mipTurnRight(pMiP, 180, 12);
    sleep(2);

    mipUninit(pMiP);
}

mipDriveForward

int mipDriveForward(MiP* pMiP, uint8_t speed, uint16_t time);
Commands the MiP robot to drive forward.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • speed: The speed at which the motion should take place. The speed can have a value between 0 and 30 with 0 being the slowest rate and 30 the fastest.
  • time: The time to drive forward in milliseconds. This parameter can have a value between 0 and 1785 milliseconds. The MiP only supports a granularity of 7 milliseconds for this parameter.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int   result = -1;
    MiP*  pMiP = mipInit(NULL);

    printf("\tDriveForwardBackward.c - Use mipDriveForward() & mipDriveBackward() functions.\n"
           "\tDrive ahead and back, 1 second in each direction.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipDriveForward(pMiP, 15, 1000);
    sleep(2);
    result = mipDriveBackward(pMiP, 15, 1000);
    sleep(2);

    mipUninit(pMiP);
}

mipDriveBackward

int mipDriveBackward(MiP* pMiP, uint8_t speed, uint16_t time);
Commands the MiP robot to drive backward.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • speed: The speed at which the motion should take place. The speed can have a value between 0 and 30 with 0 being the slowest rate and 30 the fastest.
  • time: The time to drive backward in milliseconds. This parameter can have a value between 0 and 1785 milliseconds. The MiP only supports a granularity of 7 milliseconds for this parameter.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int   result = -1;
    MiP*  pMiP = mipInit(NULL);

    printf("\tDriveForwardBackward.c - Use mipDriveForward() & mipDriveBackward() functions.\n"
           "\tDrive ahead and back, 1 second in each direction.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipDriveForward(pMiP, 15, 1000);
    sleep(2);
    result = mipDriveBackward(pMiP, 15, 1000);
    sleep(2);

    mipUninit(pMiP);
}

mipStop

int mipStop(MiP* pMiP);
Interrupt and stop current robot motion.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int   result = -1;
    MiP*  pMiP = mipInit(NULL);

    printf("\tStop.c - Use mipStop() function.\n"
           "\tInterrupt a 360 degree turn with mipStop().\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipTurnLeft(pMiP, 360, 6);
    sleep(1);
    result = mipStop(pMiP);
    sleep(1);

    mipUninit(pMiP);
}

mipFallDown

int mipFallDown(MiP* pMiP, MiPFallDirection direction);
Have the MiP fall forward or backward.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • direction: In which direction should the MiP fall: MIP_FALL_ON_BACK or MIP_FALL_FACE_DOWN.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int   result = -1;
    MiP*  pMiP = mipInit(NULL);

    printf("\tFallDown.c - Use mipFallDown().\n"
           "\tFall forward.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipFallDown(pMiP, MIP_FALL_FACE_DOWN);
    sleep(2);

    mipUninit(pMiP);
}

mipGetUp

int mipGetUp(MiP* pMiP, MiPGetUp getup);
Attempt to get the MiP back up and balancing after falling to the back or front.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • getup: In which direction should the MiP attempt to get up from: MIP_GETUP_FROM_FRONT, MIP_GETUP_FROM_BACK, and MIP_GETUP_FROM_EITHER.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:*

  • I haven't had this command work successfully during my testing.

Example:

void robotMain(void)
{
    int   result = -1;
    MiP*  pMiP = mipInit(NULL);

    printf("\tGetUp.c - Use mipGetUp().\n"
           "\tAttempt to get up from a front fall.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipFallDown(pMiP, MIP_FALL_FACE_DOWN);
    sleep(3);

    result = mipGetUp(pMiP, MIP_GETUP_FROM_FRONT);
    sleep(3);

    mipUninit(pMiP);
}

mipPlaySound

int mipPlaySound(MiP* pMiP, const MiPSound* pSounds, size_t soundCount, uint8_t repeatCount);
Have the MiP play a sequence of sounds.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pSounds: An array of MiPSound objects describing what sounds should be played. There can be a maximum of 8 entries in this array. See notes below to learn more about the MiPSound objects.
  • soundCount: The number of entries in the pSounds array (1 - 8).
  • repeatCount: After the MiP plays the sounds in pSounds once, how many more times (0 - 255) should it repeat the sequence. A value of 0 means that the sound sequence will play once and then stop whereas a value of 1 means that it would play the sequence a total of 2 times.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:
This is the MiPSound structure used for the entries of the pSounds array:

typedef struct MiPSound
{
    MiPSoundIndex sound;
    uint16_t      delay;
} MiPSound;

sound: Used to specify the index of the sound or volume control setting to be used for this entry in the pSounds array. The MiPSoundIndex enumeration is described below.
delay: Used to specify the delay in milliseconds that the MiP should wait after playing this sound before playing the next (if any) in the pSounds array. The granularity of this delay is 30 milliseconds.

The MiPSoundIndex enumeration is used to specify the index of the sound or volume control setting in the sound field of the MiPSound structure. It contains the following entries:

MIP_SOUND_ONEKHZ_500MS_8K16BIT
MIP_SOUND_ACTION_BURPING
MIP_SOUND_ACTION_DRINKING
MIP_SOUND_ACTION_EATING
MIP_SOUND_ACTION_FARTING_SHORT
MIP_SOUND_ACTION_OUT_OF_BREATH
MIP_SOUND_BOXING_PUNCHCONNECT_1
MIP_SOUND_BOXING_PUNCHCONNECT_2
MIP_SOUND_BOXING_PUNCHCONNECT_3
MIP_SOUND_FREESTYLE_TRACKING_1
MIP_SOUND_MIP_1
MIP_SOUND_MIP_2
MIP_SOUND_MIP_3
MIP_SOUND_MIP_APP
MIP_SOUND_MIP_AWWW
MIP_SOUND_MIP_BIG_SHOT
MIP_SOUND_MIP_BLEH
MIP_SOUND_MIP_BOOM
MIP_SOUND_MIP_BYE
MIP_SOUND_MIP_CONVERSE_1
MIP_SOUND_MIP_CONVERSE_2
MIP_SOUND_MIP_DROP
MIP_SOUND_MIP_DUNNO
MIP_SOUND_MIP_FALL_OVER_1
MIP_SOUND_MIP_FALL_OVER_2
MIP_SOUND_MIP_FIGHT
MIP_SOUND_MIP_GAME
MIP_SOUND_MIP_GLOAT
MIP_SOUND_MIP_GO
MIP_SOUND_MIP_GOGOGO
MIP_SOUND_MIP_GRUNT_1
MIP_SOUND_MIP_GRUNT_2
MIP_SOUND_MIP_GRUNT_3
MIP_SOUND_MIP_HAHA_GOT_IT
MIP_SOUND_MIP_HI_CONFIDENT
MIP_SOUND_MIP_HI_NOT_SURE
MIP_SOUND_MIP_HI_SCARED
MIP_SOUND_MIP_HUH
MIP_SOUND_MIP_HUMMING_1
MIP_SOUND_MIP_HUMMING_2
MIP_SOUND_MIP_HURT
MIP_SOUND_MIP_HUUURGH
MIP_SOUND_MIP_IN_LOVE
MIP_SOUND_MIP_IT
MIP_SOUND_MIP_JOKE
MIP_SOUND_MIP_K
MIP_SOUND_MIP_LOOP_1
MIP_SOUND_MIP_LOOP_2
MIP_SOUND_MIP_LOW_BATTERY
MIP_SOUND_MIP_MIPPEE
MIP_SOUND_MIP_MORE
MIP_SOUND_MIP_MUAH_HA
MIP_SOUND_MIP_MUSIC
MIP_SOUND_MIP_OBSTACLE
MIP_SOUND_MIP_OHOH
MIP_SOUND_MIP_OH_YEAH
MIP_SOUND_MIP_OOPSIE
MIP_SOUND_MIP_OUCH_1
MIP_SOUND_MIP_OUCH_2
MIP_SOUND_MIP_PLAY
MIP_SOUND_MIP_PUSH
MIP_SOUND_MIP_RUN
MIP_SOUND_MIP_SHAKE
MIP_SOUND_MIP_SIGH
MIP_SOUND_MIP_SINGING
MIP_SOUND_MIP_SNEEZE
MIP_SOUND_MIP_SNORE
MIP_SOUND_MIP_STACK
MIP_SOUND_MIP_SWIPE_1
MIP_SOUND_MIP_SWIPE_2
MIP_SOUND_MIP_TRICKS
MIP_SOUND_MIP_TRIIICK
MIP_SOUND_MIP_TRUMPET
MIP_SOUND_MIP_WAAAAA
MIP_SOUND_MIP_WAKEY
MIP_SOUND_MIP_WHEEE
MIP_SOUND_MIP_WHISTLING
MIP_SOUND_MIP_WHOAH
MIP_SOUND_MIP_WOO
MIP_SOUND_MIP_YEAH
MIP_SOUND_MIP_YEEESSS
MIP_SOUND_MIP_YO
MIP_SOUND_MIP_YUMMY
MIP_SOUND_MOOD_ACTIVATED
MIP_SOUND_MOOD_ANGRY
MIP_SOUND_MOOD_ANXIOUS
MIP_SOUND_MOOD_BORING
MIP_SOUND_MOOD_CRANKY
MIP_SOUND_MOOD_ENERGETIC
MIP_SOUND_MOOD_EXCITED
MIP_SOUND_MOOD_GIDDY
MIP_SOUND_MOOD_GRUMPY
MIP_SOUND_MOOD_HAPPY
MIP_SOUND_MOOD_IDEA
MIP_SOUND_MOOD_IMPATIENT
MIP_SOUND_MOOD_NICE
MIP_SOUND_MOOD_SAD
MIP_SOUND_MOOD_SHORT
MIP_SOUND_MOOD_SLEEPY
MIP_SOUND_MOOD_TIRED
MIP_SOUND_SOUND_BOOST
MIP_SOUND_SOUND_CAGE
MIP_SOUND_SOUND_GUNS
MIP_SOUND_SOUND_ZINGS
MIP_SOUND_SHORT_MUTE_FOR_STOP
MIP_SOUND_FREESTYLE_TRACKING_2
MIP_SOUND_VOLUME_OFF
MIP_SOUND_VOLUME_1
MIP_SOUND_VOLUME_2
MIP_SOUND_VOLUME_3
MIP_SOUND_VOLUME_4
MIP_SOUND_VOLUME_5
MIP_SOUND_VOLUME_6
MIP_SOUND_VOLUME_7

MIP_SOUND_VOLUME_OFF to MIP_SOUND_VOLUME_7 are used as entries in the pSounds array to change the volume before playing subsequent sounds in the array.

Example:

void robotMain(void)
{
    int     result = -1;
    MiP*    pMiP = mipInit(NULL);

    printf("\tPlaySound.c - Use mipPlaySound().\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    // Play 1 sound.
    const MiPSound sounds1[] = {{MIP_SOUND_ONEKHZ_500MS_8K16BIT, 0}};
    result = mipPlaySound(pMiP, sounds1, sizeof(sounds1)/sizeof(sounds1[0]), 0);

    sleep(2);

    // Play 2 sounds with 1 second delay between them, repeating them a second time.
    // Play the first at a lower volume than the second.
    const MiPSound sounds2[] = {{MIP_SOUND_VOLUME_4, 0},            // Play eating sound at half volume.
                                {MIP_SOUND_ACTION_EATING, 1000},
                                {MIP_SOUND_VOLUME_7, 0},            // Play burping sound at full volume.
                                {MIP_SOUND_ACTION_BURPING, 0},
                                {MIP_SOUND_VOLUME_1, 0}};           // Finish by setting volume low.
    result = mipPlaySound(pMiP, sounds2, sizeof(sounds2)/sizeof(sounds2[0]), 1);

    sleep(7);

    mipUninit(pMiP);
}

mipSetVolume

int mipSetVolume(MiP* pMiP, uint8_t volume);
Set the MiP's volume level.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • volume: The new volume level (0 - 7). A level of 0 turns off the sound and 7 is the loudest setting.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int     result = -1;
    uint8_t volume = 0;
    MiP*    pMiP = mipInit(NULL);

    printf("\tVolume.c - Use mipSet/GetVolume().\n"
           "\tSet volume level to 1 and read out afterwards.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipSetVolume(pMiP, 1);
    result = mipGetVolume(pMiP, &volume);

    printf("Volume = %u\n", volume);

    mipUninit(pMiP);
}

mipGetVolume

int mipGetVolume(MiP* pMiP, uint8_t* pVolume);
Retrieve the MiP's current volume level.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pVolume: Points to the integer to be filled in with the current volume level (0 - 7). A level of 0 means the sound is off and 7 is the loudest setting.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if MiP doesn't return a valid state.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int     result = -1;
    uint8_t volume = 0;
    MiP*    pMiP = mipInit(NULL);

    printf("\tVolume.c - Use mipSet/GetVolume().\n"
           "\tSet volume level to 1 and read out afterwards.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipSetVolume(pMiP, 1);
    result = mipGetVolume(pMiP, &volume);

    printf("Volume = %u\n", volume);

    mipUninit(pMiP);
}

mipReadOdometer

int mipReadOdometer(MiP* pMiP, float* pDistanceInCm);
Read the current MiP odometer tally.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pDistanceInCm: Points to the floating point variable to be filled in with the distance travelled (in centimeters) since the last reset.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if MiP doesn't return a valid state.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The MiP's odometer is similar to that in a car. It maintains the total tally of the distance travelled, even across power cycles.
  • The mipResetOdometer() call can be used to reset the odometer.

Example:

void robotMain(void)
{
    int     result = -1;
    MiP*    pMiP = mipInit(NULL);

    printf("\tOdometer.c - Use mipReadOdometer() and mipResetOdometer.\n"
           "\tRead out current odometer reading and reset.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    float cm = 0.0f;
    result = mipReadOdometer(pMiP, &cm);
    printf("MiP has travelled %f cm since the last reset.\n", cm);

    result = mipResetOdometer(pMiP);
    sleep(1);

    mipUninit(pMiP);
}

mipResetOdometer

int mipResetOdometer(MiP* pMiP);
Reset the MiP's odometer.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The MiP's odometer doesn't automatically reset during a power cycle.
  • The developer should call this function if they want to manually reset it.

Example:

void robotMain(void)
{
    int     result = -1;
    MiP*    pMiP = mipInit(NULL);

    printf("\tOdometer.c - Use mipReadOdometer() and mipResetOdometer.\n"
           "\tRead out current odometer reading and reset.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    float cm = 0.0f;
    result = mipReadOdometer(pMiP, &cm);
    printf("MiP has travelled %f cm since the last reset.\n", cm);

    result = mipResetOdometer(pMiP);
    sleep(1);

    mipUninit(pMiP);
}

mipGetStatus

int mipGetStatus(MiP* pMiP, MiPStatus* pStatus);
Get the MiP's current status (battery level and position).

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pStatus: A pointer to the MiPStatus structure to be filled in with the contents of the current MiP status.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the status.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The battery field in the MiPStatus structure contains the current battery voltage level between 4.0V and 6.4V.
  • The position field in the MiPStatus structure indicates the current position of the MiP robot. The expected values are MIP_POSITION_ON_BACK, MIP_POSITION_FACE_DOWN, MIP_POSITION_UPRIGHT, MIP_POSITION_PICKED_UP , MIP_POSITION_HAND_STAND, MIP_POSITION_FACE_DOWN_ON_TRAY, or MIP_POSITION_ON_BACK_WITH_KICKSTAND.

Example:

void robotMain(void)
{
    int     result = -1;
    MiP*    pMiP = mipInit(NULL);

    printf("\tStatus.c - Use mipGetStatus() and mipGetLatestStatusNotification().\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPStatus status = {0, 0.0f, 0};
    result = mipGetStatus(pMiP, &status);
    printf("Call mipGetStatus()\n");
    printStatus(&status);

    printf("Waiting for next MiP status notification.\n");
    while (MIP_ERROR_NONE != mipGetLatestStatusNotification(pMiP, &status))
    {
    }
    printStatus(&status);

    mipUninit(pMiP);
}

static void printStatus(const MiPStatus* pStatus)
{
    printf("Battery voltage: %f\n", pStatus->battery);
    printf("Position: %d\n", pStatus->position);
}

mipGetWeight

int mipGetWeight(MiP* pMiP, MiPWeight* pWeight);
Get MiP's current weight / tilt reading.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pWeight: A pointer to the MiPWeight structure to be filled in with the contents of the current MiP weight / tilt reading.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the status.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The weight field in the MiPWeight structure contains the signed indication of how much it is tilted to keep its center of balance beneath the current weight.

Example:

void robotMain(void)
{
    int                    result = -1;
    MiP*                   pMiP = mipInit(NULL);

    printf("\tWeight.c - Use weight update functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPWeight weight = {0, 0};
    result = mipGetWeight(pMiP, &weight);
    printf("weight = %d\n", weight.weight);
    printf("Waiting for next weight update.\n");
    while (MIP_ERROR_NONE != mipGetLatestWeightNotification(pMiP, &weight))
    {
    }
    printf("weight = %d\n", weight.weight);

    mipUninit(pMiP);
}

mipGetClapSettings

int mipGetClapSettings(MiP* pMiP, MiPClapSettings* pSettings);
Get the current clap configuration (clap delay and enable settings).

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pSettings: A pointer to the MiPClapSettings structure to be filled in with the contents of the current MiP clap enable and delay settings.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the response.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The enabled field will indicate whether clap detection is enabled or not (MIP_CLAP_DISABLED or MIP_CLAP_ENABLED). It defaults to being in the disabled state.
  • The delay field indicates the current setting of the delay expected between claps. It defaults to 500.

Example:

void robotMain(void)
{
    int                    result = -1;
    MiP*                   pMiP = mipInit(NULL);

    printf("\tClap.c - Use clap related functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPClapSettings settings = {0, 0};
    result = mipGetClapSettings(pMiP, &settings);
    printf("Initial clap settings.\n");
    printClapSettings(&settings);

    // Modify clap settings.
    // NOTE: Need some delay between settings or second one will be dropped.
    result = mipEnableClap(pMiP, MIP_CLAP_ENABLED);
    sleep(1);
    result = mipSetClapDelay(pMiP, 501);

    result = mipGetClapSettings(pMiP, &settings);
    printf("Updated clap settings.\n");
    printClapSettings(&settings);

    printf("Waiting for user to clap.\n");
    MiPClap clap = {0, 0};
    while (MIP_ERROR_NONE != mipGetLatestClapNotification(pMiP, &clap))
    {
    }
    printf("Detected %u claps\n", clap.count);

    mipUninit(pMiP);
}

static void printClapSettings(const MiPClapSettings* pSettings)
{
    printf("  Enabled = %s\n", pSettings->enabled ? "ON" : "OFF");
    printf("    Delay = %u\n", pSettings->delay);
}

mipEnableClap

int mipEnableClap(MiP* pMiP, MiPClapEnabled enabled);
Enable or disable MiP clap detection.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • enabled: Should the clap detection feature be MIP_CLAP_DISABLED or MIP_CLAP_ENABLED.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The MiP defaults to having the clap feature disabled after an application attaches.
  • Attempting to set both the clap delay and this enable state too quickly in succession (< 1 second) can cause one of them to be ignored.

Example:

void robotMain(void)
{
    int                    result = -1;
    MiP*                   pMiP = mipInit(NULL);

    printf("\tClap.c - Use clap related functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPClapSettings settings = {0, 0};
    result = mipGetClapSettings(pMiP, &settings);
    printf("Initial clap settings.\n");
    printClapSettings(&settings);

    // Modify clap settings.
    // NOTE: Need some delay between settings or second one will be dropped.
    result = mipEnableClap(pMiP, MIP_CLAP_ENABLED);
    sleep(1);
    result = mipSetClapDelay(pMiP, 501);

    result = mipGetClapSettings(pMiP, &settings);
    printf("Updated clap settings.\n");
    printClapSettings(&settings);

    printf("Waiting for user to clap.\n");
    MiPClap clap = {0, 0};
    while (MIP_ERROR_NONE != mipGetLatestClapNotification(pMiP, &clap))
    {
    }
    printf("Detected %u claps\n", clap.count);

    mipUninit(pMiP);
}

static void printClapSettings(const MiPClapSettings* pSettings)
{
    printf("  Enabled = %s\n", pSettings->enabled ? "ON" : "OFF");
    printf("    Delay = %u\n", pSettings->delay);
}

mipSetClapDelay

int mipSetClapDelay(MiP* pMiP, uint16_t delay);
Sets the expected delay between user claps.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • delay: The new delay to be used for clap detection.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • I don't know what the units are for this setting. Maybe milliseconds?
  • The MiP defaults to having the clap delay set to 500 after the application first connects.
  • Attempting to set both the clap delay and the clap enable state too quickly in succession (< 1 second) can cause one of them to be ignored.

Example:

void robotMain(void)
{
    int                    result = -1;
    MiP*                   pMiP = mipInit(NULL);

    printf("\tClap.c - Use clap related functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPClapSettings settings = {0, 0};
    result = mipGetClapSettings(pMiP, &settings);
    printf("Initial clap settings.\n");
    printClapSettings(&settings);

    // Modify clap settings.
    // NOTE: Need some delay between settings or second one will be dropped.
    result = mipEnableClap(pMiP, MIP_CLAP_ENABLED);
    sleep(1);
    result = mipSetClapDelay(pMiP, 501);

    result = mipGetClapSettings(pMiP, &settings);
    printf("Updated clap settings.\n");
    printClapSettings(&settings);

    printf("Waiting for user to clap.\n");
    MiPClap clap = {0, 0};
    while (MIP_ERROR_NONE != mipGetLatestClapNotification(pMiP, &clap))
    {
    }
    printf("Detected %u claps\n", clap.count);

    mipUninit(pMiP);
}

static void printClapSettings(const MiPClapSettings* pSettings)
{
    printf("  Enabled = %s\n", pSettings->enabled ? "ON" : "OFF");
    printf("    Delay = %u\n", pSettings->delay);
}

mipGetLatestRadarNotification

int mipGetLatestRadarNotification(MiP* pMiP, MiPRadarNotification* pNotification);
Retrieves the most recent radar notification from the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pNotification: A pointer to the MiPRadarNotification structure to be filled in with the contents of the most recent radar notification from the MiP.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_EMPTY if the MiP hasn't sent a radar notification since the connection was made.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the radar notification.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • Must enable radar mode via the mipSetGestureRadarMode() function before the MiP will start sending notification of this type.
  • The millisec field in the returned MiPRadarNotification structure can be checked by the caller to see if this notification is the same as the last one retrieved since newer notifications will contain a different value in this field.
  • The radar field in the returned MiPRadarNotification structure will contain one of these values: MIP_RADAR_NONE (the MiP detects nothing in front of it), MIP_RADAR_10CM_30CM (the MiP detects something between 10cm and 30cm), and MIP_RADAR_0CM_10CM (the MiP detects something closer than 10cm).
  • These radar notifications will be suppressed while the MiP is executing long running commands. Shorter commands like mipContinuousDrive() do allow the MiP to send the notifications in a timely fashion.
  • These radar notifications will only be sent when the MiP is actively balancing. They will be suppressed if the MiP is laying back on its kickstand for example.

Example:

void robotMain(void)
{
    int                  result = -1;
    MiPRadarNotification radar = {0, MIP_RADAR_NONE};
    MiP*                 pMiP = mipInit(NULL);

    printf("\tRadar.c - Use mipGetLatestRadarNotification() function.\n"
           "\tProgram should end once you place your handle <10cm from MiP's face.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipSetGestureRadarMode(pMiP, MIP_RADAR);
    do
    {
        result = mipGetLatestRadarNotification(pMiP, &radar);
    } while (radar.radar != MIP_RADAR_0CM_10CM);

    mipUninit(pMiP);
}

mipGetLatestGestureNotification

int mipGetLatestGestureNotification(MiP* pMiP, MiPGestureNotification* pNotification);
Retrieves the most recent gesture notification from the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pNotification: A pointer to the MiPGestureNotification structure to be filled in with the contents of the most recent gesture notification from the MiP.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_EMPTY if the MiP hasn't sent a gesture notification since the connection was made.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the gesture notification.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • Must enable gesture mode via the mipSetGestureRadarMode() function before the MiP will start sending notification of this type.
  • The millisec field in the returned MiPGestureNotification structure can be checked by the caller to see if this notification is the same as the last one retrieved since newer notifications will contain a different value in this field.
  • The gesture field in the returned MiPGestureNotification structure will contain one of the values from the following table.
  • These gesture notifications will be suppressed while the MiP is executing long running commands. Shorter commands like mipContinuousDrive() do allow the MiP to send the notifications in a timely fashion.
  • These gesture notifications will only be sent when the MiP is actively balancing. They will be suppressed if the MiP is laying back on its kickstand for example.
MIP_GESTURE_LEFT
MIP_GESTURE_RIGHT
MIP_GESTURE_CENTER_SWEEP_LEFT
MIP_GESTURE_CENTER_SWEEP_RIGHT
MIP_GESTURE_CENTER_HOLD
MIP_GESTURE_FORWARD
MIP_GESTURE_BACKWARD

Example:

void robotMain(void)
{
    int                    result = -1;
    MiPGestureNotification gesture = {0, 0};
    MiP*                   pMiP = mipInit(NULL);

    printf("\tGesture.c - Use mipGetLatestGestureNotification() function.\n"
           "\tSwipe your hand in front of MiP to create gesture.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipSetGestureRadarMode(pMiP, MIP_GESTURE);

    while (MIP_ERROR_NONE != mipGetLatestGestureNotification(pMiP, &gesture))
    {
    }
    printf("Gesture = %d\n", gesture.gesture);

    mipUninit(pMiP);
}

mipGetLatestStatusNotification

int mipGetLatestStatusNotification(MiP* pMiP, MiPStatus* pStatus);
Retrieves the most recent status notification from the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pStatus: A pointer to the MiPStatus structure to be filled in with the contents of the latest MiP status.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_EMPTY if the MiP hasn't sent a radar notification since the connection was made.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the radar notification.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • This notification is sent every 30 seconds or earlier if the MiP detects a change in position.
  • The millisec field in the MiPStatus structure can be checked by the caller to see if this notification is the same as the last one retrieved since newer notifications will contain a different value in this field.
  • The battery field in the MiPStatus structure contains the current battery voltage level between 4.0V and 6.4V.
  • The position field in the MiPStatus structure indicates the current position of the MiP robot. The expected values are MIP_POSITION_ON_BACK, MIP_POSITION_FACE_DOWN, MIP_POSITION_UPRIGHT, MIP_POSITION_PICKED_UP , MIP_POSITION_HAND_STAND, MIP_POSITION_FACE_DOWN_ON_TRAY, or MIP_POSITION_ON_BACK_WITH_KICKSTAND.

Example:

void robotMain(void)
{
    int     result = -1;
    MiP*    pMiP = mipInit(NULL);

    printf("\tStatus.c - Use mipGetStatus() and mipGetLatestStatusNotification().\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPStatus status = {0, 0.0f, 0};
    result = mipGetStatus(pMiP, &status);
    printf("Call mipGetStatus()\n");
    printStatus(&status);

    printf("Waiting for next MiP status notification.\n");
    while (MIP_ERROR_NONE != mipGetLatestStatusNotification(pMiP, &status))
    {
    }
    printStatus(&status);

    mipUninit(pMiP);
}

static void printStatus(const MiPStatus* pStatus)
{
    printf("Battery voltage: %f\n", pStatus->battery);
    printf("Position: %d\n", pStatus->position);
}

mipGetLatestShakeNotification

int mipGetLatestShakeNotification(MiP* pMiP);
Determine whether the MiP has been shaken since the last call.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_EMPTY if the MiP hasn't sent a shake notification since the last call.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the shake notification.
  • Non-zero MIP_ERROR_* code otherwise.

Example:

void robotMain(void)
{
    int                    result = -1;
    MiP*                   pMiP = mipInit(NULL);

    printf("\tShake.c - Use mipGetLatestShakeNotification() function.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    printf("Waiting for user to shake MiP.\n");
    while (MIP_ERROR_NONE != mipGetLatestShakeNotification(pMiP))
    {
    }
    printf("Shake detected.\n");

    mipUninit(pMiP);
}

mipGetLatestWeightNotification

int mipGetLatestWeightNotification(MiP* pMiP, MiPWeight* pWeight);
Retrieves the most recent weight / tilt status from the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pWeight: A pointer to the MiPWeight structure to be filled in with the contents of the latest MiP weight / tilt status.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_EMPTY if the MiP hasn't sent a weight notification since the connection was made.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected value in the weight notification.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The millisec field in the MiPWeight structure can be checked by the caller to see if this notification is the same as the last one retrieved since newer notifications will contain a different value in this field.
  • The weight field in the MiPWeight structure contains the signed indication of how much it is tilted to keep its center of balance beneath the current weight.

Example:

void robotMain(void)
{
    int                    result = -1;
    MiP*                   pMiP = mipInit(NULL);

    printf("\tWeight.c - Use weight update functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPWeight weight = {0, 0};
    result = mipGetWeight(pMiP, &weight);
    printf("weight = %d\n", weight.weight);
    printf("Waiting for next weight update.\n");
    while (MIP_ERROR_NONE != mipGetLatestWeightNotification(pMiP, &weight))
    {
    }
    printf("weight = %d\n", weight.weight);

    mipUninit(pMiP);
}

mipGetLatestClapNotification

int mipGetLatestClapNotification(MiP* pMiP, MiPClap* pClap);
Retrieves the most recent clap count detected by the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pClap: A pointer to the MiPClap structure to be filled in with the information describing the latest MiP clap detection.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_EMPTY if the MiP hasn't sent a clap notification since the connection was made.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The millisec field in the MiPClap structure can be checked by the caller to see if this notification is the same as the last one retrieved since newer notifications will contain a different value in this field.
  • The count field in the MiPClap structure contains the number of claps detected in the last event.

Example:

void robotMain(void)
{
    int                    result = -1;
    MiP*                   pMiP = mipInit(NULL);

    printf("\tClap.c - Use clap related functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    MiPClapSettings settings = {0, 0};
    result = mipGetClapSettings(pMiP, &settings);
    printf("Initial clap settings.\n");
    printClapSettings(&settings);

    // Modify clap settings.
    // NOTE: Need some delay between settings or second one will be dropped.
    result = mipEnableClap(pMiP, MIP_CLAP_ENABLED);
    sleep(1);
    result = mipSetClapDelay(pMiP, 501);

    result = mipGetClapSettings(pMiP, &settings);
    printf("Updated clap settings.\n");
    printClapSettings(&settings);

    printf("Waiting for user to clap.\n");
    MiPClap clap = {0, 0};
    while (MIP_ERROR_NONE != mipGetLatestClapNotification(pMiP, &clap))
    {
    }
    printf("Detected %u claps\n", clap.count);

    mipUninit(pMiP);
}

static void printClapSettings(const MiPClapSettings* pSettings)
{
    printf("  Enabled = %s\n", pSettings->enabled ? "ON" : "OFF");
    printf("    Delay = %u\n", pSettings->delay);
}

mipGetSoftwareVersion

int mipGetSoftwareVersion(MiP* pMiP, MiPSoftwareVersion* pSoftware);
Get the version information for the software in the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pSoftware: A pointer to the MiPSoftwareVersion structure to be filled in with the version information of the MiP software.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected response.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The MiPSoftwareVersion structure has year, month, day, and uniqueVersion fields. The uniqueVersion field is used to differentiate between software builds from the same day.

Example:

void robotMain(void)
{
    int                result = -1;
    MiPSoftwareVersion softwareVersion;
    MiPHardwareInfo    hardwareInfo;
    MiP*               pMiP = mipInit(NULL);

    printf("\tGetSoftwareHardwareVersion.c - Use mipGetSoftwareVersion() & mipGetHardwareInfo() functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipGetSoftwareVersion(pMiP, &softwareVersion);
    result = mipGetHardwareInfo(pMiP, &hardwareInfo);

    printf("software version: %u-%u-%u.%u\n",
           softwareVersion.year,
           softwareVersion.month,
           softwareVersion.day,
           softwareVersion.uniqueVersion);
    printf("hardware info\n");
    printf("  voice chip version: %u\n", hardwareInfo.voiceChip);
    printf("    hardware version: %u\n", hardwareInfo.hardware);

    mipUninit(pMiP);
}

mipGetHardwareInfo

int mipGetHardwareInfo(MiP* pMiP, MiPHardwareInfo* pHardware);
Get the version information for the hardware in the MiP.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pHardware: A pointer to the MiPHardwareInfo structure to be filled in with the version information of the MiP hardware.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_BAD_RESPONSE if the MiP sent back an unexpected response.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • The MiPHardwareInfo structure has voiceChip and hardware fields.

Example:

void robotMain(void)
{
    int                result = -1;
    MiPSoftwareVersion softwareVersion;
    MiPHardwareInfo    hardwareInfo;
    MiP*               pMiP = mipInit(NULL);

    printf("\tGetSoftwareHardwareVersion.c - Use mipGetSoftwareVersion() & mipGetHardwareInfo() functions.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    result = mipGetSoftwareVersion(pMiP, &softwareVersion);
    result = mipGetHardwareInfo(pMiP, &hardwareInfo);

    printf("software version: %u-%u-%u.%u\n",
           softwareVersion.year,
           softwareVersion.month,
           softwareVersion.day,
           softwareVersion.uniqueVersion);
    printf("hardware info\n");
    printf("  voice chip version: %u\n", hardwareInfo.voiceChip);
    printf("    hardware version: %u\n", hardwareInfo.hardware);

    mipUninit(pMiP);
}

mipRawSend

int mipRawSend(MiP* pMiP, const uint8_t* pRequest, size_t requestLength);
Send a raw command to the MiP robot.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pRequest: Is a pointer to the array of the command bytes to be sent to the robot.
  • requestLength: Is the number of bytes in the pRequest buffer to be sent to the robot.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • There are typically higher level APIs that can be used to send commands to the MiP but in cases where the functionality you need isn't already implemented in the MiP C API, you can use this function to send the raw command bytes directly to the MiP.

Example:

void robotMain(void)
{
    int     result = -1;
    size_t  responseLength = 0;
    uint8_t response[MIP_RESPONSE_MAX_LEN];
    MiP*    pMiP = mipInit(NULL);

    printf("\tRawSendReceive.c - Use mipRaw*() functions.\n"
           "\tShould set chest LED to purple and display MiP firmware revision\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    // Send 4-byte MiP command to set Chest LED to Purple.
    static const uint8_t setChestPurple[] = "\x84\xFF\x01\xFF";
    result = mipRawSend(pMiP, setChestPurple, sizeof(setChestPurple)-1);

    // Request the MiP firmware revision information and display it.
    static const uint8_t getMiPSoftwareVersion[] = "\x14";
    result = mipRawReceive(pMiP, getMiPSoftwareVersion, sizeof(getMiPSoftwareVersion)-1,
                                 response, sizeof(response), &responseLength);
    if (result == MIP_ERROR_NONE && responseLength == 5 && response[0] == 0x14)
    {
        printf("\tMiP Software Version: %d-%d-%d (build #%d)\n",
               response[1] + 2000,
               response[2],
               response[3],
               response[4]);
    }

    mipUninit(pMiP);
}

mipRawReceive

int mipRawReceive(MiP* pMiP, const uint8_t* pRequest, size_t requestLength, uint8_t* pResponseBuffer, size_t responseBufferSize, size_t* pResponseLength);
Send a raw request to the MiP and receive its raw response.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pRequest: Is a pointer to the array of the command bytes to be sent to the robot.
  • requestLength: Is the number of bytes in the pRequest buffer to be sent to the robot.
  • pResponseBuffer: Is a pointer to the array of bytes into which the response should be copied.
  • responseBufferSize: Is the number of bytes in the pResponseBuffer.
  • pResponseLength: Is a pointer to where the actual number of bytes in the response should be placed. This value may be truncated to responseBufferSize if the actual response was > responseBufferSize.

Returns:

  • MIP_ERROR_NONE on success.
  • MIP_ERROR_TIMEOUT if MiP doesn't respond to request after multiple retries.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • There are typically higher level APIs that can be used to send requests to the MiP but in cases where the functionality you need isn't already implemented in the MiP C API, you can use this function to send the raw request to the MiP and receive the raw resulting bytes.

Example:

void robotMain(void)
{
    int     result = -1;
    size_t  responseLength = 0;
    uint8_t response[MIP_RESPONSE_MAX_LEN];
    MiP*    pMiP = mipInit(NULL);

    printf("\tRawSendReceive.c - Use mipRaw*() functions.\n"
           "\tShould set chest LED to purple and display MiP firmware revision\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    // Send 4-byte MiP command to set Chest LED to Purple.
    static const uint8_t setChestPurple[] = "\x84\xFF\x01\xFF";
    result = mipRawSend(pMiP, setChestPurple, sizeof(setChestPurple)-1);

    // Request the MiP firmware revision information and display it.
    static const uint8_t getMiPSoftwareVersion[] = "\x14";
    result = mipRawReceive(pMiP, getMiPSoftwareVersion, sizeof(getMiPSoftwareVersion)-1,
                                 response, sizeof(response), &responseLength);
    if (result == MIP_ERROR_NONE && responseLength == 5 && response[0] == 0x14)
    {
        printf("\tMiP Software Version: %d-%d-%d (build #%d)\n",
               response[1] + 2000,
               response[2],
               response[3],
               response[4]);
    }

    mipUninit(pMiP);
}

mipRawReceiveNotification

int mipRawReceiveNotification(MiP* pMiP, uint8_t* pNotifyBuffer, size_t notifyBufferSize, size_t* pNotifyLength);
Get an out of band notification sent by the MiP robot.

Parameters:

  • pMiP: An object that was previously returned from the mipInit() call.
  • pNotifyBuffer: Is a pointer to the array of bytes into which the notification should be copied.
  • notifyBufferSize: Is the number of bytes in the pNotifyBuffer.
  • pNotifyLength: Is a pointer to where the actual number of bytes in the notification should be placed. This value may be truncated to notifyBufferSize if the actual response was > notifyBufferSize.

Returns:

  • MIP_ERROR_NONE on success.
  • Non-zero MIP_ERROR_* code otherwise.

Notes:

  • Sometimes the MiP robot sends notifications which aren't in direct response to the last request made. This function will return one of these responses/notifications.
  • There are typically higher level APIs that can be used to receive latest notifications from the MiP but in cases where the functionality you need isn't already implemented in the MiP C API, you can use this function instead.

Example:

void robotMain(void)
{
    int     result = -1;
    size_t  responseLength = 0;
    uint8_t response[MIP_RESPONSE_MAX_LEN];
    MiP*    pMiP = mipInit(NULL);

    printf("\tRawReceiveNotification.c - Use mipRawReceiveNotification() functions.\n"
           "\tIn less than half a minute, a notification should be displayed.\n");

    // Connect to first MiP robot discovered.
    result = mipConnectToRobot(pMiP, NULL);

    // Wait for first out of band notification to arrive.
    while (MIP_ERROR_EMPTY == mipRawReceiveNotification(pMiP, response, sizeof(response), &responseLength))
    {
    }

    // Display notification contents.
    printf("notification -> ");
    for (int i = 0 ; i < responseLength ; i++)
    {
        printf("%02X", response[i]);
    }
    printf("\n");

    mipUninit(pMiP);
}

About

C API for the WowWee MiP self-balancing robot.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published