Pages: [1] 2   Go Down
Author Topic: Bitshift help.  (Read 1224 times)
0 Members and 1 Guest are viewing this topic.
Scunthorpe, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all,

Code:
//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.
« Last Edit: September 30, 2012, 12:13:26 pm by Pavilion1984 » Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
   b = 1 << 1 | 1;

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

Try this:
Code:
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.
Logged

Scunthorpe, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 ?
Code:
byte ArrayRPM[8] =
{
  B00000000,
  B10000000,
  B11000000,
  B11100000,
  B11110000,
  B11111000,
  B11111100,
  B11111110,
  B11111111,
};
« Last Edit: September 30, 2012, 01:27:41 pm by Pavilion1984 » Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
[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:
Code:
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]
Logged

Scunthorpe, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you, you have been most helpfull and i understand now.
Quote
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.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 626
Posts: 34143
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

To replace:-
Code:
temp = result/1000;
  for(byte i = 0; i < temp; i++)
  {
    b = 1 << 1 | 1;
  }
How about
Code:
temp = result/1000;
b = (1 << temp) -1; 
Logged

Scunthorpe, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Does this work?

Code:
b = ~((1 << (8-temp)) -1);
Logged

Scunthorpe, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Scunthorpe, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
1<<5 = 00100000
00100000 -1 = 00011111
~00011111 = 11100000
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 626
Posts: 34143
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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

Code:
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);
Logged

Scunthorpe, UK
Offline Offline
Full Member
***
Karma: 0
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 626
Posts: 34143
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1] 2   Go Up
Jump to: