LCD Fluctuation

Hello
I designed a counter with 2x16 screen and Atmega328P. The circuit normally works, but when installed in the factory, the screen fluctuates. You can see the circuit diagram in the appendix, in the software I did not write the code about the unused pins and the AREF pin is idle.

Is it wrong to not code unused pins in 328P?
or
What else can be?
Thanks

OP schematic so we doh't have to download it. How to post images.

Firstly, you are missing the bypass caps (0.1uF) on Vcc, AVcc and Aref (all to ground). That can cause weird behavior.

Secondly, where is your code? Are you using lcd.clear() in the loop() code?

Does the screen fluctuate all the time or just when the relay switches or ...? A better description of the problem would be welcome.

Is it wrong to not code unused pins in 328P?

I often just leave the unused pins at input (the default mode on reset). So, no you do not have to code unused pins.

First of all, I apologize for my mistake. Thank you for your help

#include<LiquidCrystal.h>
LiquidCrystal lcd( 8 , 7,  6, 5, 4, 3);
unsigned int DATA = 0;
const int MENU = 4;
const int PLUS = 5;
const int MINUS = 6;
const int ENTER = 7;
const int RELAY = 8;

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

void setup() {
  lcd.begin(16, 2);
  pinMode(MENU, INPUT_PULLUP);
  pinMode(PLUS, INPUT_PULLUP);
  pinMode(MINUS, INPUT_PULLUP);
  pinMode(ENTER, INPUT_PULLUP);
  pinMode(RELAY, OUTPUT);
}

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

void loop() {

  lcd.setCursor(0, 0);
  lcd.print("COUNTER");
  lcd.setCursor(0, 2);
  lcd.print("DATA:");
  lcd.setCursor(11, 2);
  lcd.print(DATA);


  //PLUS

  if (digitalRead(PLUS) == LOW) {
    while (digitalRead(PLUS) == LOW);
    DATA++;
    lcd.setCursor(11, 2);
    lcd.print(DATA);
  }


  //MINUS

  if (digitalRead(MINUS) == LOW) {
    while (digitalRead(MINUS) == LOW);
    DATA--;
    lcd.setCursor(11, 2);
    lcd.print(DATA);
  }


  //ENTER

  if (digitalRead(DATA) == 100) {
    while (digitalRead(ENTER) == LOW);
    digitalWrite(RELAY, HIGH);
    delay(250);
    digitalWrite(RELAY, LOW);
    DATA = 0;
    lcd.setCursor(11, 2);
    lcd.print(DATA);
  }
}

If there is no use of analog inputs - you have not indicated any - then bypassing on Aref and Avcc is immaterial.

If unused inputs are not attached to any conductors, that is have no connection beyond the pins of the chip, then the only concern is that they may float at indeterminate levels and draw a number of microamps, generally not significant. This can be easily avoided by setting unused pins to INPUT_PULLUP.

Your use of an obsolescent 4N25 is most peculiar. As you illustrate it, its only function (as it is not isolating anything) is to reduce the current available to RL1. Given an operating current of 5 mA, I must presume you are actually using a SSR of some sort, but this would not require a "kickback" diode.

And why you would go to the trouble to assemble this from the raw components rather than using a readily available,cheap and proven Pro Mini, I cannot fathom.

Yet to look at your code posted as I write this.

OK, so your code does not match your circuit diagram whatsoever.

I think you have a lot of explaining to do. :astonished:

If there is no use of analog inputs - you have not indicated any - then bypassing on Aref and Avcc is immaterial.

I will not use analog inputs

If unused inputs are not attached to any conductors, that is have no connection beyond the pins of the chip, then the only concern is that they may float at indeterminate levels and draw a number of microamps, generally not significant. This can be easily avoided by setting unused pins to INPUT_PULLUP.

I'll do the unused input pins as you say.

Your use of an obsolescent 4N25 is most peculiar. As you illustrate it, its only function (as it is not isolating anything) is to reduce the current available to RL1. Given an operating current of 5 mA, I must presume you are actually using a SSR of some sort, but this would not require a "kickback" diode.

I used an optocoupler to isolate the relay from ATMEGA328, why did I use 4n25? I used it because I have 4n25

And why you would go to the trouble to assemble this from the raw components rather than using a readily available,cheap and proven Pro Mini, I cannot fathom.

I'm trying to understand the problem. I want to know where I made a mistake, so I don't want to get Pro Mini. Am I making a software error or as you say; "The capacitor is missing? (VCC & GND)"

I sent the wrong codes., final version, thanks

#include <Wire.h>
#include <LiquidCrystal_I2C.h>                // I2C LCD KÜTÜPHANESİ EKLENDİ
LiquidCrystal_I2C lcd(0x27, 16, 2);           // Set the LCD address to 0x27 for a 16 chars and 2 line display


unsigned int DATA = 0;
const int MENU = 4;
const int PLUS = 5;
const int MINUS = 6;
const int ENTER = 7;
const int RELAY = 8;

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

void setup() {
  lcd.begin(16, 2);
  pinMode(MENU, INPUT_PULLUP);
  pinMode(PLUS, INPUT_PULLUP);
  pinMode(MINUS, INPUT_PULLUP);
  pinMode(ENTER, INPUT_PULLUP);
  pinMode(RELAY, OUTPUT);

  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);

}

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

void loop() {

  lcd.setCursor(0, 0);
  lcd.print("COUNTER");
  lcd.setCursor(0, 2);
  lcd.print("DATA:");
  lcd.setCursor(11, 2);
  lcd.print(DATA);


  //PLUS

  if (digitalRead(PLUS) == LOW) {
    while (digitalRead(PLUS) == LOW);
    DATA++;
    lcd.setCursor(11, 2);
    lcd.print(DATA);
  }


  //MINUS

  if (digitalRead(MINUS) == LOW) {
    while (digitalRead(MINUS) == LOW);
    DATA--;
    lcd.setCursor(11, 2);
    lcd.print(DATA);
  }


  //ENTER

  if (digitalRead(DATA) == 100) {
    while (digitalRead(ENTER) == LOW);
    digitalWrite(RELAY, HIGH);
    delay(250);
    digitalWrite(RELAY, LOW);
    DATA = 0;
    lcd.setCursor(11, 2);
    lcd.print(DATA);
  }
}

But you have not isolated the relay from the ATmega at all! :astonished: The ground on both sides of the optocoupler is the same; you have reduced it to a three-terminal device - just like a transistor, but whereas a transistor has a gain greater then 1, the 4N25 has a nominal gain of 0.5. I remain absolutely fascinated by what sort of relay you have that actually operates at 5 mA on 5 V.

Your code will most certainly flicker, though nowhere near as badly as if you had included - as groundFungus points out, lcd.clear() .

With the exception of your "while" loops, there is nothing limiting the speed of actions so the LCD is being re-written at a phenomenal rate; that is what causes the flicker. You need to move the first paragraph of code

  lcd.setCursor(0, 0);
  lcd.print("COUNTER");
  lcd.setCursor(0, 2);
  lcd.print("DATA:");
  lcd.setCursor(11, 2);
  lcd.print(DATA);

into setup().

As I see it, the relay is supposed to be tripped when the count reaches 100 unless the "ENTER" switch is pressed - and while it is pressed, further counts are missed. OK, but I am still puzzled about that amazing relay!

It took me a while to figure out your crude de-bouncing of the switches using the while loops and capacitors. I doubt you will find it entirely reliable. There are much better ways to do it in software.

Okay, you're right about the relay. Incorrect isolation method. I will remove the optocoupler(Tr output) and relay from the circuit, I will use MOC series optocoupler (Triac Output), so the insulation will be better.

OK,i will move the first paragraph of code into setup().

There is a similar example on this page, only difference; "Delay added"

  if (button == HIGH) {
    a ++;
    lcd.setCursor(3, 1);
    lcd.print(a);
     delay(200);
    }

Are there any parts in the circuit that need to be added or removed? Except relay :slight_smile:
Thanks

bjk571:
There is a similar example on this page, only difference; "Delay added"

https://www.instructables.com/id/Arduino-Lcd-Counter

  if (button == HIGH) {

a ++;
   lcd.setCursor(3, 1);
   lcd.print(a);
    delay(200);
   }

Oh dear! You swore! "Instructables"! An offensive word on this forum! :astonished:

Your code is already superior to that.

Here is code to completely de-bounce four buttons. It is to implement the "Radio Buttons" function where each button turns its own LED on and all the others off.

The de-bounce "interval" is set to 10 milliseconds which means that it will respond ten milliseconds after the input stops bouncing rather than when the button is released, and will not respond further until ten milliseconds after the input stops bouncing on release, but will not impede any other operation while it waits for any de-bouncing. Note that it never uses the delay() or while() functions.

It is easily modified to do whatever else you need to do, such as counting:

// Radio Buttons!
const int led1Pin =  3;    // LED pin number
const int button1 =  2;
const int led2Pin =  5; 
const int button2 =  4;
const int led3Pin =  6;
const int button3 =  7;
const int led4Pin =  9;
const int button4 =  8;
char bstate1 = 0;
char bstate2 = 0;
char bstate3 = 0;
char bstate4 = 0;
unsigned long bcount1 = 0; // button debounce timer.  Replicate as necessary.
unsigned long bcount2 = 0;
unsigned long bcount3 = 0;
unsigned long bcount4 = 0;

// Have we completed the specified interval since last confirmed event?
// "marker" chooses which counter to check
// Routines by Paul__B of Arduino Forum
boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) { 
    *marker += interval;    // move on ready for next interval
    return true;       
  } 
  else return false;
}

// Deal with a button read; true if button pressed and debounced is a new event
// Uses reading of button input, debounce store, state store and debounce interval.
// Routines by Paul__B of Arduino Forum
boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               // Odd states if was pressed, >= 2 if debounce in progress
  case 0: // Button up so far, 
    if (button == HIGH) return false; // Nothing happening!
    else { 
      *butnstate = 2;                 // record that is now pressed
      *marker = millis();             // note when was pressed
      return false;                   // and move on
    }

  case 1: // Button down so far, 
    if (button == LOW) return false; // Nothing happening!
    else { 
      *butnstate = 3;                 // record that is now released
      *marker = millis();             // note when was released
      return false;                   // and move on
    }

  case 2: // Button was up, now down.
    if (button == HIGH) {
      *butnstate = 0;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 1;               // jackpot!  update the state
        return true;                  // because we have the desired event!
      }
      else 
        return false;                 // not done yet; just move on
    }

  case 3: // Button was down, now up.
    if (button == LOW) {
      *butnstate = 1;                 // no, not debounced; revert the state
      return false;                   // False alarm!
    }
    else { 
      if (millis() - *marker >= interval) {
        *butnstate = 0;               // Debounced; update the state
        return false;                 // but it is not the event we want
      }
      else 
        return false;                 // not done yet; just move on
    }
  default:                            // Error; recover anyway
    {  
      *butnstate = 0;
      return false;                   // Definitely false!
    }
  }
}

void setup() {
  pinMode(led1Pin, OUTPUT);      
  pinMode(button1, INPUT_PULLUP); 
  pinMode(led2Pin, OUTPUT);      
  pinMode(button2, INPUT_PULLUP);      
  pinMode(led3Pin, OUTPUT);      
  pinMode(button3, INPUT_PULLUP);      
  pinMode(led4Pin, OUTPUT);      
  pinMode(button4, INPUT_PULLUP);        
  digitalWrite (led1Pin, LOW);
  digitalWrite (led2Pin, LOW);
  digitalWrite (led3Pin, LOW);
  digitalWrite (led4Pin, LOW);
}

void loop() {
  // Select LED if button debounced
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    digitalWrite (led1Pin, HIGH);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
  } 
  // Select LED if button debounced
  if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, HIGH);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, LOW);
  } 
  // Select LED if button debounced
  if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, HIGH);
    digitalWrite (led4Pin, LOW);
  } 
  if (butndown(digitalRead(button4), &bcount4, &bstate4, 10UL )) {
    // Select LED if button debounced
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    digitalWrite (led4Pin, HIGH);
  } 
}

Thanks for the code, is there any problem in the circuit? Is it necessary to take additional precautions for Atmega?

bjk571:
Thanks for the code, is there any problem in the circuit? Is it necessary to take additional precautions for ATmega?

Circuit looks OK. Is the code useful to you?