Project 8: Darts
The purpose of this project is to continue to practice creating, editing, and using classes. The application for the project will be to create something like a Wii-mote using the LSM3038 chip. The application will be to use it to play a game of darts.
Tasks
- Create a new Arduino sketch and save it as darts. Once you have done that, copy your LEDBank_p8.h and LEDBank_p8.cpp files into the directory containing activity.ino. Alternately, you could make a new LEDBank_p8 folder in your libraries folder and put the two files there, where they will be accessible from any sketch.
- Create a new tab and save it as ACSensor_p8.h. Create a second tab and save it as ACSensor_p8.cpp. Copy over your code from project 7 into these two files.
-
The goal of the modifications to the ACSensor class for this project are to do some signal smoothing and to use the smoothed signal to calculate a derivative, which tells us how the acceleration is changing. Using the smoothed signals, we will detect when changes in the device's direction of motion have occurred.
First, we need to add some fields to our class definition to hold the smoothed averages, the derivatives, and the smoothness of the filter.
- Add two 3-element float arrays to hold the smoothed acceleration values (e.g. avgacc) and the derivative values (e.g. dacc).
- Add two 2-element float arrays to hold the smooth magnetic values (e.g. avgmag) and the derivative values (e.g. dmag).
- Add an int field to specify the filter size (e.g. filterSize).
- In your ACSensor::init method, initialize all of the average and derivative arrays to zero. Initialize your filterSize to 10.
-
Add the following member functions to your class. The accessor functions you can put into the class definition if you wish.
void setFilterSize( int N )
- set the filter size field to the given value N.int getFilterSize(void)
- return the current filter size;- Write accessor functions for the smoothed x, y, z accelerometer values (e.g.
float avgacc_x(void)
). - Write accessor functions for the smoothed x, y magnetic values.
- Write accessor functions for the derivative acceleration and magnetic values.
I found it useful to also write some functions like
void printAccelAvg(void)
for debugging purposes. - In your ACSensor::update member function, add the code necessary to generate a running local average (filtered signal) and for computing the derivative. You can follow the pseudo-code below, which goes at the end of the function.
Assign to a local float variable (e.g. weight) the value 1.0 / filterSize Loop over the three acceleration values Assign to a local float variable (e.g. preavg) the current value of avgacc[i] Assign to avgacc[i] the sum of (1-weight) times the preavg plus weight times the current reading Assign to dacc[i] the difference between the new avgacc[i] and the preavg Repeat the above instructions for the magnetic data (2 values instead of 3)
Part 2: Darts
The goal of this section is to write a program that uses the board as something like a Wii-mote to play a game of darts. To throw a dart, the user will draw back the device and then quickly move it forward. That will throw the virtual dart.
To detect a throw, the program needs to detect two events: (1) a large negative change in acceleration in the x-axis, and (2) a large positive change in acceleration in the X axis. We can do this by watching the derivative of the x acceleration.
We can design the game as a state machine with two states. In state 0, the program is watching for the first event. If it detects the first event then it initializes a sum of the x and y smoothed acceleration values and moves into state 1. In state 1 it continues to sum the x and y acceleration values until the second event occurs. When the second event occurs, it calculates the average forward velocity and the average sideways velocity, animates the dart going towards a target, and then returns to state 0.
-
Using the template below, write the main function for the darts game.
/* Name and header here */ #include <Arduino.h> #include "ACSensor_p8.h" #include "LEDBank_p8.h" // Animate prototype int animate(float y, float vel); // Main function for the darts game int main() { init(); /* variables here */ int state = 0; float runningy; // for summing y acceleration values float runningx; // for summing x acceleration values int count; // the number of values summed // create your ACSensor and LEDBank values here Serial.begin(9600); // because we like to flash LEDs led.on(500); led.off(200); led.on(500); led.off(200); for(int quit=0;!quit;) { acs.update(); switch(state) { case 0: // if the derivative in x is < -2 // print something to say it's here // set the LEDs all on or so some pattern // assign to runningy the current acceleration y smoothed average // assign to runningx the current acceleration x smoothed average // set count to 1 // set state to 1 break; case 1: // if the derivative in x is > 2 // print something to say it's here // turn off the LEDs // set state to 0 // divide runningy by count (and assign it back to itself) // divide runningx by count // call animate( runningy, runningx ) // break // increment runningy by the current y acceleration reading // increment runningx by the current x acceleration reading // increment count by 1 break; default: state = 0; break; } } return(0); }
- Take a look at this animate function. You may use it as the basis for your own or write your own from scratch.
- Have the main function keep track of the number of hits and misses. You might have it print out directions at the start of the main function.
- Take a video of your activity program working and include it in your wiki or handin folder.
Setup
Part 1: Accelerometer/Magnetic Sensor Library
Follow-up Questions
- What is an overloaded function? Give one example from the lab/project.
- Would all of your main code from project 7 still work with the updated LEDBank and ACSensor libraries?
- What are the benefits of using a function like rec_add, compared with copying a pasting that code into multiple functions?
- Why make rec_add a private member function?
Extensions
- Make your device fancier. Just remember you'll be moving it around a bit for the project.
- Use more LEDs. If you do this, comment on how difficult it was to make the change.
- Use sound and/or lights. If you do this, think about how to organize your code. Try making a class to manage the sounds.
- Make the game more interesting.
- Make it multi-player.
- Get user input at the start of the game to control aspects of it (e.g. how many rounds).
- Change the way the arguments to animate modify the dart behavior.
- Enable the target to be larger or smaller (e.g. gets smaller by round).
- Keep track of high scores.
- Make a different game. Bowling anyone?
- Make another constructor for the LEDBank class that takes in a string like "2 3 4 5 6" and uses the string to initialize the pins array and nPins fields. Look up the strsep function.
- Make the LED responses to activities more extensive.
Report
Each week you will write a brief report about your project. In general, your intended audience for your write-up is your peers not in the class. From week to week you can assume your audience has read your prior reports. Your wiki report should explain to friends what you accomplished in this project and to give them a sense of how you did it.
Your project report should contain the following elements.
- Abstract: a brief summary (200 words or less) of
the task, in your own words. give the reader context and
identify the key purpose(s) of the project. You can assume the
reader has read your prior assignments.
Writing an effective abstract is an important skill. Consider the following questions while writing it.
- Does it describe the CS concepts of the project (e.g. writing loops and conditionals)?
- Does it describe the specific project application (e.g. creating applications with the LCD)?
- Does it describe your the solution or how it was developed (e.g. what code did you write/circuits did you build)?
- Does it describe the results or outputs (e.g. did your code and circuit work as expected)?
- Is it concise?
- Are all of the terms well-defined?
- Does it read logically and in the proper order?
- A description of your solution to the tasks. This should be a description of the form and functionality of your final code and the design of your breadboard circuits. Try to describe your algorithm or code without including actual code in your report. Using 1-2 lines as an example is acceptable. Using simple diagrams or pictures of your board may be helpful when describing your circuits. Note any unique computational solutions or hardware circuits you developed.
- A description of any extensions you undertook, including images, videos, or diagrams demonstrating those extensions. If you added any functions, or other design components, note their structure and the algorithms you used.
- The answers to any follow-up questions.
- A brief description (1-3 sentences) of what you learned.
- A list of people you worked with, including TAs, and professors. Include in that list anyone whose code you may have seen, such as those of friends who have taken the course in a previous semester.
- Don't forget to label your writeup so that it is easy for others to find. For this lab, use cs153f18project8
Handin
Mount the Courses volume. Navigate to the Private sub-directory. Create a new folder called project01. (It's best to avoid spces in the directory name.) Each week, the following items should be submitted here.
- Code that should graded and any required supporting materials. This week, submit your code from all of the project tasks. Code from lab exercises will generally not be graded unless it is used as part of the project tasks.
- Videos of your work. You can also submit videos as part of your report on the wiki, but please put a copy of the video here.
Your report should be submitted as a wiki page with the appropriate label, as noted above.