The Enactive Torch

Technical Information on the Enactive Torch:

Enactive Torch RT version 1.0

A new version of the Enactive Torch is now available. For details please visit our Github repository here.

Version 3.0

Download Instructions Here.

The enactive torch is a tactile feedback device used for experiments in sensory substitution. For full details and project history please visit the Enactive Torch Blog. The ET is an open source project under the Creative Commons License.

Scroll down for details of version 3.1

The Enactive Torch V3.0

The Enactive Torch - Version 3.0

The ET a hand held device with distance sensors at one end and a vibrating motor that can be strapped to your wrist. The intensity of the vibration is lined to the distance of objects in front of the torch. It uses an Arduino pro-mini so it is totally user programmable and it includes a Sparkfun BlueSMiRF Gold bluetooth transmitter and a triple axis accelerometer so that data on usage can be logged remotely. Power comes from six AAA batteries and there is a charging socket so it can be recharged without removing the batteries. The vibrating motor can be fitted externally or internally, although an internal vibrating motor can interfere with accelerometer readings. The following page details some technical information about the ET and a source code listing for the arduino controller.

Circuit Schematic:
Enactive Torch Schematic (Click for PDF instructions)

Enactive Torch Instructions (PDF)

Version 3.1

Version 3.1 is electronically identical to V3.0 but has a different case, machined or 3D printed in plastic.


The main difference is in the orientation of the programming adapter. This now slides in from the rear rather than from the top. The images below show how to plug the USB programming adapter in.


The sensor assembly can be unplugged by removing the two screws and pulling it off.


The charger plugs into the rear and will cause the device to switch off when it is plugged in. If access is required to the batteries then there are four screws on the under surface of the device, one in each corner. Unscrew these to open the case.


Both versions are compatible with ET 3.x torches.

ET Version 3.0 (download)

Version 3.2 implements a data sampling function that is enabled by pressing the user button. When enabled sensor data is streamed over the Bluetooth serial port and includes a timestamp for each sample point. Pressing the button again will stop the stream.

ET Version 3.2 Download Zip

//Version 3.2
//global variables
int Sensor1, Sensor2;
int AccX, AccY, AccZ;
int MotorValue = 0;
int ToneFrequency = 500;
//pin input and output constants
const int MotorOutputPin = 9; //digital pin 4 - PWM OUTPUT
const int SpeakerPin = 4; //digital pin 4 - OUTPUT
const int ButtonPin = 8; //digital pin 8 - INPUT
const int GreenLED = 7; //digital pin 7 - OUTPUT
const int Sensor1Pin = 1; //analog input pin 1 - Long range sensor 20-150cm
const int Sensor2Pin = 2; //analog input pin 2 - Short range sensor 8-80cm
const int AccXPin = 5; //analog input pin 5
const int AccYPin = 4; //analog input pin 4
const int AccZPin = 3; //analog input pin 3
 X axis is along the length of the ET
 Y axis across the width
 Z axis from bottom to top
//a high voltage on the LED pin switches it off
#define LEDON LOW

bool printEnabled =0;
int printLog = 0;
long int lastTime = 0;
int logInterval = 10;
//logInterval is the time in milliseconds between data samples:
//10= 10 milliseconds between samples or 100Hz
//100 = 100millisecs between samples or 10Hz
long int startTime = 0;

void setup(){ 
  //set up the digital inputs and outputs
  pinMode(SpeakerPin, OUTPUT);
  pinMode(ButtonPin, INPUT);
  pinMode(GreenLED, OUTPUT);
void loop() {
  MotorValue = map(Sensor1, 0, 600, 0, 255);//Map the long range sensor (in the range 0-600) to the motor PWM value (in the range 0-255)
  //MotorValue = map(Sensor1, 0, 600, 0, 255);//Map sensor2 (short range) to the motor PWM value
  analogWrite(MotorOutputPin, MotorValue);
  if(printEnabled) logData();

void checkButton(){
    //button is pressed - toggle print enable state
    printEnabled = 1-printEnabled;
    //set the LED (0 = ON) so it is ON when printing
    digitalWrite(GreenLED, !printEnabled);
    //now wait in a loop until the button is released
    while(!digitalRead(ButtonPin)) delay(10);
    //Now print a message so we mark the start and end of any data captured
    //and include an iterative number marking each time we start capturing
    if(printEnabled) {
      Serial.println("START DATA: ");
      startTime = millis(); //record the time that the sample collection started
                            //Note: the millis() function returns the number of milliseconds elapsed since the Arduino started up
    if(!printEnabled) Serial.println("END DATA:");
void logData(){
  //call print data but only if a specified time has elapsed
  long int currentTime = millis();
  if(currentTime-lastTime >= logInterval){
    lastTime = currentTime; //reset for the next time
    //print the elapsed time in milliseconds since the trial was started
    //now print the sensor data;
void readSensors(){
    Sensor1 = analogRead(Sensor1Pin);
   // wait 10 milliseconds for the analog-to-digital converter to settle after the last reading:
   Sensor2 = analogRead(Sensor2Pin);
   AccX = analogRead(AccXPin);
   AccY = analogRead(AccYPin);
   AccZ = analogRead(AccZPin);

void printData(){

void playTone(){
   //play a quick tune on startup
   digitalWrite(GreenLED, LEDON);
   tone(SpeakerPin, 392); //Start with a tone
   tone(SpeakerPin, 440); //Up a full tone
   tone(SpeakerPin, 349); //Down a major third
   tone(SpeakerPin, 174); //Now drop an octave
   tone(SpeakerPin, 261); //Up a perfect fifth
   digitalWrite(GreenLED, LEDOFF);
Forum Submit