Why is my for loop skipping out the final value

Context: I have attached 16 wires to my Arduino which I am storing in an array. The array in arduino looks like this:

    const char ADDR_PINS[] = {53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23};

i.e. digital pin 53 on the arduino is represents the MSB, and pin 23 represents the LSB

I simply want to print out the address on those pins every time I access a new address on a RAM chip I have on the breadboard.

PROBLEM: This is the for loop I have programmed to do so:


unsigned int address = 0;
  // prints the address on the address pins to Serial Monitor
  for (int i = sizeof(ADDR_PINS)-1; i >= 0 ; i--){ 
    int bit = digitalRead(ADDR_PINS[i]) ? 1: 0 ;
    Serial.print(bit);
    address = (address << 1) + bit;
  }

It should iterate through addresses one by one from 0x0000 and print the address bits out bit by bit to the serial monitor (I call this for loop from a different simple function).

However, I am encountering the issue that the LSB never changes and is constantly 0. This means only addresses with even numbers are being printed, and I can't figure out why. I have tried changing the limit of i in the for loop condition to

i > 0

which resolves the LSB problem, but then causes the exact same to happen to the MSB.

Thank you for your help

You are reading the pins in the wrong order.

You are starting at the LSB end (23) and ending with the MSB end (53) and shifting all the previous bits left before adding the new bit. That will put Pin 23 at the MSB and Pin 53 at the LSB.

Try:
for (size_t i = 0; i < sizeof ADDR_PINS; i ++) {

try this

#include <assert.h>
const byte addrPins[] = {53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23};
const byte nbPins = sizeof addrPins / sizeof * addrPins;
static_assert((nbPins <= 16), "too many pins. Max is 16");
static_assert((nbPins >= 1), "Not enough pins. Min is 1");
uint16_t previousAddress = 0;

void printAddress(uint16_t addr) {
  Serial.print(F("address :"));
  for (int b = nbPins - 1; b >= 0; b--) {
    Serial.print(bitRead(addr, b));
  }
  Serial.println();
}

uint16_t readAddress() {
  uint16_t sample = 0;
  for (int i = 0; i < nbPins; i++) {
    if (digitalRead(addrPins[i]) == LOW) bitSet(sample, nbPins-1-i); // INPUT_PULLUP so LOW means selected
  }
  return sample;
}

void setup() {
  for (byte p : addrPins) pinMode(p, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println(F("Ready"));
}

void loop() {
  uint16_t currentAddress = readAddress();
  if (currentAddress != previousAddress) {
    previousAddress = currentAddress;
    printAddress(currentAddress);
  }
}

the Arduino Bits and Bytes macros can come handy, see

bit()
bitClear()
bitRead()
bitSet()
bitWrite()
highByte()
lowByte()

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.