CS5: Introduction to Computer Science at Harvey Mudd College
CS5 Web > Eng11Page2010
Submissions: CS submission site

Engineering 11 Programming References Webpage

Welcome! This page is simply a collection of useful references, hints, and tips for the programming assignments for Engineering 11, Autonomous Vehicles.

Note that homeworks are due at 12:15 on Mondays for E11 instead of the CS-standard times...


References and useful links

  1. Again, start with the solution for problem 41, which is pasted below and linked above. Rename this as ps42.pde.
  2. Partner up with someone who has the light-flashing code running on their Mudduino. It's possible to run both the light-flashing and light-reading on the same Mudduino (and it's OK for this assignment), but it's far less realistic in the long run. This is because in the final project, there will be external beacons that will be flashing Gold Codes.
  3. First coding change: Change your ps42.pde program so that
    1. It no longer flashes the LEDs.
    2. It takes in readings from your phototransistor, once per iteration of the loop() function.
    3. It prints out those readings to the Serial port.
    4. Some code to help you do this is commented out at the bottom of the ps41 solution file - you could comment that back in. However, you'll need to be sure that your phototransistor is connected to the correct pin -- or, be sure that the pin number matches the one to which the sensor is connected!
    5. Check that this works - this is Part A. In order to check, place the LED of the other Mudduino next to the phototransistor and then run this light-sensing code. If the delay times in each loop are the same, you should see that the phototransistor readings match the outputs of the LED: remember that less light gives higher phototransistor readings, and more light gives lower transistor readings.
    6. You might want to submit your code as ps42.pde once this is working. Even if you do not complete the next few parts, you have one-quarter of it complete now... !
  4. Second coding change: Change your ps42.pde program again so that
    1. It has a new array that will hold the results of the phototransistor readings. To create this new array, you will want to declare it outside of the loop() function. I declared mine right next to the GC1 array and called it GC_readings. It should have the same length as GC1, at least if you're outputting GC1 from your light-emitting board.
    2. Similar to the solution of ps41, you will need a counter to keep track of which location in the GC_readings array you will write the current light reading. I used the same counter variable as in that solution, but you're welcome to use another variable!
    3. This time, do not print data each time through the loop() function. Instead, create an if statement that checks if you have read in GC_LEN values. You are probably making this check already, in order to keep counter from getting too large!
    4. When your code has read in a full array's worth of data, only then, print out the entire array to the Serial console. Thus, your program should print not once per loop(), but once for each 31 runs of loop().
    5. I'd suggest using the function printArray in order to print your array. You wrote printArray in a previous problem set!!
    6. In addition, each of those times your code prints, also print out the correct array of bits that represents the code being flashed. If it's still GC1, then you have that array at the top of your code, and you can use printArray to print it out, too!
    7. Be sure to test your code! You should see two arrays being printed every 31st loop. One will be the array of bits that is GC1; the other will be the array of light levels from your phototransistor. See if you can match up which light levels correspond to which bits. Remember that less light leads to higher sensor values and more light leads to lower sensor values!
    8. What will make it tricky to match up which light levels correspond to which bits are two things: first, the light levels are analog values, not digital 0's and 1's. Second, the light levels will likely be shifted relative to the original Gold code bits. We will take care of these two problems, in turn!
    9. You might want to re-submit your code as ps42.pde once this is working. Even if you do not complete the next few parts, you have two-quarters of it complete now... !
  5. Third coding change: Change your ps42.pde program again so that it transforms the analog light readings to a set of bits. Here are the steps you might want to take:
    1. Start from the results of the previous part! In fact, all of the changes you'll make in this part will happen only once every 31 times through loop(). Your code should have an if statement that checks when the array taking in light readings is full -- it is in that if block that your changes in this part will be made!
    2. One of the problems with the results of the previous part is that the values reported by the phototransistors are not bits, but analog values. In order to create an array of digital values (easier to compare with the actual GC1), you will first find the average value of all of the light readings in your GC_readings array.
    3. To find the average of all of the readings in your GC_readings array, write a function (I called mine find_average) that has the signature int find_average( int A[], int LEN ). That function will take as input an array (which will be your GC_readings array) and its length. Then, you will want to sum all of the values in that array (use a loop!!). Then, (after the loop has completed!) divide by the total length of the array. It's OK to that you use integer division, because the small round-off error will not matter in this case. Finally, return the result, which should be the average of the original values of the array.
    4. Once you have the average of the values in your GC_readings array, replace each value in GC_readings with either a 0 or a 1. That bit should represent whether the original light level in each location of GC_readings was bright or dark. To do this, you could write another function. Alternatively (this is what I did), you could write a loop back in loop(), within the conditional that runs every 31st time, to convert from the analog to digital values.
    5. Finally, print out that converted array, instead of the raw (analog) light-value array. As above, continue to print out the correct code, and see if you can match up corresponding values. They still may be shifted! We turn to that next.
    6. You might want to re-submit your code as ps42.pde once this is working. Even if you do not complete the next part, you have three-quarters of it complete now... !
  6. Final coding change: Change your ps42.pde program again so that it correlates the phototransistor's light readings against all possible shifts of GC1. The goal is to see that the correlation value is relatively low for all but one shift. For one shift (the correct one!) the correlation should be 31 -- or close to it, since there may be noise in the signal. Again, these changes will happen only within the if block that runs once every 31 times through loop(). Here are the steps you might want to take:
    1. After your GC_readings array contains only 1s and 0s, use your correlate function from problem set 3 to find - and print - the correlation between your GC_readings array and all of the possible shifts (with wrapping) of GC1.
    2. Because there are 31 possible shifts (with wrapping) of GC1, you will want to write a loop that does the following:
      • Correlate GC_readings with GC1
      • Print the resulting correlation value
      • "Wrap" the GC1 array so that every value moves one position to the right. The original rightmost value moves to the zeroth position in the array. Hint! You wrote a function wrap_dest in problem set three that does this for you -- or grab it from the solutions!!
      • Continue on with the loop until all 31 possible shifts have been computed and printed
    3. There should be an obvious spike in the correlation values when the GC_readings line up with GC1. If this is happening - congratulations! You have a program that can detect whether or not it is observing a Gold Code of GC1.
    4. Optional! For this assignment, you need not go further than this, but it's worth thinking about what will be needed to detect beacons later on. If you'd like to work on this now, great! If not, you'll have a chance in the future:
      • You'll need to correlate your GC_readings array against all of the different Gold Coldes you might want to detect -- after all, you won't know which one it is! The one that has the largest spike across all of the correlation values (for all of the possible shifts) is the one you're observing.
      • You may want to take more than one array-ful of readings before correlating! As noted in the assignment, you might take 8 array-fuls and then do some averaging or majority-detection to determine whether the light is high or low in the presence of noise.
      • You'll need to speed things up! The beacons run at 4000 hertz (250 microsecond delay). To do this, you need to be sure you're printing only every 31st time through the loop. In addition, you'll need to fix NEXT_TIME so that it is set to micros() + LOOP_TIME at the end of all of the printing: this is because the printing will take so much time, it will necessarily get out of sync.
    5. But, for now, submit your ps42.pde file - your Mudduino is now detecting Gold Codes (or, at least, GC1)!

    Here is a copy of ps41solution.pde:

    // A pair of Gold Code arrays for testing ...
    const int GC_LEN = 31;
    int GC1[GC_LEN] = {0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,0,1,0,0,1,0,1,1,1,1,0};
    int GC2[GC_LEN] = {0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,1,1,0,0,1,1};
    
    int PHOTO_PIN = 1;    // our phototransistor was on analog pin #1
    int LED_PIN = 7;      // the GREEN LED is 7
    long LOOP_TIME = 1000000;  // number of microseconds per loop
    
    void setup()
    {
      pinMode(LED_PIN, OUTPUT); 
      Serial.begin(9600);
      Serial.println("Hi there!");
    }
    
    long curr_time = 0;  // the current time
    // the next time we want to take some action...
    long next_time = curr_time + LOOP_TIME;  
    int LED_level = 0;
    int sensed_light_level = 0;
    
    int counter = 0;  // tracks the number of times through the loop() function...
    
    /*
     * This is a solution for ps41.pde
     *
     * The code below cycles through the values of the array named GC1,
     * whose length is GC_LEN
     */
    void loop()
    {
      // An example of how to loop every LOOP_TIME microseconds
      curr_time = micros();      // get current time...
      if (curr_time > next_time) // is it time yet?
      {
        // add our timer interval to next_time
        next_time = next_time + LOOP_TIME;
        
        // do our task - set the LED appropriately
        LED_level = GC1[ counter ];
        
        // update the counter by adding 1
        counter = counter + 1;
    
        // make sure it's in bounds by resetting to 0 if needed
        if (counter >= GC_LEN) { counter = 0; }
        
        // set the light level
        digitalWrite( LED_PIN, LED_level );
        
        // print the time - note that this takes a lot of time!
        Serial.print("Time was ");
        Serial.println( curr_time );
        // you will need ro get rid of the above printing
        // in order to run at 4000 Hz!
        
        // Similarly, we can wait a bit now, but not if we run faster
        delayMicroseconds( 100 );
        
        // code for reading from the phototransistor
        /*
        sensed_light_level = analogRead( PHOTO_PIN );
        Serial.print("light level: ");
        Serial.println(sensed_light_level);
        */
      }
    }
    



    • Fourth week
    • ps4.pdf: Problem Set 4, in pdf format
    • ps4.doc: Problem Set 4, in MSWord format
    • See below for the starter code for PSet 4...


    Starter code for ps41 and ps42

    // A pair of Gold Code arrays for testing later...
    const int MLSRS_LEN = 31;
    int GC1[MLSRS_LEN] = {0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,0,1,0,0,1,0,1,1,1,1,0};
    int GC2[MLSRS_LEN] = {0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,1,1,0,0,1,1};
    
    int PHOTO_PIN = 1;    // our phototransistor was on analog pin #1
    int LED_PIN = 7;      // the GREEN LED is 7
    long LOOP_TIME = 1000000;  // number of microseconds per loop
    
    void setup()
    {
      pinMode(LED_PIN, OUTPUT); 
      Serial.begin(9600);
      Serial.println("Hi there!");
    }
    
    long curr_time = 0;  // the current time
    // the next time we want to take some action...
    long next_time = curr_time + LOOP_TIME;  
    int LED_level = 0;
    int sensed_light_level = 0;
    
    void loop()
    {
      // An example of how to loop every LOOP_TIME microseconds
      curr_time = micros();      // get current time...
      if (curr_time > next_time) // is it time yet?
      {
        // add our timer interval to next_time
        next_time = next_time + LOOP_TIME;
        // do our task - change the light level
        if (LED_level == 0) {
          LED_level = 1;
        } else {
          LED_level = 0;
        }
        // set the light level
        digitalWrite( LED_PIN, LED_level );
        // print the time - note that this takes a lot of time!
        Serial.print("Time was ");
        Serial.println( curr_time );
        // you will need ro get rid of the above printing
        // in order to run at 4000 Hz!
        
        // Similarly, we can wait now, but not if we run faster
        delayMicroseconds( 100 );
        
        // code for reading from the phototransistor
        /*
        sensed_light_level = analogRead( PHOTO_PIN );
        Serial.print("light level: ");
        Serial.println(sensed_light_level);
        */
      }
    }
    

    END of starter code for ps41 and ps42


    Starter code for ps31

    printArray

    void printArray( int A[], int LEN )
    {
      for (int i=0 ; i<LEN ; i=i+1 )
      {
        Serial.print(A[i]);
        Serial.print(" ");
      }
      Serial.println("");
    }
    


    getKey

    int getKey( char message[] )
    {
      Serial.print(message);         // print a prompt
      
      while (!Serial.available())    // while no keypress is available...
        { delay(100); }              // wait for keypress
      
      int value = Serial.read()-48;  // de-ASCIIfy the keypress that came in 
      Serial.println( value );       // echo the input back to be sure
      return value;
    }
    


    getNKeys

    void getNKeys( char message[], int result[], int LEN )
    {
      Serial.print(message);      // print the prompt
      
      for (int i=0 ; i<LEN ; i=i+1 )
      {
        while (!Serial.available()) { delay(100); }  // wait for keypress
        int value = Serial.read()-48;  // de-ASCIIfy the keypress that came in 
        result[i] = value;             // assign to the right place in result
      }
      
      for (int i=0 ; i<LEN ; i=i+1 )   // echo the input back to be sure
         { Serial.print( result[i] ); }
      Serial.println("");
    }
    


    one possible tester using loop -- alter as needed

    const int LEN = 5;
    int A[LEN] = {0,0,0,0,1};
    int B[LEN];
    
    void loop()
    {
      
      Serial.println("\n\nWelcome!");
      int user = getKey( "Enter a # " );
      
      Serial.print("user is ");
      Serial.println( user );
      
      
      getNKeys( "\n\n\nEnter 5 #s ", A, LEN );
      
      Serial.print("Array A is ");
      printArray(A, LEN);
    
    }
    


    Some useful constants

    These are taken from Lecture 4's lecture notes...

    const int MLSRS_LEN = 31;
    int mlsrs_taps2345_seed00001[MLSRS_LEN] = {1,0,0,0,0,1,0,1,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,1,0,0,1,0,0,1};
    int mlsrs_taps2345_seed00011[MLSRS_LEN] = {1,1,0,0,0,0,1,0,1,1,0,1,0,1,0,0,0,1,1,1,0,1,1,1,1,1,0,0,1,0,0};
    int xor_of_above[MLSRS_LEN] = {0,1,0,0,0,1,1,1,0,1,1,1,1,1,0,0,1,0,0,1,1,0,0,0,0,1,0,1,1,0,1};
    int GC1[MLSRS_LEN] = {0,1,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,0,1,0,0,1,0,1,1,1,1,0};
    int GC2[MLSRS_LEN] = {0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,0,1,1,1,0,0,1,1};
    




    Starter code for ps20

    // ps20
    // name(s):
    // date:
    
    // Light sensing with feedback!
    
    int DIST_PIN = 0;     // the range sensor is on A0
    int LIGHT_SENSOR = 1; // the phototransistor
    int LED_PIN = 3;      // the pin that will control the LED
    
    int sensed_value = 0; // variable for raw light readings
    int SET_POINT = 200;  // the desired raw light readings
    
    double led_value = 0.0;  // the strength of the LED
    
    
    void setup()
    {
      pinMode(LED_PIN, OUTPUT); 
      Serial.begin(9600);
      Serial.println("Hello, World!");
    }
    
    void loop()
    {
      // get current reading
      // see the warning below to improve this!!
      sensed_value = analogRead( LIGHT_SENSOR );
      
      // here is where your feedback goes!
      
      analogWrite(LED_PIN, led_value);
      
      Serial.print(sensed_value);
      Serial.print(" ");
      Serial.println(led_value);
      
      delay(250); // you may want to change this...
      
      // if you enter a number key N, this will
      // make the SET_POINT 100*N 
      if (Serial.available())
      {
        int value = Serial.read() - 48;
        SET_POINT = value * 100;
        Serial.print("SET_POINT is ");
        Serial.println(SET_POINT);
      }
    }
    
    

    Starter code for ps21

    // 
    // ps21 using delays
    // Fun!
    
    int DIST_PIN = 0;     // the range sensor is on A0
    int LIGHT_PIN = 1;    // the phototransistor
    int SPEAKER_PIN = 4;  // for playing notes
    int LED_RED = 5;      // red led pin
    
    unsigned long prev_LED_time = 0; // previous LED time
    unsigned long prev_MSG_time = 0; // previous MSG time
    unsigned long curr_time = 0; // current time
    
    int LED_interval = 100;  // 100 milliseconds
    int MSG_interval = 500;  // 500 milliseconds
    
    int led_status = LOW;
    
    void setup()
    {
      pinMode(LED_RED, OUTPUT); 
      Serial.begin(9600);
      Serial.println("Salam, Dunya!");  // Azeri
    }
    
    void loop()
    {
      curr_time = millis();  // get the current time
      
      // check if it's time to toggle the LED
      if (curr_time - prev_LED_time > LED_interval)
      {
        if (led_status == LOW) { led_status = HIGH; }
        else { led_status = LOW; }  // toggle led status
        digitalWrite( LED_RED, led_status ); // go!
        prev_LED_time = curr_time;  // reset previous!
      }
      
      // check if its time to send a message
      if (curr_time - prev_MSG_time > MSG_interval)
      {
        Serial.println("Still going... :-)");
        prev_MSG_time = curr_time;  // reset previous!
      }
      
      // no delay needed!
    }
    

    Helper function for ps22

    int getKey( int msg )
    {
      Serial.print("Input # "); // prompt the user
      Serial.println(msg);      // finish the prompt
      
      // if no keypress has come in, wait for 100 ms
      while (!Serial.available()) { delay(100); }
      
      int value = Serial.read();  // read the keypress that came in
      return value - 48;  // return its numeric, not ASCII, value
    }
    





    Starter code for ps10

    // ps10
    // David_Harris@hmc.edu
    // Test the serial port
    
    void setup()
    {
      Serial.begin(9600);
      
      Serial.println("Hello world!");
    }
    
    void loop()
    {
    
    }
    

    Starter code for ps11

    // ps11: math
    // name
    // Shows off some arithmetic!
    
    int num = 0;
    
    void setup()
    {
      Serial.begin(9600);
      Serial.println("Hello world!");
    }
    
    void loop()
    {
      Serial.print("num is ");
      Serial.println( num );
      if (num % 2 == 0)
      {
        num = num + 1;
      }
      else
      {
        num = num + 3;
      }
    }
    

    Starter code for ps12

    // ps12
    // LED me!
    
    int light = 5;
    
    void setup()
    {
      pinMode(5, OUTPUT); // 5 is red
      pinMode(6, OUTPUT); // 6 is yellow
      pinMode(7, OUTPUT); // 7 is green
      Serial.begin(9600);
      Serial.println("\nHola, mundo!");
    }
    
    void loop()
    {
      Serial.print("Light is ");
      Serial.println(light);
      
      digitalWrite( light, HIGH );
      delay(500);
      digitalWrite( light, LOW );
      
      if (Serial.available())
      {
        light = Serial.read() - 48; // What??
      }
    }
    

    Starter code for ps13

    Use a copy of your finished ps12 code for this one...


    Starter code for ps14

    // ps14
    // Distance sensing!
    
    int DIST_PIN = 0; // the range sensor's pin
    int SPEAKER_PIN = 4; // the speaker pin
    int raw_distance = 0;
    
    void setup()
    {
      //pinMode(DIST_PIN, INPUT); // Not needed! (Thanks, Prof. Harris!)
      pinMode(SPEAKER_PIN, OUTPUT); 
      Serial.begin(9600);
      Serial.println("Hello, world!");
    }
    
    
    void loop()
    {
      raw_distance = analogRead(DIST_PIN);
      Serial.print("I read ");
      Serial.println(raw_distance);
      //tone( SPEAKER_PIN, 440 /* raw_distance*2 */ ); // 440hz
      delay(100); // 100ms
      //noTone( SPEAKER_PIN );
    }