Skip to content

Instantly share code, notes, and snippets.

@admalledd
Last active December 16, 2015 00:59
Show Gist options
  • Save admalledd/5351998 to your computer and use it in GitHub Desktop.
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.
/*
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