Announcement

Collapse
No announcement yet.

Mapping function - voltage divider

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Mapping function - voltage divider

    I have a voltage divider where 5V = 3,2V (adjustable to 0)
    The following code works:

    Code:
    // Analog read
    var Vsteps; //Store readings from PA0
    var Voltage; //Store converted readings PA0
    
    // Map function
    func map(var n,var x1, var y1, var x2, var y2)
        n := (n - x1) * (y2 - x2) / (y1 - x1) + x2;
        return n;
    endfunc
    
    func read()
        Vsteps := pin_Read(PA0);
        Vsteps := Vsteps/10; // Divide the readings for smaller computation
        Voltage := map(Vsteps,0,265,0,32);
    
    // Write Objects
        WriteObject(tLeddigits, 0, Voltage); // Write the value to LedDigits0 object
    
    
    .... endfunc
    I don't know exactly how the mapping function works.
    I know that Voltage := map(Vsteps,fromLow,fromHigh,toLow,toHigh).
    Correct me if i'm wrong but is the value of fromHigh (255) the "resolution of the bits" ?
    If so it looks it's 8 bit instead of 12 bit. I tried with 4095 but that doesn't seam to work.

    i have 3 questions:
    1) how accurate is Vsteps vs Vsteps/10 ?
    2) how can i set fromHigh value and toHigh value to match a 0-10V scale and display the correct voltage on the screen.
    so 0V=0V and 3,3V should indicate 10V on screen.
    3) is it possible to display it as 3.30V (3.31V, 3.31V etc)?

    Thanks
    Last edited by Kingpin; 11th June 2018, 08:55 PM.

  • #2
    I found some code in the forum.
    Is the following code "better" then the previous one?

    Code:
    // Variables
    var Vsteps;
    var val[2];
    var result[2];
    var leddigitVal[2];
    var potVal[2];
    var ans[2];
    var Voltage;
    
    func read()
    Vsteps := pin_Read(PA0);         // read the value of PA0
    flt_ITOF(val, Vsteps);           // convert the value to a float
    flt_ITOF(potVal, 4095);
    flt_DIV(result, val, potVal);    // result := val/potVal
    flt_ITOF(leddigitVal, 100);
    flt_MUL(ans, result, leddigitVal);    // ans := result * leddigitVal
    Voltage := flt_FTOI(ans);        // convert float to an integer
    
    // Write Objects
    WriteObject(tLeddigits, 0, Voltage);
      
      .... endfunc
    Last edited by Kingpin; 12th June 2018, 07:07 PM.

    Comment


    • #3
      Hi,

      Yes, this code is better as it does all the maths as floating point before converting back to an integer that you can use as a value to a widget. You will get a more accurate result as an integer using the above method.

      Paul

      Comment


      • #4
        Additionally, you can skip the two flt_ITOF you have for constant values in there, along with their associated vars. Most FLT functions will take a string as argument. And since you're using float, no need to divide by 4095, then multiply by 100 - you can just do:
        Code:
        Vsteps:= pin_Read(PA0);
        flt_ITOF(val, Vsteps);
        flt_DIV(result, val, "40.95");
        frame:= flt_FTOI(result);
        It's close enough that you could really get away with dividing by 40 and using integers only.
        As for your other questions, dividing by 40 (or 40.95) would give you one decimal precision when mapped over 10v. You could write a function that uses modulo to display the decimal point. You could also divide your analog reading by 4.095 and display your result as mV instead of V, but if you really need/want the decimal, you'll have to "split" your result somehow and display it in 2 instances.

        Comment


        • #5
          Thanks, i'll try it tonight.
          Other question, does it displays 3.3V with the above code example when i apply 3.3V on the input or can i 'adjust' the 'screen output' to set whatever i want (for example 10V)?

          Comment


          • #6
            Originally posted by alevesque View Post
            As for your other questions, dividing by 40 (or 40.95) would give you one decimal precision when mapped over 10v. You could write a function that uses modulo to display the decimal point. You could also divide your analog reading by 4.095 and display your result as mV instead of V, but if you really need/want the decimal, you'll have to "split" your result somehow and display it in 2 instances.
            In Visi i can set the leddisplay for example by 2 decimals and 4 digits, that should work i think.

            Comment


            • #7
              Solved my problem, thanks for the input.

              The "problem" was this value: "flt_ITOF(leddigitVal, 100);" it should be "flt_ITOF(leddigitVal, 500);" for 5V output and 1000 for 10V (added an extra "0") on screen, which i will adjust/tweak to match the correct voltage input with my DMM.
              Voltages will be calculated now as 455 (for example) to output 4.55 on screen according below leddigits properties:




























              Last edited by Kingpin; 13th June 2018, 05:36 PM.

              Comment


              • #8
                Hi,

                That looks great, Glad you managed to solve it.

                Best regards

                Paul

                Comment

                Working...
                X