Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

C map function

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> Share your working BASCOM-AVR code here
View previous topic :: View next topic  
Author Message
Dave

Bascom Member



Joined: 05 Feb 2005
Posts: 270
Location: McMinnville, OR

usa.gif
PostPosted: Fri Jun 27, 2014 7:35 pm    Post subject: C map function Reply with quote

This is the C map function converted to bascom.

The map function is very handy for converting analog input to a more usable range for display.

Here is the description from the C reference manual:
Quote:
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.


Here is a bascom example:
Code:

$regfile = "m88def.dat"
$crystal = 8000000
$baud = 38400
$hwstack = 50
$swstack = 50
$framesize = 50

declare function map(x as Integer , byval in_min as Integer , byval in_max as integer , byval out_min as integer , byval out_max as Integer) as Integer

dim i as integer
dim x as integer

for i = 100 to 500
   x = map(i , 100 , 500 , 0 , 100)   'map 100-500 to 0-100
   print i;" = ";x
next

end

function map(x as integer , byval in_min as integer , byval in_max as integer , byval out_min as integer , byval out_max as integer) as integer
   local i1 as long
   local i2 as long
   i1=x - in_min
   i2=out_max - out_min
   i1=i1 * i2
   i2=in_max - in_min
   i1=i1/i2
   i1=i1 + out_min
   map = i1
end function
 
Back to top
View user's profile
snipsnip

Bascom Member



Joined: 10 Feb 2014
Posts: 66
Location: Melbourne

australia.gif
PostPosted: Sat Feb 28, 2015 2:09 am    Post subject: Reply with quote

just want to say thanks, a handy function.
I was trying to figure out how to do this, had smoke coming out my ears.

Good for GLCD's - Should make writing a GPS graphical track log viewer easy. Very Happy
maybe even 3D views??

cheers
Back to top
View user's profile
i.dobson

Bascom Expert



Joined: 05 Jan 2006
Posts: 1541
Location: Basel, Switzerland

switzerland.gif
PostPosted: Sat Feb 28, 2015 10:05 am    Post subject: Reply with quote

Hello,

And here's my version:-

Code:

'-----------------------------------------------------------------------------
Dim Sensor_accumulator(10) As Long                          'Sensor smoothed
Dim Sensor_raw(10) As Word                                  'Sensor Raw
Dim Sensor(10) As Integer                                   'Actual value

Dim Sensor_long As Long
Dim Sensor_value_long As Long
Dim Sensor_float As Single

Function Smooth_sensor(byval Sensor_value As Word , Byval Array_position As Byte , Byval Scale_sensor As Byte) As Integer
   'Function    : Scale and smooth value using array position as pointer
   'Author      : Ian Dobson
   'Inputs      : None.
   'Outputs     : None
   'Limitations :
   'Changes     :
   'Date        : 6.5.2014
   Dim Accumulator As Long
   'smooth raw value
   Sensor_value_long = Sensor_value                         'Add new
   Sensor_long = Sensor_accumulator(array_position)         'Load value into temp var.
   Accumulator = Sensor_long                                'This is the old average on LONG form
   Shift Accumulator , Right , Smoothing_factor(array_position)       'Accumulator sum divided by 2^smoothing factor
   Sensor_raw(array_position) = Accumulator                 'Save raw value
   Sensor_long = Sensor_long - Accumulator                  'Subtract old value
   Sensor_long = Sensor_long + Sensor_value_long
   Sensor_accumulator(array_position) = Sensor_long         'Save accumulator for next time

   If Smoothing_factor(array_position) = 0 Then             'NO Smoothing
      Sensor_raw(array_position) = Sensor_value_long        'Pass raw value
   End If

   If Scale_sensor = 1 Then
      'generate real value
      Sensor_float = Sensor_raw(array_position) - Zeropoint(array_position)       'Subtract 0 point
      Sensor_float = Sensor_float / Scale_factor(array_position)       'Scale raw to actual
      If Sensor_float > 0 Then
         Sensor(array_position) = Sensor_float              'Return integer
         Smooth_sensor = Sensor_float
      Else
         Sensor(array_position) = 0
         Smooth_sensor = 0
      End If
   Else
      'no scaling required
      Sensor(array_position) = Sensor_raw(array_position)
      Smooth_sensor = Sensor_raw(array_position)
   End If
End Function
 


The function smooth's and scales the input value writing the result to an array. The function expects:
The raw value to be scaled
Array position/Sensor number (Used for writing the result and finding the Zero/Span/Scaling factors)
Should the sensor be scaled Yes/No (1/0)

The function expects the following arrays to be defined
Zeropoint, this holds the raw value for the scaled 0 point
Scale_factor, this holds the scaling factor (number of raw points for 1 scaled unit)
Sensor_raw, this holds the raw smoothed but not scaled sensor value (This can be used to calculate the span during sensor recalibration).

I'm using this code on a project with currently 10 different sensors each with their own scaling/zero/smoothing factors. On start up the AVR reads the values for Zero/Span/Smoothing from an eeprom then starts scanning all the sensors.

Regards
Ian Dobson

_________________
Home of AVRTimer, the Bascom timer value calculator.
http://www.planet-ian.com

Walking on water and writing software to specification is easy if they're frozen.
Back to top
View user's profile Visit poster's website
Meister

Bascom Member



Joined: 27 May 2010
Posts: 314

PostPosted: Sat Feb 28, 2015 5:50 pm    Post subject: Reply with quote

http://www.vias.org/tmdatanaleng/cc_scaling.html
This does scaling (mapping) without AVR divisions:
Code:
'Example: Assume Temp4 linear function of Servo angle
Const Datamax = 7160
Const Datamin = 1430
Const Servomin = 14.5
Const Servomax = 53.9
Const C1 =(servomax -servomin) /(datamax -datamin)
Const C2 =(servomin * Datamax -servomax * Datamin) /(datamax -datamin)  
Dim  Temp4 As Single
'consider you measured Temp4=1500 and would like to know what the Servo angle was
Temp4=1500
Temp4 = Temp4 * C1
Temp4 = Temp4 + C2

yields Temp4=53.418674
So the range from Datamin to Datamax ("X-axis") is mapped linearly to the range from Servomax to Servomin ("Y-axis").
The input range is not limited to Datamin to Datamax.
Using this frequently.
Regards, Meister
Back to top
View user's profile
Dave

Bascom Member



Joined: 05 Feb 2005
Posts: 270
Location: McMinnville, OR

usa.gif
PostPosted: Thu Sep 03, 2020 1:02 am    Post subject: Reply with quote

@i.dobson, @Meiter

Thanks for the reply's and suggestions. Sorry I took over 5 years to respond. Embarassed

I think I'll be switching to Meiter mapping method from now on. Nice improvement. Thanks for the tip.
Back to top
View user's profile
six1

Bascom Expert



Joined: 27 Feb 2009
Posts: 553

germany.gif
PostPosted: Fri Sep 04, 2020 5:56 am    Post subject: Reply with quote

@Dave
Meister's procedure only makes sense, if Data is available at compile time!
if you'll get data from Sensors, you'll better go with i.Dobson

best, michael

_________________
For technical reasons, the signature is on the back of this message.
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> Share your working BASCOM-AVR code here All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum