W19 ¦ Final Project Presentation

Assignment for week 19

  • document a final project that integrates the range of units covered, answering:
    • what does it do?
    • who's done what beforehand?
    • what did you design?
    • what materials and components were used?
    • where did they come from?
    • how much did they cost?
    • what parts and systems were made?
    • what processes were used?
    • what questions were answered?
    • how was it evaluated?
    • what are the implications?
  • projects can be separate or joint, but need to show individual mastery of all of the skills
  • where possible, you should make rather than buy the parts of your project
  • present your final project, weekly assignments, and tutorials
  • Link to this week’s homeworkpage


The Poetry Machine - What does it do?

What parts and systems were made?

For my final project I have been working towards making a poetry machine.
I have used the projects in the previous weeks to prepair for the final project. So please refer to week 11, 13, 14, 15 and 18 for further documentaion in detail on specific subjects.

In this prototype I have 6 microcontrollers all connected together listening in in the same line waiting for an order. (See week 13).

Each mircocontroller controls one motor, and it has it's own ID. When the microcontroller detects it's ID it will react on the order that follows. The order is: move the motor to a certain position corresponding to the letter it received. I have been having difficulties ajusting the code to be precise each time. There is something playing up and it seems to shoot one position further when going whole circle.





On a website there is motion detection through a web cam. When motion is detected it sends a random poem from a pool of poems down the communication line. On a web server there is a node.js bridge that allows for communication between the website and the microcontrollers. (see week 14)





On the board is a Hall sensor which detects a magnet which is on the inside of the wheel. The board uses the magnet to find "home position". I have had problems when trying to have all units working together. The motors are very weak and stop very easily and that messes up the precision. It sure needs some more work, but it is nearly there.



The design process

What did you design?

All the parts used in the machine are designed and made by me with the exception of parts like nails, bolts, motors, cables and connectors. I used Illustrator to draw the machine parts used. I also used Inkscape and an addon called Gear developer to draw the gears. I go into great detail about the design pocess in week 18.

What processes were used?


  1. I used the laser cutter to cut MDF and clear plexy for the main structure.
  2. I also used the vinyl cutter for the machine lettering.
  3. Input devices: a webcam and a Hall Sensor
  4. Output devices: stepper motor
  5. I designed the circuit boards in Eagle.
  6. I programmed the circuit boads in the Arduino environment.
  7. I used networking knowledge to hookup all motor boards.

What materials and components were used? Where did they come from? How much did they cost?

  • For the design development I used 7 MDF plates 30x60 cm. I bought them from a local vendor and had them cut to size for the laser cutter. They costed less that $10 in total.
  • I also use 6 plexy plates 30x60 cm. I bought them directly from FabLab Reykjavik. They are about $11 each or $66 in total.
  • In week 15 I list in great detail what parts like motors and microcontrollers I ordered, from whom and what they costed.
  • I estimate that the final project has costed me around $480.

Who's done what beforehand?

Please refer to week 15 were I coverd this subject in detail.

The end result and how to continue

What questions were answered? How was it evaluated? What are the implications?

There were many things that did not work out and others that worked well. The motors I ordered were too weak and made the whole process unnesseccarly complicated. I had hoped to get further with this project and would have liked to finish my poetry machine with all the 30 working units like I intended to in the beginning. I managed to make a proof of concept prototype using only a single unit. And tried my best to make a prototype with 6 units work, it is nearly there but it needs at least 3 more days of work.

Writing the program for the motors was a steep learning curve. But in the end there was a working code. I believe the code could use some some more tweaking and adjusting to the machine itself. That could be easily achived given little more time.

I feel like I am just starting on this journey using motors. I am very inspired and would love to incorporate all sorts of motors in my art in the future.



Programming for the final project

For the final project I am programming the boards in the Arduino environment. I began working on the programming for the functionality of the machine in week 11 Output Devices. It began as a simple program for unipolar stepper motors and has gone through many transforamtion during the past weeks and has now ended as program for bipolar stepper motors with puls width modulation function.

For the motion detection I used javascript and html, see week 14.



For the communication between the webpage and the device I am using node.js and there I am using a javascript bridge. See week 14



/*
==============================================================================================
Stepper Motor & Hall Sensor - talking over serialport
Sigga Helga
FabAcademy  Mai, 2015

I am using ATtiny 44 AVR microcontroller with 8MHz internal clock and programming it with FABISP.
The TX (transmited from computer)= MOSI (MasterOutSlaveIn) is on PA6 and translates as Pin 5 in arduino 
The RX (Received from computer)= MISO (MasterInSlaveOut) is on PA5 and translates as Pin 6 in arduino 

I am using  Stepper motor:
It is a Bipolar motor with four wires, the step angle is 7.5 degrees

Stepper is attached as follows: 
Coil 1 = PAO=white is PIN 0 and is connected to IN2 on the first H-Bridge, PA1=red is PIN 1 and is connected to IN1 on the first H-Bridge,
Coil 2 = PA3=blue is PIN 2 and is connected to IN2 on the second H-Bridge, PA4=orange is PIN 4 and is connected to IN1 on the second H-Bridge,


This program controls one motor.  There are many motors connected but each motor has its own microcontroller Board. I am talking to many microcontroller all listening in on the same line.
I am sending 2 bites of info, first is the ID of the motor, second is the new location.
When the microcontoller reconizes it's ID it acts on the order, otherwise it ignors it.

==============================================================================================
*/
#include   //  This library allows for serial port communication from the computer to many microcontroller all listening in on one line
#define ID 3                               //  Idendification for this motor
#define stepsPerPosition 12                //  If the motor has 7,5 degree steps that means 360/7,5 = 48 and each "step_cw" function consists of 4 steps hence 48/4 =12 for full circle
#define totalPositions 40
#define myHomePosition 1

int motorPin1 = 0;                        //0 and 1 are on one coil (blue and red)
int motorPin2 = 1;                        //0 and 1 are on one coil (blue and red)
int motorPin3 = 3;                        //3 and 4 are on one coil (green and black)
int motorPin4 = 4;                        //3 and 4 are on one coil (green and black)
#define delayTime 3

int hallSensorPin = A7;                   //Hall Sensor reads magnetic field.  Using this to find the "home" position

int myCurrentPosition = myHomePosition;   // position 0 does not exist...0
int myTargetPosition = 0;                 // position 0 does not exist....0


SoftwareSerialWithHalfDuplex mySerial(6, 5, false, false); // RX, TX  for reciving and transmitting data are on pins 6 and 5.  False, false makes sure that the 

//=====================SETUP======================================================================

void setup() {
  pinMode(motorPin1, OUTPUT);       //Giving the pins connected to the motor electicity to play with, hence the output
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  pinMode(hallSensorPin, INPUT);    //the hall sensor measures magnetic field and we will be reading that info in hence the input
  
  mySerial.begin(9600);             // Setting up serial port communication,  using the 9600 talking speed
  mySerial.println("hello you");    // debug line - prints "hello You" each time you reset the program
 

}



//====================MAIN LOOP====================================================================

void loop(){
  if (myTargetPosition ==0) {                        //If my target position is Zero(a position that only exists at the beging of the program) then
      findHomePosition();                            // find the home position, the loop is defined here below. 
      myTargetPosition=1;                            // when you have found the home position set the target postion to one
  }
    if(mySerial.available() >= 2 ){                   // if 2 bytes or more arrived through the seraial communication line
            int targetID = mySerial.read();           // write down the value you read from mySerial and put it into a int called targetID
            int newTargetPosition = mySerial.read();  // write down the second value your read from mySerial into to a int called newTargetPosition
            if (targetID == ID ){                     // If the ID is the same as my ID
              myTargetPosition = newTargetPosition;   // then make the new target postion as my Target position
              }  
     }
      

      if (myCurrentPosition != myTargetPosition){     // if my current Position is not the target position
         moveOnePositionCW();                         // keep moving until you have reached it.
      }
 }
  
//==================DEFINING FUNCTIONS=============================================================



void whichDirectionToGo (){                            // Shall we go backwards or forwards?
 if (myTargetPosition > myCurrentPosition) {           // If the target number is higher that my current number
    moveOnePositionCW;                                 // move forward
  } 
  
  else if (myTargetPosition < myCurrentPosition) {    // if he target number is lower that my current number
    moveOnePositionCCW;}                              // move backwards
}


void moveOnePositionCW (){                             // one move in clockwise direction
    myCurrentPosition++;                               // add one to my current position
    if (myCurrentPosition == totalPositions+1)         // if I am one over myTotalPositions (the counting for totalPositions starts at zero hence the plus 1.
        {myCurrentPosition = 1;                        // the make my postion one, that is start counting again begining with one
        }
    for (int i = 0; i < stepsPerPosition; i++) {       //each "step_cw" consist of 4 steps, so if the motor has 7,5 degree steps that means 360/7,5 = 48 and 48/4 =12
          step_cw();
        }
}

void moveOnePositionCCW(){                            //counterClockWise direction
    myCurrentPosition--;                                // subtract one from my current position
    if (myCurrentPosition == 0 )                        // if I am one over 0 or myTotalPositios I reset the counter to start counting again
        {myCurrentPosition = totalPositions;
            }
    for (int i = 0; i < stepsPerPosition; i++) {        //each "step_ccw" consist of 4 steps, so if the motor has 7,5 degree steps that means 360/7,5 = 48 and 48/4 =12
          step_ccw();                                   //go backwards
        }        
}

  
void findHomePosition() {                                         //finds the starting point on the wheel using a hall sensor and a magnet.  This runs when the program is started and it then knows where it is
     int hallSensorValue = analogRead(hallSensorPin);             //Read the anlog pin and put the value in an int called hallSensorValue
     while ((hallSensorValue > 480) && (hallSensorValue < 520)) { //The hall sensor measures around 500-510 when it is neutral but it goes above or belove that when it senses the magnet, so if neutral  
       step_cw();                                                 // keep moving 
       delay (1);
       hallSensorValue = analogRead(hallSensorPin);               //read the hall sensor again
   // while (1){                                                  //Debugger- sends the Hall Sensor's reading to the console window 
        // mySerial.write(hallSensorValue);  
     
      
     } 
    myCurrentPosition = myHomePosition;                            //when the magnet is located then that is the home position
   
}
//=====================================================MotorStearing = PulseWidthModulation=====================================================
                                                                      
                                                                      
                                                                      //To be able to run the motor without them getting real hot we use Pulse Width Modulation
                                                                      //This means we turn the electicity off and on very rapidly, that way the coils are not always high and run cooler
                                                                                                                                    
// 8-step 
int pulseWidthModulation_count = 30;                                 // we will turn the electricity on and off 30 times                               
unsigned int onDelay = 95;                                           //Defing a OnDelay which means the electricity is high/on for 95 micro seconds
unsigned int offDelay = 5;                                           // Do not set to zero!!!  Defining a OffDelay were the electicity is off/low for 5 microseconds

void PulseWidthModulate(int pwmMotorPin1, int pwmMotorPin2)          //loop that will pulse the electicity.  Defining PulseWidth pins as pwMotorPin1 and 2.  These are placeholders for the motorPins used in the moveMotor loop
{
  for (int count = 0; count < pulseWidthModulation_count; ++count) {  //As long as the count has not been reached do this:
    digitalWrite(pwmMotorPin1, HIGH);                                 //Set the electricity on the first pin
    digitalWrite(pwmMotorPin2, HIGH);                                 //Set the electricity on the second pin
    delayMicroseconds(onDelay);                                       //delay for 95 microseconds
    digitalWrite(pwmMotorPin1, LOW);                                  //Set the electricity low the first pin                         
    digitalWrite(pwmMotorPin2, LOW);                                  //Set the electricity low the second pin
    delayMicroseconds(offDelay);                                      //delay for 5 microseconds
  }
}


//Moving the motor
int motorCurrentPosition = 1;


void step_cw (){                                          // one move in clockwise direction
    motorCurrentPosition++;                               // add one to my current position
    if (motorCurrentPosition == 5)                        // if (motorCurrentPosition == totalMotorPositions+1)  if I am one over myTotalPositions (the counting for totalPositions starts at zero hence the plus 1.
        {motorCurrentPosition = 1;                        // the make my postion one, that is start counting again begining with one
        }
      moveMotor(motorCurrentPosition);
        }
        
void step_ccw (){                                         // one move in clockwise direction
    motorCurrentPosition--;                               // add one to my current position
    if (motorCurrentPosition == 0)                        // if I am one over myTotalPositions (the counting for totalPositions starts at zero hence the plus 1.
        {motorCurrentPosition = 4;                        // the make my postion one, that is start counting again begining with one
        }
      moveMotor(motorCurrentPosition);
        }
  
void moveMotor (int index){                               //Index loop to move the motor. This way we can go single step forward, 7.5 degrees
   if (index == 1){                                       //as long as the index is at 1, set the motorpin number 1 high and so forth.  The reason why it is double is if you want to change this code to half steps.
      PulseWidthModulate(motorPin1, motorPin1);           //The reason why it is double is if you want to change this code to half steps you need sometimes need two pins high at the same time. See the code below:
       }
   if (index == 2){
      PulseWidthModulate(motorPin3, motorPin3);
     }
     
  if (index == 3){
      PulseWidthModulate(motorPin2, motorPin2);
      }
   if (index == 4){  
      PulseWidthModulate(motorPin4, motorPin4);
       }
}

/*Moving the motor                                            // Half steps used to controle the motor - 8 steps in each
int motorCurrentPosition = 1;
#define totalMotorPositions 8

void step_cw (){                                              // one move in clockwise direction
    motorCurrentPosition++;                                   // add one to my current position
    if (motorCurrentPosition == totalMotorPositions+1)        // if I am one over myTotalPositions (the counting for totalPositions starts at zero hence the plus 1.
        {motorCurrentPosition = 1;                            // the make my postion one, that is start counting again begining with one
        }
      moveMotor(motorCurrentPosition);
        }
        
void step_ccw (){                                             // one move in clockwise direction
    motorCurrentPosition--;                                   // add one to my current position
    if (motorCurrentPosition == 0)                            // if I am one over myTotalPositions (the counting for totalPositions starts at zero hence the plus 1.
        {motorCurrentPosition = 8;                            // the make my postion one, that is start counting again begining with one
        }
      moveMotor(motorCurrentPosition);
        }
        

void moveMotor (int index){
  
  if (index == 1){
      digitalWrite(motorPin1, HIGH);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, LOW);
      PulseWidthModulate(motorPin1, motorPin1);
      }
 
   if (index == 2){
      digitalWrite(motorPin1, HIGH);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, HIGH);
      digitalWrite(motorPin4, LOW);
      PulseWidthModulate(motorPin1, motorPin3);
     }
 
   if (index == 3){
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, HIGH);
      digitalWrite(motorPin4, LOW);
      PulseWidthModulate(motorPin3, motorPin3);
       }
 
   if (index == 4){  
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, HIGH);
      digitalWrite(motorPin3, HIGH);
      digitalWrite(motorPin4, LOW);
      PulseWidthModulate(motorPin2, motorPin3);
       }
 
   if (index == 5){  
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, HIGH);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, LOW);
      PulseWidthModulate(motorPin2, motorPin2);
       }
 
   if (index == 6){  
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, HIGH);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, HIGH);
      PulseWidthModulate(motorPin4, motorPin2);
       }
 
   if (index == 7){  
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, HIGH);
      PulseWidthModulate(motorPin4, motorPin4);
       }
 
   if (index == 8){  
      digitalWrite(motorPin1, HIGH);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, HIGH);
      PulseWidthModulate(motorPin1, motorPin4);
       }
}
*/


Files to download from
The Final Project
===========================

Poetry Machine Website-
Motion Detection

Here is the Motion Detection Website that talks to a node.js bridge and sends random poems to the machine.
NOTE: For the website to work it nees to sit on a server. I used XAMPP.



The Node.js bridge

Here is the node.js bridge that enables communication between the website and the machine.



The Program to Control the Motors

Here is the program for the microcontrollers that controls bipolar stepper motors. It is for a board with Hall Sensor that measures magnetic field and two H-Bridges that control the motor.



The Design Files for the Machine

Here are the design files for the machine. I used Illustrator to draw up the designs but used Gear-developer for Inkscape for the gears.



The design file for the lettering

Here are the design files I used for the laser cutter to make the letters. It is designed in Illustrator and the file is in many layers. I used a Stencil font so I could use both the letters and the offcut as a stencil to paint through.



The Design Files for the Boards

Here are the Eagle design files for the boards. The boards are designed for ATTiny44 microcontroller, an Hall sensor that reads magnetic fiels and two H-Bridges that are motor controllers. It has one 10K resistor, two 0.1Uf capacitor, two 10 Uf capacitor and one 1 Uf capacitor. It also has two 2x2 pinHeader and one 2x3 pinheader.



Final project presentations, part 1&2

Here are the final project presentations, part 1 & part 2 on Vimeo.



Final project presentations, part 3&4

Here are the final project presentations, part 3&4 on Vimeo.