im trying to link my arduino data into my speedometer widget in kivy

Question:

Im trying to link my arduino speed data to my speedometer on kivy. For example, when my speed in the arduino serial monitor is 20.5, i want the needle of my speedometer to point at that value(angle). Right now, i just set the needle to go from left(-90 deg) to right(90 deg) continuously.

Arduino serial monitor
Arduino serial monitor

Speedometer needle moving from -90deg to 90 deg
Speedometer needle moving from -90deg to 90 deg

.py file

import threading    
import serial
from kivy.animation import Animation
from kivy.clock import Clock, mainthread
from kivy.lang import Builder
from kivy.properties import StringProperty
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.app import App

class SpeedWindow(Screen):
    speed_text = StringProperty("")

    def __init__(self, **kwargs):
        super(SpeedWindow, self).__init__(**kwargs)
        threading.Thread(target=self.tm).start()

    def tm(self):
        while (1):
            with serial.Serial('COM4', 9600) as ser:
                value = ser.readline()
                ser.close()
                self.update_fix(value.decode('utf-8'))

    @mainthread
    def update_fix(self, value):
        self.speed_text = value

class WindowManager(ScreenManager):
    pass

KV = """

WindowManager:
    SpeedWindow:

<SpeedWindow>:
    angle: 90    
    name: 'speedometer'   

    Image:
        source: 'cadran.png'
        size_hint: None, None
        size: 400, 400
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}

    Image:
        source: 'needle.png'
        size_hint: None, None
        size: 170, 170
        pos_hint: {'center_x': 0.5, 'center_y': 0.5}   
        # apply rotation matrix to this Image                                                                                                                                            
        canvas.before:                                                                                                                                             
            PushMatrix                                                                                                                                             
            Rotate:                                                                                                                                                
                angle: root.angle                                                                                                                                  
                axis: (0, 0, 1)                                                                                                                                    
                origin: (self.center_x, self.center_y , 0)                                                                                                                              
        canvas.after:                                                                                                                                              
            PopMatrix                           
"""

class MyMainApp(App):
    def build(self):
        Clock.schedule_once(self.animate_needle, 1.0)  # start the animation in 2 seconds
        return  Builder.load_string(KV)

    def animate_needle(self, dt):
        # animate the needle from +90 to -90 and then back to +90
        self.anim = Animation(angle=-90.0) + Animation(angle=90)
        self.anim.repeat = True    # repeat forever
        speedometer = self.root.get_screen('speedometer')
        self.anim.start(speedometer)

if __name__ == "__main__":
    MyMainApp().run()
Asked By: helpmepls

||

Answers:

I think you can just remove the animate_needle() method and change your update_fix() method to calculate an appropriate angle:

@mainthread
def update_fix(self, value):
    self.speed_text = value
    self.angle = 90.0 - 180.0 * float(value)/100.0

The formula simply gives 90 when the value is 0 and -90 when the value is 100, and interpolates in between.

Answered By: John Anderson

I am facing a similar problem. I want to have a smooth moving needle between the different serial or socket inputs. If I only use the def update_fix the needle is jumping hardly from one input to another input. That is not the sense of animations in kivy.

The code must be such, that after the needle reached the point, the next value need to be smoothly driven within one second or a half second.

If I use the animation + animation method, the kivy plays only with the before given input and does not update the value.

Answered By: Marcus
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.