MAP is a function. 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.
So, example. Read the ADC with a 8bit value (a 0 to 255 range) and you need a to MAP to a 0-270 range, use myNewValue = map ( myADCValue, 0, 255,0,270)
Include in the release? Let me know.
~~~
'''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.
'''@param l_map: the number to map
'''@param l_fromLow: the lower bound of the value’s current range
'''@param l_fromHigh: the upper bound of the value’s current range
'''@param l_toLow: the lower bound of the value’s target range
'''@param l_toHigh: the upper bound of the value’s target range
function map ( in l_map as word, in l_fromLow as word, in l_fromHigh as word, in l_toLow as word, in l_toHigh as word) as word
Here is an example for the Xpress Evaluation board using the Map Function:
''' MAP_Test.xpress.gcb'''''' Testing the MAP Function on an Xpress Board'''UseR15(potentiometer)asa5possitionRotaryswitchanddisplay''' the current state on a VT100 Terminal (TeraTerm) and LED's#Chip16F18855,32'Generated by PIC PPS Tool for Great Cow Basic'PPSToolversion: 0.0.5.11'PinManager data: v1.55'#startupInitPPS,85SubInitPPS'Module: EUSART RC0PPS = 0x0010 'TX>RC0TXPPS=0x0010'RC0>TX(bi-directional)EndSub#optionexplicit#include<LCD2SerialRedirect.h>#defineLCD_IO0#defineUSART_BAUD_RATE19200DimNewPos,CurPosasBytedirPortAoutHSerPrint"Ready"DoNewPos=Map(ReadAD10(AN4),0,1024,0,4)ifNewPos<>CurPosthenCurPos=NewPosPortA=CurPos+1cls : locate0,0HSerPrint(CurPos)endifwait100msLoopEndfunctionmap(inl_mapasword,inl_fromLowasword,inl_fromHighasword,inl_toLowasword,inl_toHighasword)asworddiml_syscalcaslong#define_mapFactor10000l_syscalc=(l_toHigh-l_toLow)+1l_syscalc=[long]l_syscalc*_mapFactorl_syscalc=[long]l_syscalc/(l_fromHigh-l_fromLow)l_syscalc=[long]l_syscalc*l_mapmap=(l_syscalc/_mapFactor)endfunction
I vote that it be included in the next release, it will be a valuable function in may different cases.
Cheers
Chris
edit: Updated to display value on LED's as well as the terminal to enhance flexibility and assist in testing possible comms errors.
Last edit: Chris Roper 2018-02-17
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This example, also for the Xpress Evaluation Board, uses the Map Function twice.
First to convert the reading from Potentiometer R15 into a mV value and the a second time to convert the mV value into a BAR Graph scale for display on the VT100 Terminal.
''' VT100-VoltMeter.xpress.gcb'''''' Use R15 (potentiometer) as a 5 potential divider and display'''thecurrentVoltageonaVT100Terminal(TeraTerm)asaBARGraph#Chip16F18855,32'Generated by PIC PPS Tool for Great Cow Basic'PPSToolversion: 0.0.5.11'PinManager data: v1.55#startup InitPPS, 85Sub InitPPS 'Module: EUSARTRC0PPS=0x0010'TX > RC0 TXPPS = 0x0010 'RC0>TX(bi-directional)EndSub#optionexplicit#include<LCD2SerialRedirect.h>#defineLCD_IO0#defineUSART_BAUD_RATE19200DimNewPos,CurPosaswordDimGraphValasByteHSerPrint"Ready"DoNewPos=Map(ReadAD10(AN4),0,1023,0,3300)' Convert Position to mV GraphVal = Map(NewPos, 0, 3300, 0, 10) 'ConvertmVtobargraphvalueifNewPos<>CurPosthenCurPos=NewPoscls : locate1,1HSerPrint"["repeatGraphValHSerPrintChr(219)endRepeatrepeat10-GraphValHSerPrintChr(32)endRepeatHSerPrint"] "HSerPrint(CurPos)HSerPrint" mV"endifwait100msLoopEndfunctionmap(inl_mapasword,inl_fromLowasword,inl_fromHighasword,inl_toLowasword,inl_toHighasword)asworddiml_syscalcaslong#define_mapFactor10000l_syscalc=(l_toHigh-l_toLow)+1l_syscalc=[long]l_syscalc*_mapFactorl_syscalc=[long]l_syscalc/(l_fromHigh-l_fromLow)l_syscalc=[long]l_syscalc*l_mapmap=(l_syscalc/_mapFactor)endfunction
Thinking further about the Map Function would it not be better to call it Scale?
Whilst I realise that it is intended to be the equivalent to the Arduino Map Function I would argue that the Arduino team got the name wrong and we would be perpetuating that error.
My reasoning is that the Function takes one value in a linear range and equates it to another linear range.
If you were reading a linear temperature sensor such as an (NTC) thermistor you would be converting a linear voltage via an ADC into a 10 digit linier value which in turn would be scaled into degrees of temperature, be it Centigrade or Fahrenheit. Mapping on the other hand is where a non linear value, such as is the case with a thermocouple temperature sensor, is compared to a lookup table to find a value from a map of nonlinear equivalents.
Ardino is the result of Computer scientists and software engineers but Microcontrollers are from the world of process control and are still predominantly used in that role.
In light of that, Scale would make far more sence to a Control Engineer than a programmer in the context of convering analoge, or even digital, sensor readings into practical units of mesurment.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This code will allow a simple potentiometer, attached to the shaft, to give numerical feedback of the actual position of a servo motor.
''' Angular.Position.xpress.gcb'''''' Testing the MAP Function on an Xpress Board'''Displaytherotationofthepotentiometer(R15)asanAngular''' Position on a VT100 Terminal (TeraTerm).#Chip 16F18855, 32'GeneratedbyPICPPSToolforGreatCowBasic'PPS Tool version: 0.0.5.11'PinManagerdata: v1.55'#startup InitPPS, 85Sub InitPPS 'Module: EUSARTRC0PPS=0x0010'TX > RC0 TXPPS = 0x0010 'RC0>TX(bi-directional)EndSub#optionexplicit#include<LCD2SerialRedirect.h>#defineLCD_IO0#defineUSART_BAUD_RATE19200DimNewPos,CurPosasIntegerHSerPrint"Ready"DoNewPos=Map(ReadAD10(AN4),0,1023,0,270)-135'ScalePositionofPotentiometertoAngulardegreesifNewPos<>CurPosthenCurPos=NewPoscls : locate1,1HSerPrint(CurPos)endifwait100msLoopEndfunctionmap(inl_mapasword,inl_fromLowasword,inl_fromHighasword,inl_toLowasword,inl_toHighasword)asworddiml_syscalcaslong#define_mapFactor10000l_syscalc=(l_toHigh-l_toLow)+1l_syscalc=[long]l_syscalc*_mapFactorl_syscalc=[long]l_syscalc/(l_fromHigh-l_fromLow)l_syscalc=[long]l_syscalc*l_mapmap=(l_syscalc/_mapFactor)endfunction
All of the examples in this thread were created during testing and are posted here to stimulate ideas.
Even is making a few changes and these examples may be adapted to work as examples for the function in its final form. Feel free to use any of this code as you see fit.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Re-Scales a number from one range to another. That is, a value of fromLow would get Scaled 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 Scale() function may be used to reverse a range of numbers, for example myvalue = Scale( InValue , 1, 50, 50, 1)
The function also handles negative numbers well, so that this example myvalue = Scale( inValue, 1, 1023, 50, -100) is also valid and works well.
The Scale() function uses integer maths.
Anobium
Totally ripped off from Arduino code. All rights reserved by the original developer.
Using the new Scale Function the Angular Position example becomes easier to visualise as the line:
' Scale Position of Potentiometer to Angular degrees
NewPos = Map(ReadAD10(AN4), 0, 1023, 0, 270) - 135
Becomes:
' Scale Position of Potentiometer to Angular degrees
NewPos = Scale(ReadAD10(AN4), 0, 1023, -135, 135)
Making it easy to see that Zero is when the Shaft is centered and that there are 135 Degrees of rotation either side of center for a total arc of 270 Degrees.
Last edit: Chris Roper 2018-02-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Using the new Scale Function the Gauge Position on a Nextion Screen is simplified:
' Scale Position of Potentiometer to Angular degrees
' Read ADC as 8 bit value
adcval = ReadAD( AN4 )
' Scale to 270 range which is the range of 270 degrees of movement of the gauge
ScaledValue = scale( adcval, 0, 255, -135 , 135 )
' Adapt the ScaledValue to start at 225degress swing thru 0degree to 135degree. 225..360..0..135 = (360-225)+(135-0)=270. So, the 0 degree of the gauge it a 0900 hours on an analog clock face.
AdaptedScaledValue1 = ( 360 + ScaledValue ) mod 360
' Adapt the ScaledValue to start at 315degress swing thru 180degree to 45degree. 315..180..45 = (315 - 45 )=270. So, the 180 degree of the gauge it a 0300 hours on an analog clock face.
AdaptedScaledValue1 = (180-ScaledValue)
Works great. I have two gauges scaled from a pot. Range of 0 to 255 to -135 to 135.
Last edit: Anobium 2018-02-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
A user "kieth sent an email asking for analogue meter display convert to show mark/space in ms for servo actuator. bit vague but now thought this would be handy. depends how fast it is with multiply and divide rather than rescaling/rewriting the program for new scale.
It's something I'd thought about not realising it's been done.
private 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;
}
Is this function in any basic? naming for consistency and familiarity. I was unfamiliar with map..thought it was to do with a key board
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
@Stan. What???! You have just posted the Arduino MAP function. We know this exists and we acknowledged this in the documentation. What is your point in the post?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As a basic user I'm unfamiliar with map. I searched other basic for map. I saw it wanted converting. I'm assuming it's not a standard basic thing so give it a meaningful name as mentioned maybe. Re-scale would mean something more than map for basic users unfamiliar with c map perhaps. maybe scaleto . If it goes in solutions map vs rescale(range) ?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Anobium - re nextion. I sent you a nextion display. The ide was carp. I thought you'd used it as just a display. I thought of mentioning using gcb to make a nextion display ie send serial commands to use graphics to a programmed pic and screen.
it was for picaxe but got nowhwere with the program sd card except for demos.
It wouldn't take much to "make a nextion" with supported glcd. with gcb as far as graphics,the touch screen dunno.
Thinking, the nextion win ide was no fun but the idea fine. images on sd nice. cost £20
a simpler/cheaper version as most colour displays have sd slot?
Last edit: stan cartwright 2018-02-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am writing a GLCD library for the Nextion Displays. Next week I may have something ready.
State of current development. Most Great Cow BASIC GLCD commands are operational. GLCDPrint, Circle, PSET etc etc. I have sorted access to the internal fontset and the Nextion objects. Looking pretty easy to use. But, it has been a lot of work.
The SD Card is used to load the Nextion screens, but, you can do the same via the serial port.
Last edit: Anobium 2018-02-18
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
More info please about Anobium using nextion. The display you showed is called a what? it's in the ide.Guages? Did you get the thing working for you? I never did. gcb glcd does fine but not nextion equiv. any thoughts. glcd sd card image is in the forum somewhere. make new thread?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I tried scale to convert 0-255 to 45-314 degree analoge gauge. It worked.
Neat function. very fast in this visual use.
basis of a gauge for glcd. works nice with scale as shows any range.
a pretty facia would be easy with a few commands
;scaleto45to314degreesfor"rev counter"typedisplayglcdonuno#chipmega328p,16#include<UNO_mega328p.h>#optionexplicit#include<glcd.h>#INCLUDE<TRIG2PLACES.H>;#defineGLCD_TYPEGLCD_TYPE_ILI9341'Pin mappings for SPI - this GLCD driver supports Hardware SPI and Software SPI#define GLCD_DC DIGITAL_8 'Datacommandline#defineGLCD_CSDIGITAL_10' Chip select line#define GLCD_RESET DIGITAL_9 'Resetline,youcouldjusttiehigh#defineGLCD_DIDIGITAL_12' Data in | MISO - Not used therefore not really required#define GLCD_DO DIGITAL_11 'Dataout|MOSI#defineGLCD_SCKDIGITAL_13' Clock Line;#define ILI9341_HardwareSPI 'remove/commentoutifyouwanttousesoftwareSPI.#defineGLCD_EXTENDEDFONTSET1GLCDfntDefaultsize=2GLCDRotate(3)GLCDCLSILI9341_BLACK;dimradius,xcentre,ycentre,xend,yendasbytedimtemp,angle,needlecolour,newval,oldvalasworddirportc.0in;radius=200xcentre=160ycentre=120oldval=45newval=45;draw_needle;DoGLCDPrint0,0,str(readad(portc.0))+" ",ili9341_whitenewval=Scale(ReadAD(portc.0),0,255,45,314)ifnewval<>oldvalthenerase_needledraw_needleoldval=newvalendifLoopEnd;functionscale(inl_mapasword,inl_fromLowasinteger,inl_fromHighasinteger,inl_toLowasinteger,inl_toHighasinteger)asintegerdiml_syscalcasintegerdiml_syscalcFaslongl_syscalcf=0repeat(l_toHigh-l_toLow)l_syscalcf=l_syscalcf+(l_map-l_fromLow)endRepeatl_syscalc=(l_fromHigh-l_fromLow)scale=(l_syscalcf/l_syscalc)+l_toLowendfunction;suberase_needleangle=oldvalneedlecolour=ILI9341_blackradius=200needle;eraseneedleendsub;subdraw_needleangle=newvalneedlecolour=ILI9341_whiteradius=200needle;drawneedleendsub;subneedlexend=xcentre-radius*sin(angle)/255yend=ycentre+radius*cos(angle)/255line(xcentre,ycentre,xend,yend,needlecolour)endsub
Last edit: stan cartwright 2018-02-19
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I noticed the a2d doesn't get to 255 (or 1023 with readad10) on uno or nano 328p in the code just posted for scale to ili glcd. https://youtu.be/ywBkivRINl0
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This sorted it, readad goes 0-255 but connecting ad.0 to 5V and it's not steady at 255 but jumping around between 248 and 252. Connecting to 0V gives steady 0.
I've never changed the vref and readad has always been 0-255.
Add attatchments not working.
Last edit: stan cartwright 2018-02-20
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There was request a long time ago for a MAP command. Well I needed one - so, here is it.
See this for the latest!! https://sourceforge.net/p/gcbasic/discussion/629990/thread/d40aceb3/#82d6
Last edit: Anobium 2018-02-18
I like it.
Here is an example for the Xpress Evaluation board using the Map Function:
I vote that it be included in the next release, it will be a valuable function in may different cases.
Cheers
Chris
edit: Updated to display value on LED's as well as the terminal to enhance flexibility and assist in testing possible comms errors.
Last edit: Chris Roper 2018-02-17
This example, also for the Xpress Evaluation Board, uses the Map Function twice.
First to convert the reading from Potentiometer R15 into a mV value and the a second time to convert the mV value into a BAR Graph scale for display on the VT100 Terminal.
Cheers
Chris
edit; Updated to correctly show mV
Last edit: Chris Roper 2018-02-17
Nice function. Thought of this https://sourceforge.net/p/gcbasic/discussion/projects%26guides/thread/d589f1da/
Good example code @Chris Roper
Thinking further about the Map Function would it not be better to call it Scale?
Whilst I realise that it is intended to be the equivalent to the Arduino Map Function I would argue that the Arduino team got the name wrong and we would be perpetuating that error.
My reasoning is that the Function takes one value in a linear range and equates it to another linear range.
If you were reading a linear temperature sensor such as an (NTC) thermistor you would be converting a linear voltage via an ADC into a 10 digit linier value which in turn would be scaled into degrees of temperature, be it Centigrade or Fahrenheit. Mapping on the other hand is where a non linear value, such as is the case with a thermocouple temperature sensor, is compared to a lookup table to find a value from a map of nonlinear equivalents.
Ardino is the result of Computer scientists and software engineers but Microcontrollers are from the world of process control and are still predominantly used in that role.
In light of that, Scale would make far more sence to a Control Engineer than a programmer in the context of convering analoge, or even digital, sensor readings into practical units of mesurment.
Cheers
Chris
One more example.
This code will allow a simple potentiometer, attached to the shaft, to give numerical feedback of the actual position of a servo motor.
All of the examples in this thread were created during testing and are posted here to stimulate ideas.
Even is making a few changes and these examples may be adapted to work as examples for the function in its final form. Feel free to use any of this code as you see fit.
Cheers
Chris
A revised method called Scale().
myvalue = Scale( InValue , fromLow, fromHigh, inHigh, inLow)
Re-Scales a number from one range to another. That is, a value of fromLow would get Scaled 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 Scale() function may be used to reverse a range of numbers, for example
myvalue = Scale( InValue , 1, 50, 50, 1)
The function also handles negative numbers well, so that this example
myvalue = Scale( inValue, 1, 1023, 50, -100) is also valid and works well.
The Scale() function uses integer maths.
Anobium
Totally ripped off from Arduino code. All rights reserved by the original developer.
I didn't know what map did. I was surprised it re-scaled a range of values.
Learning all time. The initial Great Cow BASIC version I posted supported Bytes and Words. The version called Scale supports Integers.
Very interesting use cases posted by Chris. Ineeded to Scale 0 -255 to 225-135 (a range of 270 in a 360 full range) .
Last edit: Anobium 2018-02-18
Using the new Scale Function the Angular Position example becomes easier to visualise as the line:
Becomes:
Making it easy to see that Zero is when the Shaft is centered and that there are 135 Degrees of rotation either side of center for a total arc of 270 Degrees.
Last edit: Chris Roper 2018-02-18
Using the new Scale Function the Gauge Position on a Nextion Screen is simplified:
Works great. I have two gauges scaled from a pot. Range of 0 to 255 to -135 to 135.
Last edit: Anobium 2018-02-18
A user "kieth sent an email asking for analogue meter display convert to show mark/space in ms for servo actuator. bit vague but now thought this would be handy. depends how fast it is with multiply and divide rather than rescaling/rewriting the program for new scale.
It's something I'd thought about not realising it's been done.
private 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;
}
Is this function in any basic? naming for consistency and familiarity. I was unfamiliar with map..thought it was to do with a key board
@Stan. What???! You have just posted the Arduino MAP function. We know this exists and we acknowledged this in the documentation. What is your point in the post?
As a basic user I'm unfamiliar with map. I searched other basic for map. I saw it wanted converting. I'm assuming it's not a standard basic thing so give it a meaningful name as mentioned maybe. Re-scale would mean something more than map for basic users unfamiliar with c map perhaps. maybe scaleto . If it goes in solutions map vs rescale(range) ?
@Stan. OK
@Anobium - hold steadfast! Map is good.
Anobium - re nextion. I sent you a nextion display. The ide was carp. I thought you'd used it as just a display. I thought of mentioning using gcb to make a nextion display ie send serial commands to use graphics to a programmed pic and screen.
it was for picaxe but got nowhwere with the program sd card except for demos.
It wouldn't take much to "make a nextion" with supported glcd. with gcb as far as graphics,the touch screen dunno.
Thinking, the nextion win ide was no fun but the idea fine. images on sd nice. cost £20
a simpler/cheaper version as most colour displays have sd slot?
Last edit: stan cartwright 2018-02-18
I am writing a GLCD library for the Nextion Displays. Next week I may have something ready.
State of current development. Most Great Cow BASIC GLCD commands are operational. GLCDPrint, Circle, PSET etc etc. I have sorted access to the internal fontset and the Nextion objects. Looking pretty easy to use. But, it has been a lot of work.
The SD Card is used to load the Nextion screens, but, you can do the same via the serial port.
Last edit: Anobium 2018-02-18
ps by the time i type something the forum has been updated but doesn't show in real time so I look daft
More info please about Anobium using nextion. The display you showed is called a what? it's in the ide.Guages? Did you get the thing working for you? I never did. gcb glcd does fine but not nextion equiv. any thoughts. glcd sd card image is in the forum somewhere. make new thread?
I tried scale to convert 0-255 to 45-314 degree analoge gauge. It worked.
Neat function. very fast in this visual use.
basis of a gauge for glcd. works nice with scale as shows any range.
a pretty facia would be easy with a few commands
Last edit: stan cartwright 2018-02-19
I noticed the a2d doesn't get to 255 (or 1023 with readad10) on uno or nano 328p in the code just posted for scale to ili glcd. https://youtu.be/ywBkivRINl0
What are the returned results? The range Please post your ASM. What is VREF set to ( see help for VREF).
I added
This sorted it, readad goes 0-255 but connecting ad.0 to 5V and it's not steady at 255 but jumping around between 248 and 252. Connecting to 0V gives steady 0.
I've never changed the vref and readad has always been 0-255.
Add attatchments not working.
Last edit: stan cartwright 2018-02-20
Did you check the 0v common ground?