Web 3.0

Internet-Controlled Gun - Description

This project is still in progress


The goal of this project is to create a coil gun (a gun which uses a a wrapped coil around a tube to propel a projectile with magnetism when an electric current flows through the coil) and control it through the internet via a web interface. The gun is to be mounted on a platform with two motors, allowing it to rotate left-to-right and up-and-down. The orientation of the platform will be controllable through the web interface, as well as firing the gun. In addition, a camera will be mounted on the platform to allow the user to switch the gun to auto-target mode, where the platform will track an object of a specified color and shoot it.

This project uses several technologies:

  • Arduino Uno

    For the microntroller to control the motorized platform and to tell the gun to fire.

  • Wires and Circuits and stuff

    To create the actual coil gun.

  • HTTP WebSocket Server

    To control the gun over the web, real-time communication is required between the server and the client. I will implement the WebSocket server protocol from scratch in C++ as an addition to my original HTTP Web Server I wrote in 2013 (which this website is running on).

  • OpenCV

    For now, I am going to use OpenCV for the target tracking. Once I get a prototype working, I am considering writing my own tracking system to learn how these algorithms work.

  • Serial Port Communication

    The HTTP server listening for WebSocket messages needs to be able to write out the commands received from the web browser to the USB (emulated serial) port to be sent to the Arduino to execute these commands

Gun Control Page

Development Progress

Current Development

As I complete steps of this project, I will describe them here.

Internet-Controlled Stepper Motor

I have created a working prototype of the motor controller. This prototype allows the first stepper motor to be controlled from the web browser. The motor is hooked up to the Arduino, which is connected to the computer running the HTTP WebSocket server and website. The user can connect to the control web page for the gun and press a button to make the motor turn.

The platform supporting the Coil Gun will be mounted on top of this motor. In the following video showing the test, it just shows a web camera attached to the top of the motor.

Cube Picture

This image shows the circuit for the stepper motor.

Short video showing the stepper motor being controlled by the Internet via my website.

Internet-Controlled Transistor / Relay Switch

Now that I have finished writing my HTTP WebSocket server, I have finished the next step required for this project -- activating a transistor with the Arduino over the internet, which allows voltage from a battery to turn on the relay, which then allows voltage from another battery to power an LED connected to the relay.

This circuit will be used to tell the gun to fire -- instead of an LED connected to the relay, it will be the gun. A short demo of this circuit being controlled through the Web Browser can be seen below.

Short video showing the circuit turning on and off from the internet.

WebSocket Server Protocol C++ Implementation

The next step I completed for this project is to implement the WebSocket protocol in the C++ webserver I wrote (the same server this website runs on). The WebSocket protocol is special because it allows for asynchronous messages to be passed from the Web Browser to the Server (and the other way around) at arbitrary times. These messages avoid using HTTP headers -- they are tunneled through as if the Browser and the Server have a direct connection. The TCP socket connection functions similarly to how any other real-time network application would work -- such as a chat program or a multiplayer video game.

The most important parts of the WebSocket protocol are the initial connection handshake, and decoding subsequent messages based on their WebSocket header. When the Browser wishes to initiate a direct WebSocket connection with the Server, it sends an HTTP Get request with the "connection: Upgrade" header. This tells the Server that the Browser wishes to switch to a direct WebSocket connection. Also included in this header is a base64 key string generated by the browser.

When the Server receives this HTTP header from the browser, it must send back a handshake message. Most importantly, this handshake message contains an SHA1 hash (in base64) of the client's key string (from the header) appended with a special WebSocket string specified by the WebSocket protocol (this string is the same for all servers -- I firmly believe that whoever came up with the WebSocket protocol is a dumbass). The purpose of appending this constant string is so that the server can assert that it completely understands that the connection is going to be a WebSocket connection. I don't see the purpose of this, as the server would not send the correct header back anyway if it wasn't intending on starting a WebSocket connection.

Once this handshake is complete, the Server and Browser can now send messages back and forth to each other without associating themselves with HTTP.

Messages sent from the Browser to the Server have a special format. The header for long messages is more complex than short messages -- for the application of sending small commands to the server for the Arduino, I have ignored the possibility of the server receiving long messages.

The first byte signifies the message type (value 129 means 'text'). The second byte (for short messages) contains the message length. Messages whose length requires more than one byte to describe have a more complex header. The third, fourth, fifth, and sixth bytes contain an integer mask generated by the Browser. This mask is different for every message. This mask is another stupid thing about WebSockets. All WebSocket messages sent from the browser are encoded using this mask. The server must use the supplied mask to decode every message in order to read the actual data sent (the header is not encoded). This is intended to prevent message snooping, but is stupid because anyone trying to intercept the data can intercept the mask anyway and still use it to decode the sent data.

I have completed the implementation of all parts of the WebSocket protocol relevent to this project. The following image shows the output of my server console when receiving a WebSocket connection request, and then the subsequent output when receiving and decoding WebSocket messages from the connected Browser.

Cube Picture

This image shows my server's console output when handshaking and decoding websocket connections.

The WebSocket messages shown in the above picture instruct the server to write strings to the USB (emulated serial) port to be sent to the Arduino board. The first command sent to the server signals it to initialize the serial connection between the desktop my server runs on, and the Arduino board connected to it. The subsequent messages are "on" and "off" messages to be sent from the server desktop to the Arduino to tell it to supply or remove power from the IO pin connected to an LED (to turn the LED on and off). The Arduino board is running a simple program I wrote to listen for this messages. These messages are sent when the Javascript buttons are clicked (clicking the buttons runs a Javascript function generating a WebSocket message to be sent to the server).

The following image shows the LED light being on as a result of pressing the button in the Web Browser.

Cube Picture

All of this to turn on a single LED.

USB (emulated serial) Port - Arduino Communication Test

The first step I have completed for this project is to write a simple C++ program to write data from my desktop computer to the Arduino board. The Arduino IDE has a built-in application to send data to the board from the computer, but for this project, the data must be sent from within my own application.

The Arduino board connects to the PC using a USB port, but it functions as a serial port. This makes writing data to it extremely simple. In Windows, serial ports are accessed as if a COM port is just another file -- writing to the port is identical to writing to a file.

My simple test program sent ASCII strings to the COM port which are entered into the console on the PC. On the Arduino side, I wrote a simple program to listen for the string "on" and "off" coming in through the USB port. Upon receiving the string "on", it turns an LED on that I plugged into a breadboard and one of the Arduino IO pins.