Project 1 – Intro to Physical Computing: Student Work Fall 2020 https://courses.ideate.cmu.edu/60-223/f2020/work Intro to Physical Computing: Student Work Thu, 08 Oct 2020 15:40:56 +0000 en-US hourly 1 https://wordpress.org/?v=5.4.15 Double Transducer: Temperature to Color https://courses.ideate.cmu.edu/60-223/f2020/work/double-transducer-temperature-to-color/ Thu, 08 Oct 2020 07:44:30 +0000 https://courses.ideate.cmu.edu/60-223/f2020/work/?p=11423 Overall Photos:

Aerial photo of the entire transducer setup. (Mimi)

Top View of the Project -Daniel

Description:

This double transducer converts a temperature input into a color output. The transducer measures the ambient temperature. That measurement is then converted to movement on a servo motor. The servo motor moves in the range of 0 to 180 degrees. The higher the temperature reading is the closer the motor movement will be to 180 degrees and vise versa for lower temperatures. A magnet is attached to the arm of the servo motor, so the magnet rotates as the servo arm rotates. As the magnet rotates it changes its distance from the magnetic sensor that is located nearby. The magnet is the closest to the sensor at when the servo motor is at 0 degrees and the farthest when the servo motor is at 180 degrees. The reading from the magnetic sensor is then converted to a color that is outputted on the neoPixel ring.

Final Working Videos:

(Mimi)

(Daniel)-Not worked properly

I changed the temp value in the code to show that the light changes its color depending on the temperature.

TinkerCad Simulation:

 

Detail Photos:

Wires and Arduino we used for this project.-Daniel

The magnet is taped to the servo motor arm. When the servo arm rotates the magnet rotates as well. (Mimi)

GY 271 sensor(magnetic sensor) we used for this project.-Daniel

The NeoPixel Ring is the final output of our transducer. It outputs a color based on the magnetic field detected. (Mimi)

Process Images:

Thermistor, Magnetic sensor, and Servo Motor are wired to Arduino and working. (Mimi)

The LCD and NeoPixel ring have been added and are working. The neoPixel ring only changes shades of blue and the magnetic sensor is not reading correct values yet. (Mimi)

Starting to connect each component together on the breadboard. (Started with plugging in the LCD)-Daniel

Fully assembling the components from top to operate the system. Except, the LCD and the LED did not turn at this point because the 5V and GND circuit in the breadboard was not connected correctly.-Daniel

 

 

Discussion: 

Since this project was processed remotely, the easiest part of the project was to work in Tinkercad to demonstrate the project theoretically works. When we started the Tinkercad, we faced some problems with connecting LCD and finding the neo pixel code library. However, we passed this problem smoothly by referring back to various examples provided by the web and professor. Therefore, there was no actual hardship for working this project remotely.

However, the actual hardship came up from physical construction. Mimi had a problem with not having a consistent returning value from the magnetic sensor. Daniel had a problem with connecting his LCD and magnetic sensor to his project. We both solved this problem by asking a professor or referring back to the web explanations, but it took several tries to fix our mistakes. Also, we had a problem with choosing our materials. Mimi used a thermistor to measure the temperature, while Daniel used a temperature and humidity sensor to measure the temperature. This created little difference in coding since the temperature and humidity sensor requires its specific library to work properly.

If we had worked this project by meeting physically instead of remotely, it would have been much easier to fix our mistakes since we both had a problem with different parts. We could have fixed our mistakes by talking to each other and could have prepared the complete set of the project during our presentation. If we have the next team project time, we should find a better communication method between the working team members during the physical assembly work step to reduce differences between each project.

 

Schematic:

Schematic of the actual project

 

Code Submission:

/*
* Double Transducer: Temperature to Color
* Mimi Marino (mmarino) Daniel Moon (seonghym)
*
*
* Description: The temperature sensor reads the temperature.
    That value is then converted to a value that will
    correspond to the angle that the servo motor is moved. 
    A magnet is attached to the servo motor. As the servo
    moves the azimuth angle of the magnet with respect to 
    the magnetic sensor changes. The magnetic senesor reads
    that azimuth angle and that value is converted to an RGB 
    value. The neoPixel ring outputs this RGB color. 
*
*Credit: 
*   -HSV to RGB convertor functions 
*   https://gist.github.com/postspectacular/2a4a8db092011c6743a7 
*   
*   -Figuring out how to wire up the thermistor 
*   https://www.circuitbasics.com/arduino-thermistor-temperature-sensor-tutorial/
    
*
* Pin mapping:
*
* pin   | mode   | description
* ------|--------|------------
  6      output   Servo
  5      output   neoPixel
  A0     input    Temp Sensor
  A4     I2C      Magnet Sensor
  A5     I2C      Magnet Sensor
  3      ouput    LCD rs
  4      output   LCD enable
  10     output   LCD d4
  11     output   LCD d5
  12     output   LCD d6
  10     output   LCD d7
*/

#include <LiquidCrystal.h>
#include <Adafruit_NeoPixel.h>
#include <Servo.h>
#include <QMC5883LCompass.h>

const int SERVO_PIN = 6;
const int PIXEL_PIN = 5;
const int TEMP_PIN = A0;
const int NUMPIXELS = 12;
const int MAG_PIN = A4;
const int MAG_PIN1 = A5;
const int TEMP_LOW = 650;
const int TEMP_HIGH = 1023;

unsigned long timer = 0;
int temp;
int magnetMap;
int a;

QMC5883LCompass compass;
Servo doorMotor;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
//LiquidCrystal(rs, enable, d4, d5, d6, d7) 
LiquidCrystal lcd(3, 4, 10, 11, 12, 13);

void setup()
{
   Serial.begin(9600);
   //Sets OUPUT and INPUT pins
   pinMode(SERVO_PIN, OUTPUT);
   pinMode(PIXEL_PIN, OUTPUT);
   pinMode(TEMP_PIN, INPUT);
   doorMotor.attach(SERVO_PIN);
   
   //Sets LCD
   lcd.begin(16, 2);
   
   //Sets Neo pixel Strip
   pixels.begin();
  
   //initilizes the magnetic sensor
   compass.init();
}

void loop()
{
  // only executes every 200ms
  //updates the LCD, checks the temp sensor, 
  //updates and reads the motor position,
  //reads the magnetic sensor and outputs a color
  if ((millis() -timer >= 200)){
    
  //Read the temperature sensor 
  temp = analogRead(TEMP_PIN);
  
  //Change temp sensor input into values 0-180
  //650 -1023 corresponds to the varabilty of the 
  //sensor in my room w/o applied heat
  int tempMap = map(temp,TEMP_LOW, TEMP_HIGH, 0, 180);
  doorMotor.write(tempMap);  

  //magnetic senor outputs the azimuth angle
  compass.read();
  a = compass.getAzimuth();

  //48 corresponds to the servo at 0 degrees
  //338 corresponds to the servo at 180 degrees
  magnetMap = map(a, 48, 338, 0, 99);
  
  //makes magnetMap into value from 0.0-0.99 for 
  //hsv input
  float h = magnetMap / 100.0;
  float rgb[3];
  // converts magnetic value 0.0-0.99 to RGB value
  hsv2rgb (h, 1, .5, rgb);
  
  //Changes the color of NeoPixel Strip
  for (int i=0; i < NUMPIXELS; i++) {
      pixels.setPixelColor(i,rgb[0]*255,rgb[1]*255,rgb[2]*255);
      pixels.show();
     }    
  
  // maps current values to 0 to 99 for display
  int disTemp= map(temp, TEMP_LOW, TEMP_HIGH, 0, 99);
  int disMotor = map (doorMotor.read(), 0, 180, 0, 99);
  
  // updates the LCD with corresponding values 
  // in correct places
  lcd.clear();
  lcd.setCursor(0,0); 
  lcd.print((String)"i:" + disTemp);
  lcd.setCursor(6,0);
  lcd.print((String)"m:" + disMotor);
  lcd.setCursor(8,1);
  lcd.print(magnetMap);
  lcd.setCursor(12,1);
  //technically the color output but we map the magent
  //sensor 0-99 and use that directly to compute the RGB value
  //so the math would be the inverse so it make sense to just 
  //display the magnet map value becayse the inverse math functions 
  //would produce the same value
  lcd.print((String)"o:" + magnetMap);
  
  // updates the timer
  timer = millis();
  }
} 

// from https://gist.github.com/postspectacular/2a4a8db092011c6743a7
// expects hsv channels defined in 0.0-1.0 interval
//helps to convert HSV values to RBG values for the neopixel strip
float fract(float x) { return x - int(x); }
float mix(float a, float b, float t) { return a + (b - a) * t; }
float* hsv2rgb(float h, float s, float b, float* RBG) {
  RBG[0] = b * mix(1.0, constrain(abs(fract(h + 1.0) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s);
  RBG[1] = b * mix(1.0, constrain(abs(fract(h + 0.6666666) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s);
  RBG[2] = b * mix(1.0, constrain(abs(fract(h + 0.3333333) * 6.0 - 3.0) - 1.0, 0.0, 1.0), s);
  return RBG;
}

 

]]>
Project 1: A Double Transducer – Tilting Transduction https://courses.ideate.cmu.edu/60-223/f2020/work/project-1-a-double-transducer-tilting-transduction/ Thu, 08 Oct 2020 07:23:02 +0000 https://courses.ideate.cmu.edu/60-223/f2020/work/?p=11547 In our double transducer project, we took a light as input, transduced it to to a motor which affected a read of tilt. The tilt was then transduced once more to the rotational speed of a stepper motor output.

TinkerCad Circuit

Physical Overview

overhead view of Connor’s circuit

overhead view of Sruti’s circuit

Project Video

Notable Details

For the stepper motor, to make the rotational speed variations more obvious, we attached a popsicle stick to the rotating part of the motor.

Drawing a Marge Simpson on one side of the popsicle stick helps make movement even more obvious. In this setup, the stick is mounted with a small strip of magnetic tape.

The accelerometer is screwed onto the servo motor so that it rotates as the servo motor changes its angle, tilting the accelerometer.

To maximize the range of motion, in this setup the servo is mounted on a small deck of post-it notes. This keeps the mounted accelerometer and its related wires from dragging.

Simple Narrative Description

This project is a double transducer that converts light intensity into tilt which is then translated into rotational intensity. We use an LED which is connected to a potentiometer to vary the brightness of the LED, which is then read by a photoresistor. The photoresistor reading is then sent to a servo motor, whose angle is adjusted based on the input it gets. The accelerometer is attached to the servo and hence it also rotates with the servo, providing different tilt readings. These readings are then mapped to a stepper motor, whose rotation speed varies based on its input.

Progress Images

This image shows the first phase of our double transducer, the LED and a photoresistor which reads the light intensity.

This image shows the light intensity step which is then connected to a servo motor which is connected to the tilt sensor.

This shows the first and the last phases, light intensity and the stepper motor connected to the arduino.

This is an image that shows the entire circuit wired up, except for the LED screen.

Discussion

When we began working on this project, it sounded a lot more straightforward than it turned out to be. The light intensity step was quite easy and done very quickly. We did have a slight challenge with getting a large range of readings from the photoresistor, probably because the LED is not very bright and the background light contributes to a big part of the photoresistor’s reading. However, by adjusting the range of values from which the photoresistor readings are mapped to servo motor readings, we overcame the issue of very small angle change due to small change in photoresistor readings. 

The second main issue we faced was that the Servo motor and the stepper motor both would not function at the same time, and if they did, they wouldn’t function smoothly or properly. We later, after help from the professor, realized that this was due to a large amount of power consumption by the stepper motor, which doesn’t allow the two of them to function well together. However, we were unable to fix that error as we diagnosed the problem during the project presentation. In order to slightly improve the functioning of the two motors, we used the same trick as we used for the photoresistor, we mapped a smaller range of tilt values to a much larger range of stepper motor rotation speeds so that small incremental changes would still look bigger.

Overall, there was a lot we learned through this project. One of the main things was that physical parts don’t always work like they are supposed to. We don’t get readings as clearly and easily as we get through a simulation. It also made us realize how much more time it takes to make it work. In general, we went from knowing how to build a very basic circuit to a decently complicated double transducer through this project.

Schematic

Our circuitry schematic, rendered in Adobe Illustrator after a CircuitLab crash

Code

/*
 * Tilt Tranducer - Light -> Rotational Intensity
 *
 * Connor McGaffin (cmcgaffi) & Sruti Srinidhi (ssrinidh)
 * 
 * Description: The code below takes the readings from a photoresistor and maps 
 * it to an angle to which the servo motor rotates. As the servo motor rotates,
 * the accelerometer rotates as well and the code reads the accelerometer
 * readings and maps it to a rotational speed for the stepper motor, which
 * ultimately changes the rotational intensity.
 * 
 * Pin mapping:
 * 
 * pin   | mode   | description
 * ------|--------|------------
 * 2      input     lcd  
 * 3      output    servo motor 
 * 4      input     lcd
 * 5      input     lcd
 * 6      output    stepper motor
 * 7      output    stepper motor
 * 8      output    stepper motor
 * 9      output    stepper motor
 * 10     input     lcd
 * 11     output    LED output
 * 12     input     lcd
 * 13     input     lcd
 * A0     input     Accelerometer x-axis value
 * A1     input     Accelerometer y-axis value
 * A2     input     Accelerometer z-axis value
 * A5     input     Photoresistor value
 * 
 */

#include <Stepper.h>
#include <Servo.h>
#include <LiquidCrystal.h>

// Number of steps per revolution and step count for stepper motor
const int stepsPerRevolution = 200;
int stepCount = 0;


// initialize motors and LCD objects and their pins
Stepper myStepper(stepsPerRevolution, 6,7,8,9);
Servo tiltMotor;
LiquidCrystal lcd(13, 12, 10, 5, 4, 2);

//Initialize pin constants
const int xPin = A0;
const int yPin = A1;
const int zPin = A2;
const int LEDPIN = 11;
const int PHOTOPIN = A5;
const int SERVOTILTPIN = 3;
unsigned long timer = 0;
int photoVal;

void setup() {
  pinMode(LEDPIN, OUTPUT);
  pinMode(yPin, INPUT);
  pinMode(PHOTOPIN, INPUT);
  tiltMotor.attach(SERVOTILTPIN);
  lcd.begin(16, 2);
  Serial.begin(115200);
  Serial.setTimeout(50);
}

void loop() {
  
  int tiltAngle;
  int yPinVal;

  // Light write and read
  digitalWrite(LEDPIN,HIGH);
  photoVal = analogRead(PHOTOPIN);

  //Convert to angle of servo motor
  tiltAngle = map(photoVal, 500, 1000, 0, 180);
  tiltMotor.write(tiltAngle);

  //Read accelerometer
  yPinVal = analogRead(yPin);
  
  //Change rotational intensity of stepper motor
  int motorSpeed = map(yPinVal, 200, 1023, 0, 100);
  if (motorSpeed > 0) {
    myStepper.setSpeed(motorSpeed);
    myStepper.step(stepsPerRevolution / 100);
  }
  
  //Output details on LCD
  lcd.setCursor(0, 0);
  lcd.print("i:");
  lcd.setCursor(2,0);
  lcd.print(map(photoVal,0,1023,100,0));
  lcd.setCursor(5,0);
  lcd.print("m:");
  lcd.setCursor(7,0);
  lcd.print(map(tiltAngle, 0, 180, 0 ,100));
  lcd.setCursor(7,1);
  lcd.print(map(yPinVal, 300, 600, 0 ,100));
  lcd.setCursor(10,1);
  lcd.print("o:");
  lcd.setCursor(12,1);
  lcd.print(motorSpeed);

  delay(15);
}

 

 


 

]]>
Project 1: Double Transducer: Rotational Position to Light Intensity https://courses.ideate.cmu.edu/60-223/f2020/work/project-1-double-transducer-rotational-position-to-light-intensity/ Thu, 08 Oct 2020 00:15:43 +0000 https://courses.ideate.cmu.edu/60-223/f2020/work/?p=11401 by Arleen Liu and Jina Lee

An input taken from the rotational position of the potentiometer will determine the speed of a connected pancake vibration motor accordingly, whose vibration intensity will be read by a nearby accelerometer, which, in turn, takes those vibration readings and outputs an appropriate intensity for the output LED.

Screengrab of TinkerCAD:

Overall photo for proportion and scale:

An overall view of Arleen’s final physical circuit layout.

An overall view of Jina’s final physical circuit layout.

Detail photos of highlighted circuit aspects:

Our circuit input – a potentiometer for rotational position

A closer shot of the middle step in our circuit featuring the pancake motor and accelerometer

In order to keep the wires organized, used Pringles to cut in half to use as a holder. There is metal in the inside of the can, so had to layer paper between so there weren’t any random circulations of energy.

 

Videos of working circuits:

 

Due to not having a tripod, it was difficult to film without shaking.

Progress images:

The beginning stages of Arleen’s circuit – only the basic parts are wired up

Arleen’s circuit some more progress in the wiring featuring the addition of an accelerometer

Arleen’s circuit in it’s final stages of completion with only the LCD display left to wire up

In order to start, Jina found all the pieces so that there would not be any confusion later on.

Here is Jina’s progress as she starts to add more of the components onto the board.

At this time, the LED, accelerometer, pancake vibration motor, and potentiometer were connected. Jina now just has to add the LCD board!

Discussion:

Since this was the biggest and most complicated circuit we had built yet, the overall process, from ideation to building the simulation to actually wiring the circuit all presented novel obstacles for us to learn and grow from that will prepare us for future bigger projects.

During the ideation phase, we already encountered the struggle of being creative given the limited parts we were provided in the kit, and some of our ideas themselves were not viable or had errors in misunderstanding parts. For example, we had an idea to use the rotary encoder to somehow send electrical pulses and read it by a transistor as our circuit’s middle step, but upon receiving clarification for the actual functionality of a rotary encoder, we had to scrap that idea. In addition, going through the ideation process really opened our eyes to the vast array of input and output forms out in the world, something we would not have given thought before. In the end, we were able to implement an idea that exuded creativity, using vibration, while also having an element of simplicity to it that made it possible for us to build as beginners to electronics.

After settling on an idea for our circuit came a step that we were more familiar with: building the circuit in TinkerCAD. This step was definitely the most comfortable one for us, having built a few TinkerCAD circuits in class already for homework assignments. Most of this was a smooth process, especially the setup, but we did run into a few minor difficulties in dealing with the complexity of the wiring, especially for the LCD display, and researching how exactly the components were supposed to be wired up through other example TinkerCAD circuits. Coding the circuit was much of the same process as wiring – researching how to interact with the new components in code and encountering a few bugs from the complexity of the code relative to previous homework assignments.

For the physical building aspect, this step introduced an overall understanding of both the wiring and code. Before we physically started, there was some confusion about missing the pancake vibration motor due to its small size and placement in the kit. We had to briefly re-evaluate and figure out another option by using the stepper motor and offset magnets. Fortunately, we were able to find the pancake vibration motor which was hidden in a bag full of other small components. Once we were able to get all the parts, we started to configure the whole circuit. In order to connect the pancake vibration motor, we had to solder or tape them together which we choose later. Due to the inexperience of stripping wires, the pancake vibration motor ground was cut accidentally much shorter than the 5v wire. In the end, we were both able to successfully connect all of our components to the Arduino. Overall, it was crucial for us to organize the wires so that it would not get confusing and cause problems later on.

Schematic Diagram:

This is our schematic diagramming through CircuitLab.

Here is the original schematic drawing of our project.

Our code:

/*
 * Project 1: Double Transducer 
 * Arleen Liu and Jina Lee
 * 
 * Collaboration: RaspberryUser, a tinkerCAD designer, who helped 
 * us get a better understanding of how to connect the LCD display 
 * with a circuit. 
 * 
 * emumcu, a tinkerCAD designer, who helped us understand how to
 * connect LCD display with a potentiometer. This was helpful for us 
 * to see other ways to put connect the wirings together. 
 * 
 * Challenge: Figuring out how to wire all the components
 * properly and configuring code to translate inputs to 
 * outputs respectively.
 * 
 * Next Time: Look at more example Tinkercad circuits with parts
 * to learn how to work with them properly. Carefully and closely
 * look at our ciruits when error arises to fix. 
 * 
 * Description: An input is taken from the rotational potistion
 * of the potentiometer will determine the speed of a connected 
 * pancake vibration motor accordingly, whose vibration 
 * inteniy will be read by an accelerometer, which takes the 
 * vibation data and ouputs and intensity for the output LED.
 * 
 * Pin mapping: 
 * 
 * pin | mode | description
 * ----|------|------------
 * A0   INPUT  potentiometer
 * 9    OUTPUT red LED 
 * A1   INPUT  accelerometer 
 * A2   INPUT  accelerometer 
 * A3   INPUT  accelerometer 
 * 6    OUTPUT pancake vibration motor 
 * 5	OUTPUT DB4 LCD
 * 4	OUTPUT DB5 LCD
 * 3	OUTPUT DB6 LCD
 * 2	OUTPUT DB7 LCD
 * 12	OUTPUT RS LCD
 * 11	OUTPUT # LCD
*/ 

#include<LiquidCrystal.h>

const int POT_PIN = A0;
const int X_PIN = A3;
const int Y_PIN = A2;
const int Z_PIN = A1;
const int MOTOR_PIN = 6;
const int DB4 = 5;
const int DB5 = 4;
const int DB6 = 3;
const int DB7 = 2;
const int E = 11;
const int RS = 12;
const int LED_PIN = 9;

const int TIME_SCALE = 50;
const int a_max = 400;

// Volts per G-Force
const float sensitivity = 0.206;
long timer1 = 0, timer2 = 0;

LiquidCrystal lcd(RS, E, DB4, DB5, DB6, DB7);

void setup() {
  //Initializing pins
  pinMode(LED_PIN, OUTPUT);
  pinMode(POT_PIN, INPUT);
  pinMode(MOTOR_PIN, OUTPUT);
  analogReference(EXTERNAL);
  
  //Initializing other elements
  lcd.begin(16, 2);   
  Serial.begin(9600);
}

void loop() {

  //Reading input position value
  int potVal = analogRead(POT_PIN);
  
  //Converting to vibration
  int vTime = map(potVal, 0, 1023, 0, TIME_SCALE);
  
  //Controlling vibration intensity with potentiometer input
  if (millis() - timer1 >= (TIME_SCALE - vTime) 
      && millis() - timer1 <= TIME_SCALE) {
    digitalWrite(MOTOR_PIN, HIGH);
    Serial.println("registering");
  } else if (millis() - timer1 >= TIME_SCALE) {
  	digitalWrite(MOTOR_PIN, LOW);
    timer1 = millis();
  }
  
  float x;
  float y;
  float z;
  
  // Read acceleration pins and handle sensitivity
  x = (analogRead(X_PIN) - 512) * 3.3 / (sensitivity * 1023);
  y = (analogRead(Y_PIN) - 512) * 3.3 / (sensitivity * 1023);
  z = (analogRead(Z_PIN) - 512) * 3.3 / (sensitivity * 1023);
  
  //Reading acceleration
  int aDist = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));
  
  //Converting to light output
  int ins = map(aDist, 0, a_max, 0, TIME_SCALE);
  
  //Controlling light intensity with accleration input
  if (millis() - timer2 >= (TIME_SCALE - ins) && millis() - timer2 <= TIME_SCALE) {
    digitalWrite(LED_PIN, HIGH);
  } else if (millis() - timer2 >= TIME_SCALE) {
  	digitalWrite(LED_PIN, LOW);
    timer2 = millis();
  }
  
  //Scaling values for LCD display
  int i_scale = map(potVal, 0, 1023, 0, 99);
  int m1_scale = map(vTime, 0, TIME_SCALE, 0, 99);
  int m2_scale = map(aDist, 0, a_max, 0, 99);
  int o_scale = map(ins, 0, TIME_SCALE, 0, 99);
  
  // LCD display
  lcd.setCursor(0,0);
  lcd.print(String("i=") + i_scale);
  lcd.setCursor(6, 0);
  lcd.print(String("m:") + m1_scale);
  lcd.setCursor(8, 1);
  lcd.print(m2_scale);
  lcd.setCursor(12, 1);
  lcd.print(String("o=") + o_scale);
  lcd.print(millis() / 1000);

  delay(10);
}

 

 

 

 

]]>
Distance – Color – Sound Pitch https://courses.ideate.cmu.edu/60-223/f2020/work/distance-color-sound-pitch/ Wed, 07 Oct 2020 20:11:48 +0000 https://courses.ideate.cmu.edu/60-223/f2020/work/?p=11498 Title: Distance – Color – Sound Pitch Double Transducer

   

1. Final

2. Underside of the color wheel

 

Description: The project will take the distance measured by the ultrasonic sensor as an input, map the data to the rotational angle of servo which corresponds to different colors. The color sensor will then recognize the color that sits right above itself and output its R,G,B values. Arduino will then map the R value of the color to the pitch of the sound coming from the speaker. 

Progress: We initially had three ideas. The first one was Distance – Voltage – Sound Pitch, second one was Distance – Light Intensity – Sound Pitch, and the third one was the aforementioned Distance – Color – Sound Pitch scheme. 

The first option seemed most interesting to us so at first we decided to go with that, but in case it doesn’t work out we also decided to start working on the third scheme as a backup plan. 

Unfortunately, we couldn’t figure out how to work the generator within a reasonable amount of time – and so decided to go with the Distance – Color – Sound Pitch scheme. Turned out though, that wire was wrapped with a thin coat of enamel and we had to peel off its ends before connecting to other wires. 

The way this was going to work was a conductive material was going to be wrapped around a cylinder. The cylinder was to ensure the proper spacing within the magnetic field to enable the voltage to be generated. A thin rod was going to be pushed through a small hole in the tube with two magnets attached to the rod. In order to ensure the magnets stayed in place, two spacers were placed between the disc magnets and all of it was glued together. 

Side view of the generator. There are two magnets attached separated by two semicircles of foam.

Top view of the generator. Shows the 400 total wrappings of wire and the red LED attached. The clear rod is what is used to spin the magnet inside of the tube.

 

The design was inspired by a YouTube video by Prof. Melloch (https://www.youtube.com/watch?v=O5n6ubrbK5A&list=WL&index=38). The video describes this technique and shows the generator powering an LED. Because the generator produces an alternating current, the board system would need to be wired such that the one end of the wire goes into the ground and the other end goes into a diode which goes into the arduino board. How this was going to work was the distance from the ultrasonic sensor was going to then be turned into a value that was going into the DC motor as a speed, to turn it in one direction.The voltage amount could then be read and depending on the levels produced, would go towards the pitch. The closer the object, the faster the speeds, the higher the pitch. Move the object away, the speed will slowly decrease causing the pitch to get lower.

 

Back to the Distance – Color – Sound Pitch scheme

For mapping the distance, we used the ultrasonic sensor and the NewPing library to measure the distance between the sensor and the slider (made with a cardboard track along which you could move the paper panel). For outputting sound we used the piezo buzzer and the tone() function.  

More importantly this scheme required a color sensor – which wasn’t present in the Ideate Lab or the course kit – so we had to make one on our own! We referred to this website (https://www.instructables.com/Using-an-RGB-LED-to-Detect-Colours/) to make one using an RGB LED and a photoresistor. 

 

This color sensor was based on the fact that objects of certain colors will absorb the lights with the corresponding color spectrum. Red will absorb red lights, green will absorb red lights, and blue will absorb blue lights. And as a result, the intensity of the light when shone on a colored object will be less than when it’s shone on a white object (because these colors will absorb some of the lights whereas white would reflect all of them). Similarly, the intensity of the returning light shone on a black object will be lower than any other colored or white objects. 

So if we could measure the intensity of the lights returned by the black object and the white object, we could use them as a baseline to determine the color of the object that’s placed after. 

Following this idea we made a little container that would house the RGB LED light and a photoresistor where the colored object could be placed on top. The RGB LED will constantly blink red green and blue lights and each time it blinks the photoresistor will measure the light intensity of the returning red, green, and blue lights (after being shone to the object). We included the math in the code that would then translate this to the R, G, B values. 

 

Circuit Lab schematic. Custom parts were created in order to fulfill the space for the LCD, RGB LED, Servo Motor, and the Ultrasonic Sensor.

 

TinkerCad URL: https://www.tinkercad.com/things/5mjYhZFEZLF-smashing-turing/editel?sharecode=Hx0GhsKUVg7Llu1k5vD2kHo5FLbbgOpP2zSBgdz99OI

 

First attempt at making the color sensor 

Testing blue and red (note the RGB values on the serial monitor – pretty accurate!)

 

Final Videos:

Video Part 1: Calibration (color sensor measures the light intensity of white then black) 

Video Part 2: Double transducer at full work. The system automatically calibrates itself then starts working – split the video in half to upload them faster.

 

 

1. servo + color sensor combo. 

2. how the color wheel fits on the servo and the color sensor 

3. showing the inside of the color sensor (the shell is made of cardboard + black electrical tape to block out ambient light. On the inside there’s the RGB LED and a photoresistor)

 

Discussion: We were able to wire the individual components together relatively early in the project – US sensor to servo was working fine, and the color wheel to pitch was working fine. 

The problem developed when we were trying to connect the US sensor + servo part to the color wheel + pitch part. Upon compiling the code we kept getting the error that said: 

 

Collect2.exe: error: 1d returned 1 exit status

Exit status 1

Error compiling for board Arduino Uno.

Multiple definition definition of __vector 11_’

 

After an extensive research that took hours on end, we found out that it is because multiple devices were trying to use the same internal timer on Arduino. In this case, the tone() function and the NewPing Library were both using Timer 2. 

So what we decided to do was use a different tone function library – we found a couple called NewTone(), ToneAC(), and ToneAC2() that would provide the same result as a regular tone() function. 

But to our surprise (Not even at this point – seemed like everything that could go wrong was going wrong) this time, these new tone libraries were using Timer 1, which was the same timer that the servo library was using and we got this error message: 

 

Collect2.exe: error: 1d returned 1 exit status

Exit status 1

Error compiling for board Arduino Uno.

Multiple definition definition of __vector 7_’

 

Extremely frustrated, I started looking for libraries that did not use the timer that could replace either the NewPing, servo or the tones() mentioned above. And I came upon this thing called TimerFreeTone library – which did not use the timer! But when I ran the code the speaker didn’t make a continuous sound – it just beeped for a little after the Arduino had run all the other functions than the TimerFreeTone. And because there was a delay between the tones while the color wheel was moving – the pitch wasn’t really updating on time. 

I later noticed that all the explanations that were posted online said the NewPing ‘LIBRARY’ used the Timer – so I wondered if you had written the code yourself the tone() would work. And we did come upon a post that said both would work at the same time if you wrote the US sensor code from scratch  after which we did write the code for the US sensor ourselves  with the help from (https://create.arduino.cc/projecthub/Isaac100/getting-started-with-the-hc-sr04-ultrasonic-sensor-036380) and it worked!

Another minor problem we had came from the color sensor. It’s a makeshift color sensor so the RGB values that we were getting weren’t perfect. Even when the servo wasn’t rotating the pitch kept shifting a little (though within a small range). The fact that we painted the color wheels ourselves and the coat wasn’t consistently thick could have also contributed to this. But once you waited a little the pitch became relatively stable. Also we noticed that the servo wasn’t quickest to react at times – which made . We experimented with inserting and deleting delays at certain parts of the code and at the end it was working pretty smoothly. 

Other issues were derived from working with the L293D component towards the early stages of the design prototyping process. It was more a function of figuring out how to properly wire a motor to it to ensure the desired outcome. With trial and error, we were able to figure it out without pulling out too many hairs. The main source of this was derived from finding a model that only had one motor versus two motors attached to the L293D chip. We experienced an error that was saying there was a power imbalance for the chip and I did not know what that meant. But again, trial and error and looking for references to consult, we succeeded. 

 

The LCD was also not cooperating perfectly during testing. We were finding some of the characters being displayed were not even English. This created quite the havok as we were attempting to resolve one issue after the other just to get a general gauge of where we were in the project. Like all things, after consulting Google for a little, we found a source that was saying the LCD sometimes just needs to be unplugged and plugged back in, a simple solution to almost every electronics problem. 

 

Code:

/*

 * Project 1

 * Claire Koh, Carl Young

 * two weeks

 *

 * Collaboration: Between Claire Koh and Carl Young

 * RGB LED & Photoresistor Color sensor tutorial from: 

 * https://www.instructables.com/Using-an-RGB-LED-to-Detect-Colours/

 * Ultrasonic Sensor code from scratch:

 * https://create.arduino.cc/projecthub/Isaac100/getting-started-with-the-hc-sr04-ultrasonic-sensor-036380

 * 

 * Challenge: Timer Issue: NewPing Library, Servo Library and Tone() function all use Arduino Timer

 * Tone() and NewPing use Timer 2

 * NewTone(), ToneAC, ToneAC2 and Servo uses Timer 1

 * TimerFreetone doesn’t let out continuous tone

 * Solution: Wrote the NewPing code from scratch instead of using NewPing to get rid 

 * of the timer conflict

 * 

 * RGB LED + Photoresistor Color Detector wasn’t perfect 

 * – wasn’t able to get the perfect RGB values 

 * but they were relatively in range and did change according to the colors

 * Solution: mapped the value to 0-255. Wait it out and the pitch becomes pretty consistent

 * Servo – sometimes isn’t the quickest to react. Needs time to rotate

 * Solution: delays or no delays at right spots

 * 

 * Next time: We won’t be running into these timer problems

 * because now we know which library uses which timer. 

 * We will also try a little bit harder to find out why the

 * generator was not working to hopefully not give up on an

 * idea too quickly.

 * 

 * Description: The code below uses the ultrasonic sensor to 

 * map the distance between itself and a movable panel

 * which will be mapped to the servo angle that turns the color wheel

 * that is placed on top of the color wheel

 * Then the color sensor will read the RGB values of the color 

 * placed directly on top of it

 * Ardiuino will then translate the R value to the pitch of the sound

 * coming from the piezo buzzer.

 * 

 * Pin mapping:

 * 

 * pin   | mode   | description

 * ——|——–|————

 * A0     output    D7 pin LCD

 * A1     output    D6 pin LCD

 * A2     input     Photoresistor pin

 * A3     output    D5 pin LCD

 * A4     output    D4 pin LCD

 * 4      output    piezo buzzer

 * 6      output    Enabling pin LCD

 * 7      output    servo

 * 8      output    Blue for RGB LED

 * 9       output    Green for RGB LED

 * 10    output    Red for RGB LED

 * 11      output    Trigger Pin for Ultrasonic sensor

 * 12     input     Echo Pin for Ultrasonic sensor

 * 13     input     Register Select pin LCD

 * 

 */

 

#include <Servo.h>

#include<LiquidCrystal.h>

 

// System 1 Pins

const int TRIGGER_PIN = 11;  // Arduino pin tied to trigger pin on the ultrasonic sensor.

const int ECHO_PIN  = 12;  // Arduino pin tied to echo pin on the ultrasonic sensor.

const int MAX_DISTANCE = 30; // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

 

// System 2 Pins

const int R_LED_PIN = 10;

const int G_LED_PIN = 9;

const int B_LED_PIN = 8;

const int SERVO_PIN = 7;

const int PHOTORESISTORPIN = A2;

 

// System 3 Pins

const int SPEAKER_PIN = 4;

 

// LCD Pins

const int RSPIN = 13;

const int EPIN = 6;

const int D4PIN = A4;

const int D5PIN = A3;

const int D6PIN = A1;

const int D7PIN = A0;

 

const unsigned long WAIT = 500;

unsigned long timer;

 

int inVal, outVal;

 

int ledArray[] = {R_LED_PIN,G_LED_PIN,B_LED_PIN};

boolean balanceSet = false;

 

int red = 0;

int green = 0;

int blue = 0;

 

long colorArray[] = {0,0,0};

long whiteArray[] = {0,0,0};

long blackArray[] = {0,0,0};

 

int avgRead;

 

long duration;

long distance;

 

Servo servoMotor; 

LiquidCrystal lcd(RSPIN,EPIN,D4PIN,D5PIN,D6PIN,D7PIN);

 

void setup() {

  Serial.begin(115200); 

  Serial.setTimeout(50);

  

  lcd.begin(16,2);

  lcd.setCursor(0,0);

  lcd.print(“i:”);

  lcd.setCursor(6,0);

  lcd.print(“m:”);

  lcd.setCursor(12,1);

  lcd.print(“o:”);

 

  

  pinMode(R_LED_PIN, OUTPUT);

  pinMode(G_LED_PIN, OUTPUT);

  pinMode(B_LED_PIN, OUTPUT);

  pinMode(PHOTORESISTORPIN, INPUT);

 

  pinMode(TRIGGER_PIN,OUTPUT);

  pinMode(ECHO_PIN,INPUT);

 

  pinMode(SERVO_PIN, OUTPUT);

  pinMode(PHOTORESISTORPIN, INPUT);

  pinMode(SPEAKER_PIN, OUTPUT);

 

  servoMotor.attach(SERVO_PIN);

}

 

void loop() {

  checkBalance();

  checkColor();

  printColor();

 

  // Clears the trigPin condition

  digitalWrite(TRIGGER_PIN, LOW);

  delayMicroseconds(2);

  // Sets the trigPin HIGH (ACTIVE) for 10 microseconds

  digitalWrite(TRIGGER_PIN, HIGH);

  delayMicroseconds(10);

  digitalWrite(TRIGGER_PIN, LOW);

  // Reads the echoPin, returns the sound wave travel time in microseconds

  duration = pulseIn(ECHO_PIN, HIGH);

  // Calculating the distance

  distance = (duration * 0.0342) / 2; // Speed of sound wave divided by 2 (go and back)

  Serial.println(distance);

  if(distance>=MAX_DISTANCE){    // Caps the value for distance at 200

    distance = MAX_DISTANCE;

  }

  //delay(400);

 

  //int realdistance = map(distance, 0, , 0, MAX_DISTANCE);

  

  

 

  //int realdistance = map(distance, 0, 255, 0, MAX_DISTANCE);

  //LCD PRINTING FOR THE ULTRASONIC SENSOR

  int newDist = map(distance,0,MAX_DISTANCE,0,99);

  if(newDist<10){

    lcd.setCursor(2,0);

    lcd.print((String)”0″+newDist);

  }

  else{

    lcd.setCursor(2,0);

    lcd.print(newDist);

  }

  

                       

  //Maps the distance to the servo angle

  int servoangle = map(distance, 0, MAX_DISTANCE, -180, 180);

  servoMotor.write(servoangle);

 

  //LCD PRINTING FOR THE COLOR WHEEL (1)

  int newAngle = map(servoangle,-180,180,0,99);

  if(newAngle<10){

    lcd.setCursor(8,0);

    lcd.print((String)”0″+newAngle);

  }

  else{

    lcd.setCursor(8,0);

    lcd.print(newAngle);

  }

 

  //if (colorArray[0] <= 0) {

    //colorArray[0] = 0;

  //}

 

  // LCD PRINTING FOR THE COLOR WHEEL (2)

  int realColor = map(colorArray[0], -500, 500, 0, 255);

  int newColor = map(realColor,-500,500,0,99);

  if(newColor<10){

    lcd.setCursor(8,1);

    lcd.print((String)”0″+newColor);

  }

  else{

    lcd.setCursor(8,1);

    lcd.print(newColor);

  }

  

  int pitch = map(realColor, 0, 255, 200, 800);

  tone (SPEAKER_PIN, pitch);

  //delay(100);

 

  //LCD PRINTING FOR THE SPEAKER

  int newPitch = map(pitch,200,800,0,99);

  if(newPitch<10){

    lcd.setCursor(14,1);

    lcd.print((String)”0″+newPitch);

  }

  else{

    lcd.setCursor(14,1);

    lcd.print(newPitch);

  }

  Serial.println((String)”newDist: “+newDist);

  Serial.println((String)”newColor: “+newColor);   

  Serial.println((String)”newAngle: “+newAngle);  

  Serial.println((String)”newPitch: “+newPitch);

 

  Serial.println(newPitch);

}

 

//For MQTT Monitor

  if (millis() – timer > WAIT) {

    outVal = newPitch;

    //transmitSerialSignal();

    timer = millis();

  }

 

void checkBalance() { //check if the balance has been set, if not, set it

  if (balanceSet == false) {

    setBalance();

  }

 }

 

void setBalance() {

  //set white balance

  servoMotor.write(0);

  delay (5000); //delay for five seconds, this gives us time to get a white sample in front of our sensor

  //scan the white sample.

  //go through each light, get a reading, set the base reaing for each color red, green, and blue to the white array

  for (int i = 0; i<= 2; i++){

    digitalWrite(ledArray[i], HIGH);

    delay(100);

    getReading(5); //number is the number of scans to take for average, this whole function is redundant, one reading works just as well.

    whiteArray[i] = avgRead;

    digitalWrite(ledArray[i], LOW);

    delay(100);

  }

    //done scanning white, now it will pulse blue to tell you that it is time for the black (or grey) sample.

    

  //set black balance

  servoMotor.write(50);

  delay (5000); // wait for five seconds so we can position our black sample

  // go ahead and scan, sets the color values for red, green, and blue when exposed to black

  for (int i = 0; i <=2; i++){

    digitalWrite(ledArray[i], HIGH);

    delay(100);

    getReading(5);

    blackArray[i] = avgRead;

    digitalWrite(ledArray[i],LOW);

    delay(100);

  }

 

  balanceSet = true;

  delay(5000); //delay another 5 seconds to let us catch up

}

 

void checkColor() {

  for (int i =0; i<=2; i++){

    digitalWrite(ledArray[i],HIGH); //turn on the LED, red, green or blue depending which iteration

    delay(100);

    getReading(5);

    colorArray[i] = avgRead; //set the current color in the array to the average reading

    float greyDiff = whiteArray[i] – blackArray[i]; 

    //the highest possible return minus the lowest returns the area for values in between

    colorArray[i] = (colorArray[i] – blackArray[i])/(greyDiff)*255; 

    //the reading returned minus the lowest value divided by the possible range multiplied by 255 

    //will give us a value roughly between 0-255 representing the value for the current reflectivity

    //(for the color it is exposed to) of what is being scanned

    digitalWrite(ledArray[i],LOW); //turn off the current LED

    delay(100);

  }

}

 

void getReading(int times){

  int reading;

  int tally = 0; //take the reading however many times was requested and add them up

  for (int i = 0; i<times; i++){

    reading = analogRead(PHOTORESISTORPIN);

    tally = reading + tally;

    delay(10);

  }

  //calculate the average and set it

  avgRead = (tally)/times;

  }

 

//prints the color in the color array, in the next step, we will send this to processing to see how good the sensor works.

void printColor(){

  Serial.print(“R=”);

  Serial.print(int(colorArray[0]));

  Serial.print(“G=”);

  Serial.print(int(colorArray[1]));  

  Serial.print(“B=”);

  Serial.println(int(colorArray[2]));

}

 

void serialEvent(){

  /*  You do *not* need to call this function in your loop;

      it is a special function that will run whenever serial

      data flows into the Arduino. */

  

  /*  The function assumes your machine’s input value 

      is called “inVal” (change that variable name as needed) */

 

//For MQTT Monitor  

//If there is incoming serial data, read it

  while (Serial.available() > 0){

    // interpret incoming digits as integer and save into inVal

    inVal = Serial.parseInt();

  }

}

 

]]>
Double Transducer Documentation – Light Intensity to Rotational Position https://courses.ideate.cmu.edu/60-223/f2020/work/double-transducer-documentation-light-intensity-to-rotational-position/ Tue, 06 Oct 2020 02:27:13 +0000 https://courses.ideate.cmu.edu/60-223/f2020/work/?p=11425

Dani’s final circuit with labels

Evan’s Final Circuit

CIRCUIT OVERVIEW

For this Double Transducer project, we were given the initial input our circuit must read and the final output that it must produce as a result. We were left to decide on what the middle step would be. We explored a few different ideas at the start – perhaps color or sound could be an interesting middle step! However, after talking to Zach we quickly realized that these concepts involve a lot of complications as a middle step, leaving room for error and inconsistency when testing the circuit, so we moved away from those ideas fairly quickly. The final idea we landed upon was a fluctuating magnetic field!

Initially, we wanted the magnetic field to fluctuate by creating an electromagnet and then controlling the amount of current going through it using the Arduino to change the power of the generated magnetic field. This ultimately didn’t work, most likely due to our wires lacking the resistance necessary to generate a powerful enough field, and so we pivoted and instead made the magnetic field force “fluctuate” by moving a magnet closer and further away from the magnetometer using a servo motor. The final input-output flow goes as such:

The amount of light in a given space is received by a photoresistor. This value then changes the position of a magnet by adjusting the angle of the servo arm it’s attached to. A magnetometer reads the changing magnetic field value due to the movement of the magnet and this value is then used to adjust the rotational position of a final servo motor arm (which has a popsicle stick attached to it for emphasis!)

STEPS TO COMPLETION

Once we decided on what we wanted our final input-output chain to be, it was time to begin the tough part of the project – actually getting it to work in the way that we wanted it to.  We started with a few haphazard experiments that covered a broad range of design problems we wanted to tackle during our first, in-class, meetings but this strategy left me feeling a bit all over the place and ambivalent since we weren’t making notable progress. However, we soon switched our approach to be a more singular problem based and we got into a better progress groove. We started by tackling one of the two big unknowns: the magnetometer. Neither of us had used this sensor before and so we wanted to understand how it works (physically and code-wise) before tackling circuit components we were more familiar with.

Testing the magnetometer and wiring

Then, we began to look at the other primary unknown and an area of uncertainty: namely the electromagnet component and the LCD screen. While Evan worked on the electromagnet and trying to resolve the wiring and code associated with that, Dani began to figure out the wiring and code for the LCD screen which was a bit different to years prior (since our LCD displays didn’t have the same “backpack” that was described in the course documentation).

Dani encountered some minor wiring errors and code errors (formatting wise) while trying to get the display to work. In the end, however, the biggest challenge about the display was the sheer amount of wires needed to hook it up leading to visual clutter and physical debugging issues. That and the fact that there was a while when Dani didn’t understand why she wasn’t getting a display with my code and wiring seemingly correct (it turned out to be a simple potentiometer contrast issue in the end).

LCD not displaying information before a round of debugging

Final circuit closeup with functional LCD feedback

After wiring up the LCD screen and making sure the feedback was working properly (with pseudo-output numbers to start before we wired up the other sensors. Once the other sensors were wired and coded, their output values were placed into the LCD code’s variables), Dani began to construct the rest of the circuit. She started with the photoresistor wiring and then moved onto the servo motor while Evan worked on the coding elements.

Wired photoresistor on another breadboard for neatness

Circuit with the wired output servo moto, LCD screen, and magnetometer

Magnet attached to a second servo motor for testing. This attachment was later removed en lieu of a popsicle stick that I painted like a magnet

Final circuit construction

CHALLENGES AND DISCUSSION

  • Wiring leading to visual clutter and debugging issues
    • By wiring the LCD screen and magnetometer first, Dani cluttered up the breadboard from the get-go, thus making it harder to accurately place the servo motor and photoresistor pins. She added a second breadboard to the circuit to declutter the wires a bit more (along with adding a clearer sequential layout to the circuit by having the photoresistor as its own element). When it came to debugging the circuit, it took a while to trace the wires back to each pin they were connected to ensure that they were properly places and so, in the future, implementing a more strategic wiring method may prove to be useful.
  • Scope issues for variable declaration
    • When testing our code, we encountered several issues related to our variables – we had renamed some of them to provide better clarity as to what they do, but didn’t change all instances of that variable which lead to many snags along the way. While debugging these was fairly easy as we just had to scan the code to find the misnamed instances, ensuring to complete this full scan and check each time a variable is renamed would prevent some headaches.
  • Changing ideas and rewriting code based on these changes
    • This wasn’t a full challenge, but as our project developed and we pivoted from more complex ideas to ones that were more feasible within the time scope of our project, it was a bit tricky to correctly adjust only certain parts of the code. Knowing what code to write is once thing, but being thorough and ensuring that everything that needs to be adjusted has been changed and that there are no extraneous variables or residual code can be tricky.
  • Electromagnet creation
    • As mentioned in the above sections, we attempted to create an electromagnet that we could control the magnetic field instead of utilizing a normal bar magnet within our project. In the end, we had to shift to the bar magnet as we ran into too many issues with the electromagnet – we wish we could have tried some other wire coils to see if the different wire resistances made any difference for how the magnet functioned, but, the deciding factors of time and current access to resources left us to down-shift towards a standard magnetic interaction. Nevertheless, we still learned a lot about the use of a magnetometer and how to get different sensors to affect each other through this project and so we consider the learning outcomes to be a success no matter what.
    • The attempt at making an electromagnet.

SCHEMATIC

CODE

 

/*
* Project 1
* Dani Delgado (ddelgad1) and Evan Tipping (eftippin)
*
* Collaboration: The basic collaboration for this project was with eachother and asking our professor, Robert  *Zacharias, questions 
* relating to the sensors we were using and the Arduino code libraries that helped us to use them effectively. 
* Beyond this, we used TinkerCAD's simulator to understand the proper LED wiring and basic sample code. 
*
* Challenge: We tried to make an electromagnet to use for this project instead of moving a standard magnet with a motor, but in the end 
* we couldn't make a magnet with a powerful enough current to be detected by the mangetometer due to the wires we were using (low resitance is suspected).
* We overcame the problems that arose as a group by playing to our strengths - I worked towards the wiring and visual completion of the circuits while 
* Evan worked on debugging the code. 
*
* Next time: Virtual collaboration can be a bit tricky (expecially when sharing our physical circuit components and trying to debug eachother's 
* work) but now that I have some practice, I think that I can improve this work flow. Furthermore, next time I will learn from my wiring mistakes 
* and code blunders from this project, and apply more stratigic techniques when it comes to order of what to do (i.e. wiring the more complec components last 
* and debugging as I go rather than building it all and debugging it all at once). 
*
* Description: The code below reads the intensity of incoming light using a photo resistor. This value then changes the position of a magnet by adjusting 
* the angle of a servo motor. A magnetometer reads the changing magnetic field value due to the movement of the magnet and this value is then used to 
* adjust the rotational position of a final servo motor arm. 

* Pin mapping:
*
* pin   | mode   | description
* ------|--------|------------
* 8     | output | output for the servo motor affected by the brightness value of the photoresitor  
* 6     | output | output for the servo motor affected by the magnetic field
* A0    | input  | photoresitor input 
* 11    |        | RS pin on LCD
* 12    |        | E pin on LCD
* 5     |        | D4 pin on LCD
* 4     |        | D5 pin on LCD
* 3     |        | D6 pin on LCD
* 2     |        | D7 pin on LCD
*
*/

#include <Servo.h>
#include <LiquidCrystal.h>
#include <QMC5883LCompass.h>

// This turns out to be an angle controlling a lodestone's pos
const int PHO_MIN = 0;
const int PHO_MAX = 1023; 
const int MAG_OUT_MIN = 75;
const int MAG_OUT_MAX = 105;
const int MAG_IN_MIN = 0;
const int MAG_IN_MAX = 4000;
const int SRV_MIN = 0;
const int SRV_MAX = 180;

// Pin assignment
const int EMGPIN = 8;
const int SRVPIN = 6;
const int PHOPIN = A0;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Variables for the screen display
int disp_pho_input;
int disp_mag_output;
int disp_mag_input;
int disp_srv_output;

unsigned long timer = 0;
const unsigned long WAIT = 500;

// Init Servos
Servo output_motor;
Servo magnet_motor;

// Init compass
QMC5883LCompass compass;

void setup(void) {
  //for communication 
  Serial.begin (115200);
  Serial.setTimeout(50);
  
  // Input 1
  pinMode(PHOPIN, INPUT);
  // Output 1
  magnet_motor.attach(EMGPIN);
  // Input 2
  compass.init();
  // Output 2
  output_motor.attach(SRVPIN);
  
  lcd.begin(16, 2);
}

int get_bright() {
  int bright_in = analogRead(PHOPIN);
  disp_pho_input = map(bright_in, 0, 1023, 0, 99);
  return bright_in;
}

int bright_to_mag_str(int bright_in) {
  // Takes brightness and converts it to magnetic field strength
  int strength_out = map(bright_in, PHO_MIN, PHO_MAX, MAG_OUT_MIN, MAG_OUT_MAX);
  disp_mag_output = map(strength_out, MAG_OUT_MIN, MAG_OUT_MAX , 0, 99);
  return strength_out;
}

int mag_str_to_angle(int strength_in) {
  int angle = map(strength_in, MAG_IN_MIN, MAG_IN_MAX, SRV_MIN, SRV_MAX);
  disp_srv_output = map(angle, SRV_MIN, SRV_MAX , 0, 99);
  return angle;
}

void write_strength(int strength_out) {
  magnet_motor.write(strength_out);
}

int read_strength(){
  compass.read();
  int y = compass.getY()/10;
  disp_mag_input = map(y, MAG_IN_MIN, MAG_IN_MAX , 0, 99);
  return abs(y);
}

void angle_to_output(int angle) {
  output_motor.write(angle);  
}

void loop() {
  int bright_in = get_bright(); // Hiding the actual acquisition
  int strength_out = bright_to_mag_str(bright_in);
  write_strength(strength_out);
  
  // Separate by write + read to magnet
  
  int strength_in = read_strength();
  int angle = mag_str_to_angle(strength_in);
  angle_to_output(angle);
  
  //LCD screen feedback 
  lcd.print((String)"i:" + disp_pho_input);

  lcd.setCursor(6, 0);
  lcd.print((String) "m:" + disp_mag_output);
  
  lcd.setCursor(8, 1);
  lcd.print(disp_mag_input);

  lcd.setCursor(12, 1);
  lcd.print((String) "o:" + disp_srv_output); 

  delay(500);

  //communication loop
  if (millis() - timer > WAIT){
    int angle = mag_str_to_angle(strength_in);
    angle_to_output(angle); 
       timer = millis(); 
       Serial.println(angle);
  }
}

void serialEvent(){
  /*  You do *not* need to call this function in your loop;
      it is a special function that will run whenever serial
      data flows into the Arduino. */
  
  /*  The function assumes your machine's input value 
      is called "inVal" (change that variable name as needed) */

  // if there is incoming serial data, read it
  int bright_in = analogRead(PHOPIN);
  while (Serial.available() > 0){
    // interpret incoming digits as integer and save into inVal
    bright_in = Serial.parseInt();
  }
}

 

 

PRESENTATION SLIDES

The final section of this documentation is the presentation slides that were shared in class to overview our project’s capabilities and discuss the challenges we faced along the way. These slides can act as a TLDR for this documentation page, as they do not provide any additional in-depth information or personal thoughts about the project process.

   

 

]]>