/* * FINAL PROJECT: Robotic Flower - Kasubana * Ming-Zher Poh (mp282) * Yuk Kee Cheung (yc294) * Date: 3/31/05 * * */ #include #include #include #define begin { #define end } #include /* --------------- Angles: 0, 14, 28, 42, 56, 70, 84 (Center) - 100 steps -- using 84 -------------------- */ // Variable Declaration unsigned int time, i, j, k; // counters unsigned char num, cycle; // counters for electrodes and cycles unsigned char activate; // device ready signal unsigned int Ain; // low byte of ADC //unsigned int safe_time; // safety timer //unsigned char power, lock; signed int Efield[10], base[10], diff[10], base_diff; // reference values and differences unsigned char state[9] = {0b00110101, // motor state (half step) 0b00100100, 0b00110110, 0b00010010, 0b00111010, 0b00101000, 0b00111001, 0b00010001, 0b00110101}; unsigned char index; // index to state array int max_value, max_index; // activated electrode info unsigned char angle; // flower position // ISR interrupt [TIM0_COMP] void timer0_compare (void) // 1 ms time base begin time++; // increment counter // safe_time++; // safety timer end // Function Prototypes void initialize(void); // initializes program void turn_left(void); // turn left function void turn_right(void); // turn right function void main (void) begin initialize(); while (1) begin if (time == 200 ) // after 30 ms begin time = 0; // reset counter //PORTD ^= 0b10000000; // toggle LED i++; // toggle electrode num++; // count electrode switch (i) begin case 1: PORTB = 0b00001011; // Ref A break; case 2: PORTB = 0b00011011; // Ref B break; case 3: PORTB = 0b00011001; // electrode 1 break; case 4: PORTB = 0b00000101; // electrode 2 break; case 5: PORTB = 0b00010101; // electrode 3 break; case 6: PORTB = 0b00001101; // electrode 4 break; case 7: PORTB = 0b00011101; // electrode 5 break; case 8: PORTB = 0b00000011; // electrode 6 break; case 9: PORTB = 0b00010011; // electrode 7 break; end // switch delay_ms(1); // allow electrode to be activated // get electrode reading ADCSR.6 = 1; // start another conversion while(ADCSR.6 == 1) {} // wait for conversion to be completed Ain = (ADCL>>6); // get low byte Efield[i] = Ain + ((int)ADCH<<2); // add to high byte if (!activate) begin if (i == 9) begin i = 0; // reset counter cycle++; // increment counters end // num = 9 if (cycle == 5) // ready to take in data begin activate = 1; // start real measurement for (k=1; k<10; k++) base[k] = Efield[k]; // set base values end // cycle = 5 end // if NOT activated if (activate) begin // update bases if (Efield[1] < 900) base_diff = base[1]-Efield[1]; // detect change in base value if (i>2) begin base[i] = base[i] - base_diff; end diff[i] = base[i] - Efield[i]; // compute difference // print values if ((diff[i] > 31)) printf("E[%d]: %d value [%d]: %d base [%d]: %d\n\r", i, diff[i], i, Efield[i], i, base[i]); //results to hyperterm else printf ("E[%d]: 0 value [%d]: %d base [%d]: %d\n\r", i, i, Efield[i], i, base[i]); if (i==9) begin i = 0; // reset probe counter base[1] = base[1]-base_diff; // update new ref value end max_value = 0; // reset max value max_index = 0; // determine max electrode for (j=3;j<10;j++) // cycle through 7 electrodes begin if ((diff[j]>31) && (Efield[j]<1023)) begin if (diff[j] > max_value) // compare values begin max_value = diff[j]; // store max value max_index = j; // store max index end // if diff end end // for loop // if (lock == 0) // begin if (max_index <= 2) begin TCCR2=0b00000001; // no hand // power = 0; end else begin TCCR2 = 0b01101001; // turn on PWM // power = 1; end // end // unlocked /* // safety feature if (safe_time == 30000) // after half a minute begin safe_time = 0; // reset timer if (lock==0) // if unlocked begin if (power == 1) // if nitinol is on begin lock = 1; // lock end // end if power end // end if lock if (lock) begin lock = 0; // unlock end end */ if (max_value > 6) begin switch (max_index) begin case 3: // electrode 1 if (angle > 0) begin turn_left(); angle--; end break; case 4: // electrode 2 if (angle > 14) begin turn_left(); angle--; end else if (angle < 14) begin turn_right(); angle++; end break; case 5: if (angle > 28) begin turn_left(); angle--; end else if (angle < 28) begin turn_right(); angle++; end break; case 6: if (angle > 42) begin turn_left(); angle--; end else if (angle < 42) begin turn_right(); angle++; end break; case 7: if (angle > 56) begin turn_left(); angle--; end else if (angle < 56) begin turn_right(); angle++; end break; case 8: if (angle > 70) begin turn_left(); angle--; end else if (angle < 70) begin turn_right(); angle++; end break; case 9: if (angle > 84) begin turn_left(); angle--; end else if (angle < 84) begin turn_right(); angle++; end break; // default: // PORTC = 0; // motor off end // switch end // if max // printf("Angle = %d Max Value = %d Max Index = %d\n\r", angle, max_value, max_index); end // if activated end // if count end // while end // main void turn_right(void) begin if (index == 0) index = 8; // if end of array, restart at 0 else index--; // increment index to turn PORTC = state[index]; // set output end // turn_left void turn_left(void) begin if (index == 8) index = 0; // if end of array, restart at 0 else index++; // increment index to turn PORTC = state[index]; // set output end // turn_right void initialize (void) begin // set up ports DDRA = 0; // PORT A is an input (E-field sensor -> A/D converter) DDRD = 0xff; // PORT D is an output (LEDs) D.7 DDRB = 0x1f; // PORT B0-B4 is an output (Electrode select) DDRC = 0xff; // PORT C is an output (motor drive) PORTC = 0; // motor off PORTD = 0; // nitinol PWM // set up timer 0 TIMSK = 2; // turn on timer 0 cmp match ISR OCR0 = 249; // set to 1ms tick TCCR0 = 0b00001011; // set prescalar to 64, turn on clear-on-match //init A/D convertor ADMUX = 0b01100000; // interval voltage reference ADCSR = 0b11000111; // initial values: angle = 42; i = 0; max_value = 0; max_index = 0; activate = 0; OCR2 = 60; //init the UART UCSRB = 0x18; UBRRL = 103; printf("Sensing E-field...\n\r"); /* base[1] = 751; base[2] = 742; base[3] = 553; base[4] = 467; base[5] = 449; base[6] = 452; base[7] = 405; base[8] = 444; base[9] = 493; */ // turn on ISR #asm sei #endasm end