这段时间有一个项目要求采集放大器输出波形的失真信号,采集信号并利用手机显示。
本来的要求应该是单片机采集数据,之后进行FFT求出THD( 总谐波失真 )之后通过蓝牙模块或者Wifi模块上传。
但是其实这题也可以另辟蹊径,我们可以利用单片机直接上传原始数据,之后利用手机对数据进行处理,于是我就利用.NET MAUi制作一款手机APP
目前使用ESP32采集模拟信号上传,手机端接收数据之后显示其波形图,之后可以利用FFT函数显示其频谱图。
之后根据频谱图计算其THD的值。
这里就粘贴下源码,主要是发现这个技术真没人看,哎呀怎么会没人看呢,我觉得这个技术的实用性真的还可以欸,尤其是给我们嵌入式的人群方便的开发手机端的上位机。上次连发七篇加起来就几百的阅读量,真的伤心了o(TヘTo)我甚至标题都没挂.NET
MAUI,感觉挂了就没人看 需要源码或者交流的朋友可以私信/留言/加群 由于.NET
MAUI的跨平台特性,其具有多平台代码通用的特征,所以相同的代码就可以在不同的平台使用。
THD计算
public double CalculateTHD(Complex[] waveform)//计算THD的值 { Complex[] UseData = new Complex[waveform.Length]; Array.Copy(waveform, UseData, waveform.Length); // 执行傅里叶变换 Fourier.Forward(UseData);
// 计算基波幅值 double[] fundamentalAmplitude = FindMaxAmplitude(UseData);
// 计算所有谐波的总幅值平方和 double harmonicAmplitudeSquaredSum = 0; for (double i = fundamentalAmplitude[1]; i < UseData.Length / 2; i = i + fundamentalAmplitude[1]) { double harmonicAmplitude = findMaxInRange(UseData,(int)i, (int)(fundamentalAmplitude[1]*0.3)); harmonicAmplitudeSquaredSum += harmonicAmplitude * harmonicAmplitude; }
// 计算THD double thd = Math.Sqrt(harmonicAmplitudeSquaredSum-fundamentalAmplitude[0]*fundamentalAmplitude[0]) / fundamentalAmplitude[0];
return thd; }
** 波形显示 **
#if __ANDROID__ AndroidWifiService AndroidWifi; string Android_Wifi_IPAddress;
private async void OnMessageReceived(object sender, byte[] message) { try { await Task.Run(() => { // 将 byte[] 转换为字符串,并按空格分割为单个数据 string[] stringData = System.Text.Encoding.Default.GetString(message).Split(' ');
// 将每个数据转换为 Complex 类型并存储到 Data 中 Data = stringData.Select(s => new Complex(double.Parse(s), 0)).ToArray();
// 在这里可以对 Data 进行其他操作,例如绘制波形图等 MainThread.BeginInvokeOnMainThread(() => { if(ReciveFlag) { OrgData = new Complex[Data.Length]; Array.Copy(Data, OrgData, Data.Length); var sineSeries = new LineSeries { Title = "Sine Wave", MarkerSize = 2, MarkerStroke = OxyColors.Blue }; for (int i = 0; i < Data.Length; i++) { sineSeries.Points.Add(new DataPoint(i, Data[i].Real)); // 显示实部作为正弦波的值 } PlotModel.Series.Clear(); PlotModel.Series.Add(sineSeries); PlotModel.InvalidatePlot(true); } }); }); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }#endif