Saturday, June 29, 2013

So I just realized I can add post titles

Wow, I didn't know that.

Anyways, today I went on searching for flex resistors. I can usually find a really nice deal on ebay, but this time I'm out of luck.
Sparkfun offers them for around $8, and other sites have the same price... more or less. Some sites sell them for $12.

Here is the thing: I need two of them.

As I have explained before, I am using them in a voltage divider to an analog pin on the Attiny.

If each sensor costs around $10, The price of this device might be a bit too high for High School coaches... maybe around $50.
Maybe I can make my own
There IS another option.

There are these piezo vibration sensors that are significantly cheaper, around $3. I have a few readily available. 
They are extremely sensitive to vibrations, and they generate voltage higher than what a microcontroller can read (up to 1023, after that, it's still 1023)

I am avoiding using these sensors, however there is a way to make them less sensitive...
On forums (and in experiment) I found that adding a bunch of resistors to the piezo sensor will not lower the voltage that much, however, maybe a capacitor might do the trick. I remember reading somewhere that adding a capacitor might stabilize the output.

I will try that.

Because these sensors are so sensitive, I might be able to just slap them flat onto the backboard and rim, instead of having them dangle from the side with a weight (see the setup illustrated in prior blog post)

I will keep you all updated.

*EDIT*

AHA!
So a problem was that the shot clock kept resetting to 24 after it went to 0.
This only occurs when you use the pause button, but if you do not use it, this glitch does not happen.
How I solved it?

It was a silly mistake on my part: I have no idea why I added it.

/***************countdown and analog reading****************/
void thedeal() {
  while (sec >= 0){
    countdown(sec);
    sec = sec - 1;
    
    for (int i = 0; i<575; i++){ //change this ~ seconds
      reading();
      compare();
      delay(1);
    }
  }
//sec = 24;  //mistake here!!//
}

No idea... What was I thinking.

Well, that is fixed. From here on, the problems I need to fix are pretty easy to fix! (this one was surprisingly easy to fix...)






Please ask questions in the comments.

This is the shot clock that will change the game.

Friday, June 28, 2013

How it works

Shot clock (2)

How it works, the process, tech stuff!

So here is a picture!

This is how it is supposed to be set up.


The wires look like a mess, but it really isn't so. The manual controls can be connected via radio control, or a cat5 ethernet cable. 
The seven segment display, buzzer, and LEDS are placeholders for maybe transistors and relays that can activate larger displays, like whole light bulbs, horns, and displays.
Again, this is still a prototype.

Being a prototype, there are problems... I am still solving them.
  • timing is not totally precise, but after 24 seconds the delay is not noticeable, and certainly negligible.
  • doesn't stop at "0" (this is a big problem)
  • laser overheats (get a new laser, simple)
  • drains battery (might need to change batteries after a single game, because you need to power a lot of components)
  • I need a flex resistor (order soon)


List of materials:
  • 2x 74hc595
  • 2x Kingbright 7 segment display
  • 1x attiny44
  • 2x led
  • 4x 9.1k resistor
  • 2x 47k resistor
  • 2x 0.1 uf capacitor (104)
  • 1x 470 resistor
  • 2x transistor
  • 1x 5k trimpot
  • 2x 1k resistor
  • 1x laser
  • 1x phototransistor
  • 2x flex resistor (and maybe weights at the end of them)
  • 3x N.O. buttons
  • 1x piezo buzzer

Here is a video of it!



Schematic:
Here is the link to the PDF
Image:


How it works:

Net shot sensor

  1. A laser shoots it's beam at a phototransistor.
  2. The phototransistor outputs a digital HIGH
  3. That signal goes through an inverter gate (I used a transistor and a few resistors)
  4. That signal goes to the microcontroller
    • If the signal is HIGH, the ball has passed through the net.
    • If the signal is LOW, no ball has passed through the net.
  5. Depending on if the ball passed the net or not, the buzzer will buzz and the timer will restart.

Rim sensor

First of all, I am generating voltage from the two flex sensors.
In flex sensors, the more you flex it, the more resistance it creates.
I have decided to use the flex sensors in a voltage divider. If you look at the schematic, you will notice that R1 (resistor to Vcc) is 47k, while R2 (resistor to ground) is the flex sensor.
    • The more the flex sensor flexes, the more resistance there is on R2, and more power can flow through R1. The more the flex sensor flexes, more voltage is let pass.
Let's look at an example:
  1. The ball hits the backboard
  2. The backboard vibrates more than the rim
  3. More voltage is passed from the backboard than the rim
  4. The microcontroller compares the voltages.
    • If backboard >= rim, do nothing
  1. The ball hits the rim
  2. The rim vibrates more than the backboard
  3. More voltage is passed from the rim than the backboard
  4. The microcontroller compares the voltages.
    • If rim > backboard, buzz and restart the shot clock

Manual controls

The manual controls are connected to the same I/O pins as the sensors. In the end, the I/O pin is only sensing whether that pin is HIGH or LOW.



That's all I have for now.
What needs to be done:
  • Flex sensor
  • test on an actual (indoor) basketball hoop
  • make a PCB to get rid of all the clumsy wires

Here is the code

I used an attiny44 @ 8mhz internal, USBtinyISP as the programmer.

//Made  by TS Wang
//6/1/2013
//Documentation on this project can be found on http://tswangshotclock.blogspot.com/
/*
This project is meant to further improve Spalding's (r) shot clock.

The problems with that shot clock:
-picks up backboard vibration
-does not pick up net shots

Improvements by this shot clock:
-ignores backboard vibration
-picks up on net shots
-allows manual control from the bench
  -manual stop-where-its-at
  -manual stop-and-restart
  -manual stop (reset)
  -manual stop-and-jump-to-zero (if that is useful at all)

This project can be replicated. Replicate all you want.*/

//Attiny44 @ internal rc 8mhz

int latchone = 10;  //ST_CP or 12      Last
int clockone = 9; //SH_CP or 11      Second
int dataone = 2; //DS or 14           FIRST

int latchtwo = 3;
int clocktwo = 4;
int datatwo = 5;

int beeper = 6;

int sensor = 7;
int good = 500;

int readstop = 8;

int sec;

byte digitone[11]= {0x00 ,0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, 0x7E};

void setup() {
  pinMode(latchone, OUTPUT); pinMode(clockone, OUTPUT); pinMode(dataone, OUTPUT);
  pinMode(latchtwo, OUTPUT); pinMode(clocktwo, OUTPUT); pinMode(datatwo, OUTPUT);
  pinMode(beeper, OUTPUT);
  pinMode(sensor, INPUT); pinMode(readstop, INPUT);
}

void loop() {reading();}



/*************analog reading***********/
void reading() {
  if(digitalRead(readstop) == HIGH) {
    spaztwo();
  }
  if(analogRead(sensor) >= good) {
    spaz();
  }
  else{} 
}
/***************countdown and analog reading****************/
void thedeal() {
  while (sec >= 0){
    countdown(sec);
    sec = sec - 1;
    
    for (int i = 0; i<600; i++){ //change this ~ seconds
      reading();
      compare();
      delay(1);
    }
  }
  sec = 24;
}
/****************blink and restart*************/
void spaz() {
  sec = 24;
  countdown(sec);
  digitalWrite(beeper, HIGH);
  delay(250);
  digitalWrite(beeper, LOW);
  delay(250);
  digitalWrite(beeper, HIGH);
  delay(250);
  digitalWrite(beeper, LOW);
  delay(250);
  sec = 23;
  thedeal();
}

/****************blink and stop***************/
void spaztwo() {
  if (analogRead(sensor) >= good) { 
    digitalWrite(beeper, HIGH);
    delay(250);
    digitalWrite(beeper, LOW);
    delay(250);
    digitalWrite(beeper, HIGH);
    delay(250);
    digitalWrite(beeper, LOW);
    delay(250);
    thedeal();
  }
  else{spaztwo();}
}



/**************comparing backboard to rim vibration**************/

void compare () {
  int backboard = analogRead(0);
  int rim = analogRead(1);
  if (rim > backboard) {
    spaz();
  }
  else {}

}








/*countdown code*/
void countdown(int NTD) {
  switch (NTD) {
    case 24:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[2]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[4]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
      
    case 23:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[2]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[3]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;

    case 22:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[2]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[2]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;

    case 21:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[2]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[1]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
      
    case 20:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[2]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[10]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
      
    case 19:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[9]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
      
    case 18:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[8]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
      
    case 17:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[7]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 16:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[6]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 15:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[5]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 14:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[4]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 13:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[3]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 12:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[2]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 11:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[1]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 10:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[1]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[10]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 9:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[9]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 8:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[8]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 7:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[7]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 6:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[6]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 5:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[5]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 4:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[4]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 3:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[3]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 2:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[2]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 1:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[1]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
    case 0:
      digitalWrite(latchone, LOW);
      digitalWrite(latchtwo, LOW);
      shiftOut (dataone, clockone, LSBFIRST, digitone[10]);
      shiftOut (datatwo, clocktwo, LSBFIRST, digitone[10]);
      digitalWrite(latchone, HIGH);
      digitalWrite(latchtwo, HIGH);
      break;
  }
}

All documents can be found on my Google Drive:
https://drive.google.com/folderview?id=0B5gFDZ2efTDSX0hPdG5sWWJuemc&usp=sharing
Files will be added.

Please ask questions in the comments.

This is the shot clock that will change the game.

Shot Clock (1)

This Blog will be a chain of updates to TS Wang's Shot Clock design.

Have you all seen this automatic resetting shot clock yet? Not many people like it, and it's not worth the price.
Problems with it:
  • Picks up backboard vibrations
  • Does not sense net-shots
  • Manual controls are difficult to access.
Well, I am designing a new automatic shot clock that will fix these issues.
This new shot clock will:
  • sense net-shots (with a laser-phototransistor setup)
  • ignore backboard vibrations (by comparing voltages generated by rim vibrations versus backboard vibrations)
  • have manual controls to...
    • Reset the shot clock to 24 and count down again
    • Pause the shot clock at it's current number and wait for a signal to continue
    • Reset the shot clock (sleep mode)
    • Jump to "0" on the shot clock and stop (this was a glitch, but it might be helpful)
  • count down from 24 and stop at "0" (shot clock violation)*
What are the benefits of having an automatic resetting shot clock?
  • no more human mistakes that might lead to inaccurate and imprecise timing
  • fairness in the game of basketball
  • Does anyone remember this incident?
Basketball fans, wait no longer.
This is the shot clock that will change the game.
Well Hello!

This is my first time ever blogging.
This is a test blog.

Goodbye!