Description
This double transducer is designed to convert light intensity to magnetic field strength, which in turn is converted to rotational speed. The photocell on the far left side of the stage measures surrounding light intensity. This value is then inputted into a 180-degree hobby servo motor that moves the attached magnet to different angle values. At higher light intensity, the magnet is at a lower position angle and is thus closer to the triple-axis magnetometer positioned in the middle of the breadboard. At lower light intensity, the magnet is positioned farther away from the compass. Only the magnetic field strength in the y-axis is measured because of the more linear correlation between the readings in the y-axis and the servo’s angle position. The magnetic field value then serves as an input for the 360-degree servo motor positioned at the far right of the stage. The rotational speed of the 360-degree servo motor increases as the magnet gets closer to the compass and the magnetic field strength is greater. Thus, increasing light intensity on the left side of the stage increases the rotational speed on the far right side.

Top view of Double Transducer: Light Intensity -> Magnetic Field -> Rotational Speed

Light intensity input values are obtained using a photoresistor

I2C LCD displays the input and output values of the double transducer

The servo with the magnet attached adjusts its position depending on light intensity. Position is measured using a triple-axis compass.

Position of the magnet varies the rotational speed of this 360 hobby servo.
Progress Images

Project before components were positioned onto the board.

The first few components are zip tied to the board.

Wires are rearranged because the LCD was facing the wrong decision.

Battery is added so that it doesn’t rely on a laptop.
Discussion
Working with some of the components were easy, as we had worked with them before. We had no problems working with the photoresistor or servo motors. The challenge came from working with the magnetometer. Neither of us had ever worked with a compass before. Learning how it worked required research, and finding the right library was a difficult process. The library we initially found was unnecessarily complicated and only worked part of the time. It required a lot of fiddling with to determine what exactly was the problem. Figuring out how a new component worked and finding an appropriate library for the device was a new experience for us.
The project required a lot of tweaking to the maximum and minimum values in our code. Ensuring the inputs never went out of range and that the outputs were exactly what we wanted required us to constantly make slight edits and see how that affected the project. In addition to that, we had to make temporary code to test the range of values. Slight shifts in max and min values completely changed the rotation speed output, requiring us to carefully puzzle out the perfect range. The process gave us a new appreciation for constants in our code and valuable experience in testing a project.
Schematic

Code
/*
Project 1: Light Intensity to Rotation Speed
Leah Walko
Gracia Genero
Description: A double transducer that turns light intensity into
magnetic fields into rotation speed. A photoresistor picks up the
intensity of the light. That value changes the location of a magnet.
In turn, this affects the magnetic fields read by a compass, and based
off that value a servo motor rotates at a faster or slower speed.
Credit: QMC5883LCompass library creator, MRPrograms, for their xyz
example code, and to the course's lectures and website.
Pin mapping:
pin | mode | description
------|--------|--------------------------------------------
A1 | input | photocell to measure light intensity
A4 | input | triple axis compass SDA input
A5 | input | triple axis compass SCL input
10 | output | Servo motor that moves the magnet around
11 | output | 360 degrees servo motor with variable rotation speed
SCL | output | I2C LCD
SDA | output | I2C LCD
*/
// servo library
#include <Servo.h>
// compass and lcd libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <QMC5883LCompass.h>
// pin values
const int PHOTOPIN = A1;
const int MOTORMAGPIN = 10;
const int MOTORPIN = 11;
// range of possible values
const int ROTVAL_MAX = 89;
const int ROTVAL_MIN = 0;
const int MAGANGLE_MAX = 50;
const int MAGANGLE_MIN = 0;
const int LIGHT_MAX = 1023;
const int LIGHT_MIN = 0;
const int MAGVAL_MAX = 2700;
const int MAGVAL_MIN = -7500;
// timer for updating LCD
const int INTERVAL = 1000;
unsigned long timer = 0;
// LCD values
int screenInput = 0;
int screenMInput = 0;
int screenMOutput = 0;
int screenOutput = 0;
// compass values
int x;
int y;
int z;
// motor objects
Servo magnetMotor; // create a motor "object" called magnetMotor
Servo rotatingMotor; // create a motor "object" called rotatingMotor
// compass and LCD objects
QMC5883LCompass compass; // create a compass "object" called compass
LiquidCrystal_I2C screen(0x27, 16, 2); // create a LCD "object" called screen
void setup() {
// setup the screen
screen.init();
screen.backlight(); // turn on the backlight to start
screen.home(); // set cursor to home position
screen.print("i:"); // print out the unchanging parts of the values
screen.setCursor(6, 0);
screen.print("m:");
screen.setCursor(12, 1);
screen.print("o:");
delay(2000); // do nothing for 2 seconds
// setup the input pin -> photocell
pinMode(PHOTOPIN, INPUT);
// Initializing compass
compass.init();
// setup the output -> motor moving the magnet + motor rotating
magnetMotor.attach(MOTORMAGPIN);
rotatingMotor.attach(MOTORPIN);
rotatingMotor.write(90);
Serial.begin(9600);
}
void loop() {
// get info on light intensity
int lightVal = analogRead(PHOTOPIN);
// calculate the location of the magnet and move the motor to that angle
int magAngle = map(lightVal, LIGHT_MIN, LIGHT_MAX, MAGANGLE_MIN, MAGANGLE_MAX);
magnetMotor.write(magAngle);
// get the compass value
// Read compass values
compass.read();
// Return XYZ readings from the compass
x = compass.getX();
y = compass.getY();
z = compass.getZ();
// calculate magnetic value
int magVal = y;
// calculate rotation speed
int rotateVal = map(magVal, MAGVAL_MIN, MAGVAL_MAX, ROTVAL_MIN, ROTVAL_MAX);
// servo rotates at a speed of rotateVal (0 is faster, 90 is slower)
rotatingMotor.write(rotateVal);
// Update LCD screen values
screenInput = map(lightVal, LIGHT_MIN, LIGHT_MAX, 0, 99);
screenMInput = map(magAngle, MAGANGLE_MIN, MAGANGLE_MAX, 0, 99);
screenMOutput = map(magVal, MAGVAL_MIN, MAGVAL_MAX, 0, 99);
screenOutput = map(rotateVal, ROTVAL_MIN, ROTVAL_MAX, 0, 99);
// Display updated LCD screen values only at specific time intervals
if (millis() >= timer) {
// print light val input
screen.setCursor(2, 0);
screen.print(screenInput);
// print the magnetic field output value
screen.setCursor(8, 0);
screen.print(screenMInput);
// print the magnetic field input value
screen.setCursor(8, 1);
screen.print(screenMOutput);
// print the rotation speed output value
screen.setCursor(14, 1);
screen.print(screenOutput);
// reset timer
timer = millis() + INTERVAL;
// serial output for testing purposes
Serial.println((String)"X: " + x +
"; Y: " + y +
"; Z: " + z);
Serial.println((String)"room brightness: " + lightVal +
"; magVal: " + magVal +
"; rotateVal: " + rotateVal +
"; magAngle: " + magAngle );
}
}
- /*
- Project 1: Light Intensity to Rotation Speed
- Leah Walko
- Gracia Genero
- Description: A double transducer that turns light intensity into
- magnetic fields into rotation speed. A photoresistor picks up the
- intensity of the light. That value changes the location of a magnet.
- In turn, this affects the magnetic fields read by a compass, and based
- off that value a servo motor rotates at a faster or slower speed.
- Credit: QMC5883LCompass library creator, MRPrograms, for their xyz
- example code, and to the course's lectures and website.
- Pin mapping:
- pin | mode | description
- ------|--------|--------------------------------------------
- A1 | input | photocell to measure light intensity
- A4 | input | triple axis compass SDA input
- A5 | input | triple axis compass SCL input
- 10 | output | Servo motor that moves the magnet around
- 11 | output | 360 degrees servo motor with variable rotation speed
- SCL | output | I2C LCD
- SDA | output | I2C LCD
- */
- // servo library
- #include <Servo.h>
- // compass and lcd libraries
- #include <Wire.h>
- #include <LiquidCrystal_I2C.h>
- #include <QMC5883LCompass.h>
- // pin values
- const int PHOTOPIN = A1;
- const int MOTORMAGPIN = 10;
- const int MOTORPIN = 11;
- // range of possible values
- const int ROTVAL_MAX = 89;
- const int ROTVAL_MIN = 0;
- const int MAGANGLE_MAX = 50;
- const int MAGANGLE_MIN = 0;
- const int LIGHT_MAX = 1023;
- const int LIGHT_MIN = 0;
- const int MAGVAL_MAX = 2700;
- const int MAGVAL_MIN = -7500;
- // timer for updating LCD
- const int INTERVAL = 1000;
- unsigned long timer = 0;
- // LCD values
- int screenInput = 0;
- int screenMInput = 0;
- int screenMOutput = 0;
- int screenOutput = 0;
- // compass values
- int x;
- int y;
- int z;
- // motor objects
- Servo magnetMotor; // create a motor "object" called magnetMotor
- Servo rotatingMotor; // create a motor "object" called rotatingMotor
- // compass and LCD objects
- QMC5883LCompass compass; // create a compass "object" called compass
- LiquidCrystal_I2C screen(0x27, 16, 2); // create a LCD "object" called screen
- void setup() {
- // setup the screen
- screen.init();
- screen.backlight(); // turn on the backlight to start
- screen.home(); // set cursor to home position
- screen.print("i:"); // print out the unchanging parts of the values
- screen.setCursor(6, 0);
- screen.print("m:");
- screen.setCursor(12, 1);
- screen.print("o:");
- delay(2000); // do nothing for 2 seconds
-
- // setup the input pin -> photocell
- pinMode(PHOTOPIN, INPUT);
- // Initializing compass
- compass.init();
- // setup the output -> motor moving the magnet + motor rotating
- magnetMotor.attach(MOTORMAGPIN);
- rotatingMotor.attach(MOTORPIN);
- rotatingMotor.write(90);
- Serial.begin(9600);
- }
- void loop() {
- // get info on light intensity
- int lightVal = analogRead(PHOTOPIN);
- // calculate the location of the magnet and move the motor to that angle
- int magAngle = map(lightVal, LIGHT_MIN, LIGHT_MAX, MAGANGLE_MIN, MAGANGLE_MAX);
- magnetMotor.write(magAngle);
- // get the compass value
- // Read compass values
- compass.read();
- // Return XYZ readings from the compass
- x = compass.getX();
- y = compass.getY();
- z = compass.getZ();
- // calculate magnetic value
- int magVal = y;
- // calculate rotation speed
- int rotateVal = map(magVal, MAGVAL_MIN, MAGVAL_MAX, ROTVAL_MIN, ROTVAL_MAX);
- // servo rotates at a speed of rotateVal (0 is faster, 90 is slower)
- rotatingMotor.write(rotateVal);
-
- // Update LCD screen values
- screenInput = map(lightVal, LIGHT_MIN, LIGHT_MAX, 0, 99);
- screenMInput = map(magAngle, MAGANGLE_MIN, MAGANGLE_MAX, 0, 99);
- screenMOutput = map(magVal, MAGVAL_MIN, MAGVAL_MAX, 0, 99);
- screenOutput = map(rotateVal, ROTVAL_MIN, ROTVAL_MAX, 0, 99);
- // Display updated LCD screen values only at specific time intervals
- if (millis() >= timer) {
- // print light val input
- screen.setCursor(2, 0);
- screen.print(screenInput);
-
- // print the magnetic field output value
- screen.setCursor(8, 0);
- screen.print(screenMInput);
-
- // print the magnetic field input value
- screen.setCursor(8, 1);
- screen.print(screenMOutput);
-
- // print the rotation speed output value
- screen.setCursor(14, 1);
- screen.print(screenOutput);
- // reset timer
- timer = millis() + INTERVAL;
- // serial output for testing purposes
- Serial.println((String)"X: " + x +
- "; Y: " + y +
- "; Z: " + z);
-
- Serial.println((String)"room brightness: " + lightVal +
- "; magVal: " + magVal +
- "; rotateVal: " + rotateVal +
- "; magAngle: " + magAngle );
- }
- }
/*
Project 1: Light Intensity to Rotation Speed
Leah Walko
Gracia Genero
Description: A double transducer that turns light intensity into
magnetic fields into rotation speed. A photoresistor picks up the
intensity of the light. That value changes the location of a magnet.
In turn, this affects the magnetic fields read by a compass, and based
off that value a servo motor rotates at a faster or slower speed.
Credit: QMC5883LCompass library creator, MRPrograms, for their xyz
example code, and to the course's lectures and website.
Pin mapping:
pin | mode | description
------|--------|--------------------------------------------
A1 | input | photocell to measure light intensity
A4 | input | triple axis compass SDA input
A5 | input | triple axis compass SCL input
10 | output | Servo motor that moves the magnet around
11 | output | 360 degrees servo motor with variable rotation speed
SCL | output | I2C LCD
SDA | output | I2C LCD
*/
// servo library
#include <Servo.h>
// compass and lcd libraries
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <QMC5883LCompass.h>
// pin values
const int PHOTOPIN = A1;
const int MOTORMAGPIN = 10;
const int MOTORPIN = 11;
// range of possible values
const int ROTVAL_MAX = 89;
const int ROTVAL_MIN = 0;
const int MAGANGLE_MAX = 50;
const int MAGANGLE_MIN = 0;
const int LIGHT_MAX = 1023;
const int LIGHT_MIN = 0;
const int MAGVAL_MAX = 2700;
const int MAGVAL_MIN = -7500;
// timer for updating LCD
const int INTERVAL = 1000;
unsigned long timer = 0;
// LCD values
int screenInput = 0;
int screenMInput = 0;
int screenMOutput = 0;
int screenOutput = 0;
// compass values
int x;
int y;
int z;
// motor objects
Servo magnetMotor; // create a motor "object" called magnetMotor
Servo rotatingMotor; // create a motor "object" called rotatingMotor
// compass and LCD objects
QMC5883LCompass compass; // create a compass "object" called compass
LiquidCrystal_I2C screen(0x27, 16, 2); // create a LCD "object" called screen
void setup() {
// setup the screen
screen.init();
screen.backlight(); // turn on the backlight to start
screen.home(); // set cursor to home position
screen.print("i:"); // print out the unchanging parts of the values
screen.setCursor(6, 0);
screen.print("m:");
screen.setCursor(12, 1);
screen.print("o:");
delay(2000); // do nothing for 2 seconds
// setup the input pin -> photocell
pinMode(PHOTOPIN, INPUT);
// Initializing compass
compass.init();
// setup the output -> motor moving the magnet + motor rotating
magnetMotor.attach(MOTORMAGPIN);
rotatingMotor.attach(MOTORPIN);
rotatingMotor.write(90);
Serial.begin(9600);
}
void loop() {
// get info on light intensity
int lightVal = analogRead(PHOTOPIN);
// calculate the location of the magnet and move the motor to that angle
int magAngle = map(lightVal, LIGHT_MIN, LIGHT_MAX, MAGANGLE_MIN, MAGANGLE_MAX);
magnetMotor.write(magAngle);
// get the compass value
// Read compass values
compass.read();
// Return XYZ readings from the compass
x = compass.getX();
y = compass.getY();
z = compass.getZ();
// calculate magnetic value
int magVal = y;
// calculate rotation speed
int rotateVal = map(magVal, MAGVAL_MIN, MAGVAL_MAX, ROTVAL_MIN, ROTVAL_MAX);
// servo rotates at a speed of rotateVal (0 is faster, 90 is slower)
rotatingMotor.write(rotateVal);
// Update LCD screen values
screenInput = map(lightVal, LIGHT_MIN, LIGHT_MAX, 0, 99);
screenMInput = map(magAngle, MAGANGLE_MIN, MAGANGLE_MAX, 0, 99);
screenMOutput = map(magVal, MAGVAL_MIN, MAGVAL_MAX, 0, 99);
screenOutput = map(rotateVal, ROTVAL_MIN, ROTVAL_MAX, 0, 99);
// Display updated LCD screen values only at specific time intervals
if (millis() >= timer) {
// print light val input
screen.setCursor(2, 0);
screen.print(screenInput);
// print the magnetic field output value
screen.setCursor(8, 0);
screen.print(screenMInput);
// print the magnetic field input value
screen.setCursor(8, 1);
screen.print(screenMOutput);
// print the rotation speed output value
screen.setCursor(14, 1);
screen.print(screenOutput);
// reset timer
timer = millis() + INTERVAL;
// serial output for testing purposes
Serial.println((String)"X: " + x +
"; Y: " + y +
"; Z: " + z);
Serial.println((String)"room brightness: " + lightVal +
"; magVal: " + magVal +
"; rotateVal: " + rotateVal +
"; magAngle: " + magAngle );
}
}
Comments are closed.