Society of Robots - Robot Forum
Software => Software => Topic started by: greywanderer012345 on August 18, 2012, 01:54:09 PM
-
I have my servos programmed and working well, even without PWM. (I built admin's board). I can set the servos to any speed with my code. Now I'm trying to get the light sensors to work. I wrote my program so that the servo opposite the photoresistor allowing a higher voltage would turn at full speed and the other would remain still. However, the servos stop and go seemingly randomly when I run the code, even if I cover one photoresistor and shine a light on the other. I'm using the medium-sized photoresistors from radioshack. They have around 1kOhm when shined with light and about 400kOhm when in a dark space. I am using a 100kOhm resistor. The photoresistors are mounted under the chassis. My MCU is the atmega328p at 1MHz. I have searched the forum and troubleshooted my bot for several hours with no change. I have tested all of the connections several times. None of the pins are shorted. I'm using pins 0 and 5. I also tried to get admin's photovore project to work, just changing the pin numbers, with no luck. With my program, the most I've accomplished is observing a small change in the servo behavior if I repeatedly cover and uncover one of the photosensors, but this only produces jerking to the same rhythm as my presses. One oddity I noticed was that there is only 8kOhm between power and ground pins for PORTC. Is this a wiring flaw, or due to the connection at the voltage regulator? I can't figure this out. My code is below. Thanks.
//Photovore
#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
//This is used to count milliseconds by 2
volatile unsigned int clock_2millisecond=0;
volatile unsigned int servo_2millisecond=0;
volatile unsigned int sensor_2millisecond=0;
volatile unsigned int clock_second=0;
uint16_t leftEye=0;
uint16_t rightEye=0;
volatile int leftSpeed = 0;
volatile int rightSpeed = 0;
void DelayLoops(uint16_t nloops){
while(nloops>0){
nloops--;
}
}
void InitADC() {
ADMUX=(1<<REFS0); // Aref=AVcc
ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Enable ADC, w/ Prescalar=8
}
uint16_t ReadADC(uint8_t ch){
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;
//Start Single Conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing a 1 to it.
//This seems odd, but the end result is a zero in the bit
ADCSRA|=(1<<ADIF);
//Return Result
return(ADC);
}
int main() {
//Set PinD as Output
DDRD = 0xFF;
PORTC= 0x00;
InitADC();
//Set up the timer1
//Set Prescaler to 8 and mode to CTC
TCCR1B=(1<<WGM12)|(1<<CS10);
//The below compare value for 2ms was found empirically for 1MHz with the debugger
//and will differ with other frequencies.
OCR1A=1999;
//Enable the Output Compare A interrupt
TIMSK1|=(1<<OCIE1A);
//Enable interrupts globally
sei();
//infinite loop comparing L&R sensors
while(1){
if(clock_2millisecond>200){
rightEye= ReadADC(0);
leftEye= ReadADC(5);
}
if(rightEye>leftEye){
leftSpeed = 0;
rightSpeed= 20;
}
if(leftEye>rightEye){
leftSpeed = 20;
rightSpeed= 0;
}
}
return 0;
}
//ISR called every 2ms
ISR(TIMER1_COMPA_vect) {
clock_2millisecond++;
servo_2millisecond++;
if(servo_2millisecond==10)
{
servo_2millisecond=0;
//Send Servo Signals
//Right Servo (PORTD Pin 1)
PORTD|=0b00000010;
DelayLoops(81+rightSpeed);
PORTD=0x00;
//Left Servo (PORTD Pin 0)
PORTD|=0b00000001;
DelayLoops(81-leftSpeed);
PORTD=0b00010000;
}
if(clock_2millisecond>=500){
clock_second++;
clock_2millisecond=0;
}
}
-
One end of each photo resistor is connected to an input pin on your micro-controller - what is the other end of the photo resistor connected to?
Or, more to the point, what voltage do you see at the micro input pin when it is light vs. dark?
I'm not sure what you are doing in the code with clock_2millisecond. You compare it to > 200 to do the A/D and reset it = 0 when it gets over 500. Why not just reset it after each A/D?
-
Thanks for the responses
I'm not sure what you are doing in the code with clock_2millisecond. You compare it to > 200 to do the A/D and reset it = 0 when it gets over 500. Why not just reset it after each A/D?
I didn't realize how to use the interrupt when I wrote this code, thinking for some reason, that you used the interrupt only in freerunning mode. I think that the main reason the code didn't work was because the ADC value was not usable how I wrote it into the code.
I did finally get my bot to work. I will post that code, a photo, and video when I get to my other computer.