Gradually increase/decrease an arduino sensor reading coming into Unity

Hi I am bringing an Arduino sensor reading into Unity.
I can pass the data from Arduino into Unity without any problem.

The sensor readings are coming from a flex sensor linked to a bicep muscle.
I want to use these sensor readings to generate a HUD Powerbar within a FPS game inside the Unity game engine.(the more the player flexes their bicep the more the energy bar will increase//if the player doesn’t flex their muscle the energy bar will decrease).

I’ve already managed to take the sensor reading and apply it to the rotation of a 3d bottle - it works but it animates very ‘jumpy’ as the readings don’t increase/decrease gradually. What I would like to do is increase & decrease the sensor data readings gradually. ie. if the flex sensor reading jumps from 0 to 80 I would like the energy bar to increase in height gradually in increments of 1 from 0-80 rather than suddenly becoming 80.

I have remapped the incoming sensor readings to be between 0-100 so that they can be used as a % of the height of an energy bar graphic. I’ve attached screen shots of the arduino sketch as well as the Unity code I used to rotate a 3d object based on the arduino flex data.

Any advice on how to go about coding this gradual change either in Unity or Arduino would be really appreciated.

Thanks



1908734–123139–flex.cs (354 Bytes)

Hey, really interesting project, I have an arduino uno too but never thought to combine it with unity.
Anyway this code piece can solve your problem.

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour
{
    private float calcInput = 0f;
    private float epsilon = 0.01f;
    private float factor = 2f;
    private float currentInput = 0f;

    void Update ()
    {
        currentInput = GetInputFromArduino();

        // use this block for linear increase or decrease
        if (calcInput < currentInput - epsilon)
        {
            calcInput += Time.deltaTime * factor;
        }
        else if (calcInput > currentInput + epsilon)
        {
            calcInput -= Time.deltaTime * factor;
        }

        // use this block for non-linear increase or decrease
        calcInput += (currentInput - calcInput) / factor * Time.deltaTime;
    }
}

Hi Zehreken - thanks for getting back.
I’ve used your code inside my existing code( see attached) but the object doesn’t rotate (it rotates very fast if I use the currentInput value inside the rotation parameter but if I use the calcInput value it only rotates a very slight fraction - maybe .5 degrees). I think that the problem is cause by the arduino sensor reading from the flex sensor very rapidly and returning to zero immediately after each flex - the high values only stay on the arduino output screen for mili-seconds). I’ve tried increasing the delay in arduino but this doesn’t make any difference in Unity.

Do you know how I could put in a line of C# code that would take a high reading from the Arduino serial and then hold off taking any further readings until a few seconds had past (for example if the first high flex value that was read was 50 and then the serial readings were temporarily stopped the calcInput value would cause the bottle to gradually rotate to 50 degrees…once the calcInput value or bottle object rotation dropped back to 0 degrees the code would begin to wait for the next high flex reading). Maybe there is an easier solution ?
Thanks again for your help.

1909878–123210–flex_gradual.cs (876 Bytes)

Hey, first of all you should use calcInput value to rotate your object. You can increase ‘factor’ for faster increase or decrease. I have modified the code and added an else at the end.

using UnityEngine;
using System.Collections;
using System.IO.Ports;

public class flex_gradual : MonoBehaviour
    {
        private float calcInput = 0f;
        private float epsilon = 0.01f;
        private float factor = 2f;
        private float currentInput = 0f;
        private float timer = 0f;
        private float timeToUpdate = 1f

    void Start () {

    }
    SerialPort serial = new SerialPort("COM8",9600);
    void Update ()

    {
        if (!serial.IsOpen)
            serial.Open ();
            //int currentInput = int.Parse (serial.ReadLine ());
  
        // use this block for linear increase or decrease
        if (calcInput < currentInput - epsilon)
        {
            calcInput += Time.deltaTime * factor;
        }
        else if (calcInput > currentInput + epsilon)
        {
            calcInput -= Time.deltaTime * factor;
        }
        else // calcInput is really close to currentInput so we are ready to update currentInput
        {
            // get input from arduino
            currentInput = float.Parse(serial.ReadLine ());
        }
        transform.localEulerAngles = new Vector3(0,calcInput,0);
    }
}

or you can set a timer in the Update for arduino input

        timer += Time.deltaTime;
        if (timer >= timeToUpdate)
        {
            timer = 0f; // reset timer
            //get input from arduino
        }

I hope this helps.

Excellent - thanks