FAB ACADEMY 2014

Michael Hurtado


Input Devices

The task this week was fabricate sensors and program them.

Sensors:

A sensor is an electronic device that takes data from the real world and transforms them into electrical quantities. In total we will fabricate 6 btw sensors, then we will appointing and detail the list of components for each one.

Light Sensor:
- 1 Microcontroller AtTiny45
- 1 capacitor 1UF
- 1 resistor of 10k Ω
- 1 phototransistor
- 1 resistor 49.9k Ω
- Headers



Temperature Sensor:
- 1 microcontroller AtTiny45
- 1 capacitor 1UF
- 4 resistors of 10k Ω
- 1 thermistor
- Headers



Sensor of capacitive contact:
- 1 microcontroller AtTiny45
- 1 capacitor 1UF
- 1 resistor of 10k Ω
- 2 resistors 1m Ω
- Headers



Sound Sensor:
- 1 microcontroller AtTiny45
- 1 capacitor 1UF
- 5 resistors of 10k Ω
- 1 resistor of 1k Ω
- 1 resistor 0 Ω
- 2 capacitors of 1u F
- 1 capacitor of 0.1u F
- Headers



Magnetic field Sensor:
- 1 microcontroller AtTiny45
- 1 capacitor 1UF
- 1 resistor of 10k Ω
- 1 Hall-effect sensor
- Headers



Switch:
- 1 microcontroller AtTiny45
- 1 capacitor 1UF
- 1 resistor of 10k Ω
- 1 switch
- Headers



Manufacturing:

For manufacturing I used the Roland modeled MDX20, double-sided tape, isopropyl alcohol and a copper plate.
The following is weld the cards one by one, helping us of a welder, tin wire and paste for welding. Then of weld, the result is the following:



Programming:

To schedule our sensors, we are going to take as example the light sensor.
What we do is to enter the page:

http://academy.cba.mit.edu/classes/input_devices/index.html

And we download the files .c and "make"
We connected the FabISP and the FTDI cable to the card as in the following image:

Then we opened the console of UBUNTU and we going to the folder where we have the files.

We write in the console:
sudo make -f hello.light.45.make program-usbtiny

We obtain:



Then we write:
avrdude -p t45 -c usbtiny -U flash:w:hello.light.45.c.hex

We obtain:



Finally we write:
sudo make -f hello.light.45.make program-usbtiny

We obtain:



To display the data obtained by the sensors, we downloaded the files .py and write in console:
python hello.light.45.py /dev/ttyUSB1

We obtain:



For the others sensors:



Observations:
In Ubuntu we have to have both installed Python Tkinter, Pyserial and Numpy. Also check the connection port on the FTDI, in some cases is ttyUSB0.

After programming the sensors, the following was customize the codes. For this I used Python and smtplib library that allowed me to send mail messages to my email when the amount of light was high.

Code:

#
# hello.light.45.py
#
# receive and display light level
# hello.light.45.py serial_port
#
# Neil Gershenfeld
# CBA MIT 10/24/09
#
# (c) Massachusetts Institute of Technology 2009
# Permission granted for experimental and personal use;
# license for commercial sale available from MIT
#
# Modified by Michael Hurtado
#
from Tkinter import *
import time
import serial
import smtplib

WINDOW = 600 # window size
eps = 0.5 # filter time constant
filter = 0.0 # filtered value

TO = 'receptor@gmail.com'
GMAIL_USER = 'emisor@gmail.com'
GMAIL_PASS = 'pass'

SUBJECT = 'Home Message'
TEXT = 'The lights in garden are on'

def send_mail():
   print("sending email")
   smtpserver = smtplib.SMTP("smtp.gmail.com",587)
   smtpserver.ehlo()
   smtpserver.starttls()
   smtpserver.ehlo
   smtpserver.login(GMAIL_USER, GMAIL_PASS)
   header = 'To: ' + TO + '\n' + 'From: ' + GMAIL_USER
   header = header + '\n' + 'Subject:' + SUBJECT + '\n'
   print header
   msg = header + '\n' + TEXT + ' \n\n'
   smtpserver.sendmail(GMAIL_USER, TO, msg)
   smtpserver.close()

def idle(parent,canvas):
   global filter, eps
   #
   # idle routine
   #
   byte2 = 0
   byte3 = 0
   byte4 = 0
   ser.flush()
   while 1:
      #
      # find framing 
      #
      byte1 = byte2
      byte2 = byte3
      byte3 = byte4
      byte4 = ord(ser.read())
      if ((byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4)):
         break
   low = ord(ser.read())
   high = ord(ser.read())
   value = 256*high + low
   filter = (1-eps)*filter + eps*value
   x = int(.2*WINDOW + (.9-.2)*WINDOW*filter/1024.0)
   canvas.itemconfigure("text",text="%.1f"%filter)
   canvas.coords('rect1',.2*WINDOW,.05*WINDOW,x,.2*WINDOW)
   canvas.coords('rect2',x,.05*WINDOW,.9*WINDOW,.2*WINDOW)
   canvas.update()
   parent.after_idle(idle,parent,canvas)
   #print(filter)
   if (filter<45):
      send_mail()
      filter = 100
      

#
#  check command line arguments
#
#if (len(sys.argv) != 2):
#   print "command line: hello.light.45.py serial_port"
#   sys.exit()
#port = sys.argv[1]
port = 'COM5' #for windows
#
# open serial port
#
ser = serial.Serial(port,9600)
ser.setDTR()
#
# set up GUI
#
root = Tk()
root.title('hello.light.45.py (q to exit)')
root.bind('q','exit')
canvas = Canvas(root, width=WINDOW, height=.25*WINDOW, background='white')
canvas.create_text(.1*WINDOW,.125*WINDOW,text=".33",font=("Helvetica", 24),tags="text",fill="#0000b0")
canvas.create_rectangle(.2*WINDOW,.05*WINDOW,.3*WINDOW,.2*WINDOW, tags='rect1', fill='#b00000')
canvas.create_rectangle(.3*WINDOW,.05*WINDOW,.9*WINDOW,.2*WINDOW, tags='rect2', fill='#0000b0')
canvas.pack()
#
# start idle loop
#
root.after(100,idle,root,canvas)
root.mainloop()




Then I used Processing and the library Soundcipher to generate sound and I used particles to generate a visual interactive in accordance with the variation of light.

Code:

import arb.soundcipher.*;
import arb.soundcipher.constants.*;
import processing.serial.*;

Serial myPort;  // Create object from Serial class
int val;      // Data received from the serial port
int sensorData; // Data recieved from the serial port with 1,2,3,4 framing numbers filtered out
int highVal; //high value read in from Neil's C code 
int lowVal; //low value read in from Neil's C code 
int actualVal;  // adjusted sensor value
float eps = 0.5;
float filter = 0.0;
int NUM_PARTICLES = 200;
float w=500,c;
ParticleSystem p;
SoundCipher sc = new SoundCipher(this);
void setup()
{
  smooth();
  //size(displayWidth,displayHeight);
  size(640,480);
  background(0);
  p = new ParticleSystem();
  strokeWeight(4);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}
 
void draw()
{
  if (myPort.available() > 0) {    // If data is available
    val = myPort.read();           // read it and store it in val
    if (val > 4) {                // Filter out the framing numbers: 1,2,3,4
      highVal = myPort.read();           // read the high value sent from sensor and store it
      lowVal = myPort.read();           // read low value from sensor it and store it
      actualVal = 256 * (highVal + lowVal); // getting the actual value of the sensor 
      filter = (1-eps)*filter + eps*actualVal;
      println("The actualVal is " + filter); //print to the screen
    }
  colorMode(HSB,w);
  //c=255*sin(mouseX*mouseY/255);
  int d=(int)filter;
  c=map(d,0,1024,0,500);
  sc.playNote((int)c/10, 100, 2.0);  
  //println(frameCount);
  noStroke();
  fill(0,5);
  rect(0,0,width,height);
  p.update();
  p.render();
  }
}

class Particle
{
  PVector position, velocity;
 
  Particle()
  {
    position = new PVector(random(width),random(height));
    velocity = new PVector();
  }
   
  void update()
  {
    velocity.x = 20*(noise(filter/10+position.y/100)-0.5);
    velocity.y = 20*(noise(filter/10+position.x/100)-0.5);
    position.add(velocity);
     
    if(position.x<0)position.x+=width;
    if(position.x>width)position.x-=width;
    if(position.y<0)position.y+=height;
    if(position.y>height)position.y-=height;
  }
 
  void render()
  {
    stroke(c,w,w);
    line(position.x,position.y,position.x-velocity.x,position.y-velocity.y);
  }
}

class ParticleSystem
{
  Particle[] particles;
   
  ParticleSystem()
  {
    particles = new Particle[NUM_PARTICLES];
    for(int i = 0; i < NUM_PARTICLES; i++)
    {
      particles[i]= new Particle();
    }
  }
   
  void update()
  {
    for(int i = 0; i < NUM_PARTICLES; i++)
    {
      particles[i].update();
    }
  }
   
  void render()
  {
    for(int i = 0; i < NUM_PARTICLES; i++)
    {
      particles[i].render();
    }
  }
}