Vous êtes sur la page 1sur 9

/* This is the heart of the electronic airsoft range controller

* Currently Parts of the code are implemented and tested


* This will be moved at an Atmega328P on a seperate board when it is completed
* Currently being prototyped on an Arduino Uno
*
*
* TODO:
* Log High Scores (10)
* Scroll through High Scores when not in active play mode
*/
// Use the below sequence to write to the max chip
// slave address -> command byte -> data byte
// include wire library
#include <Wire.h>
#include <Servo.h>

/* Variables & Constants */


Servo t1servo;// servo for target 1
// max 8 objects available
byte i = 0x00;
/* variables for debounce code */
const int resetbtnpin = 2;// for
int
resetState;// for
int lastResetState =LOW; // for
long lastDebounceTime = 0;// for
long debounceDelay = 50;// for

debounce
debounce
debounce
debounce
debounce

code
code
code
code
code

/* variables for MAX IC and related */


const int maxaddress = 57;// Address of MAX IC
const byte tR = B00000101;// letter R
const byte tD = B00111101;// letter D
const byte tY = B00111011;// letter Y
const byte tS = B01011011;// letter S
const byte tE = B01001111;// letter E
const byte tT = B01110000;// letter T
const byte tG = B01011110;// letter G
const byte tO = B01111110;// letter O
const byte blank = B00000000;// nothing
const byte LEDR = B00000100;// RED LED
const byte LEDY = B00000010;// YELLOW LED
const byte LEDG = B00000001;// GREEN LED

/* variables for the photoresistor code */


int
photoStd;// standard level for the photoresistor input
int photoPin = 0;// photoresistor pin (A0)
int
photoAvg;// average level for photoresistor input
int photoDiff;// difference in readings for photoresistor input
/* variables for timed round */
unsigned long
startTime;// start time of round in millis
unsigned long length = 60 * 1000;// length of round in millis (1000ms / s)
unsigned long
endTime;// end time of round in millis
int
score;// points scored during round
int splitScore[3];// the score split into 3 digits
int
roundTime;// current elapsed time for the round
boolean inRound =false; // true during timed round

/********************************************************
* Setup and Main Loop Section
*
********************************************************/

/* Initial Setup */
void setup()
{
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(maxaddress);
Wire.write(0x04); // shutdown
Wire.write(0x01); // normal
Wire.endTransmission();
Wire.beginTransmission(maxaddress);
Wire.write(0x01); // decode
Wire.write(0x07); // Digit 1 & 2 & 3
Wire.write(0x2F); // intensity to max (autoincrements to adress 0x02)
Wire.endTransmission();
LEDOn(blank);
Wire.beginTransmission(maxaddress);
Wire.write(0x20); // Digit 1 address
Wire.write(blank); // Digit 1 value
Wire.write(blank); // Digit 2 value
Wire.write(blank); // Digit 3 value
Wire.endTransmission();

t1servo.attach(9); // target 1 servo on pin 9


t1servo.write(45); // mover target 1 servo to home position
resetTarget();// reset the target before we take readings
pinMode(resetbtnpin, INPUT);
initPhotoRes();
}

/* The main loop */


void loop()
{
if(debounceBtn() && !inRound) {
startTimedRnd();
}// end if
if(inRound) {
checkTimedScore();
testEndRnd();
}// end if
} // end loop

/********************************************************
* Timed Round Related Section
*
********************************************************/

/* Checks and updates score during timed round */


void checkTimedScore() {
if(testPhotoRes() == 1) {
resetTarget();
score = score + 5;
showScore();
}// end if
} // end checkTimedScore()

/* Starts a timed round */


void startTimedRnd() {
score = 0;
dispRSG();
startTime =millis();

endTime = 60000 + startTime;


inRound =true;
} // end startTimedRnd

/* Tests if end of round yet, acts appropriately if true */


void testEndRnd() {
static boolean LEDBlink =false; // state of yellow LED
static unsigned long nextBlink;// when next blink is
static boolean inBlink =false; // are we in a blinking state
if(millis() > endTime) {
inRound =false;
LEDOn(LEDR);
Serial.print("Final Score = ");
Serial.println(score);
showScore();
inBlink =false;
}// end if
else {
if(millis() > endTime - 10000L) {
if(!inBlink) {
/* First time through this round, set it all up */
inBlink =true;
nextBlink =millis() + 250L;
LEDBlink =true;
LEDOn(LEDG | LEDY);
}// end if
if(millis() >= nextBlink) {
if(LEDBlink) {
LEDOn(LEDG);
}// end if
else {
LEDOn(LEDG | LEDY);
}// end else
LEDBlink = !LEDBlink;
nextBlink =millis() + 250L;
}// end if
}// end if
}// end else
} // end testEndRnd

/* Splits the timed round score into 3 digits for display */


void scoreSplit() {
int tscore = score;
splitScore[0] = tscore / 100;

tscore = tscore-splitScore[0]*100;
splitScore[1] = tscore / 10;
splitScore[2] = tscore - (splitScore[1] * 10);
} // end scoreSplit

/********************************************************
* Button Related Section
*
********************************************************/

/* Debounces the button


* This will need to be updated for multiple buttons later
* returns true if button went from LOW to HIGH, false otherwise
*/
boolean debounceBtn(void) {
int reading =digitalRead(resetbtnpin);
boolean retval =false;
if(reading != lastResetState) {
lastDebounceTime =millis();
}// end if
if((millis() - lastDebounceTime) > debounceDelay) {
resetState = reading;
}// end if
if(lastResetState == LOW && resetState ==HIGH) {
retval =true;
}// end if
lastResetState = reading;
return retval;
} // end debounceBtn

/********************************************************
* MAX IC Related Section
*
********************************************************/

/* Displays the score on the 7 segment displays */


void showScore() {
scoreSplit();
setDecode(true);
Wire.beginTransmission(maxaddress);
Wire.write(0x20); // Digit 1 address

Wire.write(splitScore[0]);
Wire.write(splitScore[1]);
Wire.write(splitScore[2]);
Wire.endTransmission();
} // end showScore

/* Sets the decode state of the MAX IC to on/off


* decState : true = on , false = off
*/
void setDecode(boolean decState) {
Wire.beginTransmission(maxaddress);
Wire.write(0x01); // decode address
if(decState) {
Wire.write(0x07); // decode on for digits 1,2,3
}// end if
else {
Wire.write(0x00); // decode off for all digits
}// end else
Wire.endTransmission();
} // end setDecode(bool)

/* Display Ready, Set, Go on 7-Segment displays


* TODO: rewrite this so it works without the delays
*/
void dispRSG(void)
{
byte txt[] = {tR,tD,tY};
LEDOn(LEDR);// Red On
dispWord(txt);// RDY
resetTarget();// Pop up the target if it's down
LEDOn(LEDY);// Yellow On
txt[0] = tS;
txt[1] = tE;
txt[2] = tT;
dispWord(txt);// SET
initPhotoRes();// initialize photoresistor
txt[0] = tG;
txt[1] = tO;
txt[2] = blank;
dispWord(txt);// GO
LEDOn(LEDG);// Green On
delay(100L); // wait 1/10 of a sec
showScore();
} // end dispRSG

/* Display a message (Word) on the 7-Segment displays


* txt[] must be 3 elements long, this will fault otherwise
*/
void dispWord(byte txt[])
{
setDecode(false);
Wire.beginTransmission(maxaddress);
Wire.write(0x20); // Digit 1 address
Wire.write(txt[0]);
Wire.write(txt[1]);
Wire.write(txt[2]);
Wire.endTransmission();
} // end dispWord

/* Turn on an LED Controlled by the MAX


* clr = 0 for nothing, 1 = Red, 2 = Yellow, 3 = Green
*/
void LEDOn(byte clr)
{
Wire.beginTransmission(maxaddress);
Wire.write(0x24); // segments address
Wire.write(clr); // LEDS to turn on
Wire.endTransmission();
} // end LEDOn

/********************************************************
* Servo Related Section
*
********************************************************/

/* Move a servo through it's reset action


* 1 servo object is needed to do this action
* st = start position
* se = end position
*/
void moveservo(int st,int se,Servo svo) {
// moves the servo slowly to next position
int pos = st;
if(st > se) {
/* move servo back to home position */
for(pos = st; pos > se; pos-=5) {
svo.write(pos);

delay(15);
}// end for
}// end if
else {
/* move target back up */
for(pos = st; pos < se; pos+=4) {
svo.write(pos);
delay(14);
}// end for
}// end else
} // end moveservo

/* Cycle the servo to reset the target */


void resetTarget(void) {
// resets the target
moveservo(45,155, t1servo);
delay(100);
moveservo(155, 45, t1servo);
} // end resetTarget

/********************************************************
* Photo Resistor Related Section
*
********************************************************/

/* Initializes the array for the photoresistor


* reads the pin 10 times over 1 second
* gets min and max values
* determines what level should be for light change
*/
void initPhotoRes(void) {
int samples[10];
int c = 0;
int min = 1023;
int max = 0;
int photoTot = 0;
for(c=0; c<10; c++) {
samples[c] =analogRead(photoPin);
if(samples[c] < min) { min = samples[c]; }
if(samples[c] > max) { max = samples[c]; }
photoTot = photoTot + samples[c];
delay(250L); // wait a little for the next sample
if(c%2 == 0) { LEDOn(LEDY); }// blink the led while sampling
else { LEDOn(blank); }

}// end for


photoAvg = photoTot / 10;
photoStd = photoAvg;
photoDiff =max -min;
/* for debugging */
Serial.print("Min = ");
Serial.print(min);
Serial.print(" Max = ");
Serial.print(max);
Serial.print(" Avg = ");
Serial.println(photoAvg);
} // end initPhotoRes

/* Tests the photosensor for a level change


* retval = 0 if no sizable change, 1 if negative change, 2 if positive change
* negative = less light, positive = more light
* TODO: This section needs work...
*/
int testPhotoRes(void) {
int reading =analogRead(photoPin);
int retval = 0;
if(reading < (photoStd - 100L)) { retval = 1; }
if(reading > (photoStd + (photoDiff*2L))) { retval = 2; }
return retval;
} // end testPhotoRes

Vous aimerez peut-être aussi