Determining Colors

The code to read the input from the ADC was mainly from the ADC lab. Differentiating between colors was a difficult task. The read value was affected significantly by the distance between the sensor and the cube. The sensor allowed the servos to turn consistently to the same position but the blocks turned different amounts because the center piece of each face was loose and couldn't fully control those cubes around it. This caused the readings to differ depending on how the cube was turned previously. The ratios of the readings remained consistent for each color so we used the ratios R/G and G/B to differentiate between most colors. White consistently had a higher sum of these readings so we also used the sum to determine white. Using the ratios and sums to differentiate colors, we still had trouble between red and orange as well as between green and white. We narrowed the ranges of each acceptable reading for each color to help avoid collisions. As a safegaurd, we tested whether any group of readings didn't match exactly 1 color and repeated the reading if needed.

Turning the Cube

For turning the cube, we enabled the PWM and read the light sensors until we recorded the correct number of transitions. Then we re-disabled the PWM. We used polling as opposed to interrupts for the black / white wheels. The advantages of this were minimal delay and simplicity. Also, because there wasn't anything to compute while we waited, interrupts offered no advantage.

The Algorithm

Once all the sides had been read in, we could begin solving the cube. So we needed an algorithm that we could give the state of the cube, and that would return a sequence of turns to solve it. The problem was that the algorithm needed to fit on the Smartfusion board we were using. We looked online and found several optimal algorithms that would produce solutions with near the minimum number of turns required to solve it. However, those algorithms used large pruning tables and we weren't sure if the 256KB of memory on our board would be enough to hold them. We decided to search for a smaller, suboptimal solution and found one that used a 'humany' algorithm and didn't require large pruning tables. We converted the state that we'd read in into a the expected format of the algorithm. It returned a string so we parsed it, and performed the corresponding turns.

The algorithm and its source code were results of a competition.
Credit for the algorithm and its source code goes to:
Yuri Pertsovski : yuri_p@walla.co.il

Group Coding

To distribute the work of coding, we divided it into functions subsets. When we came to a point where we required another areas control, we just called functions with the necessary parameters. Then, when both areas were near completion, we could combine them by implementing the functions other areas required. This also allowed incremental testing by using dummy functions in place of the unmade function.

Psuedo-Code

      main {
        initialize everything
        forever {
          while( not paused, not solve, and not randomize )
            wait
          if solve {
            read cube
            run algorithm
            perform turns {
              while( pause )
                wait
            }
          }
          else if randomize {
            turn randomly
          }
        }
      }
      
      buttons ( interrupts ) {
        set pause, solve, or randomize
      }
    

Our Software Project Files

Task distribution:

John Marcoux:

  • testing servos
  • configuring light wheels

Yan Zhang:

  • Software & Algorithm
  • testing color sensor bounds

Cheng Li:

  • ADC setup
  • color sensor

Brian Kirkpatrick:

  • timer/PWM verilog
  • testing servos