在 Kivy 标签中显示来自 python 程序的心跳传感器读数
Display heartbeat sensor's readings from python program in a Kivy label
我试图在我的 Kivy 应用程序中显示从我的心跳传感器获得的值。我试过使用应用于其他传感器的数据提取方法,但它不适用于此传感器,因为它不包含任何功能。
我尝试了多种不同的方法,但它们都没有返回所需的输出。有人可以看看传感器代码并建议一些在我的 kivy 应用程序中显示输出的方法吗?
Heartbeatsensot.py
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15
if __name__ == '__main__':
adc = Adafruit_ADS1x15.ADS1015()
# initialization
GAIN = 2/3
curState = 0
thresh = 525 # mid point in the waveform
P = 512
T = 512
stateChanged = 0
sampleCounter = 0
lastBeatTime = 0
firstBeat = True
secondBeat = False
Pulse = False
IBI = 600
rate = [0]*10
amp = 100
lastTime = int(time.time()*1000)
# Main loop. use Ctrl-c to stop the code
while True:
# read from the ADC
Signal = adc.read_adc(0, gain=GAIN) #TODO: Select the correct ADC channel. I have selected A0 here
curTime = int(time.time()*1000)
sampleCounter += curTime - lastTime; # # keep track of the time in mS with this variable
lastTime = curTime
N = sampleCounter - lastBeatTime; # # monitor the time since the last beat to avoid noise
#print N, Signal, curTime, sampleCounter, lastBeatTime
## find the peak and trough of the pulse wave
if Signal < thresh and N > (IBI/5.0)*3.0 : # # avoid dichrotic noise by waiting 3/5 of last IBI
if Signal < T : # T is the trough
T = Signal; # keep track of lowest point in pulse wave
if Signal > thresh and Signal > P: # thresh condition helps avoid noise
P = Signal; # P is the peak
# keep track of highest point in pulse wave
# NOW IT'S TIME TO LOOK FOR THE HEART BEAT
# signal surges up in value every time there is a pulse
if N > 250 : # avoid high frequency noise
if (Signal > thresh) and (Pulse == False) and (N > (IBI/5.0)*3.0) :
Pulse = True; # set the Pulse flag when we think there is a pulse
IBI = sampleCounter - lastBeatTime; # measure time between beats in mS
lastBeatTime = sampleCounter; # keep track of time for next pulse
if secondBeat : # if this is the second beat, if secondBeat == TRUE
secondBeat = False; # clear secondBeat flag
for i in range(0,10): # seed the running total to get a realisitic BPM at startup
rate[i] = IBI;
if firstBeat : # if it's the first time we found a beat, if firstBeat == TRUE
firstBeat = False; # clear firstBeat flag
secondBeat = True; # set the second beat flag
continue # IBI value is unreliable so discard it
# keep a running total of the last 10 IBI values
runningTotal = 0; # clear the runningTotal variable
for i in range(0,9): # shift data in the rate array
rate[i] = rate[i+1]; # and drop the oldest IBI value
runningTotal += rate[i]; # add up the 9 oldest IBI values
rate[9] = IBI; # add the latest IBI to the rate array
runningTotal += rate[9]; # add the latest IBI to runningTotal
runningTotal /= 10; # average the last 10 IBI values
BPM = 60000/runningTotal; # how many beats can fit into a minute? that's BPM!
print ('BPM: {}'.format(BPM))
if Signal < thresh and Pulse == True : # when the values are going down, the beat is over
Pulse = False; # reset the Pulse flag so we can do it again
amp = P - T; # get amplitude of the pulse wave
thresh = amp/2 + T; # set thresh at 50% of the amplitude
P = thresh; # reset these for next time
T = thresh;
if N > 2500 : # if 2.5 seconds go by without a beat
thresh = 512; # set thresh default
P = 512; # set P default
T = 512; # set T default
lastBeatTime = sampleCounter; # bring the lastBeatTime up to date
firstBeat = True; # set these to avoid noise
secondBeat = False; # when we get the heartbeat back
print ("no beats found")
time.sleep(0.005)
** 我正在尝试将读数添加到的 kivy 应用程序**
another.py 文件
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.lang import Builder
class MainScreen(Screen):
pass
class ScreenThermo(Screen):
def __init__(self,**kwargs):
super(ScreenThermo, self).__init__(**kwargs)
Clock.schedule_interval(self.displayHR, 10)
def displayHR(self,dt):
heartbeat = 'BPM: {}'.format(BPM)
pulse = heartbeat
self.manager.screen_thermo.ids.TempLabel.text = str(pulse)
def on_enter(self, *args):
self.__init__()
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("heartk.kv")
class MenuApp(App):
def build(self):
return presentation
if __name__ == '__main__':
MenuApp().run()
.kv 文件
ScreenManagement:
id: screen_manager
screen_thermo: screen_thermo
MainScreen:
ScreenThermo:
id: screen_thermo
name: 'thermo'
manager: screen_manager
<MainScreen>:
name: "main"
Label:
text: "Welcome"
font_size: 60
halign: 'center'
valign: 'middle'
pos_hint: {'x': .01, 'y': .05}
on_touch_down: app.root.current = "thermo"
<ScreenThermo>:
Label:
text: " Pulse rate"
font_size: 50
pos: (35, 100)
Label:
id: TempLabel
font_size: 60
halign: 'center'
valign: 'middle'
我认为你可以通过一些小的修改来完成你想要的。首先添加一个 StringProperty
到你的 ScreenThermo
class,然后在 on_enter()
方法中启动一个线程到 运行 你的 Heartbeatsensot
代码为:
from Heartbeatsensot import hearbeatsensot
class ScreenThermo(Screen):
BPM_string = StringProperty('BPM: Not Detected')
def on_enter(self, *args):
Thread(target=hearbeatsensot, args=(self,)).start()
然后在您的 kv
文件中,添加对新 StringProperty
:
的引用
<ScreenThermo>:
Label:
text: " Pulse rate"
font_size: 50
pos: (35, 100)
Label:
id: TempLabel
text: root.BPM_string # references new StringProperty
font_size: 60
halign: 'center'
valign: 'middle'
现在你只需要把你想在TempLabel
中显示的内容放到BPM_string
属性中。为此,请更改 Heartbeatsensot.py
以定义可在 Thread
中使用的方法。只需将该文件中的 if __name__ == '__main__':
替换为 def hearbeatsensot(screenThermo):
,如下所示:
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15
def hearbeatsensot(screenThermo):
adc = Adafruit_ADS1x15.ADS1015()
# initialization
GAIN = 2/3
.
.
.
screenThermo.BPM_string = 'BPM: 65'
.
.
.
然后,在该方法中,只需使用类似 screenThermo.BPM_string = 'BPM: 65'
的东西(或您想要将其设置为的任何内容)。 kv
文件中对 BPM_string
的引用将自动设置绑定以在 BPM_string
被修改时更新 TempLabel
。
我试图在我的 Kivy 应用程序中显示从我的心跳传感器获得的值。我试过使用应用于其他传感器的数据提取方法,但它不适用于此传感器,因为它不包含任何功能。
我尝试了多种不同的方法,但它们都没有返回所需的输出。有人可以看看传感器代码并建议一些在我的 kivy 应用程序中显示输出的方法吗?
Heartbeatsensot.py
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15
if __name__ == '__main__':
adc = Adafruit_ADS1x15.ADS1015()
# initialization
GAIN = 2/3
curState = 0
thresh = 525 # mid point in the waveform
P = 512
T = 512
stateChanged = 0
sampleCounter = 0
lastBeatTime = 0
firstBeat = True
secondBeat = False
Pulse = False
IBI = 600
rate = [0]*10
amp = 100
lastTime = int(time.time()*1000)
# Main loop. use Ctrl-c to stop the code
while True:
# read from the ADC
Signal = adc.read_adc(0, gain=GAIN) #TODO: Select the correct ADC channel. I have selected A0 here
curTime = int(time.time()*1000)
sampleCounter += curTime - lastTime; # # keep track of the time in mS with this variable
lastTime = curTime
N = sampleCounter - lastBeatTime; # # monitor the time since the last beat to avoid noise
#print N, Signal, curTime, sampleCounter, lastBeatTime
## find the peak and trough of the pulse wave
if Signal < thresh and N > (IBI/5.0)*3.0 : # # avoid dichrotic noise by waiting 3/5 of last IBI
if Signal < T : # T is the trough
T = Signal; # keep track of lowest point in pulse wave
if Signal > thresh and Signal > P: # thresh condition helps avoid noise
P = Signal; # P is the peak
# keep track of highest point in pulse wave
# NOW IT'S TIME TO LOOK FOR THE HEART BEAT
# signal surges up in value every time there is a pulse
if N > 250 : # avoid high frequency noise
if (Signal > thresh) and (Pulse == False) and (N > (IBI/5.0)*3.0) :
Pulse = True; # set the Pulse flag when we think there is a pulse
IBI = sampleCounter - lastBeatTime; # measure time between beats in mS
lastBeatTime = sampleCounter; # keep track of time for next pulse
if secondBeat : # if this is the second beat, if secondBeat == TRUE
secondBeat = False; # clear secondBeat flag
for i in range(0,10): # seed the running total to get a realisitic BPM at startup
rate[i] = IBI;
if firstBeat : # if it's the first time we found a beat, if firstBeat == TRUE
firstBeat = False; # clear firstBeat flag
secondBeat = True; # set the second beat flag
continue # IBI value is unreliable so discard it
# keep a running total of the last 10 IBI values
runningTotal = 0; # clear the runningTotal variable
for i in range(0,9): # shift data in the rate array
rate[i] = rate[i+1]; # and drop the oldest IBI value
runningTotal += rate[i]; # add up the 9 oldest IBI values
rate[9] = IBI; # add the latest IBI to the rate array
runningTotal += rate[9]; # add the latest IBI to runningTotal
runningTotal /= 10; # average the last 10 IBI values
BPM = 60000/runningTotal; # how many beats can fit into a minute? that's BPM!
print ('BPM: {}'.format(BPM))
if Signal < thresh and Pulse == True : # when the values are going down, the beat is over
Pulse = False; # reset the Pulse flag so we can do it again
amp = P - T; # get amplitude of the pulse wave
thresh = amp/2 + T; # set thresh at 50% of the amplitude
P = thresh; # reset these for next time
T = thresh;
if N > 2500 : # if 2.5 seconds go by without a beat
thresh = 512; # set thresh default
P = 512; # set P default
T = 512; # set T default
lastBeatTime = sampleCounter; # bring the lastBeatTime up to date
firstBeat = True; # set these to avoid noise
secondBeat = False; # when we get the heartbeat back
print ("no beats found")
time.sleep(0.005)
** 我正在尝试将读数添加到的 kivy 应用程序**
another.py 文件
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager,Screen
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.lang import Builder
class MainScreen(Screen):
pass
class ScreenThermo(Screen):
def __init__(self,**kwargs):
super(ScreenThermo, self).__init__(**kwargs)
Clock.schedule_interval(self.displayHR, 10)
def displayHR(self,dt):
heartbeat = 'BPM: {}'.format(BPM)
pulse = heartbeat
self.manager.screen_thermo.ids.TempLabel.text = str(pulse)
def on_enter(self, *args):
self.__init__()
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("heartk.kv")
class MenuApp(App):
def build(self):
return presentation
if __name__ == '__main__':
MenuApp().run()
.kv 文件
ScreenManagement:
id: screen_manager
screen_thermo: screen_thermo
MainScreen:
ScreenThermo:
id: screen_thermo
name: 'thermo'
manager: screen_manager
<MainScreen>:
name: "main"
Label:
text: "Welcome"
font_size: 60
halign: 'center'
valign: 'middle'
pos_hint: {'x': .01, 'y': .05}
on_touch_down: app.root.current = "thermo"
<ScreenThermo>:
Label:
text: " Pulse rate"
font_size: 50
pos: (35, 100)
Label:
id: TempLabel
font_size: 60
halign: 'center'
valign: 'middle'
我认为你可以通过一些小的修改来完成你想要的。首先添加一个 StringProperty
到你的 ScreenThermo
class,然后在 on_enter()
方法中启动一个线程到 运行 你的 Heartbeatsensot
代码为:
from Heartbeatsensot import hearbeatsensot
class ScreenThermo(Screen):
BPM_string = StringProperty('BPM: Not Detected')
def on_enter(self, *args):
Thread(target=hearbeatsensot, args=(self,)).start()
然后在您的 kv
文件中,添加对新 StringProperty
:
<ScreenThermo>:
Label:
text: " Pulse rate"
font_size: 50
pos: (35, 100)
Label:
id: TempLabel
text: root.BPM_string # references new StringProperty
font_size: 60
halign: 'center'
valign: 'middle'
现在你只需要把你想在TempLabel
中显示的内容放到BPM_string
属性中。为此,请更改 Heartbeatsensot.py
以定义可在 Thread
中使用的方法。只需将该文件中的 if __name__ == '__main__':
替换为 def hearbeatsensot(screenThermo):
,如下所示:
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15
def hearbeatsensot(screenThermo):
adc = Adafruit_ADS1x15.ADS1015()
# initialization
GAIN = 2/3
.
.
.
screenThermo.BPM_string = 'BPM: 65'
.
.
.
然后,在该方法中,只需使用类似 screenThermo.BPM_string = 'BPM: 65'
的东西(或您想要将其设置为的任何内容)。 kv
文件中对 BPM_string
的引用将自动设置绑定以在 BPM_string
被修改时更新 TempLabel
。