Basic demo that shows how to control a Zumo shield using ST X-NUCLEO-IDB04A1 BlueTooth Low energy shield.

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 ZumoShield mbed

ST BLE shield: https://developer.mbed.org/components/X-NUCLEO-IDB04A1/

/media/uploads/bcostm/nucleo-ble-shield.jpg

Zumo shield: https://www.pololu.com/category/169/zumo-robot-for-arduino

/media/uploads/bcostm/zumo.jpg

Android Application: TBD

main.cpp

Committer:
bcostm
Date:
2015-10-12
Revision:
1:f9ed96482986
Parent:
0:901651f381c9

File content as of revision 1:f9ed96482986:

#include "mbed.h"
#include "BLE.h"
#include "SampleService.h"
#include "DeviceInformationService.h"
#include "x_nucleo_idb0xa1_targets.h"
#include "ZumoShield.h"

// See also the file X_NUCLEO_IDB0XA1/x_nucleo_idb0xa1_targets.h to configure
// the correct SPI clock (D3 or D13 pin).

// Configuration for NUCLEO_F401RE/F030R8/F070RB/F072RB/F091RC/F303RE/F334R8/F411RE/F446RE/L152RE/L476RG
#define PWM1 D9
#define PWM2 D10
// Configuration for NUCLEO_F103RB
//#define PWM1 D9
//#define PWM2 D2
// Configuration for NUCLEO_F302R8
//#define PWM1 D2
//#define PWM2 D10
// Configuration for NUCLEO_L053R8
//#define PWM1 D9
//#define PWM2 PA_15 // on Morpho connector

#define PC_DEBUG(args...) printf(args)

// Bluetooth Low Energy (BLE) device
BLE ble;
// BLE Primary Service
SampleService *sampleService;

ZumoShield zumo(
//  Function      Nucleo board   Zumo shield
    /* Motor 1 PWM */ PWM1,          // D9  !!! WARNING !!! see configuration above
    /* Motor 1 DIR */ D6,            // D7  !!! WARNING !!!
    /* Motor 2 PWM */ PWM2,          // D10 !!! WARNING !!! see configuration above
    /* Motor 2 DIR */ D8             // D8
);

// Hardware device selection
BusIn device_id(D15, D14);

// Parameters for Bluetooth Low Energy
uint8_t DEVICE_NAME[] = "Zumo_car_X"; // X is defined below with value of device_id
Gap::Address_t BLE_address_BE; // defined below with value of device_id

static const uint16_t uuid16_list[] = {SampleServiceShortUUID, GattService::UUID_DEVICE_INFORMATION_SERVICE};

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    ble.startAdvertising(); // restart advertising
}

void remoteControlCallback(const uint8_t* data, uint16_t len)
{
    float speed = 0;

    // Check if this is a remote control command (3-byte len and starting with a null byte)
    if ( (data[0]) || (len != 3) ) return;

    // data is a 3-byte sequence
    // first byte is always null
    // second byte is vertical slider position (speed)
    // third byte is horizontal slider position (direction)
    int s = data[1]; // speed (0-100)
    int d = data[2]; // direction (0-100)

    PC_DEBUG(">>> Speed=%d, Direction=%d\r\n", s, d);

    if ((s == 50) && (d == 50)) {
        zumo.stopAll();
        return;
    }

    if (s > 50) {
        speed = float(s)/100;
        if (d == 50) {
            zumo.forward(speed);
            return;
        }
    } else if (s < 50) {
        speed = (100-float(s))/100;
        if (d == 50) {
            zumo.backward(speed);
            return;
        }
    }

    if (d > 50) {
        if (s > 50) {
            zumo.turn_right(speed);
        } else if (s < 50) {
            zumo.turn_left(-speed);
        } else { // s == 50
            speed = float(d)/100;
            zumo.right(speed);
        }
    } else if (d < 50) {
        if (s > 50) {
            zumo.turn_left(speed);
        } else if (s < 50) {
            zumo.turn_right(-speed);
        } else { // s == 50
            speed = (100-float(d))/100;
            zumo.left(speed);
        }
    }

}

// Setup Bluetooth Low Energy device
void setup_BLE(void)
{
    // Set BLE device name and address
    BLE_address_BE[0] = 0xca;
    BLE_address_BE[1] = 0xcc;
    BLE_address_BE[2] = 0x61;
    BLE_address_BE[3] = 0xab;
    BLE_address_BE[4] = 0xef;
    BLE_address_BE[5] = device_id;
    DEVICE_NAME[9] = '0' + device_id;

    // Set BT Address
    ble.setAddress(Gap::ADDR_TYPE_PUBLIC, BLE_address_BE);

    // Init the BLE dev
    ble.init();
    ble.onDisconnection(disconnectionCallback);

    /* Setup primary service. */
    sampleService = new SampleService(ble, remoteControlCallback);

    /* Setup auxiliary service. */
    DeviceInformationService deviceInfo(ble, "STM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");

    /* Setup advertising. */
    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
    ble.accumulateAdvertisingPayload(GapAdvertisingData::UNKNOWN);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.setAdvertisingInterval(1000);
    ble.startAdvertising();
}

int main()
{
    PC_DEBUG(">>> Bluetooth Low Energy setup...\r\n");
    setup_BLE();
    PC_DEBUG(">>> Setup done\r\n");

    // Check motors
    zumo.right(1.0);
    wait(0.5);
    zumo.left(1.0);
    wait(0.5);
    zumo.stopAll();

    while (1) {
        ble.waitForEvent(); // low power wait for event. Must be called in the loop or BLE won't work
    }
}