Menu

Making a Map function like arduino

Help
viscomjim
2016-06-22
2016-07-03
  • viscomjim

    viscomjim - 2016-06-22

    Is it possible to create a Map function in GCB?

    From arduino...

    map(value, fromLow, fromHigh, toLow, toHigh)
    
    Description
    
    Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of fromHigh to toHigh, values in-between to values in-between, etc.
    
    Does not constrain values to within the range, because out-of-range values are sometimes intended and useful. The constrain() function may be used either before or after this function, if limits to the ranges are desired.
    
    Note that the "lower bounds" of either range may be larger or smaller than the "upper bounds" so the map() function may be used to reverse a range of numbers, for example
    
    y = map(x, 1, 50, 50, 1);
    
    The function also handles negative numbers well, so that this example
    
    y = map(x, 1, 50, 50, -100);
    
    is also valid and works well.
    
    The map() function uses integer math so will not generate fractions, when the math might indicate that it should do so. Fractional remainders are truncated, and are not rounded or averaged.
    
    Parameters
    
    value: the number to map
    
    fromLow: the lower bound of the value's current range
    
    fromHigh: the upper bound of the value's current range
    
    toLow: the lower bound of the value's target range
    
    toHigh: the upper bound of the value's target range
    
    Returns
    
    The mapped value.
    

    This is the equation that they use...

    long map(long x, long in_min, long in_max, long out_min, long out_max)
    {
      return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
    }
    

    I tried this....

    dim map, InMin, InMax, OutMin, OutMax as integer

    Value = 1012
    Value = map (Value, 0, 1023, 20, 255)
    HSerPrint Value

    function map (Value, InMin, InMax, OutMin, OutMax)
    map = (Value - InMin) * (OutMax - OutMin) / (InMax - InMin) + OutMin
    end function

    But it crashes. Not sure why. Any ideas out there?

     

    Last edit: viscomjim 2016-06-22
  • Anobium

    Anobium - 2016-06-22

    You know the next question.

    What version of Great Cow BASIC compiler?

     
  • viscomjim

    viscomjim - 2016-06-22

    Soooooo Sorrrry, latest one!

     
  • Anobium

    Anobium - 2016-06-22

    What is value defined as? A word? Is Value defined?

     

    Last edit: Anobium 2016-06-22
  • viscomjim

    viscomjim - 2016-06-22

    I did not dim Value orginally so I just tried it using

    dim Value, map, InMin, InMax, OutMin, OutMax as integer
    Value = 1012
    Value = map (Value, 0, 1023, 20, 255)
    HSerPrint Value
    
    function map (Value, InMin, InMax, OutMin, OutMax)
    map = (Value - InMin) * (OutMax - OutMin) / (InMax - InMin) + OutMin
    end function
    

    still no luck....

     
  • Anobium

    Anobium - 2016-06-22

    When does it crash? During compiling?

     
  • viscomjim

    viscomjim - 2016-06-22

    It won't output anything. I am using the same setup for different projects using serial output so I am sure the set up is working fine. I just did a new program to try and test this function out and get nothing on the serial out. It did compile.

     
  • Anobium

    Anobium - 2016-06-22

    Expanding the function.

    dim map, InMin, InMax, OutMin, OutMax as integer
    dim Value as word
    Value = 1012
    Value = map (Value, 0, 1023, 20, 255)
    HSerPrint Value
    
    function map (in Value, in InMin, in InMax, in OutMin, in OutMax)
    map = (Value - InMin) * (OutMax - OutMin) 
    map = map / (InMax - InMin) + OutMin
    end function
    

    For me... this prints 20.

    However, I am on very latest build.

     
  • viscomjim

    viscomjim - 2016-06-23

    I'm going to have to do a bit more research and experimentation on this. My math is not working correctly I think....

     
  • William Roth

    William Roth - 2016-06-30

    The integer values used the above attempts will overflow in the computations with anything but relatively small numbers.

    Arduio MAP uses LONGS which with Arduino I think are actually capable of holdng very large negative and positive numbers. GCB Longs are positive only.

    I think MAP was looked at last year and it was determined that it could not work unless\until GCB supported REAL numbers.

    A limited verion of MAP could possibly be done using longs and where none of the values are negative.

    The function below should work (within limits). If any calculation results in a negative number the results will be wrong.

    Function MAP (in Value as word , in InMin as WORD, in InMax as WORD, in OutMin as WORD, in OutMax as WORD) as LONG
         map = (Value - InMin) * (OutMax - OutMin)
         map = map / (InMax - InMin) + OutMin
    end function
    
     

    Last edit: William Roth 2016-06-30
  • William Roth

    William Roth - 2016-06-30

    Looks to me like you may simply be trying to scale an ADC from 10 bits to 8 bits. Where a value of 0-1023 is scaled to a value of 0- 255.

    If this is the case, just divide by the 10 bit ADC value by 4.

     

    Last edit: William Roth 2016-06-30
  • viscomjim

    viscomjim - 2016-06-30

    Hi William, thanks for that example. I will give it a try and report back. As this will work well with the 10 bit ADC, I am using it with a MSGEQ7. The output from the MSEQ7 ranges from 0 to 255 on the 8 bit pic ADC, from about 0 to 70 or so is noise. I am driving some DMX RGB light units and want to remap the output from the MSGEQ7 from 70 to 255 to 0 to 255. I noticed a lot of arduino code that does this and it allows for a better range on the lights. Won't be using negative numbers here so hopefully this will be a good solution. Something like this...

    EqValue(Zz) = Map (EqValue(Zz), 70, 255, 0, 255)

     

    Last edit: viscomjim 2016-06-30
    • William Roth

      William Roth - 2016-07-03

      Won't be using negative numbers here so hopefully this will be a good solution. Something like this... EqValue(Zz) = Map (EqValue(Zz), 70, 255, 0, 255)

      You do not have to use a negative number to have an errant result.

      Consider the function math.

        map = (Value - InMin) * (OutMax - OutMin)
        map = map / (InMax - InMin) + OutMin
      

      For example: IF the starting "value" is 65 then ....

      map =  (65 - 70)    *   255
      

      Since the function does not handle negative numbers .... (65 - 70) will result in an underflow and return a value of "65531" instead of "-5". This will cause the function to return an unexpected value of 90,396

      So the input value will need to be constrained to > or = to InMin to prevent this underflow. The Function then becomes:

       Function MAP (in Value as word , in InMin as WORD, in InMax as WORD, in OutMin as WORD, in OutMax as WORD) as LONG
           if value < InMin then value = InMin
           map = (Value - InMin) * (OutMax - OutMin)
           map = map / (InMax - InMin) + OutMin
      end function
      

      These maths take time that you may not have for fast response. This is why a lookup may be a better option.

      Edit: The speed is not a bad as I thought it might be. It takes the function above about 218 microseconds to complete with a PIC operating at 32Mhz. I tested on a PIC16F1788

       

      Last edit: William Roth 2016-07-03
      • viscomjim

        viscomjim - 2016-07-03

        After looking at a lot of arduino code, it seems like people use the "constrain" function quite a bit with the use of the map function. I made a "version" of this so I could do some testing to see if it solves some problems. This is what I came up with, although it probably could be done better. I'm not quite up to par yet with all the tricks yet so don't laugh...

        function Constrain (Value, Aa, Bb)
            if Value < Aa then
                Constrain = Aa
                exit function
            end if
            if Value > Bb then
                Constrain = Bb
                exit function
            end if
            if Value > Aa and Value < Bb then
                Constrain = Value
            end if
        end function
        

        Not sure how to make this prettier without the else if type statement. I will give your enhanced map function a whirl also. I appreciate your time William!

         
  • kent_twt4

    kent_twt4 - 2016-06-30

    Lots of calculations being done with very little time to refresh the display from the MSGEQ7. Here are my thoughts:
    1. Build a table with a spreadsheet based on the math required to remap the values.
    2. Reading tables is kinda slow, so when initializing the code before main, read the table into a large buffer variable (i.e. SRAM).

    Now you've got a super quick way to get from MSGEQ7 value to a DMX PWM value out. Extra points if you convert the logarithmic brightness perception of the eye to a linear scale. See gamma correction.

     
    • viscomjim

      viscomjim - 2016-07-03

      Hi Kent, running the pic at 20Mhz I can read the 7 values of the MSGEQ7, do some stuff with that data and spit out 24 DMX values (8 x 3) to an 8 channel RGB decoder pretty quickly. I am pretty amazed at the speed of these little buggers. It seems like there is plenty of time to spare also. Great Cow Basic is quite amazing! I have a very limited setup right now as I am "babysitting" at my sister's house for a while to help her out. I put together a nice little breadboard setup with a laptop that I can transport back and forth easily. Innovation at it's best...

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.