Quick clarification, this is about the sport fencing, not putting stakes and posts in the ground! Laughing
Want the source code? Check out the
GitHub Repository.


For those of you that don't know, fencing is a sport where you get to stab people while avoiding them stabbing you with swords such as foils or epees. Typically during practice there's a simple honesty system where if you get stabbed, you admit it and go to a new round. However, if both fencers get stabbed at the same time, it can be difficult to tell who stabbed first. Since the sword have a button on the end and are wired to a connection point on the bell, you can connect something called a buzzer box which can tell down to the millisecond who stabbed who first. Here's what it looks like:

Two of the connectors on the bell are for the button leads. The third contact point is for ground (detecting if your opponent hit your bell rather than you), you can ignore it for the purpose of this project.

Unfortunately, buzzer boxes are very expensive ($30-50 for one box!) and my team can't afford to buy a dozen of them. That's why I decided to try and make my own. My school has 3D printers that are free to use and most typical circuit components are pretty cheap so I think I'll be able to make one for a lot less.

Current todo list: (Finished | In-progress | Not Started | Not Feasible | Wont Do)
Hardware:
    Create an adapter that connects the blade connectors to a headphone jack which can be plugged into a phone:
    - Make phone detect headphones are plugged in
    - Add pass through port on adapter for audio to go to actual headphones
    - Make case for adapter
    Document components in the adapter
    Upload adapter schematics to Github
Software:
    Create app that can detect when blade button is pressed:
    - Get code on Github
    - Make app dark theme
    - Detect when button is pressed
    - Beep when button is pressed
    - Play beep through either the headphone jack or playing through speakers
    - Allow adjustment of beep pitch
    - Add button to toggle between Epee and Foil fencing mode
    - Add screen lock:
    - - Add slider to lock/unlock
    - - Remove all clickable buttons
    - - Prevent phone from sleeping while locked
    - Add Bluetooth communication between devices:
    - - So only the winner's phone beeps in a one-on-one match
    - - So a third device can act as a completely wireless buzz box & score keeper for a one-on-one match
    - Add score keeping
    - Test it
    - Release to Play Store
    Make icon
    Make a better readme

    Make tutorial

Progress & Eye candy:



Old plan:
End goal: Create a circuit where when a button is bumped or held, a buzzer (and an LED if I can work it in) will activate for 2 seconds. Preferably without using an Arduino.

My plan is to have a capacitor constantly being charged (while the box is on), then when the button is pressed, the capacitor discharges completely, activating the buzzer. Once it's discharged, the battery will start charging it again. The catch is, I don't how most circuit components work so this is going to be a learning curve for me. (I do understand batteries, resistors, capacitors, and I mostly understand transistors, but that's just about it!)

I was told on SAX a few days ago that this can be done with a single transistor and Mateo even created a circuit diagram for me (Note: the numbers in the circuit are not accurate). However, that circuit assumes that the button is normally closed which, on epee swords, the button is normally open. (It would be nice to be able to switch from one to the other, but one step at a time)

I'm guess my first question is: how can I keep a transistor on after only a single button press? I know I said I'd use a capacitor, but I have to idea how to wire it up like that.
Can the buzzer/light be left on until someone presses a button to turn it off?
That won't work in this case since multiple people practice at once and it'd be pretty difficult to tell if your buzzer turned off among all the other buzzing. Also our practices go on for quite a while and it'd get quite annoying; kind of like if everyone in the world drove with the horn constantly on until they wanted to use it. Wink
So you want to figure out who got hit first? This seems like a job for an arduino honestly. Sure you could do it using a fancy circuit from discrete components but an arduino would cost 5 dollars and be easier.
Threw this together; you could use a relay to have a constant output as the current decreases so the light output is steady, but this is enough for a proof-of-concept I guess.

My first thought was a 555 in oneshot configuration. Seems very similar to what Mateo's suggesting, but possibly more reliable.
Thanks Mateo, that worked great! Here's a terrible video of a prototype to show it working. The light turns off after about 2 seconds.
While we were working on this we thought, 'hey, why are we wasting money on hardware when we could just use our phones?'. So we managed to get that sort of working! In layman's terms: we got an adapter which converts the prongs on the blade to a headphone jack. Even though we have no experience with coding for Android, we were able to get our phones to vibrate whenever the blade's button was pressed! We're working on getting a sound to play through the phone speakers rather than the headphone jack currently. (well actually we're trying to figure out how to play a tone at all, but that shouldn't take too long).
Hope this helps: https://stackoverflow.com/questions/4861859/implement-sounds-in-an-android-application

I've tried making Nuclear Reactor Sim CE as an Android app for my CSP final project. Docs were basically nonexistent, so I switched to making/ finishing FusionSim CE Razz

Anyways, good luck! And don't get sliced like Fruit ninja fruits Razz
Quick update! Thanks SM84CE, that helped! Using the notification system I was able to get my phone to beep using the speaker even with a headphone jack inserted!
https://www.youtube.com/watch?v=6mSz6SgN1qY
Now I'm working on customizing the sound so you can make it any pitch you want. I've run into a big compatibility issue though. I'm trying to use android.media.AudioTrack to generate the sound and that's working fine however, I can't force the phone to play the sound through the speakers using audioTrack.setPrefferedDevice(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) since that was introduced with Android 6 and I'm running Android 4.4.2. Sad
If anyone knows of an alternative I can use, or can point me in the right direction I would greatly appreciate it!

If you'd like the code, I'm writing it in Java. The audio issue is on line 115

Code:
package com.example.fencingbuzzer;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.concurrent.TimeUnit;


public class MainActivity extends AppCompatActivity {

    boolean soundPlaying=false;


    private final double duration = .15; // seconds
    private final int sampleRate = 8000;
    private final double numSamples = duration * sampleRate;
    private final double sample[] = new double[(int)numSamples];
    private final double freqOfTone = 1440; // hz

    private final byte generatedSnd[] = new byte[2 * (int)numSamples];

    Handler handler = new Handler();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //the only button on the screen sets off the beeping noise.
        //https://youtu.be/dFlPARW5IX8?t=22m12s
        Button beepButton=(Button) findViewById(R.id.beepButton);
        beepButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loopSound();

            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Use a new tread as this can take a while
        final Thread thread = new Thread(new Runnable() {
            public void run() {
                genTone();
                handler.post(new Runnable() {

                    public void run() {
                        playSound();
                    }
                });
            }
        });
        thread.start();
    }

    //makes tone play 15 times
    public void loopSound(){
        for (int i=0;i<15;i++) {
            playSound();
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }

    void genTone(){
        // fill out the array
        for (int i = 0; i < numSamples; ++i) {
            sample[i] = Math.sin(2 * Math.PI * i / (sampleRate/freqOfTone));
        }

        // convert to 16 bit pcm sound array
        // assumes the sample buffer is normalised.
        int idx = 0;
        for (final double dVal : sample) {
            // scale to maximum amplitude
            final short val = (short) ((dVal * 32767));
            // in 16 bit wav PCM, first byte is the low order byte
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);

        }
    }

    void playSound(){
        final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length,
                AudioTrack.MODE_STATIC);
        audioTrack.write(generatedSnd, 0, generatedSnd.length);
        //audioTrack.setPreferredDevice(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) NOT COMPATIBLE WITH ANDROID 4!
        audioTrack.play();

    }

    //checks if button on blade is pressed
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
            //displays button status as closed
            TextView textViewMain = findViewById(R.id.button_state_text);
            textViewMain.setText("Closed");
            //plays beep
            loopSound();
        }
        return super.onKeyDown(keyCode, event);
    }

    //checks if button on blade is depressed
    public boolean    onKeyUp(int keyCode, KeyEvent event) {

        if(keyCode == KeyEvent.KEYCODE_HEADSETHOOK){
            //displays button status as open
            TextView textViewMain = findViewById(R.id.button_state_text);
            textViewMain.setText("Open");
            //plays beep and vibrates phone
            loopSound();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    //makes phone beep notification UNUSED CURRENTLY
    public void playBeep(){

        //https://stackoverflow.com/questions/2618182/how-to-play-ringtone-alarm-sound-in-android
        try{

            //plays beep and vibrates phone
            Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
            Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);

            r.play();
            //vibrateDevice();
            TimeUnit.MILLISECONDS.sleep(300);

            r.stop();

        }catch (Exception e){
            e.printStackTrace();
        }

    }

}
The app is nearly finished! I've made a GitHub repository in case any of you want to marvel at how poorly I understand OOP Razz

I've added a whole lot of stuff!
  • Redesigned UI
  • Thanks to Mateo, the code that forces the tone to play through the speakers works! I've also worked around the limitation I posted about above. I just decided to use the phone's built in notification sound if you're on an OS lower than Android 6.
  • I've added the ability to choose between the notification sound or a tone, along with a slider to adjust that tone's pitch.
  • I added a help button which basically contains the readme.
  • I added a mode toggle for Epee and Foil fencing since in Epee the button is normally open and in Foil the button is normally closed.
  • I added a link to the github page.
  • I added a slider that removes all the clickable buttons on the screen and forces the screen to stay on. This allows someone to stick the phone in a pocket without worrying about accidentally changing a setting!
TL;DR: Here's a video of it working! (The headphone's play/pause button works just like an Epee's button does)

https://www.youtube.com/watch?v=PqQtEQs81XA

What's left to do:
High priority:
    Fix a small bug where it will randomly beep when the screen turns off or rotates.
    Fix a bug where the screen doesn't stay on when it's suppose to
    Make the theme dark for all those OLED screens out there!
    Release to play store?
    Get the adapter diagram on GitHub.
Low priority:
    Implement Bluetooth connection between two phones and only make the winner's phone beep.
I know none of you guys are fencers, but any features you'd like to see implemented?
EDIT: I overhauled the first post with a todo list, eyecandy, and my github link!

I got the adapters all soldered together, and they still work! The app works just fine with them! I've been wondering about one thing though, since fencing requires very low latency to tell who hit first, will Bluetooth likely be too slow for having two phones communicate and figure out who hit who first? During our testing, it takes 15ms just for the phone to detect that the button was pressed. I read that Bluetooth is roughly 3x slower than a wired connection so all things considered I estimate around 50-100ms of latency. For comparison, a competition level wired fencing buzz box has only 1-2ms of latency.

I'm not completely sure if that amount of latency is good enough for just practice. In fact that's a question I wanted to ask on a fencing forum, sadly it appears all of them shut down earlier this year and moved to Reddit where I don't have an account. That means that this plan probably shouldn't happen if I can't get the latency down (especially old phones running Bluetooth 4). Any ideas for how I can overcome this? Do you think Bluetooth 5 would be quick enough to enable support for it? I can disable the feature on older phones and only allow it on newer ones if it comes to it.
Did my first big test of the app the other day, it went pretty well with a few problems:
  1. Clicking the button really quickly sometimes doesn't register on the phone. I'm not really sure how to increase how often the phone checks the impedance (resistance) of the play/pause button. Any help here would be appreciated
  2. For some reason, foil's button, when it's pressed, doesn't just act like a wire, it has some more impedance which causes the phone to trigger other functions such as vol up/down. Since we could only test it on one foil, I can't guarantee that it wasn't just broken, I'll have to test it on more foils later.
  3. Some Android phone's speakers are glitchy and/or aren't very loud (my Galaxy S3's speakers were just barely loud enough to ear in that room) I can kind of fix that by adding an option to force audio to go through a connected Bluetooth speaker. Unfortunately Bluetooth speakers also brings up the issue of latency again. Using a headphone jack splitter could also work however:
  4. Not all headphone jack splitters work with this, you need a special trrs splitter. Since this could get confusing for users I could solder on an audio pass through port on the adapter.
  5. Screen lock gets disabled when you rotate the phone for some reason.
TL;DR here's a video of one of the tests: https://www.youtube.com/watch?v=wU9YW8rGMAI
On to a different topic: Mateo and Kryptonic provided me some tips for how I could account for the latency issues I mentioned in my previous post. They recommended starting a timer on both phones, then using a technique to sync the timers. Hopefully that will work for me, I just need to get another phone to test it out!
If one user sets their system time back by a few seconds, will they always win?
c4ooo wrote:
If one user sets their system time back by a few seconds, will they always win?
If they adjust the time before the timer starts then no, it won't make a difference. If they change the time while the timer is going then I don't have a definitive answer. The way the technique works is it continuously checks the opponents timer and adjusts its own timer accordingly if it's out of sync. Maybe it could fool the system but I'd have to test that!
Unrelated to the above topic. I'd like to put this out there again: if anyone knows how to increase how often the phone checks the impedance (resistance) of the play/pause button I would really appreciate some help!
Great news, I've got the latency issues fixed! I've made a video that compares the old app (left, lower pitch) to the new one (right, higher pitch). Please ignore the last round, that was a glitch I fixed.
Enjoy: https://www.youtube.com/watch?v=EMJ2_42M7cQ

I think I'm nearing a release, I'll just have to clear it and do some final bug tests with my friend.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement