Seeing some garbage characters printed on an LCD at seemingly random times - although it does seem as if the garbage only appears after my sketch/circuit has been running for a while. I'm not sure if it's a memory leak in my code, or whether it's EM interference from e.g. AC lighting switches etc. in the vicinity.
I'd like some advice about the best electronic modifications that could be made to my circuit to mitigate against EM interference corrupting my LCD. I've read a range of similar forum posts where various capacitor values (100uF? 47uF?) have been quoted as worth putting across Vss and Vdd at the LCD, to smooth any supply noise.
If anyone has any ideas I would be very keen to hear them.
I appreciate that since I've currently got all this lashed together on breadboards, I might be seeing more EM interference than would otherwise be the case if I had everything soldered down to veroboard etc. (due to jumper wires acting as inductors?).
If you think that's my main problem then by all means say so
Here are the details of my set-up:
I'm using an Arduino Nano v3.0, driving an HD44780 LCD display using a 74HD595 shift register, as per this link:
I drew out a schematic in Fritzing for this (see attached). Note that I've chosen to use Arduino pins 5, 6 & 7 to as the datapin, latchpin and clockpin instead of 7, 8 & 9.
I've also added a simple LDR-based voltage divider consisting of a 60K resistor and a 5516 LDR as follows:
5V ]-----[[60K]]-----|-----((5516 LDR))----[GND
|
|---->to Arduino pin 2 (interrupt 0)
...the idea being that any voltage drop across the 5516 LDR (it's 'looking' straight at a blinking LED in darkness) will fire an ISR declared in my sketch.
The LDR voltage divider is connected across the same 5V & GND as the LCD/shift register circuit.
The 5V & GND are taken from the corresponding Arduino 5v / GND pins.
#include <LiquidCrystal595.h> // include the library
const float METER_BLINKS_PER_KWH = 800.0;
const float MILLIS_PER_HOUR = 3600000.0;
float bill_units_per_hour = 0;
LiquidCrystal595 lcd(5,6,7); // datapin, latchpin, clockpin
int backlightPin = 4;
const long BOUNCE_WINDOW_MS=450;
unsigned long prev_interrupt_ms = 0;
unsigned long interrupt_ms = 0;
unsigned long millis_since_last_blink = 0;
volatile unsigned long last_blink_ms = 0;
volatile int blinks = 0;
int interruptPin = 2;
unsigned long curr_millis = 0;
unsigned long prev_millis = 0;
void onBlink()
{
interrupt_ms = millis();
millis_since_last_blink = (unsigned long)(interrupt_ms - prev_interrupt_ms);
if(millis_since_last_blink >= BOUNCE_WINDOW_MS)
{
last_blink_ms = millis_since_last_blink;
blinks++;
prev_interrupt_ms = interrupt_ms;
}
}
void setup() {
pinMode(interruptPin,INPUT);
attachInterrupt(0, onBlink, FALLING);
pinMode(backlightPin,OUTPUT);
lcd.begin(16,2); // 16 characters, 2 rows
lcd.clear();
digitalWrite(backlightPin, HIGH); //turn on backlight
lcd.setCursor(0,0);
lcd.print("Blink Monitor");
lcd.setCursor(0,1);
lcd.print("Initializing...");
delay(5000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("ms kW");
}
void loop() {
curr_millis = millis();
if((unsigned long)curr_millis - prev_millis > 1000)
{
calculateKWH();
prev_millis = curr_millis;
}
}
void calculateKWH()
{
if(blinks > 0)
{
bill_units_per_hour = MILLIS_PER_HOUR / ((float)last_blink_ms * METER_BLINKS_PER_KWH); // 3600000 / [X * 800]
lcd.setCursor(0,1);
lcd.print(last_blink_ms); lcd.print(" ");//add whitespace over any previous long timing
lcd.setCursor(8,1);
lcd.print(bill_units_per_hour,2); // 2 decimal places
}
}
Thanks in advance for any help.
Happy to supply any further info you may need.