ST7565 LCD - corruption (programmatic terrarium)

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
scrubbl3r
 
Posts: 21
Joined: Sat Jul 13, 2013 6:26 pm

ST7565 LCD - corruption (programmatic terrarium)

Post by scrubbl3r »

Hi folks,

I'm having some problems with the ST7565 LCD screen corrupting. I'm not sure if this is due to a programming or an electrical problem. I think what's most relevant, electrically speaking is that my code triggers a seeed studio relay shield which turns on and off lights, a pump and some other stuff. I'm wondering if this is causing a drop in voltage which is messing up my LCD.

When the LCD screws up what happens is that the strings being rendered jump lines and draw themselves in the wrong places.. sometimes the entire screen goes black. This happens every 12 - 26 hours. I've been winnowing down functionality to isolate the problem The code posted is the most abbreviated i could make it while reproducing the error. Forgive me if there are some dead variables - i did my best to clean this up so it makes sense for your consideration.

The function for the LCD is at the very bottom - its called renderConditions().

Thanks in advance :)

Code: Select all

#include <Arduino.h> // ---- / rtc
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

#include "ST7565.h" // ---------- / lcd
#define BACKLIGHT_LED 10
ST7565 glcd(12, 11, 10, 9, 8);

#include <SHT1x.h>
#define dataPin  2
#define clockPin 3
SHT1x sht1x(dataPin, clockPin);

#define SERIES_RESISTOR 560 // --------------- / liquid level
#define SENSOR_PIN  A3
#define ZERO_VOLUME_RESISTANCE 1797.00
#define CALIBRATION_RESISTANCE 718.
#define CALIBRATION_VOLUME 18.00

#define LIGHTPIN 4 //---------------------/ relays
#define RAINPIN 5
#define VENTPIN 6
#define SPEAKERPIN 7
#define RAINBUTTONPIN A15 //-----------/ button
byte lightToggle = 0;
byte rainToggle = 0;
byte stormToggle = 0;
byte ventToggle = 0;
byte speakerToggle = 0;
byte rainDip[3] = {0,0,0};
byte ventDip[3] = {0,0,0};
byte speakerDip[3] = {0,0,0};
byte speakerComplete = 1;
byte rainButtonToggle;
int rainButtonReading;

byte currentMonth;
byte currentDay;
byte currentHour;
byte currentMinute;
byte dawn[2];
byte dusk[2];

int cT;
int cDawn;
int cDusk;
int cRainStart_1;
int cRainEnd_1;
int cRainStart_2;
int cRainEnd_2;
int cRainStart_3;
int cRainEnd_3;
int cRainStart_4;
int cRainEnd_4;
int cRainStart_5;
int cRainEnd_5;
int cVentStart;
int cVentEnd;
int cSpeakerStart;
int cSpeakerEnd;

// -------------------------------------------------/ CONFIGURATION
byte ventStart[2] = {20,41};
byte ventEnd[2] = {20,45};
byte rainStart[10] = {7,00, 10,00, 12,00, 17,00, 1,00};
byte rainEnd[10] = {7,01, 10,00, 12,00, 17,03, 1,00};
byte speakerStart[2] = {7,00};
byte speakerEnd[2] = {7,05};
// -------------------------------------------------/ CONFIGURATION

float tankTempF = 50; // ------/ sensors
float tankTempC = 50;
float tankHumid = 50;
float swampLevel = 3.33;
float resistance = 0;
byte sLevWarn = 254;
byte cycleConditions_ON = 1; // ------------------------------------------------------------------// // // 
int rainCheck = 0;

byte humMin = 70;
byte humMax = 83;
byte ventMax = 100;
byte ventMin = 88;

int tempChanged = 0; // -----------/ sentience
int humidChanged = 0;
int oldTemp = 0;
int oldHumid = 0;
int newTemp = 0;
int newHumid = 0;

#define MINSIZE 1440 // ---------/ peaks and valleys
int oldMinute;
byte twoMin = 0;
byte tmpHigh = 0;
byte tmpLow = 254;
byte humHigh = 0;
byte humLow = 254;
byte tmpHArray[MINSIZE];
byte tmpLArray[MINSIZE];
byte humHArray[MINSIZE];
byte humLArray[MINSIZE];

void setup() {
  Wire.begin();
  rtc.begin();
  if (! rtc.isrunning()) {
    //Serial.println("RTC is NOT running!");
    // rtc.adjust(DateTime(__DATE__, __TIME__)); ----------// initialize date/time
  }

  pinMode(LIGHTPIN, OUTPUT); // ---------/ pins
  pinMode(RAINPIN, OUTPUT);
  pinMode(VENTPIN, OUTPUT);
  pinMode(SPEAKERPIN, OUTPUT);
  pinMode(RAINBUTTONPIN, INPUT);
  digitalWrite(LIGHTPIN,LOW);
  digitalWrite(RAINPIN,LOW);
  digitalWrite(VENTPIN,LOW);
  digitalWrite(SPEAKERPIN,HIGH);
  
  glcd.begin(0x99);
  glcd.clear();

  for (int i=0; i<MINSIZE-1; i=i + 1) {
    tmpLArray[i] = 254;
    humLArray[i] = 254;
  }
  tmpLArray[MINSIZE-1] = 254;
  humLArray[MINSIZE-1] = 254;
  
  delay(120);
}


void loop() {
  DateTime now = rtc.now(); // --------- / time
  currentMonth = now.month();
  currentDay = now.day();
  currentHour = now.hour();
  currentMinute = now.minute();
  cT = ((currentHour*60)+currentMinute);
  cDawn = ((dawn[0]*60)+dawn[1]);
  cDusk = ((dusk[0]*60)+dusk[1]);
  
  cRainStart_1 = (rainStart[0]*60)+rainStart[1];
  cRainEnd_1 = (rainEnd[0]*60)+rainEnd[1];
  cRainStart_2 = (rainStart[2]*60)+rainStart[3];
  cRainEnd_2 = (rainEnd[2]*60)+rainEnd[3];
  cRainStart_3 = (rainStart[4]*60)+rainStart[5];
  cRainEnd_3 = (rainEnd[4]*60)+rainEnd[5];
  cRainStart_4 = (rainStart[6]*60)+rainStart[7];
  cRainEnd_4 = (rainEnd[6]*60)+rainEnd[7];
  cRainStart_5 = (rainStart[8]*60)+rainStart[9];
  cRainEnd_5 = (rainEnd[8]*60)+rainEnd[9];
  
  tankTempF = sht1x.readTemperatureF();
  tankHumid = sht1x.readHumidity();
  rainButtonReading = digitalRead(RAINBUTTONPIN);
  

  if (tankHumid > 99) {
    tankHumid = 99;
  }
  
  resistance = readResistance(SENSOR_PIN, SERIES_RESISTOR);
  swampLevel = resistanceToVolume(resistance, ZERO_VOLUME_RESISTANCE, CALIBRATION_RESISTANCE, CALIBRATION_VOLUME);
  
  renderConditions();
  cycleSeason();
  cycleConditions();
  cycleDaylight();
  rain();
  rainButton();
  highLow();
  delay(130);
}


// Tegucigalpa, Honduras light cycle ///////////////////////////////////////////
void cycleSeason() {
  
  switch (currentMonth) {
    
    case 1:
      if (currentDay < 14) { dawn[0] = 6; dawn[1] = 13; dusk[0] = 17; dusk[1] = 32; }
                      else { dawn[0] = 6; dawn[1] = 16; dusk[0] = 17; dusk[1] = 40; }
    break;
    case 2:
      if (currentDay < 14){ dawn[0] = 6; dawn[1] = 16; dusk[0] = 17; dusk[1] = 48; }
                     else { dawn[0] = 6; dawn[1] = 11; dusk[0] = 17; dusk[1] = 53; }
    break;
    case 3:
        if (currentDay < 14){ dawn[0] = 6; dawn[1] = 4; dusk[0] = 17; dusk[1] = 57; }
                       else { dawn[0] = 5; dawn[1] = 55; dusk[0] = 17; dusk[1] = 59; }
    break;
    case 4:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 43; dusk[0] = 18; dusk[1] = 00; }
                       else { dawn[0] = 5; dawn[1] = 34; dusk[0] = 18; dusk[1] = 00; }
    break;
    case 5:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 26; dusk[0] = 18; dusk[1] = 5; }
                       else { dawn[0] = 5; dawn[1] = 21; dusk[0] = 18; dusk[1] = 8; }
    break;
    case 6:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 26; dusk[0] = 18; dusk[1] = 5; }
                       else { dawn[0] = 5; dawn[1] = 21; dusk[0] = 18; dusk[1] = 8; }
    break;
    case 7:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 24; dusk[0] = 18; dusk[1] = 21; }
                       else { dawn[0] = 5; dawn[1] = 28; dusk[0] = 18; dusk[1] = 21; }
    break;
    case 8:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 33; dusk[0] = 18; dusk[1] = 17; } // set back to 18
                       else { dawn[0] = 5; dawn[1] = 35; dusk[0] = 18; dusk[1] = 59; }
    break;
    case 9:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 37; dusk[0] = 17; dusk[1] = 59; }
                       else { dawn[0] = 5; dawn[1] = 37; dusk[0] = 17; dusk[1] = 49; }
    break;
    case 10:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 38; dusk[0] = 17; dusk[1] = 38; }
                       else { dawn[0] = 5; dawn[1] = 39; dusk[0] = 17; dusk[1] = 28; }
    break;
    case 11:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 43; dusk[0] = 17; dusk[1] = 20; }
                       else { dawn[0] = 5; dawn[1] = 49; dusk[0] = 17; dusk[1] = 17; }
    break;
    case 12:
        if (currentDay < 14){ dawn[0] = 5; dawn[1] = 57; dusk[0] = 17; dusk[1] = 18; }
                       else { dawn[0] = 6; dawn[1] = 5; dusk[0] = 17; dusk[1] = 23; }
    break;
  }
}


// DALY CYCLE //////////////////////////////////////////////////////////////////////////////////////
void cycleDaylight() {
  if ((cT >= cDawn) && (cT < cDusk)) { //____________/ lights
    if (lightToggle != 1){
      digitalWrite(LIGHTPIN, HIGH);
      lightToggle = 1;
    }
  } else {
    digitalWrite(LIGHTPIN, LOW);
    lightToggle = 0;
  }
  if (cT == cDusk){
    rainCheck = 0;
  }
}


void rain() { // -------------------------------------------------------------- / rain
    if (rainDip[0] == 1 || rainDip[1] == 1 || rainDip[2] == 1){
      if(rainToggle != 1){
        rainToggle = 1;
        digitalWrite(RAINPIN, HIGH);
        rainCheck = rainCheck + 1;
        
        if (rainDip[0]==1 || rainDip[1]==1){
          if (stormToggle != 1) {
            stormToggle = 1;
            glcd.clear();
          }
        } else if (rainDip[2] == 1) {
          if (stormToggle != 1) {
            stormToggle = 1;
            glcd.clear();
          }
        }
        
      }
    } else {
      stormToggle = 0;
      rainToggle = 0;
      digitalWrite(RAINPIN, LOW);
    }
}

void rainButton() { // ------------------------------------------ / button (rain)
  if (rainButtonReading == HIGH && rainButtonToggle != 1){
    rainDip[1] = 1;
    rainButtonToggle = 1;
    glcd.clear();
  }
  if (rainButtonReading == LOW && rainButtonToggle == 1){
    rainDip[1] = 0;
    rainButtonToggle = 0;
  }
}

void cycleConditions(){
  if ( ((cT >= cRainStart_1) && (cT < cRainEnd_1)) ||
      ((cT >= cRainStart_2) && (cT < cRainEnd_2)) ||
      ((cT >= cRainStart_3) && (cT < cRainEnd_3)) ||
      ((cT >= cRainStart_4) && (cT < cRainEnd_4)) ||
      ((cT >= cRainStart_5) && (cT < cRainEnd_5)) ) {
    rainDip[2] = 1;
  } else {
    rainDip[2] = 0;
  }
}


void highLow() { // -------------------------------------- / peaks and valleys
  int tH = 0;
  int tL = 254;
  int hH = 0;
  int hL = 254;
  
  if (oldMinute != currentMinute){
    for (int i=0; i<MINSIZE-1; i=i + 1) {
      tmpHArray[i] = tmpHArray[i + 1];
      tmpLArray[i] = tmpLArray[i + 1];
      humHArray[i] = humHArray[i + 1];
      humLArray[i] = humLArray[i + 1];
    }
    tmpHArray[MINSIZE-1] = tankTempF;
    tmpLArray[MINSIZE-1] = tankTempF;
    humHArray[MINSIZE-1] = tankHumid;
    humLArray[MINSIZE-1] = tankHumid;
   }
   for (int i=0; i<MINSIZE-1; i=i + 1) {
     if (tmpHArray[i] > tH){
       tH = tmpHArray[i];
     }
     if (tmpLArray[i] < tL){
       tL = tmpLArray[i];
     }
     if (humHArray[i] > hH){
       hH = humHArray[i];
     }
     if (humHArray[i] < hL){
       hL = humLArray[i];
     }
   }
   tmpHigh = tH;
   tmpLow = tL;
   humHigh = hH;
   humLow = hL;
   oldMinute = currentMinute;
}


float readResistance(int pin, int seriesResistance) { // --------------------------------- / liquid level
  float resistance = analogRead(pin);
  resistance = (1023.0 / resistance) - 1.0;
  resistance = seriesResistance / resistance;
  return resistance;
}
float resistanceToVolume(float resistance, float zeroResistance, float calResistance, float calVolume) {
  if (resistance > zeroResistance || (zeroResistance - calResistance) == 0.0) {
    return 0.0;
  }
  float scale = (zeroResistance - resistance) / (zeroResistance - calResistance);
  return calVolume * scale;
}



void renderConditions(){ // --------------------------------- / render LCD consol
  glcd.clear();
  char buff[30];
  
  snprintf(buff, sizeof(buff) - 1, "Tmp: %dF %c%d %c%d", (int)tankTempF, 0x19, (int)tmpLow, 0x18,(int)tmpHigh);
  glcd.drawstring(16, 1, buff);
  
  snprintf(buff, sizeof(buff) - 1, "Hum: %d%c %c%d %c%d", (int)tankHumid, 37, 0x19, (int)humLow, 0x18, (int)humHigh);
  glcd.drawstring(16, 3, buff);
  
  if (swampLevel > 0){
    float slDecim = swampLevel - (int)swampLevel;
    slDecim = slDecim *100;
    snprintf(buff, sizeof(buff) - 1, "Gal: %d.%d",(int)swampLevel, (int)slDecim);
    glcd.drawstring(16, 5, buff);
  }
  else {
    sLevWarn = sLevWarn+1;
    if (sLevWarn < 4) {
      glcd.drawstring(16, 5, "EMPTY");
    }
    else {
      glcd.drawstring(16, 5, "");
      if (sLevWarn > 6){
        sLevWarn = 0;
      }
    }
  }
  glcd.display();
}

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: ST7565 LCD - corruption (programmatic terrarium)

Post by adafruit_support_bill »

I had a similar problem with an LCD display on an aquarium controller. It would get scrambled at random about once a week or so. In that case, the trigger turned out to be the turn-on surge from a nearby compressor for a refrigerator. But pumps and relays are also known bad-actors when it comes to electrical noise and power-line glitches.

You might try separating the power supplies for the electronics and the high-powered stuff. In the case mentioned above, I had to plug it into an outlet that was on a different circuit.

scrubbl3r
 
Posts: 21
Joined: Sat Jul 13, 2013 6:26 pm

Re: ST7565 LCD - corruption (programmatic terrarium)

Post by scrubbl3r »

Thanks! I'll try that right now and let you know how it goes. To be honest i fell like a knuckle head because I tried plugging the different peripherals into their own power supply, but i never thought to leave them all on the same strip and power the arduino separately. Doi. :P

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”