Bitshift help.

Hello all,

//Main.
void loop()
{
  byte b = 0;
  unsigned long temp = 0;
  unsigned long result = 0;
  char str[32];
  
  Ignition_State_Check();
  
  get_PID(ERPM, &result, str);
  temp = result/1000;
  for(byte i = 0; i < temp; i++)
  {
    b = 1 << 1 | 1;
  }
  Serial.print(b, BIN);
  delay(1000);
}

Am a bit stuck for ideas and not sure if am trying to do this correctly. I have a value in unsigned long result then that gets divided by 1000 to give me either a 0 or a 1 or a 2 or a 3 or a 4 or a 5 or a 6 or a 7 or a 8 depending whats in unsigned long temp. I then am trying to use a for loop to give me for example in byte b 00111111. This will then be used to light up 6 out of 8 LED's but i ony get is 00000010. Can anyone tell me what am doing wrong?

Thanks.

    b = 1 << 1 | 1;

Here you're assigning b to 0... temp times.

Try this:

for(byte i = 0; i < temp; i++)
  {
    b = b | (1 << i);
  }

There, every time the loop runs, b gets a 1 in one more place over.

Thank you, could please explain what this is doing b = b | (1 << i); because i cant get my head around it and if i had a value of 6 i would get 111111 but do i need to add 2 0's at the end to make up the full 8 bits like 11111100? Also is this a good way to do what am trying to do or would using a array like this be a better way ?

byte ArrayRPM[8] = 
{
  B00000000,
  B10000000,
  B11000000,
  B11100000,
  B11110000,
  B11111000,
  B11111100,
  B11111110,
  B11111111,
};
[code]
1 << i;

makes the values:

00000001
00000010
00000100
00001000
00010000
00100000
01000000
10000000

assuming that it runs 8 times. Then by using a bitwise OR on each one, the one's just add together. So

00000001
00000010
00000100
00001000
00010000

all OR'd together makes

00011111

if you want to make the output look like
11110000 for an input of 4, then you could do this:

for(byte i = 0; i < temp; i++)
  {
    b = b | (1 << (8-i));
  }

That makes it go in reverse order.

I'm almost certain there is a better way to do this than using a loop or a lookup table though.[/code]

Thank you, you have been most helpfull and i understand now.

I'm almost certain there is a better way to do this than using a loop or a lookup table though.

If anyone knows then that would be great.

To replace:-

temp = result/1000;
  for(byte i = 0; i < temp; i++)
  {
    b = 1 << 1 | 1;
  }

How about

temp = result/1000;
b = (1 << temp) -1;

Yes Grumpy_Mike but for example if result was 4 then i need that code to create 11110000.

Does this work?

b = ~((1 << (8-temp)) -1);

I have just tested that and yes it does work, great. What is the -1 doing in this if you don't mind me asking (i have not used these functions before so this is new to me)? If am going to use it i need to know what it is doing lol but thanks a bunch to WizenedEE and Grumpy_Mike.

  b = 1 << 1 | 1;

use instead:

  b = (b << 1) | 1;

to produce 0b00000001 -> 0b00000011 -> 0b00000111 ...

or

  b = (b >> 1) | 0x80;

to produce 0b10000000 -> 0b11000000 -> 0b11100000 ...;

This is also considerably faster.

Code:
b = 1 << 1 | 1;
use instead:

Code:
b = (b << 1) | 1;
to produce 0b00000001 -> 0b00000011 -> 0b00000111 ...

or

Code:
b = (b >> 1) | 0x80;
to produce 0b10000000 -> 0b11000000 -> 0b11100000 ...;

This is also considerably faster.

dhenry, i have tested what you have said and it doen't work.

Pavilion1984:
I have just tested that and yes it does work, great. What is the -1 doing in this if you don't mind me asking (i have not used these functions before so this is new to me)? If am going to use it i need to know what it is doing lol but thanks a bunch to WizenedEE and Grumpy_Mike.

1<<5 = 00100000
00100000 -1 = 00011111
~00011111 = 11100000

What is the -1 doing

Subtracting one.

Any power of two can be expressed as a 1 followed by several zeros, the number depending on the power. If you subtract one from the resulting number you get zero followed by several ones.
If you want the inverse of this, for example you have 0001 1111 and you want 1110 0000 then just take the inverse of the number. There are many ways of doing this, here are some, assume the number you want to invert is in a vaiable called b

b = ~b; // note this is a tilda not a minius
b = b ^ 0xff // exclusive or inverts all bits in a variable that have a matching one in the number you are exoring it with
b = not(b);

Ok thanks alot. So i have 2 options of code to use

1 - the lookup table
or
2 - the bitshift function

is one better then the other or just personal preference? I will be using the i2c driver for my display and this RPM stuff is just the start of it. I now need to find out the best way to flash the last "on" LED in 11111000 if a variable has been set to 5 or if the variable has been set to 6 flash the last "on" LED in 11111100.

It is always better to use an algorithm than a look up table in my opinion.

For flashing create a number with a one in the bit you want to flash using bit shift operations. Then exclusive or this number with your byte save and output.
Every exclusive or operation will toggle the bit you set in the number.

Ok cheers. Is bit set good to use here or keep using the << stuff? Am just trying to work out a routine now.

I have managed to create the following test sketch to simulate my real program and try to implement the gear shit indicator led flash. The timings have been slowed down for easier reading in the serial monitor.

byte temp;
byte Display_RPM;
byte ShiftIndicator = 5;
unsigned long result = 6902;

long previousMillis = 0;

byte flash(long Interval)
{
  long currentMillis = millis();
  if(currentMillis - previousMillis > Interval)
  {
    previousMillis = currentMillis;
    return 1;
  }
  else
  {
    return 0;
  }
}

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

void loop()
{
  temp = result/1000;
  Display_RPM = ~((1 << (8 - temp)) -1); 
  if(temp >= ShiftIndicator && flash(1000) == 1)
  {
    bitSet(Display_RPM, 0);
    Serial.println(Display_RPM, BIN);
  }
  else
  {
    Serial.println(Display_RPM, BIN);
  }
  delay(900);
}

Is there a better way todo this or is this ok? The useful thing is that i can use the flash routine for other things too.