⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 speed controol of a dc motor
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pic18.h>
#include "serial.h"

#define PWM_TICKS 1

/*Current Gain settings are:
 * Kp = 1600
 * Ki = 400
 */

#define INTEGRAL_CONSTANT (i_gain);
#define PROPORTIONAL_CONSTANT (p_gain);
#define DIFFERENTIAL_CONSTANT (d_gain);
#define JOINT_CONSTANT (j_gain);
#define ARC_CONSTANT (a_gain);
#define STOP_DEADBAND 1
#define PCONTROL_DEADBAND 5
#define MIN_SPEED 1
#define MAX_STEP 1

#define RIGHT_DIRECTION RA4
#define LEFT_DIRECTION RB5

/*Right = A = Bottom*/
#define RIGHT_PWM_H CCPR1L
#define RIGHT_PWM_M DC1B1
#define RIGHT_PWM_L DC1B0

/*Left = B = Top*/
#define LEFT_PWM_H CCPR2L
#define LEFT_PWM_M DC2B1
#define LEFT_PWM_L DC2B0

#define FORWARD_LEFT 1
#define BACKWARD_LEFT 0
#define FORWARD_RIGHT 0
#define BACKWARD_RIGHT 1
#define RIGHT_BRAKE RA2
#define LEFT_BRAKE RA3

#define DEBUG 0
#define DEBUG_ALL 0 
#define USE_SPI
#define USE_EEPROM

#define EEPROM_KP_ADDRESS 0
#define EEPROM_KI_ADDRESS 0x08
#define EEPROM_KD_ADDRESS 0x10
#define EEPROM_KJ_ADDRESS 0x18
#define EEPROM_KA_ADDRESS 0x20

#define SPEED_SET 5
#define DIST_SET 10
#define LEFT_SPEED_SET 15
#define RIGHT_SPEED_SET 20
#define LEFT_DIST_SET 25
#define RIGHT_DIST_SET 30
#define GENERAL_READ 35
#define SHIFTED_DIST 40
#define RESET_DIST 45

void LoopTime(void);
void Initialize(void);
void PwmInitialize(void);
void BlinkAlive(void);
void UpdatePWM(void);
void ManageAccel(void);
void puthex(unsigned int c);
void puthexc(unsigned char c);
void get_params(void);
void write_pwm_left(unsigned int duty_cycle);
void write_pwm_right(unsigned int duty_cycle);
void position_control(void);
void parse_SPI(void);
void set_left_position_target(long new_target);
void set_right_position_target(long new_target);
void write_float_to_eeprom( float value, unsigned int address );
void read_float_from_eeprom( float *value, unsigned int address );

/*JF had made all of these static*/
static long last_count_left = 0;
static long last_count_right = 0;
static long error_integral_left = 0;
static long error_integral_right = 0;
static long last_error_left = 0;
static long last_error_right = 0;
static float joint_integral_error = 0;

volatile long count_left = 0;
volatile long count_right = 0;
unsigned char portb_copy = 0;
volatile long count_left_reference = 0;
volatile long count_right_reference = 0;
volatile long count_left_reference_report = 0;
volatile long count_right_reference_report = 0;
float applied_right = 0;
float applied_left = 0;
long left_tick_target;
long right_tick_target;

char controlling_position = 0;
char position_slowdown = 0;

//SPI parsing flags
char newmessage = 0;
char setspeed = 0;
char setdist = 0;
int interrupt_speed_left;
int interrupt_speed_right;
int interrupt_dist_left;
int interrupt_dist_right;

/*Delete Between These*/
char printmessage = 0;
char spi_temp = 0;
char sawthis = 0;
/*Delete Between THese*/

int desired_target_right =0;
int desired_target_left = 0;
long target_right =0;
long target_left = 0;
float p_gain = 0.01;
float i_gain = 0.01;
float d_gain = 0.00;
float j_gain = 0.00;
float a_gain = 0.00;
volatile char rx_message[8];
char tx_message1[8];
char tx_message2[8];
char *current_tx_message = tx_message1;
char *newest_tx_message = tx_message1;

void main(void)
{
    unsigned char PWM_counter = 0;
    char c;

    TRISA = 0xFE; 
	//RA0 = 1;
    Initialize();
    PwmInitialize();

    serial_init();
	//RA0 = 1;

    while(1)
    { 	
        if(RA1 == 0 && kbhit())
        {
            if(kbhit())
            {
                c = getch();
            }
			if(c == 'q')
			{
				printf("QuickBug\n\r");
				asm("goto 0x6002");
			}
			else if(c == 'r')
            {
                desired_target_left = -desired_target_left;
                desired_target_right = -desired_target_right;
            }
			else if(c == 'a')
			{
				desired_target_left = -25;
				desired_target_right = 25;
			}
			else if(c == 'w')
			{
				desired_target_left = 25;
				desired_target_right = 25;
			}
			else if( c == 'd')
			{
				desired_target_left = 25;
				desired_target_right = -25;
			}
			else if(c == 'x')
			{
				desired_target_left = -25;
				desired_target_right = -25;
			}
            else if(c == 's')
            {
                desired_target_left = 0;
                desired_target_right = 0;
            }
            else if(c == 'b')
            {
                RA2 ^= 1;
				RA3 ^= 1;
                printf("Brakes: %d, %d", RA2, RA3);
            }
			else if(c == 'p')
			{
				set_left_position_target(0);
            	set_right_position_target(3375);	
			}
			else if(c == '[')
			{
				set_left_position_target(1687);
				set_right_position_target(-1687);
			}
			else if(c == ']')
			{
				set_left_position_target(-1687); 	
				set_right_position_target(1687);
			}
            else 
            {
                write_pwm_left(0);
                write_pwm_right(0);
                get_params();
                count_left = 0;
                count_right = 0;
                last_count_left = 0;
                last_count_right = 0;
                error_integral_left = 0;
                error_integral_right = 0;
                last_error_left = 0;
                last_error_right = 0;
            }
        }
        BlinkAlive();
        PWM_counter++;
        if(PWM_counter == PWM_TICKS)
        {
            PWM_counter = 0;
			if(sawthis)
			{
				putch('T');
				sawthis = 0;
			}
            if(printmessage)
            {
				printmessage = 0;
#if 0  
				putch('.');
                putch('\n'); 
				putch('\r');
                putch('[');
				for( i = 0; i < 8; i++ )
				{
					puthexc( rx_message[i] );
                    putch( ' ' );
				}
				putch(']');
                putch(' ');
#endif
				
                if( WCOL )
                {
                    putch( 'C' );
                    WCOL = 0;
                }
                if( SSPOV )
                {
                    putch( 'O' );
                    SSPOV = 0;
                }
            }
            parse_SPI();
            position_control();
            UpdatePWM();
            ManageAccel();
        }
        LoopTime();
    }
}

/* parse_SPI ******************************************************************
 * This function will run when the newmessage flag is non-zero.  When it runs,
 * parse_SPI reads the recieved message (rx_message) and carries out sets
 * requested by the controlling processor.
 * ***************************************************************************/
void parse_SPI(void)
{
    if (newmessage)
    {
		putch(newmessage);
		newmessage = 0;
		if(setspeed)
		{
			putch('s');	
			setspeed = 0;  //we've delt with speed update
			GIEL = 0;
			desired_target_left = interrupt_speed_left;
			desired_target_right = interrupt_speed_right;
			GIEL = 1;
			if((desired_target_left < 0) && (desired_target_right < 0))
			{
				putch('-');
			}
		}	
		if(setdist)
		{
			putch('d');
			setdist = 0; //we've delt with the distance update
			GIEL = 0;
            set_left_position_target(interrupt_dist_left);
            set_right_position_target(interrupt_dist_right);
			GIEL =1;
		}
    }
}


void set_left_position_target(long new_target)
{
	GIEH = 0;  //disable interrupts so we don't get wack reference data
    count_left_reference = count_left;
	GIEH = 1;  //reenable interrupts
    left_tick_target = new_target;
 	controlling_position |= 0x01;	
	
	if(((new_target > 0) && (desired_target_left < 0)) || 
	   ((new_target < 0) && (desired_target_left > 0)))
    {
        desired_target_left = -desired_target_left;
    }
}


void set_right_position_target(long new_target)
{
	GIEH = 0;  //disable interrupts so we don't get wack reference data
    count_right_reference = count_right;
	GIEH = 1;  //reenable interrupts
    right_tick_target = new_target;
	controlling_position |= 0x02;
	
    if(((new_target > 0) && (desired_target_right < 0)) || 
	   ((new_target < 0) && (desired_target_right > 0)))
    {
        desired_target_right = -desired_target_right;
    }
}

void position_control(void)
{
    static int posn_error_left;
    static int posn_error_right;
	
    if(controlling_position)
    {			
		GIEH = 0;
        posn_error_left = left_tick_target - ( count_left - count_left_reference ); 
        posn_error_right = right_tick_target - ( count_right - count_right_reference );
		GIEH = 1;

 		putch('\n');
		putch('\r');
		puthex(posn_error_left);
		putch(' ');
		puthex(posn_error_right);		
		putch('|');
		puthex(count_left);
		putch(' ');
		puthex(count_right);
		putch('|');
		puthex(desired_target_left);
		putch(' ');
		puthex(desired_target_right);
		putch('|');
				
		
		
		/*CONTROL LEFT WHEEL*/

		if(controlling_position & 0x01)
		{
			if((posn_error_left > 0 && desired_target_left < 0) || 
	  	 	   (posn_error_left < 0 && desired_target_left > 0))
   		 	{
				putch('<');
   		     	desired_target_left = -desired_target_left;
	   	 	}
			
			if((posn_error_left < (desired_target_left)) && 
			   (posn_error_left > -(desired_target_left)))
			{
				desired_target_left = 0;
				controlling_position &= 0xFE;
			}
		}
		else
		{
			desired_target_left = 0;
		}

		
		
		/*CONTROL RIGHT WHEEL*/

		if(controlling_position & 0x02)
		{
			if((posn_error_right > 0 && desired_target_right < 0) || 
			   (posn_error_right < 0 && desired_target_right > 0))
	    	{
				putch('>');
	        	desired_target_right = -desired_target_right;
	    	}
			if((posn_error_right < (desired_target_right)) && 
			   (posn_error_right > -(desired_target_right)))
			{
				desired_target_right = 0;
				controlling_position &= 0xFD;
			}
		}
		else
		{
			desired_target_right = 0;
		}
    }
}

void UpdatePWM(void)
{
	/*Remember for this section: 
	 * A = Bottom Port = Left
	 * B = Top Port = Right
	 */
		
    long saved_left;
    long saved_right;
    long diff_left;
    long diff_right;
    long error_left;
    long error_right;
	long distance_left;
	long distance_right;
	long report_distance_left;
	long report_distance_right;
	

    /* We need to disable interrupts here or we'll have a race
     * condition while copying these 2-byte values because the ISR
     * could jump in and change the value under us -- JF
     */
    GIEH = 0;
    saved_left = count_left;
    saved_right = count_right;
    GIEH = 1; 

	distance_left = saved_left - count_left_reference;
	distance_right = saved_right - count_right_reference;

	//This section smooths rapid changes in target speed, and sets
	//the target_left and target_right variables accordingly
	if(1)//(position_slowdown & 0x01) == 0)  //position isn't slowing left wheel
	{
		if((desired_target_left - target_left) > MAX_STEP)
		{
			target_left += MAX_STEP;
		}
		else if ((desired_target_left - target_left) < -MAX_STEP)
		{
			target_left -= MAX_STEP;
		}
		else
		{	
			target_left = desired_target_left;
		}
	}
	
	if(1)//(position_slowdown & 0x02) == 0)  //position isn't slowing right wheel
	{
		if((desired_target_right - target_right) > MAX_STEP)
		{
			target_right += MAX_STEP;
		}
		else if ((desired_target_right - target_right) < -MAX_STEP)
		{
			target_right -= MAX_STEP;
   	    }
	    else
	   	{
	   		target_right = desired_target_right;
	   	}
	}

    diff_left = saved_left - last_count_left;
    diff_right = saved_right - last_count_right;
	
#if 1 //DEBUG
    //putch('\r');
    //putch('\n');
		if(controlling_position){
	 	puthex(diff_left >> 16);
		puthex(diff_left);
	    putch(' ');
	    puthex(diff_right >> 16);
		puthex(diff_right);
	}
#endif

    error_left = target_left - diff_left;
    error_right = target_right - diff_right;
#if DEBUG_ALL
    putch('|');
    puthex(error_left);
    putch(' ');
    puthex(error_right);
#endif

    error_integral_left += error_left;
    error_integral_right += error_right;
	
	if(desired_target_right == desired_target_left && desired_target_right != 0 && desired_target_left != 0)
	{
		joint_integral_error += diff_left - diff_right + ARC_CONSTANT;
	}

    /******** Control Left Wheel ********/
    if( target_left == 0 && desired_target_left == 0 &&
		((diff_left >= -STOP_DEADBAND) && (diff_left <= STOP_DEADBAND)))
    {
        applied_left = error_integral_left * INTEGRAL_CONSTANT;
	}
    else 
    {   
        applied_left = error_integral_left * INTEGRAL_CONSTANT;
		applied_left += error_left * PROPORTIONAL_CONSTANT;
		applied_left += (error_left - last_error_left) * DIFFERENTIAL_CONSTANT;
		if(desired_target_left == desired_target_right)
		{   /*We will only add the straightness gain if we want to go straight*/
			applied_left -= joint_integral_error * JOINT_CONSTANT;
		}
    }
	
    if(applied_left > 1023)
    {
        applied_left = 1023;
    }
    else if(applied_left < -1023)
    {
        applied_left = -1023;
    }

    /******** Control Right Wheel ********/
    if(target_right == 0 && desired_target_right == 0 &&
		((diff_right >= -STOP_DEADBAND) && (diff_right <= STOP_DEADBAND)))
    {
        applied_right = error_integral_right * INTEGRAL_CONSTANT;
    }
    else
    {   
        applied_right = error_integral_right * INTEGRAL_CONSTANT;
        applied_right += error_right * PROPORTIONAL_CONSTANT;
        applied_right += (error_right - last_error_right) * DIFFERENTIAL_CONSTANT;
		if(desired_target_left == desired_target_right)
		{  /*We will only add the straightness gain if we want to go straight*/
			applied_right += joint_integral_error * JOINT_CONSTANT;
		}

    }
	
	if(applied_right > 1023)
    {
        applied_right = 1023;
    }
    else if(applied_right < -1023)
    {
        applied_right = -1023;
    }


    //Loads the outgoing status message
	/* Write into the tx buffer that isn't currently being transmitted */
	if( current_tx_message == tx_message1 )
	{
		newest_tx_message = tx_message2;
	}
	else
	{
		newest_tx_message = tx_message1;
	}
#if 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -