Final Project¶
Ali Redha and I worked on making a bluetooth control boat using Adafruit Feather.
Main Documentation¶
Click here for the project documentation
Research¶
In this project, an adafruit feather board was programmed to control the motion of a simple boat through Bluetooth signals by linking the bluefruit app to the board and using control pad.
Materials¶
| Qty | Description | Price | Link | Notes | 
|---|---|---|---|---|
| 1 | Adafruit Feather | $37.50 | https://www.adafruit.com/product/4516 | |
| 1 | 9 Volt battery | $6.19 | http://amazon.com/test | |
| 2 | Motors | $5.51 | http://amazon.com/test | |
| 2 | Fans | $4.50 | http://amazon.com/test | |
| 1 | L298N Motor Driver | $11.49 | http://amazon.com/test | |
| 1 | Breadboard | $5.99 | http://amazon.com/test | |
| 20 | Jumpers | $3.40 | http://amazon.com/test | |
| 1 | WaterProof Tape | $3.00 | http://amazon.com/test | 
2D Boat Modeling¶
The boat was designed using the TinkerCad website
The minimum boat volume to float= Load Mass/(Water Density-Boat Density) = 2kg/(1030-48)kg =0.002m^3
The 3D design has transformed into 2D parts using Papercraft Maker Website The design was obtained by laser cutting using a cutting machine.
For more about Computer controlled cutting process

Input & Output device¶
Using the BluefruitConnect smartphone application to control the motors. While the boat requires two motors, and the microcontroller was not delivering a specific amount of current and voltage for the motors, an L298N Motor Driver will be helpful to allow controlling the two motors.
Connections¶
In the motor driver, the A&B motors are connected to the four outputs, 9 Volt battery connected to VS and GND, another connection for GND to the GNC pin in the adafruit, the inputs connections are: in1 = 10, in2 = 11, in3 = A4, in4 = A5.

The motors motion principle¶

After uploading the code which is noted down, we link the BluefruitConnect app to the board using control pad.

For more about Input & Output device
Testing¶
Code¶
#include <bluefruit.h>
int in1 = 10;
int in2 = 11;
int in3 = A4;
int in4 = A5;
// OTA DFU service
BLEDfu bledfu;
// Uart over BLE service
BLEUart bleuart;
// Function prototypes for packetparser.cpp
uint8_t readPacket (BLEUart *ble_uart, uint16_t timeout);
float   parsefloat (uint8_t *buffer);
void    printHex   (const uint8_t * data, const uint32_t numBytes);
// Packet buffer
extern uint8_t packetbuffer[];
void setup(void)
{
  Serial.begin(115200);
  while ( !Serial ) delay(10);   // for nrf52840 with native usb
  Serial.println(F("Adafruit Bluefruit52 Controller App Example"));
  Serial.println(F("-------------------------------------------"));
  Bluefruit.begin();
  Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values
  // To be consistent OTA DFU should be added first if it exists
  bledfu.begin();
  // Configure and start the BLE Uart service
  bleuart.begin();
  // Set up and start advertising
  startAdv();
  Serial.println(F("Please use Adafruit Bluefruit LE app to connect in Controller mode"));
  Serial.println(F("Then activate/use the sensors, color picker, game controller, etc!"));
  Serial.println();  
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
}
void startAdv(void)
{
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  // Include the BLE UART (AKA 'NUS') 128-bit UUID
  Bluefruit.Advertising.addService(bleuart);
  // Secondary Scan Response packet (optional)
  // Since there is no room for 'Name' in Advertising packet
  Bluefruit.ScanResponse.addName();
  /* Start Advertising
   * - Enable auto advertising if disconnected
   * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   *
   *   
   */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds  
}
/**************************************************************************/
void loop(void)
{
  // Wait for new data to arrive
  uint8_t len = readPacket(&bleuart, 500);
  if (len == 0) return;
  // Got a packet!
  // printHex(packetbuffer, len);
  // Color
  if (packetbuffer[1] == 'C') {
    uint8_t red = packetbuffer[2];
    uint8_t green = packetbuffer[3];
    uint8_t blue = packetbuffer[4];
    Serial.print ("RGB #");
    if (red < 0x10) Serial.print("0");
    Serial.print(red, HEX);
    if (green < 0x10) Serial.print("0");
    Serial.print(green, HEX);
    if (blue < 0x10) Serial.print("0");
    Serial.println(blue, HEX);
  }
  // Buttons
  if (packetbuffer[1] == 'B') {
    uint8_t buttnum = packetbuffer[2] - '0';
    boolean pressed = packetbuffer[3] - '0';
    Serial.print ("Button "); Serial.print(buttnum);
    if (pressed){
    if (pressed & buttnum==5 ) {
      Serial.println(" pressed");
      digitalWrite(in2, HIGH);
      digitalWrite(in3, LOW);    //forward ok
      digitalWrite(in1, LOW);
      digitalWrite(in4, HIGH);
    }
    if (pressed & buttnum==8 ) {
      Serial.println(" pressed");
      digitalWrite(in2, HIGH);
      digitalWrite(in3, LOW);   //right ok
      digitalWrite(in1, LOW);
      digitalWrite(in4, LOW);
    }
    if (pressed & buttnum==7 ) {
      Serial.println(" pressed");
      digitalWrite(in3, LOW);
      digitalWrite(in2, LOW);   //left ok
      digitalWrite(in1, LOW);
      digitalWrite(in4, HIGH);
    }
    if (pressed & buttnum==6 ) {
      Serial.println(" pressed");
      digitalWrite(in1, HIGH);
      digitalWrite(in4, LOW);    //reverse ok
      digitalWrite(in2, LOW);
      digitalWrite(in3, HIGH);
    }
    }
    else {
      Serial.println(" released");
      digitalWrite(in1, LOW);
      digitalWrite(in4, LOW);    //reverse ok
      digitalWrite(in2, LOW);
      digitalWrite(in3, LOW);
    }
  }
  // GPS Location
  if (packetbuffer[1] == 'L') {
    float lat, lon, alt;
    lat = parsefloat(packetbuffer+2);
    lon = parsefloat(packetbuffer+6);
    alt = parsefloat(packetbuffer+10);
    Serial.print("GPS Location\t");
    Serial.print("Lat: "); Serial.print(lat, 4); // 4 digits of precision!
    Serial.print('\t');
    Serial.print("Lon: "); Serial.print(lon, 4); // 4 digits of precision!
    Serial.print('\t');
    Serial.print(alt, 4); Serial.println(" meters");
  }
  // Accelerometer
  if (packetbuffer[1] == 'A') {
    float x, y, z;
    x = parsefloat(packetbuffer+2);
    y = parsefloat(packetbuffer+6);
    z = parsefloat(packetbuffer+10);
    Serial.print("Accel\t");
    Serial.print(x); Serial.print('\t');
    Serial.print(y); Serial.print('\t');
    Serial.print(z); Serial.println();
  }
  // Magnetometer
  if (packetbuffer[1] == 'M') {
    float x, y, z;
    x = parsefloat(packetbuffer+2);
    y = parsefloat(packetbuffer+6);
    z = parsefloat(packetbuffer+10);
    Serial.print("Mag\t");
    Serial.print(x); Serial.print('\t');
    Serial.print(y); Serial.print('\t');
    Serial.print(z); Serial.println();
  }
  // Gyroscope
  if (packetbuffer[1] == 'G') {
    float x, y, z;
    x = parsefloat(packetbuffer+2);
    y = parsefloat(packetbuffer+6);
    z = parsefloat(packetbuffer+10);
    Serial.print("Gyro\t");
    Serial.print(x); Serial.print('\t');
    Serial.print(y); Serial.print('\t');
    Serial.print(z); Serial.println();
  }
  // Quaternions
  if (packetbuffer[1] == 'Q') {
    float x, y, z, w;
    x = parsefloat(packetbuffer+2);
    y = parsefloat(packetbuffer+6);
    z = parsefloat(packetbuffer+10);
    w = parsefloat(packetbuffer+14);
    Serial.print("Quat\t");
    Serial.print(x); Serial.print('\t');
    Serial.print(y); Serial.print('\t');
    Serial.print(z); Serial.print('\t');
    Serial.print(w); Serial.println();
   }
}
Assembly¶
For the boat’s assembly we have used vynil and laser cuttign
For more about Computer controlled cutting

We have decorated the boat by stars and “FABLAB” term
Hero Shot¶
Files: VINYL DESIGN Laser Cut