Pinball Machine EGGN 383 Final Project May 6, 2013

advertisement
Pinball Machine
EGGN 383 Final Project
May 6, 2013
Mei Li and Caleb Whitehead
Introduction
The objective of our project was to design and implement a small-scale pinball machine. To make
the project feasible given the allotted time we had, the operations of our pinball machine were limited.
Two servo motors drive two separate paddles. User input via a pushbutton activates the paddles to strike
the pinball, which then travels around the playing base. If the pinball enters the score region, it will be
detected by infrared (IR) break-beam sensors and the machine will update the score on the liquid crystal
display (LCD). If the pinball enters the escape region the machine will decrement the number of escapes
remaining. Game is over when the pinball escapes three times; the goal is to enter the score region as
many times as possible.
Project specifications were met with two software steps. First, we initialized all necessary
components such as the LCD and the PWM system, which controlled the servo motors. Second, we used
a polling technique to read input from the pushbuttons and drive the paddles accordingly, as well as to
read the input from the break beam sensors and adjust the scores on the LCD accordingly.
Hardware Overview
As shown in the hardware diagram in Figure 1, the main electrical components for this project are
the servo motors, pushbuttons, IR break-beam sensors, and LCD. The mechanical aspects of this project
consisted of the playing base, the paddles, and how they are mounted together with the electrical
components. We used two servo motors, rated at 6V, to swing the paddles to 60 degrees. The motors were
mounted on the bottom of the playing base, and as the pinball fell, the pushbuttons could activate the
motors. Two IR break-beam sensors were installed around the center of the playing base. The gap
between the emitter and the receiver served as the scoring region, and as the pinball travelled through the
gap, the beam was broken and the LCD updated the scoring. A similar principle applied to the IR breakbeam sensor installed at the bottom of playing base, and the difference was that this sensor served as the
escape region.
The picture in Figure 2 shows our implementation of the conceptual design in Figure 1. We used
wooden materials for the playing base and the paddles. Cardboard material was considered in our original
design but it was too fragile and did not offer a smooth playing field for the pinball. However, we used
cardboard material to make the edges and obstacles on the playing base.
1
Figure 1: Hardware Diagram
Figure 2: Hardware Implementation
2
Circuit Description
The circuit we used to construct the pinball machine consisted of two parts: the primary control
circuit and the 555 timer circuit. The first, shown in Figure 3, included the wiring between the HCS12
microcontroller and all of the major components involved in mechanical controls and data transfer. This
circuit can be further divided into three primary functions: The LCD was wired to PortAD, which was
used for this project as nothing more than a simple input/output port. PortT monitors the pushbutton
signal inputs and adjusts the servo motor outputs accordingly. Finally, the IR sensor outputs were
captured using 3 different pins on PortM.
The LCD used for this project was the same device used in Lab 7; the wiring method remained
unchanged from what we used previously, but because PortAD pins 0 and 1 were hardwired to other
components, all pins used were shifted up by two pins from those used on PortT. The IR sensor outputs
were sent to PortM, pins 2 through 4, which were configured as inputs to read the signals.
The wiring on PortT is somewhat convoluted for a couple of design reasons. The servo motors
require a PWM signal to control them properly; changing the duty cycle adjusts the device position.
PWM signals can be transferred from the PWM system to PortT using the MODRR register; however,
they can only be transferred to pins 0 through 4. However, the servo motor outputs, J3 and J6, are
hardwired to PortT pins 4 and 5. As a result, the PWM signals were sent to pins 3 and 4, and then the
signal on pin 3 was hardwired to pin 5 on the header board. All of this wiring is shown in Figure 3. The
pushbutton inputs used a simple pull-up resistor control scheme, and are sent to pins 0 and 2 on PortT,
which are configured as inputs.
Figure 3: Primary HCS12 control schematic
3
The second part of the circuit, shown in Figure 4, was the 555 timer circuit. Although the 555
timer was driven by the power supply from the SSMI board, this was an entirely separate circuit and used
only to produce the 38 kHz signal necessary for operating the IR LED outputs to the break beam sensors.
To achieve the desired square wave output, the 555 timer was configured in Astable mode, as depicted
below. A variable resistor was used to fine tune the signal output for the IR devices used. The output from
the timer was sent through a series resistor-IR LED circuit that transmitted a continuous beam to the IR
sensors in Figure 3.
Figure 4: 555CN IC Timer schematic
Software Design
As formerly mentioned, the software we used to control this device consisted of two primary
tasks within the main function. The first was an initialization phase, and the second, within the infinite
loop, was code that would continuously poll and respond to inputs on the pushbuttons and IR sensors.
Pseudocode for the software is shown in Figure 5, whereas Appendix A3 details the actual main function
in C used to implement the design.
Initialize
LCD (on PortAD)
PWM system (on PortT)
IR sensors (already set as inputs on PortM)
Set score to zero
Set number of escapes left to three
While(true)
Drive motor forward if button depressed
Drive motor back if button released
Waiting = 1 if score sensor detects ball
Increase score, waiting = 0 if score sensor doesn't detect ball and waiting = 1
If escape sensor detects ball, wait until escape sensor doesn't detect ball, then decrease escapes
left
Update counters on the LCD
Display "Game Over" if no escapes left
While (Game Over) enter infinite loop to disable game
Figure 5: Pinball Machine Pseudocode
4
In the initialization phase, all DDRx registers were set to appropriate values so that the pins were
configured as input or output, and the score counters were initialized to 0, for the score, and 3, for the
number of escapes allowed. All functions required to initialize the LCD are in Appendix A2; essentially,
this required clearing the display, configuring the cursors, and preparing it to show characters as desired.
In the polling phase, the motor functions were very simple. IF statements determined if the
pushbuttons were currently depressed or not, and changed the duty cycle of the PWM signal to the servo
motor accordingly. Polling the IR sensors required first evaluating whether or not any IR beams were
broken and then using that information to update the LCD display. The pseudocode shows redundancies
that were put in place to prevent unbounded scoring increases should the ball become lodged between
sensors. When the escape counter reached zero the “Game Over” state was implemented by entering a
second, nested loop that prevented the program from operating until the reset button was pushed.
Verification
Since this project consisted of different hardware components, we developed the testing
procedure for one component at a time. We started the implementation of the project by verifying that we
could adapt the LCD code and schematic from previous labs to be used on PortAD. After testing the
LCD, we moved on to experiment with different types of motors. Initially, we were not sure which type
of motor would be ideal to swing a paddle. The DC motor we had in the lab was not accessible as it was
built into a wheel system architecture, and would also have created error with continuous forward and
reverse motion. Furthermore, the stepper motor was designed for applications required accurate
positioning but could not provide torque adequate for our project, so we opted to use the servo motor.
Servo motors require a PWM signal to control their position. Having set-up the push-buttons to
control the PWM duty cycle for their corresponding motors, we used an oscilloscope to measure the
output signal being used. As Figure 6 shows, the steady position for each motor required a different duty
cycle, as they are positioned in mirror locations from each other.
Figure 6: PWM signal used to place each servo motor in initial, steady position
5
The next task was to implement the IR break-beam sensors. To make the pinball machine
portable, we decided to use a 555 Timer instead of a function generator to modulate the frequency
required for the IR emitter. In this process, we experimented with the potentiometer and the trimpot for
the variable resistor. As Figure 7 shows, the modulated signal for the emitter was not exactly 38 kHz. It
was important for us to maintain the 36.6 kHz signal in order for all the break-beam sensors to work
properly. Through experimentation, we found out that trimpot gave us more stabilized signals.
Figure 7: Modulated signal for IR emitters
After verifying the 555 timer, we tested the IR sensors. As expected, when an object was in
between the emitter and the receiver, the beam was broken. Figure 8 shows this instance while Figure 9
shows when there was nothing in between the emitter and the receiver. After testing the IR sensors we
mounted them on the board and soldered their terminals to wires for connection to the SSMI board.
6
Figure 8: Oscilloscope trace when an object breaks the IR sensor beam
Figure 9: Oscilloscope trace when there is no IR detection
7
Conclusion
Given the scope of the project specifications from the beginning, which proposed a simplified
version of a pinball game, this project was successful. After adding a second, external power supply we
were able to drive both servo motor paddles with precision, and the IR sensor system was successful in
detecting the presence of the ball and appropriately adjusting the score. Use of servo motors allowed the
position of the paddles to be controlled with every button press, which eliminated positioning errors that
may have been introduced by other motors. Also, the use of a 555 timer chip allowed us to make the game
more compact and portable, while still providing adequate control over the output signal.
While designing this project we faced three primary challenges that consumed a great deal of
time. The first challenge dealt with capturing the signal from the pushbuttons; initially we planned to use
input capture on PortT, but we discovered that the initial bouncing from the pushbutton produced
occasional false triggers that caused this method to be unreliable. We resolved this problem by polling the
state of the pushbuttons in the main function, rather than responding to the state transitions only.
The second problem was caused by the HCS12’s power limitations. When we attached both servo
motors simultaneously we observed erratic behavior when controlling them with the pushbuttons. This
included false triggers on both motors, continued, random oscillatory behavior after the pushbuttons were
no longer being operated, and failure to operate at all. This problem was resolved by powering the second
motor with an external 5V DC power supply, but still using the PWM signal from the HCS12 for control.
This system allowed us to retain both paddles in our design. Although we were able to use both motors,
we were required to use slower motors provided in lab rather than higher speed servos, as the parts we
ordered did not arrive on time.
The final difficulty we faced was tied to the IR sensors. We found there to be some slight
variation in the signal frequency that each IR sensor would detect, so there was a substantial amount of
trial and error involved in configuring the 555 timer to output exactly the right signal so that high and low
signals were consistent.
We were pleased with the successful implementation of our design. We learned a great deal about
the power dependency of the HCS12 microcontroller, and were able to expand our knowledge about using
the various ports available.
8
Appendix
A1: Microsecond Delay Function (delays number of microseconds input x10)
void DelayuSec(unsigned int t) {
if (t !=0){
t*=10;
__asm {
; Main loop is 24 cycles, or 1 usec
ldx t
; 3 additional cycles here
loop: psha ; 2 E cycles
pula
; 3 E cycles
psha ; 2 E cycles
pula
; 3 E cycles
psha ; 2 E cycles
pula
; 3 E cycles
psha ; 2 E cycles
pula
; 3 E cycles
nop ; 1 E cycle
dbne x,loop ; 3 E cycles
}
}
}
A2: LCD Functions (writeNibbleToLCD, writeByteToLCD, InitializeLCD, printLCD)
void writeNibbleToLCD(char n, char rs, int t) {
rs <<=5;
PTAD = (rs|0x10|(0x0f & n))<<2;
//PTAD <<= 2;
DelayuSec(1);
PTAD &= ~0x40;
DelayuSec(t);
}
void writeByteToLCD(char b, char rs, int t) {
char temp = b>>4;
writeNibbleToLCD(temp, rs, 1); // for high nibble, shift left 4
// bits
writeNibbleToLCD(b, rs, 1); // for low nibble, nibble function
// will take care of masking b
DelayuSec(t);
}
void InitializeLCD(void) {
int i;
for (i=0; i<100; i++) {
// delay 100ms to allow LCD powerup
DelayuSec(1000);
}
9
// The first parameter in each call is the nibble to be sent,
// the second parameter is the rs value (rs=0 indicates an
// instruction), and the third parameter is the time to delay
// after sending (in units of us).
writeNibbleToLCD(0x03, 0, 5000); //delay at least 4 ms = 4000 us
writeNibbleToLCD(0x03, 0, 5000);
writeNibbleToLCD(0x03, 0, 5000);
writeNibbleToLCD(0x02, 0, 5000);
// The first parameter in each call is the byte to be sent (as
// two nibbles), the second parameter is the rs value (rs=0
// indicates an instruction), and the 3rd parameter is the time
// to delay after sending both nibbles (usec).
// These commands are all fast (~40 us) except for "clear
// display" (2 ms)
writeByteToLCD(0x28,0,50); // 2 lines, 5x8 dots
writeByteToLCD(0x0c,0,50); // display on, no cursor, no blinking
writeByteToLCD(0x14,0,50); // shift cursor right
writeByteToLCD(0x01,0,2000); // clear display and cursor home
}
void printLCD(char mystr[]) {
int i;
char strChar;
writeByteToLCD(0x01,0,2000); // clear the display
for(i = 0; i<80; i++) {
strChar = mystr[i];
if(strChar == 0) break;
writeByteToLCD(strChar, 1, 50);
}
}
A3: Main Function (with include statements)
#include <hidef.h>
/* common defines and macros */
#include "derivative.h"
/* derivative-specific definitions */
#include <stdio.h>
void main(void) {
/* initialize variables for LCD */
char toLCD[80];
// Stores the value to be displayed
int file_number = 0; // Unused variable used to call sprintf
int score = 0;
// Score count
int escapes = 3;
// Number of escapes remaining
char waiting, update; // Used in the IR polling function
// initialize PAD pins for LCD
DDRAD = 0xfc;
10
// Set up PWM System to drive the Servo motor(s) on PT3-PT4
PWMCLK = 0x18;
// Select clock SA/SB as the clock source
PWMPRCLK = 0x66; // Set clock prescalar to 64 on A and B
PWMSCLA = 15;
// Divider for clock SA
PWMSCLB = 15;
// Divider for clock SB
PWMPOL = 0x18;
// PWM3/PWM4 output high at the start of period
PWMPER4 = 250;
// Period = 250 ticks
PWMPER3 = 250;
PWMDTY4 = 14;
// Duty = 12 ticks, which is about 1 ms
PWMDTY3 = 22;
PWME = 0x18;
// Enable PWM3/PWM4
MODRR = 0x18;
// Route PWM to PortT PT3/PT4
// Set up PT3/PT4 for output to the motors
DDRT = 0x18;
InitializeLCD();
EnableInterrupts;
waiting = 0;
// Initialize IR sensors with no ball detectio
// Initialize score display to starting values
file_number = sprintf(toLCD, "Score: %d \n\n Escapes Remaining:
%d", score, escapes);
printLCD(toLCD);
for(;;) {
/* * * * * POLL PUSHBUTTONS * * * * */
//"Outside" pushbutton controls J3, treats it as left paddle
//"Inside" pushbutton controls J6, treats it as right paddle
//PWM Duty cycles for forward and reverse positions are opposite
//for left and right paddles
if (!(PTT &0x01))//PT0 is low; Left Motor forward
PWMDTY3 = 14;
else
PWMDTY3 = 22;
if (!(PTT &0x04))//PT2 is low; Right Motor forward
PWMDTY4 = 22;
else
PWMDTY4 = 14;
/* * * * * POLL IR SENSORS * * * * * */
if (PTM & 0x18){ //check if ball is in a score region
score++;
//if present, increase score counter
update=1;
//”update” tells the LCD to refresh
}
11
if (PTM & 0x04) {
while (PTM & 0x04);//if ball enters escape region, wait for
//user to remove it
escapes--;
update = 1;
//”update” tells the LCD to refresh
}
if (escapes>0){
file_number = sprintf(toLCD, "Score: %d \n Escapes Remaining:
%d", score, escapes);
if (update){
//Takes time, so only refresh if scores change
printLCD(toLCD);
update =0;
}
}
if (escapes ==0) {
printLCD("Game Over");
for(;;); //infinite loop prevents further gameplay at “Game
//Over” until Reset button pressed
}
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
12
Download