Don't ad-block us - support your favorite websites. We have safe, unobstrusive, robotics related ads that you actually want to see - see here for more.
0 Members and 1 Guest are viewing this topic.
//Photovore atmega328p @ 1MHz//Be sure to set optimization in IDE to zero for delay to work#include <avr/io.h>#include <avr/interrupt.h>//volatile unsigned int clock_2millisecond=0;//^^^Uncomment the above if you want to time anything else in//the timer ISR. Remeber to reset it to zero if it gets above //500.//Add a clock_second, ...minute, etc., counter if you need to//This is used to count milliseconds by 2volatile unsigned int servo_2millisecond=0;volatile unsigned int sensor_2millisecond=0;uint8_t leftEye = 0;uint8_t rightEye = 0;//speed range is -20 to 20, negative speeds = reversevolatile int leftSpeed = 0;volatile int rightSpeed = 0;void DelayLoops(uint16_t nloops){ while(nloops>0){ nloops--; }}void InitADC() { ADMUX=(1<<REFS0)|(1<<ADLAR); // Aref=AVcc, Left Adjusted ADMUX|=0b00000101; //Start by reading pinC5 ADCSRA|=(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Prescalar=8, be sure to change for different MCU Hz ADCSRA|=(1<<ADEN); //Enable ADC ADCSRA|=(1<<ADSC); //Start ADC ADCSRA|=(1<<ADIE); //Enable ADC Interrupt }int main() { //Set PinD as Output DDRD = 0xFF; //Clear PORTC 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 with the debugger // and will differ with other frequencies OCR1A=2000; //Enable the Output Compare A interrupt (Will be TIMSK, without the '1', on MCU's with only 1 of these timers) TIMSK1|=(1<<OCIE1A); //Enable interrupts globally sei(); //infinite loop while(1); //This will be skipped if optimization is used return 0;}//ISR called every 2ms. why 2? had rounding issues w/ 1msISR(TIMER1_COMPA_vect) { clock_2millisecond++; servo_2millisecond++; if(servo_2millisecond==10) { servo_2millisecond=0; //Send Servo Signals //Right Servo (PORTD Pin 2) PORTD|=0b00000010; DelayLoops(81+rightSpeed); PORTD=0x00; //Left Servo (PORTD Pin 1) PORTD|=0b00000001; DelayLoops(81-leftSpeed); PORTD=0b00010000; } if(clock_2millisecond>=500){ clock_second++; clock_2millisecond=0; }}//Called when A/D Conversion completesISR(ADC_vect){ if((ADMUX & 0b00000111) == 0b00000101){ //If current pin is C5 // read left photosensor, the +20 is an adjustment I made // to account for a diffence the sensors were reading // when the light was in front of the bot and may need adjusting leftEye=ADCH + 20; ADMUX&=0b11111000; //Clear pin register (right 3 bits only) ADMUX|=0b00000001; //Set pin to C1 if(leftEye < rightEye-8) // The -8 acts as a threshhold rightSpeed=-20; else rightSpeed=20; //Small delay, might not be necessary. I added this on the //same debug run as the other changes that got the bot to //work. This might make the ISR too long if you add more //code. If it makes trouble, take it out or enable nested //interrupts. DelayLoops(50); //start next conversion ADCSRA|=(1<<ADSC); } else if((ADMUX & 0b00000111) == 0b00000001){ //If current pin is C1 rightEye=ADCH; ADMUX&=0b11111000; //Clear pin ADMUX|=0b00000101; //Set pin to C5 if(rightEye < leftEye-8) leftSpeed=-20; else leftSpeed=+20; DelayLoops(50); ADCSRA|=(1<<ADSC); }}
It is heavily commented. I wrote it, so ask me if you don't get any of it.