做微波炉变压器点焊机,程序设计
本帖最后由 xyz123123 于 2020-3-5 18:48 编辑《http://www.shoudian.org/forum.php?mod=viewthread&tid=1505742 做微波炉变压器点焊机,先做控制板》
接下来是程序设计。
电路板焊好后,首先要闪个灯,以确认基本正常。
while (1)
{
LED_PIN = ~LED_PIN;
Delay_ms(500);
}
延时在很多地方用到,如液晶屏接口时序控制,蜂鸣器,液晶屏文字显示停留时间,焊接时间控制等。因此做成一个子程序。
Keil C51调用函数时传递参数、LCALL、函数返回的RET,开销是固定的。在C程序中嵌入汇编指令,在计数判断各分支插入适当的NOP指令,保证跳或不跳都耗同样的时间,就能实现准确延时若干个机器周期。
使用12MHz晶振时,传统51单片机一个机器周期是1μs,比较简洁。延时函数就写成
void Delay_us(int8u t);1个字节只能计到255μs,适用于电路时序控制等需要十几~一两百微秒延时的地方。
8位的51单片机处理16位数要复杂一点,因此另写一个
void Delay_us_2(int16u t);参数是2字节整数,可实现几十~65535μs的延时。
当超过上百毫秒时,就不需精确到微秒程度了,可调用刚才的Delay_us_2()。
void Delay_ms(int16u t)
{
while (t != 0)
{
Delay_us_2(99x);
t -= 1;
}
}
本帖最后由 xyz123123 于 2020-3-5 18:49 编辑
接下来要点亮液晶屏。
大众款1602字符屏,控制芯片一般是HD44780或相似的。
虽是大众款,可芯片手册难见一份准确的,连初始化的几条指令流程都讲得不太清晰,各兼容芯片的手册都差不多。日货一向小气,估计自该芯片面世起也是能用就得了,内部逻辑结构、设计意图、应用细节,只有设计此芯片的那几个人自珍了。所以拿它来简单用用即可,没多少好考究的。
虽然芯片规格称接口速度能到1MHz,但液晶模块里PCB走线细且长,又未适当接电源退耦电容,用示波器观察可见波形边沿形状不好。所以将控制脉冲放慢到2~3μs。
使用12MHz晶振时,传统51单片机一条指令一两μs,和HD44780配合较合适。现今的单时钟周期51单片机或其它高速单片机主频十几MHz以上,1μs能运行十多条指令,受影响明显。
虽然HD44780提供BUSY信号可查询,但控制指令总共就清屏、设置模式、设置光标、读写数据、读写地址这几条,执行耗时都是固定的,没必要去读BUSY信号。
况且读BUSY信号这个操作本身也和其它指令一样速度不高。
再有,网上见的资料大多没提到,读BUSY信号这个操作还须等上一次指令之后好几十微秒才能进行。呃,除了清屏、归零两条指令耗时1.5ms外,其它指令耗时均才37μs,比读BUSY信号还快咧{:5_616:}。
支持大神,编程我玩不来 本帖最后由 xyz123123 于 2020-3-1 23:15 编辑
HD44780每行的显存是40个字符,1602屏每行只可显示16个字符。
屏幕滚动的功能似乎没什么用,估计不太会用它去做滚动广告、屏保之类的吧。对显示效果要求不高,一般也不会去搞两屏内容快速切换。
因此写几个常用的功能就够。
void LcdLocate(int8u row, int8u col);//指定字符显示位置。
void LcdPrint(int8u c);//显示一个字符。
void LcdPrintString(int8u row, int8u col, int8u *str);//依次显示str中的字符,直至'\0'。不考虑超出16列、换行之类的。
void LcdClearRow(int8u row);//其实就是从行首位置起显示16个空格。
例如,程序初始的界面:
LcdInit();
LcdPrintString(1, 1, "Spot Welder");
LcdPrintString(2, 1, " 2020-02");
本帖最后由 xyz123123 于 2020-3-15 21:57 编辑
接下来是按键。
设置一个定时中断,每1ms扫描一遍按键,记录每个按键的状态、持续时间。当连续若干次的状态不变时,才认为按键已稳定。
一般微动开关的按键抖动多在5ms以内。若要过滤50Hz市电线路的干扰,可将判断时间加长到几十毫秒,不过按键的响应也会相应延迟。这个时间值可做进参数设置功能里,让用户自由变更。
在菜单操作中,按+、-键调节数值时,短按一次增减1步长,若持续按键达一两秒则连续自动调节,例如一秒重复10次。
大范围的调节,例如“触发延迟10~15000μs,调节步长10μs”,一秒重复10次的话,持续按键要150秒才能调到头,显然太久。一般按着键十几秒估计就令人厌烦了。
因此须判断当持续按键超过例如3秒后,进一步加速,例如一秒重复100次。
有些产品按键很少,看似简洁,但用起来要区分短按、长按,功能复用太多,很麻烦。
这里准备6个按键:设置,取消,减,增,确认,焊接。
按〖设置〗进入参数设置菜单,〖减〗〖增〗移动光标,〖确认〗进入该项,〖取消〗退回上一级菜单。
在参数项目中,按〖减〗〖增〗进行调节,持续按着可快速调节,按〖确认〗保存,〖取消〗则放弃更改。
调试观察,扫描一次6个按键要耗好几百步。传统51单片机接12MHz晶振时,1ms里有六七百μs都用来处理按键了。
简单控制类的应用通常运算量不多,需要的是响应速度。按上述情况,若不用高优先级中断,就要等几百微秒处理完按键之后再来响应其它事件,而且剩下的处理能力只剩两百多步了。
例如控制步进电机,一圈200个脉冲,每秒5转,则每1ms要处理一个脉冲,1ms内只剩两百多μs来处理,较吃力。
换成现今的单周期51,速度翻十几倍,1ms里只用去了几十μs,能充分迅速地响应其它事件。
现在做这个点焊机控制,没什么需要高速响应的控制,焊接动作那几百毫秒精确计时期间可暂停按键、液晶屏等其它处理,大众款51足以胜任了。
你是高手,厉害 学习高手编程 本帖最后由 xyz123123 于 2020-3-5 18:50 编辑
接下来是存储器。
需要保存的几个参数:
交流电过零点之后多久触发。
第一次焊接时间。
第一次焊接之后等待时间。
第二次焊接时间。
第二次焊接之后等待时间。
交流过零检测电路是个电压比较器,检测到电压低于一定值时动作,在零点左右产生一个约1ms宽的脉冲。
程序可能是在零点之前捕捉到,则延时几百μs后即零点。或是零点之后才捕捉到,则下个半波零点是9点几ms之后。
为了保持磁平衡,令变压器每次通电整数个全波,因此零点之后才捕捉到的,下个过零点选在19点几ms之后。
于是,该参数的设置范围是0~20000μs。
整机做好后,用示波器观察程序捕捉到的零点时刻,减去接触器机械动作延迟时间,来做设定。小继电器的动作时间大概是数毫秒,大个头的接触器不知如何。
不用示波器的话,也可观察接触器触点通断时的火花,调节达到火花最小即可。
据说先短焊第一次,可去除氧化层、预热,紧接着焊第二次,这样的效果好。因此预留了两组焊接、等待的时间参数。
为了保持磁平衡,焊接时间取20ms的整数倍,范围定20~2000ms吧。
焊接时间也可短到10ms的倍数,程序里只要记录是在正半周还是负半周的过零点触发的,下次交换即可。估计20ms够短了,先不考虑太复杂的。
焊接之间的间隔,感觉100~2000ms范围可以了。
AT24Cxx存储器,便宜,IIC接口不复杂。
为防芯片上电自动复位失败,程序应对其发指令复位。方法见芯片手册,通常发至多9个SCL时钟就能完成。
只读写几个字节,不需考虑连续读写、页长度之类的,做两个子程序就好。
void At24cByteWrite(int8u addr, int8u dat);
int8u At24cRandomRead(int8u addr);
Keil C51将多字节整数按高位字节先行,保存到AT24Cxx时按同样顺序就好。
例如保存一个2字节整数4779,可在存储器地址0x00存0x12、地址0x01存0xAB。
本帖最后由 xyz123123 于 2020-3-1 21:27 编辑
硬件部分基本好了。接下来是菜单操作过程。
按〖设置〗键,进入菜单。
按〖减〗〖增〗移动光标,〖确认〗进入该项,〖取消〗退回上一级菜单。
按〖减〗〖增〗进行调节数值,持续按着可快速调节,按〖确认〗保存,〖取消〗则放弃更改。
退出最初级菜单后,回到等待焊接状态。
各项参数都是简单整数,调节过程都是相似的,只是提示文字、数值范围不同。将不同的部分定义一个结构体
typedef struct
{
int8u *Title;
int8u *Unit;
int16u Value;
int16u ValueMin;
int16u ValueMax;
int16u ValueAdj;
} INPUT_DIALOG;
做一个子程序InputDialog()来统一调用,比较简洁。例如设置触发延时:
……
INPUT_DIALOG dialog;
dialog.Title = "Trig Delay";
dialog.Unit = "us";
dialog.Value = (int16u)At24cRandomRead(ADDR_TRIG_DELAY) << 8;
dialog.Value |= At24cRandomRead(ADDR_TRIG_DELAY + 1);
dialog.ValueMin = 0;
dialog.ValueMax = 20000;
dialog.ValueAdj = 10;
InputDialog(&dialog);
……
换stm32f0系列更好,便宜效率更高 玩得不是一般的溜! 本帖最后由 xyz123123 于 2020-3-5 18:46 编辑
主程序部分就简单了,按〖设置〗键就进入参数设置菜单,按〖焊接〗则暂停扫描按键、等待过零信号、驱动继电器。
void main()
{
LcdPrintString(1, 1, "Spot Welder");
LcdPrintString(2, 1, " 2020-02");
LoadConfig();
while(1)
{
if (KeyIsPressed(KEY_SETUP))
{
Menu();
LoadConfig();
}
else if (KeyIsPressed(KEY_WELD))
{
//暂停按键扫描
//等待过零信号
Delay_us_2(cfg_TrigDelay);
RELAY = RELAY_ON;
Delay_ms(cfg_WeldingTime1);
RELAY = RELAY_OFF;
Delay_ms(cfg_WaitingTime1);
RELAY = RELAY_ON;
Delay_ms(cfg_WeldingTime2);
RELAY = RELAY_OFF;
Delay_ms(cfg_WaitingTime2);
//恢复按键扫描
}
}
}
电路板焊好了,用示波器检测一下。
过零检测用的是交流9V供电入口接两个二极管,驱动一个三极管。交流过零时三极管截止,集电极接的单片机引脚上便出现一个高电平脉冲。
估计是因为小变压器内阻高,仅几十mA的平均电流,整流后的正弦半波顶端已被拉平了。
放大看看。
过零检测用的三极管集电极接的单片机引脚本来是接键盘用的,有个小电容滤波,所以触发波形的上升沿较缓。现在检测的是下降沿,不要紧。
再放大一点。
可见触发脉冲约800μs,即单片机在过零点之后400μs才检测到。
将“触发延迟”这项参数就设为10ms-400μs=9600μs,用单片机的一个空余引脚输出一个信号来观察。
能准确定位到下个过零点。
将参数设置为“第一焊20ms、等100ms、第二焊40ms”的效果。
程序搞定{:5_605:}。
进来看看,看焊接效果。 做好等收成品 组装和初步试验,见《http://www.shoudian.org/forum.php?mod=viewthread&tid=1508031 做微波炉变压器点焊机,总装》。
本帖最后由 hellohello22 于 2020-3-17 00:09 编辑
t -= 1; {:5_616:}
写成 t--; 不是更简单吗
本帖最后由 xyz123123 于 2020-3-17 00:39 编辑
hellohello22 发表于 2020-3-17 00:08
t -= 1;
写成 t--; 不是更简单吗
唔,只对指针使用++和--,那样不易搞错2字节数还是4字节数之类的。算术运算的话都明确地写加减多少。
喜欢程序每一行写得简单,人看着易懂,调试也方便。例如像
while (*str++) {...}这种就觉得不好,喜欢
while (1)
{
c = *p;
if (c == '\0') break;
...
p++;
}这样的。
如何优化是编译器的事,不应让人分心。
如今的编译器感觉蛮给力的,增减1的操作尽量使用对应的机器指令,自不必提。
见Keil C51编译出的,判断一个2字节整数是否等于0
MOV A,低字节
OR A,高字节
JZ ……
还有2字节整数减1
MOV A,低字节
DEC 低字节
JNZ (没有从高字节借位)
DEC 高字节(若原来低字节是0,即为向高字节借了位)
都蛮巧妙的。
xyz123123 发表于 2020-3-17 00:36
唔,只对指针使用++和--,那样不易搞错2字节数还是4字节数之类的。算术运算的话都明确地写加减多少。
喜 ...
++/-- 是自动根据类型处理 , 就算你写-=1 /+=1 也是一样的,毫无差别。
uint32_t *p ;
p++ 和p+=1 都是地址变换4b
uint32_t val;
val++和val+=1 都是数值+1
页:
[1]