Homemade Portal 2 Gun

After being asked at home “Can you make me a Portal Gun for ComicCon ?” my reply was “What’s a Portal Gun?” and then “What’s ComicCon?”

Well after being shown some online images of the gun, and a very impressive build blog by a professional prop designer called Harrison Krix ( see here ) the challenge was on. From glancing down Harrison’s blog it all seemed straight forward ! How wrong could I be.

ComicCon is tomorrow (after posting this morning I printed my tickets and see I have booked for Sunday’s event) and I will need to wire everything together this evening but nearly there at last. This is some notes and ideas that fellow hobbyist/diy builders may find useful. Here’s my gun so far:

WP_20160526_001.jpg

Our gun was always built as cheaply as possible – main components are 68mm PVC downpipe, 102mm section of PVC pipe (sold for installing extractor fans), 150mm section of PVC pipe (again for extract fans), Oasis florists foam, old aluminium sections from a greenhouse, papermache and other sundries.

Once tomorrow is out of the way I hope to update this blog with lots of detail….but for now I’ll just stick some build photos in there.

The electronics are also homemade – I salvaged the RGB LEDs from my corroded outdoor lighting strips and re-soldered to some homemade PCBs. I made a controller to take care of the selection (Blue or Amber) and utilised the same trigger switch for the main ‘fire’. The circuit uses MOSFETs to sink the high current from the LEDs. Rather than power the unit from 3x AA batteries I have used a smaller USB Lithium-Ion battery pack. As these can deliver high currents I have also incorporated an inline fuse. The update here is that I have discovered the Lithium USB stick decides to power off after about 1 minute – I think the current is too low so it thinks the attached device has fully charged. I tried increasing this to a minimum of 400mA but this still wouldn’t result in power being left connected. Therefore back to plan 1: 3x AAA batteries. Strangely a much larger USB Powerbank I have will keep powering the circuit but this powerbank is too large to fit into the Portal Gun housing.

One of the first stumbling points when following Harrison’s blog was that I didn’t have a lathe but I soon found a really good article online (well presented, clear instructions and a motivated young engineer building it).  See Youtube article on the Art Of Weapons post here

…more to follow

Oasis

This is so vey soft that once you have made something it is almost useless. I glues the blocks together using hot melt glue. I then made full size plans for plan view, side view and end views. I place one view onto my assembled blocks and cut straight down inline with the template. I repeated this for the other two views but these became progressivley more difficult as square was lost. Then I sanded all the ridges away using P80 sandpaper. An issue arose with the glue seams – they needed cutting back with electronic snips as they were too tough to sand.

The finished rear cowel looked great but had absolutely no strength – the slightlest knock or rough handling left marks. This thing needed toughening up. I tried treating a few off cuts; some with acrylic paint, some with PVA glue and some with polyurethane varnish. The latter seemed best so I coated the whole coweling with thinned down varnish. It got really heavy and stank the shed out. The next day it got left in the sun and dried quite well – it was definately harder but not ideal.

Next I decided to paper mache it. This made it much stronger.

Then I covered it with some plasterers glass fibre scrim – the self adhesive stuff. Over this I added a layer of car body repair filler. This was filed and sanded down (don’t forget to use a dusk mask if you are doing this) and repeated several times.

I also tried watered down wood filler that also worked well and went hard. This sanded more easily than the car filler and didn’t smell as bad nor get stuck on my tools.

Electronics

Drawn out using Eagle PCB Design software . In the past I have used Staples and printed to acetate at 50p a sheet but this time they wanted an additional £3 for accessing the files off my CD – seemed a bit steep so I wnt elsewhere. This time I printed onto plain white paper at my local library – thank you Hampshire County Council as your staff were great sorting me out. I dabbed vegetable oil onto the circuit layout and they pressed the paper between sheets of kitchen towel to renmove excess. The oil makes the paper go translucent. I doubled the sheets up, puts them togetehr and exposed asome pre-sensitised copper clad board on my homemade UV box (3minutes 20s per side). I developed this in warm Sodium Hydroxide and etched in my small etch tank (a rectangular glass vase from Ikea with a 50W fish tank heater inside). Etching took about 4 -5 minutes. Front_Board_Layer1_v2

The circuit is controlled by a PIC16F1829 microcontroller by Microchip who make, what I believe, is one of the best supported ranges of microcontrollers. This is easily programmed using the Pickit3 and the free XC8 C compiler.

Cables

These are URM43 type coaxial cable outer sheathing. Inside is some stout galvanised fencing wire and a twisted pair of small signal cable on the end of which is soldered the white LEDs up near the claws. Each has an inline 150 Ohm resistor.

Cast or Turn

I made an armature that fitted snugly in the 68mm PVC drainpipe. I used a combination of glued strips of PVC, MDF and car body filler to make the various sections at the end and to then turn them down to size. Harrison’s site made something similar but then made a negative mould and cast this as one piece – I turned the part instead (as it’s a one-off that doesn’t matter).

Stickers

I forgot to buy the online decals that I could print on my inkjet. Instead I used white tissue paper (from a greetings card shop), used double sided tape to stick a piece to some stout card and passed this through my printer. I stuck the images on using PVA glue – careful not to put too much on the face as the ink is water soluable.

Firmware

The C code used in the compiler is shown below.

/*
 * File:   Portal Gun Controller v1b - editted for Blog site
 * Author: Rodders
 * Created on 22nd May 2016
 * Config Control
 *
 *
 * Purpose:
 *
 * Target PIC is PIC16F1829 - 20 pins
 *
 * v1b   xxxx
 */

#include <xc.h>
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>            // Boolean (true/false) definition

#define    _XTAL_FREQ    16000000        // Variable used for time delays only

void flash(int intFlashes);
void initialPic(void);

//global variables
bool FireColour;
int Pattern;

// ********************************************************************
void interrupt isr(void){

    GIE=0;                      //turn off interrupts (note they are automatically turned on when ISR finishes)

    // finish
    // reset any flags
    GIE=1;
}

// ********************************************************************
//void interrupt low_isr(void){ //only if device has two priority levels???
//}


// ********************************************************************
void initialPIC(void)
{   // Initialize user ports and peripherals.
    //clock set up; 64MHz
    OSCCONbits.IRCF0=true;
    OSCCONbits.IRCF1=true;
    OSCCONbits.IRCF2=true;
    OSCCONbits.IRCF3=true;
    OSCCONbits.SCS0=false;
    OSCCONbits.SCS1=false;

    OSCCONbits.SPLLEN = 0;   //x4 clock even if config file sets pllen=0

    // Set port directions for I/O pins: 0 = Output, 1 = Input
    //PortA
    ANSELA = 0b00000000;            // Make all PORTA pins digital I/O
    TRISA = 0b00000000;            // PWM RA0-RA7 = x8 pins    RA0 is CS/SS for SPI
    LATA = 0x00;

    //PortB
    ANSELB = 0b00000000;
    TRISB = 0b10000000;            // PWM RB0-RB5 = x6 pins    Keep RB6 and RB7 clear as ICSP only                   // Change RB7 and RB6 to SPI inputs

    //PortC
    LATC=0x00;
    ANSELC = 0x00;
    TRISC = 0x00;                     // RC3 and RC4 are inputs for SPI from Raspberry Pi

    OPTION_REGbits.nWPUEN=0;    //if off - needed to set portc pull ups in next line
    WPUC = 0b10000000;
    INLVLC=0x00;          //schmitt triggers 0=off

    //TMR2 Setup
    //uses Fosc/4 = 16Mhz
    T2CON=0b00000001;          //pre-scale to 1/4
    PR2=80;                    //test increment 256 steps
    T2CONbits.TMR2ON=true;

    // Interrupt on Change, IOC
    IOCAP=0x00000001;       //portA, Positive edge    ....caution as using CD4011B
    IOCAF=0;

    //INTCON setup
    GIE=0;
    PEIE=1;

}

// ********************************************************************
void flash(int intFlashes)
// as a test utility
{
    for (int j=0; j< intFlashes;j++)
    {
        // Turn LED on and wait for a time delay
        LATCbits.LATC2=1;
        for ( int i = 0; i < 5; i++ ) __delay_ms( 100 ); //see http://www.microchip.com/forums/m673703-p2.aspx
        // On the PIC18F series, the __delay_ms macro is limited to a delay of 179,200
        // instruction cycles (just under 15ms @ 48MHz clock).

        // Turn LED off and wait for a time delay
        LATCbits.LATC2=0;
        for ( int i = 0; i < 5; i++ ) __delay_ms( 100 );
    }

    for ( int i = 0; i < 10; i++ ) __delay_ms( 100 );        //finish with a slight delay before exiting
}

int main(int argc, char** argv) {

       //set up hardware
       initialPIC();

       FireColour=false;                //false=blue, true=orange
       Pattern=0;

       //turn the main output LEDs off
       LATBbits.LATB4=false;
       LATBbits.LATB5=false;
       LATBbits.LATB6=false;

       while(1){                        //the main loop that continously runs

           // set the top indicator LED colour according to the FireColour value, RGB LED
           // take low to illuminate these LEDs
           if (! FireColour){
               //blue
                LATCbits.LATC0=true;        //R
                LATCbits.LATC1=true;        //G
                LATCbits.LATC2=false;       //B
           }
           else{
                //orange
                LATCbits.LATC0=false;
                LATCbits.LATC1=false;
                LATCbits.LATC2=true;
           }

           //now wait for the trigger to be pulled, and for the line to go low, internal resistor pulls this pin high
           while(PORTBbits.RB7==true){
           }

                            LATCbits.LATC3=false;
                            LATCbits.LATC6=false;
                            LATCbits.LATC7=false;

           //wait and test again
           __delay_ms( 300 );
           if (PORTBbits.RB7==false){
               //line is still low so assume it was a large trigger pull as the user wants to fire

               //turn claw LEDs off
                LATCbits.LATC3=true;
                LATCbits.LATC6=true;
                LATCbits.LATC7=true;

               //work out which colour
               if (! FireColour){
                   LATBbits.LATB4=true;         //B
                   LATBbits.LATB5=false;        //G
                   LATBbits.LATB6=false;        //R
               }
               else{
                   LATBbits.LATB4=false;
                   LATBbits.LATB5=true;
                   LATBbits.LATB6=true;
               }

               while (PORTBbits.RB7==false){
                   //wait for it to go high which signals a release of the button
               }

               //turn main output LEDs off
               LATBbits.LATB4=false;
               LATBbits.LATB5=false;
               LATBbits.LATB6=false;

               //and the claw LEDs back on
                LATCbits.LATC3=false;
                LATCbits.LATC6=false;
                LATCbits.LATC7=false;
               
                __delay_ms( 300 );
           }

           else {
                //line has returned high quickly; a quick tap - so toggle the colour on the indicator
               if (FireColour){
                   FireColour=false;
                }
               else{
                   FireColour=true;
               }               

           } //else
           __delay_ms( 300 );           //add a delay to stop racing

       }    //while

    return (EXIT_SUCCESS);
}

And the associated CONFIG.H

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s