Proposal Bot Generation 1
Summary Blog Post

Author/s: Ethan Thiessa, Haydon Chiu, Jonathan Valdez, Tyler Galgas

Executive Summary

By: Ethan Thiessa

Many people struggle with trying to find the perfect or unique marriage proposal for their significant other. Proposal bot solves this issue by providing the person with a unique, fun way to propose with a small robot. This omnidirectional robot will autonomously draw out on a piece of paper “Will you marry me?” while playing a little jingle. When the bot is done drawing out the message, a box on top of the bot will pop open revealing the engagement ring.

Program and Project Objectives

By: Ethan Thiessa

Program Objectives

The Robot Company (TRC) will be debuting its 2020 line-up of robots and consumer technology at the Bridal Wedding Expo 2020 convention in Los Angeles, CA on May 8, 2020. Your team’s assignment is to make the 3D printed and/or laser-cut prototypes to be showcased at the convention, prior to production starting in the second quarter of 2021. The robots will feature our new ArxRobot smart phone application and the Arxterra internet applications allowing people to easily control their new robots. In addition, the robots should be able to operate autonomously in draw mode. To decrease electronics cost, interoperability between all TRC robots will be maintained by incorporation of the 3DoT board, developed by our Electronics R&D Section. Modification of downloadable content is limited to software switch setting and robot unique graphics of the smart phone and Arxterra applications.  Modifications of electronics is limited to custom 3DoT shields as required by the unique project objectives of your robot.  The Marketing Division has set our target demographic as men between the ages of 20 and 30, with a median (target) age of 25. To decrease production costs, please keep robots as small as possible, consistent with our other objectives. As with all our products, all safety, environmental, and other applicable standards shall be met. Remember, all men, including the disabled are our most important stakeholders. Our Manufacturing Division has also asked me to remind you that Manufacturability and Repairability best practices must be followed.

Project Objectives

The purpose of the Proposal Bot project is to use the robot’s autonomous drawing capabilities to appeal to a new market of consumers: people who plan to be engaged. The Proposal Bot intends to offer an interesting and unique method of proposal to this market. The robot will be able to move forward,  backward, sideways, diagonally, rotate, and write on a paper surface in a romantic location. This first generation of the project will offer an opportunity to study the movement and precision of an omnidirectional robot to autonomously draw out a predefined message.

Mission Profile

By: Ethan Thiessa

The mission of the Proposal Bot is to write out the message “MARRY ME?” in block letters on a paper surface and open an engagement ring box at the end of the message revealing the engagement ring, in order to impress the person to say “yes.” In addition, the user shall be able to control Proposal Bot’s movement using the Arxterra app. If time allows, Proposal Bot will also be capable of writing in cursive for better presentation.

Project Features

By: Tyler Galgas

Proposal Bot- an omnidirectional robot that will be controlled through the Arxterra app to write out the message- M A R R Y  M E – through the use of a pen plotter (not pictured) and once finished, a box will pop open presenting a shiny ring.

Figure 1. Front View of Proposal Bot


Figure 2. Completed Proposal Bot


Figure 3. Inside Proposal Bot

Requirements

Due to limitations placed on this project by “stay at home” conditions enforced by California State University Long Beach and the state of California, this project will not include the implementation of L2 Performance Requirements. Therefore upon verification of this project, it is difficult to examine the overall quality of hardware design, as Proposal Bot still uses V1 hardware for verification.

Engineering Standards and Constraints

By: Jonathan Valdez

Applicable Engineering Standards

  1. EEE 29148-2018 – ISO/IEC/IEEE Approved Draft International Standard – Systems and Software Engineering — Life Cycle Processes –Requirements Engineering.
  2. NASA/SP-2007-6105 Rev1 – Systems Engineering Handbook
  3. Bluetooth Special Interest Group (SIG) Standard (supersedes IEEE 802.15.1)
  4. C++ standard (ISO/IEC 14882:1998)
  5. NXP Semiconductor, UM10204, I2C-bus specification and user manual.
  6. ATmega16U4/ATmega32U4, 8-bit Microcontroller with 16/32K bytes of ISP Flash and USB Controller datasheet section datasheet, Section 18, USART.
  7. USB 2.0 Specification released on April 27, 2000, usb_20_20180904.zip

Environmental, Health, and Safety (EH&S) Standards

  1. All Lithium (Li-ion, Li-polymer) batteries shall be purchased with and stored, when not in use, in a fire and explosion proof battery bag.
  2. CSULB COE Lab Safety
  3. CSULB Environmental Health & Safety
  4. IEEE National Electrical Safety Code

Project Level 1 Functional Requirements

By: Ethan Thiessa

The Level 1 Functional Requirements describe the functions and characteristics that Proposal Bot will have.

L1-1 -Proposal Bot will be constrained to a completion date of May 11, 2020.
L1-2 Proposal bot will be constrained to not exceed $250.
L1-3 Surface Mount Technology will be implemented on the custom PCB for Proposal Bot.
L1-4 Lithium-polymer battery will be stored when not in use in a fire and explosion-proof battery bag.
L1-5 Proposal Bot will implement the Arduino Uno microcontroller.
L1-6 Proposal Bot will use a medium density fiberboard for the chassis of the robot.
L1-7 Proposal bot will have a Custom PCB that provides power for the four stepper motor drivers.
L1-8 The custom PCB will also provide power for the two servo motors via a buck converter that steps down from 11.1V to 6V.
L1-9 The custom PCB will also enable Bluetooth communication via a Bluetooth module that follows IEEE 802.15.1 standardized protocol.
L1-10 Proposal Bot shall be able to traverse on white paper, poster board, and cardboard that the rollers can grip to and that the pen can write on.
L1-11 Proposal Bot shall have a servo powered pen plotter mechanism that lifts and lowers the pen.
L1-12 Proposal Bot shall be able to move forward and backward
L1-13 Proposal Bot shall be able to move in a sideways motion
L1-14 Proposal Bot shall be able to rotate in place
L1-15 Proposal Bot shall be able to move diagonally.
L1-16 Proposal Bot shall draw the proposal message “MARRY ME” in block letters on a poster or large sheet of paper.
L1-17 Proposal bot shall draw the letters in the message with spaces between letters.
L1-18 Proposal bot shall write out the message autonomously after given the instruction by the user from the ArxRobot App.
L1-19 A ring box shall open up autonomously when Proposal Bot is done drawing the message revealing the “engagement ring.”
L1-20 Movement of the Proposal Bot shall be able to be controlled using the ArxRobot app via Bluetooth.
L1-21 Proposal Bot should write the proposal message in cursive utilizing Bezier curves.
L1-22 Users should be able to input a message using their phone on the Arxterra App for Proposal Bot to write out.
L1-23 Fully assembled robot’s noise level shall be below the noise level of a typical restaurant (80dB).
L1-24 Disassembly and assembly of Proposal Bot shall take 20 minutes or less

System/Subsystem/Specifications Level 2 Requirements

By: Ethan Thiessa

Level 2 Requirements

Based on the block diagram and should be traceable to L1 requirements.

L2.1 – Each wheel, 4 in total, shall utilize a NEMA 17 stepper motor that runs on 8.5V-11.1V for forwards, backwards, sideways, and diagonal motion.

L2.2 – The rollers will have rubberized centers in order to have better traction on surfaces so that more precision is achieved.

L2.3 – The wheels will be made up of 4 different parts: the wheelbase plate, the wheel outer plate, the shaft couple, and 10 rollers that are attached using 3mm diameter rods each with a length of 20mm.

L2.4 – The pen plotter will be designed to push the pen down at a certain pressure so that Proposal Bot writes clearly, but doesn’t mess up the writing surface.

L2.5 – The Arxterra App shall have custom software implemented.

L2.6 – The ArxRobot app user interface will include 8 toggleable buttons for movement control over Proposal Bot’s wheels.

L2.7 – The Robot’s 4 Stepper Motors will be powered by a 11.1V lithium-Ion battery with each Stepper pulling around 600mA-1000mA.

L2.8 – The robot’s 2 servo motors will be powered through a buck converter that steps down the 11.V lithium-ion battery to 6V.

L2.9 – All of the electronics will be mounted inside of the base of Proposal Bot.

Mass Shared Resource Report / Allocation

By: Tyler Galgas

Power Shared Resource Report / Allocation

By: Tyler Galgas

Project Report

Project WBS and PBS

By: Ethan Thiessa

Below is the Project Work Breakdown Structure (WBS) and Product Breakdown Structure (PBS). The WBS shows the work that needs to be done to complete Proposal Bot and the person responsible for those tasks. The WBS and PBS show the basic tasks that need to be done to complete the Proposal Bot and the Excel sheet linked below displays the complete task list to complete the project.

Complete Task List

Figure 1. Work Breakdown Structure

The PBS shows the items needed for Proposal Bot to function and the person responsible for each task. These are all of the items that need to be completed in order to complete Proposal Bot’s mission requirements.

Figure 2. Product Breakdown Structure

Cost

By: Ethan Thiessa

The budget allocated for the construction of Proposal Bot was $250.00. Each team member has to keep track of the budget during the time of the project. A lot of money was saved on this project by already having a 3-Dot board and using common stepper motors that were easily salvageable. 3D printing cost was minimized by attempting to consoladate as many 3D models into one printer space as we could.

Schedule

By: Tyler Galgas

Concept and Preliminary Design

The concept for our robot initially revolved around the capability of moving in any direction also known as omnidirectional. The robot can achieve this omnidirectional movement by utilizing a special type of wheels called Mecanum wheels. These wheels use rollers attached to its circumference, these rollers are positioned diagonally or at a 45-degree angle to the axis of rotation of the wheel. The wheels exert force in a diagonal direction when moving forward or backward, by rotating the wheels in certain patterns these diagonal forces allow the robot to move forwards, backward, diagonally in any direction, sideways, and be able to rotate in place.

Literature Review

By: Jonathan Valdez

The majority of information regarding our first generation Proposal Bot came from the howtomechatronics website. This site provided the stl files to 3D print the Mecanum wheels along with how to assemble them once they have been printed. The dimensions needed to laser cut the box used to house all the electrical components were also given. The initial circuit diagram and electrical components needed were also listed and utilized for version one of our project.

  1. https://howtomechatronics.com/projects/arduino-mecanum-wheels-robot/

Design Innovation

By: Haydon Chiu

  1. Tape grip- Our initial rollers that were 3D printed were unfortunately did not produce enough traction. So in order to implement enough traction to move omnidirectional in an efficient manner, our group used duck tape that provided our solution.
  2. Processing simulation- Initially, our group planned on moving forward digitally with a simulation by using Processing, but instead our group was able to implement the physical representation and have a virtual simulation of the bots movements.
  3. Thicker wheel rods- The initial thickness of the rods used to build the wheels was too skinny and made the wheels wobble therefore we had to re-build the wheels using a thicker diameter of steel rods to allow the wheels to be sturdier.

Conceptual Design / Proposed Solution

By: Ethan Thiessa

Provide details of the proposed solution that meets the project specifications while best satisfying the applicable constraints. Provide block diagram representation of the proposed system, discuss each subsystem in detail and provide any preliminary results including simulation or analytical results to support your hypothesis. Also provide an initial budget estimate and timeline for the completion of the project.

System Design / Final Design and Results

System Block Diagram

By: Ethan Thiessa

The System begins with the Arduino Uno having three sets of code instructions that will be sent to the stepper motor drivers and the servo PWM connections on the custom PCB. The 5V power supply from the arduino uno will be used to drive the digital signals to the Bluetooth module and the stepper motor drivers. The custom PCB works as an Aruduino Uno shield that provides a Bluetooth module, 4 stepper motor drivers that are powered by the 11.1V lithium-ion battery, a buck converter that converts the 11.1V from the lithium ion battery to 6V, and servo PWM connections. There will be 4 NEMA 17 stepper motors connected to the 4 stepper motor drivers  respectively. There will also be 2 MG90 Servo motors that will control the open actuation of the ring box and the up/down actuation of the pen plotter and are powered by the 6V output of the buck converter.

Figure 1. System Block Diagram

The diagram below is the system block diagram for the PCB expanded so that we can see the connections from the Arduino Uno to the custom PCB shield and the connections to the servo and stepper motors. 8 digital connections from the Arduino will be used to send the wheel instruction codes to the STEP and DIR(direction) pins on the DRV8825 stepper motor drivers. The STEP pin controls the distance the wheel will travel and the DIR pin controls the direction the wheel moves. The 5V power supply from the arduino will power the digital signals in the stepper motor drivers via the RST and SLP pin and the HC-05 Bluetooth module via the VCC pin. The 4 stepper motors that control the wheels will be connected to the 4 stepper motor drivers respectively via the B2, B1, A1, and A2 pins. The MG90 servos will be powered via the 6V output from the buck converter and the digital logic will come from two PWM digital lines from the arduino.

Figure 2. Custom PCB

Interface Definition

By: Ethan Thiessa

Below is the interface matrix for Proposal Bot’s wire connections. This matrix is split up into the different headers on the custom PCB where the electric components connect to.

Figure 1. Interface Matrix

Arduino Connections

The first two 8 pin header with pins 1-8 and pins 9-16 correspond to the connections from the custom PCB to the digital pins on the Arduino Uno. The next two 6 pin headers with pins 17-23 and pins 24-29 correspond with the connections from the custom PCB to the power pins and analog pins on the Arduino Uno. With all theses headers connected, the custom PCB can act as an Arduino Uno shield, sitting on top of the Arduino.

Stepper Motor ConnectionsThe four 4 pin male headers are connected to each of the motor drivers corresponding motor connections. The wires from the motors are color-coded to the 4 pin headers so that the motor is plugged in correctly.

Servo Motor Connections

The two 3 pin headers are connected to the output of the buck converter, GND, and the PWM connections from the Arduino. These 3 pin male headers are used so that the two servo motors can connect directly to the custom Shield.

HC-05 Bluetooth Connections

The 6 pin female header is connected to the Arduino RX and TX lines along with the Arduino’s 5V supply and ground. This is used so that the Bluetooth module can connect directly to the custom PCB.

DRV8825 Motor Driver Connections

The last two 8 pin headers are used in parallel to connect the DRV8825 Motor drivers to the custom PCB. RST and SLP are connected to the Arduino’s 5V logic supply and STEP and DIR are connected to the Arduino’s digital pins. All four motor drivers are connected directly to the 11.1V battery supply via the VMOT and GND2 pin. These connections are used for each of the four motor drivers.

Modeling/Experimental Results

Mission Command and Control

By: Haydon Chiu

Figure 1. ArxRobot Control

Code:

/* 
* Telemetry and Custom Command Sample Arduino Code
* Telemetry Example: Monitor an extended I/O register value and send to control panel display
* Command Example: Add Robot unique MOVE, BLINK, and SERVO commands
*/

// include C:Program Files (x86)Arduino 1_6_5hardwarearduinoavrlibraries
#include  // instantiated as ArxRobot at end of class header
#include 
#include  // I2C support
#include 
#include 

ArxRobot ArxRobot; // instantiated as ArxRobot at end of class header

AccelStepper LeftBackWheel(1, 42, 43); // (Type:driver, STEP, DIR) - Stepper1
AccelStepper LeftFrontWheel(1, 40, 41); // Stepper2
AccelStepper RightBackWheel(1, 44, 45); // Stepper3
AccelStepper RightFrontWheel(1, 46, 47); // Stepper4

/*
* Command Example
* Step 1: Assign new command mnemonics ID numbers
* In our example we will be adding 3 custom comma
* nds (2 new and one predefined).
* The predefined MOVE command is intercepted and our robot unique code is to be
* run instead. The MOVE command mnemonic ID 0x01 is already defined in Configure.h
* The next two commands are new and assigned to the first two addresses in the
* custom command address space 0x40 - 0x5F.
*/
#define BLINK 0x40
#define SERVO 0x41
const uint8_t CMD_LIST_SIZE = 3; // we are adding 3 commands (MOVE, BLINK, SERVO)
int wheelSpeed = 500;
/*
* Command Example
* Step 4: Write command handlers
*/

/*
* User Defined Command BLINK (0x40) Example
* A5 01 40 E4
*/
void blinkHandler (uint8_t cmd, uint8_t param[], uint8_t n)
{
int dataIn = param[0];
int m = 0;
if (dataIn == 0x0C) {
m = 0;
}
if (dataIn == 0x0A) {
m = 1;
}
if (dataIn == 0x04) {
m = 2;
}
if (dataIn == 0x07) {
m = 3;
}
if (dataIn == 0x0B) {
m = 4;
}
if (dataIn == 0x05) {
m = 5;
}
if (dataIn == 0x09) {
m = 6;
}
if (dataIn == 0x03) {
m = 7;
}
if (dataIn == 0x08) {
m = 8;
}
//if (dataIn == 9) {
//m = 9;
//}
//if (dataIn == 10) {
//m = 10;
//}
/*
if (dataIn == 11) {
m = 11;
}
if (dataIn == 12) {
m = 12;
}
if (dataIn == 14) {
m = 14;
}*/
// Set speed
/*
if (dataIn >= 16) {
wheelSpeed = dataIn * 10;
Serial.println(wheelSpeed);
}
}
*/
if (m == 4) {
moveSidewaysLeft();
}
if (m == 5) {
moveSidewaysRight();
}
if (m == 2) {
moveForward();
}
if (m == 7) {
moveBackward();
}
if (m == 3) {
moveRightForward();
}
if (m == 1) {
moveLeftForward();
}
if (m == 8) {
moveRightBackward();
}
if (m == 6) {
moveLeftBackward();
}
// if (m == 9) {
// rotateLeft();
//}
//if (m == 10) {
//rotateRight();
//}
if (m == 0) {
stopMoving();
}
LeftBackWheel.runSpeed();
RightBackWheel.runSpeed();
LeftFrontWheel.runSpeed();
RightFrontWheel.runSpeed();

} // blinkHandler

/*
* Override MOVE (0x01) Command Example
* A5 05 01 01 80 01 80 A1
*/
void moveHandler (uint8_t cmd, uint8_t param[], uint8_t n)
{
Serial.write(cmd); // move command = 0x01
Serial.write(n); // number of param = 4
for (int i=0;i Board.
*/
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
uint16_t pwm_reading = (uint16_t) OCR4D; // read 8-bit Output Compare Register Timer 4D and cast to 16-bit signed word
motorPWM.sendSensor(pwm_reading);
#else
// Timer/Counter 0 registers set by UNO Bootloader (freq. = 1 Khz)
// Timer/Counter Control Registers TCCR0B = 0x03 (Prescaler of 64) and TCCR0A (Fast PWM, TOP = 0xFF) = 0x03
uint16_t pwm_reading = (uint16_t) OCR0B;
motorPWM.sendSensor(pwm_reading);
#endif
}

void moveForward() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(wheelSpeed);
}
void moveBackward() {
LeftFrontWheel.setSpeed(-wheelSpeed);
LeftBackWheel.setSpeed(-wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(-wheelSpeed);
}
void moveSidewaysRight() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(-wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(wheelSpeed);
}
void moveSidewaysLeft() {
LeftFrontWheel.setSpeed(-wheelSpeed);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(-wheelSpeed);
}
void rotateLeft() {
LeftFrontWheel.setSpeed(-wheelSpeed);
LeftBackWheel.setSpeed(-wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(wheelSpeed);
}
void rotateRight() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(-wheelSpeed);
}
void moveRightForward() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(0);
RightFrontWheel.setSpeed(0);
RightBackWheel.setSpeed(wheelSpeed);
}
void moveRightBackward() {
LeftFrontWheel.setSpeed(0);
LeftBackWheel.setSpeed(-wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(0);
}
void moveLeftForward() {
LeftFrontWheel.setSpeed(0);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(0);
}
void moveLeftBackward() {
LeftFrontWheel.setSpeed(-wheelSpeed);
LeftBackWheel.setSpeed(0);
RightFrontWheel.setSpeed(0);
RightBackWheel.setSpeed(-wheelSpeed);
}
void stopMoving() {
LeftFrontWheel.setSpeed(0);
LeftBackWheel.setSpeed(0);
RightFrontWheel.setSpeed(0);
RightBackWheel.setSpeed(0);
}

How it works?
The code above works by implementing the basics of the Arxterra app and Arduino library. Since our bot is using an Arduino board instead of the 3Dot Board, it was necessary to modify the library of the Arxterra library in Arduino. It was necessary to erase the 3Dot files and make sure that Arduino is the device connected in the code via our HC-05 bluetooth module. Our code was based off of Dejan’s code from HowToMechatronics.com and he implements a lot of if then statements that would then call upon pre-designated functions such as moveForward(), moveBackward(), and many other motions. The app was designed by inputting buttons that would call up, down, left, right, sideways right, and so on. Hex numbers were labeled for these spots and will correspond to the bot. For example, if the button for stopMoving was selected on the app, the corresponding hex number 0x0C would be true which would lead the stopMoving function to be called.

A flowchart explaining the process can be seen below:

Electronic Design

By: Jonathan Valdez

Introduction

This electrical design is a system of electrical components connected in such a way to carry out the desired operation. Below are a couple schematic diagrams showing the electrical interconnections between the components for both versions one and two of Proposal Bot. Versions one and two are very similar however, version two utilizes a buck converter used to step down the battery pack voltage to power the servo motors which are used to control both the pen plotter and ring box.

V1 Electrical Circuit

Figure 1: V1 Circuit Implementation


Figure 2: DRV8825 stepper motor driver layout

This integrated motor driver makes interfacing with a microcontroller easy since you only need two pins to control the speed and the direction of the stepper motor. This driver has a maximum output capacity of 45V and ± 2 A which is ideal for driving small to medium sized stepper motors like the NEMA 17 bipolar stepper motor used to drive Proposal Bot.

Electrical Components:

1 – Arduino Uno

1 – Gens ace 2200mAh 11.1V 45C 3S1P Lipo Battery Pack

4 – NEMA 17 stepper motors

4 – DRV8825 stepper drivers

4 – 100uF electrolytic capacitors

1 – HC-05 bluetooth module

V2 Circuit Implementation

Figure 3: V2 Circuit Implementation

Figure 3 shows the breadboard version two circuit implementation. Notice the Buck Converter at the bottom of Figure 3 which is used to step down the Li-Po battery pack 11.1V to 6V in order to power the sg90 servo motors which are used to control both the pen plotter and ring box of Proposal Bot. https://www.arxterra.com/?p=158195&preview=true (Buck Converter Analysis Blog post)

PCB Design

By: Ethan Thiessa

Link to EagleCad Files

SMD PCB Schematic

Figure 1. SMD PCB Schematic

The custom PCB for Proposal bot consists of three different types of modules: the stepper motor drivers, the Bluetooth module, and the buck converter to power the servo motors. The 4 motor drivers are connected to the PCB via 8 pin female headers, which does not follow the SMD only constraint. There are also four 100uF SMD capacitors connected to the VMOT of the motor driver and an SMD 4 pin header used for each motor driver to connect the stepper motors. The Bluetooth module is connected via a 6pin through-hole female header with two SMD resistors acting as a voltage divider for the logic input of the device. The buck converter is made up of all SMD components used to output 6V to the two 3pin SMD male headers to connect the servo motors. Finally, the two 6 pin and two 8 pin headers to the right of the schematic are used to connect the custom shield directly on top of the Arduino Uno.

SMD PCB Layout

Figure 2. SMD PCB Layout

Above is the SMD PCB Layout for the custom PCB for Proposal Bot. The through-hole male headers are used to connect to the PCB to the Arduino Uno as a shield. For the best power management for the PCB, I used a star configuration for the positive power supply for the Lipo battery screw connector. A large copper pour is placed from the positive terminal of the battery connector to the middle of the four stepper motor drivers. From there, 50 mil wires are connected to the Vin supply of all four motor drivers and the input of the LM2596 switch converter. For grounding the board, I used two copper ground pours on the top and bottom of the PCB to accommodate the analog and digital power lines. From research, combining both the digital and analog grounds into one with grounding all over the board was the best way to reduce noise from the analog power line.

Through-hole PCB Schematic 

Figure 3. Through-hole PCB Schematic

Because of COVID-19 and the quarantine, our group did not have the proper tools to assemble the SMD board. Therefore, I designed a through-hole schematic of our PCB so that we could still assemble and test the PCB design with Proposal Bot. The schematic design is almost identical to the SMD schematic with the exception of replacing all SMD components with through-hole components.

Through-hole PCB Layout

Figure 4. Through-hole PCB Layout

Similar to the SMD PCB layout, the through-hole layout is almost identical albeit being slightly smaller. The buck converter components were moved arranged slightly different then the SMD layout to accommodate the wiring and size of the components.

Assembled PCB

Figure 5. Assembled PCB

Firmware

By: Haydon Chiu

Link to all Firmware

/* PROPOSALBOT Final Code
* 05/10/2020
* EE 400D
* Professor Gary Hill
* Group members: Ethan Thiessa, Haydon Chiu, Tyler Galgas, and Jonathan Valdez
* Written by: Haydon Chiu (Omnidirectional movement) with additional code written by Ethan Thiessa and Jonathan Valdez
* 
* The code will allow ProposalBot to move omnidirectionally so that the 
* bot can spell the words "MARRY ME". The bot utilizes the Accelstepper library.
* It will call upon the functions that have combinations 
* of wheel movements that allow for the function to move omnidirectionally.
* The step format of the movement in void loop() can be seen below.
* 
* Steps:
* 1. The first part to initiate movement is to call the time (time1,time2,time3,etc.).
* 2. The time variable(s) will be put into a while loop and will be subtracted as
* millis()-time, this will then be compared (less than) to a number depending on how long 
* one wants the bot to move in that direction.
* 3. Call a function (moveRightforward, moveBackward, moveForward)
* 4. Call .runSpeed() on each wheel to initiate the movement of the
* previous function
* 5. After the while loop, a delay will be called so that the code will have a chance
* to pause before the next while loop gets called.
*/


#include 
#include 
// Define the stepper motors and the pins the will use
AccelStepper LeftBackWheel(1, 13, 12); // (Type:driver, STEP, DIR) - Stepper1
AccelStepper LeftFrontWheel(1, 11, 10); // Stepper2
AccelStepper RightBackWheel(1, 9, 8); // Stepper3
AccelStepper RightFrontWheel(1, 7, 6); // Stepper4

int wheelSpeed = 150;
int servoPin1 = 3;
int servoPin2 = 5;
Servo servo,ringServo; 

int servoAngle = 0; // servo position in degrees

unsigned long time,time1,time2,time3,time4,time5,time6,time7,time8,time9,time10,time11,time12,time13,time14, //These variables are going to be used as the start of the timer for our robot movements.
time15,time16,time17,time18,time19,time20,time21,time22,time23,time24,time25,
time26,time27,time28,time29,time30,time31,time32,time33,time34,time35,time36,time37,time38,time39;



void setup() {
// put your setup code here, to run once:
//.setMaxSpeed() is used to set the wheels for maximum movement in the attempt that the wheels speed to match movements
Serial.begin(9600); 
servo.attach(servoPin1);
ringServo.attach(servoPin2);
LeftFrontWheel.setMaxSpeed(3000);
LeftBackWheel.setMaxSpeed(3000);
RightFrontWheel.setMaxSpeed(3000);
RightBackWheel.setMaxSpeed(3000);
servo.write(90);
ringServo.write(0);
}

void loop() {
//Beginning of M
servo.write(180);
delay(1000);
time = millis();
while(millis()-time < 800){
moveRightForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time1 = millis();
while(millis()-time1 <400){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time2 = millis();
while(millis()-time2 < 400){
moveRightForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time3 = millis();
while(millis()-time3 < 800){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};
//End of M

/*The movement of moveSidewaysRight() will act as 
* the space bar.
*/
delay(500);
servo.write(90);
delay(1000);
time4 = millis();
while(millis()-time4 < 500){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

//End of Space
delay(500);
servo.write(180);
//Beginning of A

delay(1000);
time5 = millis();
while(millis()-time5 < 500){
moveRightForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time6 = millis();
while(millis()-time6 < 600){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time7 = millis();
while(millis()-time7 < 600){
moveSidewaysLeft();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time8 = millis();
while(millis()-time8 < 400){
moveRightForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time9 = millis();
while(millis()-time9 < 800){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

//End of A

delay(500);
//Beginning of Space
servo.write(90);
delay(500);
time10 = millis();
while(millis()-time10 < 500){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

//End of Space

delay(500);
//Beginning of R
servo.write(180);
delay(500);
time11 = millis();
while(millis()-time11 < 700){
moveForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time12 = millis();
while(millis()-time12 < 400){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time13 = millis();
while(millis()-time13 < 500){
moveLeftBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time14 = millis();
while(millis()-time14 < 600){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};
//End of R

delay(500);
//Beginning of space
servo.write(90);
delay(500);
time15 = millis();
while(millis()-time15 < 500){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
servo.write(180);

//Beginning of R
delay(500);
time16 = millis();
while(millis()-time16 < 700){
moveForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time17 = millis();
while(millis()-time17 < 400){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time18 = millis();
while(millis()-time18 < 500){
moveLeftBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time19 = millis();
while(millis()-time19 < 600){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};
//End of R

delay(500);
servo.write(90);

//Beginning of space
delay(500);
time20 = millis();
while(millis()-time20 < 500){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};
//End of space

delay(500);
servo.write(180);

//Beginning of Y
delay(500);
time21 = millis();
while(millis()-time21 < 400){
moveForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time22 = millis();
while(millis()-time22 < 400){
moveLeftForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time23 = millis();
while(millis()-time23 < 400){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time24 = millis();
while(millis()-time24 < 400){
moveRightForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
servo.write(90);
/*Since Y doesn't end at the bottom of a letter
* it wil be necessary to moveSidewaysRight()
* and moveBackward()
*/
delay(500);
time25 = millis();
while(millis()-time25 < 500){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time26 = millis();
while(millis()-time26 < 800){
moveBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

//End of space movement
delay(500);
servo.write(180);
//M
delay(500);
time27 = millis();
while(millis()-time27 < 800){
moveRightForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time28 = millis();
while(millis()-time28 <400){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time29 = millis();
while(millis()-time29 < 400){
moveRightForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time30 = millis();
while(millis()-time30 < 800){
moveRightBackward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

//End of M

delay(500);
servo.write(90);

//Beginning of space
delay(500);
time31 = millis();
//Serial.println(time);
while(millis()-time31 < 500){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};
//End of space

delay(500);
servo.write(180);

//Beginning of E

delay(500);
time32 = millis();
while(millis()-time32 < 600){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time33 = millis();
while(millis()-time33 < 600){
moveSidewaysLeft();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time34 = millis();
while(millis()-time34 < 400){
moveForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time35 = millis();
while(millis()-time35 < 600){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time36 = millis();;
while(millis()-time36 < 600){
moveSidewaysLeft();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time37 = millis();
while(millis()-time37 < 400){
moveForward();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};

delay(500);
time38 = millis();
while(millis()-time38 < 600){
moveSidewaysRight();
LeftFrontWheel.runSpeed();
LeftBackWheel.runSpeed();
RightFrontWheel.runSpeed();
RightBackWheel.runSpeed();
};


delay(1000);
ringServo.write(100);
delay(5000);

}
/*
* These functions will be called in order
* to get ProposalBot to move omnidirectionally
*/
void moveForward() {
LeftFrontWheel.setSpeed(-wheelSpeed);
LeftBackWheel.setSpeed(-wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(wheelSpeed);
}
void moveBackward() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(-wheelSpeed);
}
void moveSidewaysRight() {
LeftFrontWheel.setSpeed(-wheelSpeed);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(wheelSpeed);
}
void moveSidewaysLeft() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(-wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(-wheelSpeed);
}
void rotateLeft() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(wheelSpeed);
}
void rotateRight() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(-wheelSpeed);
}
void moveRightForward() {
LeftFrontWheel.setSpeed(-wheelSpeed);
LeftBackWheel.setSpeed(0);
RightFrontWheel.setSpeed(0);
RightBackWheel.setSpeed(wheelSpeed);
}
void moveRightBackward() {
LeftFrontWheel.setSpeed(0);
LeftBackWheel.setSpeed(wheelSpeed);
RightFrontWheel.setSpeed(-wheelSpeed);
RightBackWheel.setSpeed(0);
}
void moveLeftForward() {
LeftFrontWheel.setSpeed(0);
LeftBackWheel.setSpeed(-wheelSpeed);
RightFrontWheel.setSpeed(wheelSpeed);
RightBackWheel.setSpeed(0);
}
void moveLeftBackward() {
LeftFrontWheel.setSpeed(wheelSpeed);
LeftBackWheel.setSpeed(0);
RightFrontWheel.setSpeed(0);
RightBackWheel.setSpeed(-wheelSpeed);
}
void stopMoving() {
LeftFrontWheel.setSpeed(0);
LeftBackWheel.setSpeed(0);
RightFrontWheel.setSpeed(0);
RightBackWheel.setSpeed(0);
}

Processing/Example and explanation

Processing ProposalBot

Due to the condition of the COVID-19 situation that was currently happening at this time, it was necessary to implement a simulation of the movement of the code. As seen in the video above, the square draws the words "MARRY ME". Originally, our group decided to move forwards as a digital simulation group, but with a lot of tinkering with the code and hardware, the physical representation was back on track. The processing code that I developed, did help with visualizing how the physical code works, and while a little messier, the physical hardware imitates the simulation code. The code for processing can be seen below and the video above.

float x = 0;
float y = 500;
int state = 0;
int state_a = 0;
 
void setup() {

  size(3000, 3000);
  background(102);
  //draw();
}

void draw()
{

  //fill(0);
  
  rect(x,y,20,20);
  //M();
  //A();
 //M
  if (state == 0){
    //background(102);
    x = x+1;
    y = y-1;
    //line(0,500,x,y);
    if (x > 100){
      x = 100;
      y = 400;
      state = 1;
    }
}else if (state == 1){
  x = x+1;
  y = y+1;
  if (x > 150){
    x = 150;
    y = 450;
    state = 2;
  }
}else if (state == 2){
    x = x+1;
    y = y-1;
    if (x > 200){
      x = 200;
      y = 400;
      state = 3;
    }
}else if (state == 3){
  x = x+1;
  y = y+1;
  if (x > 300){
    x = 300;
    y = 500;
    state = 4;
  }//A
}else if (state == 4){
  //fill(102);
  //background(102);
  x = x+1;
  //y = y-1;
  if (x > 350){
    x = 350;
    y = 500;
    state = 5;
    }
}else if (state == 5){
  x = x+1;
  y = y-1;
    if (x >400){
      x = 400;
      y = 450;
      state = 6;
}
  }else if (state == 6){
    x = x+1;
    if (x > 500){
      x = 500;
      y = 450;
      state = 7;
}
  }else if (state == 7){
    x = x-1;
    if (x == 400){
      x = 400;
      y = 450;
      state = 8;
    }
  }else if (state == 8){
  x = x+1;
  y = y-1;
  if (x > 450){
    x = 450;
    y = 400;
    state = 9;
  }
  }else if (state == 9){
  x = x+1;
  y = y+1;
  if (x > 550){
    x = 550;
    y = 500;
    state = 10;
}//R
  }else if (state == 10){
    //background(102);
  x = x+1;
  //y = y-1;
  if (x > 600){
    x = 600;
    y = 500;
    state = 11;
    }
  }else if (state == 11){
    y = y-1;
    if (y <350){
      x = 600;
      y = 350;
      state = 12;
    }
  }else if (state == 12){
  x = x+1;
  y = y+1;
  if (x > 650){
    x = 650;
    y = 400;
    state = 13;
  }
  }else if (state == 13){
  x = x-1;
  y = y+1;
  if (x < 600){
    x = 600;
    y = 450;
    state = 14;
  }
}else if (state == 14){
  x = x+1;
  y = y+1;
  if (x > 650){
    x = 650;
    y = 500;
    state = 15;
  }
}//R
else if (state == 15){
  //background(102);
  x = x+1;
  //y = y-1;
  if (x > 700){
    x = 700;
    y = 500;
    state = 16;
    }
  }else if (state == 16){
    y = y-1;
    if (y <350){
      x = 700;
      y = 350;
      state = 17;
    }
  }else if (state == 17){
  x = x+1;
  y = y+1;
  if (x > 750){
    x = 750;
    y = 400;
    state = 18;
  }
  }else if (state == 18){
  x = x-1;
  y = y+1;
  if (x < 700){
    x = 700;
    y = 450;
    state = 19;
  }
}else if (state == 19){
  x = x+1;
  y = y+1;
  if (x > 750){
    x = 750;
    y = 500;
    state = 20;
  }//Y
}else if (state == 20){
  //background(102);
  x = x+1;
  if (x > 850){
    x = 850;
    y = 500;
    state = 21;
}
}else if (state == 21){
  y = y-1;
  if (y < 450){
    x = 850;
    y = 450;
    state = 22;
  }
}else if (state == 22){
  x = x-1;
  y = y-1;
  if (x < 800){
    x = 800;
    y = 400;
    state = 23;
}
}else if (state == 23){
  x = x+1;
  y = y+1;
  if (x > 850){
    x = 850;
    y = 450;
    state = 24;
  }
}else if (state == 24){
  x = x+1;
  y = y-1;
  if (x > 900){
    x = 900;
    y = 400;
    state = 25;
  }
} else if (state == 25){
  //background(102);
    x = x+1;
    if (x > 1000){
      x = 1000;
      y = 400;
      state = 26;
    }
}else if (state == 26){
  //background(102);
  y = y+1;
  if (y > 500){
    x = 1000;
    y = 500;
    state = 27;
  }//M
}  else if (state == 27){
    x = x+1;
    y = y-1;
    if (x > 1100){
      x = 1100;
      y = 400;
      state = 28;
    }
}else if (state == 28){
  x = x+1;
  y = y+1;
  if (x > 1150){
    x = 1150;
    y = 450;
    state = 29;
  }
}else if (state == 29){
    x = x+1;
    y = y-1;
    if (x > 1200){
      x = 1200;
      y = 400;
      state = 30;
    }
}else if (state == 30){
  x = x+1;
  y = y+1;
  if (x > 1300){
    x = 1300;
    y = 500;
    state = 31;
  }
}else if (state == 31){
  //background(102);
  x = x+1;
  if (x >1350){
    x = 1350;
    y = 500;
    state = 32;
}
}//E
else if(state == 32){
  x = x+1;
  if (x > 1450){
    x = 1450;
    y = 500;
    state = 33;
  }
}else if (state == 33){
  x = x-1;
  if (x < 1350){
    x = 1350;
    y = 500;
    state = 34;
  }
}else if (state == 34){
  y = y-1;
  if (y < 450){
    x = 1350;
    y = 450;
    state = 35;
  }
}else if (state == 35){
  x = x+1;
  if (x > 1450){
    x = 1450;
    y = 450;
    state = 36;
  }
}else if (state == 36){
  x = x-1;
  if (x < 1350){
    x = 1350;
    y = 450;
    state = 37;
  }
}else if (state == 37){
  y = y-1;
  if (y < 400){
    x = 1350;
    y = 400;
    state = 38;
  }
}else if (state == 38){
  x = x+1;
  if (x > 1450){
    x = 1450;
    y = 400;
    state = 39;
  }
}
}


void M(){
 if (state == 0){
    x = x+1;
    y = y-1;
    if (x > 200){
      x = 200;
      y = 300;
      state = 1;
    }
}else if (state == 1){
  x = x+1;
  y = y+1;
  if (x > 250){
    x = 250;
    y = 350;
    state = 2;
  }
}else if (state == 2){
    x = x+1;
    y = y-1;
    if (x > 300){
      x = 300;
      y = 400;
      state = 3;
    }
}else if (state == 3){
  x = x+1;
  y = y+1;
  if (x > 400){
    x = 400;
    y = 500;
    state = 4;
  }
}else if (state == 4){
  x = x+1;
  y = y-1;
  if (x > 500){
    x = 500;
    y = 550;
    }
}
}

void A(){
  if (state_a == 0){
    x = x+1;
    y = y-1;
    if (x > 500){
      x = 500;
      y = 550;
      state_a = 1;
    }
  }else if (state_a == 1){
    x = x+1;
    if (x >525){
      x = 525;
      state_a = 2;
}
  }
}

Mechanical/Hardware Design

By: Tyler Galgas

Link to all 3D Models

Frame illustrations:

The frame illustrations were created in Adobe Illustrator so that the illustrations can be used to laser cut the chassis for Proposal Bot. The designs below are the second iteration of the chassis with improved measurements then the first iteration and added designs. The first iteration of the chassis was laser cut with 3mm acrylic, which proved as a problem for the strength of the chassis. The second iteration was made to be laser cut with 6mm wood, but because of COVID-19 and the closure of the library, we were unable to obtain the second iteration of the chassis.

Figure 1. Base of Chassis

Dimensions: 200.5mm x 150mm

The first illustration above is the base of the chassis with the mount for the pen plotter and cut out for the pen to write on the paper. This design was improved from the first iteration making it slightly bigger so that both the front and back plates along with the side pieces can fit on top of the base so that the chassis has more structural integrity.

Figure 2. Front and Back Plate of Chassis

Dimensions: 144mm x 65mm

Above is the illustration for the front and back plate of the robot's chassis.

Figure 3. Side Plates of Chassis

Dimensions: 200.38mm x 64.9mm

Above is the illustration for the side plates for the robot chassis. The side plates have a custom cutout mount that fits the NEMA 17 stepper motors. This design was improved after the first iteration after we saw problems with the clearance of the chassis from the ground along with problems with motor alignment. To fix these problems, we lowered the mounts of the stepper motors so that we can get more clearance of the ground so that the pen plotter works properly. Alignment of the motor mounts was also fixed by adjusting the dimensions of the plate.

3D Models of the Mecanum Wheels:

The mecanum wheels of Proposal Bot were made up of four different 3d models to fully assemble the mecanum wheels for omnidirectional motion.

Figure 4. Wheel Base Plate

Above is the 3d model of the wheel base plate for the mecanum wheels.

Figure 5. Wheel Outer Plate

Above is the 3d model for the outer wheel plate for the mecanum wheel.

Figure 6. Wheel Roller

Above is the 3d model of the rollers for the mecanum wheel. 10 rollers are connected to the inner and outer wheel plate via 3mm steel rods to assemble the mecanum wheel.

Figure 7. Shaft Coupler

Above is the 3d model for the shaft coupler of the mecanum wheel. These shaft couplers are used to connect the mecanum wheel to the stepper motor's shaft. This 3d model was custom designed for the NEMA 17 stepper motor shaft.

Pen Plotter 3D Models:

The Pen Plotter Base is meant to be screwed into the base of the chassis so that a pen can be attached allowing Proposal Bot to draw.

Figure 8. Pen Plotter Base

Below is the 3D model for the pen plotter moving block that is attached directly to the pen. This block will move in a linear motion on the pen plotter base. It is attached to the base via 3mm steel rods and a servo motor will transfer rotational motion into linear motion to move the pen up and down.

Figure 9. Pen Plotter Moving Block

Verification & Validation Test Plan

By: Ethan Thiessa

Proposal Bot generation 1 will verify all the functional requirements implemented in the design using the verification test plan. The execution of the test plan will involve 4 test cases. Each test case is segmented into steps such that each requirement can be verified sequentially. Additionally, each test case contains detailed success criteria and pre-conditions that will help in determining whether a requirement passes the verification. The test cases are labeled: TC-01, TC-02, TC-03, and TC-04. All test cases were performed in the office of Ethan’s home.

Test Case 1 involves visual-based tests used to verify requirements through visual inspection and/or visual tests.

Test Case 2 involves testing Proposal Bot’s basic operations verifing requirements related to the individual parts of Proposal Bot’s basic operations and movements.

Test Case 3 is the Missions test that verifys requirements related to the main mission of Proposal Bot.

Tets Case 4 is the ArxRobot test used to verify requirements related to ArxRobot firmware, commands, telemetry, and ArxRobot control panel.

Concluding Thoughts and Future Work

As we came to a close on this project, our group decided to video chat one last time to ponder and recap our time during this project. There were lots of things that went right and certainly double the amount of things that went wrong. At the end, our group was able to accomplish the task of drawing the letters "Marry Me", but the letters - while readable- were not the most aesthetically pleasing. In future iterations of this project, our group unanimously agreed that one of the biggest improvements were to increase the aesthetics of the project. Our frame could be a bit more pleasing especially if it were to be proposing to someone. Ideally, "marry me" was only the beginning and we hope that the next iterations improves upon the code and perhaps even allows for more letters to be drawn. The letters that were drawn should also be more aesthetic and even perhaps drawn in a cursive manner, which could instantly solve the aesthetic problem. In terms of hardware, Tyler and Jonathan believed that the hardware served its purpose but would have ideally had a stronger frame and a more sturdy pen plotter that could potentially change fonts.

It's interesting to note that in the beginning our group believed this project would be an easy A. Clearly, this was not the case and in fact, our group ran into many hurdles while also running into the cherry on top, the coronavirus situation. Implementing the engineering method and adapting to the many situations that occurred was surely a learning curve. Haydon and Ethan both had to adapt to testing the bot in a situation where face to face contact was not accessible and some creative methods were needed to fix the things that required unaccessible resources. In the future, we both agreed that these issues can be solved with a little bit of ingenuity and wit, and while not easy, I think the group succeeded in exceeding what we thought was possible in this project.

For the future groups that decide to take on our project (and this class in general) make sure that your group stays on top of the project. Always be prepared for the unexpected and try to keep an open mind when trying to discover new solutions. For example, instead of moving in a manner correlating to a distance, our bot was moved in correspondence to time which made things a bit easier for troubleshooting and presents a creative solution. Also, the Accelstepper library that was used for our project can both be a valuable tool and or also a pain so be wary. Most importantly and most typical of all classes, make sure you have fun and try not to stress as much. Follow the steps in the Engineering Method!

References/Resources

By: Ethan Thiessa, Tyler Galgas, Hayden Chiu, Jonathan Valdez

These are the starting resource files for the next generation of robots. All documentation shall be uploaded, linked to, and archived in to the Arxterra Google Drive. The “Resource” section includes links to the following material.

  1. Project Video
  2. CDR/PDR
  3. Schedule
  4. Verification and Validation Plan
  5. Solidworks File (zip folder) Linked to in Mechanical Design Post
  6. Fritzing Files Linked to in Electronics Design Blog Post
  7. EagleCAD files (zip folder) Linked to in Electronics Design Blog Post
  8. Arduino and/or C++ Code (zip folder) Linked to in Software Design Blog Post
  9. Complete Bill of Materials (BOM)