liguang70217 发表于 2009-12-24 18:46:30

用ATmega8制作的下推式磁悬浮

最近这段时间在坛里溜达,闲来无事,参照《STM8下推式磁悬浮实验 》,用Mega8+L298N+3503做了个下推式磁悬浮, 现将图片发上来,供参考。

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518291.jpg
(原文件名:1.jpg)

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518292.jpg
(原文件名:2.jpg)

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518293.jpg
(原文件名:3.jpg)

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518294.jpg
(原文件名:4.jpg)

没有大环形磁铁,就用小磁铁围一圈代替,效果很好。
http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518296.jpg
(原文件名:7.jpg)
霍尔器件位于四个电磁铁中间位置。

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518297.jpg
(原文件名:HR.jpg)

liguang70217 发表于 2009-12-24 18:48:47

磁铁位于电磁铁的下方:
http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518299.jpg
(原文件名:5.jpg)

gzhuli 发表于 2009-12-24 19:02:52

呵呵,那一圈小磁铁效果也很好啊。

elder60 发表于 2009-12-24 19:19:48

祝贺楼主。

外圈磁铁再少点,应该也可。

咕唧霖,赶快把你的那个CPU改一下并公开原码,这样动手的人会更多的。

LZ能公开原理图和原码吗?

wmsky 发表于 2009-12-24 20:37:38

高人

gzhuli 发表于 2009-12-24 21:06:59

【3楼】 elder60 60岁老头
咕唧霖,赶快把你的那个CPU改一下并公开原码,这样动手的人会更多的。
--------------------------
我的电路、代码和设计要点都已经在STM8下推式磁悬浮实验里公开了。
STM8 Minikit的图纸在论坛的STM8/STM32区置顶帖里有,其实我就是用了最小系统,STM8接上电源就能跑了,晶振都不用。
不过现在玩STM8的人确实不多,如果楼主能公开M8的代码,估计动手的人就真的会多起来了(其实STM8移植到M8也不难,移植到STM32也很容易)。

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518369.PNG
STM8S Minikit 线路图 (原文件名:STM8S Minikit.PNG)

my2009 发表于 2009-12-25 12:21:01

高手,佩服

liguang70217 发表于 2009-12-25 13:02:15

原理图和源程序都是参照《STM8下推式磁悬浮实验 》中的,只是改里一下端口,手头没有L293,就用L298代替,效果一样,磁铁用8个也可以,只是浮上来的距离短一些,下面是《STM8下推式磁悬浮实验 》中的原理图,我还没画成型的原理图,等整理一下传上来:
http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_518585.png
(原文件名:ourdev_511868.png)

liguang70217 发表于 2009-12-25 17:32:48

用ATmega8制作的下推式磁悬浮原理图:点击此处下载 ourdev_518751.pdf(文件大小:137K) (原文件名:下推式磁悬浮.pdf)

liguang70217 发表于 2009-12-25 18:12:20

源程序公开:
//--------------------------------------------------------------------------
//下推式磁悬浮源程序2009.12.18
//liguang70217
//liguang70217@126.com
//http://liguang70217.blog.hexun.com/
//ICC-AVR application builder : 2009-12-17 17:27:22
// Target : M8
// Crystal: 12.000Mhz
//--------------------------------------------------------------------------
#include <iom8v.h>
#include <macros.h>
#include"BIT.h"

#defineLED_A _PB0
#defineLED_B _PB1

#defineCA   _PD0
#defineCB   _PD1

#defineN7

#define MAX_PID_OUTPUT                         950
#define MAX_INTEGRATION_ERROR                100
#define X_DIRECTION_FLAG                0x01
#define Y_DIRECTION_FLAG                0x02
//--------------------------------------------------------------------------
typedef struct {
        int targetValue;
        int Kp;
        int Ki;
        int Kd;
        int integrationError;
        int prevError;
} PID;

PID xPID,yPID;

unsigned char direction;

unsigned int value_buf_x,value_buf_y;
unsigned char ix=0,iy=0;

unsigned int xpos,ypos;//AD转换后存放采集值
unsigned char HH;

unsigned intxError, yError;
unsigned intxPWM, yPWM;
//--------------------------------------------------------------------------
//------------延时子程序----------------------------------------------------
void                delay(unsigned int h)
{
unsigned char j;
while(h--){
             for(j=190;--j;)        continue;
          }
}
//--------------------------------------------------------------------------
// PID calculation routine
int calcPID(PID *pid, int error)
{
int output;

if (pid->Ki != 0)
        {
                pid->integrationError += error;
                // Limit the maximum integration error
                if (pid->integrationError > MAX_INTEGRATION_ERROR)
                {
                        pid->integrationError = MAX_INTEGRATION_ERROR;
                }
                else if (pid->integrationError < -MAX_INTEGRATION_ERROR)
                {
                        pid->integrationError = -MAX_INTEGRATION_ERROR;
                }
        }

        output = pid->Kp * error + pid->Ki * pid->integrationError + pid->Kd * (error - pid->prevError);

        // Limit the maximum output
        if (output > MAX_PID_OUTPUT)
        {
                output = MAX_PID_OUTPUT;
        }
        else if (output < -MAX_PID_OUTPUT)
        {
                output = -MAX_PID_OUTPUT;
        }

        pid->prevError = error;
return output;
}
//--------------------------------------------------------------------------
void port_init(void)
{
PORTB = 0xff;
DDRB= 0xff;
PORTC = 0x00; //m103 output only
DDRC= 0x00;
PORTD = 0x00;
DDRD= 0xff;
}
//--------------------------------------------------------------------------
//TIMER1 initialize - prescale:1
// WGM: 7) PWM 10bit fast, TOP=0x03FF
// desired value: 2KHz
// actual value: 11.719KHz (82.9%)
void timer1_init(void)
{
TCCR1B = 0x00;//停止定时器
TIMSK |= 0x00;//中断允许
TCNT1H = 0x00;
TCNT1L = 0x00;//初始值
OCR1AH = 0x01;
OCR1AL = 0xFF;//匹配A值
OCR1BH = 0x01;
OCR1BL = 0xFF;//匹配B值
ICR1H= 0xFF;
ICR1L= 0xFF;//输入捕捉匹配值
TCCR1A = 0xA3;
TCCR1B = 0x09;//启动定时器
}
//--------------------------------------------------------------------------
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
MCUCR= 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR   = 0x00;

port_init();
timer1_init();

// TIMSK = 0x04; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//-----------------------------------------------------------------------------
//ADC采样函数,采样第0通道信号,采样分辨率256
//x为ad端口号
unsigned int get_ad(unsigned char x)
{
union        adres{ int y1; unsignedcharadre; }adresult;
unsigned int i;
ADMUX = 0xc0+x;                           /*基准AVCC、左对齐、通道7*/
ADCSRA = 0xC3;                                   /*使能、开启、8分频*/
while(!(ADCSRA & (1 << ADIF)));   /*等待*/
adresult.adre=ADCL;            //读取并存储A/D转换结果,A/D转换的结果通过共
adresult.adre=ADCH;            //用体的形式放入了变量y1中       
ADCSRA &= ~(1 << ADIF);                   /*清标志*/
ADCSRA &= ~(1 << ADEN);                   /*关闭转换*/
return adresult.y1;
}
//--------------------------------------------------------------------------
//滑动平均滤波
unsigned int filter_x(void)
{
   unsigned char count;
   unsigned longsum=0;
   value_buf_x = get_ad(0);
   ix=ix+1;
   if ( ix == N ) ix = 0;
   for ( count=0;count<N;count++)
             sum = sum + value_buf_x;
   return (unsigned int)(sum/N);
}
//--------------------------------------------------------------------------
//滑动平均滤波
unsigned int filter_y(void)
{
   unsigned char count;
   unsigned longsum=0;
   value_buf_y = get_ad(1);
   iy=iy+1;
   if ( iy == N ) iy = 0;
   for ( count=0;count<N;count++)
         sum = sum + value_buf_y;
   return (unsigned int)(sum/N);
}
//-----------------------------------------------------------------------------
void main(void)
{
unsigned int ZD;
unsigned int ccc;
init_devices();

ZD=511;
// PID Parameter Initialization
xPID.Kp = 4;
xPID.Ki = 0;
xPID.Kd = 30;
xPID.integrationError = 0;
xPID.prevError = 0;
xPID.targetValue = ZD;

yPID.Kp = 4;
yPID.Ki = 0;
yPID.Kd = 30;
yPID.integrationError = 0;
yPID.prevError = 0;
yPID.targetValue = ZD;



while(1)
{
   xpos=filter_x();
   ypos=filter_y();
   
   if(xpos>ZD)
   {
    xpos=xpos-ZD;
    CA=1;
    xError = xPID.targetValue - xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;   
   }
   else
   {
    xpos=ZD-xpos;
        CA=0;
        xError = xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;
   }
                     
   if(ypos>ZD)
   {
    ypos=ypos-ZD;
        CB=1;
    yError = yPID.targetValue - ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;
   }
   else
   {
    ypos=ZD-ypos;
        CB=0;
    yError = ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;   
   }
}
}
//----------------------------------------------------------------------------

elder60 发表于 2009-12-25 20:18:49

谢谢!

gzhuli 发表于 2009-12-25 20:25:17

L298N内部没有集成二极管,外部最好加上。
我的L293D是有的,就是看上这点而没用L298N,一个字懒。 ^v^

potatoES 发表于 2009-12-25 20:30:45

这个猛

elder60 发表于 2009-12-26 08:24:47

liguang70217

是否有兴趣,再接再厉,做一个上拉的(霍尔在上)。可能你会发现,好象更难。

另外,现在这个电路中,可以去掉2个线圈,也可实现悬浮。不过,稳态时,电流较大。

aaaa0000 发表于 2009-12-26 09:41:08

难道传说中的彩票摇奖机就是用这个原理做的,GC-D想开什么号就开什么号。

my2009 发表于 2009-12-26 15:18:48

elder60:---"另外,现在这个电路中,可以去掉2个线圈,也可实现悬浮。不过,稳态时,电流较大."

我觉得,理论上可以只要一个线圈控制一个方向,但是一个线圈力很弱,比如线圈在左边,
悬浮物太靠右边时,要往左边拉, 一个线圈力度不够

my2009 发表于 2009-12-26 17:05:08

请教楼主和咕唧:

楼主的电路和咕唧霖的电路都用了LM324/LM358, 没有把3503直接接入MPU(或加分压电阻),是否是灵敏度不够?

gzhuli 发表于 2009-12-26 20:13:11

回复【16楼】my2009
楼主的电路和咕唧霖的电路都用了LM324/LM358, 没有把3503直接接入MPU(或加分压电阻),是否是灵敏度不够?
-----------------------------------------------------------------------

是的,我做了30倍放大,楼主做了21倍,MCU的PID算法P=4,即再放大4倍。
假设磁铁移动1mm ADC采样结果变化30,如果不放大30倍,那ADC就只变化1,0-30中间细节全丢失了,即使PID的P做得再大也无法弥补丢失的信号。
最理想的模拟放大倍数就是在线圈最大控制范围内,ADC采样值刚好从0到满幅,我试验出来是30倍比较恰当。

pinocchio 发表于 2009-12-26 20:25:25

不知道这样的磁铁哪里能买到?

ggddll 发表于 2009-12-26 20:31:06

my2009 发表于 2009-12-26 23:11:34

谢谢咕唧霖的解答, 我明白了.

【18楼】: 淘宝有这种小磁铁, 深圳的电子市场也有, 其他城市的电子元器件市场估计也会有

liguang70217 发表于 2009-12-28 13:33:44

在这之前做过一个上拉式磁悬浮:

liguang70217 发表于 2009-12-28 13:35:43

上拉式磁悬浮照片:
http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_519813.jpg
(原文件名:1.jpg)

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_519814.jpg
(原文件名:5.jpg)

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_519815.jpg
(原文件名:3.jpg)

http://cache.amobbs.com/bbs_upload782111/files_24/ourdev_519816.jpg
(原文件名:4.jpg)

elder60 发表于 2009-12-28 15:07:17

哈,好。
请楼主和咕唧霖在“★请已实验基本成功的先行者在下面回贴,以便今后网友查找。”一贴中登记一下。
最好再加上磁铁重量,悬浮高度(距离)和工作电流。
楼主请登记2种。

另请忘了登记者,尽快补上。

yinhe 发表于 2010-3-12 15:04:46

ji

super373 发表于 2010-3-29 09:14:30

很动心....

crazy_b-boy 发表于 2010-4-4 19:24:27

努力实践中

crazy_b-boy 发表于 2010-4-7 18:20:01

24v稳压 用 7824 可以吗

hongyancl 发表于 2010-4-7 18:36:37

回复【9楼】liguang70217
-----------------------------------------------------------------------

dddddddddddddd

crazy_b-boy 发表于 2010-4-7 18:38:57

回复【1楼】liguang70217
-----------------------------------------------------------------------

24v稳压 用 7824 可以吗

liguang70217 发表于 2010-4-9 13:04:30

7824发热量大,其实整流滤波直接驱动即可,对电压要求不严。

crazy_b-boy 发表于 2010-4-9 20:40:43

回复【30楼】liguang70217
-----------------------------------------------------------------------

谢谢
但是我一测都37v了

crazy_b-boy 发表于 2010-4-10 21:56:57

回复【30楼】liguang70217
-----------------------------------------------------------------------

298 非常热????????

my2009 发表于 2010-4-12 09:47:48

为什么要用24V的电压? 其实12V--15V 就够了, 换一个电源试试

gpzdc986 发表于 2010-4-12 12:36:37

mark

liguang70217 发表于 2010-4-12 13:06:22

298要加足够的散热器,M8的晶振最好上16MHz的。

crazy_b-boy 发表于 2010-4-13 13:57:06

谢谢大家我从焊电路 用 293 298 不好焊

guhenggao 发表于 2010-4-30 14:07:24

mark

crazy_b-boy 发表于 2010-5-3 15:22:11

回复【35楼】liguang70217
-----------------------------------------------------------------
两个滑动变阻器 怎么调啊 谢谢

arduino 发表于 2010-5-3 16:15:47

强力顶!!!!!!!!!!!1

chongcao 发表于 2010-5-4 10:46:14

学习中。

zbjzxc 发表于 2010-5-4 11:13:40

记号

liguang70217 发表于 2010-5-4 11:41:04

回复 【38楼】 crazy b-boy
-----------------------------------------------------------------
在初始状态下,调至运放输出电压的1/2的AD基准电压。

crazy_b-boy 发表于 2010-5-9 17:59:44

回复【42楼】liguang70217
-----------------------------------------------------------------------

在初始状态下,调至运放输出电压1.65v对吧? 我的mage8会热好像又烧了 还涨价了!! 298不热线圈不用加铁芯吗?我缠了六层够用吗?

liguang70217 发表于 2010-5-10 12:51:02

回复 【43楼】 crazy b-boy
-----------------------------------------------------------------
是要调到1.65V,M8应该不会热,应该是线路连接问题,298输出应接保护二极管,这在电路图中忘画了,参见【11楼】 gzhuli 咕唧霖。

crazy_b-boy 发表于 2010-5-11 12:01:09

回复【44楼】liguang70217
-----------------------------------------------------------------------

哦 谢谢 努力中 。。。。。。。。。。。。。。

crazy_b-boy 发表于 2010-5-11 20:14:26

回复【44楼】liguang70217
-----------------------------------------------------------------------

也不知道如何称呼 有时间能加我qq吗 我刚学单片机一年多 天天要去上那不太有用的课现在有很多不懂地方望您不吝赐教 QQ:393441746 (左手)

crazy_b-boy 发表于 2010-5-15 21:39:38

不用了 最近 进展不错

chongcao 发表于 2010-5-30 16:42:16

回复【9楼】liguang70217
-----------------------------------------------------------------------

楼主:liguang70217
请教你公开得程序:
#include"BIT.h"
这个头函数怎么来得呀?
#defineLED_A _PB0
#defineLED_B _PB1
这两行电路上怎么体现?
#defineCA   _PD0
#defineCB   _PD1
它们是不是就是:PD0PD1端口?
#defineN7

#define MAX_PID_OUTPUT       950
#define MAX_INTEGRATION_ERROR 100

#define X_DIRECTION_FLAG         0x01
#define Y_DIRECTION_FLAG         0x02
这两个标志没用呀?
请留下你得联系方式,请教学校呀!!!
本人qq:910266897

liguang70217 发表于 2010-5-31 13:02:35

回复【48楼】 chongcao
-----------------------------------------------------------------------
#include"BIT.h"记得就在本站下载的,可以搜一下。

chongcao 发表于 2010-5-31 16:22:28

谢谢楼主的回复,找到了:RD_UseAVRPORTBit.h AVR通用位操作支持库。
本人对单片机了解不多,真诚向各位大师请教学习,请不吝赐教!

看了程序,感觉L293 的驱动很费解,PWM怎么工作的?
//源程序公开:
//--------------------------------------------------------------------------
//下推式磁悬浮源程序2009.12.18
//liguang70217
//liguang70217@126.com
//http://liguang70217.blog.hexun.com/
//ICC-AVR application builder : 2009-12-17 17:27:22
// Target : M8
// Crystal: 12.000Mhz
//--------------------------------------------------------------------------
#include <iom8v.h>
#include <macros.h>
//#include"BIT.h"
#include <ioinit.h>
//#defineLED_A _PB0
//#defineLED_B _PB1

//#defineCA   _PD0
//#defineCB   _PD1







//----端口初始化----------------------------------------------------------------------
void port_init(void)
{
PORTB = 0xff; //=1   感觉成了单向磁场控制了!!!!
DDRB= 0xff; //OUTPUT

PORTC = 0x00; //m103 output only
DDRC= 0x00; //INPUT

PORTD = 0x00; //=0
DDRD= 0xff; //OUTPUT
}




//--------------------------------------------------------------------------
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
MCUCR= 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR   = 0x00;

port_init();//端口初始化
timer1_init();//T1初始化

//////usart_init(); //串口初始化

// TIMSK = 0x04; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}



//4.霍尔采样电路
//霍尔采样电路采用了2片有源线性霍尔UGN3503,后接一级运放反相放大器?
// 放大倍数为30倍,并且由一个10K多圈电位器调整输出中点电平。
//运放和霍尔使用5V单电源供电,UGN3503的输出中点电压约2.5V?
//运放LM324输出电压范围约50mV~3.6V,因此STM8的ADC参考电压使用3.3V,
//分别调整10K电位器使LM324输出1.65V,此时STM8的ADC采样结果应该接近511,
//误差虽然越小越好,但不需要绝对准确(霍尔、运放都有温漂,不可能绝对准确),
//一般调整至480~550范围内即可。


//1.ADC0采样完成(EOC)中断
//EOC中断轮流采集CH6和CH7通道的数据,
//并对采样值进行7阶移动平均滤波,结果存放于xPos和yPos变量。
//-----------------------------------------------------------------------------
//ADC采样函数,采样第0通道信号,采样分辨率256
//x为ad端口号
unsigned int get_ad(unsigned char x)
{
union adres{ int y1; unsignedcharadre; }adresult;
unsigned int i;
ADMUX = 0xc0+x;            /*基准AVCC、左对齐、通道7*/   
ADCSRA = 0xC3;            /*使能、开启、8分频*/
while(!(ADCSRA & (1 << ADIF)));   /*等待*/
adresult.adre=ADCL;            //读取并存储A/D转换结果,A/D转换的结果通过共
adresult.adre=ADCH;            //用体的形式放入了变量y1中   
ADCSRA &= ~(1 << ADIF);    /*清标志*/
ADCSRA &= ~(1 << ADEN);    /*关闭转换*/
return adresult.y1;
}


//--------------------------------------------------------------------------
// x---滑动平均滤波
unsigned int filter_x(void)
{
   unsigned charcount;
   unsigned longsum=0;
   value_buf_x = get_ad(0);
   ix=ix+1;
   if ( ix == N ) ix = 0;
   for ( count=0;count<N;count++)
             sum = sum + value_buf_x;
   return (unsigned int)(sum/N);
}


//--------------------------------------------------------------------------
//y----滑动平均滤波
unsigned int filter_y(void)
{
   unsigned charcount;
   unsigned longsum=0;
   value_buf_y = get_ad(1);
   iy=iy+1;
   if ( iy == N ) iy = 0;
   for ( count=0;count<N;count++)
         sum = sum + value_buf_y;
   return (unsigned int)(sum/N);
}

//****************************************************************************
//-----------------------------------------------------------------------------
void main(void)
{
unsigned intZD;
unsigned int ccc;

init_devices(); //initialize all peripherals

//+++++++GUO-TEST-TEST--TEST-TESTTEST-TEST--TEST-TEST-+++++++++++++++++++++
uart_charsend( 0x88 );//串口发送数据测试
PORTD=0<<PD0;//端口测试
PORTD=1<<PD1;//端口测试
//TEST-TEST--TEST-TESTTEST-TEST--TEST-TEST-TEST-TEST--TEST-TESTTEST-TEST--TEST-TEST-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



ZD=511;
// PID Parameter Initialization ------PID参数初始化
//本系统只使用了PD控制,Ki为0,积分项不参与计算。
//Kp, Kd的值需要根据悬浮物的质量调整,整定方法可参考有关资料

//-----------X PID参数
xPID.Kp = 4; //LM324/LM35830倍放大, MCU的PID算法P=4,即再放大4倍。
xPID.Ki = 0;
xPID.Kd = 30;
xPID.integrationError = 0;
xPID.prevError = 0;
xPID.targetValue = ZD;

//-----------YPID参数
yPID.Kp = 4; //LM324/LM35830倍放大, MCU的PID算法P=4,即再放大4倍。
yPID.Ki = 0;
yPID.Kd = 30;
yPID.integrationError = 0;
yPID.prevError = 0;
yPID.targetValue = ZD;



while(1)
{
   xpos=filter_x();
   ypos=filter_y();
   
   if(xpos>ZD)
   {
    xpos=xpos-ZD;
    //CA=1;
        PORTD=1<<PD0;//PD0
    xError = xPID.targetValue - xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;   
   }
   else
   {
    xpos=ZD-xpos;
//CA=0;
PORTD=0<<PD0;//PD0
xError = xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;
   }
   
//......................................................................
      
   if(ypos>ZD)
   {
    ypos=ypos-ZD;
//CB=1;
PORTD=1<<PD1;//PD1
    yError = yPID.targetValue - ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;   
   }
   else
   {
    ypos=ZD-ypos;
//CB=0;
PORTD=0<<PD1;//PD1
    yError = ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;   
   }
}
}
//----------------------------------------------------------------------------

ottife 发表于 2010-5-31 19:31:03

有意思

phwj2006 发表于 2010-5-31 20:41:04

厉害,学习了

gzhuli 发表于 2010-6-3 14:49:20

回复【50楼】chongcao
-----------------------------------------------------------------------

PWM部分你哪里不明白?能具体点吗?

chongcao 发表于 2010-6-3 16:26:02

if(xpos>ZD)
   {   
    xpos=xpos-ZD;   
    //CA=1;
PORTD=1<<PD0;//PD0
    xError = xPID.targetValue - xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;   
   }
这里的误差计算:xError = xPID.targetValue - xpos=xPID.targetValue -xpos+ZD=2*ZD-xpos   怎么会是这样?
xPWM   = calcPID(&xPID, xError);
OCR1A= xPWM;
这两行怎么理解?

gzhuli 发表于 2010-6-3 16:55:37

回复【54楼】chongcao
-----------------------------------------------------------------------

ZD是中点,即PID的目标值,所以xPID.targetValue = ZD。
我的STM8代码中,是先计算误差xError = xPID.targetValue - xPos,然后将绝对误差输入calcPID(),计算出修正量xPWM,然后判断xPWM的正负,设置PWM波形和GPIO的极性。
简单点讲,我的xError和xPWM是有极性的,中点值是0,当xPWM < 0时,PWM波是反相的(看我的帖子里面的波形图)。

LZ的代码计算出的xPWM是没极性的,所以他要以2 * ZD - xPos来算出没极性的,中点在ZD的误差值xError。
如果中点是ADC半量程,那么LZ的代码和我的代码是一样的,但如果中点不在ADC半量程处,我的xError就不等效于2 * ZD - xPos。
在我的原型设计中带自校准功能,中点是可调的,只是后来发现不用自校准也工作得挺好,所以发布出来的代码就把中点固定在511了。
LZ的代码基于我的代码修改过来,这部分没有简化,所以看起来像在绕圈。

chongcao 发表于 2010-6-3 17:01:47

谢谢楼主的回复,由于本人水平不是很高,你的程序原理勉强看的懂,那个PWM时序图很容易理解。到了这里就费解了许多。

“LZ的代码计算出的xPWM是没极性的,所以他要以2 * ZD - xPos来算出没极性的,中点在ZD的误差值xError。
如果中点是ADC半量程,那么LZ的代码和我的代码是一样的,但如果中点不在ADC半量程处,我的xError就不等效于2 * ZD - xPos。”
理解不了?xError怎么理解? 它不是以ZD=511 为中心吗?xPos>ZD,xError=xPos-ZDxPos<ZD,xError=ZD-xPos这样理解不对吗?   

请问搂主,下面两行是怎么实现 PWM 输出的?
xPWM   = calcPID(&xPID, xError);   
OCR1A= xPWM;

gzhuli 发表于 2010-6-3 17:11:09

xPWM是PID运算结果,OCR1A是TIMER1的比较寄存器,OCR1A = xPWM就是设置PWM输出的占空比。TIMER1有两个输出比较寄存器,正好分别用于X和Y通道,所以 OCR1A = xPWM 和 OCR1B = yPWM 就分别实现了两个PWM输出的设置。

chongcao 发表于 2010-6-3 17:38:34

回复【57楼】gzhuli 咕唧霖
-----------------------------------------------------------------------

你的意思是:TIMER1 初始化后,按照设定值就可以自动输出PWM波形,不需要额外的代码;而波形的占空比受控于PID运算结果。
霍尔输出-->采集ADC-->PID 运算,得到控制偏移量-->TIMER1自动产生PWM波形,占空比受控于PID函数的运算结果-->X,Y电磁铁产生双向磁场,纠正悬磁铁的偏移或倾斜
这样理解对吗?

gzhuli 发表于 2010-6-3 17:51:03

回复【58楼】chongcao
-----------------------------------------------------------------------

是的。

chongcao 发表于 2010-6-3 18:03:12

再次感谢楼主的指导,光自学还是不行的。单片机的控制原理大致搞清楚了,我可以组织电路实验了。
前期我实验了模拟L324的上拉式悬浮,接下来,我看也从M8的上拉式 PID控制实验 开始,等到成功了,再实验下推式悬浮。
我实验了,上拉式:下霍尔,上霍尔,双霍尔,加铁心,加辅助磁铁。都通过了,感谢各位大师的知道,特别是楼主大量的帖子的指导。

chongcao 发表于 2010-6-4 16:29:21

回复【55楼】gzhuli 咕唧霖
-----------------------------------------------------------------------

http://cache.amobbs.com/bbs_upload782111/files_29/ourdev_559566.GIF
(原文件名:ZD.GIF)

楼上讲的已经很好了,可惜我对PID 不是很了解,只是想当然理解。
当if(xpos>511) //采集值与平衡值比较
   {
    PORTD=1<<PD0;//PD0=1
   
        xpos=xpos-511;
    xError = 511 - xpos; //计算误差:采集数据和设定的平衡值比较(减法),得出一个差值,通过pid算法后得出控制量输出,就能达到目的。
        OCR1A= calcPID(&xPID, xError); //PB1 output
    //xPWM   = calcPID(&xPID, xError);
    //OCR1A= xPWM;//设置PWM输出的占空比
   }
   else
   {
    PORTD=0<<PD0;//PD0=0
   
        xError = 511-xpos;   
    OCR1A=calcPID(&xPID, xError);
        //xPWM   = calcPID(&xPID, xError);
    //OCR1A= xPWM; //设置PWM输出的占空比
   }
对于:xpos>511-->xError=2*ZD-xPOS 为什么把误差取在那??,直接xpos>511-->xError=xpos-511 或 xpos<511-->xError=511-xpos 不行吗?
xError 与 PID函数calcPID(&xPID, xError) 的关系,怎样通俗的理解?
那程序是如何产生双极性的PWM波形呢?

chongcao 发表于 2010-6-4 17:08:35

回复【61楼】chongcao
-----------------------------------------------------------------------

似有悟,不知对否?
http://cache.amobbs.com/bbs_upload782111/files_29/ourdev_559578.GIF
(原文件名:ZD.GIF)
T1 T2 期间:PORTD=0<<PD1;//PD1=0
            yError = 511-ypos;
           OCR1B= calcPID(&yPID, yError);
             可以理解为:          偏差愈大,占空比越高;
T3 T4 期间:PORTD=1<<PD1;//PD1=1
           ypos=ypos-511;
            yError = 511 - ypos;
            OCR1B= calcPID(&yPID, yError);
            PWM波形极性没变,但是误差越大,占空比越小,此时起作用的是,PWM波形的低电平,“空”越宽,从而最终加到电磁铁上的波形极性是反转的!

gzhuli 发表于 2010-6-5 16:09:52

回复【62楼】chongcao
-----------------------------------------------------------------------

是的。

chongcao 发表于 2010-6-6 09:24:54

谢谢楼上的指导!
    LM324 m8电路,面包板已制作完毕,遗憾的是,下载源程序时,可能是并口下载线制作有问题,烧坏了台式机的并口。好在用笔记本下载通过。以后再做个,USB-ISP 下载线吧。
   1.65V,调试很敏感,直接用10K调,太敏感,回头上下加10K电阻试试。
   没有接电磁铁,用示波器观察某一组的波形,当1.65V正确时,能够得到设计的波形,且能够随着磁体-霍尔的相对位置的变化而变化,但是如果1.65V偏离太大,控制波形就不是理想设计的了。
   霍尔上端没有磁铁时,为什么PD0 PB1仍然有方波输出?
   根据示波器波形画出如下波形示意图:

http://cache.amobbs.com/bbs_upload782111/files_29/ourdev_559872.GIF
(原文件名:实验波形动画.GIF)
   从中可以看出,上磁铁左--右移动时,PB1的波形“极性”发生了变化(有个界线),占空比也随磁铁的移动变化,与程序的原理相吻合。

gzhuli 发表于 2010-6-6 09:48:15

方波输出肯定有的,哪有1.65V一点不差的?

chongcao 发表于 2010-6-6 10:00:56

噢,大师在线呀!谢谢了,我那实验波形对吗?
理论上,如果1.65V准确就应该是一条线?既然有误差,是不是不必刻意追求1.65V的准确?
1.65V,调试很敏感,直接用10K调,太敏感,回头上下加10K电阻试试。 ---可行否?
把10K 可变电阻接到3.3v试试。
    通过实验我还发现,实际的情况与我原来的想象还是有出入的。原以为,上磁铁倾斜才会有霍尔反映的,实际是,上磁铁水平移动到一定距离霍尔才反映的,霍尔检测的主要是上磁铁的水平移动!

gzhuli 发表于 2010-6-6 10:28:30

磁悬浮是一个闭环控制系统,电磁铁控制悬浮磁铁,霍尔检测磁铁位置反馈给控制电路,最终使霍尔输出和中点电压相等,所以其实1.65V并不需要绝对精准,系统能自动调节过来的。
4个电磁铁控制的是悬浮磁铁的水平位置,不能控制倾斜,所以有可能还要加适当的配重物,使悬浮磁铁保持稳定。

chongcao 发表于 2010-6-8 10:06:32

谢谢楼主的指导,我把M8做下推悬浮的程序直接用于上拉式悬浮,程序没改,用了一个通道,功率驱动用了一只场效应管,霍尔检测先放在下端(这种方法最简单,容易理解、调试),悬浮成功。
    实验发现,场效应管的输入电容效应还是比较明显的,把方波拉弯了,好在不影响工作。
    不知何故,稳定性没有模拟的好,原来实验的模拟电路,可以说一丝不动,放2个小时也没问题,单片机反而不是很理想,原以为会更好。
    提高悬距不知从何下手?
    提高功放供电电压?增加电磁铁的圈数?用更大更强的悬浮磁铁?

gzhuli 发表于 2010-6-8 11:11:29

原来的程序是控制磁铁水平位置的,上拉式是控制垂直距离的,PID参数需要重新调整才能工作在最佳状态。
由于上拉式是单向的,没有一个中点位置,应该要把I参数也用上,以修正累积误差,否则时间长了累积误差不断增大,就不能悬浮了。

chongcao 发表于 2010-6-8 15:49:01

谢谢大师的指导!
由于有前期制作模拟电路的经验,对单片机的实验,想了半天才想明白其中的原理(没改程序)。但是只是对整个程序工作原理有大致了解,对其中的P、I、D参数还真不明白,不知道他们做何用?
我现在的实验,I 取何值比较合适?程序其他地方还动吗?

chongcao 发表于 2010-6-9 09:42:24

gzhuli 咕唧霖 同志,你有:elder60 60岁老头的联系方式吗?我有事情想请教他,一直没他的消息。

gzhuli 发表于 2010-6-9 22:23:46

回复【71楼】chongcao
-----------------------------------------------------------------------

没有啊……

crazy_b-boy 发表于 2010-6-23 20:11:21

好酷我回来了

crazy_b-boy 发表于 2010-6-23 20:35:07

线圈不会热吗

bbi3014 发表于 2010-6-23 20:58:05

狠人啊

czxxn 发表于 2010-6-24 16:37:15

请教!LZ的源程序,其中unsigned int ccc; 是什么意思


//-----------------------------------------------------------------------------
void main(void)
{
unsigned int ZD;
unsigned int ccc;
init_devices();

ZD=511;
// PID Parameter Initialization
xPID.Kp = 4;
xPID.Ki = 0;
xPID.Kd = 30;
xPID.integrationError = 0;
xPID.prevError = 0;
xPID.targetValue = ZD;

yPID.Kp = 4;
yPID.Ki = 0;
yPID.Kd = 30;
yPID.integrationError = 0;
yPID.prevError = 0;
yPID.targetValue = ZD;



while(1)
{

zhihaoa 发表于 2010-7-27 15:23:16

mark

crazy_b-boy 发表于 2010-10-25 12:38:24

一上电就有输出?霍尔高吗?电压不是中间值?线圈还热?511要改吗?

liguang70217 发表于 2010-10-25 13:15:29

上电就有输出,电磁铁不放上的话理论上霍尔无信号,先调节运放输出电压为参考电压的1/2值,线圈温热属正常,511不需要改。

crazy_b-boy 发表于 2010-10-25 16:52:15

回复【79楼】liguang70217
-----------------------------------------------------------------------

谢谢楼主

crazy_b-boy 发表于 2010-10-26 17:18:23

//--------------------------------------------------------------------------
//下推式磁悬浮源程序2009.12.18
//liguang70217
//liguang70217@126.com
//http://liguang70217.blog.hexun.com/
//ICC-AVR application builder : 2009-12-17 17:27:22
// Target : M8
// Crystal: 12.000Mhz
//--------------------------------------------------------------------------
#include <iom8v.h>
#include <macros.h>
#defineN7
#define MAX_PID_OUTPUT       950
#define MAX_INTEGRATION_ERROR 100
#define X_DIRECTION_FLAG         0x01
#define Y_DIRECTION_FLAG         0x02
//--------------------------------------------------------------------------
typedef struct {
int targetValue;
int Kp;
int Ki;
int Kd;
int integrationError;
int prevError;
} PID;

PID xPID,yPID;

unsigned char direction;

unsigned int value_buf_x,value_buf_y;
unsigned char ix=0,iy=0;

unsigned int xpos,ypos;//AD转换后存放采集值
unsigned char HH;

unsigned intxError, yError;
unsigned intxPWM, yPWM;
//--------------------------------------------------------------------------
//------------延时子程序----------------------------------------------------
void delay(unsigned int h)
{
unsigned char j;
while(h--){
       for(j=190;--j;) continue;
          }
}
//--------------------------------------------------------------------------
// PID calculation routine
int calcPID(PID *pid, int error)
{
int output;

if (pid->Ki != 0)
{
pid->integrationError += error;
// Limit the maximum integration error
if (pid->integrationError > MAX_INTEGRATION_ERROR)
{
pid->integrationError = MAX_INTEGRATION_ERROR;
}
else if (pid->integrationError < -MAX_INTEGRATION_ERROR)
{
pid->integrationError = -MAX_INTEGRATION_ERROR;
}
}

output = pid->Kp * error + pid->Ki * pid->integrationError + pid->Kd * (error - pid->prevError);

// Limit the maximum output
if (output > MAX_PID_OUTPUT)
{
output = MAX_PID_OUTPUT;
}
else if (output < -MAX_PID_OUTPUT)
{
output = -MAX_PID_OUTPUT;
}

pid->prevError = error;
return output;
}
//--------------------------------------------------------------------------
void port_init(void)
{
PORTB = 0xff;
DDRB= 0xff;
PORTC = 0x00; //m103 output only
DDRC= 0x00;
PORTD = 0x00;
DDRD= 0xff;
}
//--------------------------------------------------------------------------
//TIMER1 initialize - prescale:1
// WGM: 7) PWM 10bit fast, TOP=0x03FF
// desired value: 2KHz
// actual value: 11.719KHz (82.9%)
void timer1_init(void)
{
TCCR1B = 0x00;//停止定时器
TIMSK |= 0x00;//中断允许
TCNT1H = 0x00;
TCNT1L = 0x00;//初始值
OCR1AH = 0x01;
OCR1AL = 0xFF;//匹配A值
OCR1BH = 0x01;
OCR1BL = 0xFF;//匹配B值
ICR1H= 0xFF;
ICR1L= 0xFF;//输入捕捉匹配值
TCCR1A = 0xA3;
TCCR1B = 0x09;//启动定时器
}
//--------------------------------------------------------------------------
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
MCUCR= 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR   = 0x00;

port_init();
timer1_init();

// TIMSK = 0x04; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//-----------------------------------------------------------------------------
//ADC采样函数,采样第0通道信号,采样分辨率256
//x为ad端口号
unsigned int get_ad(unsigned char x)
{
union adres{ int y1; unsignedcharadre; }adresult;
unsigned int i;
ADMUX = 0xc0+x;            /*基准AVCC、左对齐、通道7*/   
ADCSRA = 0xC3;            /*使能、开启、8分频*/
while(!(ADCSRA & (1 << ADIF)));   /*等待*/
adresult.adre=ADCL;            //读取并存储A/D转换结果,A/D转换的结果通过共
adresult.adre=ADCH;            //用体的形式放入了变量y1中   
ADCSRA &= ~(1 << ADIF);    /*清标志*/
ADCSRA &= ~(1 << ADEN);    /*关闭转换*/
return adresult.y1;
}
//--------------------------------------------------------------------------
//滑动平均滤波
unsigned int filter_x(void)
{
   unsigned char count;
   unsigned longsum=0;
   value_buf_x = get_ad(0);
   ix=ix+1;
   if ( ix == N ) ix = 0;
   for ( count=0;count<N;count++)
             sum = sum + value_buf_x;
   return (unsigned int)(sum/N);
}
//--------------------------------------------------------------------------
//滑动平均滤波
unsigned int filter_y(void)
{
   unsigned char count;
   unsigned longsum=0;
   value_buf_y = get_ad(1);
   iy=iy+1;
   if ( iy == N ) iy = 0;
   for ( count=0;count<N;count++)
         sum = sum + value_buf_y;
   return (unsigned int)(sum/N);
}
//-----------------------------------------------------------------------------
void main(void)
{
unsigned int ZD;
unsigned int ccc;
init_devices();

ZD=511;
// PID Parameter Initialization
xPID.Kp = 4;
xPID.Ki = 0;
xPID.Kd = 30;
xPID.integrationError = 0;
xPID.prevError = 0;
xPID.targetValue = ZD;

yPID.Kp = 4;
yPID.Ki = 0;
yPID.Kd = 30;
yPID.integrationError = 0;
yPID.prevError = 0;
yPID.targetValue = ZD;



while(1)
{
   xpos=filter_x();
   ypos=filter_y();
   
   if(xpos>ZD)
   {
    xpos=xpos-ZD;
PORTD|=(1<<0);//CA=1
    xError = xPID.targetValue - xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;   
   }
   else
   {
    xpos=ZD-xpos;
PORTD&=~(1<<0);   //CA=0
xError = xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;
   }
      
   if(ypos>ZD)
   {
    ypos=ypos-ZD;
PORTD|=(1<<1);//CB=1
    yError = yPID.targetValue - ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;   
   }
   else
   {
    ypos=ZD-ypos;
PORTD&=~(1<<1);   //CB=0
    yError = ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;   
   }
}
}

仿造没成功线圈电阻大约多少啊 有反馈 硬件也不用太精确啊 郁闷

crazy_b-boy 发表于 2010-10-26 17:20:06

仿造不成功啊 线圈电阻多大啊 有反馈 硬件不用太苛刻吧 郁闷

crazy_b-boy 发表于 2010-10-26 18:49:29

//--------------------------------------------------------------------------
//下推式磁悬浮源程序2009.12.18
//liguang70217
//liguang70217@126.com
//http://liguang70217.blog.hexun.com/
//ICC-AVR application builder : 2009-12-17 17:27:22
// Target : M8
// Crystal: 12.000Mhz
//--------------------------------------------------------------------------
#include <iom8v.h>
#include <macros.h>
#defineN7
#define MAX_PID_OUTPUT       950
#define MAX_INTEGRATION_ERROR 100
#define X_DIRECTION_FLAG         0x01
#define Y_DIRECTION_FLAG         0x02
//--------------------------------------------------------------------------
typedef struct {
int targetValue;
int Kp;
int Ki;
int Kd;
int integrationError;
int prevError;
} PID;

PID xPID,yPID;

unsigned char direction;

unsigned int value_buf_x,value_buf_y;
unsigned char ix=0,iy=0;

unsigned int xpos,ypos;//AD转换后存放采集值
unsigned char HH;

unsigned intxError, yError;
unsigned intxPWM, yPWM;
//--------------------------------------------------------------------------
//------------延时子程序----------------------------------------------------
void delay(unsigned int h)
{
unsigned char j;
while(h--){
       for(j=190;--j;) continue;
          }
}
//--------------------------------------------------------------------------
// PID calculation routine
int calcPID(PID *pid, int error)
{
int output;

if (pid->Ki != 0)
{
pid->integrationError += error;
// Limit the maximum integration error
if (pid->integrationError > MAX_INTEGRATION_ERROR)
{
pid->integrationError = MAX_INTEGRATION_ERROR;
}
else if (pid->integrationError < -MAX_INTEGRATION_ERROR)
{
pid->integrationError = -MAX_INTEGRATION_ERROR;
}
}

output = pid->Kp * error + pid->Ki * pid->integrationError + pid->Kd * (error - pid->prevError);

// Limit the maximum output
if (output > MAX_PID_OUTPUT)
{
output = MAX_PID_OUTPUT;
}
else if (output < -MAX_PID_OUTPUT)
{
output = -MAX_PID_OUTPUT;
}

pid->prevError = error;
return output;
}
//--------------------------------------------------------------------------
void port_init(void)
{
PORTB = 0xff;
DDRB= 0xff;
PORTC = 0x00; //m103 output only
DDRC= 0x00;
PORTD = 0x00;
DDRD= 0xff;
}
//--------------------------------------------------------------------------
//TIMER1 initialize - prescale:1
// WGM: 7) PWM 10bit fast, TOP=0x03FF
// desired value: 2KHz
// actual value: 11.719KHz (82.9%)
void timer1_init(void)
{
TCCR1B = 0x00;//停止定时器
TIMSK |= 0x00;//中断允许
TCNT1H = 0x00;
TCNT1L = 0x00;//初始值
OCR1AH = 0x01;
OCR1AL = 0xFF;//匹配A值
OCR1BH = 0x01;
OCR1BL = 0xFF;//匹配B值
ICR1H= 0xFF;
ICR1L= 0xFF;//输入捕捉匹配值
TCCR1A = 0xA3;
TCCR1B = 0x09;//启动定时器
}
//--------------------------------------------------------------------------
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
MCUCR= 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR   = 0x00;

port_init();
timer1_init();

// TIMSK = 0x04; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//-----------------------------------------------------------------------------
//ADC采样函数,采样第0通道信号,采样分辨率256
//x为ad端口号
unsigned int get_ad(unsigned char x)
{
union adres{ int y1; unsignedcharadre; }adresult;
unsigned int i;
ADMUX = 0xc0+x;            /*基准AVCC、左对齐、通道7*/   
ADCSRA = 0xC3;            /*使能、开启、8分频*/
while(!(ADCSRA & (1 << ADIF)));   /*等待*/
adresult.adre=ADCL;            //读取并存储A/D转换结果,A/D转换的结果通过共
adresult.adre=ADCH;            //用体的形式放入了变量y1中   
ADCSRA &= ~(1 << ADIF);    /*清标志*/
ADCSRA &= ~(1 << ADEN);    /*关闭转换*/
return adresult.y1;
}
//--------------------------------------------------------------------------
//滑动平均滤波
unsigned int filter_x(void)
{
   unsigned char count;
   unsigned longsum=0;
   value_buf_x = get_ad(0);
   ix=ix+1;
   if ( ix == N ) ix = 0;
   for ( count=0;count<N;count++)
             sum = sum + value_buf_x;
   return (unsigned int)(sum/N);
}
//--------------------------------------------------------------------------
//滑动平均滤波
unsigned int filter_y(void)
{
   unsigned char count;
   unsigned longsum=0;
   value_buf_y = get_ad(1);
   iy=iy+1;
   if ( iy == N ) iy = 0;
   for ( count=0;count<N;count++)
         sum = sum + value_buf_y;
   return (unsigned int)(sum/N);
}
//-----------------------------------------------------------------------------
void main(void)
{
unsigned int ZD;
unsigned int ccc;
init_devices();

ZD=511;
// PID Parameter Initialization
xPID.Kp = 4;
xPID.Ki = 0;
xPID.Kd = 30;
xPID.integrationError = 0;
xPID.prevError = 0;
xPID.targetValue = ZD;

yPID.Kp = 4;
yPID.Ki = 0;
yPID.Kd = 30;
yPID.integrationError = 0;
yPID.prevError = 0;
yPID.targetValue = ZD;



while(1)
{
   xpos=filter_x();
   ypos=filter_y();
   
   if(xpos>ZD)
   {
    xpos=xpos-ZD;
PORTD|=(1<<0);//CA=1
    xError = xPID.targetValue - xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;   
   }
   else
   {
    xpos=ZD-xpos;
PORTD&=~(1<<0);   //CA=0
xError = xpos;
    xPWM   = calcPID(&xPID, xError);
    OCR1A= xPWM;
   }
      
   if(ypos>ZD)
   {
    ypos=ypos-ZD;
PORTD|=(1<<1);//CB=1
    yError = yPID.targetValue - ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;   
   }
   else
   {
    ypos=ZD-ypos;
PORTD&=~(1<<1);   //CB=0
    yError = ypos;
    yPWM   = calcPID(&yPID, yError);
    OCR1B= yPWM;   
   }
}
}
望高手指教

crazy_b-boy 发表于 2010-11-16 14:17:35

我放上上去上面的磁铁一直在抖 一会就掉了 非常不稳定 有时候还转得非常快

liguang70217 发表于 2010-11-18 13:34:03

晶振多大的?我用的是16M,底下的磁铁要和电磁铁平行,电磁铁在上,环形磁铁在下,电磁铁中心部分下半节可以放入半截磁芯,以加强磁力,一般的抖动的原因:一是单片机运行速度不够快,二是电磁铁磁力不够,三是永磁铁和电磁铁的位置偏差较大。

crazy_b-boy 发表于 2010-11-18 17:40:30

12M的晶振 ADCSRA = 0xC3;            /*使能、开启、8分频*/这是采样频率吧 用手拿着可以感觉到个方向的阻力
xPID.Kp = 4;
xPID.Ki = 0;
xPID.Kd = 30; 参数调的时候我怎么看震荡啊位置的偏差也就是霍尔了 洞洞板两个洞之间的距离吧

liguang70217 发表于 2010-11-18 18:28:21

PID参数凭经验而定,但一定要理解到位三个参数的作用,设置就简单了;悬浮磁铁应加配重,如果悬浮磁铁较轻的话同样不稳;我的那个是直径25的。

crazy_b-boy 发表于 2010-11-18 19:49:02

我的是19可能是小了 线圈距离有些大

crazy_b-boy 发表于 2010-11-21 19:23:53

熔丝位是1111吧 16M 晶振 PID 不合适 他就会一直抖吗?

crazy_b-boy 发表于 2010-11-21 19:28:57

会不会是 电阻放大的21倍 就很大了 pwm占空比输出就很大啊

ykcxw1972 发表于 2010-11-21 21:28:37

回复【楼主位】liguang70217
-----------------------------------------------------------------------

你好,能给我多指导吗?我是外行,但我相信我能。

ykcxw1972 发表于 2010-11-21 21:33:03

楼主:你好!
    我想同你联系,如果可以请给我来电:13064607808,或来个短信,谢谢!

crazy_b-boy 发表于 2010-11-26 15:45:29

为什么我测量线圈两端只有一个方向的电压啊
不是双极性吗?

crazy_b-boy 发表于 2010-11-30 21:33:49

点击此处打开 ourdev_601455HZJE07.jpg(文件大小:1.22M,只有400K以内的图片才能直接显示) (原文件名:20101128322.jpg)

gzhuli 发表于 2010-12-1 09:26:49

回复【94楼】crazy b-boy
-----------------------------------------------------------------------

成功了?

crazy_b-boy 发表于 2010-12-1 20:36:03

回复【95楼】gzhuli 咕唧霖
-----------------------------------------------------------------------


谢谢您

crazy_b-boy 发表于 2010-12-1 20:36:32

http://v.youku.com/v_show/id_XMjI2NjMxMTI4.html 我做的优酷视频

gzhuli 发表于 2010-12-1 21:15:07

很不错呀,能说说最后参数是怎么样的吗?
另外,L298N那么大个散热还要加风扇?应该没这么大功耗的吧?我DIP16的L293D都没上散热片。

pinocchio 发表于 2010-12-2 00:10:20

mark
页: [1] 2
查看完整版本: 用ATmega8制作的下推式磁悬浮