Обновление метки Kivy по данным датчика температуры ardunio - PullRequest
0 голосов
/ 21 марта 2020

Я знаю, что здесь есть несколько других веток обновления kivy / label, но после нескольких дней применения этих рекомендаций я все еще не приблизился к получению метки в kivy для обновления с данными о температуре от ardunio. Это для панели управления Campervan, которая должна управлять приводами для раскладывания дивана-кровати при нажатии кнопок и отображать данные датчика на экране.

У меня работает соединение через последовательный порт, так как кнопки управления привода работают , но я изо всех сил пытаюсь получить ярлык для обновления с данными датчика температуры. Серийный монитор ardunio IDE показывает, что ardunio выводит температуру в порядке, и если я копирую / вставляю функцию temp_sensor в новый скрипт, он печатает данные в порядке.

Я новичок в программировании, python и Киви, поэтому извиняюсь, если я тупой!

Вот код python:

import kivy
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivy.clock import Clock
from kivy.properties import ObjectProperty, NumericProperty, StringProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen

import serial
import webbrowser
import time

browser_launch = 'https://www.google.com'
ser= serial.Serial('/dev/cu.usbmodem14201', 9600, timeout=5) 


class MainWindow(Screen): #The home screen, that navigates to other control windows, and has the buttons controlling the actuators.

    desktop = ObjectProperty(None)
    settings = ObjectProperty(None)
    bed = ObjectProperty(None)
    sofa = ObjectProperty(None)

    def desktop_button(self):
        webbrowser.open_new(browser_launch)
        print("Desktop Pressed")

    def settings_button(self):
        print("Settings Pressed")

    def bed_button(self):
        ser.write(b'B')  #These buttons work, and interact with the ardunio as they should.
        print("Bed Pressed")

    def sofa_button(self):
        ser.write(b'S')
        print("Sofa Pressed")

    pass

class TempWindow(Screen): #Second screen that is navigated to from the main screen. This will display temperature inside the van, (and outside, plus control the heater eventually)

    temp_sensor_inside = NumericProperty(0)

    def temp_sensor(self):  #If I run this function in a seperate python script it works.
        time.sleep(2)
        while 1:
            temp_reading = ser.readline().decode('ascii')
            float_temp = float(temp_reading)
            return float_temp
    pass

class DataWindow(Screen):
    pass

class WindowManager(ScreenManager):
    pass



kv = Builder.load_file('my.kv')

class MyMainApp(App):
    def build(self):
        return kv


if __name__ == "__main__":
    MyMainApp().run()

    ser.close()

И соответствующая часть .kv файла:

<TempWindow>:
    name: 'temp'

    temp_sensor_inside: temp_sensor_inside

    FloatLayout:
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: 'background.png'

        Label:
            id: temp_sensor_inside
            text: str(root.temp_sensor())
            font_size: 50
            pos_hint: {'x': -0.15, 'y': 0.1}


1 Ответ

0 голосов
/ 22 марта 2020

Вот пример (на основе вашего кода), который должен вам помочь. В приведенном ниже примере я пропустил несколько вещей, которые не влияют на ответ. И я заменил ваш код для доступа к датчику температуры просто глобальной переменной с именем float_temp, поскольку у меня нет такого датчика:

import threading
import time
from functools import partial

from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.screenmanager import Screen, ScreenManager

float_temp = 55.0


class TempWindow(Screen): #Second screen that is navigated to from the main screen. This will display temperature inside the van, (and outside, plus control the heater eventually)

    temp_sensor_inside = ObjectProperty(None)

    def on_enter(self, *args):
        # start polling the temperature
        threading.Thread(target=self.poll_sensor).start()


    def poll_sensor(self):
        global float_temp
        while 1:
            # temp_reading = ser.readline().decode('ascii')
            # float_temp = float(temp_reading)
            float_temp += 1.5
            Clock.schedule_once(partial(self.set_temp, float_temp))
            time.sleep(2)

    def set_temp(self, temp, dt):
        self.temp_sensor_inside.text = str(temp)

kv_str = '''
<TempWindow>:
    temp_sensor_inside: temp_sensor_inside
    name: 'temp'
    Label:
        id: temp_sensor_inside
        text: '000'
'''

class TempWindowApp(App):
    def build(self):
        kv = Builder.load_string(kv_str)
        sm = ScreenManager()
        sm.add_widget(TempWindow())
        return sm


TempWindowApp().run()

Метод on_enter() выполняется, когда TempWindow отображается. Этот метод запускает новую нить для мониторинга датчика температуры, потому что вы не хотите увеличивать GUI с oop, который работает вечно. Метод poll_sensor() получает текущую температуру от вашего датчика (в моем случае она просто увеличивает float_temp) и вызывает set_temp(), используя Clock.schedule_once(). Clock.schedule_once() запускает set_temp() обратно в основном потоке (требуется для кода, который изменяет GUI), а set_temp() изменяет текст Label до ObjectProperty, который ссылается на id от kv.

...