日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

proteus仿真micropython_基于micropython的滑动平均滤波器

發(fā)布時(shí)間:2025/3/15 python 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 proteus仿真micropython_基于micropython的滑动平均滤波器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

滑動(dòng)平均濾波也叫遞推平均濾波。

把連續(xù)取得的N個(gè)采樣值看成一個(gè)隊(duì)列,隊(duì)列的長(zhǎng)度固定為N,每次采樣到一個(gè)新數(shù)據(jù)放入隊(duì)尾,并扔掉原來(lái)隊(duì)首的一次數(shù)據(jù)(先進(jìn)先出原則),把隊(duì)列中的N個(gè)數(shù)據(jù)進(jìn)行算術(shù)平均運(yùn)算,獲得新的濾波結(jié)果。

從這個(gè)原理中可以感覺(jué)出這種濾波方法的平滑度會(huì)很高,所以會(huì)適用于高頻震蕩系統(tǒng),對(duì)周期性的干擾有很好的抑制作用。但是也是有缺點(diǎn)的,靈敏度低,

對(duì)偶然出現(xiàn)的脈沖性干擾的抑制作用較差不易消除由于脈沖干擾所引起的采樣值偏差不適用于脈沖干擾比較嚴(yán)重的場(chǎng)合,由于他要保存過(guò)去N個(gè)樣本的數(shù)據(jù)所以說(shuō)會(huì)比較浪費(fèi)RAM。

(N值的選取:流量,N=12;壓力,N=4;液面,N=4-12;溫度,N=1-4。)

以上引用來(lái)自互聯(lián)網(wǎng),由于出處太多已分不清是誰(shuí)的原創(chuàng),如果原作者見(jiàn)了需版權(quán)聲明請(qǐng)通知

本次實(shí)驗(yàn)是基于pyboard的,原碼作者是英國(guó)一個(gè)大牛用匯編寫(xiě)的https://github.com/peterhinch/micropython-filters.git

這個(gè)帖子主要對(duì)其進(jìn)行了測(cè)試以及用python寫(xiě)了個(gè)可以移植到其他micropython平臺(tái)的代碼。后續(xù)會(huì)貼出FIR濾波器,傅立葉變換等帖子,之前一直想發(fā)帖,無(wú)奈總是提示我有敏感詞匯發(fā)不了

下圖為官網(wǎng)pyboard的圖以及本次測(cè)試用的板子圖

板子是我自己畫(huà)板掏錢打板手工焊的,完全兼容其他pyboard的開(kāi)發(fā)板,所以盡管放心測(cè)試

截圖201712261006377680.png (500.06 KB, 下載次數(shù): 22)

2017-12-26 10:06 上傳

截圖201712261334343967.png (312.66 KB, 下載次數(shù): 17)

2017-12-26 13:34 上傳

英國(guó)牛人代碼如下,

[AppleScript] 純文本查看 復(fù)制代碼# Implementation of moving average filter in Arm Thumb assembler

# Author: Peter Hinch

# 15th Feb 2015

# Updated to reflect support for sdiv instruction

# Timing: 27uS on MicroPython board (independent of data)

# Function arguments:

# r0 is an integer scratchpad array. Must be of length 3 greater than

# the number of values to be averaged.

# On entry array[0] must hold the array length, other elements must be zero

# r1 holds new data value

# Return value: the current moving average

# array[0] is array length, array[1] is the current sum, array[2] the insertion point

# r2 holds the length of the coefficient array

# Pointers (byte addresses)

# r3 start of ring buffer

# r4 insertion point (post increment)

# r5 last location of ring buffer

# Other registers

# r7 temporary store for result

@micropython.asm_thumb

def avg(r0, r1):

mov(r3, r0)

add(r3, 12) # r3 points to ring buffer start

ldr(r2, [r0, 0]) # Element count

sub(r2, 4) # Offset in words to buffer end

add(r2, r2, r2)

add(r2, r2, r2) # convert to bytes

add(r5, r2, r3) # r5 points to ring buffer end (last valid address)

ldr(r4, [r0, 8]) # Current insertion point address

cmp(r4, 0) # If it's zero we need to initialise

bne(INIT)

mov(r4, r3) # Initialise: point to buffer start

label(INIT)

ldr(r7, [r0, 4]) # get current sum

ldr(r6, [r4, 0])

sub(r7, r7, r6) # deduct oldest value

add(r7, r7, r1) # add newest value

str(r7, [r0, 4]) # put sum back

str(r1, [r4, 0]) # put in buffer and post increment

add(r4, 4)

cmp(r4, r5) # Check for buffer end

ble(NOLOOP)

mov(r4, r3) # Incremented past end: point to start

label(NOLOOP)

str(r4, [r0, 8]) # Save the insertion point for next call

ldr(r1, [r0, 0]) # Element count

sub(r1, 3) # No. of data points

mov(r0, r7) # The sum

sdiv(r0, r0, r1) # r0 = r0//r1

為了提高效率代碼是由匯編寫(xiě)的直接操作寄存器。

這個(gè)函數(shù)入口主要有兩個(gè)參數(shù),第一個(gè)參數(shù)為隊(duì)列的緩存,第二參數(shù)為最新的數(shù)據(jù),關(guān)于第一個(gè)參數(shù)源碼作者有說(shuō)明,這個(gè)參數(shù)的長(zhǎng)度必須比隊(duì)列長(zhǎng)度的長(zhǎng)3,這個(gè)參數(shù)第一個(gè)元素存儲(chǔ)著這個(gè)參數(shù)的總長(zhǎng)度,第二元素為N個(gè)樣本數(shù)據(jù)的和,第三個(gè)元素是數(shù)據(jù)的插入點(diǎn)(對(duì)于第二個(gè)第三個(gè)元素不需要去操心,用來(lái)給匯編提供便利)后面的元素為采樣值的緩存。

作者提供了一個(gè)測(cè)試程序,主要測(cè)試了一下這個(gè)用匯編寫(xiě)的代碼的執(zhí)行用時(shí),跑一下試試

[Python] 純文本查看 復(fù)制代碼# Demo program for moving average filter

# Author: Peter Hinch

# 12th Feb 2015

import array, pyb

from avg import avg

data = array.array('i', [0]*13) # Average over ten samples

data[0] = len(data)

def test():

for x in range(12):

print(avg(data, 1000))

for x in range(12):

print(avg(data, 0))

def timing():

t = pyb.micros()

avg(data, 10)

t1 = pyb.elapsed_micros(t) # Time for one call with timing overheads

t = pyb.micros()

avg(data, 10)

avg(data, 10)

t2 = pyb.elapsed_micros(t) # Time for two calls with timing overheads

print(t2-t1,"uS") # Time to execute the avg() call

test()

print("Timing test")

timing()

測(cè)試結(jié)果

截圖201712261336544902.png (83.56 KB, 下載次數(shù): 13)

2017-12-26 13:36 上傳

隊(duì)列長(zhǎng)度為10,執(zhí)行用時(shí)8微秒,效率挺高的了

那么接下來(lái)看看直接接設(shè)備進(jìn)行實(shí)時(shí)測(cè)試看效果怎么樣。

思路:外接一個(gè)三軸加速度計(jì),取一個(gè)軸的數(shù)據(jù)進(jìn)行濾波,同時(shí)打印原始數(shù)據(jù)和濾波后的數(shù)據(jù)做對(duì)比(當(dāng)然板載一個(gè)MMA7660三軸加速度計(jì),但是其輸出的數(shù)值范圍太小了,并不是說(shuō)小數(shù)值不能用只是為了提高觀察效果我采用了外置的加速度計(jì))

代碼如下

[Python] 純文本查看 復(fù)制代碼import MPU6050

import array

from protocol import *

from avg import *

from pyb import I2C,UART,delay

#golbal data

accx_data = array.array('i', [0]*8)

#f_acc_data = avg_filiter(accx_data)

accx_data[0] = len(accx_data)

#hardwareobject

uart_port = UART(4,57600)

iic = I2C(1,I2C.MASTER)

acc_dev = MPU6050.MPU6050(iic)

while True:

raw_data = acc_dev.read_Accel_z()

filter_data = avg(accx_data,raw_data)

send_data = data_send(raw_data,filter_data,0,0,0,0,0,0,0)

uart_port.write(send_data)

delay(20)

用串口示波器把數(shù)據(jù)顯示出來(lái)效果如圖

截圖201712261349484095.png (145.63 KB, 下載次數(shù): 16)

2017-12-26 13:49 上傳

局部圖

截圖201712261350306731.png (176.56 KB, 下載次數(shù): 15)

2017-12-26 13:50 上傳

繼續(xù)放大

截圖201712261351009137.png (217.63 KB, 下載次數(shù): 14)

2017-12-26 13:51 上傳

紅色是原始數(shù)據(jù),藍(lán)色是濾波后的數(shù)據(jù),本次實(shí)驗(yàn)滑動(dòng)的N為5,從圖像來(lái)看確實(shí)對(duì)波形的毛刺有了很好的平滑效果,波形有輕微的延時(shí)

大致思路明白了,那么現(xiàn)在用python自己來(lái)寫(xiě)一個(gè)滑動(dòng)濾波的函數(shù),捋一下大致步驟就是,建立一個(gè)先入先出的隊(duì)列,然后每次新的數(shù)據(jù)入列先把最前面的元素出列然后對(duì)所有的數(shù)據(jù)求平均值,由于對(duì)樣本的和是一個(gè)反復(fù)的過(guò)程,所以為了提高效率,采納原作者的思路,找一個(gè)位置來(lái)存放所求的和,每次計(jì)算只需減去最前面的樣本在加上最新的樣本即可,這樣就省去N-2次的加法計(jì)算。(我之前用最簡(jiǎn)單最笨的方法寫(xiě)的試了,實(shí)在是耗時(shí)太長(zhǎng)了,最后借鑒了源作者的方法,換句話說(shuō)就是對(duì)原作者代碼的匯編到python的翻譯,這樣也可以在其他不支持匯編的平臺(tái)上無(wú)縫移植了)

代碼如下,但是用時(shí)太久了,樣本長(zhǎng)度為10的情況下測(cè)試的。

[Python] 純文本查看 復(fù)制代碼import array, pyb

class avg_filiter():

def __init__(self,cache_data):

self.cache = cache_data

self.len = len(cache_data)

self.cache[0] = self.len

self.sum = 0

for item in cache_data[3:]:

self.sum += item

self.cache[1] = self.sum

def avg(self,new_data):

self.cache[1] = self.cache[1] - self.cache[3]

self.cache[1] = self.cache[1] + new_data

self.cache[3:-1] = self.cache[4:]

self.cache[-1] = new_data

return self.cache[1]//(self.len - 3)

data = array.array('i', [0]*13) # Average over ten samples

fdata = avg_filiter(data)

def test():

for x in range(12):

print(fdata.avg(1000))

for x in range(12):

print(fdata.avg(0))

def timing():

t = pyb.micros()

fdata.avg(10)

t1 = pyb.elapsed_micros(t) # Time for one call with timing overheads

t = pyb.micros()

fdata.avg(10)

fdata.avg(10)

t2 = pyb.elapsed_micros(t) # Time for two calls with timing overheads

print(t2-t1,"uS") # Time to execute the avg() call

test()

print("Timing test")

timing()

但是程序耗時(shí)整整翻了十倍

截圖201712261340208536.png (76.89 KB, 下載次數(shù): 17)

2017-12-26 13:40 上傳

不過(guò)雖然時(shí)間相對(duì)匯編來(lái)說(shuō)有點(diǎn)長(zhǎng),但是對(duì)于一般的AD采集的場(chǎng)合這個(gè)時(shí)間完全夠用了,現(xiàn)在可以開(kāi)心的移植到esp8266上了

滑動(dòng)濾波相對(duì)簡(jiǎn)單一點(diǎn),大概就這里吧。后面附件貼上代碼,里面有mpu6050的庫(kù)

mpu6050 滑動(dòng)平均濾波.zip

(4.74 KB, 下載次數(shù): 70)

2017-12-26 10:53 上傳

點(diǎn)擊文件名下載附件

代碼

總結(jié)

以上是生活随笔為你收集整理的proteus仿真micropython_基于micropython的滑动平均滤波器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。