Jump to content
Sign in to follow this  
Dave_H

Servo Motor Control

Recommended Posts

Hi

 

I been trying to control a servo motor by using two analog ports as feedbacks to give the motors actual direction. I.E if analog port 2 is greater than 3 go clockwise. If 3 is greater than 2 go anticlockwise. But for some reason when the number exceed 255 on ethier port the motor changes direction as it is looping back to zero (0-255). I understand that I need to use a 16 bit int to get the whole range that I require which I thought I had done. The number appear correctly upon an LCD screen when 5v=1023 on both ports. So I'm not sure exactly what I'm doing wrong?? help ??????????????

 

First the program get the two results of mag_plus and mag_minus to find intially what is greater

 

while(1)
{			  // get mag_minus and mag_plus results
		Fwd_power();  
		mag_minus();
		mag_plus();

			if(fwd>3) // RF power is greater than 0.3V enable matchnet 
			{
			set_bit(portb,1);	 // Turn on led 
			tune_ca_left();		  // Tune  motor CA clockwise
			tune_ca_right();	  // turn motor CA anticlockwise
			}
			else
			{
			clear_bit(portb,1); 
			}
		}

 

 

Then the program jumps to ethier loop depending on what is greater

 

 

unsigned char tune_ca_left()
{
		while(mag_p>mag_m)  // is mag_p greater than mag_m
		{
		mag_minus();		  // get mag_minus result	
		mag_plus();			// get mag plus result
		set_bit(portb,4);// set motor direction intially	
		set_bit(portb,5);// turn motor clockwise
		} 
}				


unsigned char tune_ca_right()
{
		while(mag_m>mag_p)
		{

		mag_minus();
		mag_plus();
		set_bit(portb,5);
		clear_bit(portb,4);// set motor direction ???
		delay(3000);
		}

}

 

mag_minus/mag_plus get the cursor position and get the returned result

unsigned char mag_plus()
{
lcd_cursor(0,0); // Set cursor top left hand position
mystrcpy(name2,magplus); // put magplus name on screen
mag_p=ad_Channel_2();	// go analog routine and return result to mag_p
}

unsigned char mag_minus()
{
lcd_cursor(0,1); 
mystrcpy(name2,magminus);
mag_m=ad_Channel_3();
}

 

 

The routine then jumps to ad 2/3 to get the results to return

 

unsigned int ad_Channel_2() //Channel_2 of A/D PORT RA2 mag_plus readback
{
unsigned int CH2_adcon0=0x15;  // Select channel 2 
unsigned int result;


result= read_adc0(CH2_adcon0);	  // analog conversion result
display1_value(result,2,0); // Display result and position on screen correctly

return result;
}	



unsigned int ad_Channel_3() //Channel_3 of A/D PORT RA3 mag_minus readback 
{
unsigned int CH3_adcon0=0x1d;  // Select channel 3 
unsigned int result;


result= read_adc0(CH3_adcon0);	  // analog conversion result
display1_value(result,2,1); // Display result and position on screen correctly

return result;
}

 

 

 

Then to get the analog routine to get the result

 

unsigned char ADCRESL@0x9e;  // control reg for A/D
	 unsigned char ADCRESH@0x1e;


int read_adc0 (unsigned char adcon_0 ) // Main A/D conversion sub 

{ 

  unsigned char h, l =0; 
  unsigned int result=0; 
  adcon0 = adcon_0 & 0xFb;  /* Switch ADC channel*/ 

  ad_delay(100);  

  adcon0 = adcon0 + 0x04;  //start conversion 

  while ( adcon0 & 0x04 );//spin while the conversion runs  

  h = ADCRESH; 
  l = ADCRESL; 

  result = (256 * h) + l; // Add high byte-to-low 
  return result; 

}

 

 

If anyone can see what I'm doing wrong I would be very grateful as I cannot find the problem

 

Many thanks in advance Dave H

Share this post


Link to post
Share on other sites

Hi, I am new to PIC as well. I am trying to achieve the same thing that you are. I am having problems with A/D conversion as well.. but.. what I do is whatever adc_read() result is, I write it to eeprom to check the value. Unfortunately I always get 0xC4 and 0xC3 in my eeprom memory.. Let me know if writing to eeprom helps you out.. IF so.. you can try and help me with mine.. =P

Share this post


Link to post
Share on other sites
Hi, I am new to PIC as well. I am trying to achieve the same thing that you are. I am having problems with A/D conversion as well.. but.. what I do is whatever adc_read() result is, I write it to eeprom to check the value. Unfortunately I always get 0xC4 and 0xC3 in my eeprom memory.. Let me know if writing to eeprom helps you out.. IF so.. you can try and help me with mine.. =P

 

Hi

 

I've fixed the problem by changing the subroutine to int values and by changing the return result to a short after searching ad problems from the forum this seems to have fixed the problem. I'll go back and change things one at a time next to find where exactly the problem was.

 

Chisterz. What is the problem that you have been facing ?(I'll see if I can help ??!!) I tend to send the results to an LCD display to show the actual result from the a/d conversion. I'll have a play at writing the value to eeprom thanks for the tip.

I have been using the eeprom memory to store recipe information for timers and other values which does save and recall values correctly see if this help .

 

/* This function will hold 10 recipes with 5 data values which have been setup within the
main function. The files are placed into an array for easier storage and easier unstorage.
The I.C has a eeprom memory size of 256byte which will hold 51 recipes conbinations 'IF REQUIRED'*/

#include<system.h>
#include"Eeprom memory storage.h"


unsigned char stored_values[5]; // five timer values required to save per recipe
unsigned power_stored;
unsigned char value1;


// READ value to eeprom memory
unsigned short read_eeprom(unsigned char addr)
{
eeadr = addr; // low byte
eeadrh = 0; // high byte
clear_bit(eecon1,EEPGD); // select eeprom memory
set_bit(eecon1,RD); // set read bit
return(eedata);
}


// WRITE value to eeprom memory
unsigned int write_eeprom(unsigned char addr,unsigned int data)
{

eeadrh = 0; // high byte
eeadr = addr; // low byte
eedath = 0; // high byte
eedata = data; // low byte
clear_bit(eecon1,EEPGD); // select eeprom data memory
set_bit(eecon1,WREN); // enable write
eecon2 = 0x55;
eecon2 = 0xaa;
set_bit(eecon1,WR); // write command

while(eecon1&2); // wait untill writing is ready
clear_bit(eecon1,WREN); // disable write

}





unsigned int Send_values_to_memory(unsigned char start_address)
{

int i=0;

	for ( i=0; i < 5; i++ ) 
	{ 
   write_eeprom(start_address,stored_values[i]);// write values to eeprom memory
   start_address++;
   }

	// Save 16 bit number to, two 8 bit EEPROM addresses
	write_eeprom(start_address,(unsigned char)power_stored); // load power level to memory first 8 bits
	start_address++;				   // increment holding address
	write_eeprom(start_address,(unsigned char)(power_stored>>8)); // Load power level to memory second 8 bits

}




/* This function will hold 10 recipes with 5 data values which have been setup within the
main function. The files are placed into a array for easier storage and easier unstorage*/

unsigned int write_to_memory (unsigned char pre_weld,unsigned char pre_warm_time,unsigned char weld_time,unsigned char dwell_time,
				  unsigned int powerlevel,char save)
{


stored_values[0]=pre_weld;
stored_values[1]=pre_warm_time;
stored_values[2]=weld_time;
stored_values[3]=dwell_time;
power_stored= powerlevel;


	switch(save)
	{
	case 1 : Send_values_to_memory(0x00);
	break;

	case 2 : Send_values_to_memory(0x08);
	break;

	case 3 : Send_values_to_memory(0x0E);
	break;

	case 4 : Send_values_to_memory(0x14);
	break;

	case 5 : Send_values_to_memory(0x19);
	break;

	case 6 : Send_values_to_memory(0x1E);
	break;

	case 7 : Send_values_to_memory(0x23);
	break;

	case 8 : Send_values_to_memory(0x28);
	break;

	case 9 : Send_values_to_memory(0x2D);
	break;

	case 10 : Send_values_to_memory(0x32);
	break;

	}

}







unsigned char read_from_memory(char program_number)
{


switch(program_number)
{
	case 1 :  reload_values_from_memory(0x00);
	break;

	case 2 :  reload_values_from_memory(0x08);
	break;

	case 3 :  reload_values_from_memory(0x0E);
	break;

	case 4 :  reload_values_from_memory(0x14);
	break;

	case 5 :  reload_values_from_memory(0x19);
	break;

	case 6 :  reload_values_from_memory(0x1E);
	break;

	case 7 :  reload_values_from_memory(0x23);
	break;

	case 8 :  reload_values_from_memory(0x28);
	break;

	case 9 :  reload_values_from_memory(0x2d);
	break;

	case 10 : reload_values_from_memory(0x32);
	break;

}



}

 

 

 

I hope this helps Dave

 

 

Dave

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...