Sei sulla pagina 1di 21

Stepper Motor

Mission Mapping Software

In this lab, you will learn more about the Adafruit motor shield and how it can be used to control a stepper motor. Your work with the IR sensors will also continue as you teach your rover how to map the terrain surrounding it, equipping it with sufficient knowledge to navigate around possible obstructions, and finally reach the desired plaques of interest.

Table of Contents
1 2 Reading 1.1 References Homework and Mission 2.1 Homework 2.2 Mission 2.3 Documentation Lab Checklist Parts How it Works 5.1 General 5.2 Construction 5.3 Unipolar vs. Bipolar 5.4 Movement 5.4.1 Single 5.4.2 Double 5.4.3 Interleave 5.4.4 Microstep Lab Experiments 6.1 Gyro Calibration 6.2 Horizontal Alignment of the Scan Platform 6.3 Mapping Experiment 6.3.1 Documentation Software 7.1 Gyro Calibration Application 7.2 Mapping Software Application

3 4 5

7.3

Find Objects Software Package 7.3.1 findObjects Global variables 7.3.2 Subroutine findObjects() 7.4 Verify Software Package 7.4.1 verify Global variables 7.4.2 Subroutine verify() 7.5 Utility Functions 7.5.1 Function stepTurret() 7.5.2 Function arcSine()

Reading

Your reading this week is Chapter 10 Serial Communications Sections 10.1 and 10.1.2 Serial Peripheral Interface (SPI).

Most of the material in this document on the SPI subsystem can be found in Chapter 18 The Serial Peripheral Interface (SPI) of the ATmega328P Datasheet. We will be looking at stepper motors and the SPI serial communications as they are implemented by the Arduino and the Adafruit Motor Shield. Here is the motor shield schematic http://www.ladyada.net/make/mshield/download.html and here is the pdf documenting the shield and how to control a stepper motor (pages 25 and 26) http://www.robotshop.ca/content/PDF/adafruit-motor-shield-arduino-user-guide.pdf

1.1 References
1. Atmel AVR Micrcontroller Primer:Programming and Interfacing, by Barrett, Section 6.4 DC Motor Speed and Direction Control 2. HSI Stepper Motor Theory and Stepper Motor are good recources, among many on the

web, for learning about Stepper Motors. 3. Stepper Motor Basics - Introduction to Stepper Motors. 4. Interface Electronics - Ricky's World 5. YouTube Video - Motorola Stepper Motor Control IC 6. Atmel application notes doc7672.pdf (Sensor-based Control of Three Phase Brushless DC Motors) 7. Parallax 12-Volt Unipolar Stepper Motor 8. Stepper Motor - Wikipedia 9. Identifying Stepper Motor wires 10. http://www.netrino.com/Embedded-Systems/How-To/PWM-Pulse-Width-Modulation 11. http://www.ducttapeeng.com/smd/smd11.htm - disassembly 12. http://www.stepperworld.com/Tutorials/pgBipolarTutorial.htm - sequences

2
2.2

Homework and Mission


Mission

Before your rovers can travel to points of interest (the plaques), it needs to be able to pick them out from other terrain features (walls, cabinets, desks, chairs, etc.). At the end of this lab you should have completed a... IR Mapping Experiment - the Difference Map Software with associated documentation to identify targets within the field-of-view of the rover. As a necessary precondition for completing these experiments, the scan platform and IR rangers will need to be aligned horizontally.

2.3

Documentation

Summarize your experimental results and equation(s) in the subsection named IR Sensors within the Hardware Build section of your Project Document. This subsection should include a discussion of the modifications you made to the indoor mapping experiment in order to achieve success on the test site.

Lab Checklist

The checklist is filled in by the instructor at the beginning of next weeks lab. Horizontal Alignment of the scan platform with tilt calculation IR Mapping Experiment Graphical results with comments from running makeMap program are included in the IR section of the Project Document. Target Location Algorithm added to the Software Code Section. Results from running your findObjects software to identify targets within the field-of-

view of the rover. Rover successfully completes the mission

Parts

For this lab, we will need the following essentials...

Solderless breadboard

Sharp GP2Y0A710YK0F Long Range IR Sensor $19.50

Sharp GP2Y0A02YK0F Medium Range IR Sensor $12.50

Bourns Inc. 10.0 K Potentiometer Digikey 3310Y-001103L-ND

4.7 K resistor

10uF Capacitor

680 ohm resistor

LED

In addition to our essentials, we will need some measuring equipment and supplies to complete this lab...

Tape Measure (inches and cm)

Laser Pointer

Level

Electrical Tape

You will also need your breadboard wire bundle plus half-size breadboard.

How it Works

The best discussion on how stepper motors work can be found on Wikipedia under Stepper motor. To learn how to use these in the Arduino IDE look here. Also see AdaFruit Make it Work under the Stepper section.

5.1

General

Stepper motors can be salvaged from obsolete disk drives and ink jet printers. The motors from 3.5" floppy motors are not suitable for this lab. Bipolar motors have 4 wires and unipolar motors have 5,6 or 8. Bipolar motors generally have a larger torque and smaller step angle when compared to unipolar stepper motors. You can find common phase leads by using a ohmmeter to measure resistances between leads, common phase leads will have low resistances in around 30 ohms. Stepper motors can be broken down into 3 categories. 1. Variable reluctance stepper- magnetic flux seeking the lowest reluctance path through a magnetic circuit. 2. Permanent magnet stepper- has a cylindrical permanent magnet rotor. 3. The hybrid stepper- combination of variable reluctance and permanent magnet steppers Source: http://www.stepperboard.com/MotorConnections.htm

5.2

Construction

An inductive motor like our stepper motor has two major components: a stator and a rotor. The rotor is the magnetic armature of the stepper motor and is the moving part of the stepper motor. The rotor consists of bearings, magnetic shaft and poles. This cylindrical shaft contains permanent magnets which interact with the stator. The stator is the external part of the inductive motor that does not move. The stator contains the bearing housing, the stator coils and the stator poles. (Follow this link for a disassemble). A stepper motor is a type of motor whose circular rotation of the rotor is divided into smaller discrete steps. The number of steps a stepper motor takes in order to make one full rotation of the rotor is fixed and is determined by the number of poles inside the motor. Each step turns the rotor a certain number of degrees. Smaller step angles are obtained by adding more poles on both the rotor and stator. Both unipolar and bipolar stepper motors are constructed this way while the main difference lies in

the wiring of the coils.

Souce: Motors Guide Source:HSI Stepper Motor Theory

5.3

Unipolar vs. Bipolar

Unipolar stepper motors are designed to have a canter tap which is common to two coils working together. The positive voltage is then applied to the common tap and the nodes a and b are alternately grounded to produce changes in polarity to the magnetic field. You can check the direction of the field by using the equation B=IxR (this is greatly simplified for our purposes) where B is the magnetic field, I point in the direction of positive current flow, and R is in the direction of where you want to measure the magnetic field at. For example if 1 is positive, a is grounded, and b is open (high impedance) current flows from 1 to a in Figure 1 and the direction of the magnetic field flows out at the left end and comes in at the right end (Figure 2 is meant to clear up which way is north or south. If the magnetic field is outgoing it is south while north is on the receiving end). If the current flows from 1 to b,while a is high impedance, then the polarity is reversed. Figure 1 Figure 2

From:http://www.cs.uiowa.edu/~jones/step/types.html

From:http://en.wikipedia.org/wiki/ File:Dipole_field.svg

A bipolar motor has no center tap and the current must flow from a to b or from b to a. We must reverse the current in order to reverse the magnetic field as opposed to switching the ground. This requires a more complex design to handle and is usually left to an H-bridge to configure.

5.4

Movement

The stepping sequence of a bipolar stepping motor can be broken down into: 1. Step mode: Full step (one-phase or two-phase), Half Step (eight-phase), Micro-stepping (not used in the lab). 2. Misc factors: Power, torque, step angle and accuracy. The type of stepping sequence that is used is dependent on the type of application of the motor.

Source: Stepper World For the Adafruit Motor shield we can have four different modes of activation. These modes are Single, Double, Interleave, and Microstep. For a GIF animation showing these stepper modes visit CNC Router Source.

5.4.1 Single
This mode refers to the single-coil activation aka the Wave Drive, One-Phase activation of the motors. See GIF animation. For the ROB-09238 this gives you a step of 1.8o.

5.4.2 Double
This mode refers to the double-coil activation aka the Full Step, Two-Phase activation of the motors. See GIF animation. For the ROB-09238 this gives you a step of 1.8o.

5.4.3 Interleave
This mode refers to the single-coil/double-coil aka the Half Step activation of the motors. See GIF animation. For the ROB-09238 this gives you a step of 0.9o.

5.4.4 Microstep
The micro-stepping mode is the most complex of all the stepping modes. That is why some stepper drivers only offer full and half step modes. Micro-stepping is when the current applied to each winding is proportional to a mathematical function, providing a fraction of a full step. The most common divisions are 1/4th, 1/8th, 1/10th, etc. However, there are some drivers that provide up to 1/256th of a full step. Micro-stepping provides greater resolution and smoother motor operation. This is very advantageous as it reduces the need for mechanical gearing when trying to achieve high resolution. However, micro-stepping can affect the repeatability of the motor. (source: CNC Router Source).

Lab Experiments

To accomplish our objectives, the lab consists of a number of experiments. Do Not Forget Unless otherwise indicated, all experiments may be run with fully charged battery or from an external source (USB or Adapter). Please, include all experimental setup and results in your lab notebook.

6.2 Horizontal Alignment of the Scan Platform


In this part of the lab we are going to make sure your rover is mission ready by checking the horizontal alignment of the scan platform. The following steps assume you have incorporated a reliable method for adjusting perpendicular alignment of the scan platform with respect to the base and parallel alignment of IR ranger with respect to the platform. Specific design recommendation include using screws to attach your stepper motor to the base and to include a screw for adjusting the tilt (i.e., pitch) of the long range IR sensor. The Sharp GP2Y0A710YK0F conveniently provided a mounting hole for pitch adjustment. Further the electrical wires running from the base to the platform must allow for the platform to rotate at least 180 degrees in any direction. 1. Attach your laser pointer to the scan platform and co-align with the IR ranger - not the side. We are currently not sure if the best location is directly over the IR source or sensor.

2. Place your rover on the raised platform at the front of the lab. Using your level, find a relatively flat and level part of the floor. After placing your rover at this location, again using your level, verify that the base of the rover is level to the floor.

3. Using your triangle adjust the stepper motor mount so the shaft of the stepper motor is perpendicular to the base. This assumes that any adapters you have attached to the shaft of the stepper motor are also aligned. Verify this alignment for all 360 degrees of rotation. 4. Using the triangle and level adjust the scan platform/IR sensor so it is perpendicular to the shaft/mounting adapter of the stepper motor and parallel to the floor for all 360 degrees of rotation. It is critical that the IR sensor not be tilted with respect to the axis of rotation.

5. Have the rover run the scan platform demonstration sequence from last week. 6. Approximately locate the laser beam's maximum and minimum height from the floor. 7. Place a target at these two locations 4 meters from the rover. You may have to reorient the rover to be able to locate the targets on the platform. 8. If required, repeat steps 2 through 7, until the laser beam stays approximately level to the floor during its 360 degree scan. Once you feel the scan platform is mission ready, program the rover to move one meter and run the scan platform demonstration sequence from last week. Locate the minimum and maximum height. Do not move the scan platform by hand - we are trying to replicate the real-world that the rover will encounter during the mission. Place targets as far away as you can at these two locations and record the beam height, distance, and the rotation angle from the home position (straight ahead). Tell your rover to move approximately 1 more meter, and again have the rover run the scan platform demonstration sequence. Record beam height, distance, and the rotation angle.

Have the rover move an additional meter and repeat the sequence. After running these experiments calculate the maximum angle that the floor could be tilted, so the laser does not hit the floor or go over an 11 inch high target. Rotation Angle Test 1 Test 2 Distance to Target Beam Height Signature/Date

6.3 Mapping Experiment


Run the Arduino mapping program provided in the software section of this document. The program rotates one half-step (INTERLEAVE) and runs an IR measurement test sequence (function statPak). The program repeats this sequence until the rover has completed a 360 degree scan of the room. The software has been designed to support most of your stepper motors, this means a step size of 0.9 degrees and 400 test points. If needed, update these variables for your stepper motor. Also set the analog input pin (sensorPin) as required by your design. Before running the mapping experiment... 1. Verify that you have completed everything on the Baseline IR Calibration checklist specifically, Step 1: Wire the Circuit and Step 2: Setup the Test Fixtures. 2. You will be running the mapping experiment with the laser ON. You should verify that the laser does not invalidate your baseline calibration data. Tape the laser on the top of the IR ranger (not the side). Tell me if the results are better with the laser over the IR source or sensor. 3. Verify that the Horizontal Alignment of the Scan Platform is complete. Be sure the wires running from the base to the scan platform can support at least 180 degrees of rotation. Place the rover at the front of the lab, as defined by the instructor and make a 360 degree map of this location. Place six (6) plaques as required by the Mission Plan. Include targets within the range of both IR sensors.

Using your compass, string, and ruler measure the rotation angle and distance of the targets relative to the IR sensor(s). Record the location (angle and distance)

of these plaques in your lab notebook. You may also want to take a picture(s) and/or video for future reference. As you can see in the figure below, the photo makes a nice background for displaying the results of your mapping experiments. I recommend running with the laser ON in order to record when the IR is looking at a target. Download and run the program. Launch the terminal program (warning: opening or closing the terminal program during a scan will effect your experimental results). You should see the message "in setup," followed by "press any key to start scan." Press any key to start the scan. Record in your lab notebook the steps at which the laser hits a target. After the scan platform has mapped 180 degrees, spun 360 degrees, and completed the next 180 degree scan, you should see the message "data set complete," followed by "press any key to start scan." Remove the plaques from the scan area and press any key to start the second scan. Stop the program after the scan platform has completed two full mappings as previously defined (with and without plaques). Cut and Paste your results into a text file. Import this text file (comma delimited) into an Excel spreadsheet. Add columns translating test values into distances. For both mappings, add a column named sample difference and have Excel calculate the difference in the average distance from each measurement (dn - dn-1). Next add a column named mapping difference and have Excel calculate the difference in the average distance for each sample angle (with and without plaques). You are welcome to download my Excel spreadsheet and use it as a template for recording your data.

6.3.1 Documentation
Document your experimental results and subsequent calculations in the subsection named IR Sensors within the Hardware Build section of your Project Document.

7 Software
7.1 Gyro Calibration Application 7.2 Mapping Software Application
The following program requires utility functions getRange and ReadADC located in the "Utility Functions" Section of Lab 4.
/* * * * * * * *

Mission Mapping Software Begins by... note: word is equivalent to unsigned int, which is equivalent to uint16_t By Gary Hill

* March 27, 2010 */ #include <stdint.h> #include <avr/io.h> #include <avr/pgmspace.h> /* * The range data needs to be unsigned int * * rangedata.h should look like this: * const int range_length=1024; * * const unsigned int range_data[] PROGMEM = { * 437, 437, ... * }; * */ #include <AFMotor.h> #include "rangedata.h" byte sensorPin=4; // 400 entries x 2 bytes/entry = 800 bytes, ATmega328P has 2,048 bytes of SRAM int map_data[400]; AF_Stepper motor(200, 1); // instantiate a 1.8 degrees/step stepper motor void setup() { motor.setSpeed(10); Serial.begin(9600); Serial.println("in setup"); analogReference(EXTERNAL); motor.release(); makeMap(); } void loop() { } /* * Make a Difference Map */ void makeMap() { int dn = 0; tweak(); // adjust IR Ranger zero angle // generate a difference map // where Vref is 3.3V

// 10 rpm

// take 200 measurements and 199 steps (stops at 179.1 degrees clock-wise) for (int i = 0; i < 200; i = i++) { dn = readADC(sensorPin); map_data[i] = pgm_read_word(&range_data[dn]); // Serial.println(map_data[i]);

motor.step(1, FORWARD, INTERLEAVE); // 0.9 degrees/step delay(60); // @ 10 rpm, this should take 15 ms + 45 ms margin } // rotate counter clock-wise 399 steps (stops at 180 degrees clock-wise) // 0.9 degrees/step x 399 steps = - 359.1 degrees motor.step(399, BACKWARD, INTERLEAVE); delay(10000); // @ 10 rpm, this should take 6 seconds + 4 second margin // take 200 measurements and 199 steps (stops at 359.1 degrees clock-wise) for (int i = 0; i < 200; i = i++) { dn = readADC(sensorPin); map_data[i + 200] = pgm_read_word(&range_data[dn]); // Serial.println(map_data[i + 200]); motor.step(1, FORWARD, INTERLEAVE); // 0.9 degrees/step delay(60); // @ 10 rpm, this should take 15 ms + 45 ms margin } // cancel extra step motor.step(1, BACKWARD, INTERLEAVE); Serial.println("initial mapping complete"); Serial.println("add targets and enter go"); tweak(); // adjust IR Ranger zero angle

// take 200 measurements and 199 steps (stops at 179.1 degrees clock-wise) for (int i = 0; i < 200; i = i++) { dn = readADC(sensorPin); map_data[i] = map_data[i] - pgm_read_word(&range_data[dn]); Serial.println(map_data[i]); motor.step(1, FORWARD, INTERLEAVE); // 0.9 degrees/step delay(60); // @ 10 rpm, this should take 15 ms + 45 ms margin } // rotate counter clock-wise 399 steps (stops at 180 degrees clock-wise) // 0.9 degrees/step x 399 steps = - 359.1 degrees motor.step(399, BACKWARD, INTERLEAVE); delay(10000); // @ 10 rpm, this should take 6 seconds + 4 second margin // take 200 measurements and 199 steps (stops at 359.1 degrees clock-wise) for (int i = 0; i < 200; i = i++) { dn = readADC(sensorPin); map_data[i + 200] = map_data[i + 200] - pgm_read_word(&range_data[dn]); Serial.println(map_data[i + 200]); motor.step(1, FORWARD, INTERLEAVE); // 0.9 degrees/step delay(60); // @ 10 rpm, this should take 15 ms + 45 ms margin } // cancel extra step motor.step(1, BACKWARD, INTERLEAVE); Serial.println("difference mapping complete"); }

/* * Terminal adjust of starting angle * Enter the plus or minus character (+/-) and the number of steps (n = 1 to 9). */ void tweak(){ char ch; // used by tweak Serial.println("enter +n, -n, or go where n = 1-9 steps and go = start scan"); while(1) { while (Serial.available() <= 1) {} // do nothing // send data only when you receive data: if (Serial.available() > 1) { // read the incoming byte: ch = Serial.read(); // Serial.println(ch, HEX); if ( ch == 0x2d ) { Serial.print("minus "); ch = Serial.read(); ch = ch - 0x30; Serial.println(ch, HEX); // 0.9 degrees/step x 399 steps = - 359.1 degrees motor.step(ch, BACKWARD, INTERLEAVE); } else if ( ch == 0x2b ) { Serial.print("plus "); ch = Serial.read(); ch = ch - 0x30; Serial.println(ch, HEX); motor.step(ch, FORWARD, INTERLEAVE); // 0.9 degrees/step } else if (ch == 0x67 ) { ch = Serial.read(); delay(250); Serial.println("scanning..."); return; } else { ch = Serial.read(); Serial.println("unknown entry"); } } } }

7.3

Find Objects Software Package

The following program requires utility functions getRange and ReadADC located in the shared "Utility Functions" Section of this document.

7.3.1 findObjects Global variables


Place these variable declarations at the top of your program.
// In order to quickly change the number of steps we must use define // and not a constant, as the arduino ide doesn't like variables

// initializing the array length #define map_length 400 #define plaque_array_size 20 // findObjects variables int numPlaques=6; int sensitivity=15; // difference in distance (cm) of mapping data for a // plaque to be suspected int minWidth=2;

This software program assumes that makeMap has been called and has generated a 400 entry array.
// 400 entries x 2 bytes/entry = 800 bytes, ATmega328P has 2,048 bytes of SRAM // and 1,024 bytes of EEPROM int map_data[map_length];

If you simply want to test findObjects add the following array declaration.
int map_data[]= {-8,14,18,7,18,85,147,200,197,174,55,0,-54,1,-14,10,6,-1,4,6,10,36,49,66,58,135,-110,-3,0,10,1,-1,6,2,2,1,18,53,50,45,43,39,25,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,18,17,20,19,16,16,16,9,13,-3,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,-1,0,0,-1,0,0,0,0,-1,0,0,3,0,31,79,97,100,103,111,118,122,131,137,140,34,7,5,-3,-10,14,-9,7,9,15,0,0,0,0,0,0,0,0,0,0,0,17,42,52,-10,15,25,3,46,12,87,179,224,288,76,108,125,32,0,-1,-7,-12,0,7,-9,-5,0,-11,12,-10,-3,4,1,-2,-14,6,2,12,30,40,-27,5,23,-19,6,5,-15,-46,-17,-97,23,93,32,101,21,3,0,0,0,0,0,0,0,-4,-1,3,29,52,-2,-13,0,83,0,0,0,-2,0,0,0,12,94,-143,-309,-71,-69,-27,37,139,265,148,4,77,197,0,1,0,264,72,0,77,135,243,0,15,11,16,2,-242,320,-205,1,5,8,10,0,-1,-1,0,0,-8,15,9,0,-16,-292,-125,-239,-8,-11,2,0,0,-1,0,40,0,0,-1,82,0,76,206,4,0,2,9,0,0,-2,4,0,-9,6,4,4,-4,1,0,0,0,0,0,0,0,0,0,0,0,0,-20,0,6,2,1,1,0,-7,2,0,1,1,-5,-2,-1,10,14,6,-2,12,7,5,-4,1,1,-16,14,16,0,0,15,8,0,-7,21,0,0,2,0,0,0,0,0,0,0,1,2,-1};

7.3.2 Subroutine findObjects()


void findObjects(){findObjects(map_length);} void findObjects(int mapEnd){ Serial.println("finding objects"); boolean plaqueDetected=false; // flag determining recording status // false means that there is currently no plaque detected, // true means a plaque is being evaluated int gapCounter=0; int gapTolerance=1; // starting index of a suspected plaque (see sensitivity) int beginning=0; int ending=0; // ending index of a suspected plaque int p_Idx=0; // index of a detected plaque // makeMap(mapEnd); for (int i = 0; i < map_length; i++){

// don't stop detecting plaques

// if the difference is greater than (15), and we're not already recording, // then start recording plaque length if((map_data[i]>=sensitivity)&!plaqueDetected){ beginning = i; // The previous gap count could be moved in code for different effects. // It is placed here so that it counts the total length of gaps in a // signal as opposed to any individual gap in a signal ie: for a // tolerance of 2 10101011 won't pass. gapCounter = 0; plaqueDetected=true; } if((map_data[i]<sensitivity)&plaqueDetected){ gapCounter++; // if the value falls below (15) dont count ending = i - gapCounter; // the extra gap in the ending of the plaque if(gapCounter > gapTolerance) { // only stop after the gap has exceeded plaqueDetected=false; // the tolerance if(ending-beginning >= minWidth){ // if plaque was wide enough count it p_angle[p_Idx]= (ending + beginning)/2; // save the angle as the //Serial.print(p_Idx); // midpoint of the beginning and end //Serial.print(": "); //Serial.println(p_angle[p_Idx]); p_Idx++; // move to the next array location } } } } verify(p_Idx); // manual override y/n of detected plaques

} // else gapCounter=0; // place the reset to gapCounter here if you'd like // to clear it after the end of every gap

7.4

Verify Software Package

Needs to be modified to write final list to EEPROM The verify function allows the user to approve/disapprove plaques found by findObjects. It also recovers distance-to-plaque data destroyed by makeMap in order to reduce SRAM overhead.

7.4.1 verify Global variables


Place these variable declarations at the top of your program. // verify constants and variables #define plaque_array_size 20; int p_angle[plaque_array_size]; int p_dist[plaque_array_size];

// 12 *2 = 24 bytes

int p_length = 0; // number of verified plaques, may be less than // actual array size if some plaques were not approved

7.4.2

Subroutine verify()

void verify(int numDetected){ char userIn; int angle; // current angle to detected but not verified plaque int dist; // current angle to detected but not verified plaque boolean valid; // used to see if user input is valid Serial.println("Please manually verify with a y/n if this is a plaque"); Serial.print("This is out of: "); Serial.println(numDetected); Serial.println("Angle:Distance"); p_length = -1; // initialize number of verified plaques

for (int p_Idx = 0; p_Idx < numDetected; p_Idx++){ valid=false; // angle is a interleave number of steps NOT degrees or radians angle = p_angle[p_Idx]; // This assumes FORWARD is CW and BACKWARD is CCW // This may not be a good assumption for your rover. motor.step(angle,FORWARD,INTERLEAVE); delay(60); dist = getRange('L'); Serial.print(angle); Serial.print(": "); Serial.println(dist); Serial.flush(); while(Serial.available()==0){} valid = false; while(!valid){ userIn=Serial.read(); if (userIn=='y'||userIn=='Y'){ p_length++; p_dist[p_length] = dist; p_angle[p_length] = angle; valid=true; } else if(userIn=='n'||userIn=='N'){ valid=true; } else { Serial.println("Invalid input"); Serial.flush(); }

// now that the user has verified or disallowed this plaque // return to home position. motor.step(angle,BACKWARD,INTERLEAVE); } } Serial.println("Done"); }

7.5 Utility Functions


The following utility functions are common to many of the programs you will be writing.

7.5.1 Function stepTurret()


This utility must replace all motor shield step commands to the stepper motor, including onestep and step. Once replaced, lost_dog_counter will always contain the number of +/- steps needed to return the turret to its home position.
int lost_dog_counter=0; void stepTurret(int a_steps, int a_dir, int a_style) { if(a_style == SINGLE){ a_steps = 2 * a_steps; } if (a_dir == FORWARD){ lost_dog_counter += a_steps; } else{ lost_dog_counter -= a_steps; } if(a_steps==1){ motor.onestep(a_dir, a_style); delay(motor.usperstep/1000); } else { motor.step(a_steps, a_dir, a_style); } }

7.5.2

Function arcSine()

/* * Find offset angle (in interleave steps) based on distance-to-target * ref: http://www.nongnu.org/avr-libc/user-manual/ group__avr__math.html#g98384ad60834911ec93ac5ae1af4cf0a * asin argument must be between -1 and 1, returned value is between * -pi and pi (-90 and 90 degrees) * * INPUT * Data Argument Description

* Type Units * double a_opp cm opposide side of a right triangle * (typically offset distance) * double a_hyp cm hypotenuse of a right triangle * (typically dstance measured by ir ranger) * * OUTPUT * returns angle steptype * * note: if steptype is INTERLEAVE then a step is (0.9 degrees/step), * otherwise SINGLE is assumed (1.8 degrees/step). */ int arcSine(double a_opp, double a_hyp){ double d_x; float d_angle; d_x = a_opp/a_hyp; if (-1 > d_x || d_x > 1) { // domain error digitalWrite(ledPin, HIGH); Serial.print("domain error x = "); Serial.println(d_x); return(-1); } d_angle = asin(d_x)/radians_step; // calculate angle in degrees return int(d_angle); } // convert to steps

7.6

EEPROM Functions

7.6.1 Ardunio Library Functions


The Arduino write and read functions are all you need to read and write a byte of data to EEPROM

EEPROM.write(address, value)
Parameters address: the location to write to, starting from 0 (int) value: the value to write, from 0 to 255 (byte) Example
#include <EEPROM.h> void setup() { for (int i = 0; i < 512; i++) EEPROM.write(i, i); } void loop() { }

EEPROM.read(address)
Parameters address: the location to read from, starting from 0 (int) Returns the value stored in that location (byte) Example
#include <EEPROM.h> int a = 0; int value; void setup() { Serial.begin(9600); } void loop() { value = EEPROM.read(a); Serial.print(a); Serial.print("\t"); Serial.print(value); Serial.println(); a = a + 1; if (a == 512) a = 0; delay(500); }

//Extension to EEPROM library by Tim Hirzel #include<avr/EEPROM.h> float readFloat(int address){ float out; eeprom_read_block((void *) &out, (unsigned char *) address , 4 ); return out; } void writeFloat(float value, int address){ eeprom_write_block((void *) &value, (unsigned char *) address, 4); }

Potrebbero piacerti anche