Arduino DigitalRead Generating Strange Results

Hi

I have some code that reads the digital pins on my arduino ( have tried on both uno and nano )

( Please note the code referencing the graphics drivers is there as my ultimate intention is to generate graphics output to my display based on the digital inpiut values received )

When i run the code below on the serial monitor without there being anything attached to any of the digital pins the code outputs to screen results indicating that the if condition for digital_4 input is true when in fact its not.

Just wondering if anyone can advise what may be the issue and steps to rectify

#include "U8glib.h"
U8GLIB_SSD1351_128X128_332 u8g(13, 11, 8, 9, 7);            // Arduino UNO: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, DC = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)

int digital_4= HIGH ;
int digital_5=HIGH ;
int digital_6=HIGH ;
int digital_7=HIGH ;
int digital_8=HIGH ;
int digital_9=HIGH ;
int digital_10=HIGH ;
int digital_11=HIGH ;

void setup() {
  //start serial connection
  Serial.begin(9600);
  //configure pin 4 as an input and enable the internal pull-up resistor
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);  
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  // pinMode(13, OUTPUT);

 
 // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }
}

void loop() {
  //read the pushbutton value into a variable
  digital_4 = digitalRead(4);
  digital_5 = digitalRead(5);
  digital_6 = digitalRead(6);
  digital_7 = digitalRead(7);
  digital_8 = digitalRead(8);
  digital_9 = digitalRead(9);
  digital_10 = digitalRead(10);
  digital_11 = digitalRead(11);


 if (digital_4 == LOW) {
  Serial.println("speed zones: 40");
  Serial.println();
   }
 else if (digital_5 == LOW) {
  Serial.println("speed zoned: 50");
  Serial.println();  
   }
 else if (digital_6 == LOW) {
  Serial.println("speed zoned: 60");
  Serial.println();   
  }
 else if ((digital_5 and digital_6)  == LOW) {
  Serial.println("speed zoned: 70");
  Serial.println();   
  }
 else if (digital_8 == LOW) {
  Serial.println("speed zoned: 80");
  Serial.println();   
  }
 else if (digital_9 == LOW) {
  Serial.println("speed zoned: 90");
  Serial.println();   
  }
 else if (digital_10 == LOW) {
  Serial.println("speed zoned: 100");
  Serial.println();   
  }
 else if (digital_11 == LOW) {
  Serial.println("speed zoned: 110");
  Serial.println();   
  }  

}
1 Like

Hey Claude,

This is a bit of a hardware limitation some microcontrollers have. “Unattached” is not the same as “grounded”

With nothing attached to the pin, it’s a floating voltage that varies randomly. If you want to make sure it’s low, attach a wire from the pin to ground (digital pin 14).

If you really want to see how it floats, try it on an analog pin and watch the value change as you move your hand closer and further away!

Ok so if I used code written for each pin I have a digitalRead I need have the relevant wire attached to the respective digital source. Or to put it another way comment out digitalreads in code until those pins actually have the respective digital output wires from the source attached ???

Claude Raiola
0414 228 948

Hi Claude,

I’m a bit unclear on what you’re asking but the answer to the question I think you’re asking is yes.

You need to have a well-defined voltage on the input pins, whether that’s 5v (Vcc) or 0v (Ground) - but it’s best not to tie these directly to Vcc or Ground without a current limiting resistor in the middle. If you set it to an output or forget to activate a pullup resistor accidentally you can get large currents through the pin.

Input voltages need to be below 0.3Vcc for digital low, or above 0.6Vcc for digital high: Preferably just 0v and 5v (Vcc). See page 258 on the datasheet.

I will try and clarify

I have a 12volt powered device that has 3 digital outputs

So I am attaching each digital output to a digital pin on arduino

Then my sketch will output specific info to my display depending on which digital output is outputting low, hence the of statements in the sketch.

Given the above do I still need to consider the pull-up resister ( which think is already embedded in the board arduino nano or uno )

Claude Raiola
0414 228 948

Hi Claude,

It wouldn’t hurt anything to connect the two boards through 1k current limiting resistors just as a bit of insurance against coding mistakes, but you could get away without it if everything’s implemented correctly.

I’ve also noticed that your code won’t work the way you expect to:

if (digital_4 == LOW) {
  Serial.println("speed zones: 40");
  Serial.println();
   }
 else if (digital_5 == LOW) {
  Serial.println("speed zoned: 50");
  Serial.println();  
   }
 else if (digital_6 == LOW) {
  Serial.println("speed zoned: 60");
  Serial.println();   
  }
 else if ((digital_5 and digital_6)  == LOW) {
  Serial.println("speed zoned: 70");
  Serial.println();   
  }

It will never print “speed zoned: 70”. If digital_5 is low, it will print “speed zoned:50”, then jump out of the if statements.

Regards,
Oliver
Support | Core Electronics

I assume the “12volt powered device that has 3 digital outputs” are 5V outputs.
The Arduino cannot tolerate 12V input. You would need to use a resistor divider to ensure the pin input never goes above 5V.

When specifying pins as input you can use pinMode(4, INPUT_PULLUP), this attaches a 30K to 60K resistor to the Arduino pin inside the chip. This ensures that the pin will be in a high state when read, if nothing is connected.

Owen is correct in the above post.
The code will never get to else if ((digital_5 and digital_6) == LOW) {
It will exit if digital_5 or digital_6 are LOW.

Cheers
Jim

1 Like

Hi regarding.

The code will never get to else if ((digital_5 and digital_6) == LOW) {
It will exit if digital_5 or digital_6 are LOW.

If have multiple digital outputs from the peripheral device.

So if digital output5 on peripheral connects to pin5 on arduino and
digital output6 on peripheral connects to pin6 on arduino were both output “low” at the same time why wouldn’t the above if condition work ???

Claude Raiola
0414 228 948

The problem is the logic of the nested if statements. I have rewritten the code to include all { } brackets and indented the statements. Hopefully this shows what is happening.

When digital_5 is LOW the the second if statement will be true and “speed zoned: 50” will be output. The else part of this if statement will be ignored and that includes the last if statement where digital_5 and digital_6 are checked.

For “speed zoned: 50” to be output, digital_5 = LOW and digital_6 = HIGH.
For “speed zoned: 60” to be output, digital_5 = HIGH and digital_6 = LOW.
For “speed zoned: 70” to be output, digital_5 = LOW and digital_6 = LOW.

Change if (digital_5 == LOW) to if ((digital_5 == LOW) and (digital_6 == HIGH))
Change if (digital_6 == LOW) to if ((digital_5 == HIGH) and (digital_6 == LOW))

if (digital_4 == LOW) {
  Serial.println("speed zones: 40");
  Serial.println();
} else {
  if (digital_5 == LOW)   {
    Serial.println("speed zoned: 50");
    Serial.println();  
  } else {
    if (digital_6 == LOW) {
      Serial.println("speed zoned: 60");
      Serial.println();
    } else {
      if ((digital_5 and digital_6)  == LOW) {
        Serial.println("speed zoned: 70");
        Serial.println();   
      }
    }
  }
}

Regards
Jim

PS I have tested the changes and all speed zones print correctly, including 70.

1 Like

Ohhh crap

Yes I see it now, one of the 2 conditions above would be met before it reaches the and condition option lol

Claude Raiola
0414 228 948

1 Like

Ok

So I have sorted the oversight re the I statement and assigned the pullup to the inputs

I have 3 digital outputs and when I connect any of them to any of the 3 digital inputs the output to the serial monitor is as it should be changing based on which condition is met in the if statements where there is 1 low and 2 high in the condition

However as soon as I try and add 2 or 3 outputs each to its own input to test the if conditions of (2 low’s and 1 high or 3 highs ) the output to the serial monitor is “-------“ which is the output for the condition of high high high

Spent hours trying to figure out why the multiple simultaneous input is not outputting based on the if conditions

Any words of wisdom would be appreciated

#include “U8glib.h”

U8GLIB_SSD1351_128X128_332 u8g(13, 11, 8, 9, 7); // Arduino UNO: SW SPI Com: SCK = 13, MOSI = 11, CS = 8, DC = 9, RESET = 7 (http://electronics.ilsoft.co.uk/ArduinoShield.aspx)

int digital_4;

int digital_5;

int digital_6;

// int digital_7;

// int digital_8;

//int digital_9;

// int digital_10;

// int digital_11;

void setup() {

//start serial connection

Serial.begin(9600);

//configure pin 4 as an input and enable the internal pull-up resistor

pinMode(4, INPUT_PULLUP);

pinMode(5, INPUT_PULLUP);

pinMode(6, INPUT_PULLUP);

//pinMode(7, INPUT_PULLUP);

//pinMode(8, INPUT_PULLUP);

//pinMode(9, INPUT_PULLUP);

//pinMode(10, INPUT_PULLUP);

//pinMode(11, INPUT_PULLUP);

// pinMode(13, OUTPUT);

// assign default color value

if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {

u8g.setColorIndex(255); // white

}

else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {

u8g.setColorIndex(3); // max intensity

}

else if ( u8g.getMode() == U8G_MODE_BW ) {

u8g.setColorIndex(1); // pixel on

}

else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {

u8g.setHiColorByRGB(255,255,255);

}

}

void loop() {

//read the pushbutton value into a variable

digital_4 = digitalRead(4);

digital_5 = digitalRead(5);

digital_6 = digitalRead(6);

//digital_7 = digitalRead(7);

//digital_8 = digitalRead(8);

//digital_9 = digitalRead(9);

//digital_10 = digitalRead(10);

//digital_11 = digitalRead(11);

if ((digital_4==LOW) and (digital_5==HIGH) and (digital_6==HIGH)) {

Serial.println(“speed zones: 40”);

Serial.println();

digital_4==HIGH;

}

else if ((digital_4==LOW) and (digital_5==HIGH) and (digital_6==LOW)) {

Serial.println(“speed zoneds 50”);

Serial.println();

digital_4==HIGH;

digital_6==HIGH;

}

else if ((digital_4==LOW) and (digital_5==LOW) and (digital_6==LOW)) {

Serial.println(“speed zoned: 60”);

Serial.println();

digital_4==HIGH;

digital_5==HIGH;

digital_6==HIGH;

}

else if ((digital_4==HIGH) and (digital_5==LOW) and (digital_6==HIGH)) {

Serial.println(“speed zoned: 70”);

Serial.println();

digital_5==HIGH;

}

else if ((digital_4==HIGH) and (digital_5==HIGH) and (digital_6==LOW)) {

Serial.println(“speed zoned: 80”);

Serial.println();

digital_4==HIGH;

digital_6==HIGH;

}

else if ((digital_4==HIGH) and (digital_5==HIGH) and (digital_6==HIGH)) {

Serial.println("—");

Serial.println();

}

// else if (digital_8 == LOW) {

// Serial.println(“speed zoned: 80”);

// Serial.println();

// }

// else if (digital_9 == LOW) {

// Serial.println(“speed zoned: 90”);

// Serial.println();

// }

// else if (digital_10 == LOW) {

// Serial.println(“speed zoned: 100”);

// Serial.println();

// }

// else if (digital_11 == LOW) {

// Serial.println(“speed zoned: 110”);

// Serial.println();

// }

}

Regards

Claude Raiola

0414 228 948

If you’ve only got two pins connected the third pin will always be high (that’s what the internal pullup is for - if it’s disconnected it will be high). Sounds like everything’s working as it should, just not how you expected :wink:

The code you have posted works. I tested it with all inputs, so this is not the problem.
A few comments:
The digital inputs are either HIGH or LOW (+5V or 0V) so the variables can be declared as bool not int.
(int takes 2 bytes of memory bool takes 1 bit.)
Statements like digital_5==HIGH; are not needed. Although they don’t make a difference to the output. Anyway == is a compare, = is an assign.

Suggestion.
Connect only switches to the inputs that allow you to set the input HIGH (+5V) or LOW (0V) and see what is happens. This will prove the micro and code are working correctly.

Use a multimeter to measure the voltage on the outputs of the device you are connecting to, but without the micro connected. This should allow you to determine the state you expect the code to respond to for a particular input.
For the digital inputs to register a LOW the level should be 0.3V or less, above 0.6V it should register a HIGH. As per the post from Oliver above.
Try a set up a static condition so the input is at a particular state for a while allowing a measurement to be taken.

Connect the inputs to the micro and measure the voltage again. If the measurements are not the same there is a loading problem. The digital inputs are high impedance and should not affect the device you are connecting.

From all this you should be able to get an idea of where the problem is.

Cheers
Jim

1 Like

Hi James,

Good advice on using switches to manually toggle the inputs! I’d again reiterate it’s a good idea to put 1k current limiting resistors in series with the switches as a bit of a safety belt (which should be connected to ground when using INPUT_PULLUP).

Note that this is 0.3Vcc (0.3 * 5V = 1.5V) and 0.6Vcc = 3V for Vcc=5v.

Regards,
Oliver
Support | Core Electronics

I have made the changes suggested re int to bool

Other than that the issues remain when I connect a digital output to one pin the relevant if conditions outputs but when I connect two digital pins to 2 inputs it still outputs as if the condition all 3 inputs are set to high just as when no inputs are connected.

image0.jpeg

Claude Raiola
0414 228 948

The digital output from the external device is a max of 1.5v according to manufacturers so is this why it want register high input on arduino ??? Given your comment ( Note that this is 0.3Vcc (0.3 * 5V = 1.5V) and 0.6Vcc = 3V for Vcc=5v.)

When I connect a led ( without any arduino involved ) and send a digital pulse from the device the led lights up as expected

Claude Raiola

0414 228 948

Very likely. Have you tried James’ suggestion of using switches? You could just stick some wires in the Arduino pins and ground them if you don’t have switches.

No I do not have any switches

Also found using a multi meter the digital output voltage varies regardless of it being active or not as per this clip

(Attachment Video.mov is missing)

image0.pngimage1.pngimage2.pngimage3.pngEx

Claude Raiola
0414 228 948

I had a look at the manual for the GV300W.
The digital outputs are open drain, capable of up to 150mA, enough to drive a relay or LED. (which the manual shows) The Arduino inputs consume maybe 0.1mA or less.

The pics of the multimeter do not give a clear indication of what is happening. Although it is easy to tell when the digital output is being driven, as the light is on. I suspect the output is floating when it is not being driven hence the low reading on the meter.

Also note the manual for the LED connection shows +8V to +32V as the supply, with a series resistor but does not state the value of the resistor. This would depend on the current needed to activate the LED. The typical current for a LED is 10 to 20mA with 30mA as maximum.

Given the above I suggest the following circuit be used.
When the GV300W digital output is OFF the 470 ohm resistor will pull the Arduino input high.
When the GV300W digital output is ON it will pull the Arduino input low.
The use of a 470 ohm will ensure the open drain output is driving some current. (approx. 10mA)

Image1

Regards
Jim

1 Like