View previous topic :: View next topic |
Author |
Message |
Dave
Joined: 05 Feb 2005 Posts: 314 Location: OR
|
Posted: Fri Jun 27, 2014 7:35 pm Post subject: C map function |
|
|
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 |
|
|
snipsnip
Joined: 10 Feb 2014 Posts: 74 Location: Melbourne
|
Posted: Sat Feb 28, 2015 2:09 am Post subject: |
|
|
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.
maybe even 3D views??
cheers |
|
Back to top |
|
|
i.dobson
Joined: 05 Jan 2006 Posts: 1570 Location: Basel, Switzerland
|
Posted: Sat Feb 28, 2015 10:05 am Post subject: |
|
|
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 _________________ Walking on water and writing software to specification is easy if they're frozen. |
|
Back to top |
|
|
Meister
Joined: 27 May 2010 Posts: 319
|
Posted: Sat Feb 28, 2015 5:50 pm Post subject: |
|
|
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 |
|
|
Dave
Joined: 05 Feb 2005 Posts: 314 Location: OR
|
Posted: Thu Sep 03, 2020 1:02 am Post subject: |
|
|
@i.dobson, @Meiter
Thanks for the reply's and suggestions. Sorry I took over 5 years to respond.
I think I'll be switching to Meiter mapping method from now on. Nice improvement. Thanks for the tip. |
|
Back to top |
|
|
six1
Joined: 27 Feb 2009 Posts: 553
|
Posted: Fri Sep 04, 2020 5:56 am Post subject: |
|
|
@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 |
|
|
|
|
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
|
|