Society of Robots - Robot Forum
Software => Software => Topic started by: ChrisMcC on February 27, 2009, 06:06:08 PM
-
Hi folks. This is my first post so I'd like to start by thanking everyone who's contributed to this site. It's a fantastic resource. Places like this remind you of humanity's positive side.
Anyway, I'm building a robot with my son. It's based on the $50 robot but will use the Maxbotics sonar for object avoidance.
So far I've built the circuit on a breadboard and it's fine. I'm hooked up to the PC through the AVRISP Mk II and can program the ATMega8. The servos are working fine. I'm familiar enough with C, if a bit rusty.
So now I just need to work with the sonar. I've been reading the ATMega8 and Maxbotics datasheets (the full one for the MCU) and scouring the forums here and anywhere else that seems useful.
My thoughts on how to use the sonar are as follows
1. Connect (other than the power) just the PW pin. From my reading of the datasheet this should default the RX pin to constant reading, which is fine by me.
2. PW would be wired to PC1(ADC1) (Pin 24 on the datasheet).
3. When PC1 goes high, start a timer.
4. When PC1 goes low, record timer value and reset.
5. Calculate distance based of the length of the pulse / 2.
6. Initiate a turn if the distance is below a threshold. (by the by; does anyone know why threshold only has one 'h' in the middle? It's not a joke, it's just puzzled me for a while)
Now, I'm completely prepared for all of that to be utterly wrong. Or should that be utterly prepared to be completely wrong? Hmm...
Sorry. Back to the plot.
I've read through tutorials and such like on timers and while they seem a wee bit complex, I'm sure I could get one going on it's own. What I've not found, is an example of using a timer the way I plan to; having it basically monitor a pin and react to what happens on it.
If my approach is right, can anyone help with this?
Many thanks in advance
Chris
-
A quick and dirty answer is to use a local variable rather than a timer eg;
..... Ask sonar to send a ping ........
iint16_t counter=0;
// Loop until we get a response back
while( response in progress){
counter++;
}
// Have now got a value in counter which is linear to the time (all other interrupts aside)
More elegant stuff out there - but thats a reasonable estimate for general usage.
-
Thanks for that Webbot.
I had considered using something along the lines of what you described but in terms of complexity, it seems simpler to have the sonar take care of the transmit and receive. And given that the Maxbotics provides that functionality I'd like to utilize it.
Of course, thinking about it, there's an element of what I want in your answer. In your method, I'd still have to be waiting for the status of a pin to change, once the pulse went out. Then when the pin goes low, do calculations and make decisions based on that.
So for both approaches, I need to do something similar to get feedback from the sensor.
I'm hoping someone can give a more detailed answer of how to pick up on the pin changes. For the continuous pinging I'd need to be reading a pin to see when it goes from low to high and from high to low. If I can do that, I can run any code I like off of those events.
Thanks again Webbot.
Chris
-
Ok. I've been back with the Mega8 datasheet, looking at configuring pins for I/O.
When it talks about using pins as output, you need to write logic 1 or 0 to the pin you're working with.
When it talks about using pins as input, it describes it in terms of the voltage being high or low.
So, does that mean that when my sensor sets the pin (PC1) high, the PINC1 bit would be read as a logic 1?
If so, then I just need to keep checking the value and start my timer when it reads 1 and stop the timer when it reads 0.
Am I heading in the right direction here?
-
Yes your going in the right direction. Sorry I'm only drip feeding info rather than a pre-made solution - but if you can find out why stuff works then you'll learn a load more.
Then you can do:
int counter=0;
while(read input from (PORTC, PC1) is in middle of pulse){
counter++;
}
Then counter gives you a value according to the pulse.
When you want a more accurate version then use the timer. This requires some more hardware knowledge so you may need to check the datasheet again....
... set the prescaler to a non-zero value to activate the timer at the start of your program....
TCNT = 0; // clear the timer
while(read input from (PORTC, PC1) is in middle of pulse){
.. do nothing ..
}
uint8_t duration = TCNT; // read the timer
Note how the returned value will depend on your processor frequency and on the prescaler value.
The Axon library contains code for this kind of stuff - but that is for a different processor (ATMega640) so wont work on the Mega8. You could compare both datasheets to work out how it works and translate it - but that may take more effort!