GSWA - Example 07 - P69 - variable not working

Platform: WinXP / Arduino UNO
Sketch: (see below) An edited Example 07 from Getting Started With Arduino.

I'm trying to find a way to make the LED at Pin 9 present a wider scope of intensity depending on recent exposure feedback from the LDR. So I've been setting up variables that might be helpful for something like that.

For some reason, my brightness variable keeps coming up zero.
A manual calculation quickly shows we're not in the ballpark for what brightness should be. I double-checked with a spreadsheet of outgoing variables. (See highlighting for quick reference.)

It compiles, so it's probably not a syntax error. I'm guessing it has something to do with 'int'. Can someone explain to me what's going on with that value?

Example serial data, pinout and sketch follow for reference.

Cheers

Example Values - Serial Port Monitor:

val = 203 | ravgval = 181 | hval = 203 | intensity = 50 | brightness = 0 | thisTime = 5154
val = 207 | ravgval = 193 | hval = 208 | intensity = 51 | [glow]brightness = 0[/glow] | thisTime = 5366
val = 202 | ravgval = 194 | hval = 208 | intensity = 50 | [glow]brightness = 0[/glow] | thisTime = 5236
val = 204 | ravgval = 194 | hval = 208 | intensity = 51 | [glow]brightness = 0[/glow] | thisTime = 5296
val = 131 | ravgval = 175 | hval = 208 | intensity = 32 | brightness = 0 | thisTime = 5008
val = 129 | ravgval = 136 | hval = 188 | intensity = 32 | brightness = 0 | thisTime = 5158
val = 128 | ravgval = 127 | hval = 168 | intensity = 32 | brightness = 0 | thisTime = 5146
val = 127 | ravgval = 126 | hval = 168 | intensity = 31 | brightness = 0 | thisTime = 5104
val = 127 | ravgval = 126 | hval = 168 | intensity = 31 | brightness = 0 | thisTime = 5076
val = 126 | ravgval = 125 | hval = 168 | intensity = 31 | brightness = 0 | thisTime = 5052
val = 126 | ravgval = 125 | hval = 168 | intensity = 31 | brightness = 0 | thisTime = 5058
val = 131 | ravgval = 125 | hval = 168 | intensity = 32 | brightness = 0 | thisTime = 5096

Board Pinout:

Sketch:

// Example 06A: Blink LED at a rate specified by the value of the analogue input.

#define LED 13 // The pin for the LED
#define LED2 9 // The pin for the LED

int val = 0; // Variable used to store the value coming from the sensor.
int hval = 0; // Keep tabs of the highest value since the last delayTime.
int ravgval = 0; // Keep rolling average.
int intensity = 0; // Buffered val
[glow]int brightness = 0;[/glow] // Calculated brightness value
int delayTime = 5000; // Five seconds in milliseconds.
int thisTime = 0; // A counter to compare with delayTime.

void setup() {
  pinMode(LED, OUTPUT); // LED is an OUTPUT.
  pinMode(LED2, OUTPUT); // LED2 is an OUTPUT.
  
  // Note: Analogue pins are automatically set as inputs.
  
}

void loop(){
  val = analogRead(0); // Read the value from the sensor.
  ravgval = ((14*ravgval)+val)/15; // Mock Rolling Average.
  if(val > hval){
    hval = val;
  } 
  intensity = val/4; // analog value transformed to variable within writable parameters
  [glow]brightness = (intensity/254)*hval;[/glow]
  
  digitalWrite(LED, HIGH); // Turn LED on.
  analogWrite(LED2, intensity); // Turn LED2 on.
  
  delay(val); // Stop the program for some time.
  thisTime = thisTime + val; // Add val to current delayTime.
  
  digitalWrite(13, LOW); // Turn LED off.

  delay(val); // Stop the program for some time.
  thisTime = thisTime + val; // Add val to current delayTime.
  
  if (thisTime > delayTime){
  // Write to serial port every time thisTime is greater than delayTime.
    Serial.begin(9600);
    Serial.print("val = ");
    Serial.print(val);
    Serial.print(" | ravgval = ");
    Serial.print(ravgval);
    Serial.print(" | hval = ");
    Serial.print(hval);
    Serial.print(" | intensity = ");
    Serial.print(intensity);
    Serial.print(" | brightness = ");
    Serial.print(brightness);
    Serial.print(" | thisTime = ");
    Serial.println(thisTime);
    thisTime = 0; // Reset our counter.
    if (hval > val + 50){
    hval = hval - 20; // Reduce hval incrementally.
    }
  }

}

val is going to be in the range 0 to 1023. When you divide the value by 4, you reduce the range to 0 to 255. These are integers.

Next, you divide the integer by 254. This will result in a value of either 0 or 1. If the value in intensity was 254 or 255, brightness will be 1 * hval. Otherwise, it will be 0 * hval, which is 0.

Integer arithmetic may not be what you want to be doing.

PaulS - Thank you for your reply.

I might not be understanding what you mean about intensity.
Intensity calculates on the fly to be somewhere between 50 and 30.
Intensity must always be 255 or less since it's val/4.
Intensity divided by 254 gives me a percentage.
I'm actually multiplying that percentage by the highest-recently-found-val 'hval', not 254.
If I take my data into excel:

brightness = (intensity/254)*hval
val = 203 | ravgval = 181 | hval = 203 | intensity = 50 | brightness = 0 | thisTime = 5154
(50/254)*203 = 40 <-- Expected result

val = 207 | ravgval = 193 | hval = 208 | intensity = 51 | brightness = 0 | thisTime = 5366
(51/254)*208 = 42 <-- Expected result

val = 202 | ravgval = 194 | hval = 208 | intensity = 50 | brightness = 0 | thisTime = 5236
(50/254)*208 = 41 <-- Expected result

val = 204 | ravgval = 194 | hval = 208 | intensity = 51 | brightness = 0 | thisTime = 5296
(51/254)*208 = 51 <-- Expected result

val = 131 | ravgval = 175 | hval = 208 | intensity = 32 | brightness = 0 | thisTime = 5008
(32/254)*208 = 26 <-- Expected result

I suspect you may be right about ints, but when I do the math as shown above, I get these results completely different from what arduino is showing me.

Int seems to be handling my rolling mock average as expected:

ravgval = ((14*ravgval)+val)/15; // Mock Rolling Average.

Why not brightness?

Intensity divided by 254 gives me a percentage.

No, it doesn't. it gives you a ratio. But, the division is integer division.

Intensity calculates on the fly to be somewhere between 50 and 30.

Dividing 30 by 254 gives 0. Dividing 50 by 254 gives 0.

If I take my data into excel:

Sure. Because excel doesn't distinguish between integers and real numbers. C and the Arduino do.

In excel, (50/254)*203 = 40. In C, (50/254)*203 = 0, because 50/254 = 0, because both values are integers.

Now, (50.0/254.0) * 203.0 will give 39.96063 as a result, because all the operands are floats.

By the way, you would get different results if you changed the order of the operations. Multiply first, then divide. The result is still integer math, but the result would not always be 0.

I realized just as you were replying.
Thanks - it clears up a lot.
Is there an easy work around for int, or should I try float?

PEMDAS - Parentheses are your friends, eh?

I changed it to a float. It works now, though maybe not as expected.
I've certainly got a lot to think about. Thanks!

val = 52 | ravgval = 39 | hval = 53 | intensity = 13.00 | brightness = 2 | thisTime = 5028
val = 52 | ravgval = 39 | hval = 53 | intensity = 13.00 | brightness = 2 | thisTime = 5044
val = 65 | ravgval = 41 | hval = 65 | intensity = 16.00 | brightness = 4 | thisTime = 5130
val = 224 | ravgval = 128 | hval = 224 | intensity = 56.00 | brightness = 49 | thisTime = 5126
val = 233 | ravgval = 180 | hval = 233 | intensity = 58.00 | brightness = 53 | thisTime = 5428
val = 481 | ravgval = 188 | hval = 481 | intensity = 120.00 | brightness = 227 | thisTime = 5168
val = 476 | ravgval = 283 | hval = 481 | intensity = 119.00 | brightness = 225 | thisTime = 5732