单相逆变电源软件设计
单相逆变电源软件设计
文章目录
- 单相逆变电源软件设计
- 一、题目要求
- 1.题目
- 2.系统总体框图
- 二、控制核心及环境配置
- 1.CCS环境配置
- 2.Quartus环境配置
- 三、软件核心功能
- 1.产生SPWM波
- 2.PID算法调控输出电压
- 3.顶层设计
- 四、其他
- 1.FPGA生成固化文件
- 2.其他代码
- 总结
一、题目要求
1.题目
要求设计并制作输入为15V直流电压,输出为10V正弦交流电压的单相逆变电源。
2.系统总体框图
软件思路:
FPGA:利用Matlab生成正弦及三角波查找表,在Quartus中使用rom查表产生正弦波与三角波,比较二者的大小,正弦波大于三角波为“1”,正弦波小于三角波为“0”(双极性调制),产生两路互补的SPWM波,经由逆变电路及滤波电路最终可以得到正弦交变电压,通过改变正弦波的幅值可以改变最终输出电压的大小。
单片机:接收频率设定并传给FPGA,显示当前状态,进行AD采样数字信号到具体值的转换,PID算法稳压。
AD采样:采用ADS8688进行采样,通过积分法Urms2=1T∫0T∣U∣2dtU_{rms}^2=\frac{1}{T}{\int_{0}^{T}}\left| U \right| ^ 2dtUrms2=T1∫0T∣U∣2dt得到交流有效值。
二、控制核心及环境配置
tiva系列单片机:TM4C123GH6PM
Cyclone IVE 系列FPGA:EP4CE6E22C8
IDE:Code Composer Studio 以及 Quartus 17.0
1.CCS环境配置
Code Composer Studio配置:
2.Quartus环境配置
Quartus 17.0配置:
三、软件核心功能
1.产生SPWM波
方案一:单极性调制
方案二:双极性调制
这里我使用的是方案二,双极性调制产生正弦波。
首先利用Matlab产生正弦查找表以及三角波查找表。
产生正弦查找表的代码如下:
ADDR_WIDTH=12;
DATA_WIDTH=16;
depth=2^ADDR_WIDTH;
x=ceil(((2^DATA_WIDTH/2-1)*sin(0:pi*2/depth:2*pi)+2^DATA_WIDTH/2));
fid=fopen('sinrom1.mif','w');
fprintf(fid,'width=%d;\n',DATA_WIDTH);
fprintf(fid,'depth=%d;\n',depth);
fprintf(fid,'address_radix=uns;\n');
fprintf(fid,'data_radix=uns;\n');
fprintf(fid,'Content Begin\n');
for(k=1:depth)fprintf(fid,'%d:%d;\n',k-1,x(k));
end
fprintf(fid,'end;');
产生三角波查找表的代码如下:
ADDR_WIDTH=12;
DATA_WIDTH=16;
depth=2^ADDR_WIDTH;
x=ceil(2*(2^DATA_WIDTH/2-1)*sawtooth(0:pi*2/depth:2*pi)+2^DATA_WIDTH - 1);
y=ceil(-2*(2^DATA_WIDTH/2-1)*sawtooth(0:pi*2/depth:2*pi)+2^DATA_WIDTH - 1);
fid=fopen('trirom1.mif','w');
fprintf(fid,'width=%d;\n',DATA_WIDTH);
fprintf(fid,'depth=%d;\n',depth);
fprintf(fid,'address_radix=uns;\n');
fprintf(fid,'data_radix=uns;\n');
fprintf(fid,'Content Begin\n');
for(k=1:depth/2)fprintf(fid,'%d:%d;\n',k-1,x(k));
end
for(j=depth/2+1:depth)fprintf(fid,'%d:%d;\n',j-1,y(j));
end
fprintf(fid,'end;');
然后在Quartus中利用IP核生成rom查找表实例。
一路Next直到下图所示页面,如图所示选中Matlab生成的.mif文件作为查找表。
最后勾选生成实例文件即可。
生成正弦波和三角波后,比较生成互补的SPWM波,注意要设置死区!
生成SPWM波代码如下:
always @(posedge clk, negedge rst_n)
beginif(!rst_n)beginspwm1_tmp <= 0;spwm2_tmp <= 0;cnt1 <= 0;cnt2 <= 0;endelsebegin//spwm1if(sin_sig >= tri_sig) //延后一段时间再拉高beginif(cnt1 >= dead) //cnt1 == deadbeginspwm1_tmp <= 1;cnt1 <= 0;endelse if(spwm1_tmp != 1) //spwm1还没被拉高,则计数cnt1 <= cnt1 + 1;else; endelsebegin spwm1_tmp <= 0; end//spwm2 if(sin_sig >= tri_sig)begin spwm2_tmp <= 0; endelse //延后一段时间再拉高beginif(cnt2 >= dead) //cnt == deadbeginspwm2_tmp <= 1;cnt2 <= 0;endelse if(spwm2_tmp != 1) //spwm2还没被拉高,则计数cnt2 <= cnt2 + 1;else; endend
end
2.PID算法调控输出电压
调控输出电压可以通过改变正弦波的调制度来实现。这里我使用ADS8688芯片进行交流采样,计算获取交流电压的有效值(代码放在其他代码的压缩包中)。
PID调控代码如下:
void PID(void)
{double deltK;deltV[2] = Vset - Vrms;deltK = Kp * (deltV[2] - deltV[1]) + Ki * deltV[2] + Kd * (deltV[2] - 2 * deltV[1] - deltV[0]);deltV[0] = deltV[1];deltV[1] = deltV[2];K = K + (int)deltK;if(K > KMAX)K = KMAX;else;if(K < KMIN)K = KMIN;else;}
让输出电压稳定的关键一在PID参数选取的适当,二在AD采样准确稳定。
3.顶层设计
Verilog顶层文件:
module DC_AC
(
input wire clk, // 50MHz
input wire rst_n,
input wire [7:0]ADDR,
input wire RD,WR,
input wire SDO, // ADS8688 串行数字输出
//input wire [15:0] K,
//input wire [23:0] fs,output wire spwm1_sig,
output wire spwm2_sig,
output wire irq,
output wire RST, // ADS8688 复位信号
output wire CS, // ADS8688 片选信号(低电平有效)
output wire SCLK, // ADS8688 串行时钟
output wire SDI, // ADS8688 串行数字输入
output wire alarm,inout wire [15:0]DATA,
inout wire [3:0]KEY_H,KEY_V
);wire cs0,cs1,cs2,cs3,cs4,cs5,cs6;
wire software_rst_n;
wire [7:0] rddat0; //mcu读键盘值 CS0
wire [15:0] wrdat0;
wire [15:0] wrdat1; //K CS5
wire [15:0] wrdat2;
wire [15:0] wrdat3; //fs CS7
wire datacs0,datacs1;
wire [3:0]addr_ad;wire [23:0] fc = 24'd17_000; //载波频率17k
wire [23:0] fs; //调制频率
wire [15:0] K; //调制度
wire [15:0] sin_sig;
wire [15:0] tri_sig;
wire clk_50Hz;wire [15:0] outRMS0; //CS1
wire [15:0] outRMS1; //CS2assign fs = wrdat3;
assign K = wrdat1;assign alarm = (K>500)?0:1;Sin Sin_inst
(.clk(clk) , // input clk_sig.rst_n(rst_n) , // input rst_n_sig.fre(fs) , // input [23:0] fre_sig.sin_sig(sin_sig) // output [15:0] sin_sig_sig
);Tripul Tripul_inst
(.clk(clk) , // input clk_sig.rst_n(rst_n) , // input rst_n_sig.fre(fc) , // input [23:0] fre_sig.tri_sig(tri_sig) // output [15:0] tri_sig_sig
);SPWM SPWM_inst
(.clk(clk) , // input clk_sig.rst_n(rst_n) , // input rst_n_sig.sin_input(sin_sig) , // input [15:0] sin_input_sig.tri_sig(tri_sig) , // input [15:0] tri_sig_sig.K(K) ,.spwm1_sig(spwm1_sig) , // output spwm1_sig_sig.spwm2_sig(spwm2_sig) // output spwm2_sig_sig
);clkdiv clkdiv_inst
(.clk(clk) , // input clk_sig.rst_n(rst_n) , // input rst_n_sig.div(32'd1_000_000) , // input [31:0] div_sig.clkout(clk_50Hz) // output clkout_sig
);BUS BUS_inst
(.clk(clk) , // input clk_sig.rst_n(rst_n) , // input rst_n_sig.ADDR(ADDR) , // input [7:0] ADDR_sig.RD(RD) , // input RD_sig.WR(WR) , // input WR_sig.DATA(DATA) , // inout [7:0] DATA_sig.software_rst_n(software_rst_n) , // output software_rst_n_sig.cs0(cs0) , // output cs0_sig.cs1(cs1) , // output cs1_sig.cs2(cs2) , // output cs2_sig.cs3(cs3) , // output cs3_sig.cs4(cs4) , // output cs4_sig.cs5(cs4) , // output cs5_sig.cs6(cs4) , // output cs6_sig.rddat0(rddat0) , // input [7:0] rddat0_sig.rddat1(outRMS0) , // input [7:0] rddat1_sig.rddat2(outRMS1) , // input [7:0] rddat2_sig
// .rddat3(rddat3) , // input [7:0] rddat3_sig.wrdat0(wrdat0) , // output [7:0] wrdat0_sig.wrdat1(wrdat1) , // output [7:0] wrdat1_sig.wrdat2(wrdat2) , // output [7:0] wrdat2_sig.wrdat3(wrdat3) , // output [7:0] wrdat3_sig.addr_ad(addr_ad) , //output reg [3:0]addr_ad.datacs0(datacs0) , //output reg datacs0.datacs1(datacs1) //output reg datacs1
);KEY KEY_inst
(.clk(clk) , // input clk_sig.rst_n(rst_n) , // input rst_n_sig.rddat(rddat0) , // output [7:0] rddat_sig.irq(irq) , // output irq_sig.cs(cs0) , // input cs_sig.KEY_H(KEY_H) , // inout [3:0] KEY_H_sig.KEY_V(KEY_V) // inout [3:0] KEY_V_sig
);ads8688 ads8688_inst
(.clk_50M(clk) , // input clk_50M_sig.rst_n(rst_n) , // input rst_n_sig.addr(addr_ad) , // input [3:0] addr_sig.RD(RD) , // input RD_sig.datacs0(datacs0) , // input datacs0_sig.datacs1(datacs1) , // input datacs1_sig.clk_50Hz(clk_50Hz) , // input clk_50Hz_sig.RST(RST) , // output RST_sig.CS(CS) , // output CS_sig.SCLK(SCLK) , // output SCLK_sig.SDI(SDI) , // output SDI_sig.SDO(SDO) , // input SDO_sig.outRMS0(outRMS0) , // output [15:0] outRMS0_sig.outRMS1(outRMS1) // output [15:0] outRMS1_sig
// .Vc(Vc)
);
endmodule
CCS中的main
函数:
#include "common.h"
#include "bus_fpga.h"
#include "LCD12864_rom_enable.h"
#include "blue.h"
#include <math.h>/*** main.c* 1.7增加了附加功能:1、按键设置 2、过流保护灯亮 3、蜂鸣器*/const int FMIN = 1;
const int FMAX = 999;
const double FULL = 10.24;
const double Vset = 10;
const int KMAX = 990;
const int KMIN = 900;char keydat;
int a;
int fs = 50;
int K = 900; //K的精度为1/1000
double Vrms = 0;
double Irms = 0;
double deltV[3] = {0};
float Kp = 45; //65 30 60; 38 35
float Ki = 10; //27 16 24; 17
float Kd = -12; //-10; -25 -20 -25
double V_list[5] = {0};
double I_list[5] = {0};
double V_sum;
double I_sum;
unsigned int j;
int overFlag = 0;
int fs_tmp[3] = {-1,-1,-1};void mcuInit(void);
void getKey(void);
void getAD(int cnt);
void overCurrent(void);
void keyResponse(void); //无用
void changeFreq(void);
void PID(void);
void showPID(void); //无用
void ctrlPID(void); //无用
double change_voltage(unsigned int AD_value,double FS);
void showStatus(void);
void WRFPGA(void);
int datalen(int data);
void __key_delay(void);int main(void)
{mcuInit();initialize_uart();while(1){V_sum = 0;I_sum = 0;for(j=0;j<5;j++){ //采样5次取平均值__key_delay();getKey();changeFreq();
// getStringFVT();
// updateKey(&a);getAD(j);PID();showStatus();WRFPGA();V_sum = V_sum + V_list[j];I_sum = I_sum + I_list[j];}Vrms = V_sum / 5 * 7.80435435; // * 7.810155Irms = I_sum / 5 * 0.47501069;PID();overCurrent();}}
四、其他
1.FPGA生成固化文件
FPGA本身并没有存储程序的功能,需要依靠外部flash芯片来实现程序的固化。以下两种方法分别介绍了用AS口和JTAG口固化程序。
方法一:生成.pof文件
step1:从Assignments进入Device。
step2:选择Device and Options。
step3:按照下图更改选项,注意这里的Device要看你FPGA上的flash芯片型号。
step4:全编译一下即可得到.pof文件。第一次烧录需要 Add Device 和 Add File。
方法二:生成.jic文件
step1:在File里面找到Convert Programming Files。
step2:选择生成.jic文件,同时选择flash芯片型号。
step3:往下翻找到Flash Loader添加设备,添加对应FPGA型号。
step4:选择SOF Data,添加.sof文件。
step5:点击Generate再重新全编译一遍即可生成.jic文件,用JTAG口,在烧录时Add File中选中相应的.jic文件即可。
烧录后,FPGA重新上电即成功固化程序。
2.其他代码
见单相逆变电源程序压缩包。
总结
在用Tiva和FPGA进行开发的时候,要注意二者之间的通信问题,比如有时候通信通道会传一些不定值,可能换个通道就好了。在CCS中烧录程序时如果配置出错可能会导致程序无法烧录,务必要正确配置后再进行烧录,可以先了解一些配置的基础知识。
单相逆变电源软件设计相关推荐
- matlab单相电源在哪里,浅谈基于MATLAB的单相独立光伏逆变电源电路仿真设计
156电子技术 独立型光伏发电系统系统结构如图 1 所示,主要有太阳电池组件(方阵).控制器.储能蓄电池(组).直流 / 交流逆变器等部分组成.光伏阵列发出的直流电通过器将其逆变为交流电供给负载,蓄电 ...
- 从零开始做单相逆变电源(硬件)
文章目录 前言 一.主要模块需求 1.全桥模块 2.采样电路 光耦 前言 题目:单相正弦逆变电源 具体软件部分请参照从零开始做单相逆变电源(软件)] 一.主要模块需求 本系统以TM4C123GH6PM ...
- 三相逆变器双pi控制器参数如何调节_单相逆变电源的电压双闭环矢量控制新方法,解决传统方案的不足...
东北大学信息科学与工程学院.潞安集团司马煤业有限公司的研究人员宋崇辉.徐涛.王振环.刁乃哲.陈宏志,在2019年第16期<电工技术学报>上撰文(论文标题为"单相逆变电源电压双闭环 ...
- 多核片上系统(SoC)架构的嵌入式DSP软件设计
多核片上系统(SoC)架构的嵌入式DSP软件设计 Multicore a System-on-a-Chip (SoC) Architecture SoCs的软件开发涉及到基于最强大的计算模型在各种处理 ...
- 软件设计之 数据库设计
[按语:在软件设计或是动态网站开发中,数据库设计时很重要,我觉得可以说是开发工作的核心部分,所以学好数据库设计,是很重要的,也是大有前途的...] ◆.概念 首先要搞清楚容易混淆的两个概念:&quo ...
- 概要设计实例_多核片上系统(SoC)架构的嵌入式DSP软件设计
多核片上系统(SoC)架构的嵌入式DSP软件设计 Multicore a System-on-a-Chip (SoC) Architecture SoCs的软件开发涉及到基于最强大的计算模型在各种处理 ...
- 由学习《软件设计重构》所想到的代码review(二)
前言 对于一个程序员来讲如何来最直接的来衡量他的技术能力和产出呢?我想最直观的作法是看他的代码编写能力,就拿我经常接触的一些程序员来看,他们买了很多技术重构类书籍,但是看完后代码编写能力并没有显著提高 ...
- 面向过程的软件设计方法
面向过程的软件设计方法 前面主要是对系统的分析,从而明确我们系统的逻辑模型.也就是说,通过前面几章我们清楚了"系统需要做什么?".而软件设计阶段主要任务则是要实现系统逻辑模型向物流 ...
- 自己拿项目,软件设计开发,释放你的力量
自己拿项目,软件设计开发,释放你的力量,链接地址 http://un.zhubajie.com/r/?u=4674706&l=http://u.zhubajie.com/user/buyer ...
最新文章
- layer的一种用法,自己画出弹出框样式
- [Android]反编译apk + eclipse中调试smali
- 在线聊天javascript代码
- Ollydbg使用教程学习总结(四)
- “辩者21事”之解读——分析性理性要与辩证理性相结合
- 基于Java+jsp+servlet的养老院管理系统设计和实现
- 菜鸟喜欢的C# 入门认识和添加,修改,删除 文件夹 文件 大全(转)
- 还不会用typedef?C语言typedef的详细用法总结,一篇解决你的困惑。(学习笔记2--typedef设置别名)
- python猫狗大战pytorch_深度学习实战---猫狗大战(pytorch实现)
- 安卓运行时监听配置更改:sim卡、本地语言、键盘显示或隐藏、字体大小、UI模式、屏幕方向、屏幕布局(另一个屏幕)、可用屏幕大小(横纵向)、无屏幕大小(外接屏幕)。
- 数据结构——一些小点
- 三菱PLC自带FIFO操作指令编程应用
- 电阻电感电容基本单位、读数、封装类型、种类
- ireport mysql_iReport连接Mysql创建图表报表
- mysql建立spj_数据库概论——SQL练习一(SPJ零件问题)
- 什么是Cloud Computing?
- 数据可视化中的格式塔心理学
- 解决iphone的短信中心号码设置错误的方案
- 微巴士阳光出行---竞品分析
- 油气计量比较好的软件_您准备好使用计量互联网了吗?
热门文章
- 本科生学计算机科学行吗,【学习方法】一位大三本科生的计算机科学与技术学习反思录...
- Kong 网关 | Route
- wechat talk
- 为什么实际下载速度比宽带带宽小很多
- 中关村知识产权领军和重点示范企业申报,200万资金补助
- kubernetes-nvidia-plugin设计解读
- 详解Java中的Object.getClass()方法
- onload、onunload、onbeforeunload的区别
- AV-TEST杀毒软件能力测试(2018年1月-12月)杀毒软件排名
- ieframe.dll修复方法