CS 153: Project 8

Title image Fall 2018

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

    Setup

  1. 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.
  2. Part 1: Accelerometer/Magnetic Sensor Library

  3. 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 Adafruit help pages for the LSM303 sensor.

  4. 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.

    1. Add two 3-element float arrays to hold the smoothed acceleration values (e.g. avgacc) and the derivative values (e.g. dacc).
    2. Add two 2-element float arrays to hold the smooth magnetic values (e.g. avgmag) and the derivative values (e.g. dmag).
    3. Add an int field to specify the filter size (e.g. filterSize).

  5. In your ACSensor::init method, initialize all of the average and derivative arrays to zero. Initialize your filterSize to 10.
  6. Add the following member functions to your class. The accessor functions you can put into the class definition if you wish.

    1. void setFilterSize( int N ) - set the filter size field to the given value N.
    2. int getFilterSize(void) - return the current filter size;
    3. Write accessor functions for the smoothed x, y, z accelerometer values (e.g. float avgacc_x(void)).
    4. Write accessor functions for the smoothed x, y magnetic values.
    5. 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.

  7. 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.

  8. 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);
    }

  9. Take a look at this animate function. You may use it as the basis for your own or write your own from scratch.
  10. 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.
  11. Take a video of your activity program working and include it in your wiki or handin folder.

Follow-up Questions

  1. What is an overloaded function? Give one example from the lab/project.
  2. Would all of your main code from project 7 still work with the updated LEDBank and ACSensor libraries?
  3. What are the benefits of using a function like rec_add, compared with copying a pasting that code into multiple functions?
  4. Why make rec_add a private member function?

Extensions


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.

  1. 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?

  2. 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.
  3. 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.
  4. The answers to any follow-up questions.
  5. A brief description (1-3 sentences) of what you learned.
  6. 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.
  7. 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.

Your report should be submitted as a wiki page with the appropriate label, as noted above.