/******************************************************************************** ********************************EYE ROBOT CODE*********************************** ********************************************************************************/ #include #include #include #include #include "sed1335.h" #include "graphics.h" #include "touch.h" #include "gui.h" #include "bitmaps.h" #include //State Machine Definitions #define GreenScan 1 //RGB scanning states #define RedScan 2 #define BlueScan 3 #define Photoscantop 4 //position photodetector scanning states #define Photoscanbottom 5 #define Photoscanleft 6 #define Photoscanright 7 #define Right 8 #define Up 9 #define Left 10 #define Down 11 #define MoveState 12 #define SearchDone 13 #define TrackObject 14 #define Red_High 2 #define Red_Mid 1 //color scale levels #define Red_Low 0 #define Green_High 2 #define Green_Mid 1 #define Green_Low 0 #define Blue_High 1 #define Blue_Low 0 void initialize(void); void draw_main_gui(void); void tracking(void); // to enter track mode void searching(void); //to enter search mode void backsearch(void);// GUI setup functions void backtrack(void); void trackbackmore(void); void trackmore(void); void printred(void); //prints out color labels void printgreen(void); void printblue(void); void printwhite(void); void printyellow(void); void printdarkred(void); void printdarkgreen(void); void printpink(void); void EyeTrack(void); //Variable Declarations unsigned int count; //counter to time the state machine unsigned char AinR, AinG, AinB; //ADC for red, green, blue LED's unsigned char AinPhotobottom, AinPhotoleft, AinPhotoright, AinPhotoTop; //ADC for photodiodes unsigned char Ainright_old, Ainleft_old, Ainbottom_old, Aintop_old; //previous ADC for photodiodes signed char LeftDeriv, RightDeriv, TopDeriv, BottomDeriv; //State Machine Variables unsigned char MainState; //main state machine that controls ADC, and the eye movement control unsigned char TrackState; //controls eye movement in tracking mode unsigned char ControlMove, TrackMove; //Flags for control mode and track mode //Servo Variables unsigned int pwidth, pwidth2, widthLR, widthUD; //variables that control PWM for servos //Color Variables unsigned char red, green, blue; unsigned char color; //color that the eye is currently detecting unsigned char InputColor; //the color that user wants to track unsigned char colorcount; //# of consecutive cycles that the eye detects correct (specified) color -> used for tracking unsigned char misscount; //# of consecutive cycles that the eye detects incorrect (specified) color -> used for tracking unsigned char ShakeFlag; //flag used for Eye Twitching movement unsigned char k; //Timer0 Compare Match Interrupt interrupt [TIM0_COMP] void timer0_compare(void) { count++; //creating a time base of approx 20ms if (140 == count) //150 count = 0; //The following creates period 20ms pulse that has pulse width of widthLR and widthUD if(pwidth == 148) //count up 20ms periods (LR Motor) { PORTC.6 = 1; pwidth = 0; } else if (pwidth == widthLR) //widthLR adjusts pulse of servo that moves left/right { PORTC.6 = 0; } pwidth++; if(pwidth2 == 148) //counts up 20ms periods (UD Motor) { PORTC.7 = 1; pwidth2 = 0; } else if (pwidth2 == widthUD)//widthUD adjusts pulse of servo that moves up/down { PORTC.7 = 0; } pwidth2++; } void no_task() //DO NOT REMOVE! used to delete gui widget functions { } void main(void) { unsigned short i; struct Point* coord; initialize(); nRS(1); // turn off LCD reset SED1335_init(); SED1335_clear_text_layer(); SED1335_clear_graphics_layer(); TOUCH_init(); TOUCH_get_coord(); // skip first conversion, puts TOUCH to sleep draw_main_gui(); // display main gui on LCD while(1) { if (count == 0) //poll for states { switch (MainState) //sampling for 7 values. RGB and 4 position sensors. { case RedScan: ADMUX = 0b01100000; //RED LED -> A.0 ADCSR.6=1; while(ADCSR.6==1){} //delay until start conversion flag is completely set (used for accurate ADC sampling) AinR = ADCH-105; //scale adc value MainState = GreenScan; //Quantize the red detection to 3 regions if(AinR >= 9) red = Red_High; else if (AinR >= 5) red = Red_Mid; else red = Red_Low; break; case GreenScan: ADMUX = 0b01100010; //GREEN LED -> A.2 ADCSR.6=1; while(ADCSR.6==1){} AinG = ADCH-117; //scale adc value MainState = BlueScan; //Quantize the green detection to 3 regions if (AinG >= 53) green = Green_High; else if (AinG >= 27) green = Green_Mid; else green = Green_Low; break; case BlueScan: ADMUX = 0b01100001; //BLUE LED -> A.1 ADCSR.6=1; while(ADCSR.6==1){} AinB = ADCH; //scale adc value MainState = Photoscanbottom; //Quantize the blue detection to 2 regions if (AinB >= 65) blue = Blue_High; else blue = Blue_Low; break; case Photoscanbottom: ADMUX = 0b01100011; //BOTTOM PHOTODETECTOR -> A.3 ADCSR.6=1; while(ADCSR.6==1){} Ainbottom_old = AinPhotobottom; AinPhotobottom = ADCH; BottomDeriv = AinPhotobottom - Ainbottom_old; //Calculate derivative by subtracting the past ADC from the current MainState = Photoscanleft; break; case Photoscanleft: ADMUX = 0b01100100; //LEFT PHOTODETECTOR -> A.4 ADCSR.6=1; while(ADCSR.6==1){} Ainleft_old = AinPhotoleft; AinPhotoleft = ADCH; LeftDeriv = AinPhotoleft - Ainleft_old; //Calculate derivative by subtracting the past ADC from the current MainState = Photoscanright; break; case Photoscanright: ADMUX = 0b01100101; //RIGHT PHOTODETECTOR -> A.5 ADCSR.6=1; while(ADCSR.6==1){} Ainright_old = AinPhotoright; AinPhotoright = ADCH; RightDeriv = AinPhotoright - Ainright_old; //Calculate derivative by subtracting the past ADC from the current MainState = Photoscantop; break; case Photoscantop: ADMUX = 0b01100110; //TOP PHOTODETECTOR -> A.6 ADCSR.6=1; while(ADCSR.6==1){} Aintop_old = AinPhotoTop; AinPhotoTop = ADCH; TopDeriv = AinPhotoTop - Aintop_old; //Calculate derivative by subtracting the past ADC from the current MainState = MoveState; break; case MoveState: GUI_poll(); //poll the input information from the touchscreen //Color Schemes (9 colors) //Use combination of ADC of Red, Green and Blue LED's to detect 9 different colors if (red == Red_High && green == Green_High && blue == Blue_Low) color = 1; //yellow else if (red == Red_High && green == Green_Low && blue == Blue_Low) color = 2; //red else if (red == Red_High && green == Green_Mid && blue == Blue_High) color = 3; //pink else if (red == Red_Mid && green == Green_Low && blue == Blue_Low) color = 4; //dark red else if (red == Red_Mid && green == Green_High && blue == Blue_Low) color = 5; //green else if (red == Red_Low && green == Green_Mid && blue == Blue_Low) color = 6; //dark green else if (red == Red_Low && green == Green_High && blue == Blue_High) color = 7; //teel else if (red == Red_Low && green == Green_Mid && blue == Blue_High) color = 8; //blue else if (red == Red_High && green == Green_High && blue == Blue_High) color = 9; //white else color = 0; //no color if (TopDeriv > 50 ) //if the derivative wrt time is very high, //then perform a temporary twitch ShakeFlag = 1; else ShakeFlag = 0; //CONTROL MODE if (ControlMove == 1) //if control flag is set { coord = TOUCH_get_coord(); //poll coordinate if screen is being touched if (ShakeFlag == 1 && k < 10) //perform the twitch for a short time { k++; if (k%2 == 0) { widthLR++; widthUD++; //turn up and left } else { widthLR--; widthUD--; //turn down and right } if(k == 10) { ShakeFlag = 0; //shut off the twitch k = 0; } } //Use touchscreen to move eye up down, left right if (((*coord).x) !=500 && (((*coord).x) <=317 )) widthLR = 10 - (((*coord).x)/30-4); if ((((*coord).y) !=500) && (((*coord).y) >=160) && (((*coord).y) <=230)) widthUD = 11; else if ((((*coord).y) !=500) && (((*coord).y) !=76) && (((*coord).y) <=70) && (((*coord).y) >=0 )) widthUD = 9; else if ((((*coord).y) !=500) && (((*coord).y) !=76) && (((*coord).y) < 160) && (((*coord).y) >80)) widthUD = 10; //display the current color that the eye sees if (color == 1) SED1335_bitmap(yellowlabel, 200, 150); else if (color == 2) SED1335_bitmap(redlabel, 200, 150); else if (color == 3) SED1335_bitmap(pinklabel, 200, 150); else if (color == 4) SED1335_bitmap(darkredlabel, 200, 150); else if (color == 5) SED1335_bitmap(greenlabel, 200, 150); else if (color == 6) SED1335_bitmap(darkgreenlabel, 200, 150); else if (color == 7) SED1335_bitmap(teallabel, 200, 150); else if (color == 8) SED1335_bitmap(bluelabel, 200, 150); else if (color == 9) SED1335_bitmap(whitelabel, 200, 150); } //TRACK MODE else if (TrackMove == 1) //if track flag is set EyeTrack(); MainState = RedScan; break; } //END SWITCH CASE STATEMENT } //END if (count==0) } //END WHILE LOOP } //END MAIN // functions that are tied to the color gui widgets void printred() { SED1335_bitmap(redlabel, 200, 150); InputColor = 2; TrackState = Right; } void printgreen() { SED1335_bitmap(greenlabel, 200, 150); InputColor = 5; TrackState = Right; } void printblue() { SED1335_bitmap(bluelabel, 200, 150); InputColor = 8; TrackState = Right; } void printyellow() { SED1335_bitmap(yellowlabel, 200, 150); InputColor = 1; TrackState = Right; } void printdarkgreen() { SED1335_bitmap(darkgreenlabel, 200, 150); InputColor = 6; TrackState = Right; } void printdarkred() { SED1335_bitmap(darkredlabel, 200, 150); InputColor = 4; TrackState = Right; } void printpink() { SED1335_bitmap(pinklabel, 200, 150); InputColor = 3; TrackState = Right; } void printwhite() { SED1335_bitmap(whitelabel, 200, 150); InputColor = 9; TrackState = Right; } void printteal() { SED1335_bitmap(teallabel, 200, 150); InputColor = 7; TrackState = Right; } //backsearch() is a GUI function that takes action when user presses "back" button from Search mode //to return to the main gui menu void backsearch() { GUI_remove_button(1,no_task); SED1335_clear_text_layer(); SED1335_clear_graphics_layer(); SED1335_bitmap(title, 0, 0); GUI_add_button(190,60,104,27,trackbutton,tracking); GUI_add_button(190,120,104,27,searchbutton,searching); ControlMove = 0; //search mode flag is down //motor goes back to neutral(center) position widthLR = 10; widthUD = 10; } //searching() is a function that takes action when user selects Search Mode from the main frame gui void searching() { GUI_remove_button(2,no_task); SED1335_clear_text_layer(); SED1335_clear_graphics_layer(); SED1335_bitmap(eyeframe, 60,100); GUI_add_button(250,190,64,43,backlabel,backsearch); ControlMove = 1; //search mode flag is set } //backsearch() is a function that takes action when user presses "back" button from Track mode //to go back to the main gui menu void backtrack() { GUI_remove_button(6,no_task); SED1335_clear_text_layer(); SED1335_clear_graphics_layer(); SED1335_bitmap(title, 0, 0); GUI_add_button(190,60,104,27,trackbutton,tracking); GUI_add_button(190,120,104,27,searchbutton,searching); TrackMove = 0; //track mode flag is down //motor goes back to neutral postion widthLR = 10; widthUD = 10; } //tracking() is a function that sets the appropriate flags //for tracking and enters a gui menu to choose selectable colors // void tracking() { GUI_remove_button(2,no_task); SED1335_clear_text_layer(); SED1335_clear_graphics_layer(); GUI_add_button(0,0,96,29,redlabel,printred); GUI_add_button(150,0,96,29,greenlabel,printgreen); GUI_add_button(0,50,96,29,bluelabel,printblue); GUI_add_button(150,50,96,29,darkgreenlabel,printdarkgreen); GUI_add_button(250,190,64,43,backlabel,backtrack); GUI_add_button(0,100,96,29,morelabel,trackmore); TrackMove = 1; //track mode flag is set TrackState = Right; } //trackmore() is a function that allows users to enter a gui //to select more colors void trackmore() { GUI_remove_button(6,no_task); SED1335_clear_text_layer(); SED1335_clear_graphics_layer(); GUI_add_button(0,100,96,29,darkredlabel,printdarkred); GUI_add_button(150,100,96,29,yellowlabel,printyellow); GUI_add_button(0,150,96,29,teallabel,printteal); GUI_add_button(150,150,96,29,whitelabel,printwhite); GUI_add_button(0,200,96,29,pinklabel,printpink); GUI_add_button(250,190,64,43,backlabel,trackbackmore); } //trackbackmore() is a function that goes back to the first track menu void trackbackmore() { GUI_remove_button(6,no_task); SED1335_clear_text_layer(); SED1335_clear_graphics_layer(); GUI_add_button(0,0,96,29,redlabel,printred); GUI_add_button(150,0,96,29,greenlabel,printgreen); GUI_add_button(0,50,96,29,bluelabel,printblue); GUI_add_button(150,50,96,29,darkgreenlabel,printdarkgreen); GUI_add_button(250,190,64,43,backlabel,backtrack); GUI_add_button(0,100,96,29,morelabel,trackmore); } //draw_main_gui() brings up the title screen void draw_main_gui () { unsigned short i; struct Point* coord; GUI_init(); SED1335_bitmap(title, 0, 0); GUI_add_button(190,60,104,27,trackbutton,tracking); GUI_add_button(190,120,104,27,searchbutton,searching); } //EyeTrack() implements the tracking mode movement //Initially the eye rotates in a square path looking for a user specified color. //If it is detected, the eye then tracks the color when that color moves void EyeTrack(void) { switch(TrackState) { case Right: //move right if (widthLR < 14) widthLR++; else TrackState = Up; break; case Up: //move up and look for color if (color == InputColor) //If user specified color is detected, goto SearchDone state TrackState = SearchDone; else if (widthUD < 11) widthUD++; else TrackState = Left; break; case Left: //move left and look for color if (color == InputColor) //If user specified color is detected, goto SearchDone state TrackState = SearchDone; else if (widthLR > 6) widthLR--; else TrackState = Down; break; case Down: //move down and look for color if (color == InputColor) //If user specified color is detected, goto SearchDone State TrackState = SearchDone; else if (widthUD > 9) widthUD--; else TrackState = Right; break; case SearchDone: //If you were detecting specified color, and suddenly fail, then goto TrackObject State misscount = 0; if (color == InputColor) //keep track of consecutive times the eye sees specified color colorcount++; else colorcount == 0; if (color != InputColor && colorcount > 1) TrackState = TrackObject; break; case TrackObject: colorcount = 0; if (color != InputColor) misscount++; else misscount = 0; if (misscount == 20) TrackState = SearchDone; //Left/Right Tracking Movement //If right side is brighter than left, and right's derivative of intensity is greater than left's, rotate right if ((abs(RightDeriv) > abs(LeftDeriv)) && (AinPhotoright > AinPhotoleft+8)) { if(widthLR < 15) widthLR ++; } //If left side is brighter than right, and left's derivative of intensity is greater than right's, rotate left else if ((abs(RightDeriv) < abs(LeftDeriv)) && (AinPhotoright < AinPhotoleft +8)) { if (widthLR >5) widthLR --; } //Up/Down Tracking Movement //If top side is brighter than bottom, and top's derivative of intensity is greater than bottom's, rotate up if ((abs(TopDeriv) > abs(BottomDeriv)) && (AinPhotoTop > AinPhotobottom)) { if (widthUD >9) widthUD --; } //If bottom side is brighter than top, and bottom's derivative of intensity is greater than top's, rotate down else if ((abs(TopDeriv) < abs(BottomDeriv)) && (AinPhotoTop < AinPhotobottom )) { if (widthUD < 11) widthUD ++; } break; } } //END EyeTrack(); //INITIALIZE void initialize(void) { DDRC = 0xff; //motor output (C.6, C.7) //init the A to D converter ADMUX = 0b01100000; //enable ADC and set prescaler to 1/128*16MHz=125,000 //and clear interupt enable //and start a conversion ADCSR = 0b11000111; TIMSK=2; //turn on timer 0 cmp match ISR OCR0 = 34; //set the compare re to 34 time ticks TCCR0=0b00001011; // clock/64 and enable interrupt count = 0; //initialize counters to 0 MainState = RedScan; //initialize RGB state TrackState = Right; TrackMove =0; //flag for Track Mode ControlMove = 0; //flag for Control Mode pwidth = 0; pwidth2 = 0; widthLR = 10; //motorLR start at center widthUD = 10; //motorUD start at center //Initialize derivative values LeftDeriv = 0; RightDeriv = 0; TopDeriv = 0; BottomDeriv = 0; color = 0; InputColor = 10; red = Red_Low; green = Green_Low; blue = Blue_Low; colorcount = 0; misscount = 0; ShakeFlag = 0; #asm sei #endasm }