UBC Mech 423 Final Project Proposal Body-weight-shifting RC Car Game GoGoRC Kelvin Poon-Feng (54004106) kelvin.poonfeng@alumni.ubcl.ca Jordan (Yodan) Karyanto (58104100) lhjordanlh@gmail.com April 13th, 2015 1 Abstract Shifting body-weight to command has not been the most common way of implementing controller. There have been several successful cases such as the Wii Fit or some electric skateboards, but the applications and the options for weight-shifting controller is rather limited. Therefore, in this Mech 423 Biomechatronics course, we decided to build a weight-shifting controller ourselves and test the application and investigate on the control algorithm. To make the project more extensive and interesting, we also used the controller to control a remote control toy car and even built the interactive race track for user to play. In the end of the project, we have a working prototype of a weight-shifting controller, its compatible sensor circuitry to connect to the microcontroller and radio frequency transmitter, the codes that control the RC car and the interactive race track as well as a software for gaming interface. The user can stand on top of the controller board to run the RC car and play the game that requires the RC car to pass through checkpoints in the shortest time possible. Below is a picture of the final product. 2 Table of Contents Contents 1. Project Objective .................................................................................................................... 4 2. Rationale for Project............................................................................................................... 4 3. Summary of Functional Requirements: .................................................................................. 4 4. Functional Requirement 1: Board Platform Design and Fabrication ....................................... 5 5. Functional Requirement 2: Electrical Circuitry of the Controller .............................................. 7 6. Functional Requirement 3: RC Transmitter Circuitry and Code .............................................. 9 7. Functional Requirement 4: Arduino Code for Sensor Interface and Radio Command Transmission ............................................................................................................................11 8. Functional Requirement 5: Interactive Game Track with C# Program ...................................12 9. System Evaluation ................................................................................................................14 10. Reflections ..........................................................................................................................15 Appendix A: Sensor Circuit Test Code ......................................................................................17 Appendix B: Transmitter Test Code ..........................................................................................18 Appendix C: Weight-shift Controller Code .................................................................................19 3 1. Project Objective The vision of this project is to build a fully functioning game where the user gets to stand on a board to control a RC car on a custom-made track by weight-shifting his/her body. The game consists of controlling the RC car to pass through several checkpoints (using sonic-transducer sensor) in the shortest amount of time. At the end of the project, we completed a platform (the board) where the user will be able to stand on and shift his/her weight forward, backward or turning to control the RC car in the same direction. The RC car will receive the signals and move on the track and try to pass the checkpoints in the shortest given amount of time. There is also be an functional game user interface built with C# working with Arduino and sonic transducer to run the timer and record the scores. The RC car itself is a store-bought toy car. 2. Rationale for Project Using human instinct to control modern electronic and technologies has been the mainstream trend of modern technologies. There has been many technologies that use gesture input or other ways of acquiring inputs from hands or arms, but there are less that use body balance and body weight. We think we can use this as a training for us to build the next generation of modern technologies. The application of using body balance/weight input can be used in controlling modern vehicle, virtual reality gaming, fitness training purpose and more. Moreover, through this project we can also learn to integrate many other technologies and skills such as wireless communication, serial communication with user experience in gaming and more. Finally, the main objective of this project is the development of the balance sensor. Although the sensor is used to interface with a RC car in this project, it could potentially be useful for other projects such interfacing with computer for skateboarding and/or snowboarding training game, or as the controller of a two-wheeled electric board (imagine a mountable and driveable roomba). There might have been some similar projects that have been done and similar technologies that are available elsewhere, but there hasn’t been a game that is easily accessible to public that one can play and see the tangible output instead of in virtual reality (eg. Screen). We believe the game will be enjoyable and fun, at the same time, we can learn a lot from this project. 3. Summary of Functional Requirements: The overall system has been separated into five functional requirements. Table 1 summarizes the functional requirements and lists the responsible person for the particular FR. Each FR is also explained further in the next sections. Table 1: Functional Requirements of the Project, listed with effort required and assigned person Functional Requirements % Effort Person Responsible FR#1: Board Platform Design and Fabrication 15 Jordan 4 FR#2: Sensor Interface Circuitry and Controller Electronics 20 Kelvin FR#3: RC Transmitter Circuitry and Code 15 Kelvin FR#4: Arduino Code for Sensor Interface and Radio Command Transmission 30 Both FR#5: Interactive Game Track with C# Program 20 Jordan 4. Functional Requirement 1: Board Platform Design and Fabrication FR1: Approach and Design The objective is to build the platform at the input device of the system. The platform has a basic mechanical design consisting of two plywoods sandwiching a rubber mat, where the 4 sensors will sit at four corners. As the body weight is shifting, the four corners will bend and thus commanding the sensors. Figure 1: Original Platform Framework with Sensors 5 Figure 2: Redefined Framework with Sensor Solidworks Design Figure 2: Redefined Platform Framework with Sensors (Exploded View) FR1: Inputs & Outputs The material are 2 plywoods, a rubber mat and 4 force sensors along with 8 padding made with mouse pads as shown above. The input will be the person standing on the board and shift his/her weight in all directions. The output will be the four resistance changes coming from the four sensors. (Can be detected with multi-meters to examine the change of resistance). FR1: Parameters The parameters here will be the sensor’s orientations, sensor’s mounting, sensor’s triggered sensitivity, board strength, mat’s flexibility. The sensor’s sensitivity is affected by the nature of the sensor design and all the other parameters described above. The difficulty is the design and implementation of one will affect the other parameter. For example, if the rubber mat is too flexible then the board needs to be more stiff; if the sensor is over sensitive, then the board and the mat needs to be more stiff. The mounting of the sensor will also depends on how the board interact with the sensor and rubber mat. Thus, we need to fix the most limiting parameter first, in this case, it would probably be the stiffness of the board as we don’t have too wide of a range for the stiffness of the board. The followed by the sensor’s nature sensitivity, the rubber mat’s properties and the rest should be easier to be adjusted. In the operation, I will build the frame of the platform first and adjust the mounting of the sensors as well as the other parameters. FR1: Testing and Results The testing on this module is rather simple. At first was finding the range of the sensitivity of the sensor. The range was easily found by connecting the sensor’s lead to the multimeter and measure the minimum and maximum resistance of the sensor by pressing it from no pressure to full pressure with finger tips. We then place the sensors in between the paddings and stood on the board and see the range of the change of the resistance of the sensor while shifting the body weight forward, backward and sideways. In the end, we only needed to make a little changes such as the thickness of the paddings and how tight the bolts and nuts tightening the plywoods, padding, rubber matt and sensors. This is because the materials and the geometry seemed to give a very reasonable range of resistance change to begin with. 6 The board was eventually incorporated with the sensor circuitry and MCU very well making it a great weight-shifting controller. 5. Functional Requirement 2: Electrical Circuitry of the Controller FR2: Approach and Design The objective of this functional requirement is to create and handle the electrical circuitry used to obtain data from the sensors. Functional Requirement 1 handles the aspect of placing the sensors on the platform, while the electrical connections are handled in this section. As stated before, the sensors are force sensing resistors (FSRs). The sensors were connected following the manufacturer's guide for a voltage divider as shown below. Figure 2: Sensor Schematic Since the FSR’s resistance goes down as the force increases, the sensor was connected such that when no force is applied, the signal would be zero. An op-amp buffer was used to reduce the error from the source impedance. A TL082 op amp was used and it was powered by +12V and -12V. The +5V and +12V were supplied directly from the Arduino UNO and the -12V was supplied by another wall-wart. Hence, a total of two identical 12V wall-warts were used to power the sensors. The output signal of this circuit was connected to one of the Arduino UNO analog ports. The R1 resistor is the calibration resistor that alters and adjusts the sensitivity of the sensor. The voltage signal as a function of force of this voltage divider is shown below. Figure 3: Voltage Divider Output (taken from FSR Sensor Manufacturer’s guide) Note that the force is in units of grams. As shown in Figure 3, the behaviour of the sensor is highly non-linear for high values of R1. However, for resistances between 3kΩ and 10kΩ, the signal increase is more gradual. Once attached to the board, we tested the minimum resistance 7 the FSR would go down to by shifting most of the weight to the sensor. It was found that the FSR would go down to 1kΩ. We first tried using 10kΩ, but the signal would saturate too quickly for our purpose, hence, by trial and error, we used 6.8kΩ instead. This would ideally give us a maximum voltage signal of 4.35V, which we can then map to 5V in the code. The complete circuit schematic is shown next. Figure 4: Sensor Circuit Schematic Hence, the sensor circuitry consists of four voltage dividers corresponding to the sensors at each corner of the board. The circuit was soldered onto a protoboard and enclosed in a box as shown below. Figure 5: Completed Circuit and Enclosure FR2: Inputs & Outputs The inputs into sensor circuitry is the 5V source and the external force input from the person’s weight. The outputs of the sensors will be their voltage representation of the force applied at their location. These voltages are fed into four analog ports in the Arduino Uno. The range of the voltages is 0 - 5 V and the received analog has a 10-bit resolution for a signal that ranges from 0 to 1023. 8 FR2: Parameters The parameters of this functional requirement are the calibration resistance values. These resistors are used to calibrate the sensitivity of the sensors. Ideally, the higher the range, the better. Hence, the target was to try and obtain the largest range. As discussed above, the 6.8kΩ resistor was used. FR2: Testing and Results To develop the sensor circuitry, the following plan was carried out. 1. Test and characterize sensitivity of sensors a. The sensors were connected to a multimeter and the resistance of the FSR was observed as the force increased. From this, we found that the sensor is nonlinear and has a saturation level at 1kΩ. 2. Calculate ideal resistance for calibration resistors to obtain maximum range across 5-V, and iterate accordingly a. Using the 10kΩ resistor would’ve given a higher range, but it would’ve also introduced more nonlinearity. Hence, the 6.8kΩ was used. 3. Feed the voltage divider signals through the buffer op amps and then to the Arduino Uno, then check the received signal To test the resulting circuit, we used the serial port of the Arduino Uno to receive and print the values at the analog ports. We observed that when there was no force, the signal would read zero and when they were pressed, the signal would read values around 900 - corresponding to the voltage of 4.35V as expected. These observations indicated that the sensors and the interface circuitry were working as designed. The code used for this test is in Appendix A. 6. Functional Requirement 3: RC Transmitter Circuitry and Code FR3: Approach and Design The objective of this functional requirement is to create the communication link between the board and the RC car. The original idea, as outlined in the proposal, was to create a transmitter from scratch. However, given the tight project timeframe, it was decided that it would be quicker to use the controller that came with the toy car. The controller uses push buttons to detect whether to move forward, backwards, turn left or turn right. By soldering lead wires into the PCB test points corresponding to these pushbuttons (as shown below) and then sending signals to them using the Arduino Uno, a master-slave controller was established. 9 Figure 6: Controller Circuit Figure 7: Transmitter Circuitry Testing the controller, it was found that it was active low. Furthermore, the turning of the RC car could only be in three states: turning right, turning left, or not turning. Hence, the signal that is sent to the LFT and RGH pins are digital, while the signals for FOR and BAC are PWM signals to control the speed. FR3: Inputs & Outputs The inputs into this section is the four command inputs: move forward, move backwards, turn left or turn right. The signals are active low, hence they are kept high when there is no signal. The turn signals are digital, while the forward and backward signals are analog PWM signals.. The output is the RC transmission signal. FR3: Parameters There were no parameters that needed to be tuned or changed. FR3: Testing and Results To test whether the system worked, a pre-planned sequence was written into the Arduino. The test code has been replicated in Appendix B. Since the test was qualitative in nature, there are no quantitative results recorded other than whether the system worked or not. After applying the test code, it was observed that the circuit does work as intended. 10 7. Functional Requirement 4: Arduino Code for Sensor Interface and Radio Command Transmission FR4: Approach and Design This module is the part where the MCU will take the signals from the platform controller (from FR1 and FR2) as the command inputs and process the data to decide what to send to the RC car. The software will basically take the bytes inputs and command the transmitter to send the correct radio signal to run the RC car. The following figure shows the algorithm that was deployed. Figure 8: Code Algorithm As stated before, the sensors were highly non-linear. The calibration resistor was chosen to reduce this nonlinearity and the maximum voltage range with this resistor was 4.35V. After reading all four sensor signals, the input value was linearly mapped to the range 0 to 1023 using the map function in the Arduino library (that is, 4.35V now corresponds to 1023 and 0V corresponds to analog value of 0). From the input signals, the average of the front sensors is compared to the average of the back sensors by subtraction and the result determines both whether to go forward or backwards and the speed. The subtraction result is mapped to 0 and 255 values to get a valid speed signal. Afterwards the turning is determined by comparing the 11 left sensors with the right sensors. If the difference is higher than the turn threshold, the Arduino will send the corresponding turn signal. The code is then looped. FR4: Inputs & Outputs The inputs here would be the 4 input signals coming from the 4 sensors implemented on the platform. And the outputs would be the command signals telling the transmitter what to send and the output signals from the transmitter to the RC car. FR4: Parameters The parameter in this section is the turn threshold. The threshold must be tuned for better turning control. FR4: Testing and Results Appendix C contains the complete code of the project. The testing for this requirement is whether the assembled system works. That is, the test consists of finding out how well the weight-shift controller performs in controlling the RC car. Its performance can be observed in the project video made for the course. A summary of the observations of the testing is listed below: ● Controlling the speed of the car is hard due to the nonlinear behaviour of the sensors ● The turning of the car can be glitchy since it can get stuck (due to toy car build quality) ● A weight-shift based controller can feel unnatural due to the lack of dexterity associated in precisely changing one’s center of gravity - as such, precise direction and speed control can be hard 8. Functional Requirement 5: Interactive Game Track with C# Program FR5: Approach and Design In this module, a Window’s user interface program is written in C# that runs the game, a functioning track with obstacles and checkpoints made with sonic transducers is also completed. The C# program will start from requiring to connect with the Arduino that runs the sonic transducers, then it will prompt the user to enter one’s name and then jump to the main window. The main windows consists of the rules of the game, start button, reset button and the status of the individual checkpoint. (Picture shown below). Once the game is started, the timer will start counting down; when the user pass through the checkpoints, the checkpoint label will turn the color from red to blue and record the time indicating a status change as well as converting the time to score. And the tack is a little field with customizable obstacles, ramps and checkpoints made with sonic transducers that is connected to the Arduino, which is connected to the PC. 12 Figure 9: Running Track with Checkpoint Sensors Figure 10: Main Game Windows (Windows Program Layout) FR5: Inputs & Outputs The inputs are essentially all the materials such as the small wooden blocks, small wooden ramps and the physical presence of object in front of the sonic transducer checkpoints. The software side input would be things like user’s name, pressing start button and the signal from 13 the sonic transducers checkpoints. The output would be the signals of the sonic transducer checkpoints to the PC on the hardware side. On the software side, the output would be the pretty interface on screen that tell the user what stage of the game they are on (Start, beginning, playing, game over, score, ranking...etc). FR5: Parameters The parameters for the track itself would be the physical setup of the track (obstacles and ramps) and the the sonic transducer checkpoints as well as the RC car momentum and speed. On the software side, they are the signal from the sonic transducers and user inputs (such as name, start pressing...etc). The physical parameters such as the blocks, ramp and other obstacles implementation will depend on how strong (momentum and speed) of the car, we will have to make sure the game is playable (not too difficult), but the obstacles do work in the sense of making the game more challenging and fun. On the software side, the sonic transducer distance to the RC car path and other obstacles will affect the signal coming into the PC. Hence we need to carefully calibrate them. Where are user’s input such as name and pressing the start button should be trivial. FR5: Testing and Results The testing of system starts from directly connect all the components (PC program, Arduino, Sonic Transducer and obstacles) together and test the system by running the program. We first tried to see if the checkpoints worked as desired by putting our hands over the sonic transducers. Once it works, then we tried to play the whole game by controlling the RC car with the controller board and direct the RC car to pass through the sonic transducers. (Essentially playing the game) At first, there were some problem with the sonic transducer because there were too many wires connected to the Arduino, some wires were touching, some came loose making the game malfunctioning. Once the wires were cleaned up, the game worked perfectly as expected. Scores were converted properly and the timer also run smoothly. After that experience, we always make sure the wires connected to the Arduino are cleaned up properly, and we never encounter any problem anymore. 9. System Evaluation The overall system evaluation is very similar to the testing done for Functional Requirement 5 since that is the way it was planned from the beginning. The main goal of our project was to develop the weight-shift controller while the RC car and game track were mainly introduced to test how well the controller would perform. As such, the game track we used to test the system on (which is the same one used in the project video) requires turning and precise manipulation of the toy car to arrive at the checkpoints. The following figure shows the main components of the project: 14 Figure 11: Photo showing the Game Interface, the Game Track, and the Controller The game itself served as a test for the functionality of our system as it showed that the integration of all the components of our system worked correctly. 10. Reflections Overall, our end product of this GoGoRC project is a fair working prototype that has rooms for improvement. There are problems with the sensor’s linearization and there is also a mechanical limitation of the RC car, making the control of the RC car difficult at times. However, the controller board works in sending the proper signals with reasonable weight-shifting by the user and with certain degrees of software linearization. We had done enough research to make a fair evaluation of the level of difficulties associated with the project. Thus, we were able to fulfill all the functional requirements outlined in the original proposal. On the other hand, the fabrication of the product is rather rough and unpolished. If we have a chance to do this project over again, we will put all the parts together more quickly to leave more time for fine tuning and polishing the products. We also didn’t write the code in MSP430 because we got caught up tuning and calibrating the sensors. We would have used the MSP430 if we had a chance to do this project again. The most valuable things we have learned from the project is definitely the integration of all the electrical components for good user experience, using available scrap pieces to do fast mechanical prototyping and most importantly the making and using of weight-shifting controller. Not only we had a chance to practice our electrical and mechanical engineering prototyping skills, we also have better insight to weight-shifting controller. Understanding the sensor properties and tuning it to work with what the system desires is one thing, but actually standing on top of the controller and using it helped us to really understand the using of weight-shifting controller board. When the user shift their weight, the stiffness of the board to deflect should be 15 just enough to make user feel stable, but feeling the shift as well. More importantly, having the sensors to be tuned to have right sensitivity to make the user feel in control is even harder, but contributes the most to user experience, which is something we can work harder to make the system better in the future. As of the entire course, we think proper integration of electrical and mechanical design, proper firmware coding and fast engineering prototyping with available resources are the most valuable lessons. We would love to get more engaged and become more skillful in firmware coding and design as well as learning more serious control theory application and product development (such as business life cycle) in the future. We hope to learn deeper in these fields to get into mechatronic research and development. 16 Appendix A: Sensor Circuit Test Code The following Arduino Code was used to test whether the sensor circuit was working. const int topLeft = A1; const int topRight = A0; const int botLeft = A2; const int botRight = A3; double analogInTL; double analogInTR; double analogInBL; double analogInBR; void setup(){ Serial.begin(9600); } void loop(){ analogInTL = analogRead(topLeft); analogInTR = analogRead(topRight); analogInBL = analogRead(botLeft); analogInBR = analogRead(botRight); Serial.print(analogInTL); Serial.print(" "); Serial.print(analogInTR); Serial.print(" "); Serial.print(analogInBL); Serial.print(" "); Serial.print(analogInBR); Serial.println(" "); } 17 Appendix B: Transmitter Test Code The following Arduino Code was used to test whether the transmitter was working. const int forward = 11; const int backward = 10; const int turnLeft = 12; const int turnRight = 9; void setup(){ pinMode(turnLeft,OUTPUT); pinMode(turnRight,OUTPUT); pinMode(forward,OUTPUT); pinMode(backward,OUTPUT); pinMode(topLeft,INPUT); pinMode(topRight,INPUT); pinMode(botLeft,INPUT); pinMode(botRight,INPUT); analogWrite(forward, 255); analogWrite(backward, 255); digitalWrite(turnLeft, HIGH); digitalWrite(turnRIght, HIGH); } void loop(){ //Go forward for five seconds analogWrite(forward, 0); delay(5000); //Turn left for 500ms digitalWrite(turnLeft, LOW); delay(500); //Go Straight at half speed digitalWrite(turnLeft, HIGH); analogWrite(forward, 135); delay(1000); //Go backwards analogWrite(forward, 255); analogWrite(backward, 0); delay(2000); //Stop analogWrite(backward,255); delay(5000); } 18 Appendix C: Weight-shift Controller Code The following Arduino Code was used to read the sensor values from the board and transmit the commands as desired to control the RC car. const int topLeft = A1; const int topRight = A0; const int botLeft = A2; const int botRight = A3; const int forward = 11; const int backward = 10; const int turnLeft = 12; const int turnRight = 9; double analogInTL; double analogInTR; double analogInBL; double analogInBR; const int maxTL = 915; const int maxTR = 915; const int maxBL = 880; const int maxBR = 920; double go; double turn; int turnThreshold = 800; void setup(){ // Serial.begin(9600); pinMode(turnLeft,OUTPUT); pinMode(turnRight,OUTPUT); pinMode(forward,OUTPUT); pinMode(backward,OUTPUT); pinMode(topLeft,INPUT); pinMode(topRight,INPUT); pinMode(botLeft,INPUT); pinMode(botRight,INPUT); } void loop(){ analogInTL = analogRead(topLeft); 19 analogInTR = analogRead(topRight); analogInBL = analogRead(botLeft); analogInBR = analogRead(botRight); // // // // // // // // // Serial.print(analogInTL); Serial.print(" "); Serial.print(analogInTR); Serial.print(" "); Serial.print(analogInBL); Serial.print(" "); Serial.print(analogInBR); Serial.print(" "); analogInTL = map(analogInTL,0,max(maxTL,analogInTL),0,1023); analogInTR = map(analogInTR,0,max(maxTR,analogInTR),0,1023); analogInBL = map(analogInBL,0,max(maxBL,analogInBL),0,1023); analogInBR = map(analogInBR,0,max(maxBR,analogInBR),0,1023); // // // // // // // // // Serial.print(analogInTL); Serial.print(" "); Serial.print(analogInTR); Serial.print(" "); Serial.print(analogInBL); Serial.print(" "); Serial.print(analogInBR); Serial.print(" "); go = 0.5*(analogInTL + analogInTR) - 0.5*(analogInBL + analogInBR); turn = (analogInTL + analogInBL) - (analogInTR + analogInBR); // // Serial.print(go); // Serial.print(" "); // Serial.print(turn); // Serial.print(" "); if(abs(turn)>turnThreshold){ go = 2*go; if(turn > 0){ digitalWrite(turnLeft, LOW); digitalWrite(turnRight, HIGH); }else{ digitalWrite(turnLeft, HIGH); digitalWrite(turnRight, LOW); } 20 }else{ digitalWrite(turnLeft,HIGH); digitalWrite(turnRight,HIGH); } if(go > 0){ go = map(go,1023,0,0,255); analogWrite(forward,go); analogWrite(backward,255); }else if(go < 0){ go = -go; go = map(go,1023,0,0,255); analogWrite(forward,255); analogWrite(backward,go); }else{ analogWrite(forward,255); analogWrite(backward,255); } delay(5); } 21