Read Nibble

Hi.

I have a problem that should be really straight forward.

I'm building a line following robot. In front of the robot I have four LDR-sensors connected to a LM324 comparator chip. I would like to read the input from the comparator as a Nibble. I would then like to read them as binary numbers so I can make a if - then statement like this one.

If sensorreading = 0100 then
Do.....
elseif sensorreading = 1100 then
do....

See the picture?

I can't seem to find out how to do the programming of this.

If someone could help me with this it will be very appreciated.
Out of curiosity I would like to know hot to send out a Nibble as well.
Like if I want to control a BCD to 7-segment driver....

Thanks in advance.

I can't seem to find out how to do the programming of this

I can't seem to see how your Arduino is wired.

I can figure out the wiring myself. I want the arduino to be wired after the code not vice versa. Said in a different way: I would like the programming to be as simple and logical as possible, and make the wiring to fit the code.

Your question is a little bit hidden; there is no such thing as a "nibble"... Presumable you want to shift four input bits into a byte. Your second question is most likely how to shift 4 bits from a byte out on 4 different lines?

input = digitalRead(ldr0) + (digitalRead(ldr1)<<1) + (digitalRead(ldr2)<<2) + (digitalRead(ldr3)<<3);
digitalWrite(bcd0, output&1);
digitalWrite(bcd1, output&2);
digitalWrite(bcd2, output&4);
digitalWrite(bcd3, output&8);

Ther are also "cleaner" solutions...

Depending on your programming experience, there are the bitWrite, bitRead etc functions, or there are bit OR operations with shifts.
Arduino also has handy binary constants defines, if you're not comfortable with hex.

there is no such thing as a "nibble"

Don't listen to him. He'll tell you the tooth fairy is a myth too.

By Nibble I mean half a byte....
And yeah, I want to shift four input bits into a byte.

How would the Byte look like If I use deSilvas solution? Would it be only four bits long or will I have a byte similar to this: 00001111?

DeSilva: Could you give me the "cleaner solutions"?

Four bits are not addressible by the processor, so yes, your byte would look like 00001111.
Is that a problem?

I like Desilva solution....

However, could someone show me how to make a simple if - then statement?

Like

if input = 0110 then
MoveForward()
elseif input = 0100
MoveLeft
End if

Would it be more "correct"/simple to use an array for the input sensors and then somehow convert it into a byte afterwards?

AWOL:

I think it's a problem. I should be able to get rid of the four bits by using the "lowByte" function right?

If you're willing to make the HW follow the SW, then you can do:

nibble = PINB & 0xF;

Where your sensors are connected to digital pins 8 through 11.
This is "pure AVR programming" and not Arduino libraries any more, but I think it's a bit silly to go the lengths some people are suggesting unless there is a particularly good reason (like, say, needing to mix bits from different ports, or be portable to Mega, or...) It's not like the mishmash using digitalRead() is actually any easier to understand by the time you're done, and it's WAY slower and bigger.

I think it's a problem

I'm really struggling to see why.

Because I would like to make a simple if - then statement that decides how the robot should move depending on the sensor input.

I think it's easier to understand the code if I know that 0001 means that the line is at the rightmost sensor and if it's 0010 the line is under the third sensor and so on....

Could I use an integer variable instead of a Byte?

Have you looked at the binary constants that the Arduino environment defines for you?

(and no, I don't understand the problem here)

This

if input = 0110 then
MoveForward()
elseif input = 0100
MoveLeft
End if

will become the following C program which should most likely even work:

if (input == 0B0110) 
  MoveForward();
if (input == 0B0100)
  MoveLeft();

Thanks guys...

Groove: Which binary constants?

Two more questions....

  1. How do I get rid of the four bits of the byte by using the low/high-byte function?

  2. In this code....
    if (input == 0B0100)

Why do you put a "0" in front of B???? Are there a place where I can read about working with binary numbers with the Arduino.

I agree with Richard about using the "B" notation: it's a violation of standard C/C++, and confusing.

Better practice is something like this (assumes you have sensors connected to D4 through D7):

#define HARD_LEFT     0x80
#define SLIGHT_LEFT     0x40
#define SLIGHT_RIGHT     0x20
#define HARD_RIGHT     0x10
#define SENSOR_MASK  0xf0

...

    sensors = PIND & SENSOR_MASK;
    switch (sensors)
        {
        case HARD_LEFT:
                        // Do left stuff
            break;
        case SLIGHT_LEFT:
                        // Do left stuff
            break;
        case SLIGHT_RIGHT:
                        // Do right stuff
            break;
        case HARD_RIGHT:
                        // Do right stuff
            break;
        default:
                        // Do "no sensor on" stuff
        }

That makes your code easier to read, helps avoid hard-to-spot typos (like typing "3" instead of "2"), and opens up other possibilities. E.g., if the field of view of your sensors overlaps, you can do something like

#define CENTERED  0x60

to define a case where two sensors are on at once.

Thanks again.

It's nice to see how you guys solves these kind of things.
I really like the coding examples.

Yet, I have a hard time understanding why Hex should be easier to understand. I get confused by Hex-numbers. When I look at hex I have to convert it in my head. First do dec and then to binary. Otherwise I can't really imagine where the line is :-[

When I look at something like 1000, then I know that the line is all to the left. I can do that really quickly.

One line of the code in the example above seems a bit strange to me:

sensors = PIND & SENSOR_MASK;

Wouldn't the Arduino read digital pins 0 to 7 If I use a PIND command and store them in the byte "sensors"?

Can't I use digital pin 1,2 and 3 as outputs then?

What exactly happens here: PIND & SENSOR_MASK?
What will the Sensor byte look like in Binary afterwards if I read a 0x80 from the sensor and add the SENSOR_MASK?

Thanks in advance

The B notation is not a violation, otherwise the compiler would reject it.
It may not be in the spirit of C, but may be useful for some, with appropriate caveats.

When I look at hex I have to convert it in my head. First do dec and then to binary.

No the whole point about hex is that it is easy to convert directly into binary in your head. Practice, write out a list of hex numbers from 0 to f and along side write the binary. No need for decimal.

When I look at something like 1000, then I know that the line is all to the left. I can do that really quickly.

Yes and that is hex 0x8 - I can do that in my head

sensors = PIND & SENSOR_MASK;

This is anding together two numbers, Anding is a way of removing selected bits from a bit pattern (number) - a zero in a pit position of the mask wipes out the effect of a logic one in the number PIND. For a good discussion see:-
http://www.arduino.cc/en/Reference/PortManipulation

Can't I use digital pin 1,2 and 3 as outputs then?

I don't follow?

Thank you very much for the patience and the good answers :slight_smile:

What happens if I have digital pin 1, 2 and 3 set as outputs and I make the:

Sensors = PIND

Wouldn't it try to read on digital pin 0 - 7? I only use four of these pins(D4 - D7)...

Will I only have four bits stored in my variable after the "anding" with SENSOR_MASK?