310 likes | 433 Views
South Jersey Robotics Club. July 2014 Meeting Presentation Topic – Arduino (cont). Agenda. New Member Introductions! Show and Tell Maker Fare trip planning More Arduino (aka, small robot programming) Next meeting planning… Lunch!. Introductions. Please state your: Name
E N D
South Jersey Robotics Club July 2014 Meeting Presentation Topic –Arduino (cont)
Agenda • New Member Introductions! • Show and Tell • Maker Fare trip planning • More Arduino (aka, small robot programming) • Next meeting planning… • Lunch!
Introductions • Please state your: • Name • Interests in this area • Software? Electronics? Mechanical? • Which platforms (Arduino, Pic, NXT, Vex, RasPi, etc.) • Level of experience • What you want to get out of the club • Quick description of any projects you’re currently working on or want to start
Show and Tell • New Raspberry Pi Model B+! http://www.adafruit.com/products/1914 I’m getting to “play” (well, test) this now:
NYC World Maker Fare 2014 • September 20+21 • Do we want to do a group ride? • Don’t have to decide this month, just keep it in mind / pencil it into your calendar… • (Wait, people still have paper calendars?!?)
Arduino continued… • First off – getting 1… • Microcenter has the Mega 2560 on sale for $19.99! (I picked up 2 on Monday). • There seemed to be some confusion about functions, and objects. So I figured we should work on that… • Also going to take you guys through the evolution of a project, so you can see how I attack it…
A little about the project… • So, I built the Makerscanner 3D laser scanner setup. • Let’s see it in action…. • Problems: • Only does 1 face at a time • Need multiple scans to make a full object • Tedious to manually sweep the laser. Easy to bump the unit…
A little about the project… • Ok, so let’s automate this. Robotics to the rescue! • To do this we need: • A servo to sweep the laser back and forth • A stepper motor to turn the turntable • A button to indicate when we’re ready to move to the next stage of the scan process • And LCD to show the status to the user • A buzzer to indicate to get the user’s attention
What’s the difference in motor types? • Servo • Good accuracy • Usually limited rotational range (although there are continuous rotation servos). • You push a value and it goes to that rotational position. • Relatively low rotational speed. • DC motor - You give it power, it spins, but no control over how much it spins (just how fast, depending on the PWM). • Need to use encoders to detect how far it’s turned... • Easy to exceed the desired turn amount. • Stepper – sort of best of both. • Turns a specific amount on each “pulse” (usually in 1/nth of a turn). • Can go fast, but can also be pretty exacting.
First steps…. • Figure out your circuit… • I recommend laying out everything you know you’re going to need • See if anything requires specific pins • See if there are any conflicts • If there are no conflicts, wire it up and keep track of the function of each pin • Remember, all grounds MUST tie together somewhere! • Don’t mix motor power (Vmotor) (battery) with the circuitry power (Vcc) (+5) • I’ve already wired everything up on the board…
The Stepper Motor • Gonna cheat with this one – using the Arduino motor shield! • For the rest, don’t get hung up on the exact pins on the Arduino side – we’re using the Mega so we have TONS of I/O to spare. Just be concerned with not reusing pins, and making sure we use PWM-enabled pins where they’re called for.
Building up the software… • Every one of these has example code in the Arduino Examples folder. So we’ll use these as guidance on how to do each function. • We’ll start from the Servo example and build up from there.. • Then we’ll build functionality, 1 step at a time.
void loop() { for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees { myservo.write(pos); delay(15) } for(pos = 180; pos>=0; pos-=1) { myservo.write(pos); delay(15); } } #include <Servo.h> Servo myservo; intpos = 0; // variable to store the servo position void setup() { myservo.attach(10); // attaches the servo on pin 10 to the servo object }
Library void loop() { for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees { myservo.write(pos); delay(15) } for(pos = 180; pos>=0; pos-=1) { myservo.write(pos); delay(15); } } Servo Object #include <Servo.h> Servo myservo; intpos = 0; // variable to store the servo position void setup() { myservo.attach(10); // attaches the servo on pin 10 to the servo object } Method call on the object
Let’s try it! • So this should basically take care of sweeping the laser back and forth… But how do we tell the code that we want to wait for a button press when we think the scan is complete? • We need to add in some button code! • Let’s look at the Button example program…
const intbuttonPin = 35; // the number of the pushbutton pin const intledPin = 13; // the number of the LED pin // variables will change: intbuttonState = 0; // variable for reading the pushbutton status void setup() { // initialize the LED pin as an output: pinMode(ledPin, OUTPUT); // initialize the pushbutton pin as an input: pinMode(buttonPin, INPUT); } void loop() { // read the state of the pushbutton value: buttonState = digitalRead(buttonPin); // check if the pushbutton is pressed. // if it is, the buttonState is HIGH: if (buttonState == HIGH) { // turn LED on: digitalWrite(ledPin, HIGH); } else { // turn LED off: digitalWrite(ledPin, LOW); } }
void loop() { for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees { // in steps of 1 degree myservo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position checkButton(); } for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees { myservo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position checkButton(); } // check to see if the button was pressed... // if not, then sweep back and forth again if(pressed) { pressed = FALSE; // now do something, but what??? Serial.println("A button had been pressed!"); } } #include <Servo.h> const int SERVOPIN = 10; const int BUTTONPIN = 35; // define our global variables.... Servo myservo; // create servo object to control a servo intpos = 0; // variable to store the servo position boolean pressed = FALSE; // variable to store if the button was pressed void setup() { pinMode(BUTTONPIN, INPUT); myservo.attach(SERVOPIN); // attaches the servo on pin 10 to the servo object Serial.begin(9600); } void checkButton() { if(!pressed && digitalRead(BUTTONPIN)) { pressed=TRUE; Serial.println("Button pressed!"); } }
Let’s try it! • Ok, so you’re probably wondering why I checked the previous status of the pressed variable? • Well, what if I press the button and then release it? The first check will see the press, but then the 2nd would say “It’s not pressed”, which would defeat the purpose. So instead, we’ll reset the variable once we get down to doing something with the button.
Let’s try it! • Debouncing… • Yeah, I didn’t really do that here… • What does Debouncing mean? • Checking the button pin twice quickly to make sure it really was pressed (and not just registering pushed because of noise). • Ok, so now we need to actually DO something because we pressed the button! • Let’s make the turntable rotate, and then wait until the user presses the button again to indicate that they’re ready to capture again. • First, let’s look at the Stepper example…
#include <Stepper.h> // Map our pins to constants to make things easier to keep track of const intpwmA = 3; const intpwmB = 11; const intbrakeA = 9; const intbrakeB = 8; const intdirA = 12; const intdirB = 13; // The amount of steps for a full revolution of your motor. // 360 / stepAngle const int STEPS = 800; // Initialize the Stepper class Stepper myStepper(STEPS, dirA, dirB); void setup() { // Set the RPM of the motor myStepper.setSpeed(30); // Turn on pulse width modulation pinMode(pwmA, OUTPUT); digitalWrite(pwmA, HIGH); pinMode(pwmB, OUTPUT); digitalWrite(pwmB, HIGH); // Turn off the brakes pinMode(brakeA, OUTPUT); digitalWrite(brakeA, LOW); pinMode(brakeB, OUTPUT); digitalWrite(brakeB, LOW); } // end setup() void loop() { // Move the motor X amount of steps myStepper.step(STEPS); // Pause delay(2000); }
// Handle sweeping the servo back and forth. void sweep() { for (pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees { // in steps of 1 degree myservo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position checkButton(); } for (pos = 180; pos >= 0; pos -= 1) // goes from 180 degrees to 0 degrees { myservo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position checkButton(); } } // Handle checking to see if the button was pressed. void checkButton() { if (!pressed && digitalRead(BUTTONPIN)) { pressed = true; Serial.println("Button pressed!"); } } #include <Servo.h> #include <Stepper.h> // Sets up all our pins // {Snipped to save space…. } // The amount of steps for a full revolution of your motor. // 360 / stepAngle const int STEPS = 800; // define our global variables.... Servo myservo; // create servo object to control a servo int pos = 0; // variable to store the servo position boolean pressed = false; // variable to store if the button was pressed // Initialize the Stepper class Stepper myStepper(STEPS, dirA, dirB); void setup() { pinMode(BUTTONPIN, INPUT); myservo.attach(SERVOPIN); // attaches the servo on pin 10 to the servo object // Set the RPM of the motor myStepper.setSpeed(30); // Turn on pulse width modulation pinMode(pwmA, OUTPUT); digitalWrite(pwmA, HIGH); pinMode(pwmB, OUTPUT); digitalWrite(pwmB, HIGH); pinMode(brakeA, OUTPUT); digitalWrite(brakeA, LOW); pinMode(brakeB, OUTPUT); digitalWrite(brakeB, LOW); Serial.begin(9600); }
void loop() { myservo.write(90); // set the laser to the calibrate position Serial.println("Press button to start calibration"); while(!pressed) { checkButton(); } // if we get here the button was pressed. pressed = false; delay(2000); Serial.println("Press button when calibration done"); while(!pressed) { checkButton(); } pressed=false; delay(2000); Serial.println("Sweeping!"); // if we get here the button was pressed // start scanning! and do it until we detect a press while(!pressed) { sweep(); } // ok the button was pressed, so stop sweeping pressed=false; delay(2000); Serial.println("Save the file, then press button to advance turntable"); while(!pressed) { checkButton(); } // ok pressed, advance the stepper moter pressed=false; Serial.println("Turning table..."); myStepper.step(STEPS); // 10 degrees on the stepper, not nec the turntable. // Ok ,reset and do it all over again! Serial.println("Done!"); }
So what’s this doing? • Prompt the user that we’re resetting for next scan. • Setting laser to 90 degrees to calibrate, and waiting for button press to start scanning • Performing the sweep back and forth repeatedly until the button is pressed again. • Stop sweeping, rotate the turntable 10 degrees, and then start all over again!
Let’s add in the LCD and speaker… • So, what if we wanted to put the prompt onto a LCD instead of the serial port? #include <LiquidCrystal.h> LiquidCrystal lcd(43, 41, 51, 49, 47, 45); //set the proper pin #’s you used here… void setup() { // set up the LCD's number of columns and rows: lcd.begin(16, 2); …. • Then everywhere we had a Serial.println(), replace it with this lcd.print( text ); • For the Speaker, just add a line like this: tone(33, 200, 1000); // (pin#, frequency, duration)
Questions??? • Build up your functionality a little at a time • Get something working, then add in the next piece. • Save backup copies! • Remember, loop() will get executed over and over until power is removed. Plan for this in your code! • Writing outto Serial Console is a great debugging tool • Remember that it slows down your program, and timing can be important! • Whenever you do something more than 1-2 times in your code, consider moving it into a function • Try to keep setup() and loop() short and simple to read!!!! • Makes the code smaller overall… Smaller=easier! • LOTS of good libraries out there!!! • Use them instead of reinventing the wheel. • The Examples are your friend! Make use of them!
Next meeting • What’s a good date? August 9? 16? • Location? • Topic? • Some Ideas: • OpenCV for beginners • Intro to ROS (Robot Operating System) • Maze Solving • Obstacle detection and avoidance/tracking • Web based robot control interface • Line following / line sensors / PID control • Basic Electronics/ Circuits • Mini Sumo • IMUs + GPS • Filtering (Particle / Extended Kahlman) • Encoders • Raspberry Pi primer • How to use an O-Scope / Logic Analyzer • How to use EagleCAD • How to Solder