ATMega 328p, digitalRead not low

Hi Folks. I have an issue where I’m trying to read some digital pins and their voltages aren’t quite low enough. I’m looking for suggestions.

Here’s the story:

I’ve built a split keyboard so I’ll just describe one of them but both behave the same.

I had a PCB manufactured. It uses an Atmega328. Pins 0 through 4 are set as outputs and set high. They are my rows. And I’m not using pin 0 to receive anything so I believe this is okay.

I’m using analog pins 0 through 5 as digital inputs with the internal pull up set. These are the columns.

I have an outer loop that sequentially sets each row to low. I have a nested loop that runs through each column then tries a digitalRead on the corresponding pin. If it’s LOW, then I know that the key at the corresponding row and column has been pressed.

Now all of this works great for most of the keys except those furthest from the MCU. When I probe these with an oscilloscope, I can see a nice square wave with the voltage drop to a bit above 3V. The other keys, the ones that work, drop a bit further - just below 3V which is evidently enough to be read as LOW.

If I do an analogRead rather than digitalRead, and check if the value is less than 900, all the keys work but it all becomes too slow after I add logic to handle modifier keys (shift, ctrl, etc.).

I wonder if the diodes by each key may have too high a resistance - preventing the pins from dropping low fast enough. The diodes are 1N4148s. They are there to prevent ghosting.

I’ve also fiddled with setting the output pins’ bits directly to speed things up (rather than use the digitalWrite) but haven’t figured out how to do a similarly fast read of the analog pins.

Other stuff:

I use a 5V voltage regulator.
16MHz oscillators with a couple of 22uF diodes
A couple of 220uF electrolytic caps between the main rail and ground
The keyboard is using the Bluefruit LE Friend to interface with my computer/iPad.

Given that I already have these PCBs made, introducing an op amp or other complex set of components may be problematic. What might I try to get this working just right? Should I fiddle with the Avcc or ARef perhaps?

FYI, I’ve been learning electronics since around January so please pardon my ignorance. Thanks for your time.

Sorry folks, I posted this again because I didn't think this original had actually gone up.

Post schematic. Why is the voltage not dropping to near zero?

" The other keys, the ones that work, drop a bit further - just below 3V which is evidently enough to be read as LOW."
Reading a LOW output from another pin should be much lower - <1.5V. Unless there is too much pullup resistance and the pin can’t sink enough current.

Can you check that you have pinMode (pinX, OUTPUT); in setup() for the row pins?

Thanks for your interest DrAzzy, you too CrossRoads.

DrAzzy:

Why is the voltage not dropping to near zero?

Yes, that is the question. Dunno.

I’ve attached a screenshot of one of the keyboards. The rows are those wires going over the top of the keys. The columns are those attached to the diodes.

CrossRoads:

See near the bottom of the setup method… I have both INPUT and INPUT_PULLUP here but I’ve tried it with just INPUT_PULLUP. No difference. colPins is an array with values 14 through 19 which I understand correspond to analog pins A0 through A5.

void setup(void)
{

if ( !ble.begin(VERBOSE_MODE) )
{
error(F(“Couldn’t find Bluefruit, make sure it’s in CoMmanD mode & check wiring?”));
}

if ( FACTORYRESET_ENABLE )
{
if ( ! ble.factoryReset() ) {
error(F(“Couldn’t factory reset”));
}
}

ble.echo(false);

ble.info();

if (! ble.sendCommandCheckOK(F( “AT+GAPDEVNAME=ICC Left Keyboard” )) ) {
error(F(“Could not set device name?”));
}

if ( ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) )
{
if ( !ble.sendCommandCheckOK(F( “AT+BleHIDEn=On” ))) {
error(F(“Could not enable Keyboard”));
}
} else
{
if (! ble.sendCommandCheckOK(F( “AT+BleKeyboardEn=On” ))) {
error(F(“Could not enable Keyboard”));
}
}

if (! ble.reset() ) {
error(F(“Couldn’t reset??”));
}

for (int i = 0; i < ROWS; i++)
{
pinMode(rowPins*, OUTPUT);*
_ digitalWrite(rowPins*, HIGH);_
_
}_
_
for (int i = 0; i < COLS; i++)_
_
{_
_ pinMode(colPins, INPUT);_
digitalWrite(colPins, INPUT_PULLUP);
_ }
}

*_

for (int i = 0; i < ROWS; i++)
{
pinMode(rowPins, OUTPUT);
digitalWrite(rowPins, HIGH);
}

for (int i = 0; i < COLS; i++)
{
pinMode(colPins, INPUT);
digitalWrite(colPins, INPUT_PULLUP);
}

This is wrong.

I don’t know what you’ve declared colPins and rowPins as so I can’t give further help (this is why we don’t like when people post snippets!) - but there’s no way that this will result in setting pinMode on each of them, because you are passing identical arguments to pinMode and digitalWrite every time around the loop!

Hi again Crossroads, in case you spot this:

for (int i = 0; i < ROWS; i++)
{
pinMode(rowPins, OUTPUT);
digitalWrite(rowPins, HIGH);
}

for (int i = 0; i < COLS; i++)
{
pinMode(colPins, INPUT);
digitalWrite(colPins, INPUT_PULLUP);
}

You’ll note I’m missing the index in the array. I just copied that snippit of code from the wrong place this is the version I’m testing:

for (int i = 0; i < ROWS; i++)
{
pinMode(rowPins*, OUTPUT);*
_ digitalWrite(rowPins*, HIGH);_
_
}_
for (int i = 0; i < ROWS; i++)
_
{_
_ pinMode(rowPins, OUTPUT);
digitalWrite(rowPins, HIGH);
}*_

In both cases, the [i]
is missing. Or the forum stripped it off because you didn’t use code tags.

for (int i = 0; i < ROWS; i++)
 {
   pinMode(rowPins[i], OUTPUT);
   digitalWrite(rowPins[i], HIGH);
 }

 for (int i = 0; i < COLS; i++)
 {
   pinMode(colPins[i], INPUT);
   digitalWrite(colPins[i], INPUT_PULLUP);
 }

Okay my bad. The missing indexes in the arrays is because of this site’s parser. I didn’t use the code tags mentioned in the Read Me page.

The indexes were there when I pasted my code. So yes, I wholly understand. I’m a professional programmer so I ought to. Let’s see if this is works:

for (int i = 0; i < ROWS; i++)
  {
    pinMode(rowPins[i], OUTPUT);
    digitalWrite(rowPins[i], HIGH);
  }

  for (int i = 0; i < COLS; i++)
  {
    pinMode(colPins[i], INPUT);
    digitalWrite(colPins[i], INPUT_PULLUP);
  }

Hi Crossroads,

You said:

Reading a LOW output from another pin should be much lower - <1.5V. Unless there is too much pullup resistance and the pin can’t sink enough current.

And in my original post I said:

I wonder if the diodes by each key may have too high a resistance - preventing the pins from dropping low fast enough. The diodes are 1N4148s. They are there to prevent ghosting.

These diodes are reading about 0.592 Ohms on my multi-meter. And the keys furthest away from the MCU are going through 5 of them. That’s about 3 Ohms total. It sounds like this is my problem, no? If so, what to do about it?

Is there a better diode than the 1N4148 - which is the one I’ve read as being recommended because it’s “fast”.

I don't think your button/diode design is correct then. I gotta run, I'll try and look at that later tonight.

Oh! There's your problem. The diodes are wired wrong - you're getting caught by the 0.7v drop across each diode.

You shouldn't have the signal going through more than one diode, ever. The column line should be connected directly to each of the 5 diodes, instead of being chained like you have them.

Time for a respin (or some patient work with a razor blade and soldering iron on your prototype)

Yup. I screwed it up alright - put those diodes in series. I think I can fix it.

This was my reference and certainly I did it wrong. How to make a keyboard – the matrix | komar's techblog

Thank you kindly for your help.