Ejemplo n.º 1
0
int main(void)
{
	m_clockdivide(0);
	unsigned char accel_scale = 0;
	unsigned char gyro_scale = 0;
	int data[9] = {0,0,0,0,0,0,0,0,0};
	m_usb_init();
	m_imu_init(accel_scale, gyro_scale);

    while(1)
    {
		m_wait(10);
		m_imu_raw(data);
		m_usb_tx_int(data[0]);
		m_usb_tx_char('\t');
		m_usb_tx_int(data[1]);
		m_usb_tx_char('\t');
		m_usb_tx_int(data[2]);
		m_usb_tx_char('\t');
		m_usb_tx_int(data[3]);
		m_usb_tx_char('\t');
		m_usb_tx_int(data[4]);
		m_usb_tx_char('\t');
		m_usb_tx_int(data[5]);
		m_usb_tx_char('\n');
		m_usb_tx_char('\r');
    }
}
Ejemplo n.º 2
0
int main(void)
{
	//original data
	int Data[9]={0};
	int RealinputACC = 0;
	int RealinputGyr = 0;
	//variables of flags
	int switchNum = 0;
	int paraDeter = 0;
	//temporary variables for test
	int tmp=0;
	int getValue=0;
	//variables for PID control
	int output;
	int angleHis1=0,angleHis2=0;
	int inputK=0,inputI=0,inputD=0;
	int Output=0;
	int OutputHis1=2000;
	int OutputHis2=2000;
	int KpIni=KPINI,KiIni=KIINI,KdIni=KDINI;
	float Kp = 1;
	float Ki = 0;
	float Kd = 0.5;
	int AngleCali = 0;
	int AngleActual=0;
	// Parameters for speed control
	int speed = 0;
	// PID variables for speed controller
	int speedHis1 = 0, speedHis2 = 0;
	int speedI = 0, speedD = 0;
	int outputSpeed =0;
	
	systemInitial();
	// send back comfirm information to prove that wireless has been connected
	char haha[5]="Hello";
	wireless_string(haha,5);
	wireless_char('\n');
	clear(DDRB,0);
	clear(PORTB,0);
	// using wireless to change parameters of PID controller, and if DIP switch 1 is ON, this can be skipped
	if (!check(PINB,0))
	{
		while(1)
		{
			//m_green(ON);
			int success;
			success = m_rf_read(buffer, packLength);
			if ((success==1)&&(buffer[0]>=45))
			{
				m_green(ON);
				ConvertFinishFlag=1;
			}
			else{
				m_green(OFF);
			}
			if (ConvertFinishFlag==1)
			{
				if (switchNum==0)
				{
					// send back current value of parameter and determine which one should be changed
					wireless_string(buffer,packLength);
					wireless_char(':');
					if ((buffer[0]=='k')&&(buffer[1]=='p'))
					{
						paraDeter = 1;
						wireless_int(KpIni);
					}
					if ((buffer[0]=='k')&&(buffer[1]=='i'))
					{
						paraDeter = 2;
						wireless_int(KiIni);
					}
					if ((buffer[0]=='k')&&(buffer[1]=='d'))
					{
						paraDeter = 3;
						wireless_int(KdIni);
					}
					m_wait(50);
					wireless_char('\n');
					switchNum++;
				}else{
					// change the parameter, and if the input is not a value, it will send back "SayAgain" and wait untill the input is a value
					getValue = atoi(buffer);
					if ((getValue==0)&&(buffer[0]!='0'))
					{
						char Sorry1[8] = "SayAgain";
						wireless_string(Sorry1,8);
						m_wait(50);
						wireless_char('\n');
						m_wait(50);
						switchNum=1;
					}else{
						wireless_string(buffer,packLength);
						m_wait(50);
						wireless_char('\n');
						m_wait(50);
						switchNum=0;
						switch (paraDeter)
						{
							case 1:KpIni=getValue;break;
							case 2:KiIni=getValue;break;
							case 3:KdIni=getValue;break;
						}
					}
				}
				// when the input is "start", the robot will start
				if ((buffer[0]=='s')&&(buffer[1]=='t')&&(buffer[2]=='a')&&(buffer[3]=='r')&&(buffer[4]=='t'))
				{
					break;
				}
				ConvertFinishFlag=0;
				memset(buffer,0,packLength);
				m_wait(100);
			}
		}
	}
	m_green(OFF);
	// Initializing IMU
	while(!m_imu_init(1,0));
	int AngleHis=0;
	// calibrate the balance angle value, the code here is trying to find out offset of the angle
	for (int numpoint=0;numpoint<499;numpoint++)
	{
		if(m_imu_raw(Data))
		{
			RealinputACC = ACCPART*(Data[1]-ACOFFSET);
			RealinputGyr = GYRPART*(GYOFFSET-Data[3]);
			Kalman_Filter(RealinputACC,RealinputGyr);
		}
		AngleHis+=angle;
	}
	AngleCali = AngleHis/500;
	// Enable timer interrupt and global interrupt
	set(TIMSK3 , OCIE3A);
	// Initializing the pin change interrupt which will capture the phase of the signal input of the encoder
	set(PCMSK0 , PCINT4);
	set(PCICR , PCIE0);
	clear(DDRB,4);
	clear(DDRB,5);
	sei();
	// Initializing all the parameters will be used in the PID control of the speed ( or we could say 'displacement')
	Kp = (float)KpIni/1000;
	Ki = (float)KiIni/1000;
	Kd = (float)KdIni/1000;
	float Kps, Kds, Kis;
	int OutputSpeedActual = 0;
	Kps = 4;
	Kds = 5;
	Kis = 0.5;
    while(1)
    {
		if (Timer3Flag==1)		//Here is the control loop, all the data sample process and output should be here
		{
			cli();	//Try to reduce the possibility of changing the data read from IIC, cause multiple device will use the same line and there also different interrupt in the program
			// read data from IMU
			if(m_imu_raw(Data))
			{
				m_red(TOGGLE);
			}
			// make the input value get rid of the offset
			RealinputACC = ACCPART*(Data[1]-ACOFFSET);	//The acceleration input without offset
			RealinputGyr = GYRPART*(Data[3]-GYOFFSET);	//The anglar velocity input without offset
			Kalman_Filter(RealinputACC,RealinputGyr);	//Using the Kalman Filter to get the reliable output of the angle

			// read the changed parameter, because the wireless cannot send float, so change it to float here
			Kp = (float)KpIni/1000;
			Ki = (float)KiIni/1000;
			Kd = (float)KdIni/1000;
			// calibrate the angle value by using the balance offset of the angle
			AngleActual = angle-AngleCali;
			inputK = AngleActual-angleHis1;
			inputI +=AngleActual;

			// PID controller, which you will find that Ki always be zero
			Output = Kp*AngleActual + Ki*inputI + Kd*inputK;
			
			// dead region, which means the value in this region won't give the wheels a speed, so remove it from output to make the output speed linear with the input angle
			if (AngleActual>0)
			{
				OutputHis1 =1823-Output;
			}
			if (AngleActual<0)
			{
				OutputHis1 =2193-Output;
			}
			if (AngleActual==0)
			{
				if (angleHis1>0)
				{
					OutputHis1 =1823;
				}
				if (angleHis1<0)
				{
					OutputHis1 =2193;
				}
				if (angleHis1=0)
				{
					OutputHis1 =OutputHis1;
				}
			}
			if (AngleActual>0)
			{
				OutputHis2 =1857-Output;
			}
			if (AngleActual<0)
			{
				OutputHis2 =2148-Output;
			}
			if (AngleActual==0)
			{
				if (angleHis1>0)
				{
					OutputHis2 =1857;
				}
				if (angleHis1<0)
				{
					OutputHis2 =2148;
				}
				if (angleHis1=0)
				{
					OutputHis2 =OutputHis2;
				}
			}
			// Try to check whether the output value in the limitation
			if (OutputHis1>4000)		//Detect the limitation of the output value
			{
				OutputHis1=4000;
			}else{
				if (OutputHis1<3)
				{
					OutputHis1=3;
				}
			}
			if (OutputHis2>4000)		//Detect the limitation of the output value
			{
				OutputHis2=4000;
			}else{
				if (OutputHis2<3)
				{
					OutputHis2=3;
				}
			}
			// set the output duty cycle
			OCR1B = OutputHis1;	// for B6
			OCR1C = OutputHis2;	// for B7
			
			angleHis2 = angleHis1;	//record value of the angle which will be used in PID controller(differential)
			angleHis1 = AngleActual;//record value of the angle which will be used in PID controller(differential)
			
			Timer3Flag=0;
		}

		if (Timer3Flag2==INTERRUPT1S)	//this condition used to send the wireless data or usb data, cause the frequency here is below 10Hz
		{
			cli();	// same concern with above
			
			speed += numPulse;	//red the the value of holes (net value, which means one direction is positive and the other is negative, here is just a summation)
			
			speedI += speed;
			speedD = speed - speedHis1;
			// PID controller of the speed(displacement actually) 
			outputSpeed = Kps*speed + Kis*speedI + Kds*speedD;
			
			//if (speed>0)
			//{
				//OutputSpeedActual =1800-outputSpeed;
			//}
			//if (speed<0)
			//{
				//OutputSpeedActual =2200-outputSpeed;
			//}
			//if (speed==0)
			//{
				//if (speed>0)
				//{
					//OutputSpeedActual =1800;
				//}
				//if (speed<0)
				//{
					//OutputSpeedActual =2200;
				//}
				//if (speed=0)
				//{
					//OutputSpeedActual =OutputSpeedActual;
				//}
			//}
			// For stability concern, I decide to limit this value, which means the maximum change of duty cycle is 500/4000 = 12.5%
			if (outputSpeed>500)
			{
				outputSpeed=500;
			}
			if (outputSpeed<-500)
			{
				outputSpeed=-500;
			}
			OCR1B = OutputHis1+outputSpeed;
			OCR1C = OutputHis2+outputSpeed;
			
			speedHis2 = speedHis1;
			speedHis1 = speed;
			// all the wireless receiving and sending codes should be wrote here 
			wireless_int(RealinputACC);	// send back value from IMU of acceleration of Y
			wireless_char('\t');
			wireless_int(RealinputGyr);	// send back value from IMU of angular speed around X
			wireless_char('\t');
			wireless_int(AngleActual);	// send back the current angle value
			wireless_char('\n');
			m_green(TOGGLE);
			Timer3Flag2=0;
			// clear the counter
			numPulse = 0;
			sei();
		}
		//if (Timer3Flag3==INTERRUPT10MS)
		//{
		//}				
    }
}
Ejemplo n.º 3
0
int main(void)
{
m_clockdivide(3); //2MHz

//Timer
clear(TCCR1B,CS12);
set(TCCR1B,CS11);
clear(TCCR1B,CS10); //8 precale timer

set(TCCR1B,WGM13);
set(TCCR1B,WGM12);
set(TCCR1A,WGM11);
set(TCCR1A,WGM10);

set(TCCR1A,COM1B1);
clear(TCCR1A,COM1B0);

m_usb_init();

m_imu_init(0,0);

OCR1A = 250;


//read=1;

while(1){

read = m_imu_raw(data);

ax = data[0];
ay = data[1];
az = data[2];
gx = data[3];
gy = data[4];
gz = data[5];

gx_filtered=gx_filtered_prev+gx*dt;
gx_filtered_latest = 0.99*(gx_filtered_old + (gx_filtered-gx_filtered_prev));
//gx_previous = gx;
//gx = gx_previous

//ay_filtered = 0.99*ay_filtered + 0.01*ay;

//a = pow((pow(ax,2) + pow(ay,2) + pow(az,2)),0.5);
//g = pow((pow(gx,2) + pow(gy,2) + pow(gz,2)),0.5);

angle = 0.98*(angle+(gx_filtered*dt))+0.02*ay;


// ay_refined = (ay - ay_offset)*ay_scale;

error = target_angle-angle;
az = (kp * error) + (kd*(error-error_last)/dt) + (ki*sum_error*dt);
OCR1B = abs((kp * error) + (kd*(error-error_last)/dt) + (ki*sum_error*dt))*250/15000;
error_last = error;
sum_error = sum_error + error;
move = OCR1B;


if (angle>0) {
m_red(OFF);
//OCR1B = 65535 - (65535/12500)*abs(move);

clear(DDRB,1);
clear(PORTB,1);

set(DDRB,2);
set(PORTB,2);

set(DDRD,4);
set(PORTD,4);

clear(DDRD,6);
clear(PORTD,6);
} else {
m_red(ON);
//OCR1B = 65535 - (65535/12500)*abs(move);


set(DDRB,1);
set(PORTB,1);

clear(DDRB,2);
clear(PORTB,2);


set(DDRD,6);
set(PORTD,6);

clear(DDRD,4);
clear(PORTD,4);
}

m_usb_tx_string("error\t");
m_usb_tx_int(error);


//        m_usb_tx_string("\tax\t");
//        m_usb_tx_int(data[0]);
//        m_usb_tx_string("\tay\t");
//        m_usb_tx_int(data[1]);
//        m_usb_tx_string("\taz\t");
//        m_usb_tx_int(data[2]);
//        m_usb_tx_string("\tgx\t");
//        m_usb_tx_int(data[3]);
//        m_usb_tx_string("\tgy\t");
//        m_usb_tx_int(data[4]);
m_usb_tx_string("\toffset\t");
m_usb_tx_int(gz);
//        m_usb_tx_string("\ta\t");
//        m_usb_tx_int(a);
//        m_usb_tx_string("\tg\t");
//        m_usb_tx_int(g);
m_usb_tx_string("\tmove\t");
m_usb_tx_int(move);
m_usb_tx_string("\tgx_filtered\t");
m_usb_tx_int(gx_filtered);
m_usb_tx_string("\n");


}
}
Ejemplo n.º 4
0
int main(void) {
	//original data
	int Data[9]={0};
	int RealinputACC = 0;
	int RealinputGyr = 0;

	//variables of flags
	int switchNum = 0;
	int paraDeter = 0;

	//temporary variables for test
	int tmp=0;
	int getValue=0;

	//variables for PID control
	int output;
	int angleHis1=0,angleHis2=0;
	int inputK=0,inputI=0,inputD=0;
	int Output=0;
	int OutputHis1=2000;
	int OutputHis2=2000;
	int KpIni=KPINI,KiIni=KIINI,KdIni=KDINI;
	float Kp = 1;
	float Ki = 0;
	float Kd = 0.5;
	int AngleCali = 0;
	int AngleActual=0;
	
	systemInitial();
	// send back comfirm information to prove that wireless has been connected
	wireless_string(haha,5);
	wireless_char('\n');
	clear(DDRB,0);
	clear(PORTB,0);
	// using wireless to change parameters of PID controller, and if DIP switch 1 is ON, this can be skipped
	if (!check(PINB,0)) {
		transmitEdsCode();

	}
	m_green(OFF);
	// Initializing IMU
	while(!m_imu_init(1,0));
	int AngleHis=0;
	// calibrate the balance angle value, the code here is trying to find out offset of the angle
	for (int numpoint=0;numpoint<499;numpoint++)
	{
		if(m_imu_raw(Data))
		{
			RealinputACC = ACCPART*(Data[1]-ACOFFSET);
			RealinputGyr = GYRPART*(GYOFFSET-Data[3]);
			Kalman_Filter(RealinputACC,RealinputGyr);
		}
		AngleHis+=angle;
	}
	AngleCali = AngleHis/500;
	// Enable timer interrupt and global interrupt
	set(TIMSK3 , OCIE3A);
	set(PCICR,0);
	set(PCMSK0,5);
//	set(PCMSK0,4);
	sei();
    while(1)
    {
		if (Timer3Flag==1){	//Here is the control loop, all the data sample process and output should be here
		
		cli();
			// read data from IMU
			if(m_imu_raw(Data)) {
				m_red(TOGGLE);
			}
			// make the input value get rid of the offset
			RealinputACC = ACCPART*(Data[1]-ACOFFSET);	//The acceleration input without offset
			RealinputGyr = GYRPART*(Data[3]-GYOFFSET);	//The anglar velocity input without offset
			Kalman_Filter(RealinputACC,RealinputGyr);	//Using the Kalman Filter to get the reliable output of the angle

			// read the changed parameter, because the wireless cannot send float, so change it to float here
			Kp = (float)KpIni/1000;
			Ki = (float)KiIni/1000;
			Kd = (float)KdIni/1000;
			// calibrate the angle value by using the balance offset of the angle
			AngleActual = angle-AngleCali;
			inputK = AngleActual-angleHis1;
			inputI +=AngleActual;

			// PID controller, which you will find that Ki always be zero
			Output = Kp*AngleActual + Ki*inputI + Kd*inputK;
			
			// dead region, which means the value in this region won't give the wheels a speed, so remove it from output to make the output speed linear with the input angle
			if (AngleActual>0) {
				OutputHis1 =1823-Output;
			}
			if (AngleActual<0) {
				OutputHis1 =2193-Output;
			}
			if (AngleActual==0) {
				if (angleHis1>0) {
					OutputHis1 =1823;
				}
				if (angleHis1<0) {
					OutputHis1 =2193;
				}
				if (angleHis1=0){
					OutputHis1 =OutputHis1;
				}
			}

			if (AngleActual>0)
				OutputHis2 =1857-Output;

			if (AngleActual<0)
				OutputHis2 =2148-Output;

			if (AngleActual==0) {
				if (angleHis1>0) 
					OutputHis2 =1857;
				if (angleHis1<0)
					OutputHis2 =2148;
				if (angleHis1=0)
					OutputHis2 =OutputHis2;
			}
			// Try to check whether the output value in the limitation
			if (OutputHis1>4000)		//Detect the limitation of the output value
			{
				OutputHis1=4000;
			}else{
				if (OutputHis1<3)
				{
					OutputHis1=3;
				}
			}
			if (OutputHis2>4000){		//Detect the limitation of the output value
				OutputHis2=4000;
			}else{
				if (OutputHis2<3)	{
					OutputHis2=3;
				}
			}

			// set the output duty cycle
			OCR1B = OutputHis1;	// for B6
			OCR1C = OutputHis2;	// for B7
			
			angleHis2 = angleHis1;	//record value of the angle which will be used in D 
			angleHis1 = AngleActual;//record value of the angle which will be used in D
			
			Timer3Flag=0;
			sei();
		}



	//*****************************************************************
	// Because the holes on our encoder are few, so in the 5 ms period it 
	// probably won't get any data. So my advice is to write the code for 
	// encoder here, which period is 100ms, then we may get some points,
	// or if we like we can use flag3 and set it to 1000ms to get more 
	// points, 1s is enough short to get precise position
	//*****************************************************************



	//condition used to send the wireless data or usb data, 
	// 	because the frequency here is below 10Hz
		if (Timer3Flag2==INTERRUPT1S)	{ 	
			cli();
			tmp = angle;
			// send back value from IMU of acceleration of Y
			wireless_int(RealinputACC);	
			wireless_char('\t');
			// send back value from IMU of anglar speed around X
			wireless_int(RealinputGyr);	
			wireless_char('\t');
			wireless_int(AngleActual);	// send back the current angle value
			wireless_char('\n');
			m_green(TOGGLE);
			Timer3Flag2=0;
			sei();
		}		
    }
}
Ejemplo n.º 5
0
int main(void)
{
    m_clockdivide(0);
    Timer3_init();//timer for setting delta t for angle value
     timer1_init();
    m_usb_init();
    m_imu_init(2, 3);
    sei();
    //for motor control-testing
    while(1)
    {
        if (update_angle) {
            
            m_imu_raw(data);
            Ax = (float)data[0]*g/accel_scale;
            Ay = (float)data[1]*g/accel_scale;
            Az = (float)data[2]*g/accel_scale;
            Gx = (float)data[3]/gyro_scale;
            Gy = (float)data[4]/gyro_scale;
            Gz = (float)data[5]/gyro_scale;
           // Mx = (float)data[6];
           // My = (float)data[7];
           // Mz = (float)data[8];
            
            
            //angle calculation
            theta_Ay = (float)Ay*90/g;
            angle = alpha*(angle_old + Gx*timestep*5)+ (1-alpha)*theta_Ay;
            angle_old = angle;
            delta_angle = angle_old + Gx*timestep*5;
            integral_angle += angle;
            //PID
            //output = (Kp*angle) + Kd*(angle - angle_old)*timestep + (Ki*integral_angle*timestep) ;
            output = Kp*angle + Kd*Gx*timestep + Ki*integral_angle*timestep;
            
            m_usb_tx_string("\t Ax: ");
            m_usb_tx_int(Ax);
            m_usb_tx_string("\t Ay: ");
            m_usb_tx_int(Ay);
            m_usb_tx_string("\t Az: ");
            m_usb_tx_int(Az);
            m_usb_tx_string("\t Gx: ");
            m_usb_tx_int(Gx);
            m_usb_tx_string("\t Gy: ");
            m_usb_tx_int(Gy);
            m_usb_tx_string("\t Gz: ");
            m_usb_tx_int(Gz);
            m_usb_tx_string("\t angle_Gx: ");
            m_usb_tx_int(angle);
            m_usb_tx_string("\t output: ");
            m_usb_tx_int(output);
     
            m_usb_tx_string("\n");
            update_angle = 0;
        }
        
        //PID Control
      // 
        
        //pwm , sensor , whell rotation spd, fbk loop, pwm generate;
        //pseudo code to control motor
        //      initialise timer for motor here, and set OCR1A,OCR1B,OCR1C value based on the speed u want to control the bot.
         //                  go slow or fast, angle less, slow, angle more faster
                
                
                if (angle > base_angle){//>
                    //move forward
                    set(DDRB,6);//set Port B pin 6 for output
                    clear(PORTB,6); //clear Port B pin 6}
                    clear(DDRB,7);
                    flag_foward = 1;
                    flag_back = 0;
                                    }
                if (angle < -base_angle){
                    //move backwards
                    set(DDRB,7);//set Port B pin 7 for output
                    clear(PORTB,7); //clear Port B pin 7
                    clear(DDRB,6);
                    flag_back = 1;
                    flag_foward = 0;
                }
        //timer1_init();//testing fr working
        timer_update();
    }
}
Ejemplo n.º 6
0
/************************************************************
Main Loop
************************************************************/
int main(void)
{
	/* Confirm Power */
	m_red(ON);

	/* Initializations */
	init();
	usb_enable();
	timer3_init();
	int gy_previous_reading = 0;

	/* Confirm successful initialization(s) */
	m_green(ON);

	/* Run */
	while (1){
		if (m_imu_raw(data))
		{
			m_green(ON);
			m_red(OFF);
			
			
			ax = lowpass(0.85,ax,data[0])+AX_OFFSET;
			az = lowpass(0.85,az,data[2])+AZ_OFFSET;
			gy = lowpass(ALPHA_LOW,gy,data[4])+GY_OFFSET;
			gy = highpass(ALPHA_HIGH,gy,gy_previous_reading,data[4]);
			gy_previous_reading = data[4];
			
			/*
			m_usb_tx_string("ax= ");
			m_usb_tx_int(ax);
			m_usb_tx_string("     az=");
			m_usb_tx_int(az);
			m_usb_tx_string("     gy=");
			m_usb_tx_long(gy);
			m_usb_tx_string("\n");
			*/
			
			
			int angle = ((float)ax*RAD2DEG)/sqrt(((float)ax*ax+(float)az*az));
			
			if (check(TIFR3,OCF3A)){	//check if timestep has completed 
				angle += gy*TIMESTEP;	//add thetadot*timestep to angle 
				set(TIFR3,OCF3A);		//reset flag 
			}
			
			m_usb_tx_int(angle);
			m_usb_tx_string("\n");
			
			/*
			m_usb_tx_string("ax= ");
			m_usb_tx_int(data[0]);
			m_usb_tx_string("     ay= ");
			m_usb_tx_int(data[1]);
			m_usb_tx_string("     az= ");
			m_usb_tx_int(data[2]);
			m_usb_tx_string("     gx= ");
			m_usb_tx_int(data[3]);
			m_usb_tx_string("     gy= ");
			m_usb_tx_int(data[4]);
			m_usb_tx_string("     gz= ");
			m_usb_tx_int(data[5]);
			m_usb_tx_string("\n");
			*/
			
		}
		else
		{
			m_green(OFF);
			m_red(ON);
		}
	}
}