Vending Machine Project, LCD No Work :(

Hi guys,

Take it easy on me please, I am very knew to the tinkering and electronic field in terms of Arduino projects. So I wanted to make a Arduino Uno based vending machine.

I have taken a design from Gabriel, full credit to him. On Hackaday ( Mini vending machine | Hackaday.io ) and made it more specialized for Arduino Uno, this was very stupid of me, but I want to learn so I have thrown myself into the middle of it. Unfortunately when I connected my LCD today, I discovered the black box display problem, I tried many solutions including switching data ports etc. but had no luck and thought it was time to consult the many wise humans on this forum.

I have no idea whether its related to using the analogue ports on my Arduino, or something to do with the trim pot, but I am exhausted and know somebody here will have much more of an idea then me

I have attached my pcb file, schematic and code, so y'all can have a field day. Any help is welcome and I am open to being scolded, as I know that this project is a real mess.

Have a lovely day or night wherever you may be, and thanks for any help :blush:,
If y'all need anything more leave a reply and I'll attach more things.



CODE BELOW IN A SEPERATE REPLY

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

Please post your full sketch, using code tags when you do

Posting your code using code tags prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

It is also helpful to post full error messages in code tags as it makes it easier to scroll through them and copy them for examination


```cpp
#include <Servo.h>
#include <LiquidCrystal.h>
#include <SPI.h>
#include <MFRC522.h>
#include "vm.h"

#define SS_PIN 7
#define RST_PIN 8

#define KEY A1
#define HALL A0

#define LOCKER 3
#define M2 5
#define M3 6
#define M4 9
#define M5 10
#define LCD_RS 4
#define LCD_EN 2
#define LCD_D4 A2
#define LCD_D5 A3
#define LCD_D6 A4
#define LCD_D7 A5

#define ERR_DEBUG 1
#define CARD_DEBUG 1

#define STANDBY 0
#define LOGIN 1
#define PASS 2
#define CHECK 3
#define SELECTION 4
#define DELIVERY 5
#define MAINT 6

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance.
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
int state = STANDBY;
int count = 0;
int login[4];
int pass[4];
int selected_user;
int item;
unsigned long timer;

struct user {
  String login;
  String pass;
  int credits;
  String uname;
  String card;
  int length_card;
};

user users[5];

char ButtonPrint(int print_or_not);
int CheckLogin();
void CreateUsers();

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Starting vending machine system...");
  SPI.begin();         // Initiate  SPI bus
  mfrc522.PCD_Init();  // Initiate MFRC522
  StartVendingMachine(M2, M3, M4, M5, HALL, LOCKER, KEY);
  lcd.begin(16, 2);
  lcd.print("VENDING MACHINE");
  lcd.setCursor(1, 1);
  lcd.print("OPEN PROJECT");
  delay(2000);
  CreateUsers();
}
void loop() {
  switch (state) {
    case STANDBY:
      lcd.clear();
      lcd.print("ENTER YOUR LOGIN");
      lcd.setCursor(5, 1);
      lcd.print("TO BUY");
      while (state == STANDBY) {
        if (Button() != -1) state = LOGIN;
        if (mfrc522.PICC_IsNewCardPresent()) {
          mfrc522.PICC_ReadCardSerial();
          state = CHECK;
        }
        lcd.setCursor(0, 0);
        if ((millis() >> 12) & 1) {
          lcd.print("ENTER YOUR LOGIN");
        } else {
          lcd.print(" TAP YOUR CARD  ");
        }
      }
      break;
    case LOGIN:
      lcd.clear();
      lcd.print("LOGIN:");
      lcd.setCursor(12, 0);
      lcd.print("XXXX");
      lcd.setCursor(12, 0);
      count = 0;
      while (state == LOGIN) {
        if (Button() != -1) {
          ButtonPrint(true);
          login[count] = ButtonPrint(false);
          count++;
          while (Button() != -1)
            ;
          delay(50);
          timer = millis() + 4000;
        }
        if (count >= 4) state = PASS;
        if (timer < millis()) state = STANDBY;
      }
      break;
    case PASS:
      lcd.setCursor(0, 1);
      lcd.print("PASSWORD:");
      lcd.setCursor(12, 1);
      count = 0;
      while (state == PASS) {
        if (Button() != -1) {
          lcd.print("*");
          pass[count] = ButtonPrint(false);
          count++;
          while (Button() != -1)
            ;
          delay(50);
          timer = millis() + 4000;
        }
        if (count >= 4) state = CHECK;
        if (timer < millis()) state = STANDBY;
      }
      break;
    case CHECK:
      selected_user = CheckLogin();
      if (selected_user >= 0) {
        lcd.clear();
        lcd.setCursor(5, 0);
        lcd.print("HELLO");
        lcd.setCursor(0, 1);
        lcd.print(users[selected_user].uname);
        delay(2000);
        if (selected_user == 0) {
          state = MAINT;
          break;
        }
      } else {
        lcd.clear();
        lcd.setCursor(5, 0);
        lcd.print("WRONG");
        lcd.setCursor(1, 1);
        lcd.print("USER/PASSWORD");
        delay(2000);
        state = STANDBY;
        break;
      }

      if (users[selected_user].credits == 0) {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("CREDITS       00");
        lcd.setCursor(0, 1);
        lcd.print("PLEASE, RECHARGE");
        delay(4000);
        state = STANDBY;
      } else {
        state = SELECTION;
      }
      break;
    case SELECTION:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("CREDITS");
      lcd.setCursor(14, 0);
      if (users[selected_user].credits < 10) lcd.print("0");
      lcd.print(users[selected_user].credits);
      lcd.setCursor(0, 1);
      lcd.print("CHOOSE    1 TO 4");
      timer = millis() + 10000;
      while (state == SELECTION) {
        if (Button() >= 1 && Button() <= 4) {
          item = Button();
          lcd.setCursor(0, 0);
          lcd.print("CONFIRM ITEM X? ");
          lcd.setCursor(0, 1);
          lcd.print(" PRESS X AGAIN  ");
          lcd.setCursor(13, 0);
          ButtonPrint(true);
          lcd.setCursor(7, 1);
          ButtonPrint(true);
          while (Button() != -1)
            ;
          delay(100);
          timer = millis() + 4000;
          while (Button() == -1) {
            if (timer < millis()) {
              state = STANDBY;
              break;
            }
          }
          if (Button() == item) state = DELIVERY;
          else {
            while (Button() != -1)
              ;
            delay(100);
            break;
          }
        }
        if (timer < millis()) state = STANDBY;
      }
      break;
    case DELIVERY:
      users[selected_user].credits--;
      lcd.clear();
      lcd.print("REMAINING");
      lcd.setCursor(14, 0);
      if (users[selected_user].credits < 10) lcd.print("0");
      lcd.print(users[selected_user].credits);
      lcd.setCursor(4, 1);
      lcd.print("CREDITS");
      delay(4000);
      Rotate(item, CLOCKWISE, 1, 1000);
      lcd.clear();
      for (int i = 0; i < 3; i++) {
        lcd.print("   THANK YOU");
        delay(1000);
        lcd.clear();
        delay(1000);
      }
      state = STANDBY;
      break;
    case MAINT:
      Unlock();
      lcd.clear();
      lcd.print("MAINTENANCE MODE");
      lcd.setCursor(0, 1);
      lcd.print("PRESS # TO LEAVE");
      while (state == MAINT) {
        if (Button() == 11) {
          lcd.clear();
          lcd.print("DO YOU CONFIRM?");
          lcd.setCursor(0, 1);
          lcd.print(" PRESS # AGAIN");
          while (Button() != -1)
            ;
          delay(100);
          timer = millis() + 4000;
          while (Button() == -1) {
            if (timer < millis()) {
              state = MAINT;
              break;
            }
          }
          delay(100);
          if (Button() == 11) {
            Lock();
            while (Button() != -1)
              ;
            delay(100);
            state = STANDBY;
          } else break;
        }
      }
  }
}

/*-----------------------------------------------------------------------------------------------------------------------*/
// Function returns the key numer as int
// Arguments:
//   Flag to sinalize if it's required print on LCD or not
//   1 -> print on LCD
//   0 -> don't print on LCD
// Returns:
//   0 to 9; * # D C B A -> ASCII code of pressed key
//   -1 -> error
/*-----------------------------------------------------------------------------------------------------------------------*/
char ButtonPrint(int print_or_not) {
  int key;
  key = Button();
  if (key >= 0 && key <= 9) {
    if (print_or_not) lcd.print(key);
    return key + 0x30;
  } else {
    switch (key) {
      case 10:
        if (print_or_not) lcd.print("*");
        return '*';
        break;
      case 11:
        if (print_or_not) lcd.print("#");
        return '#';
        break;
      case 12:
        if (print_or_not) lcd.print("D");
        return 'D';
        break;
      case 13:
        if (print_or_not) lcd.print("C");
        return 'C';
        break;
      case 14:
        if (print_or_not) lcd.print("B");
        return 'B';
        break;
      case 15:
        if (print_or_not) lcd.print("A");
        return 'A';
        break;
      case -1:
        return -1;
        //lcd.print("NONE");
        break;
    }
  }
}

/*-----------------------------------------------------------------------------------------------------------------------*/
// Function returns the user number as int
// Arguments:
//   NONE
// Returns:
//   >0 -> index of the checked user
//   -1 -> error
/*-----------------------------------------------------------------------------------------------------------------------*/
int CheckLogin() {
  int i;
  int j;
  char card_buffer[20];
  if (mfrc522.uid.size > 0) {
#if (CARD_DEBUG)
    Serial.println("Card detected...");
#endif
    for (byte i = 0; i < mfrc522.uid.size; i++) {
      sprintf(&card_buffer[i * 2], "%02x", mfrc522.uid.uidByte[i]);
    }
#if (CARD_DEBUG)
    Serial.print("Card code lenght: ");
    Serial.println(mfrc522.uid.size);
    Serial.print("Card ID: ");
    Serial.println(card_buffer);
#endif
    for (i = 0; i <= 4; i++) {
      if (users[i].length_card == mfrc522.uid.size * 2) {
#if (CARD_DEBUG)
        Serial.print("   User ");
        Serial.print(i);
        Serial.println(" has same lenght");
#endif
        for (j = mfrc522.uid.size * 2; j > 0; j--) {
          if (users[i].card[j - 1] != card_buffer[j - 1]) break;
        }
        if (j == 0) {
#if (CARD_DEBUG)
          Serial.print("   User ");
          Serial.print(i);
          Serial.println(" is a match!");
#endif
          mfrc522.uid.size = 0;
          return i;
        }
      }
    }
#if (CARD_DEBUG)
    Serial.println("Card ID doesn't match any user");
#endif
    mfrc522.uid.size = 0;
  } else {
    for (i = 0; i <= 4; i++) {
      if (users[i].login[0] == login[0] && users[i].login[1] == login[1] && users[i].login[2] == login[2] && users[i].login[3] == login[3]) {
        break;
      }
    }
    if (users[i].pass[0] == pass[0] && users[i].pass[1] == pass[1] && users[i].pass[2] == pass[2] && users[i].pass[3] == pass[3]) return i;
  }
  return -1;
}

/*-----------------------------------------------------------------------------------------------------------------------*/
// Function create test users - The final version
// Arguments:
//   NONE
// Returns:
//   NONE
/*-----------------------------------------------------------------------------------------------------------------------*/
void CreateUsers() {
  //Creating all test users-----------------------------------------------------------

}

A1/A2 etc are analog inputs not gpio , these are connected internally to be read only via multiplexer (search google)

I will attach a photo tomorrow, but it shows black boxes in the space where text is meant to be, my trim pot works correctly but I can't seem, to get any signal cause no matter what I tried I couldn't get any text to appear.

And yes I played with the trim pot to see if contrast was the issue, and that didn't appear to be the problem.

#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <avr/pgmspace.h>

#define NUM_DIGITAL_PINS            20
#define NUM_ANALOG_INPUTS           6
#define analogInputToDigitalPin(p)  ((p < 6) ? (p) + 14 : -1)

#if defined(__AVR_ATmega8__)
#define digitalPinHasPWM(p)         ((p) == 9 || (p) == 10 || (p) == 11)
#else
#define digitalPinHasPWM(p)         ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11)
#endif

#define PIN_SPI_SS    (10)
#define PIN_SPI_MOSI  (11)
#define PIN_SPI_MISO  (12)
#define PIN_SPI_SCK   (13)

static const uint8_t SS   = PIN_SPI_SS;
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK  = PIN_SPI_SCK;

#define PIN_WIRE_SDA        (18)
#define PIN_WIRE_SCL        (19)

static const uint8_t SDA = PIN_WIRE_SDA;
static const uint8_t SCL = PIN_WIRE_SCL;

#define LED_BUILTIN 13

#define PIN_A0   (14)
#define PIN_A1   (15)
#define PIN_A2   (16)
#define PIN_A3   (17)
#define PIN_A4   (18)
#define PIN_A5   (19)
#define PIN_A6   (20)
#define PIN_A7   (21)

static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;

yes they are definitions but they are not meant to be used for digitial outputs

Maybe your not sending an ascii character (the lcd is not recognising the character) again use digital outputs just to test it

Ahhhh thanks guys, I just don't have enough Digi ports free, so I thought I'd be able to pinMode define, but it appears that's not the case.

@bastjan
You are wrong. Analogue pins A0 to A5 on a Uno can be used as digital pins

You have incorrect information, the pins A0-A5 are digital (14...19), but not A6 & A7 in arduino nano

Have you tried to test the display and it's wiring to the board with a simple test sketch with none of the other code?
There is an example in the ide under the pull down menu
File>Examples>ExamplesForAnyBoard>LiquidCrystal>HelloWorld

Change the pins in the sketch to what you are using, and see if you can get the display to show the text in the example.

/*
  LiquidCrystal Library - Hello World

 Demonstrates the use a 16x2 LCD display.  The LiquidCrystal
 library works with all LCD displays that are compatible with the
 Hitachi HD44780 driver. There are many of them out there, and you
 can usually tell them by the 16-pin interface.

 This sketch prints "Hello World!" to the LCD
 and shows the time.

  The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 Library originally added 18 Apr 2008
 by David A. Mellis
 library modified 5 Jul 2009
 by Limor Fried (http://www.ladyada.net)
 example added 9 Jul 2009
 by Tom Igoe
 modified 22 Nov 2010
 by Tom Igoe
 modified 7 Nov 2016
 by Arturo Guadalupi

 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/LiquidCrystalHelloWorld

*/

// include the library code:
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis() / 1000);
}

Thanks for the reply. Turns out I was tired and stoopid. I just hadn't defined my analogue pins correctly in my code and RW wasn't grounded correctly. I now have a working LCD.

I would still like to thank everybody for helping and assisting, your words of constructive feedback allowed me to fault find more effectively and I have been better for it.

Have a fantastic week everybody and once again thanks for the help :))

I don't think there's anyone on this forum who couldn't say the same thing.

Good luck with your Arduino journey.