can anyone help me solve code not working

Hello. I am a noob at this stuff so bear with my bad code. I am making a simple project where four buttons control the placement of a custom character on an LCD screen. However, even when I don’t push the buttons, the character moves on the screen in ways I don’t want it too. The buttons don’t even work when I press them. Any ideas why?

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
int x = 0;
int y = 0;
int up = 2;
int right = 3;
int down = 4;
int left = 5;
byte Man[] = {
  B00100,
  B01010,
  B00100,
  B01110,
  B10101,
  B00100,
  B01010,
  B10001
};

void setup() {
  Serial.begin(9600);
pinMode(up, INPUT);
pinMode(left, INPUT);
pinMode(down, INPUT);
pinMode(right, INPUT);
pinMode(12, OUTPUT);
digitalWrite(12,HIGH);
  lcd.init();
lcd.backlight();
lcd.createChar(1, Man);
  lcd.setCursor(x,y);
lcd.write(1);
}
void loop() {

  lcd.setCursor(x,y);
lcd.write(1);
if(digitalRead(down) == 1 and y < 3){
y--;

}

if(digitalRead(up) == 1 and y > 0 ){
y++;



}

if(digitalRead(left) == 1 and x > 0){
x--;



}

if(digitalRead(right) == 1 and x < 19){
x++;


}
delay(1000);
Serial.println( x );
Serial.println( y );

}

Please help me fix this, its very frustrating.

The buttons don't even work when I press them.

Without looking at the logic of the sketch yet, I see your button pins are pinMode()-ed as input, and that you look for a 1 as a press. That means they should have pull down resistors to guarantee they are actually low until the button takes the pin high.

Tell us how the buttons are wired, and especially, do you have pull down resistors?

And PS, when you realise something like "the buttons don't even work when I press them" it's time to run a separate sketch that does nothing other than test a button, like this tutorial.

Without a schematic we would only be guessing.
Post your schematic in CAD or a picture of a hand drawn circuit in jpg or png- (PLEASE, not a pretty Fritzing drawing).

okay, so I tested each button with an LED, and they all work. Ive made a schematic of what I made. The LCD is I2c, so I didn't connect it on the schematic. I dont exactly know what a pull up resistor is. I know how to enable it, but I don't know what it does. Thanks for the help.

It’s difficult (that is to say, impossible) to tell from that postage stamp if you have external resistors for that test, so perhaps you enabled the internal pulllups for the test?

But they’re not enabled in the original code…

So, tell us if there are pullups (external or internal) or pulldowns (external) in the mix, and if your test rig and code differ from the actual, since you said orginally the buttons didn’t work yet now they do…

Your "schematic" is too small to view.

Here is how to upload an image: https://forum.arduino.cc/index.php?topic=364156.0

A Fritzing picture is NOT a schematic. But if it's all you have.....

Lol sorry I didn’t see how the image turned out. I attached the image below. My buttons are sending signals, but the code isn’t running them properly. I changed the code a little bit, so here it is again. sorry if I’m being really dumb, I don’t exactly know what some of the words you guys are using mean. Thanks.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
int x = 0;
int y = 0;
int up = 2;
int right = 3;
int down = 4;
int left = 5;
byte Man[] = {
  B00100,
  B01010,
  B00100,
  B01110,
  B10101,
  B00100,
  B01010,
  B10001
};

void setup() {
  Serial.begin(9600);
pinMode(up, INPUT_PULLUP);
pinMode(left, INPUT_PULLUP);
pinMode(down, INPUT_PULLUP);
pinMode(right, INPUT_PULLUP);
pinMode(12, OUTPUT);
digitalWrite(12,HIGH);
  lcd.init();
lcd.backlight();
lcd.createChar(1, Man);
  lcd.setCursor(x,y);
lcd.write(1);
}
void loop() {
lcd.clear();
  lcd.setCursor(x,y);
lcd.write(1);
if(digitalRead(down) == LOW and y < 3){
y--;

}

if(digitalRead(up) == LOW and y > 0 ){
y++;



}

if(digitalRead(left) == LOW and x > 0){
x--;



}

if(digitalRead(right) == LOW and x < 19){
x++;


}
delay(1000);
Serial.println( x );
Serial.println( y );

}

Sorry for using fritzing, I can make a cad one if you want. When I made the buttons INPUT_PULLUP, It stopped the custom character from moving all around the screen, but now none of the buttons affect the character.

Maybe you dont get what pullup does, it means that your input stays high or true or logic "1" while nothing its connected to that pin, so to change it to "0" or false or low, you must connect it to ground, ie a button that toggles to GND.

You current code works for me, almost.

So I changed the y-- and y++ around though, since moving down a row in human terms is actually incrementing the line number since the top row (as seen by human) is 0, and the row below that is 1.

Disclaimer, I use a:

  • different LCD I2C library
  • 16x2 screen

(And of course as edpsycho says, with input pullup the button needs to go to ground.)

Okay, ive editted the code and the setup and Ive managed to make the left and right controls work. Ill put the new code and diagram below, and sorry I’m gonna use a fritzing because it easiest.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
int x = 0;
int y = 0;
int up = 5;
int right = 4;
int down = 3;
int left = 2;
byte Man[] = {
  B00100,
  B01010,
  B00100,
  B01110,
  B10101,
  B00100,
  B01010,
  B10001
};

void setup() {
  Serial.begin(9600);
pinMode(up, INPUT_PULLUP);
pinMode(left, INPUT_PULLUP);
pinMode(down, INPUT_PULLUP);
pinMode(right, INPUT_PULLUP);
pinMode(12, OUTPUT);
digitalWrite(12,HIGH);
  lcd.init();
lcd.backlight();
lcd.createChar(1, Man);
  lcd.setCursor(x,y);
lcd.write(1);
}
void loop() {
lcd.clear();
  lcd.setCursor(x,y);
lcd.write(1);
if(digitalRead(down) == LOW and y < 3 and y != 0){
y++;

}

if(digitalRead(up) == LOW and y > 0 ){
y--;



}

if(digitalRead(left) == LOW and x > 0){
x--;



}

if(digitalRead(right) == LOW and x < 19){
x++;


}
delay(100);
Serial.println( x );
Serial.println( y );

}

Your down won’t work from the start position, since y is 0 to start (top row) and you only do a y++ when y isn’t 0…

if(digitalRead(down) == LOW and y < 3 and y != 0){
y++;

}

here is the new fritzing image. Also I removed the “y != 0,” but it still wont go down.

|500x187

Why have you got pulldown resistors when you have pinMode(, INPUT_PULLUP)?

Lose the resistors.

I GOT IT TO WORK… mostly! I dont even know what I did, I just took out the resistors and put them back in. The problem is that whenever the character goes into the first collum or fourth row, it immediately gets pushed back into the 2nd collum of third row. Any ideas why? Thank you guys so Much for the help, I can stress it enough.

Ok hang on, I just enlarged that latest pic, and you have the button to 5V it seems.

So not only lose the resistors, but put the button from the pin to ground. Then the pin will be high when the button is left alone, and go low when it's pressed.

Okay, I did what you said. I found a solution to the problem on my last post, but the program has a bug. If you try and go left off the screen on row 3 or 4 (the codes row 3 and 2), it will temporarily show the character on the rightmost side of row 2 or 1.

Probably need to look at the numbers in those < and > at the edges? Remember the columns are numbered 0 to 19 inclusive (20 columns) and the rows are 0 to 3 inclusive (4 rows).