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/
Zumo shield: https://www.pololu.com/category/169/zumo-robot-for-arduino
Android Application: TBD
main.cpp@1:f9ed96482986, 2015-10-12 (annotated)
- Committer:
- bcostm
- Date:
- Mon Oct 12 11:35:56 2015 +0000
- Revision:
- 1:f9ed96482986
- Parent:
- 0:901651f381c9
Initial version.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bcostm | 0:901651f381c9 | 1 | #include "mbed.h" |
bcostm | 0:901651f381c9 | 2 | #include "BLE.h" |
bcostm | 0:901651f381c9 | 3 | #include "SampleService.h" |
bcostm | 0:901651f381c9 | 4 | #include "DeviceInformationService.h" |
bcostm | 0:901651f381c9 | 5 | #include "x_nucleo_idb0xa1_targets.h" |
bcostm | 0:901651f381c9 | 6 | #include "ZumoShield.h" |
bcostm | 0:901651f381c9 | 7 | |
bcostm | 0:901651f381c9 | 8 | // See also the file X_NUCLEO_IDB0XA1/x_nucleo_idb0xa1_targets.h to configure |
bcostm | 0:901651f381c9 | 9 | // the correct SPI clock (D3 or D13 pin). |
bcostm | 0:901651f381c9 | 10 | |
bcostm | 0:901651f381c9 | 11 | // Configuration for NUCLEO_F401RE/F030R8/F070RB/F072RB/F091RC/F303RE/F334R8/F411RE/F446RE/L152RE/L476RG |
bcostm | 0:901651f381c9 | 12 | #define PWM1 D9 |
bcostm | 0:901651f381c9 | 13 | #define PWM2 D10 |
bcostm | 0:901651f381c9 | 14 | // Configuration for NUCLEO_F103RB |
bcostm | 0:901651f381c9 | 15 | //#define PWM1 D9 |
bcostm | 0:901651f381c9 | 16 | //#define PWM2 D2 |
bcostm | 0:901651f381c9 | 17 | // Configuration for NUCLEO_F302R8 |
bcostm | 0:901651f381c9 | 18 | //#define PWM1 D2 |
bcostm | 0:901651f381c9 | 19 | //#define PWM2 D10 |
bcostm | 0:901651f381c9 | 20 | // Configuration for NUCLEO_L053R8 |
bcostm | 0:901651f381c9 | 21 | //#define PWM1 D9 |
bcostm | 0:901651f381c9 | 22 | //#define PWM2 PA_15 // on Morpho connector |
bcostm | 0:901651f381c9 | 23 | |
bcostm | 0:901651f381c9 | 24 | #define PC_DEBUG(args...) printf(args) |
bcostm | 0:901651f381c9 | 25 | |
bcostm | 0:901651f381c9 | 26 | // Bluetooth Low Energy (BLE) device |
bcostm | 0:901651f381c9 | 27 | BLE ble; |
bcostm | 0:901651f381c9 | 28 | // BLE Primary Service |
bcostm | 0:901651f381c9 | 29 | SampleService *sampleService; |
bcostm | 0:901651f381c9 | 30 | |
bcostm | 0:901651f381c9 | 31 | ZumoShield zumo( |
bcostm | 0:901651f381c9 | 32 | // Function Nucleo board Zumo shield |
bcostm | 0:901651f381c9 | 33 | /* Motor 1 PWM */ PWM1, // D9 !!! WARNING !!! see configuration above |
bcostm | 0:901651f381c9 | 34 | /* Motor 1 DIR */ D6, // D7 !!! WARNING !!! |
bcostm | 0:901651f381c9 | 35 | /* Motor 2 PWM */ PWM2, // D10 !!! WARNING !!! see configuration above |
bcostm | 0:901651f381c9 | 36 | /* Motor 2 DIR */ D8 // D8 |
bcostm | 0:901651f381c9 | 37 | ); |
bcostm | 0:901651f381c9 | 38 | |
bcostm | 0:901651f381c9 | 39 | // Hardware device selection |
bcostm | 0:901651f381c9 | 40 | BusIn device_id(D15, D14); |
bcostm | 0:901651f381c9 | 41 | |
bcostm | 0:901651f381c9 | 42 | // Parameters for Bluetooth Low Energy |
bcostm | 0:901651f381c9 | 43 | uint8_t DEVICE_NAME[] = "Zumo_car_X"; // X is defined below with value of device_id |
bcostm | 0:901651f381c9 | 44 | Gap::Address_t BLE_address_BE; // defined below with value of device_id |
bcostm | 0:901651f381c9 | 45 | |
bcostm | 0:901651f381c9 | 46 | static const uint16_t uuid16_list[] = {SampleServiceShortUUID, GattService::UUID_DEVICE_INFORMATION_SERVICE}; |
bcostm | 0:901651f381c9 | 47 | |
bcostm | 0:901651f381c9 | 48 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
bcostm | 0:901651f381c9 | 49 | { |
bcostm | 0:901651f381c9 | 50 | ble.startAdvertising(); // restart advertising |
bcostm | 0:901651f381c9 | 51 | } |
bcostm | 0:901651f381c9 | 52 | |
bcostm | 0:901651f381c9 | 53 | void remoteControlCallback(const uint8_t* data, uint16_t len) |
bcostm | 0:901651f381c9 | 54 | { |
bcostm | 0:901651f381c9 | 55 | float speed = 0; |
bcostm | 0:901651f381c9 | 56 | |
bcostm | 0:901651f381c9 | 57 | // Check if this is a remote control command (3-byte len and starting with a null byte) |
bcostm | 0:901651f381c9 | 58 | if ( (data[0]) || (len != 3) ) return; |
bcostm | 0:901651f381c9 | 59 | |
bcostm | 0:901651f381c9 | 60 | // data is a 3-byte sequence |
bcostm | 0:901651f381c9 | 61 | // first byte is always null |
bcostm | 0:901651f381c9 | 62 | // second byte is vertical slider position (speed) |
bcostm | 0:901651f381c9 | 63 | // third byte is horizontal slider position (direction) |
bcostm | 0:901651f381c9 | 64 | int s = data[1]; // speed (0-100) |
bcostm | 0:901651f381c9 | 65 | int d = data[2]; // direction (0-100) |
bcostm | 0:901651f381c9 | 66 | |
bcostm | 0:901651f381c9 | 67 | PC_DEBUG(">>> Speed=%d, Direction=%d\r\n", s, d); |
bcostm | 0:901651f381c9 | 68 | |
bcostm | 0:901651f381c9 | 69 | if ((s == 50) && (d == 50)) { |
bcostm | 0:901651f381c9 | 70 | zumo.stopAll(); |
bcostm | 0:901651f381c9 | 71 | return; |
bcostm | 0:901651f381c9 | 72 | } |
bcostm | 0:901651f381c9 | 73 | |
bcostm | 0:901651f381c9 | 74 | if (s > 50) { |
bcostm | 0:901651f381c9 | 75 | speed = float(s)/100; |
bcostm | 0:901651f381c9 | 76 | if (d == 50) { |
bcostm | 0:901651f381c9 | 77 | zumo.forward(speed); |
bcostm | 0:901651f381c9 | 78 | return; |
bcostm | 0:901651f381c9 | 79 | } |
bcostm | 0:901651f381c9 | 80 | } else if (s < 50) { |
bcostm | 0:901651f381c9 | 81 | speed = (100-float(s))/100; |
bcostm | 0:901651f381c9 | 82 | if (d == 50) { |
bcostm | 0:901651f381c9 | 83 | zumo.backward(speed); |
bcostm | 0:901651f381c9 | 84 | return; |
bcostm | 0:901651f381c9 | 85 | } |
bcostm | 0:901651f381c9 | 86 | } |
bcostm | 0:901651f381c9 | 87 | |
bcostm | 0:901651f381c9 | 88 | if (d > 50) { |
bcostm | 0:901651f381c9 | 89 | if (s > 50) { |
bcostm | 0:901651f381c9 | 90 | zumo.turn_right(speed); |
bcostm | 0:901651f381c9 | 91 | } else if (s < 50) { |
bcostm | 0:901651f381c9 | 92 | zumo.turn_left(-speed); |
bcostm | 0:901651f381c9 | 93 | } else { // s == 50 |
bcostm | 0:901651f381c9 | 94 | speed = float(d)/100; |
bcostm | 0:901651f381c9 | 95 | zumo.right(speed); |
bcostm | 0:901651f381c9 | 96 | } |
bcostm | 0:901651f381c9 | 97 | } else if (d < 50) { |
bcostm | 0:901651f381c9 | 98 | if (s > 50) { |
bcostm | 0:901651f381c9 | 99 | zumo.turn_left(speed); |
bcostm | 0:901651f381c9 | 100 | } else if (s < 50) { |
bcostm | 0:901651f381c9 | 101 | zumo.turn_right(-speed); |
bcostm | 0:901651f381c9 | 102 | } else { // s == 50 |
bcostm | 0:901651f381c9 | 103 | speed = (100-float(d))/100; |
bcostm | 0:901651f381c9 | 104 | zumo.left(speed); |
bcostm | 0:901651f381c9 | 105 | } |
bcostm | 0:901651f381c9 | 106 | } |
bcostm | 0:901651f381c9 | 107 | |
bcostm | 0:901651f381c9 | 108 | } |
bcostm | 0:901651f381c9 | 109 | |
bcostm | 0:901651f381c9 | 110 | // Setup Bluetooth Low Energy device |
bcostm | 0:901651f381c9 | 111 | void setup_BLE(void) |
bcostm | 0:901651f381c9 | 112 | { |
bcostm | 0:901651f381c9 | 113 | // Set BLE device name and address |
bcostm | 0:901651f381c9 | 114 | BLE_address_BE[0] = 0xca; |
bcostm | 0:901651f381c9 | 115 | BLE_address_BE[1] = 0xcc; |
bcostm | 0:901651f381c9 | 116 | BLE_address_BE[2] = 0x61; |
bcostm | 0:901651f381c9 | 117 | BLE_address_BE[3] = 0xab; |
bcostm | 0:901651f381c9 | 118 | BLE_address_BE[4] = 0xef; |
bcostm | 0:901651f381c9 | 119 | BLE_address_BE[5] = device_id; |
bcostm | 0:901651f381c9 | 120 | DEVICE_NAME[9] = '0' + device_id; |
bcostm | 0:901651f381c9 | 121 | |
bcostm | 0:901651f381c9 | 122 | // Set BT Address |
bcostm | 0:901651f381c9 | 123 | ble.setAddress(Gap::ADDR_TYPE_PUBLIC, BLE_address_BE); |
bcostm | 0:901651f381c9 | 124 | |
bcostm | 0:901651f381c9 | 125 | // Init the BLE dev |
bcostm | 0:901651f381c9 | 126 | ble.init(); |
bcostm | 0:901651f381c9 | 127 | ble.onDisconnection(disconnectionCallback); |
bcostm | 0:901651f381c9 | 128 | |
bcostm | 0:901651f381c9 | 129 | /* Setup primary service. */ |
bcostm | 0:901651f381c9 | 130 | sampleService = new SampleService(ble, remoteControlCallback); |
bcostm | 0:901651f381c9 | 131 | |
bcostm | 0:901651f381c9 | 132 | /* Setup auxiliary service. */ |
bcostm | 0:901651f381c9 | 133 | DeviceInformationService deviceInfo(ble, "STM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); |
bcostm | 0:901651f381c9 | 134 | |
bcostm | 0:901651f381c9 | 135 | /* Setup advertising. */ |
bcostm | 0:901651f381c9 | 136 | ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
bcostm | 0:901651f381c9 | 137 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); |
bcostm | 0:901651f381c9 | 138 | ble.accumulateAdvertisingPayload(GapAdvertisingData::UNKNOWN); |
bcostm | 0:901651f381c9 | 139 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
bcostm | 0:901651f381c9 | 140 | ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
bcostm | 0:901651f381c9 | 141 | ble.setAdvertisingInterval(1000); |
bcostm | 0:901651f381c9 | 142 | ble.startAdvertising(); |
bcostm | 0:901651f381c9 | 143 | } |
bcostm | 0:901651f381c9 | 144 | |
bcostm | 0:901651f381c9 | 145 | int main() |
bcostm | 0:901651f381c9 | 146 | { |
bcostm | 0:901651f381c9 | 147 | PC_DEBUG(">>> Bluetooth Low Energy setup...\r\n"); |
bcostm | 0:901651f381c9 | 148 | setup_BLE(); |
bcostm | 0:901651f381c9 | 149 | PC_DEBUG(">>> Setup done\r\n"); |
bcostm | 0:901651f381c9 | 150 | |
bcostm | 0:901651f381c9 | 151 | // Check motors |
bcostm | 0:901651f381c9 | 152 | zumo.right(1.0); |
bcostm | 0:901651f381c9 | 153 | wait(0.5); |
bcostm | 0:901651f381c9 | 154 | zumo.left(1.0); |
bcostm | 0:901651f381c9 | 155 | wait(0.5); |
bcostm | 0:901651f381c9 | 156 | zumo.stopAll(); |
bcostm | 0:901651f381c9 | 157 | |
bcostm | 0:901651f381c9 | 158 | while (1) { |
bcostm | 0:901651f381c9 | 159 | ble.waitForEvent(); // low power wait for event. Must be called in the loop or BLE won't work |
bcostm | 0:901651f381c9 | 160 | } |
bcostm | 0:901651f381c9 | 161 | } |