Voight-Kampff Machine

Distinguishing Humans from Replicant's

Similar projects worth following
The Voight-Kampff is a machine that uses biometric sensors to measure a subjects emotional response. Voight-Kampff machines are used by Blade Runners to determine whether an individual is a real human or a replicant (which are not legally allowed on earth). Since replicant's exhibit lower emotional responses than humans it is a simpler and more cost effective method than performing a complete genetic analysis of every suspected individual.

At the present time, this project is divided into 2 parts:

  1. Voight-Kampff machine (this project) - functional replica of the movie prop
  2. viEwMotion (View Emotion) - wearable Voight Kampff - which houses the sensors used fort measuring emotional response (in the form of a wrist band).

This section of the overall project will address the building and fabrication of the machine used in Bladerunner. This includes working out a complete 3D model of the machine, building the moving parts (arm, "eye", and bellows), interfacing the 3 separate monitors, LED bargraphs, and all software and hardware including schematics.

The viEwMotion section will focus on the sensors used (with full schematics, etc.), software algorithm development and fabrication of the wrist band housing the sensors.

RedGreenBargraph Drawing 1.pdf

Mounting jig for Red and Green bargraph

Adobe Portable Document Format - 546.80 kB - 10/14/2017 at 19:07


RedBargraph Drawing 1.pdf

Mounting jig for Red bargraph

Adobe Portable Document Format - 509.37 kB - 10/14/2017 at 19:07


  • 1 × Continuous Rotation Servo (standard size) FeeTech FS5103R (Adafruit product number 154)
  • 1 × Continuous Rotation Micro Servo FeeTech FS90R (Adafruit product number 2442)
  • 1 × NEMA17 Stepper Motor with Planetary Gearbox 5:1 planetary gearbox
  • 1 × Standard Servo
  • 8 × Rectangular LED's green over main monitor

View all 12 components

  • Better Screens, LCD and CRT

    Tom Meehan04/24/2018 at 03:31 0 comments

    The screen dimensions, for the 3 screens on the Voight Kampff, that I've finally decided on, which I based on advice from numerous others.... as well as what I could find in the correct aspect ratio of 4:3 (which is what was used at the time the movie was made). For the main screen, I'm using a color CRT screen with 5”diagonal (640x480 pixels with RCA video input), for the 2 smaller screens I'm using 2.4”diagonal LCD (320x240 pixels, with an SPI interface).

    For the large, main, color screen:

    I, finally, found a 5” diagonal color CRT screen

    Magnavox portable TV, model #RD0510 C102, manufactured August 1992 (about $26 US ,including shipping). This screen has 2 RCA plugs for input – 1 video and 1 audio. Video input works perfectly, audio I did not test since I don't need it. The image below is from the eBay posting.

    For the 2 smaller monitors (which I calculated to be 2.5” diagonal):

    I settled on 2.4” LCD screens that take input though an SPI connection

    2.4" SPI TFT LCD Display 2.4 Inch Touch Panel LCD ILI9341 240x320 5V/3.3V. ( Ideally I hoped to find some B&W CRT screens with a 2.5” diagonal).

    Listing details from eBay were:


    Size:2.4" SPI Serial

    Display area:36.72(W)X48.96(H)mm

    Driver element: a-Si TFT active matrix

    Pixel arrangement: RGB vertical stripe

    Driver IC: ILI9341

    Backlight: White LED

    Viewing Direction: 6 o?clock

    Color Depth: 262K/65K

    Resolution: 240RGB*320

    5V compatible, use with 3.3V or 5V logic

    Need at least 4 IOs from your MCU

    With PCB plate (including power supply IC, SD), compatible with 5110 interface

    $6.22 + $1.85 postage

    Since, I don't need the touch screen on these I plan on removing them (they peel off fairly easily). Ideally it would be perfect to have B&W screens without touchscreen – but, due to supply and demand they are actually harder to find and more expensive.

    At around this time last year (if memory serves me right) I tried using some similar LCD screens, only 2.8” diagonal and despite trying everything I could think of, including getting replacement screens, I could not get them to work, after about 2 weeks of trying (including getting replacements), so I I gave up and put them in my “Deep Fried Silicone” jar (assuming they must all be dead).

    Recently, I acquired a Saelea logic analyzer clone and I thought “why not test the communication lines going to these screens from my old Arduino Uno R3 board to the LCD screens”... surprise, the D3 pin on my Arduino was not functioning. Lucky for me, this is an old board and the AVR chip is a DIP, instead of surface mount. So, I just pulled out the origonal ATMEL 328P and it out and plugged a new one in. Wallah... all the screens work perfectly now.

    The 2.8” LCD screens, I ordered previously, were “Shield's” that mounted directly onto an Arduino Uno R3 board and used most of the pins on the board to control the screen. (Used parallel 8 bit communication)

    The newer 2.4” LCD screens, I recently received, use fewer pins on the Arduino (configured for SPI, Serial Peripheral Communication) to interface with and control the screen. I have encountered a few unexpected issues... The most serious was the expectation that the screens worked at both 3.3v and 5v logic and power levels (they explicitly state “5V compatible, use with 3.3V or 5V logic”). It turns out this was not “exactly” true.

    The “price” of inexpensive parts, frequently, seems to be a lack of documentation.

    When I received my new LCD screens I was ready, my Arduino board already had an “example” sketch uploaded for SPI communication and wired to a solderless breadboard – just needed to plug in the screen and power everything up. Plugged the screen into the breadboard, connected the power supply, and … nothing happened.

    Looking for schematics – figured that since...

    Read more »

  • A whole lot of updates for Voight Kampff Build

    Tom Meehan11/24/2017 at 06:43 0 comments

    I've been working on this build, and it's many different challenges for quite a while now.  But, I've neglected to post my trials and tribulations to my build log here.  So, I thought it was about time to do so.

    I'll start with a bunch of video's that document progress on different aspects of this build and in following posts I'll add details and update additional progress.

    These videos begin with the oldest updates and end with the most recent updates.

    A recap of my progress around the time of my last post:

    Update on actual functioning Bellow's:

    Work on the small monitors:

    Changes to the VK machine Bar Graphs:

  • Bellow's Mechanism Functioning!

    Tom Meehan07/03/2017 at 00:25 0 comments

    After a much experimentation, much of it making overly complicated mechanisms, I finally went back to basics and tried using a normal regular servo to move the bellows. I'm not sure why i didn't try it first but I think it was because of difficulties in getting the "arm" to raise - nothing I tried had enough torque until I found a geared stepper.

    Anyway, here's the video of my test run:

    The code is super basic, just using the standard Arduino Servo library to control the motion. I want to smooth out the motion if I can. If possible, I hope to find a servo library that allows steps less than 1 degree (or, if I have to, write my own).

  • Progress on the infamous Voight-Kampff arm

    Tom Meehan06/09/2017 at 04:33 0 comments

    I've been trying to get a video of my functioning Voight-Kampff “arm” filmed and posted for more than a week now, finally I recorded it and now I can post it and here it is:

    After re-writing my control code multiple times I finally realized what I was doing wrong – I simply needed to change my conditional statements from “if” to “while”. An embarrassing mistake but all to easy to miss when I haven't had anyone else look at my code (to easy to read “into” your own writing – if I'd had someone else look at it they would have caught it immediately – “palm to forehead” moment).

    Here's the functioning code:

    /*VK arm - lift, extend, rotate 
    *  Serial communication used in initial debugging
    *  Goal - use signal from RPi to trigger the arm raise, extend and
    *  rotate sequence
    *   - endstops for safety and to signal extension and rotation limits
    //Arm Raise motor -Stepper motor driven by Pololu A4988 driver
      int RaiseDir = 8; //dir pin - arduino pin to direction pin on Stepper Driver
      int RaiseStep = 9; //step pin - arduino pin to step pin on Stepper Driver
    #include <Servo.h>
    // Arm Extension servo
    Servo ExtServo;    //Extends and retracts upper arm
      int ExtStop = 3;
      boolean ExtVal = true;
      int ExtFor = 100;  //adjust according to speed and weight
      int ExtBack = 0;
      int ExtHold = 90;
    //  "Eye" Rotation servo
    Servo RotServo;     //Rotates eye Up (forward) or Down (back)
      int RotStop = 6;
      boolean RotVal = true;
      int RotUp = 100;  //adjust according to speed and weight
      int RotDown = 86;
      int RotHold = 90;
    void setup() {
      ExtServo.attach(2);  //470uF electrolytic cap- for motor start
      RotServo.attach(5);  //470uF electrolytic cap- for motor start
      pinMode(RaiseDir, OUTPUT);
      pinMode(RaiseStep, OUTPUT);
      pinMode(ExtStop, INPUT_PULLUP);
      pinMode(RotStop, INPUT_PULLUP);
    void loop() {
      delay(1000);    //Pause
      Raise();        //Raise the arm
      delay(1000);    //Pause
      Extend();       //Extend the arm
      delay(1000);    //Pause
      Rotate();       //Rotate "Eye" forward
    void Raise() {
      Serial.println("Raising Arm...");
      digitalWrite(RaiseDir,LOW); // Set Dir high
        for(int x = 0; x < 125; x++)   {
          digitalWrite(RaiseStep,HIGH); // Output high
          delay(10); // Wait
          digitalWrite(RaiseStep,LOW); // Output low
          delay(10); // Wait
      Serial.println("Arm Raised...");
    void Extend() {
      while  (ExtVal == true)  {     
        //Serial.println("Extending Arm..  ");
        ExtVal = digitalRead(ExtStop);
       //Serial.println("Arm Extended..");
    void Rotate()  {
       while (RotVal == true) {
        //Serial.println("Rotating Up..");
        RotVal = digitalRead(RotStop);
       //Serial.println("Eye In Position...");
    Well anyway, it's fixed and working correctly now. I do still need to add a “retract and store” sequence but that is fairly simple now and will depend on the types of end-stops I use to detect the positions of the different moving parts.

    I'm continuing to work on modeling, what I refer to as, the “eye” servo box. I haven't added all the details yet since I'm still trying to finalize the scale (in reference to the “shaver”). One attempt is visible in the current video (3D-printed the front half, filled lines with “Bondo Glazing and Spot Putty”, sanded, primed and painted black).

    The screens on the VK are continuing to give me headaches – I made cutouts of the different available LCD screen sizes (that support “component input” and 4:3 aspect ratio) just so that I could check out how they might work.

    I've also been attempting to use some old CRT viewfinder's (salvaged from VHS Video Camera's) and trying to project the image onto a mini screen. So far this has been unsuccessful, I... Read more »

  • VK - LED Bar Graphs

    Tom Meehan04/24/2017 at 00:16 0 comments

    Light Bar Above Main Screen

    For this bar graph I'm currently using 12 - 2x5mm rectangular LED's (I used Red/Green LED's that have 3 leads - common cathode, 2 anodes 1 for each color). I was thinking to make a more graded display (2 levels for each LED – green then red so 24 levels) but realized that wouldn't really match the display in movie. The movie display looks like a 8 Red then 4 Green array, so I'm only using 2 leads for each LED – 8 with Red anode and 4 with Green anode (final design will use single color LED's).

    I'm currently using two SN74HC595 - 8 bit serial to parallel out shift registers to control the LED's. This means that 16 bits of information (0 or 1 / on or off) are sent out (4 bits are unused since there are only 12 LED's). A great tutorial on using these shift registers with LED's and Arduino's is at Adafuit - Arduino Lesson 4.

    Light Bar Below Small Screens

    The 10 bar LED below the 2 smaller screens, on the left side (from the examiners point of view).

    These LED bar-graphs seem to fit, they are come in a 20 DIL package with a 2.54mm pin spacing (they fit perfectly on a solder-less breadboard, bridging the middle of the board). My initial idea was to use shift registers (74HC595's) for this bar-graph also but remembered a circuit I built following a tutorial a few years ago that used a single Johnson Decade Counter (CD4017BE) to control all 10 LED's and at that time I adapted it to work with an Attiny85 using an analog input (voltage divider made of a resistor and a 10K thermistor – for basic temperature biofeedback). This tutorial is a good on on using the Johnson Decade Counter.

    The Johnson Decade Counter decreases the pins used to control the LED array from 3 to 2 and eliminates the need for current limiting resistors (though still likely a good idea) since it can only output 10mA per pin. Unlike the 595 shift registers used for the main screen LED Bar the 4017 requires us to use rapid switching for persistence of vision – only one LED can be lit at a time.

  • CAD work update

    Tom Meehan04/12/2017 at 18:41 0 comments

    Quick update on CAD work on workup for 3D model of Voight Kampff.

    Still refining this but all files are up on OnShape (may need to create a free account to view or work files).

  • AD8232 ECG Breakout Testing

    Tom Meehan04/12/2017 at 04:08 0 comments

    The AD8232 is a great chip, from Analog Devices, for reading bio-electrical signals (mainly muscle and heart - but may be good for EEG). The chip only comes in a 4 mm × 4 mm, 20-lead LFCSP package but thankfully SparkFun carries a breakout for it SparkFun Single Lead Heart Rate Monitor – AD8232 ,SEN-12650.

    SparkFun even has a hookup guide and a repository on Github for code examples. The code on Github hasn't been updated for a few years but I've tested the Arduino code and it works fine (the Processing code does not seem to work on the newest release of Processsing - 3.3). To visualize the heart data I just used the Arduino code and the Serial Plotter in the Arduino IDE (located in the “Tools” tab). Here's an example:

    I'll go into further detail later.

    But, for now I built up a VK model using card stock (the front is fairly accurate but the top is missing a lot of details):

    In the foreground are some of the sensors and screens I've been testing.

    I mainly put this model together to:

    1. See if my measurements and scale were correct.
    2. To use as a physical comparison for parts (to see if screens, etc actually fit correctly).

    Thankfully, it seems that I'm on the right track!

  • Non-contact IR Thermometer Updates

    Tom Meehan04/07/2017 at 06:59 0 comments

    Testing Harbour Freight non-contact IR temp sensor. Drawing from DIY Thermal Camera for information on connecting to Arduino for sending serial information to laptop.

    I adapted and simplified some code to read and send the temperature data:

    /*Harbour Freight Non-Contact IR Temp Sensor
    adapted from
      changed to use serial monitor instead of a 16x2 LCD and function order re-organized
        setup -> loop -> readBit  with indentations added to make reading easier
    #define CLK 3
    #define DATA 4
    volatile int nbits = 0;
    volatile byte hexbyte = 0;
    volatile byte read_byte;
    volatile int byte_ready = 0;
    volatile unsigned char message[4];
    volatile int nbytes = 0;
    volatile int message_waiting = 0;
    unsigned long last_time = 0;
    float temp;
    float ambient;
    void setup() {
      pinMode(CLK, INPUT);
      pinMode(DATA, INPUT);
      attachInterrupt(1, readBit, FALLING);
    void loop() {
      if (message_waiting == 1) {
        last_time = millis();
      if (message[0] == 0x4c) {
        int t = message[1]<<8 | message[2];
        temp = t/16.0 -273.15;
        Serial.print(millis()/1000.0);Serial.print(" ");
          else if (message[0] == 0x66) {
            int t = message[1]<<8 | message[2];
            ambient = t/16.0 -273.15;
       message_waiting = 0;
      if (millis() - last_time > 1000) {
        nbits = 0;
        nbytes = 0;
        hexbyte = 0;
        message_waiting = 0;
        byte_ready = 0;
        last_time = millis();
    void readBit() {
      int val = digitalRead(DATA);
      int bit = (val == HIGH) ? 1 : 0;
      hexbyte = (hexbyte << 1) | bit;
      if (nbits == 8) {
        if (byte_ready == 0) {
          read_byte = hexbyte;
          byte_ready = 1;
        if (hexbyte == 0xd) {
          nbytes = 0;
          message_waiting = 1;
        else if (message_waiting == 0) {
          if (nbytes < 4) {
            message[nbytes] = hexbyte;
      hexbyte = 0;
      nbits = 0;
    Finally have a better understanding of the S:D ratio that is given on commercial non-contact temperature sensor units. The Harbour Freight one that I purchased states that it 6:1 spot to distance ratio, this means that at 6 inches the spot size (area read) is 1 inch and at 12 inches the spot size is 2 inches.

    A good illustration (from Grainger, shows a 12:1 ratio):

  • Non-contact IR Thermometer / Sensor for Blush Response

    Tom Meehan04/06/2017 at 02:55 0 comments

    Initially I tested the Melexis 90614 sensor (I chose this sensor due to it's smaller field of view compared to other sensors I looked at). While the sensor worked perfectly, it was only good for short range (under 10cm) – I expected this might be the case which is why I detailed the method of narrowing the field of view in my last post. I tried that method by using a 1mm hole (in polished steel sheet metal) and placing it 1mm from sensor. Well, no luck. This only resulted in cutting the total IR getting to sensor (limited view by cutting everything else out – not by focusing field of view to smaller area, which would utilize the whole sensor).

    This led me to dropping the whole idea of measuring changes in temperature of the “cheek” area due to not being able to focus a sensor on a small area from any reasonable distance. Well, that is, until I met Michael Shaub at the Hackaday Un-Conference in Chicago. Talking to him about his IR Imaging project DIY Thermal Camera , as well as his presentation of the project, gave me the motivation to look further into how these sensors can be focused on a small area at a greater distance from the sensor.

    Presently testing out ideas using: Infrared Laser Thermometer Pittsburgh® - Harbour Freight item#93984 ($18.99) (which I think is the one Micheal is using). Basic specs for this are below:

    • 6:1 spot size to distance ratio
    • Non-contact IR thermometer pin-out
      • Data (pin D on module) to pin 12
      • Clock (pin C on module) to pin 2
      • Power (pin V on module) to diode from 3.3V supply
      • Ground (pin G on module) to ground

    Test results coming soon!

  • Issues and Solutions

    Tom Meehan03/13/2017 at 17:30 0 comments

    Mechanical issues encountered and solved (mostly):

    Biggest mechanical issue has been with my 3D Printer – one of the nuts on my Z-axis lead screws became stripped out. It took awhile to determine this was the issue (initially looked like a failure in the coupling of the lead screw to the stepper motor) and once I did figure it out I had to find a replacement nut, disassemble and re-assemble the printer, and then re-level and re-calibrate the whole thing. This obviously held me up in prototyping test parts but it is fixed and working better than ever now.

    Extension arm – currently testing 1/4” aluminum cylindrical extrusion (sounds technical but I got it off the shelf at Menards). Have found that it is “nominally” 1/4”, but is actually a bit larger than that. Came into play when testing a 1/4” I.D. nylon bushing – by itself it worked, but when inserted into a wood block it was to tight for the rod, even after running a 1/4” drill bit through it. So, switched to some Delrin – drilled a 1/4” hole through a 3/4”x3/4”x3/4” cube – better but still tight. Sanded down the lower section of the 1/4” aluminum rod with 400-600 grit sand paper – now it slides in and out smoothly.

    Servo motors – primarily the motor to extend the arm, needed more torque and metal gears – solved (SG-90 servo's from TowerPro). Encountered one new issue with the servo for arm extension – I incorrectly thought that the servo would rotate more than 180 degrees. I was able to fix this by converting the servo motor into a continuous rotation gear motor ( Adafruit guide to modifying servo for continuous rotation ). I will need to add limit switches to mark the endpoints of the travel of the arm.

    Raising the arm - continuing to test motors for raising the arm on the VK. None of the Servo's I have on hand are strong enough (high enough torque) and they stall under the tests I've tried. The same goes for all but the largest of the geared motors that I have on hand. I finally put together a test rig for my largest geared motor only to find that it had insufficient torque at lower speeds (controlling with PWM and a L293 H-Bridge). I ended up having to order a NEMA 17 stepper motor with a planetary gearbox (5:1 reduction), torque ratings look more than sufficient. I should receive it by Wednesday this week.

    Sensor Issues solved and working on:

    PulseOx sensor (MAX30100) – surface mount pads are just too small for me (since I'm just a beginner with surface mount components). I've etched multiple breakout boards (pics below) but have been unsuccessful at making an actual working board, the pads on the surface mount package are just to small for me (I've only just started using SMD components). I decided it would just be easier to buy a commercial module, the MAXREFDES117 (it uses the MAX30102 PulseOx sensor and comes with sample code for the Arduino).

    After receiving the MAXREFDES117 I soldered some header pins on to connect it up. Downloaded the code from Maxim Integrated, opened it up in my Arduino IDE and tried compiling it... a no go, it threw a bunch of errors and would not compile. Looking through all the header files I found that I needed to change the pin and port assignments the the I2C interface to work correctly. I did all that but still it wouldn't compile. Then I figured I might need to update my IDE – turns out it was a bit old (I was using 1.6.4 while the newest is 1.8.1). After updating everything I opened the new IDE, loaded up the example sketch and tried again to compile – it still failed. After some online searching and watching some videos by Maxim Integrated I could not find any comments by anyone using this module with an Arduino.

    Finally I decided to reach out to Maxim Integrated Support and emailed them about my problems with getting the module to work with their sample code. I did receive a reply back stating that they tested the sample code and experienced the same...

    Read more »

View all 14 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates