Our project was to create a double Tansducer that converted a magnetic field strength to a printed color output. To accomplish this, we chose two middle steps to convert the input signal to the output.
Project Details
Project Video
Project Description
We wanted to take input from the forces produced by a magnet, and give that information to a rotating motor. Then, the motor would rotate a gear, which would move a horizontal block with ridges that fit into the gear. We then sensed the position of the horizontal block, and then gave that information to another rotating motor. This second rotating motor was attached to a curved piece of paper, which had a range of colors on it. Our final output was the outward-facing color on the paper. All the information about positions and level of magnetic strength were printed as numbers on a screen for the viewer to see.
Progress Pictures
Discussion:
We both learned a lot from this process. We enjoyed teaming up together because we were equally invested in the success of the project, and because both had (semi-overlapping but still) different areas of technical expertise, which allowed us to synthesize knowledge from our respective fields. For example, Matthew is a Mechanical Engineering major and really good at CAD, so we were able to make quality, physical mechanisms within our middle step via our rack and pinion. Shenai is an Electrical and Computer Engineering major and she tackled a lot of the wiring and programming challenges.
Comments from Shenai: I enjoyed the team aspect of this project, as well as the hands-on quality of the work, which was something I had been lacking in my other classes. I also felt that I grew as a debugger, both in code and circuitry. It was really satisfying when I spotted that Matt’s stepper motor wasn’t properly grounded, and was able to fix it quickly. Another super satisfying moment was when I combined our separate code into a single file, very quickly checked for timing issues/duplicated pins and variables, and it compiled and ran perfectly on the first try.
However, we had a terrible time with the stepper motor. We had to go through 3 different chips and 2 motors, and we had to discard our custom-made 3-D print that housed the smaller motor because the smaller motor wouldn’t work properly with any of the chips. The 3-D print made us want to hang onto the smaller motor because we had already put so much time into setting up our machine specifically for it, but finally we ended up pivoting to the more powerful and reliable motor. I think if we had been more willing to pivot entirely instead of changing little things to fit our past decisions, we would have breezed through this process faster. Although, I will say, I got really fast at unwiring and rewiring various stepper motors and their drivers, so this iterative process was helpful for my technical growth in that respect.
Comments from Matthew: It was very exciting to have the opportunity to apply my knowledge of mechanical systems and CAD into this project. Despite having to change which stepper motor we used, the parts I created for the project all worked without the need for iterative design and further prototypes. This saved the course budget some money as we didn’t have to keep printing and printing more materials. Together, we were able to synthesize electrical and mechanical design in an effective and creative way to produce a successful end result. In addition to applying my Mechanical Engineering skills, I was able to learn a lot on the electrical side as well. I was able to brush up my coding skills in Arduino, become familiar with different electrical connections and sensors (magnetometer, ultrasonic ranger, stepper and servo motors, etc), and I even got to learn how to strip and solder wires for the first time. I feel that the acquisition of these new skills will help me grow as an engineer and will allow me to be more versatile in upcoming projects.
Functional Block Diagram
Electric Schematic
Code:
/* * Magentic Field to Color Gradient Double Transducer * * By: Matt Wagner and Shenai Chan * * Desc: Takes in a reading of magnetic field strength, * converts it to rotational position on stepper motor, * uses Ultrasonic Ranger to sense the position of a * rack driver by the motor, feeds that information * to rotational position on a servo motor with substantial * delay to allow for proper reading of the servo position. * Sends input/output/intermediate information to an LCD display. * * Pin mapping table: * SDA & SCL connected to both LCD and 3-axis magnetometer * 6 <-> servo * 8 <-> dir on stepper motor * 9 <-> step on stepper motor * 11 <-> echo on ultrasonic ranger * 12 <-> trig on uultrasonic ranger * * Credit: * Referenced starter code by Robert Zacharias on timing signal sends; * instantiating USR, LCD, and servo; and writing to LCD. * * https://courses.ideate.cmu.edu/60-223/f2021/tutorials/code-bites * https://courses.ideate.cmu.edu/60-223/f2021/tutorials/I2C-lcd * * Referenced docs from Patrick Wasp's AccelStepper lib & * MPrograms' compass lib */ /* First, import some libraries: */ // I2C Library #include <Wire.h> // For the 3-axis magnetometer #include <QMC5883LCompass.h> // For the stepper motor #include <AccelStepper.h> // For the ultrasonic ranger #include <NewPing.h> // For the Servo Motor #include <Servo.h> // For the LCD display #include <LiquidCrystal_I2C.h> /* Then, instantiate objects that correlate to wired devices */ // Make LCD obj LiquidCrystal_I2C screen(0x27, 16, 2); int iVal; int mVal1; int mVal2; int oVal; // Make magnetometer obj QMC5883LCompass compass; // Make stepper obj, as well as corresponding variables for waits // between writes, and keeping track of current position #define dirPin 8 #define stepPin 9 #define motorInterfaceType 1 const int wait = 1000; long timer = 0; AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin); int currentPos; // Make USR obj #define TRIGGER_PIN 12 #define ECHO_PIN 11 #define MAX_DISTANCE 200 NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // Make servo obj Servo gaugeMotor; const int GAUGEMOTORPIN = 6; const unsigned long DISPUPDATETIME = 500; const unsigned long TIMEBETWEENREADS = 3000; unsigned long lastMove = millis(); unsigned long lastUpdate = millis(); void setup() { // Initialize the serial port Serial.begin(9600); // Initialize I2C Wire.begin(); // Initialize the servo motor gaugeMotor.attach(GAUGEMOTORPIN); // Initialize the magnetometer compass.init(); // Initialize the stepper motor stepper.setCurrentPosition(0); stepper.setMaxSpeed(500); // Initialize the LCD screen.init(); // turn on the backlight to start screen.backlight(); // set cursor to home position, i.e. the upper left corner screen.home(); } void loop() { // read ultrasonic ranger int currDist = sonar.ping_cm (); mVal2 = currDist; Serial.print("Ping: "); Serial.print(currDist); // Send ping, get distance in cm and print result (0 = outside set distance range) Serial.println("cm"); // map range distance to degree range 15 to 165 degrees int mappedAngle = map(currDist, 3, 11, 15, 165); oVal = mappedAngle; // write to LCD with appropriate timing if (millis() - lastUpdate >= DISPUPDATETIME){ screen.clear(); screen.print("i:"); screen.print(iVal); screen.setCursor(5, 0); screen.print("m:"); screen.print(mVal1); screen.setCursor(7, 1); screen.print(mVal2); screen.setCursor(11, 1); screen.print("o:"); screen.print(oVal); screen.home(); lastUpdate = millis(); } // write to servo with appropriate timing if (millis() - lastMove >= TIMEBETWEENREADS){ // move motor if (mappedAngle >= 15 && mappedAngle <= 165){ gaugeMotor.write(mappedAngle); lastMove = millis(); } } // read from magnetometer and write to stepper with appropriate timing if ((millis() - timer) >= wait) { if (stepper.distanceToGo() == 0) { Serial.println("in if statement"); int z; compass.read(); z = compass.getZ(); iVal = map(z, 0, 37000, 0, 99); Serial.println(z); int loc = map(z, 0, 37000, 0, -200); if (0 <= z && z <= 37000) { if (0 >= loc && loc > -50) { stepper.moveTo(0); } else if (-50 >= loc && loc > -100) { stepper.moveTo(-50); } else if (-100 >= loc && loc > -150) { stepper.moveTo(-100); } else if (-150 >= loc && loc >= -200) { stepper.moveTo(-150); } Serial.println(loc); stepper.setMaxSpeed(25); stepper.setAcceleration(25); timer = millis(); mVal1 = map(z, 0, 37000, 0, 99); } } } stepper.run(); }