Last active
December 16, 2015 00:59
-
-
Save admalledd/5351998 to your computer and use it in GitHub Desktop.
"Monkey Timer" project. Times speed of a projectile and at the same time triggers a relay to drop a stuffed animal monkey.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
V0.1 initial github upload. working timer, shift register display (4 digit 7 segment). | |
V0.2 working code, needs better docs/comments | |
v0.3 changed display, tested with real monkey system and v1.0 of embeded hardware (no longer on breadboard) | |
out a-f of shift register is to segment a-f of 7segment. | |
four pins on arduino are the digit select pins | |
pin 2 is start timer IR barrier interrupt | |
pin 3 is stop timer IR barrier interrupt | |
Uses the TimerOne library to handle updating the display as often as possible-ish | |
shift register pin out and general helpfull info: http://bildr.org/2011/02/74hc595/ | |
4 digit 7 segment display used: https://www.sparkfun.com/products/9483 (has data sheet) | |
//arduino pins | |
0 : no connect (left for serial to computer for detailed info) | |
1 : no connect (left for serial to computer for detailed info) | |
2 : start_timer interrupt pin | |
3 : stop_timer interrupt pin | |
4 : digit 0 on LCD (thousands) | |
5 : digit 1 on LCD (hundreds) | |
6 : digit 2 on LCD (tens) | |
7 : digit 3 on LCD (ones) | |
-- | |
8 : dataPin to shift register (pin 14 "SER" of 74HC595) | |
9 : latchPin to shift register(pin 12 "RCLK" of 74HC595) | |
10: clockPin to shift register(pin 11 "SRCLK" of 74HC595) | |
11: relayPin to transister to boost power to control relay | |
13: LED built into arduino, used to signal timer status (timing/not timing) | |
//shift register pins | |
1 : segment B | |
2 : segment C | |
3 : segment D | |
4 : segment E | |
5 : segment F | |
6 : segment G | |
7 : | |
8 : GND | |
9 : | |
10: VCC | |
11: to arduino pin 10, "SRCLK" | |
12: to arduino pin 9, "RCLK" | |
13: GND | |
14: to ardiono pin 8, "SER" | |
15: segment A | |
16: VCC | |
//LCD pins | |
1 : digit 0, arduino pin 4 | |
2 : digit 1, arduino pin 5 | |
3 : segment D | |
4 : | |
5 : segment E | |
6 : digit 2, arduino pin 6 | |
7 : | |
8 : digit 3, arduino pin 7 | |
9 : | |
10: | |
11: segment F | |
12: | |
13: segment C | |
14: segment A | |
15: segment G | |
16: segment D | |
//note each segment has a 330 ohm resistor (orange orange brown) between it and the shift register | |
A | |
F B | |
G | |
E C | |
D | |
//interrupt curcuit stuff | |
10kohm (brown black orange) pull up, http://www.reconnsworld.com/ir_ultrasonic_basicirdetectemit.html | |
*/ | |
#include <TimerOne.h> | |
const int ledPin = 13;// LED connected to digital pin 13 | |
const int dataPin = 8;//Pin connected to DS of 74HC595 (pin 14 "SER") | |
const int latchPin = 9;//Pin connected to ST_CP of 74HC595 (pin 12 "RCLK") | |
const int clockPin = 10;//Pin connected to SH_CP of 74HC595 (pin 11 "SRCLK") | |
const int relayPin = 11; | |
const int potPin = A0; | |
const int digitPins[4] = { | |
4,5,6,7}; //pins to control the 4 common anode pins of the display | |
const byte digit[13] = //seven segment digit bits | |
{ | |
//each bit relates to one part of the 7 segment: P is unused, the others are the name of the segment | |
//note that these are inverted due to what type of display and shift register you use. | |
//if you have wired it the same as me, out A is segment A, B is B and so on. with H unused (is P technically?) | |
// PGFEDCBA | |
B11000000, //0 | |
B11111001, //1 | |
B10100100, //2 | |
B10110000, //3 | |
B10011001, //4 | |
B10010010, //5 | |
B10000010, //6 | |
B11111000, //7 | |
B10000000, //8 | |
B10010000, //9 | |
B11110111, //_ (used for we are timing output) | |
B10111111, //- (used for scrolling) | |
B11111110 | |
}; | |
int digitBuffer[4] = { | |
11,11,11,11}; //buffer to hold current output to display | |
int digitScrollBuffer[13]={ | |
11,11,11,11, | |
12,12,12,12, | |
12,12,12,12, | |
12}; //current whole line of stuff to display. | |
volatile int currentDigit = 0; | |
int currentScrollDigit = 0; | |
int decimalPointDigit = 4; | |
unsigned long cur_time = 0; | |
volatile unsigned long start_time = 0; | |
volatile unsigned long elapsed_time = 1;//because we want to simulate as if we just did a shot so there is no fancy start up logics | |
unsigned long relayTime = 0; //time in millis() that we need to stop the relay (so as not to use a delay() | |
unsigned long scrollTime = 0; //time in millis() that we need to scroll to the next digit at | |
void setup() { | |
Serial.begin(9600); //serial debug and/or more acurrate mesurement of timings | |
pinMode(ledPin, OUTPUT); | |
for(int i=0;i<4;i++) | |
{ | |
pinMode(digitPins[i],OUTPUT); | |
} | |
pinMode(latchPin, OUTPUT); | |
pinMode(clockPin, OUTPUT); | |
pinMode(dataPin, OUTPUT); | |
pinMode(relayPin, OUTPUT); | |
Timer1.initialize(2500); //how often to draw the display in mincroseconds | |
Timer1.attachInterrupt(drawDisplay); | |
pinMode(2,INPUT); | |
pinMode(3,INPUT); | |
attachInterrupt(0, start_timer, RISING); | |
attachInterrupt(1, stop_timer, RISING); | |
} | |
void drawDisplay() | |
{ | |
//write select digits to the display. draws one digigt at a time, but leaves it on until the next draw. | |
//this leaves no forced digit delay in the draw interrupts. | |
writeDigit(currentDigit); | |
currentDigit++; | |
if (currentDigit>3) currentDigit=0; | |
} | |
void writeDigit(int digitScan) | |
{ | |
for(byte i=0;i<4;i++) | |
{ | |
//turn off all digits | |
digitalWrite(digitPins[i], LOW); | |
} | |
digitalWrite(latchPin, LOW); //start shifting | |
//digit[digitBuffer[digitScan]] is "get the current drawing digits number from the buffer, then get the | |
// seven segment decoding of that digit, shift that out to the shiftreg setting all those pins. | |
int tempDigit = digit[digitBuffer[digitScan]]; | |
if (decimalPointDigit == digitScan) bitWrite(tempDigit,7,0); | |
shiftOut(dataPin, clockPin, MSBFIRST, tempDigit); | |
digitalWrite(latchPin, HIGH);//stop shifting | |
digitalWrite(digitPins[digitScan], HIGH);//turn this digit on until the next writeDigit() | |
} | |
void scroll() | |
{ | |
//scroll the display one digit to the left in the buffer | |
int fakedigit = 0; | |
decimalPointDigit = 4; | |
for (int i = 0; i < 4;i++){ | |
fakedigit = currentScrollDigit+i; | |
if (fakedigit>12){ | |
fakedigit = fakedigit - 13; //loop to begining | |
} | |
digitBuffer[i] = digitScrollBuffer[fakedigit]; | |
if (fakedigit == 6) { | |
decimalPointDigit = i; | |
} | |
} | |
currentScrollDigit++; | |
if (currentScrollDigit > 13){ | |
currentScrollDigit = 0; | |
} | |
} | |
void printBuffer(){ | |
return; | |
for (int i=0; i<13;i++){ | |
Serial.print(digitScrollBuffer[i]); | |
Serial.print(","); | |
} | |
Serial.println(); | |
} | |
void loop() | |
{ | |
if (cur_time != elapsed_time){ | |
//if these dont match, we just got a interrupt | |
if (elapsed_time == 0){ | |
//if time is 0, we just started the timer | |
Serial.println("Timer Start!"); | |
for (int i =0; i<13;i++){ | |
digitScrollBuffer[i] = 10; | |
} | |
digitalWrite(relayPin, HIGH); | |
relayTime = millis()+1000; | |
} | |
else{ | |
for (int i =0; i<13;i++){ | |
digitScrollBuffer[i] = 11;//reset | |
} | |
currentScrollDigit = 0; | |
Serial.println("Timer Stop!"); | |
Serial.println(elapsed_time); | |
// to explain, first is that time is in microseconds, we need miliseconds, so all divides have an extra 1000 on them | |
// next is see http://stackoverflow.com/a/7435631 for the maths. | |
digitScrollBuffer[4] = (elapsed_time/100000000)%10; | |
digitScrollBuffer[5] = (elapsed_time/10000000)%10; | |
digitScrollBuffer[6] = (elapsed_time/1000000)%10; | |
digitScrollBuffer[7] = (elapsed_time/100000)%10; | |
digitScrollBuffer[8] = (elapsed_time/10000)%10; | |
digitScrollBuffer[9] = (elapsed_time/1000)%10; | |
digitScrollBuffer[10] = (elapsed_time/100)%10; | |
digitScrollBuffer[11] = (elapsed_time/10)%10; | |
digitScrollBuffer[12] = elapsed_time%10; | |
printBuffer(); | |
} | |
cur_time = elapsed_time; //set so we can tell when the timer changes | |
} | |
//stop monkey logics | |
if (relayTime <= millis()){ | |
digitalWrite(relayPin, LOW); | |
} | |
if (scrollTime <= millis()){ | |
scroll(); | |
scrollTime = millis() + 750; | |
} | |
} | |
void start_timer(){ | |
//note that this runs every time there is a rising edge, so that means timing is betweeen | |
//the LAST edge of the start pin and the first edge of the stop pin. | |
if (elapsed_time !=0){ | |
start_time = micros(); | |
elapsed_time = 0; | |
Serial.println("U"); | |
digitalWrite(13,HIGH); | |
} | |
} | |
void stop_timer(){ | |
//care that micros() does not overflow and wrap around after 70 minutes, ignored for now. | |
//supposedly doing it this way makes it work just fine ish? needs testing for that, but reset every hour | |
//and you will be just fine. I think... | |
if (start_time != 0){ | |
elapsed_time = micros() - start_time; | |
start_time=0; | |
Serial.println("I"); | |
digitalWrite(13,LOW); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment