天天看點

步進電機S曲線的生成

S型曲線公式

步進電機的速度從0變為一個比較大的速度,需要一個加速過程,否則會産生振動或是電機的堵轉。電機加速通常有T型曲線和S型曲線兩種方式。S型曲線相對于T型曲線,S型曲線的速度不會突變。S型曲線的原始公式如下:

y=K/(1+Exp(a-b*x))(K>0,b>0)

Exp是指數函數,由這個公式可以看出y會随着x的增大,逼近K。把這個公式應用到電機控制之中,K看成最大的速度Vmax,x看成時間t的變量,那麼t=0時,就是電機的初始速度,即V0=Vmax/(1+Exp(a-b*(0)))=Vmax/(1+Exp(a));反推求出a與V0,Vmax之間的關系,a=In((Vmax-V0)/V0).b決定曲線的快慢,b越大V變化越快,也就越快接近Vmax。

單片機一般采用定時器來産生脈沖控制電機的轉動,産生脈沖的頻率決定電機轉動的快慢,這個頻率與單片機的晶振的頻率nXtal,定時器的預分頻nPrevXtal,定時器的自動重裝載寄存器的資料Xload有關,晶振的頻率由硬體決定,定時器的預分頻在單片機的初始化的時候設定,那麼我們要改變電機的運作速度,就隻能通過改變定時器的的自動重裝載寄存器的資料。通常的做法是把自動重裝載寄存器的資料放到一個數組裡面,現在要做的是如何生成這個數組的資料。我這裡介紹使用上位機VC編寫界面來生成這個數組及曲線。如下圖:

步進電機S曲線的生成
步進電機S曲線的生成

軟體界面需要設定的資料有:晶振頻率nXtal,預分頻nPrevXtal,步進電機驅動器細分nPrevMotor,運作的最大速度nMaxSpeed,達到最大速度時的位置坐标(對應界面上的極限)nMaxPoint以及a,b參數是通過滑動條設定,a對應起始速度,b對應加速快慢.

速度與自動重裝載寄存器的關系

電機的轉速的機關一般是rpm,即一分鐘多少轉.如果電機的轉速是V(rpm),那麼自動重裝載寄存器的資料應該是多少?步進電機驅動器細分為nPrevMotor,那麼單片機發脈沖的速度是nPrevMotorV/60每秒,即定時器一秒鐘産生中斷的個數。

**1/(Xload/(nXtal/nPrevXtal))=(nPrevMotorV/60)**

Xload=60nXtal/(nPrevXtalnPrevMotor*V)

其中V=Vmax/(1+Exp(a-bt)),即

**Xload=60nXtal*(1+Exp(a-bt))/(nPrevXtalnPrevMotor*Vmax)**

Xload是自動重裝載寄存器的資料,nXtal是晶振頻率,nPrevXtal是預分頻系數。

VC生成數組的代碼如下:

int nMaxPoint,nXtal,nPrevXtal,nPrevMotor,nMaxSpeed;
nMaxPoint = GetDlgItemInt(IDC_EDIT_MAX_POINT);
nXtal = GetDlgItemInt(IDC_EDIT_XTAL);
nPrevXtal = GetDlgItemInt(IDC_EDIT_PREV_XTAL);
nPrevMotor = GetDlgItemInt(IDC_EDIT_MOTOR_F);
nMaxSpeed = GetDlgItemInt(IDC_EDIT_SPEED_MAX);
double k;
k= (double)nMaxSpeed;
CString strArray;
unsigned short nTimerCount;

strArray.AppendFormat(_T("/*============================================================================\r\n"));
strArray.AppendFormat(_T("晶振頻率        = %d;\r\n"),nXtal);
strArray.AppendFormat(_T("預分頻頻率	= %d;\r\n"),nPrevXtal);
strArray.AppendFormat(_T("極限點		= %d;\r\n"),nMaxPoint);
strArray.AppendFormat(_T("極限轉速   	= %d;\r\n"),nMaxSpeed);
strArray.AppendFormat(_T("周脈沖數   	= %d;\r\n"),nPrevMotor);
strArray.AppendFormat(_T("S型曲線\r\n"));
strArray.AppendFormat(_T("============================================================================*/\r\nunsigned int code WaitTable[]={\r\n"));

for(int i= 0;i<nMaxPoint;i++)
{
	nTimerCount = (nXtal)*(1+exp(a-b*i))/(nPrevXtal*nPrevMotor*nMaxSpeed);
		
	strArray.AppendFormat(_T("0x%04X, "),nTimerCount);
	if (((i+1)%10)==0)
	{
		strArray.AppendFormat(_T("  // %d\r\n"),(i/10+1)*10);
	}
	
}
	strArray.AppendFormat(_T("};\r\n"));
	SetDlgItemText(IDC_EDIT_DISPLAY,strArray);
           

就這樣生成一個S曲線的資料數組,隻需要把這個這個數組拷貝到你的單片機程式裡面,定時器使用比較中斷的方式,在中斷處理函數裡面,移動數組的下标即可。當然如果單片機是stm32,還可以使用DMA的方式來做,這樣可以減少中斷.

S型曲線界面的繪制

這個S曲線的顯示使用的是一個Picture控件顯示,根據輸入晶振頻率,預分頻,最大速度,極限點。。來繪制,使用GDI相關接口在Picture控件視窗面繪制.代碼如下:

int CSCurveDlg::DrawCurve(void)
{
	CWnd* pWnd = GetDlgItem(IDC_EDIT_DISPLAY);
	if(NULL!=pWnd)
	{
		RECT rect;
		pWnd->GetClientRect(&rect);
		int nHeight = rect.bottom-rect.top-4;
		int nWidth = rect.right-rect.left-4;
		CDC* pDC = pWnd->GetDC();
		pDC->FillSolidRect(&rect,RGB(255,255,255));
		POINT p1,p2;

		int i;
		double y1,y2;
		double k;
		k = (double)GetDlgItemInt(IDC_EDIT_SPEED_MAX);
		int nYmax=DrawTable(pDC,nWidth,nHeight);
		int nMaxPoint = GetDlgItemInt(IDC_EDIT_MAX_POINT);
		CSliderCtrl* pSlider1 = (CSliderCtrl*)GetDlgItem(IDC_SLIDER_ACC);
		b=(double)(((double)pSlider1->GetPos())/20);
		
		for (i=0;i<nMaxPoint;i++)
		{
			y1 = (nYmax-5)/(1+exp(a-(b*i)));
			y2 = (nYmax-5)/(1+(exp(a-b*(i+1))));
			p1.x=i*nWidth/nMaxPoint;
			p2.x=(i+1)*nWidth/nMaxPoint;
			p1.y = nHeight-y1;
			p2.y = nHeight-y2;
			pDC->MoveTo(p1);
			pDC->LineTo(p2);
		}
		
	}
	return 0;
}
           

源碼下載下傳