Unexpected outcomes from variable assignment

Hi there chaps. Can anyone see why this isnt working? I am sampling an LDR, (ldrM) and trying to use it as the starting point for a loop. When i print out 'num' i get a correct reading but when i assign it to 'pos' i get a 0...Any thoughts? Thanks!

   { ////
      if (high == false) {
        byte num = ldrM * 0.6; //ldrm is an ldr reading
        static unsigned long timer = millis();
        static int pos = num;
        Serial.println(pos);
        if (millis() - timer > 60) {
          timer = millis();

          if (pos > 0) {
            analogWrite(eyes, pos);
            pos -= 1;
          }
        }
      }
    }

You only assign it to pos once, at initialization of pos. Split the declaration and assignment of pos.

And why do you need two variables with the same? Where num can't hold the max outcome of 613...

Let's see the whole program that demonstrates the problem.

   byte num = ldrM * 0.6; //ldrm is an ldr reading

Are you trying to put a float value into a byte ?

   static int pos = num;

If num is a byte why is pos an int ?

You only assign it to pos once, at initialization of pos. Split the declaration and assignment of pos.

ive tried this, still get the same result.

And why do you need two variables with the same?

because ldrM is a dynamic variable in that it is constantly changing(in response to light). i want to copy its value so i can then increment down from that initial value.

Are you trying to put a float value into a byte ?

Yes the ldr value becomes a float when it is multiplied as i have done.

If num is a byte why is pos an int ?

I thought that by using an int rather than a byte i might have more success. i also tried casting it as an int.

i also tried

Apparently everything BUT posting ALL of your code.

Got there in the end chaps. I believe it was something to do with the static variable being assigned before the ldr was 'booted up' because it worked when i put in an if statement which assigned it after it is > 0. Sometimes seemingly simple problems can drain a lot of time! Thanks chaps!

    { 
      if (high == false && allowed == true) {
        static unsigned long timer = millis();
        static byte pos;
        byte numb = ldrM * 0.6;
        static bool once = true;
        
        if (numb > 0 && once == true) { //assign it just once
          pos = numb;
          once = false;
        }


        if (millis() - timer > 60) {
          timer = millis();

          if (pos > 0) {
            analogWrite(eyes, pos);
            pos -= 1;
            Serial.println(pos);
          }
        }
      }
    }

I believe it was something to do with the static variable being assigned before the ldr was 'booted up

People do believe the strangest things, don't they?

gonadgranny:
ive tried this, still get the same result.

Please show us :slight_smile:

gonadgranny:
because ldrM is a dynamic variable in that it is constantly changing(in response to light).

That's the nature of a variable. But it only changes if you tell it to. And you don't show where you do that. So post the whole program. And even if it changes, why do you need two copies? num and pos?

gonadgranny:
Yes the ldr value becomes a float when it is multiplied as i have done.

Again, show us! And what does that "multiplication" represent?

gonadgranny:
I thought that by using an int rather than a byte i might have more success. i also tried casting it as an int.

You're not getting more out of a byte by potting it into an int. Once a variables that does not fit is assigned to a byte you don't get the rest back by assigning it to an int. But again, why do you need two copies?

And why do you only need it once? Your code now just doesn't make sense...

@AWOL, agreed... Just adding code like a mad monkey until it works instead of figuring out the problem.

People do believe the strangest things, don't they?

They certainly do! we have to construct our reality from limited data. Our beliefs enable us to feel comfortable in an infinitely complex world. Whether they(our beliefs) are skewed in respect to the 'truth' matters not to the individual unless another is willing to show them the error of their ways. boom. morning philosophy.

Septillon, thanks for taking the time to reply but all is working now (even if why exactly is unbeknownst to me) .

we have to construct our reality from limited data.

We do, but you have all the data, but you're not showing it to us.

gonadgranny:
from limited data.
...
even if why exactly is unbeknownst to me

It's YOU who is just looking at a limited set of data while having way more data... Code is not about believe, it's about a very strict set of rules. It not working is fully your fault. Not knowing why is also fully your fault. You could do a lot more then just adding weird patches. For example, show us all the code. Printing more debug data etc. Because not knowing why something doesn't work, or worst, not knowing why something else does work, just makes you a terrible programmer :wink: Or should I say a very good believer? ::slight_smile:

I was kind of jesting around there folks but yes I agree that its better to know why things are as they are rather than adding 'weird patches'.

void loop() {

  {
    //map the ldr values  ///do this less frequenctly to free up cpu time
    static unsigned long ldrTimer = millis();
    if (millis() - ldrTimer > 20) {
      ldrTimer = millis();

      ldrVal = analogRead(ldr);
      ldrM = map(ldrVal, ldrMin, ldrMax, 10, 255);
    }



    { 
      if (high == false && allowed == true) {
        static unsigned long timer = millis();
        static byte pos;
        byte numb = ldrM * 0.6;
        static bool once = true;

        if (numb > 0 && once == true) { //assign it just once
          pos = numb;
          once = false;
        }


        if (millis() - timer > 40) {
          timer = millis();

          if (pos > 0) {
            analogWrite(eyes, pos);
            pos -= 1;
          }
        }
      }
    }
  }
}

is this enough code? the reason im not just giving you the whole lot is because theres about 800 lines. Ive tried to pluck the relevant bits out...

If this code compiles and has the same error, yeah.

Or in this case, make it compile and test to see if you can get the same error white the boiled down version.

And still, looking at this I still don't see any reason for having both numb and pos...

ok this is done with only one variable. it complies and gives me the 'error' a zero instead of the true value. whereas if i print "ldrM * 0.6" it gives me the correct value.

int ldr = A0;
int eyes = 11;

int ldrVal;//variable to store the ldr value
int ldrM;
int ldrMax = 960;//max and min values for the ldr
int ldrMin = 40;

byte num;

bool high = false;
bool allowed = true;


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

void loop() {

  {
    //map the ldr values  ///do this less frequenctly to free up cpu time
    static unsigned long ldrTimer = millis();
    if (millis() - ldrTimer > 20) {
      ldrTimer = millis();

      ldrVal = analogRead(ldr);
      ldrM = map(ldrVal, ldrMin, ldrMax, 10, 255);
    }



    { 
      if (high == false && allowed == true) {
        static unsigned long timer = millis();
        static byte pos = ldrM * 0.6;

        Serial.println(pos);
        

        if (millis() - timer > 40) {
          timer = millis();

          if (pos > 0) {
            analogWrite(eyes, pos);
            pos -= 1;
          }
        }
      }
    }
  }
}

ok this is done with only one variable. it complies and gives me the 'error' a zero instead of the true value:

There is NOTHING in that code called error. Post your serial output instead of waving your hands uselessly.

       byte numb = ldrM * 0.6;

I see that you are still trying to put a float into a byte.

Why ?

Now we are talking!

You only fill ldrM with a read value after 20ms. Because the first if() is just executed after 20ms. But the second if() is executed right away and will use the 0 that's initialized into pos just fine.

PS.

ldrM = map(ldrVal, ldrMin, ldrMax, 10, 255);

You do know this will give you strange things when ldrVal is NOT between 40 and 960?
PPS. You have a very bad task of variable names. high is confusing with HIGH. And what is high? What is allowed? What is M in ldrM? etc
PPPS. And I agree with UKHeliBob it's a bit weird to use a float to come to pos...

I see that you are still trying to put a float into a byte.

because im using the *0.8 to scale the value and the byte is there because i am trying to save space. i presume that it just truncates the bit after the decimal?

You only fill ldrM with a read value after 20ms. Because the first if() is just executed after 20ms. But the second if() is executed right away and will use the 0 that's initialized into pos just fine.

well done sir! That indeed was the problem after all! While im here the reason i have timed the analogRead is because i am trying to save cpu. is it actually necessary for things like that?

You do know this will give you strange things when ldrVal is NOT between 40 and 960?

the reason i chose these max and min values was becuase they were the ones which i detected under very bright light and my finger over the sensor. i dont expect to go above or below those values....

PPS. You have a very bad task of variable names. high is confusing with HIGH. And what is high? What is allowed? What is M in ldrM? etc

i agree, i havent quite mastered the art. are there any tips on choosing good ones as i do confuse myself sometimes.

gonadgranny:
because im using the *0.8 to scale the value and the byte is there because i am trying to save space. i presume that it just truncates the bit after the decimal?

It indeed does. But why not stick to map() here as well?
pos = map(ldrM, 0, 255, 0, 153)
or just int
pos = ldrM * 6 / 10;
Or if 0,6 isn't all that critical... Because he, it's almost just 1/2
pos = ldrM / 2;

gonadgranny:
While im here the reason i have timed the analogRead is because i am trying to save cpu. is it actually necessary for things like that?

Depends on what you want to do and if it troubles the rest if you read it to often. I don't know what you actually do with the ldr reading nor what you do in the rest of the program. From a micro standpoint there is nothing troubling about reading the ADC often other then it takes time. From a human standpoint there is no need to read that often, even the 50 times a second you do now is wayyyyyyy faster then we notice.

gonadgranny:
the reason i chose these max and min values was becuase they were the ones which i detected under very bright light and my finger over the sensor. i dont expect to go above or below those values....

But if it does... If it returns 1023 the map will result in 271 :slight_smile: It's on you to decide if this may ever cause a problem. But for example, if you try to store this in a byte it will. To fix this, also add a contrain()

gonadgranny:
i agree, i havent quite mastered the art. are there any tips on choosing good ones as i do confuse myself sometimes.

Rule number 1, don't try to use short names. That might seem nice and fast but it will get you later on because you don't know what it was exactly. So in the case of M, what is M? Does it stand for maped? If so, why is it mapped? Add that instead.

For other variables:
int ldr => const byte LdrPin
int eyes => const byte EyesPin
bool high => bool isSomethingHigh
bool allowed => bool isSomethingAllowed
pos => I don't see you use it as a position, only a brightness (I guess?)

Thanks Septillion, that was very helpful!