The scaled_value function -- where is it, actually?

I would like to know where the Arduino IDE gets access to the function called "scaled_value()". I have encountered it in the book I am reading, and the author did explain what it does, so i can use it, but I am curious 'where' it actually resides? I can find nothing at all online about where this function is kept, what library it might be in, or where it is declared so that Arduino IDE can use it. I searched all the Arduino and Processing *.cpp and *.h files on my PC, as well as all the keyword.txt files for those 2 applications. I also tried looking for it in online lists of C++ functions. Zilch. Isn't it documented somewhere? Is there a way to change how it works (so maybe it rounds to other numbers of decimal values, for example)? I'd like to read more about it. Can someone point me to information about this function?

Have you tried using this "scaled_value" in a sketch? What happened?

maybe you need map() - http://www.arduino.cc/en/Reference/map - ???

It sounds more like a function that the author of your book had written, perhaps in an earlier example. Or as AWOL put it rather more succinctly, can you compile an example that uses it?

Thanks for the replies, but as I did mention in my first post, I can use it and I do get the desired result. I just can't find any documentation on it. If the function were created by the book author, he would have either had to include a library with the function in it, or else declare (define) the function in this project sketch before using it during the Serial.Print code line as he did, correct? Neither is the case. I can post the entire sketch if desired. But I was hoping someone already was familiar with the scaled_value() function and could shed some light on its origin.

I couldn't compile a sketch using it, could you post one that uses it?

scaled_value() Is not a function I've come across and it's not listed in the Arduino reference, so I guess you will have to post your sketch to prove to us that's it's part of the Arduino distrubution. Are you including any libraries in your sketch?

http://arduino.cc/en/Reference/HomePage

Lefty

Please note that this project runs well and does what it is supposed to do when the sensors are wired up to my UNO board. I just wanted to know where “scaled_value” comes from, because I can’t find it listed anywhere.

Thanks.

Here is the entire code for the project. It utilizes this first sketch running in Arduino IDE. The second sketch I will post below the fgirst one is meant to be run in the Processing IDE, and produces an “inverted sonar” display. What this project does is utilize a Ping))) model 28015 Ultrasonic Sensor to measure distance from 2 thru 300 cm, and then uses a TMP36 temperature sensor to provide better accuracy, since sound’s speed of travel is affected by ambient temperature and humidity. The project is meant to introduce the reader to these sensors and show them in action.

Here is the Arduino code. I have begun adding comment lines to explain in my own words how this sketch works (part of my learning process). Where my comments currently stop is where you will find the use of the scaled_value() function. There is no library file being included here.

//Ultrasonic_Precise_Sensor.pde
// Uses a Ping))) ultrasonic sensor model 28015 to measure diatances of 2cm to 300cm
//This sketch adds a TMP36 temperature sensor to increase accuracy (sound travel times vary
//up to 12% depending upon ambient temperature and humidity).

//Define constants:

const unsigned int TEMP_SENSOR_PIN = 0;
const float SUPPLY_VOLTAGE = 5.0;
const unsigned int PING_SENSOR_IO_PIN = 7;
const float SENSOR_GAP = 0.2;
const unsigned int BAUD_RATE = 9600;

float current_temperature = 0.0;              //Define floating point variable:
unsigned long last_measurement = millis();    //Define function to handle last tempearature data taken. 

void setup() {
  Serial.begin(BAUD_RATE);
}

void loop() {
  unsigned long current_millis = millis();              //declare function used to handle the ultrasonic pulse travel time measured
  if (abs(current_millis - last_measurement) >= 1000) { //has time reading changed within last second? Only get new temp reading if change is detected.
    current_temperature = get_temperature();            //get temperature reading
    last_measurement = current_millis;                  //load current time value into last_measurement function  
  }
  Serial.print(scaled_value(current_temperature));      //print to Serial Monitor the value of the temperature sensor using the scaled value function, which is another hidden and undocumented
                                                        //function (can't find it anywhere), but fortunately he explains what it does in the book on page 101. Takes a floating point number and 
                                                        //rounds it to 2 digits. Then it multiples the number by 100, resulting in a "long" value. This reduces memory and processor overhead during
                                                        //handling of this piece of data. The result must be divided by 100 to regain its true value in the end. 
  Serial.print(",");
  const unsigned long duration = measure_distance();
  Serial.println(scaled_value(microseconds_to_cm(duration)));
}

long scaled_value(const float value) {
  float round_offset = value < 0 ? -0.5 : 0.5;
  return (long)(value * 100 + round_offset);
}

const float get_temperature() {
  const int sensor_voltage = analogRead(TEMP_SENSOR_PIN);
  const float voltage = sensor_voltage * SUPPLY_VOLTAGE / 1024;
  return (voltage * 1000 - 500) / 10;
}
  
const float microseconds_per_cm() {
    return 1 / ((331.5 + (0.6 * current_temperature)) / 10000);
}
      
const float sensor_offset() {
  return SENSOR_GAP * microseconds_per_cm() * 2;
}

const float microseconds_to_cm(const unsigned long microseconds) {
  const float net_distance = max(0, microseconds - sensor_offset());
  return net_distance / microseconds_per_cm() / 2;
}

const unsigned long measure_distance() {
  pinMode(PING_SENSOR_IO_PIN, OUTPUT);
  digitalWrite(PING_SENSOR_IO_PIN, LOW);
  delayMicroseconds(2);
  
  digitalWrite(PING_SENSOR_IO_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_SENSOR_IO_PIN, LOW);
  
  pinMode(PING_SENSOR_IO_PIN, INPUT);
  return pulseIn(PING_SENSOR_IO_PIN, HIGH);
}

And here is the sketch for Processing. I am not as familiar with Processing as what I have learned on Arduino. There is no “#include”, but there IS an “import processing.serial.*” I looked through the files I could read with a text editor in the Processing library folders. There is one named Serial. But I could not find anything in it which listed “scaled_value”.

//Ultrasonic/InvertedSonar.pde
import processing.serial.*;

final int WIDTH = 1000;
final int HEIGHT = 1000;
final int xCenter = WIDTH / 2;
final int yCenter = HEIGHT / 2;
final int LINE_FEED = 10;

Serial arduinoPort;
SensorData sensorData;
int degree = 0;
int radius = 0;


void setup() {  //Line 1 page 109
  size(WIDTH, HEIGHT);
  println(Serial.list());
  String arduinoPortName = Serial.list()[0];
  arduinoPort = new Serial(this, arduinoPortName, 9600);
  arduinoPort.bufferUntil(LINE_FEED);
}

void serialEvent(Serial port) {    //Found "SerialEvent" instead of "serialEvent" during debugging - preventing the data from being printed or from moving the dot on the sketch's display.
  sensorData = getSensorData();
  if (sensorData != null) {
    println("Temperature: " + sensorData.getTemperature());
    println("Distance: " + sensorData.getDistance());
    radius = min(300, int(sensorData.getDistance() * 2));
  }
}

SensorData getSensorData() {
  SensorData result = null;
  if (arduinoPort.available() > 0) {
    final String arduinoOutput = arduinoPort.readStringUntil(LINE_FEED);
    result = parseArduinoOutput(arduinoOutput);
  }
  return result;
}

SensorData parseArduinoOutput(final String arduinoOutput) {
  SensorData result = null;    //IDE is not tabbing new lines correctly beginning here
  if (arduinoOutput != null) {
    final int[] data = int(split(trim(arduinoOutput), ','));
    if (data.length == 2)
    result = new SensorData(data[0] / 100.0, data[1] / 100.0);
  }
  return result;
}

void init_screen() {
  background(255);
  stroke(0);
  strokeWeight(1);
  int[] radius_values = {300, 250, 200, 150, 100, 50 };
  for (int r = 0; r < radius_values.length; r++) {
    final int current_radius = radius_values[r] * 2;
    ellipse(xCenter, yCenter, current_radius, current_radius);
  }
  strokeWeight(10);
}
void draw() {
  init_screen();
  int x = (int)(radius * Math.cos(degree * Math.PI / 180));
  int y = (int)(radius * Math.sin(degree * Math.PI / 180));
  point(xCenter + x, yCenter + y);
  if (++degree == 360)
     degree = 0;
}

Help me if I’m being a little dense here, but isn’t that the scaled_value function about 8-9 lines down from where it’s called?

Heh. Well, perhaps the "who is dense" issue would be debatable. :grin:

As many times as I looked at this code while typing it in I missed that being there when it came time to put in my comments. Plus, being new myself to this whole hobby, I guess I was expecting that a function had to be declared BEFORE it was called, so expected to find all the function declarations toward the top. This would explain why I had not been able to find a "definitive" reference, wouldn't it? The author created this function.

Sorry for the confusion. :) I really do appreciate the help!!

Happy Arduinoing!

I guess I was expecting that a function had to be declared BEFORE it was called, so expected to find all the function declarations toward the top.

A function does need to be declared before it is called.

One of the things that the Arduino IDE does (but that I wish it didn't) is to scan the code and create function prototypes (mostly correctly) for all functions that do not have a function prototype defined.

It would be nice if the IDE actually modified the sketch that was being compiled so you could see that this was happening.

Well, this is an interesting turn of events in the learning curve, for sure! So I take it if I move the declaration of this function up toward the top "where it belongs" (logically) the sketch will still run OK then?

Thanks very much for clarifying this point! It inspires self-confidence to find that what I was expecting was for good reason.

Regards,

Zoandar

A long, long time ago compilers couldn't resolve a function that was declared after it was called and would throw an error. Programmers whined that they wanted to put the meat of a module up at the top so they could find it easily when they were modifying it. So language developers put in two pass scanning to resolve some of this. Then the programmers complained that they wanted the lowest level routines at the end of the module because they were seldom changed so a new system of scanning the source came into being. Now we can put the lowest level routines at the very bottom (end) of the module and the highest level routines at the top.

So now, we put the highest level routines in the middle and wrap stuff around it in a stream of consciousness fashion that makes it hard, even for the author, to find.

Seems like the further we go......

:)

Sort of like the old German phrase "The hurrier I go, the behinder I get!".

I can see the merit in both of the first two phases of your evolution story. In fact, when I have written programs in languages like Basic and more recently AutoHotkey, I always put my subroutines down toward the end of the page. But to my way of thinking, "definitions" ought to come "first". How can I read a 'story' if I don't know what the words mean? It's like when reading a magazine article and the author tosses in an acronym without at least once saying what it stands for. That always bugs me.

Thanks for explaining that I can apparently put these declarations anywhere I want. But my preference will be to put them up front. Actually, in AutoHotkey it is common to have a section of required code at the top of every program, and then to put your actual code doing the work below that. So I guess it's hard to please everyone. :)

Regards,