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.
Progress Images
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 ); } }
Comments are closed.