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

  1. /*
  2. Project 1: Light Intensity to Rotation Speed
  3. Leah Walko
  4. Gracia Genero
  5. Description: A double transducer that turns light intensity into
  6. magnetic fields into rotation speed. A photoresistor picks up the
  7. intensity of the light. That value changes the location of a magnet.
  8. In turn, this affects the magnetic fields read by a compass, and based
  9. off that value a servo motor rotates at a faster or slower speed.
  10. Credit: QMC5883LCompass library creator, MRPrograms, for their xyz
  11. example code, and to the course's lectures and website.
  12. Pin mapping:
  13. pin | mode | description
  14. ------|--------|--------------------------------------------
  15. A1 | input | photocell to measure light intensity
  16. A4 | input | triple axis compass SDA input
  17. A5 | input | triple axis compass SCL input
  18. 10 | output | Servo motor that moves the magnet around
  19. 11 | output | 360 degrees servo motor with variable rotation speed
  20. SCL | output | I2C LCD
  21. SDA | output | I2C LCD
  22. */
  23. // servo library
  24. #include <Servo.h>
  25. // compass and lcd libraries
  26. #include <Wire.h>
  27. #include <LiquidCrystal_I2C.h>
  28. #include <QMC5883LCompass.h>
  29. // pin values
  30. const int PHOTOPIN = A1;
  31. const int MOTORMAGPIN = 10;
  32. const int MOTORPIN = 11;
  33. // range of possible values
  34. const int ROTVAL_MAX = 89;
  35. const int ROTVAL_MIN = 0;
  36. const int MAGANGLE_MAX = 50;
  37. const int MAGANGLE_MIN = 0;
  38. const int LIGHT_MAX = 1023;
  39. const int LIGHT_MIN = 0;
  40. const int MAGVAL_MAX = 2700;
  41. const int MAGVAL_MIN = -7500;
  42. // timer for updating LCD
  43. const int INTERVAL = 1000;
  44. unsigned long timer = 0;
  45. // LCD values
  46. int screenInput = 0;
  47. int screenMInput = 0;
  48. int screenMOutput = 0;
  49. int screenOutput = 0;
  50. // compass values
  51. int x;
  52. int y;
  53. int z;
  54. // motor objects
  55. Servo magnetMotor; // create a motor "object" called magnetMotor
  56. Servo rotatingMotor; // create a motor "object" called rotatingMotor
  57. // compass and LCD objects
  58. QMC5883LCompass compass; // create a compass "object" called compass
  59. LiquidCrystal_I2C screen(0x27, 16, 2); // create a LCD "object" called screen
  60. void setup() {
  61. // setup the screen
  62. screen.init();
  63. screen.backlight(); // turn on the backlight to start
  64. screen.home(); // set cursor to home position
  65. screen.print("i:"); // print out the unchanging parts of the values
  66. screen.setCursor(6, 0);
  67. screen.print("m:");
  68. screen.setCursor(12, 1);
  69. screen.print("o:");
  70. delay(2000); // do nothing for 2 seconds
  71. // setup the input pin -> photocell
  72. pinMode(PHOTOPIN, INPUT);
  73. // Initializing compass
  74. compass.init();
  75. // setup the output -> motor moving the magnet + motor rotating
  76. magnetMotor.attach(MOTORMAGPIN);
  77. rotatingMotor.attach(MOTORPIN);
  78. rotatingMotor.write(90);
  79. Serial.begin(9600);
  80. }
  81. void loop() {
  82. // get info on light intensity
  83. int lightVal = analogRead(PHOTOPIN);
  84. // calculate the location of the magnet and move the motor to that angle
  85. int magAngle = map(lightVal, LIGHT_MIN, LIGHT_MAX, MAGANGLE_MIN, MAGANGLE_MAX);
  86. magnetMotor.write(magAngle);
  87. // get the compass value
  88. // Read compass values
  89. compass.read();
  90. // Return XYZ readings from the compass
  91. x = compass.getX();
  92. y = compass.getY();
  93. z = compass.getZ();
  94. // calculate magnetic value
  95. int magVal = y;
  96. // calculate rotation speed
  97. int rotateVal = map(magVal, MAGVAL_MIN, MAGVAL_MAX, ROTVAL_MIN, ROTVAL_MAX);
  98. // servo rotates at a speed of rotateVal (0 is faster, 90 is slower)
  99. rotatingMotor.write(rotateVal);
  100. // Update LCD screen values
  101. screenInput = map(lightVal, LIGHT_MIN, LIGHT_MAX, 0, 99);
  102. screenMInput = map(magAngle, MAGANGLE_MIN, MAGANGLE_MAX, 0, 99);
  103. screenMOutput = map(magVal, MAGVAL_MIN, MAGVAL_MAX, 0, 99);
  104. screenOutput = map(rotateVal, ROTVAL_MIN, ROTVAL_MAX, 0, 99);
  105. // Display updated LCD screen values only at specific time intervals
  106. if (millis() >= timer) {
  107. // print light val input
  108. screen.setCursor(2, 0);
  109. screen.print(screenInput);
  110. // print the magnetic field output value
  111. screen.setCursor(8, 0);
  112. screen.print(screenMInput);
  113. // print the magnetic field input value
  114. screen.setCursor(8, 1);
  115. screen.print(screenMOutput);
  116. // print the rotation speed output value
  117. screen.setCursor(14, 1);
  118. screen.print(screenOutput);
  119. // reset timer
  120. timer = millis() + INTERVAL;
  121. // serial output for testing purposes
  122. Serial.println((String)"X: " + x +
  123. "; Y: " + y +
  124. "; Z: " + z);
  125. Serial.println((String)"room brightness: " + lightVal +
  126. "; magVal: " + magVal +
  127. "; rotateVal: " + rotateVal +
  128. "; magAngle: " + magAngle );
  129. }
  130. }