I am working on a project to control germicidal UV lamps for decontaminating N95 masks. It is supposed to have a display of how long the box has been operating, and eventually it is supposed to have a menu to select different operating intensities. I have been having intermittent issues with the display, where it will scroll out gibberish characters (pictured). If I cycle power the issue usually goes away, but it never clears on its own. Also, the issue begins at startup so if the screen is normal it stays normal.
I have been able to achieve seemingly stable operation by tweaking the code. Since it is an intermittent issue though, I want to understand the cause so I know it will not come back.
A secondary (possibly related) issue I uncovered is I can display the timing variable (unsigned long) twice with different results (pictured). It displays the least significant byte the same, but the upper bytes seem to be scrambled. This seems to be on a bit/byte level, since it happens with DEC (by multiples of 2), HEX, and BIN.
The attached code sometimes generates the gibberish text, and consistently displays the mismatched variable. My hardware is listed below. I would really appreciate some help with this one!
Arduino UNO R3
Newhaven Display NHD-0216K1Z-FSW-FBW-L (16x2 LCD)
DFRobot Relay Shield
Adafruit VEML6070 UV Sensor Breakout
Bourns PEC11R-4020F-S0024-ND Push-button Rotary Encoder
#include <Wire.h>
#include "Adafruit_VEML6070.h"
#include <LiquidCrystal.h>
#include <ClickEncoder.h>
#include <TimerOne.h>
const int rs = 12, en = 11, d4 = 6, d5 = 5, d6 = 4, d7 = 3;
const int relay1 = 2;
const int relay2 = 7;
const int relay3 = 8;
const int relay4 = 10;
const int reedSwitch = 13; //monitors the drawer
unsigned long secondsPassed = 0; //total time since initialization
unsigned long secondsClosed = 0; //time the drawer has been closed
unsigned int uvReading = 0;
unsigned long currentTime = 0;
unsigned long loopTime = 0;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
Adafruit_VEML6070 uv = Adafruit_VEML6070();
ClickEncoder *encoder;
int16_t last, value;
void timerIsr() {
encoder->service();
}
void setup() {
delay(100);
lcd.begin(16, 2);
delay(100);
lcd.setCursor(0, 0);
lcd.print(F("Starting... "));
uv.begin(VEML6070_1_T); // pass in the integration time constant (1T= 125ms)
pinMode(relay1,OUTPUT);
pinMode(relay2,OUTPUT);
pinMode(relay3,OUTPUT);
pinMode(relay4,OUTPUT);
pinMode(reedSwitch,INPUT_PULLUP);
Timer1.initialize(50); //Normal 1000, increased frequency for troubleshooting
Timer1.attachInterrupt(timerIsr);
//The relays turn on the UV lamps. Disabled for troubleshooting
/*digitalWrite(relay1, HIGH);
delay(100);
digitalWrite(relay2, HIGH);
delay(100);
digitalWrite(relay3, HIGH);
delay(100);
digitalWrite(relay4, HIGH);*/
delay(5000);
last = -1;
currentTime = millis();
loopTime = currentTime;
}
void loop() {
currentTime = millis();
uvReading = uv.readUV();
if(digitalRead(reedSwitch)){
lcd.setCursor(0, 0); //Col, Row
lcd.print(secondsPassed, HEX);
lcd.print(F(" seconds on "));
lcd.setCursor(0, 1); //Col, Row
lcd.print(F("Opened, "));
lcd.setCursor(8, 1);
lcd.print(F("UVA: "));
lcd.print(uvReading);
lcd.print(F(" "));
secondsClosed = 0;
} else {
lcd.setCursor(0, 0); //Col, Row
lcd.print(secondsPassed, BIN); //Normal void, BIN for troubleshooting
lcd.print(F(" seconds on "));
lcd.setCursor(0, 1);
lcd.print(secondsPassed, BIN); //Normally pass secondsClosed
lcd.print(F(" s "));
lcd.setCursor(16, 1);
lcd.print(F("UVA: "));
lcd.print(uvReading);
lcd.print(F(" "));
}
if(currentTime >= (loopTime + 100)) //Normal 1000. Increased speed for troubleshooting
{
loopTime = currentTime;
secondsPassed++;
secondsClosed++;
}
delay(2);
}