/* De olika biblioteken som ska inkluderas */ #include #include #include #include /* Definiering av globala variabler och konstanter */ #define F_CPU 16000000UL // klockhastigheten för delay.h #define SPEED_MIN 50 // hastighetsbegränsing #define SPEED_MAX 100 // hastighetsbegränsing #define ACTION_TIME 2000 // tid för vanliga handlingar milisec #define MOOD_IMPROVEMENT_TIME 600 // tiden för horror att sjunka med ett i milisec #define CAUTION_TIME 3000 // tiden för försiktighet efter högt ljud i milisec #define LOOK_FORWARD 150 // servo fram i mikrosekunder/10 #define LOOK_LEFT 120 // servo vänster i mikrosekunder/10 #define LOOK_RIGHT 180 // servo höger i mikrosekunder/10 #define RANGESENSOR 0 // ADMUX address till avståndssensorn #define LDR_LEFT // ADMUX och extern mux addres till vänster LDR #define LDR_LEFT_CENTER // ADMUX och extern mux addres till vänster-fram LDR #define LDR_CENTER // ADMUX och extern mux addres till fram LDR #define LDR_RIGHT_CENTER // ADMUX och extern mux addres till höger-fram LDR #define LDR_RIGHT // ADMUX och extern mux addres till höger LDR #define LDR_TOP // ADMUX och extern mux addres till rygg LDR #define HAPPY_BEEP 1 // typ av ljud #define SCARED_BEEP 2 // typ av lijud #define NORMAL_BEEP 3 // typ av lijud #define FOOD_BEEP 4 // typ av lijud #define CLOSE_RANGE 400 // värde för range sensorn #define SERVO_TRAVEL 700 // tid för servot att flytta på sig i milisec #define MOTOR_STOP 0 // motorbroms #define MOTOR_FORWARD 1 // båda motorer fram #define MOTOR_BACKWARD 2 // båda motorer bak #define MOTOR_ROTATE_LEFT 3 // vänster motor bak höger motor fram #define MOTOR_ROTATE_RIGHT 4 // vänster motor fram höger motor bak #define HORROR_LIMIT 70 // gränsvärde för flykt #define HUNGER_LIMIT 80 // gränsvärde för matsökande #define FULLNESS_LIMIT 20 // gränsvärde för glädjerus #define HAPPINESS_LIMIT 30 // gränsvärde för glädjerus #define FOODSOURCE 900 // gränsvärde för matkälla #define SHELTER 300 // gränsvärde för skydd #define NORMAL 0 // sinnestillstånd #define HAPPY 1 // sinnestillstånd #define HUNGRY 2 // sinnestillstånd #define SCARED 3 // sinnestillstånd #define AVOID 4 // sinnestillstånd volatile unsigned char motoRight, motoLeft, servoGoal, led[24], motorProportion[2], mood, beepType; volatile unsigned int microSecX10, pwmMicroSecX10,servoInPlace, switch_ADC, hunger, horror, ldr[6], ldr_lowrange[6], range[3], cautionTime, ledTime, moodTime, servoInPlace, b[8]; volatile long miliSec, actionTime, beepTime, cautiousTime; void motorDir(char); void avoid(void); /* Initieringsfunktioner */ void io_init(){ // IO riktning DDRA |= (1< 99){ miliSec++; microSecX10 = 0; if (beepTime > 0) beepTime--; if (actionTime > 0) actionTime--; if (cautiousTime > 0) cautiousTime--; if (ledTime > 0) ledTime--; if (moodTime == 0) moodTime = MOOD_IMPROVEMENT_TIME; else moodTime--; if (servoInPlace > 0) servoInPlace--; } pwmMicroSecX10++; if (pwmMicroSecX10 >= 1999){ //20ms upprepning pwmMicroSecX10 = 0; PORTD |= (1<= servoGoal) //150 = 1,5ms PORTD &= ~(1< HORROR_LIMIT) horror = 100; else if (cautionTime == 0){ motorDir(MOTOR_STOP); cautionTime = CAUTION_TIME; } else{ horror = 100; cautionTime = 0; }*/ } ISR (INT1_vect){ // den här ISR körs när switchar aktiveras if (PIND & (1< 1 && i < 22){ led[i]++; led[i-1]--; led[i-2]--; led[i+1]++; led[i+2]++; } if (ledTime == 0) // räkna ut tid till nästa byte. mellan 1 och 10 milisec ledTime = hunger * 9 / 1024 + 1; } void updateLed(){ // uppdaterar lysdioderna över i2c char n; for (n = 0; n <= 20; n++){ TWCR = (1<= FOODSOURCE){ motorDir(MOTOR_STOP); beepType = FOOD_BEEP; return; } motorDir(MOTOR_FORWARD); if (ldr_lowrange[0] > ldr_lowrange[2] || ldr_lowrange[0] > ldr_lowrange[2]) motorProportion[0], motorProportion[1] = 1, 3;//motor prop vänster else if (ldr_lowrange[3] > ldr_lowrange[2] || ldr_lowrange[4] > ldr_lowrange[2]) motorProportion[0], motorProportion[1] = 3, 1;//motor prop höger else motorProportion[0], motorProportion[1] = 3, 3;//motor prop fram } void scared(){ // leta mörker if (ldr[5] <= SHELTER){ motorDir(MOTOR_STOP); beepType = SCARED_BEEP; return; } motorDir(MOTOR_FORWARD); if (ldr_lowrange[0] < ldr_lowrange[2] || ldr_lowrange[0] < ldr_lowrange[2]) motorProportion[0], motorProportion[1] = 1, 3; //motor proportioner vänster else if (ldr_lowrange[3] < ldr_lowrange[2] || ldr_lowrange[4] < ldr_lowrange[2]) motorProportion[0], motorProportion[1] = 3, 1; //motor proportioner höger else motorProportion[0], motorProportion[1] = 3, 3; //motor proportioner fram } void avoid(){ // backa och kör åt annat håll static char tic; if (actionTime == 0 && tic == 0){ motorDir(MOTOR_BACKWARD); actionTime = ACTION_TIME / 2; tic++; } if (actionTime != 0) return; if (range[0] >= CLOSE_RANGE){ if (range[1] >= CLOSE_RANGE){ if (range[2] >= CLOSE_RANGE){ // om alla tre rangevärden är >= CLOSE_RANGE motorDir(MOTOR_BACKWARD); motorProportion[0], motorProportion[1] = 3, 3; // motor proportioner fram actionTime = ACTION_TIME / 2; } else{ // om vänster och fram rangevärde är >= CLOSE_RANGE motorDir(MOTOR_ROTATE_RIGHT); actionTime = ACTION_TIME / 2; } } else if (range[2] >= CLOSE_RANGE){ // om vänster och höger rangevärde är >= CLOSE_RANGE motorDir(MOTOR_BACKWARD); motorProportion[0], motorProportion[1] = 3, 3; // motor proportioner fram actionTime = ACTION_TIME / 2; } else{ // om vänster rangevärde är >= CLOSE_RANGE motorDir(MOTOR_FORWARD); actionTime = ACTION_TIME / 2; motorProportion[0], motorProportion[1] = 3, 1; //motor proportioner höger } } else if (range[2] >= CLOSE_RANGE){ if (range[1] >= CLOSE_RANGE){ // om höger och fram rangevärde är >= CLOSE_RANGE motorDir(MOTOR_ROTATE_LEFT); actionTime = ACTION_TIME / 2; } else{ // om höger rangevärde är >= CLOSE_RANGE motorDir(MOTOR_FORWARD); actionTime = ACTION_TIME / 2; motorProportion[0], motorProportion[1] = 1, 3;//motor proportioner vänster } } else if (range[1] >= CLOSE_RANGE){ // om fram rangevärde är >= CLOSE_RANGE motorDir(MOTOR_BACKWARD); motorProportion[0], motorProportion[1] = 3, 3; // motor proportioner fram actionTime = ACTION_TIME / 2; } else{ tic = 0; mood = NORMAL; } } void decision(){ static int i; if (actionTime != 0 && (PIND & (1< HORROR_LIMIT){ mood = SCARED; for (i = 0; i < 6; i++) ldr_lowrange[i] = ldr[i] / 8; } else if (hunger > HUNGER_LIMIT){ mood = HUNGRY; for (i = 0; i < 6; i++) ldr_lowrange[i] = ldr[i] / 8; } else if (hunger < FULLNESS_LIMIT && horror < HAPPINESS_LIMIT) mood = HAPPY; else mood = NORMAL; } void action(){ //beep(); //updateLedPulse(); //updateLed(); if (cautionTime != 0) // väntar på mer oljud return; switch (mood){ // kör rätt beteende case NORMAL: normal(); break; case HAPPY: happy(); break; case HUNGRY: hungry(); break; case SCARED: scared(); break; case AVOID: avoid(); break; } motoRight = (hunger * (SPEED_MAX - SPEED_MIN) / 1023 + SPEED_MIN) * motorProportion[1] / 3; motoLeft = (hunger * (SPEED_MAX - SPEED_MIN) / 1023 + SPEED_MIN) * motorProportion[0] / 3; OCR0 = motoRight; // uppdaterar PWM duty OCR2 = motoLeft; // uppdaterar PWM duty } int main(){ servoGoal = LOOK_FORWARD; io_init(); // io-riktning ext_int_init(); // externa interrupts timer1_init(); // startar timer1 pwm_init(); // startar PWM adc_init(); //i2c_init(); sei(); // aktiverar globala interrupts //mood = NORMAL; //beepType = NORMAL_BEEP; //led[0], led[1], led[2], led[3], led[4], led[5] = 254, 127, 0, 0, 0, 0; //led[6], led[7], led[8], led[9], led[10], led[11] = 0, 0, 0, 0, 0, 0; //led[12], led[13], led[14], led[15], led[16], led[17] = 0, 0, 0, 0, 0, 0; //led[18], led[19], led[20], led[21], led[22], led[23] = 0, 0, 0, 0, 0, 127; //motorProportion[0], motorProportion[1] = 3, 3; volatile unsigned char n = 0; while(1){ ADMUX = (ADMUX & 0xF8)|RANGESENSOR; // clears the bottom 3 bits before ORing run_ADC(); _delay_ms (300); range[1] = ADC; if (range[1] < CLOSE_RANGE){ PORTB |= (1<