Arduino Uno digitalRead does not work properly

Hi,

I am doing a binary counter project involving 74HC590 and Arduino Uno. The counter part works fine, only the output of the counter is a bit lower at 3.5V for high level. So I put a voltage level shifter for each bit, so that the Arduino would read either strong 5V or 0V. The only problem is that it does not... (wiring circuit is down bellow.) The voltage level shifter is an inverter, so in the code I invert the bits once again to get the real 74HC590 output. My digitalRead always return logic high, even when the voltage at that point is zero volts.

I have been checking my wiring, looking for floating or shorted or not connected pins and playing with the multimeter all day. From the hardware perspective, my circuit is flawless.

The problem is that no matter what the 74HC590 outputs and what the 2N2222 outputs as well, the reading of digitalRead is always high (before the software inversion of bits.) I can clearly see that my multimeter shows strong 0V at the collector of the 2N2222 which is directly connected to the Uno, but digitalRead answer stays high. If I physically unplug the wire and plug it straight to ground, then the answer becomes correct. This is literally driving me crazy, there is absolutely nothing between the emitter and ground. Why is that I always read logic high at the collector, even if the real voltage measured by multimeter is 0V?

You dont have have examine my code line by line, all the magic happens in the Timer_up() function.

#include <Wire.h>  
#include <LiquidCrystal_I2C.h>  

LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 rows

unsigned long Start = 0;
unsigned long Initial_value = 7000;  

volatile bool button_pressed = false;
bool Timer_on = false;
int Measuring_time;

//ISEJIMAI------------------------------------------------------------
const int Decoder_A0 = 10; 
const int Decoder_A1 = 19; 
const int Decoder_A2 = 12;                      

const int PWM = 11;

const int Timer_1_16_32_STOP = 18;

//IEJIMAI------------------------------------------------------------

const int button = 13; 

const int Time_block_1 = 14;
const int Time_block_2 = 15;
const int Time_block_3 = 16;
const int Time_block_4 = 17;

const int BIT_1  = 2; //LSB
const int BIT_2  = 3;
const int BIT_3  = 4;
const int BIT_4  = 5;
const int BIT_5  = 6;
const int BIT_6  = 7;
const int BIT_7  = 8;
const int BIT_8  = 9; //MSB
//-----------------------------------------------------------------

void setup() {
  Serial.begin(115200);
  lcd.init(); 
  lcd.backlight();
  lcd.print("Hi");
  Serial.print("Hello world.");

  pinMode(Decoder_A0, OUTPUT);
  pinMode(Decoder_A1, OUTPUT);
  pinMode(Decoder_A2, OUTPUT);

  pinMode(PWM, OUTPUT);
  digitalWrite(PWM, LOW);

  pinMode(Timer_1_16_32_STOP, OUTPUT);

  digitalWrite(Decoder_A0, LOW);
  digitalWrite(Decoder_A1, LOW);
  digitalWrite(Decoder_A2, LOW);
  digitalWrite(Timer_1_16_32_STOP, LOW);

  //------------------------------
  pinMode(button,INPUT);

  pinMode(Time_block_1,INPUT);
  pinMode(Time_block_2,INPUT);
  pinMode(Time_block_3,INPUT);
  pinMode(Time_block_4,INPUT);

  pinMode(BIT_1,INPUT);
  pinMode(BIT_2,INPUT);
  pinMode(BIT_3,INPUT);
  pinMode(BIT_4,INPUT);
  pinMode(BIT_5,INPUT);
  pinMode(BIT_6,INPUT);
  pinMode(BIT_7,INPUT);
  pinMode(BIT_8,INPUT);

}

void loop() {

  if (Timer_on  && (millis() - Start >= Measuring_time)) {
    Timer_on  = false;
    Timer_up();
  }

  if (digitalRead(button)){
  lcd.clear();
  lcd.print("Counting...");
  Serial.println("Counting...");
  Measuring_time=(((digitalRead((Time_block_1))*8)+(digitalRead(Time_block_2)*4)+(digitalRead(Time_block_3)*2)+(digitalRead(Time_block_4)*1))*Initial_value)+Initial_value;
  Start = millis();
  Timer_on  = true;
  button_pressed = false;
  }
                            //Dummy signal for the 74HC590 counter to count something
  digitalWrite(PWM, HIGH);
  delay(200);
  digitalWrite(PWM, LOW);
  delay(200);
  digitalWrite(PWM, HIGH);
  delay(200);
  digitalWrite(PWM, LOW);
  delay(200);
  digitalWrite(PWM, HIGH);
  delay(200);
  digitalWrite(PWM, LOW);
  delay(200);
  digitalWrite(PWM, HIGH);
  delay(200);
  digitalWrite(PWM, LOW);
  delay(200);

}

//----------------------------------

void Timer_up() { 

  uint32_t Rezultatas = 0;
  byte MSB = 0b0;
  byte UPPER8 = 0b0;
  byte LOWER8 = 0b0;
  byte LSB = 0b0;
 
  delay(1);
  digitalWrite(Decoder_A0, LOW);          //Selecting the 74HC590 chip, these 3 outputs work like a chip select in SPI or similar
  delay(1);
  digitalWrite(Decoder_A1, LOW);
  delay(1);
  digitalWrite(Decoder_A2, LOW);

  delay(1000);
  digitalWrite(Timer_1_16_32_STOP, HIGH); //Trigger for the 74HC590 to capture the most recent counter value to the registers and hold it
  delay(1000);                            //Extra long delays to be sure that none of the 74HC590 internal timings are violated

  LSB |= !digitalRead(BIT_1);
  Serial.println(digitalRead(BIT_1));

  LSB |=((!digitalRead(BIT_2)) << 1);
  Serial.println(!digitalRead(BIT_2));

  LSB |=((!digitalRead(BIT_3)) << 2);
  Serial.println(!digitalRead(BIT_3));

  LSB |=((!digitalRead(BIT_4)) << 3);
  Serial.println(!digitalRead(BIT_4));

  LSB |=((!digitalRead(BIT_5)) << 4);
  Serial.println(!digitalRead(BIT_5));

  LSB |=((!digitalRead(BIT_6)) << 5);
  Serial.println(!digitalRead(BIT_6));

  LSB |=((!digitalRead(BIT_7)) << 6);
  Serial.println(!digitalRead(BIT_7));

  LSB |=((!digitalRead(BIT_8)) << 7);
  Serial.println(!digitalRead(BIT_8));

  Serial.println(" ");

  lcd.clear();
  lcd.print(LSB);
  Serial.println(LSB);
}

Assuming I'm reading that code correctly you have too many pins assigned a purpose for an Uno.

0 and 1 are Serial.
2 through 19 are given constant identifiers used in your code.

Where is the LCD connected?

A 74HCT245 (with its minimum Vih of 2V) powered by 5V would give you 8 level shifting buffers in one DIP package. But I digress. You need to explain how you have your LCD hooked up on the I2C pins, but you then reuse the I2C pins as outputs (Decoder_A1 on 19 - A5/SCL and Timer_1_16_32_STOP on 18 - A4/SDA). It makes no sense to me.

A full schematic would clear things up.

Oh, then please ignore everything I said. If you know what the problem is and isn't then you certainly don't need help from anyone here.


I apologize, I removed the post as soon as I understood your point. It was my mistake, here is my D18/D19 wiring diagram.

Look at the pinout diagram.

A4 is the same pin as SDA. It's microcontroller pin PC4. See how A4 is also labelled SDA?

A5 is the same pin as SCL. It's microcontroll pin PC5. See how A5 is also labelled SCL?

They are the same pins, just brought out in two separate places.

SDA = A4 = D18
SCL = A5 = D19

They are clearly identified (in green) in the diagram, do you see it?

Use the pins to communicate with the LCD or use them for something else but not both.

On the other hand, all data is relevant if you want a solution, we are not fortune tellers.

Edit:
ATmega328 input level HIGH = Vcc * 0.6
So 5V * 0.6 = 3V, with 3.3V not need level shifters.
Anyway, GND of emitters is connected to GND of UNO, right?

To facilitate our understanding and be able to help you better, post a complete schematic of your project and give a brief description of how you expect it to work.

You are using an I2C LCD.

The I2C LCD is connected to the I2C pins of the arduino UNO.
The I2C pins of the UNO are pins A4 (18) and A5 (19).

But you are using pin 18 for something else along these lines:
" digitalWrite(Timer_1_16_32_STOP, HIGH);"

and you defined:
" const int Timer_1_16_32_STOP = 18; ".

So there will be conflict between this function, digitalWrite() , and I2C.

With that capacitor 220nF across the transistor you'll be lucky to get a usable signal if the input frequency exceeds about 500Hz.

EDIT
At 1kHz, the signal hardly reaches 1.5 volts:

1 Like

That's "impossible"! :wink:

Make sure the grounds are connected and when you measure with the measure, always measure relative to the Arduino's ground. If both voltages are zero (relative to the same ground) they will both read low. Unless the Arduino is fried, but readings would still be consistent or the Arduino wouldn't work at all.

BTW - With the circuit you've shown, it's OK to leave the transistor connected when you ground the Arduino input for testing. You are bypassing the transistor with a short and current flows through the 5.1K resistor. (There is no collector-emitter voltage or current... There is only the normal base-emitter voltage & current.)

...I was working on a board at work last week that had a "simple but impossible" problem. It was driving me crazy too!!! It took me a couple of days of on & off testing and experimenting and it turned-out to be an intermittent solder joint. Sometimes it was working and sometimes it wasn't but I was getting repeatable-illogical results just from the dumb-luck of the intermittent connections.

Alright, I removed the LCD screen completely and my problem is partially solved now (seems that the problem was over-definition of the pins D19 and D18). However, I still need that LCD screen, but I do not have any free pins left on my Uno except my D0 and D1 (Uart ones, those are free at the moment.) In theory I could bring back LCD to the 19 and 18, and move some of the digital pins to 0 and 1, but as far as I know, 0 and 1 have internal pull ups, so those are not suitable for anything but Uart. Is there any solution to keep my Uno and bring back the LCD? Thank you in advance.

IO expander? MCP23017? Shift register? 74HC595?
Either will get you more pins for signals.
You can use D0 and D1 as signals, but you will

  • not be able to use SerialMonitor for debugging
  • will need to disconnect at least those two signals in order to program.
2 Likes

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