Using multiple nibbles in Shiftout

Hi,
As part of a larger project I am currently using a 8 bit shift register to output signals onto 8 separate LEDs (Going to be an encoder in the future, but LEDs are easier to see/debug code with :slight_smile: ) I was able to define a byte of information and output it from the Arduino to the shift register. However, I am unable to I put two or more nibbles/bits together to form a usable byte while still keeping the prefix of "B" to define the output as binary. For example;

LEDout = B,Part1,Part2;
...
shiftOut(dataPin, clockPin, LSBFIRST, ShiftOut);

Where Part1 and Part2 are nibbles and B is the binary description, this returns the error "error: ‘B’ was not declared in this scope"

My schematic is exactly the same as Breadboard Layout | Arduino Lesson 4. Eight LEDs and a Shift Register | Adafruit Learning System Except from the fact that instead of using digital pins 4,5 &6, I use pins 11,13&12 respectively

This is my sketch currently used to understand the shift register and using nibbles as inputs;

int latchPin = 13;
int clockPin = 12;
int dataPin = 11;

byte Part1  = 0010;
byte Part2  = 0110;

byte LEDout = B00000000;

void setup() 
{
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  LEDout = B,Part1,Part2;
}

void loop() {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, LEDout);
  digitalWrite(latchPin, HIGH);
}

Does anyone have any idea on how I could form a single byte with the binary prefix from 2 (or more) nibbles (or bits)?

Thanks in advance,
Alex

However, I am unable to I put two or more nibbles/bits together to form a usable byte while still keeping the prefix of "B" to define the output as binary.

Then forget about the B. The B is a directive to the compiler to interpret the rest of the value as binary data. You already have binary data.

You store one nibble in the byte, shifting it 4 bits as you do so. Then, you simply add the second nibble.

PaulS:
Then forget about the B. The B is a directive to the compiler to interpret the rest of the value as binary data. You already have binary data.

I tried it without the B, using a single byte. If I used the byte 00101010 with the B, it showed as 00101010. However, without the B it showed up as 00001000 :~

PaulS:
You store one nibble in the byte, shifting it 4 bits as you do so. Then, you simply add the second nibble.

How do I add one nibble another? I tried separating them by a comma with no success, the same results when using a vertical bar.

LEDout = Part1,Part2;
LEDout = Part1|Part2;

PaulS:

However, I am unable to I put two or more nibbles/bits together to form a usable byte while still keeping the prefix of “B” to define the output as binary.

Then forget about the B. The B is a directive to the compiler to interpret the rest of the value as binary data. You already have binary data.

Not quite. 0b is the prefix that does that. B is the first character of a number of macros that equate to decimal values.

You store one nibble in the byte, shifting it 4 bits as you do so. Then, you simply add the second nibble.

byte val = (Part1 << 4) | Part2;
shiftOut(dataPin, clockPin, LSBFIRST, val);

Or, combined:

shiftOut(dataPin, clockPin, LSBFIRST, (Part1 << 4) | Part2);

majenko:

PaulS:
You store one nibble in the byte, shifting it 4 bits as you do so. Then, you simply add the second nibble.

shiftOut(dataPin, clockPin, LSBFIRST, (Part1 << 4) | Part2);

Thanks! That makes a lot more sense to me than it did previously, but I’m still slightly hazy as to how to implement the B prefix. :~

There is NO B prefix!

WHat is it you think you want to do with a mythical B prefix?

majenko:
There is NO B prefix!

WHat is it you think you want to do with a mythical B prefix?

I thought that the B was used to state that the following 8 bits were binary code and it has worked for my so far, without it the LEDs light up randomly and then settling on a certain sequence.

Using the line;

shiftOut(dataPin, clockPin, LSBFIRST, B10101010);

I repeatedly get the LEDs to light up in the pattern 10101010 (1 being on, 0 being off) without any peculiarities.

Using the line;

shiftOut(dataPin, clockPin, LSBFIRST, 10101010);

I get the LEDs to light up in a completely random order for a second, then every time it'll turn to 00010010.

As I said before, B is the first character of a set of #define macros that equate to decimal numbers:

#define B0 0
#define B00 0
#define B000 0
#define B0000 0
#define B00000 0
#define B000000 0
#define B0000000 0
#define B00000000 0
#define B1 1
#define B01 1
#define B001 1
#define B0001 1
#define B00001 1
#define B000001 1
#define B0000001 1
#define B00000001 1
... etc ...
#define B1010101010 170
... etc ...

So, by typing "B10101010" you are actually telling it the number 170, but by telling it 10101010 you are telling it the number ten million, one hundred and one thousand and ten. But that doesn't fit into 8 bits, so you end up with 18 (00010010).

So no, I still don't understand what you think you want to achieve with it...

What I want is for 2 nibbles of information to be bonded and then shown on 8 LEDs.
For example;
Nibble 1: 0110
Nibble 2: 1010

Bond to produce the byte 01101010 and then show up on the LEDs as 01101010 (Again, with 1 being on and 0 being off)

Unfortunately this does not follow through;

int latchPin = 13;
int clockPin = 12;
int dataPin = 11;

byte Part1  = 0110;
byte Part2  = 1010;

void setup() 
{
  Serial.begin(9600);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}

void loop() {
  Serial.println((Part1 << 4) | Part2);
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, (Part1 << 4) | Part2);
  digitalWrite(latchPin, HIGH);
}

The desired result with LEDs it 01101010, but what I actually get is 11110010 and the serial monitor says the integer of 1266, not a binary number. So what I think I want is to be able to use the define macro within the loop.

What you have to understand is that binary, decimal, and hexadecimal are just all human representations of the same patterns of on and off values in memory.

All of them represent the exact same value, and it’s just how they are displayed that is different.

The binary value 10101010 and the decimal value 170 are both the exact same thing.

Your two “nibbles” are just part filled bytes:

Part1 = 0b00000110
Part2 = 0b00001010

There is then an added complication of hidden casting in the serial print…

Build the two nibbles into a single byte first, it’s simpler to control it:

byte val = (Part1 << 4) | Part1;

What that’s doing is first shifting Part1 4 bits to the left, so it turns into:
0b01100000
Then it "or"s the second part with it:

01100000
00001010 OR
--------
01101010

And that value is 106 in decimal, so a Serial.print of it should give you 106.

majenko:

byte val = (Part1 << 4) | Part1;

What that’s doing is first shifting Part1 4 bits to the left, so it turns into:
0b01100000
Then it "or"s the second part with it:

01100000

00001010 OR

01101010



And that value is 106 in decimal, so a Serial.print of it should give you 106.

Thanks, now I completely understand what is happening to the current sketch, it’s correctly joining the two nibbles into one byte and proceeds to convert it to a decimal, it then gives the shift register that decimal number and it displays it onto the LEDs. I now understand that I don’t want the byte to be converted at all (I think) I require for it to stay expressed in a binary form so that the LEDs light up exactly as the two nibbles are put together.

There is no conversion. Decimal, as I said, is just a human representation of the patterns of on-and-off. Binary is the closest representation of that pattern, as it is a 1:1 relationship.

One thing I didn't notice, but now I have some beer in me I see it plain:

byte Part1  = 0110;
byte Part2  = 1010;

Those aren't binary numbers. Just because you are using 1 and 0 doesn't make it binary. Is the number 10 ten or one-zero binary? Or maybe 16 in hexadecimal?

The default base in C is base 10, so those numbers are one-hundred-and-ten and one-thousand-and-ten. So actually you are putting into the bytes the binary patterns:
Part1: 01101110
Part2: [11]11110010

The second won't fully fit into a byte, so the first two bits are discarded.

OR those two values together and you get:

01101110
11110010 OR
--------
11111110

If you want to specify the numbers as being binary in the first place, either use the non-standard macro definitions B1010 and B0110, or use the proper (or more proper - gcc specific, but most compilers are gcc these days) 0b1010 and 0b0110 notation.

There is no "conversions" happening between binary/decimal/hex. The following are exactly the same numbers but represented in different "bases" (Radix - Wikipedia):
int x=0b10011101; // binary number (base 2)
int x=157; // decimal number (base 10, what you have used to)
int x=0x9d; // hexadecimal number (base 16)
int x=0235; // octal number (base 8 )

Cheers, Jarkko

it's correctly joining the two nibbles into one byte and proceeds to convert it to a decimal

No. Forget "decimal". There in no such thing in C or C++. There is a "decimal representation" of a number (base 10).

it then gives the shift register that decimal number

It most certainly does not. The binary value is what is passed to the function. Computers only understand and deal with binary. All other representations are for people.

I now understand that I don't want the byte to be converted at all (I think) I require for it to stay expressed in a binary form so that the LEDs light up exactly as the two nibbles are put together.

I don't think you do understand that. But, it's true.

JarkkoL:
There is no "conversions" happening between binary/decimal/hex. The following are exactly the same numbers but represented in different "bases" (Radix - Wikipedia):

majenko:
There is no conversion. Decimal, as I said, is just a human representation of the patterns of on-and-off. Binary is the closest representation of that pattern, as it is a 1:1 relationship.

[/quote]

PaulS:

it's correctly joining the two nibbles into one byte and proceeds to convert it to a decimal

No. Forget "decimal". There in no such thing in C or C++. There is a "decimal representation" of a number (base 10).

Poor vocabulary on my part, I meant convert as in converting binary to decimal by keeping the numerical value, but changing for. i.e. Decimal 14 'converted' to Binary 1110
But, as you say, this is wrong, so I'll make sure never to express the change of representation base as 'convert' again. :slight_smile:

majenko:
One thing I didn't notice, but now I have some beer in me I see it plain:

byte Part1  = 0110;

byte Part2  = 1010;



Those aren't binary numbers. Just because you are using 1 and 0 doesn't make it binary. Is the number 10 ten or one-zero binary? Or maybe 16 in hexadecimal?

I assumed that by using the data type of 'byte' it would mark it as a binary number, like that of int (5.5234234...turns into 5, I thought the value gets turned into a usable value)

majenko:
If you want to specify the numbers as being binary in the first place, either use the non-standard macro definitions B1010 and B0110, or use the proper (or more proper - gcc specific, but most compilers are gcc these days) 0b1010 and 0b0110 notation.

I tried both B and 0b and they both work as I wanted, I just never stated that they were binary in the first place (Previous quote) Thanks you very much. :slight_smile:

PaulS:

it then gives the shift register that decimal number

It most certainly does not. The binary value is what is passed to the function. Computers only understand and deal with binary. All other representations are for people.

:blush: Yeah, I usually know that computers only operate in binary, I guess I must of just been not thinking things through as well as normal.

alexw2150:
I assumed that by using the data type of ‘byte’ it would mark it as a binary number, like that of int (5.5234234…turns into 5, I thought the value gets turned into a usable value)

No, a byte is merely an unsigned 8 bit number - anything between 0 and 255. It’s the same as an “unsigned char” or “uint8_t”. An int is a signed 16-bit number - anything between -32768 and 32767. Neither specify anything about how a number should be represented (other than signedness), they are merely defining the size of the storage slot the number gets put in.