//FILENAME: DC_Motor.c //AUTHOR: Nate Bassett //DESCRIPTION: Prelab #7, Fall 2005 // This program collects data for different tachometer speeds of a motor // and stores them to an array. The tachometer values are read in on // PA0. #include #include #include #include "sio.c" /* ---------------Deadband Limits-------------------*/ #define c_kinetic_pos 0x02 //Static Friction #define c_kinetic_neg 0x02 //Make the value positive #define c_static_pos 0x04 //Kinetic Friction #define c_static_neg 0x04 //Make the value positive #define c_max 255 //Limit count #define c_min 255 //Make the value positive #define UBRR_VALUE 51 //Change to correct baud rate #define CLK_ms 10 //Set the updates for every 10ms, same as CLK_ms /*-------------Function Prototypes-----------------*/ int deadband(int c_wanted); void PWM_init(); void PWM_update(int value); void PWM_setup(); int v_output(int v_adjusted); void IO_setup(); void IO_update(); unsigned AD_read(); void AD_setup(); int arraymaker(); /*------------------Global Variables----------------------*/ int db_correct = 0; //Deadband correction is off by default int j = 0; int moving = 0; //Assume it starts without moving int count = 0; //A count value to be output on Port B int table[100]; /*-----------------------Clock Interrupt Stuff----------------------------*/ unsigned int CNT_timer1; //the delay time volatile unsigned int CLK_ticks = 0; //the current number of ms volatile unsigned int CLK_seconds = 0; //the current number of seconds SIGNAL(SIG_OVERFLOW0) //the interrupt calls this function { CLK_ticks += CLK_ms; if(CLK_ticks >= 1) //the number of interrupts between output changes { CLK_ticks = CLK_ticks - 1; CLK_seconds++; IO_update(); } TCNT0 = CNT_timer1; } void CLK_setup() //start the interrupt service routine { TCCR0 = (0< 0) //A positive output { c_adjusted = c_pos + (unsigned)(c_max - c_pos) * c_wanted / c_max; if(c_adjusted > c_max) c_adjusted = c_max; } else //The output value must be negative { c_adjusted = -c_neg - (unsigned)(c_min - c_neg) * -c_wanted / c_min; if(c_adjusted < -c_min) c_adjusted = -c_min; } return c_adjusted; } void PWM_setup() { DDRD = 0xFF; //Set as an output on PD7 TCCR2 = _BV(WGM21) | _BV(WGM20) | _BV(COM21) | _BV(CS20); OCR2 = 0x00; //Set the initial duty cycle to 100% } //Call this routine once the program starts void PWM_init() { DDRD |= (1 << PD5); //Set PWM outputs DDRC |= (1 << PC0) | (1 << PC1); //Set motor direction outputs on Port C //Using OCR1 TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10); //Turn on both PWM outputs on counter 1 TCCR1B = _BV(CS11); //Set the internal clock to /8 } //To update the PWM output void PWM_update(int value) { if(value > 255) value = 255; if(value < 0) value = 0; OCR2 = value; //duty cycle } //Call the interrupt loop int v_output(int v_adjusted) { int RefSignal; //The value to be returned if(v_adjusted >= 0) { //Set the direction bits to CW on, CCW off PORTC = (PINC & 0xFC) | 0x02; //bit 1 on, 0 off if(v_adjusted > 255) //clip output over maximum { RefSignal = 255; } else {RefSignal = v_adjusted;} } else { //Need to reverse output sign //Set the direction bits to CW off, CCW on PORTC = (PINC & 0xFC) | 0x01; //bit 0 on, 1 off if(v_adjusted < -255) //clip output below minimum { RefSignal = 255; } else { RefSignal = -v_adjusted; //Flip sign } } return RefSignal; } void IO_setup() { DDRB = 0xFF; //all of port B is outputs PWM_setup(); AD_setup(); DDRA = (unsigned char)0; //set port A to outputs } //This routine will run once per interrupt for updates void IO_update() { if(db_correct == 0) PWM_update(count); else PWM_update(deadband(count)); if(count > 0) arraymaker(); } int arraymaker() { table[j] = AD_read(); j++; if(j > 99) { j=0; count=0; moving=0; } return 0; } void AD_setup() { ADMUX = 0xC0; //set the input to channel 0 ADCSRA = 0xE0; //turn on ADC and set to free running } unsigned AD_read() { return (ADCW >> 2); //Returns digital output from AD register } void delay(int ticks) //Ticks are approx. 1 ms { volatile int i,j; for(i=0;i 255) count = 255; if(count ==1) //It has just started moving { moving = 0; IO_update(); delay(200); moving = 1; } outint(count); outln(" = count, INCREMENTED"); } else if(c == '-') { if(--count < -255) count = -255; if(count == -1) //It has just started moving { moving = 0; IO_update(); delay(200); moving = 1; } outint(count); outln(" = count, DECREMENTED"); } else if(c == '0') { count = 0; outint(count); outln(" = count"); } else if(c == '1') { count = 28; outint(count); outln(" = count"); } else if(c == '2') { count = 56; outint(count); outln(" = count"); } else if(c =='3') { count = 84; outint(count); outln(" = count"); } else if(c =='4') { count = 112; outint(count); outln(" = count"); } else if(c =='5') { count = 140; outint(count); outln(" = count"); } else if(c =='6') { count = 168; outint(count); outln(" = count"); } else if(c =='7') { count = 196; outint(count); outln(" = count"); } else if(c =='8') { count = 224; outint(count); outln(" = count"); } else if(c =='9') { count = 255; outint(count); outln(" = count"); } else if(c == 'p') { outint(count); outln(" = count"); } else if(c =='d') { if(db_correct == 0) { db_correct = 1; outln("Deadband Correction ON"); } else { db_correct = 0; outln("Deadband Correction OFF"); } } else if(c =='s') { count = 0; moving = 0; outint(count); outln(" = count, MOTOR STOPPED"); } else if(c =='h') { outln(" + : Increment Value"); outln(" - : Decrement Value"); outln(" d : Enable or Disable (default) Deadband Comp."); outln(" r : Makes the Process Idle"); outln(" a : Prints the Array Values to the Screen"); outln(" 0-9 : Sets the Cd Value to a Value Between 0 and 255 in Equal Divisions"); outln(" s : Stop the Motor"); outln(" q : Quit"); } else if (c == 'r') //breaks the 1 sec loop and sets j and count to 0 { outint(AD_read()); outln(" = AD value\n"); outint(count); //count = 0; //j = 0; } else if (c == 'a') //Dumps the entire array onto screen { int k; for (k=0; k<100; k++) outint (table[k]); } else if (c == 'q') { count = 0; moving = 0; outint(count); outln(" = count, QUITTING!!"); break; } } sio_cleanup(); return 1; }