system
August 18, 2009, 1:38am
1
So far I have seen the Blink without delay program and the water buckett program. I just cannot seem to wrap my mind around the concept. Or, how I can apply that to my individual situation. (Sorry for being so dense.)
If someone could give me another example. I have a set of brows on my robot. When I raise the brows, I leave them UP about 1-2 seconds and use a 1000 to 2000 delay. This is right in the middle of my PING and IR scan. So, it makes the whole robot run slow. But, the brows are really cool and I wish to keep them. Someone said that I could use this NO Delay technique in order to pause the brows without pausing the PING scan. I am hopelessly loss trying to understand this. If someone could be so kind to explain this concept to someone who has JUST begun to use 'c'. I finally understand how to do a subroutine, but that took me a week and a half and LOTS of advice.
The reason I activate these during the scan is so the BROWS can go UP when the PING or IR sees something. It is a really cool effect.
Thanks!
Here is some quickly put together and untested code that should get you going.
#include <MegaServo.h>
MegaServo myservo;
// Begin Robot Code
//int micVal;
//int cdsVal;
int irLval; // Left IR
int irCval; // Center IR
int irRval; // Right IR
int i; // Generic Counter
int x; // Generic Counter
int PLval; // Pulse Width for Left Servo
int PRval; // Pulse Width for Right Servo
int cntr; // Generic Counter Used for Determining amt. of Object Detections
int counter; // Generic Counter
int clrpth; // amt. of Milliseconds Of Unobstructed Path
int objdet; // Time an Object was Detected
int task; // Routine to Follow for Clearest Path
int pwm; // Pulse Width for Pan Servo
boolean add; // Whether to Increment or Decrement PW Value for Pan Servo
int distance; // Distance to Object Detected via Ultrasonic Ranger
int oldDistance; // Previous Distance Value Read from Ultrasonic Ranger
float scale = 1.9866666666666666666666666666667; // *Not Currently Used*
int LeftPin = 6; // Left Servo
int RightPin = 9; // Right Servo
int PingServoPin = 5; // Pan Servo
int irLPin = 0; // Analog 0; Left IR
int irCPin = 1; // Analog 1; Center IR
int irRPin = 2; // Analog 2; Right IR
int ultraSoundSignal = 7; // Ultrasound signal pin
int val = 0; // Used for Ultrasonic Ranger
int ultrasoundValue = 0; // Raw Distance Val
int oldUltrasoundValue; // *Not used*
int pulseCount; // Generic Counter
int timecount = 0; // Echo counter
int ledPin = 13; // LED connected to digital pin 13
int pos = 0;
int SPKR = 4;
long browTimer;
int browState;
#define BAUD 9600
#define CmConstant 1/29.034
void setup() {
myservo.attach(11);
pos = 40;
myservo.write(pos);
delay(150);
myservo.detach();
Serial.begin(9600);
pinMode(SPKR, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(LeftPin, OUTPUT);
pinMode(RightPin, OUTPUT);
pinMode(PingServoPin, OUTPUT);
pinMode(irLPin, INPUT);
pinMode(irCPin, INPUT);
pinMode(irRPin, INPUT);
// Beep!
{
for (int i = 0; i<500; i++) { // generate a 1KHz tone for 1/2 second
digitalWrite(SPKR, HIGH);
delayMicroseconds(400);
digitalWrite(SPKR, LOW);
delayMicroseconds(400);
}
for(i = 0; i < 20; i++) {
digitalWrite(PingServoPin, HIGH);
delayMicroseconds(655 * 2);
digitalWrite(PingServoPin, LOW);
delay(20);
}
ultrasoundValue = 600;
i = 0;
}
}
void loop()
{
Look();
Go();
checkBrow();
}
void Look() {
irLval = analogRead(irLPin);
irCval = analogRead(irCPin);
irRval = analogRead(irRPin);
if(irLval > 200) {
BrowUP();
PLval = 850;
PRval = 820;
x = 5;
cntr = cntr + 1;
clrpth = 0;
objdet = millis();
}
else if(irCval > 200) {
BrowUP();
PLval = 850;
PRval = 820;
x = 10;
cntr = cntr + 1;
clrpth = 0;
objdet = millis();
}
else if(irRval > 200) {
BrowUP();
PLval = 650;
PRval = 620;
x = 5;
cntr = cntr + 1;
clrpth = 0;
objdet = millis();
}
else {
x = 1;
PLval = 850;
PRval = 620;
counter = counter + 1;
clrpth = (millis() - objdet);
if(add == true) {
pwm = pwm + 50;
}
else if(add == false) {
pwm = pwm - 50;
}
if(pwm < 400) {
pwm = 400;
add = true;
}
if(pwm > 950) {
pwm = 950;
add = false;
}
digitalWrite(PingServoPin, HIGH);
delayMicroseconds(pwm * 2);
digitalWrite(PingServoPin, LOW);
delay(20);
readPing();
if(ultrasoundValue < 150) { // this value is the closeness of PING will get.
cntr = cntr + 1;
switch(pwm) {
case 400:
x = 7;
PLval = 650;
PRval = 650;
Go();
break;
case 500:
x = 10;
PLval = 650;
PRval = 650;
Go();
break;
case 600:
x = 14;
PLval = 850;
PRval = 850;
Go();
break;
case 700:
x = 10;
PLval = 850;
PRval = 850;
Go();
break;
case 950:
x = 7;
PLval = 850;
PRval = 850;
Go();
break;
}
}
}
if(cntr > 25 && clrpth < 2000) {
clrpth = 0;
cntr = 0;
Scan();
}
}
void Go() {
for(i = 0; i < x; i++) {
digitalWrite(LeftPin, HIGH);
delayMicroseconds(PLval * 2);
digitalWrite(LeftPin, LOW);
digitalWrite(RightPin, HIGH);
delayMicroseconds(PRval * 2);
digitalWrite(RightPin, LOW);
delay(20);
}
}
void readPing() { // Get Distance from Ultrasonic Ranger
timecount = 0;
val = 0;
pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output
digitalWrite(ultraSoundSignal, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(ultraSoundSignal, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(ultraSoundSignal, LOW); // Holdoff
pinMode(ultraSoundSignal, INPUT); // Switch signalpin to input
val = digitalRead(ultraSoundSignal); // Append signal value to val
while(val == LOW) { // Loop until pin reads a high value
val = digitalRead(ultraSoundSignal);
}
while(val == HIGH) { // Loop until pin reads a high value
val = digitalRead(ultraSoundSignal);
timecount = timecount +1; // Count echo pulse time
}
ultrasoundValue = timecount; // Append echo pulse time to ultrasoundValue
// Lite up LED if any value is passed by the echo pulse
if(timecount > 0){
digitalWrite(ledPin, HIGH);
}
}
void Scan() { // Scan for the Clearest Path
oldDistance = 30;
task = 0;
for(i = 1; i < 5; i++) {
switch(i) {
case 1:
//Serial.println("Pos. 1");
pwm = 1125; /// incr. by 100 from 1085
break;
case 2:
//Serial.println("Pos. 2");
pwm = 850; //// increased by 100 from 850
break;
case 3:
//Serial.println("Pos. 3");
pwm = 400;
break;
case 4:
//Serial.println("Pos. 4");
pwm = 235;
break;
}
for(pulseCount = 0; pulseCount < 20; pulseCount++) { // Adjust Pan Servo and Read USR
digitalWrite(PingServoPin, HIGH);
delayMicroseconds(pwm * 2);
digitalWrite(PingServoPin, LOW);
readPing();
delay(20);
}
distance = ((float)ultrasoundValue * CmConstant); // Calculate Distance in Cm
if(distance > oldDistance) { // If the Newest distance is longer, replace previous reading with it
oldDistance = distance;
task = i; // Set task equal to Pan Servo Position
}
}
distance = 50; // Prevents Scan from Looping
switch(task) { // Determine which task should be carried out
case 0: // Center was clearest
x = 28;
PLval = (850);
PRval = (850);
Go();
break;
case 1: // 90 degrees Left was Clearest
x = 14;
PLval = (650);
PRval = (650);
Go();
break;
case 2: // 45 degrees left
x = 7;
PLval = (650);
PRval = (650);
Go();
break;
case 3: // 45 degrees right
x = 7;
PLval = (850);
PRval = (850);
Go();
break;
case 4: // 90 degrees right
x = 14;
PLval = (850);
PRval = (850);
Go();
break;
}
}
void checkBrow()
{
switch (browState)
{
case 1: //Brow Up
if ((millis() - browTimer) > 500)
{
BrowDown();
}
break;
case 2: //Brow Down Waiting to Detach Servo
if ((millis() - browTimer) > 120)
{
myservo.detach();
browState = 0;
}
break;
default:
break;
}
}
void BrowUP()
{
browTimer = millis();
myservo.attach(11);
pos = 0;
myservo.write(pos);
browState = 1;
}
void BrowDOWN()
{
browTimer = millis();
myservo.attach(11);
pos = 40;
myservo.write(pos);
browState = 2;
}
// End Robot Code
system
August 18, 2009, 4:12am
3
Imagine you get a ping. You raise the eyebrows and look at the clock. The time is 8:45:16. You want to keep the brows up for 2 seconds, or until 8:45:18. So everytime you go through Loop, you look at the clock. If it's not time yet, you continue on and do whatever. But if it is time, then you lower the eyebrows.
HTH.
system
August 18, 2009, 12:44pm
4
Thank You Guys, I will try it. This forum Rocks~!
I got this error message:
In function 'void checkBrow()':
error: 'BrowDown' was not declared in this scope
which I do not know what it means.
But, at least I have it in place in the program and an example of a starting place that I can work with to study. I feel we have made a step forward. This is Great!
system
August 18, 2009, 1:18pm
5
You call "BrowDown" in "checkBrow", but you've defined "BrowDOWN".
C/C++ is case-sensitive.
system
August 18, 2009, 1:26pm
6
You are Right! It works now!
You Guys are sooo GOOD!
system
August 18, 2009, 1:49pm
7
I'm not sure why you've got attach/detach calls in the brow routines. Unless you're re-purposing the servo pin, I can't really see the point of this.
system
August 18, 2009, 1:56pm
8
Just plain Ignorance of the 'c' language. I figured that I would save battery life and not wear out the servo from having it stay there so solidly.
system
August 19, 2009, 7:46am
9
rather than checking directly in the loop function which action to perform accordingly to the time, you could also delegate the responsability to run to the "action" themself. proto-thread like system seems really good for this kind of problems...
http://www.sics.se/~adam/pt/
system
August 19, 2009, 1:58pm
10
Thanks, Elwing, this looks interesting. How would I unzip this in windows? It looks like it is made for the Mac which I dearly love but cannot afford right now.
system
August 19, 2009, 2:47pm
11
.tar.gz is just a tar archive inside a gz archive, there are many option to open theses kind of archive, winzip does it just well. the version directly in this website seem quite old, it is simplier, but there is a sourceforge project containing a reimplementation (protothread - Browse Files at SourceForge.net also inside a .tar.gz...) that also contain the scheduler part.
depending on what you want to do you might prefer the version without a scheduler that is too complex for your application... it is up to you...
system
August 19, 2009, 3:58pm
12
I usually use winrar, winace, or winzip, or 7zip. I did not know that it would work. Thanks! I actually prefer the mac platform, but mine is down.