Project showcase
Nama

Nama © CC BY-NC

A textile interface for controlling generative audiovisual output.

  • 4,667 views
  • 0 comments
  • 6 respects

Components and supplies

Apps and online services

About this project

Introduction

Nama is a soft circuit instrument that has open purpose and usage, being able to be freely folded, twisted, tightened and manipulated in various contexts to generate real time digital data of its movement.

Based on the concept of relational object created by Lygia Clark, the interface is built upon a fabric tissue given its physical particularities that, through its interaction in motion, are able to bring to senses characteristics related to virtuality such as: fluidity, flexibility and mobility. Therefore causing, along with the sensible feedback, a non-verbal and kinesthetic understanding of virtual liquidity.

The current setup of the interface has a single Lilypad Arduino, 5 Lilypad Accelerometers, one Xbee Module, and a LiPo battery sewed altogether manually with conductive thread. Data is gathered by the accelerometers and sent wirelessly to a computer through Arduino and Xbee, where they will be reprocessed into some kind of output. The project also includes a customizable software specially designed to receive the data from the interface.

Documentation

A video that demonstrates its potential:

And below, a video documentation of an interactive installation produced based on the instrument:

List of materials and components:

  • 1 LilyPad Arduino 328 Main Board.
  • 5 LilyPad Accelerometers ADXL335.
  • 1 LilyPad Xbee.
  • LilyPad FTDI Basic Breakout
  • 5V LilyPad LiPower.
  • 2 XBee 1mW Chip Antenna
  • Series 1. - XBee Explorer USB.
  • Polymer Lithium Ion Battery (LiPo)
  • 1000mAh (good up to 8h running).
  • LiPo Charger Basic
  • Micro-USB.
  • Conductive Thread
  • 234/34 4ply.
  • Needle set.
  • Fabric of your choice.
  • Thin wire + solder (optional).
  • Textile glue + mounting tape (optional)

More info at:

http://viraseres.com/nama

Code

Arduino CodeArduino
///////////////////////////////////////////////////////////////
// Nama Project v1.0
// Instrument Arduino code.
// ------------------------------------------------------------
// Created by Luiz Zanotello on May/2012.
// Under Creative Commons License: CC BY-NC-SA 3.0.
// More information at: http://www.viraseres.com/nama
///////////////////////////////////////////////////////////////

//Accelerometer 1 (z) - bottom right
////////////////////////////////////
const int a1pinV = 6; //output current pin
const int a1pinZ = A0; //data pin

//Accelerometer 2 (z) - top right
/////////////////////////////////
const int a2pinV = 7; //output current pi
const int a2pinZ = A1; //data pin

//Central accelerometer (x/y)
/////////////////////////////
const int aCpinV = 8; //output current pi
const int aCpinX = A2; //data pin
const int aCpinY = A3; //data pin
//Accelerometer 3 (z) - top left
////////////////////////////////
const int a3pinV = 2; //output current pi
const int a3pinZ = A4; //data pin

//Accelerometer 4 (z) - bottom left
///////////////////////////////////
const int a4pinV = 3; //output current pi
const int a4pinZ = A5; //data pin

////////////////////////////////////////////////////////

void setup()
{
  //Begin serial transmition:
  Serial.begin(115200);
  //Set output pins (+ current):
  pinMode(a1pinV, OUTPUT);
  digitalWrite(a1pinV, HIGH);
  pinMode(a2pinV, OUTPUT); 
  digitalWrite(a2pinV, HIGH);
  pinMode(aCpinV, OUTPUT); 
  digitalWrite(aCpinV, HIGH);
  pinMode(a3pinV, OUTPUT); 
  digitalWrite(a3pinV, HIGH);
  pinMode(a4pinV, OUTPUT); 
  digitalWrite(a4pinV, HIGH);
}

////////////////////////////////////////////////////////

void loop()
{ 
  // Printing analog data received from accelerometers
  Serial.println();
  Serial.print(5); // Number of accelerometers
  Serial.print(',');
  Serial.print(analogRead(a1pinZ)); // Accelerometer 1 reading (z)
  Serial.print(',');
  Serial.print(analogRead(a2pinZ)); // Accelerometer 2 reading (z)
  Serial.print(',');
  Serial.print(analogRead(a3pinZ)); // Accelerometer 3 reading (z)
  Serial.print(',');
  Serial.print(analogRead(a4pinZ)); // Accelerometer 4 reading (z)
  Serial.print(',');
  Serial.print(analogRead(aCpinX)); // Central accelerometer reading (x)
  Serial.print(',');
  Serial.print(analogRead(aCpinY)); // Central accelerometer reading (y)
  Serial.print(tranG);
  delay(10);
}

////////////////////////////////////////////////////////
Processing CodeJava
A sample code of how to link the Instrument to Processing, with a simple visualization software.
//////////////////////////////////////////////////////////////////////////////////////////////
// Nama Project v1.0
// Instrument data receiver.
// -------------------------------------------------------------------------------------------
// All codes created by Luiz Zanotello on May/2012.
// Under Creative Commons License: CC BY-NC-SA 3.0.
// More information at: http://www.viraseres.com/nama
//////////////////////////////////////////////////////////////////////////////////////////////

// General configuration
int baudRate = 115200; //Baud rate 
int serialPort = 0; //Serial port
boolean isPrinting = true; //Print to post?

// Libraries
import processing.serial.*;
import processing.opengl.*;

//////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  size(1200, 600, OPENGL);
  beginSerial();
  setupFonts();
  smooth();
}

void draw() {
  background(230, 230, 212);
  visualizeData();
  if (isPrinting==true) {
    printValues();
  }
}

void printValues() {
  println("AC NAME / RAW / FILTERED / DIFFERENCE / FILTERED DIFFERENCE");
  println("A1(z): "+acData[1][0]+" / "+acData[1][1]+" / "+acData[1][2]+" / "+acData[1][3]);
  println("A2(z): "+acData[2][0]+" / "+acData[2][1]+" / "+acData[2][2]+" / "+acData[2][3]);
  println("A3(z): "+acData[3][0]+" / "+acData[3][1]+" / "+acData[3][2]+" / "+acData[3][3]);
  println("A4(z): "+acData[4][0]+" / "+acData[4][1]+" / "+acData[4][2]+" / "+acData[4][3]);
  println("A5(x): "+acData[5][0]+" / "+acData[5][1]+" / "+acData[5][2]+" / "+acData[5][3]);
  println("A5(y): "+acData[6][0]+" / "+acData[6][1]+" / "+acData[6][2]+" / "+acData[6][3]);
  println("AV(z): "+acData[0][0]+" / "+acData[0][1]+" / "+acData[0][2]+" / "+acData[0][3]);
  println();
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Kalman Filter Class.
// Created by Interactive Matter.
// (http://github.com/interactive-matter/Processing/tree/master/lis302dl_kalman)
// -------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////

public class KalmanFilter {
  private float q;
  private float r;
  private float x;
  private float p;
  private float k;
  public KalmanFilter(float q, float r, float p, float initial_value) {
    this.q=q;
    this.r=r;
    this.p=p;
    this.x=initial_value;
  }
  public float addSample(float measurement) {
    //omit x=x
    p=p+q;
    k=p/(p+r);
    x= x + k*(measurement-x);
    p=(1-k)*p;
    return x;
  }
  public String toString() {
    return "KalmanFilter with p="+p+", k="+k;
  }
  public float getQ() {
    return q;
  }
  public float getR() {
    return r;
  }
  public float getP() {
    return p;
  }
  public float getK() {
    return k;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Serial communication and configuration to the Lilypad accelerometer soft circuit.
// -------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////

// Use the following variables to calibrate the readings from the accelerometers.
// Change the "low" and "high" values of each accelerometer
// according to the average lowest and highest values received.

int a1lowZ = 307;
int a1highZ = 759;
int a2lowZ = 294;
int a2highZ = 727;
int a3lowZ = 281;
int a3highZ = 711;
int a4lowZ = 286;
int a4highZ = 717;
int a5lowX = 303;
int a5highX = 769;
int a5lowY = 298;
int a5highY = 747;

//////////////////////////////////////////////////////////////////////////////////////////////

// Mapping variables
Serial myPort;
float acData[][] = new float[7][4]; // [raw, filt, dif, dif filt] [average z, 1, 2, 3, 4, 5x, 5y, 5z]
float acDataOld[] = new float[7]; // used for calculating the differences
float newValue, newValueFiltered, masterAverage, newDif, rawDif; //mapping

// Kalman filter instances
// q(process noise), r(sensor noise), p(estimated error), initial_value

KalmanFilter filterDif0 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif1 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif2 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif3 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif4 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif5 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif6 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterDif7 = new KalmanFilter(0.1, 16, 0.1, 1);
KalmanFilter filterA1 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA2 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA3 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA4 = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA5X = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterA5Y = new KalmanFilter(0.5, 256, 100, 510);
KalmanFilter filterMaster = new KalmanFilter(0.5, 256, 100, 510);

//////////////////////////////////////////////////////////////////////////////////////////////

// Serial Event
void beginSerial() {
  myPort = new Serial(this, Serial.list()[serialPort], baudRate);
  myPort.bufferUntil(10);
}

// Map Data
void serialEvent(Serial p) {
  String inString;
  try {
    inString = (myPort.readString());
    if (inString != null) {
      String[] listSt = split(inString, ',');     
      if (listSt.length == 7) {
        masterAverage = 0;

        //////////////////////
        // Accelerometer 1 - Z
        newValue = float(listSt[1]);
        if (Float.isNaN(newValue)) {
          newValue = acData[1][0];
        }
        acData[1][0] = newValue;
        masterAverage = masterAverage+newValue;
        newValueFiltered = constrain(map(filterA1.addSample(newValue), a1lowZ, a1highZ, 0.01, 1.0), 0.001, 2.0);
        if (Float.isNaN(newValueFiltered)) {
          newValueFiltered = acData[1][1];
        }
        acData[1][1] = newValueFiltered;

        //////////////////////
        // Accelerometer 2 - Z
        newValue = float(listSt[2]);
        if (Float.isNaN(newValue)) {
          newValue = acData[2][0];
        }
        acData[2][0] = newValue;
        masterAverage = masterAverage+newValue;
        newValueFiltered = constrain(map(filterA2.addSample(newValue), a2lowZ, a2highZ, 0.01, 1.0), 0.001, 2.0);
        if (Float.isNaN(newValueFiltered)) {
          newValueFiltered = acData[2][1];
        }
        acData[2][1] = newValueFiltered;

        //////////////////////
        // Accelerometer 3 - Z
        newValue = float(listSt[3]);
        if (Float.isNaN(newValue)) {
          newValue = acData[3][0];
        }
        acData[3][0] = newValue;
        masterAverage = masterAverage+newValue;
        newValueFiltered = constrain(map(filterA3.addSample(newValue), a3lowZ, a3highZ, 0.01, 1.0), 0.001, 2.0);
        if (Float.isNaN(newValueFiltered)) {
          newValueFiltered = acData[3][1];
        }
        acData[3][1] = newValueFiltered;

        //////////////////////
        // Accelerometer 4 - Z
        newValue = float(listSt[4]);
        if (Float.isNaN(newValue)) {
          newValue = acData[4][0];
        }
        acData[4][0] = newValue;
        masterAverage = masterAverage+newValue;
        newValueFiltered = constrain(map(filterA4.addSample(newValue), a4lowZ, a4highZ, 0.01, 1.0), 0.001, 2.0);
        if (Float.isNaN(newValueFiltered)) {
          newValueFiltered = acData[4][1];
        }
        acData[4][1] = newValueFiltered;

        //////////////////////
        // Accelerometer C - X
        newValue = float(listSt[5]);
        if (Float.isNaN(newValue)) {
          newValue = acData[5][0];
        }
        acData[5][0] = newValue;
        newValueFiltered = constrain(map(filterA5X.addSample(newValue), a5lowX, a5highX, 0.01, 1.0), 0.001, 2.0);
        if (Float.isNaN(newValueFiltered)) {
          newValueFiltered = acData[5][1];
        }
        acData[5][1] = newValueFiltered;

        //////////////////////
        // Accelerometer C - Y
        newValue = float(listSt[6]);
        if (Float.isNaN(newValue)) {
          newValue =acData[6][0];
        }
        acData[6][0] = newValue;
        newValueFiltered = constrain(map(filterA5Y.addSample(newValue), a5lowY, a5highY, 0.01, 1.0), 0.001, 2.0);
        if (Float.isNaN(newValueFiltered)) {
          newValueFiltered = acData[6][1];
        }
        acData[6][1] = newValueFiltered;

        //////////////////////
        // Master average calc
        newValue = masterAverage/4;
        if (Float.isNaN(newValue)) {
          newValue = acData[0][0];
        }
        acData[0][0] = newValue;
        newValueFiltered = constrain(map(filterMaster.addSample(newValue), (a4lowZ+a3lowZ+a2lowZ+a1lowZ)*0.25, (a4highZ+a3highZ+a2highZ+a1highZ)*0.25, 0.01, 1.0), 0.001, 2.0);
        if (Float.isNaN(newValueFiltered)) {
          newValueFiltered = acData[0][1];
        }
        acData[0][1] = newValueFiltered;
        setDifferences();
      }
    }
  }
  catch(Exception e) {
    println(e);
  }
}

// Set differences
void setDifferences() {
  for (int i=0;i<acData.length;i++) {
    acData[i][2] =  acData[i][1]-acDataOld[i];
    if (i==0) {
      acData[i][3] = filterDif0.addSample(acData[i][2]);
    }
    if (i==1) {
      acData[i][3] = filterDif1.addSample(acData[i][2]);
    }
    if (i==2) {
      acData[i][3] = filterDif2.addSample(acData[i][2]);
    }
    if (i==3) {
      acData[i][3] = filterDif3.addSample(acData[i][2]);
    }
    if (i==4) {
      acData[i][3] = filterDif4.addSample(acData[i][2]);
    }
    if (i==5) {
      acData[i][3] = filterDif5.addSample(acData[i][2]);
    }
    if (i==6) {
      acData[i][3] = filterDif6.addSample(acData[i][2]);
    }
    if (Float.isNaN(acData[i][3])) {
      acData[i][3] = acDataOld[i];
    }
    if (acData[i][3]<0.0001) {
      acData[i][3]=0;
    }
    if (acData[i][2]<0.0001) {
      acData[i][2]=0;
    }
    acDataOld[i] = acData[i][1];
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Graphical visualization of the interface data.
// -------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////

// Config
int interfaceDimensionX = 128;
int interfaceDimensionY = 134;

// Mapping variables
PFont titleFont, contentFont, copyrightFont;
float goPoint[][] = new float[5][3];
float baseX, baseY;

void setupFonts() {
  titleFont = loadFont("ArialNarrow-23.vlw");
  contentFont = loadFont("Courier-15.vlw");
  copyrightFont = loadFont("Courier-9.vlw");
}

void visualizeData() {
  // Bg  
  fill(35, 41, 44);
  rect(-2, -2, 380, height+4);
  
  // Base position of text
  baseX = 60;
  baseY = 214;

  // Title
  textFont(titleFont);
  fill(230, 230, 212);
  text("Nama Instrument v1.0", baseX-6, baseY-60); 
  textFont(contentFont);
  fill(230, 230, 212);
  text("", baseX-6, baseY-28);
  textFont(copyrightFont);
  text("ACC:       RAW  FILTER  DIF  DIF+FILTER", baseX-6, baseY);
  
  // 1
  baseY = baseY+34;
  textFont(titleFont);
  fill(215, 102, 124);
  text("A1z: ", baseX-6, baseY); 
  fill(230, 230, 212);
  textFont(contentFont);
  text(int(acData[1][0]), baseX+48, baseY-3);
  text("", baseX+79, baseY-3);
  text(acData[1][1], baseX+84, baseY-3);
  text("", baseX+142, baseY-3);
  text(acData[1][2], baseX+147, baseY-3);
  text("", baseX+205, baseY-3);
  text(acData[1][3], baseX+210, baseY-3);

  // 2
  baseY = baseY+34;
  textFont(titleFont);
  fill(215, 181, 102);
  text("A2z: ", baseX-6, baseY); 
  fill(230, 230, 212);
  textFont(contentFont);
  text(int(acData[2][0]), baseX+48, baseY-3);
  text("", baseX+79, baseY-3);
  text(acData[2][1], baseX+84, baseY-3);
  text("", baseX+142, baseY-3);
  text(acData[2][2], baseX+147, baseY-3);
  text("", baseX+205, baseY-3);
  text(acData[2][3], baseX+210, baseY-3);

  // 3
  baseY = baseY+34;
  textFont(titleFont);
  fill(102, 215, 161);
  text("A3z: ", baseX-6, baseY); 
  fill(230, 230, 212);
  textFont(contentFont);
  text(int(acData[3][0]), baseX+48, baseY-3);
  text("", baseX+79, baseY-3);
  text(acData[3][1], baseX+84, baseY-3);
  text("", baseX+142, baseY-3);
  text(acData[3][2], baseX+147, baseY-3);
  text("", baseX+205, baseY-3);
  text(acData[3][3], baseX+210, baseY-3);

  // 4
  baseY = baseY+34;
  textFont(titleFont);
  fill(102, 130, 215);
  text("A4z: ", baseX-6, baseY); 
  fill(230, 230, 212);
  textFont(contentFont);
  text(int(acData[4][0]), baseX+48, baseY-3);
  text("", baseX+79, baseY-3);
  text(acData[4][1], baseX+84, baseY-3);
  text("", baseX+142, baseY-3);
  text(acData[4][2], baseX+147, baseY-3);
  text("", baseX+205, baseY-3);
  text(acData[4][3], baseX+210, baseY-3);

  // 5x
  baseY = baseY+34;
  textFont(titleFont);
  fill(139, 137, 127);
  text("A5x: ", baseX-6, baseY); 
  fill(230, 230, 212);
  textFont(contentFont);
  text(int(acData[5][0]), baseX+48, baseY-3);
  text("", baseX+79, baseY-3);
  text(acData[5][1], baseX+84, baseY-3);
  text("", baseX+142, baseY-3);
  text(acData[5][2], baseX+147, baseY-3);
  text("", baseX+205, baseY-3);
  text(acData[5][3], baseX+210, baseY-3);

  // 5y
  baseY = baseY+34;
  textFont(titleFont);
  fill(139, 137, 127);
  text("A5y: ", baseX-6, baseY); 
  fill(230, 230, 212);
  textFont(contentFont);
  text(int(acData[6][0]), baseX+48, baseY-3);
  text("", baseX+79, baseY-3);
  text(acData[6][1], baseX+84, baseY-3);
  text("", baseX+142, baseY-3);
  text(acData[6][2], baseX+147, baseY-3);
  text("", baseX+205, baseY-3);
  text(acData[6][3], baseX+210, baseY-3);

  // separador
  baseY = baseY+34;
  textFont(contentFont);
  fill(230, 230, 212);
  text("", baseX-6, baseY-3);

  // Average
  baseY = baseY+34;
  textFont(titleFont);
  fill(230, 230, 212);
  text("AVz: ", baseX-6, baseY); 
  fill(230, 230, 212);
  textFont(contentFont);
  text(int(acData[0][0]), baseX+48, baseY-3);
  text("", baseX+79, baseY-3);
  text(acData[0][1], baseX+84, baseY-3);
  text("", baseX+142, baseY-3);
  text(acData[0][2], baseX+147, baseY-3);
  text("", baseX+205, baseY-3);
  text(acData[0][3], baseX+210, baseY-3);
  
  // Credits
  textFont(copyrightFont);
  fill(35, 41, 44);
  text("created by luiz gustavo zanotello at jun/2012", width-233, height-30);
  text("http://www.viraseres.com/nama", width-154, height-20);
  text("under CC BY-NC-SA 3.0", width-114, height-10);

  ////////////////////////////////////////////////////////////////////////////////////////////
  // Graph
  noStroke();
  fill(255);
  baseX = width-width/3+map(acData[5][1], 0, 1, -1, 1)*100;
  baseY = height/2+map(acData[6][1], 0, 1, -1, 1)*100+map(acData[0][1], 0, 1, -1, 1)*50;
  translate(baseX, baseY, map(acData[0][1], 0, 1, 50, -100));
  perspective();
  rotateX(radians(acData[5][1]*360));
  rotateY(radians(acData[6][1]*360));
  rotateZ(radians(acData[0][1]*360));
  directionalLight(120, 120, 120, 0, -1, -1);
  ambientLight(230, 230, 230);

  // 4
  fill(142-(acData[2][3]*255*100), 170-(acData[2][3]*255*100), 255-(acData[2][3]*255*100), 90+(acData[4][3]*255*100));
  goPoint[4][0] = 0-interfaceDimensionX+map(acData[4][1], 0, 1, -100, 100);
  goPoint[4][1] = interfaceDimensionY/2+map(acData[4][1], 0, 1, -100, 100);
  goPoint[4][2] = map(acData[4][1], 0, 1, -400, 400);
  pushMatrix();
  translate(goPoint[4][0], goPoint[4][1], goPoint[4][2]);
  sphere(6);
  popMatrix();

  // 3
  fill(142-(acData[1][3]*255*100), 255-(acData[1][3]*255*100), 201-(acData[1][3]*255*100), 90+(acData[4][3]*255*100));
  goPoint[3][0] = 0-interfaceDimensionX+map(acData[3][1], 0, 1, -100, 100);
  goPoint[3][1] = 0-interfaceDimensionY/2+map(acData[3][1], 0, 1, -100, 100);
  goPoint[3][2] = map(acData[3][1], 0, 1, -400, 400);
  pushMatrix();
  translate(goPoint[3][0], goPoint[3][1], goPoint[3][2]);
  sphere(6);
  popMatrix();

  // 2
  fill(255-(acData[3][3]*255*100), 221-(acData[3][3]*255*100), 142-(acData[3][3]*255*100), 90+(acData[4][3]*255*100));
  goPoint[2][0] = interfaceDimensionX+map(acData[2][1], 0, 1, -100, 100);
  goPoint[2][1] = 0-interfaceDimensionY/2+map(acData[2][1], 0, 1, -100, 100);
  goPoint[2][2] = map(acData[2][1], 0, 1, -400, 400);
  pushMatrix();
  translate(goPoint[2][0], goPoint[2][1], goPoint[2][2]);
  sphere(6);
  popMatrix();

  // 1
  fill(255-(acData[4][3]*255*100), 142-(acData[4][3]*255*100), 164-(acData[4][3]*255*100), 90+(acData[4][3]*255*100));
  goPoint[1][0] = interfaceDimensionX+map(acData[1][1], 0, 1, -100, 100);
  goPoint[1][1] = interfaceDimensionY/2+map(acData[1][1], 0, 1, -100, 100);
  goPoint[1][2] = map(acData[1][1], 0, 1, -400, 400);
  pushMatrix();
  translate(goPoint[1][0], goPoint[1][1], goPoint[1][2]);
  sphere(6);
  popMatrix();

  // C
  fill(179-(acData[5][3]*255*100)-(acData[6][3]*255*100), 177-(acData[5][3]*255*100)-(acData[6][3]*255*100), 167-(acData[5][3]*255*100)-(acData[6][3]*255*100), 90+(acData[5][3]*255*100)+(acData[6][3]*255*100));
  goPoint[0][0] = map(acData[5][1], 0, 1, -400, 400);
  goPoint[0][1] = map(acData[6][1], 0, 1, -400, 400);
  goPoint[0][2] = map(acData[0][1], 0, 1, -100, 100);
  pushMatrix();
  translate(goPoint[0][0], goPoint[0][1], goPoint[0][2]);
  sphere(6);
  popMatrix();

  // Lines
  stroke(255);
  line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[1][0], goPoint[1][1], goPoint[1][2]);
  line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[2][0], goPoint[2][1], goPoint[2][2]);
  line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[3][0], goPoint[3][1], goPoint[3][2]);
  line(goPoint[0][0], goPoint[0][1], goPoint[0][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
  line(goPoint[1][0], goPoint[1][1], goPoint[1][2], goPoint[2][0], goPoint[2][1], goPoint[2][2]);
  line(goPoint[1][0], goPoint[1][1], goPoint[1][2], goPoint[3][0], goPoint[3][1], goPoint[3][2]);
  line(goPoint[1][0], goPoint[1][1], goPoint[1][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
  line(goPoint[2][0], goPoint[2][1], goPoint[2][2], goPoint[3][0], goPoint[3][1], goPoint[3][2]);
  line(goPoint[2][0], goPoint[2][1], goPoint[2][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
  line(goPoint[3][0], goPoint[3][1], goPoint[3][2], goPoint[4][0], goPoint[4][1], goPoint[4][2]);
}

Schematics

Materials and components
F93pplehaq320jk
Design
How to sew the components
Fcmmishhaq320in
Fritzing Schematic
NamaInstrument_1.0.fzz

Comments

Similar projects you might like

The Cheapest ESP8266 Programmer!

Project tutorial by Gustavo Reynaga

  • 3,800 views
  • 0 comments
  • 15 respects

Control Music Volume and Ledbar Using Slider of 1Sheeld

Project tutorial by ahmed ismail

  • 1,535 views
  • 2 comments
  • 11 respects

How to Make a Remote Controlled Robotic Hand with Arduino

Project showcase by Gabry295

  • 36,641 views
  • 5 comments
  • 115 respects

Digital Clock with Mirrored Display Driven by Accelerometers

Project showcase by LAGSILVA

  • 14,768 views
  • 1 comment
  • 39 respects

Stopwatch and Lap Time Counter

Project showcase by LAGSILVA

  • 13,897 views
  • 5 comments
  • 24 respects

The TrafficLight

Project showcase by Advaith Jagathesan

  • 13,068 views
  • 1 comment
  • 20 respects
Add projectSign up / Login