Reading PORTB giving odd results using a NANO

I am reading PORTB and making only one Pin high at a time, so the first four inputs 8,9,10,11 this should represent 1/2/4/8.

However, I am ending up with intermediary numbers, see the results below.

00000000000000000000000000000011111111111111111111111111000000000000020000000040000000000000000000000000000000000000666666666640000000000000000000
-----------------

Here is my code, can someone explain, why this is happening, how to circumvent the issue.

   DDRB=0;
   while(1){

     Serial.print(String(PINB));
     delay(100);

   }

Where is setup() ?
Where is loop() ?
Where is Serial.begin() ?
What are intermediary numbers ?

There is a website for that: https://snippets-r-us.com/

Thanks for your reply,

Setup is empty other than Serial.begin(115200);

The code supplied is inside the loop and is the only code inside the loop.

As explained in my post, only one signal is being made at a time on Bit 0,1,2 or 3, therefore only 1,2,4 & 8 should appear. And also as provided in my post is a string of values output where you can see 66666 appears this should not be possible.

I hop this makes things clear.

You have to show the sketch that causes the problem. Now we have to guess what your sketch is, we have to guess what the problem is, and we have to guess what the solution is :woozy_face: Someone might start talking about a magic crystal ball. We use that to look into to see what you are not telling us :exploding_head:

This is a normal sketch, doing normal things, with a expected result:

// Forum: https://forum.arduino.cc/t/reading-portb-giving-odd-results-using-a-nano/1131576
// This Wokwi project: https://wokwi.com/projects/365868922987712513

// Note: When the crystal is used, the PORTB6 and PORTB7 pins are
//       internally disconnected. 
//       So it is okay to set DDRB for all bits.

void setup() 
{
  Serial.begin(115200);
  DDRB=0;
}

void loop() 
{
  byte x = PINB;
  Serial.print(x);
  Serial.print(",");
  delay(150);
}

Try the sketch in Wokwi:

1 Like

Do you have pull-down resistors on the pins, or are they allowed to “float” when they are not set “high”?

1 Like

You say you're only making one pin high at a time, but what are you doing with the other pins? If they're not tied to ground directly or through a pull-down resistor, they're floating and can read high or low randomly.

You might try using the built-in pull-up resistors as so:

  DDRB = 0; // input mode
  PORTB = 0x3F; // enable pull-ups in input mode

then pull one pin at a time low instead of high as before. You can invert the value read from PINB so you still see the 1, 2, 4, etc

  Serial.print(String(0x3F & ~PINB));

If I do not have a signal tied high, then the values are always zero ( not floating ) and can be measured as zero on an oscilloscope. And as I am looking for a high on the pin

This feels like a lag somehow in the values as you can see previous values being still held for example if I change from a 1 to a 2 then I end up with a 3 for a while even though 1 is removed prior to 2 being made high

The only thing different in your sketch is that you are using a byte and a slightly longer delay, but I need it to be faster than that.

At 115200, you can push 10000 char/sec through serial. With your code, the loop will take way less than 100 uS to loop. What do you think happens? Right, the serial output queue fills, and becomes a blocking code, limiting your throughput.

And, pay heed to the comments about inputs with no pullup/down. You're soon a victim of Murphy if you don't.

Push your serial to 1000000, set Serial Monitor to the same value, see if that gives you realtime response.

I know it is not to do with pull down because prior to this snippet this was being driven by a chip with only high or low and I was getting this problem so I generated small loop to test it manually.

void setup() {
  Serial.begin(115200);
  DDRB &= ~0b00111111;  // clear bits 0-5, leave bits 6-7 as is
}

void loop() {
  Serial.println(PINB, BIN);  // print all bits on PORTB
  delay(100);
}

The signal can always read 0 and still be floating.

Same thing happens ( I removed the BIN as I wanted one digit to represent) .

444444444444444444444444444444444401111111111111111111111111111111111111000000000000000000000011111111111111111111154444444444466666666222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221010222

As you see all looked ok until I got to the rogue bunch of six's this should have never been possible.

You have to be careful to not change bits 6, 7 of PORT B --

**PORTB** maps to Arduino digital pins 8 to 13 
The two high bits (6 & 7) map to the crystal pins 
and are not usable

DDRB - The Port B Data Direction Register - read/write
PORTB - The Port B Data Register - read/write
PINB - The Port B Input Pins Register - read only

This shows exactly that the pins float. They take time to go from high to low because there is no pull-down resistor. Therefore, the charge only flows off slowly through random current paths with very high impedance.

If you measure with a scope, your probe acts as the pulldown resistor - so you will measure zero.

Looks fine to me, the values seem to be "floating".

  • Grab six 10K resistors and use them to pulldown pins D8-D13 to GND, then run a test.
  • Then use them to pullup pins D8-D13 to 5V, then run a test.

Are the results stable?
Are the results what you expect?

The probes were on the signals when this was happening, so . . .

That does not make sense. If there were floating voltages which were high enough to cause a '1', then they would have been seen, they were not.

Ya know what, this is what I am going to do.

I'm going to feed port bits 4-7 into Port B bits 0-3 and cycle it, if that still shows me the problem then you might have a point and I will investigate.

It is okay to set the output mode and write to those bits. When a external crystal is selected, then those pins are disconnected from the registers. But I don't know if that is in the datasheet somewhere :dizzy_face:
The same for PortC. When the reset is used as a reset pin, then the whole 8 bits of PortC can be written and PortC6 and PortC7 are ignored.

@gelpack, you have not showed your sketch so far.
Can you show a photo of your project as well, so we can confirm that you have a classical Nano and that you don't have floating pins.

When you connect a oscilloscope to a pin, then you have changed something. A probe of a oscilloscope has a resistor of 1MΩ or 10MΩ to GND. A floating pin of a Arduino Nano has no resistor to GND, it has a input impedance of hundreds of MegaOhms to something/nothing, but not to GND.

In the simulation I have slide switches to be sure that a input is not floating. That works.

Yes but you are missing my point, regardless of the probes impedance, if the logic level was high enough to be seen as a HIGH on the input, this would have been seen on the scope.

Anyway, lets pause this topic, because I want to do some more experimentation and then I will come back.

Thanks for all your input to everyone.

You show what you have, we tell you what's wrong, you fix it, everyone is happy.