GLCD behaving awkwardly

08 Nov 2013

I have this following code written ,I'm using the kl25z board so whats the catch about running GLCD with it an Ks0108 Driver compatible one is the library written for it prints left to right and right to left as default so I did this change then from there on it started on working all fine. but when I made the complete prototype circuitry it shows half screen and the other half is gone??

One reason this may happen is that because I have code written to display on GLCD screen on press of a designated button over a IR remote and when that button is pressed it activated some outputs which in turn take 5v to activate some TIP122 transistor NPN from the same source from where the GLCD takes power ,so then I checked for the voltage but its healthy steady @ 4.9v, so is it because of milliamps going to the GLCD then??

#include "mbed.h"
#include "KS0108.h"
#include "Arial12.h"
#include "SystemFont5x7.h"
#include "image.h"
#include "starting.h"
#include "brew.h"
#include "menu_stop.h"
#include "menu_alert.h"
#include "menu_status.h"
#include "menu_realview.h"
#include "menu_temp.h"
#include "ReceiverIR.h"
#include "ds1307.h"

#define TEMP_PIN  PTC9

//--------------LCD connections-----------------------------//
// KS0108 (PinName _RST,PinName _DI, PinName _RW, PinName _E, PinName _CS1, PinName _CS2, PinName DB0, PinName DB1, PinName DB2, PinName DB3, PinName DB4, PinName DB5, PinName DB6, PinName DB7);
KS0108  display(PTC3,PTD6, PTE31, PTA17, PTC5, PTC4, PTA16, PTC17, PTC16, PTC13, PTC12, PTC11, PTC10, PTC6);
//--------------Timer's-------------------------------------//
Ticker flowmtr1_wait;//Timer totalflow1;
Timer LCDviewer; //Timer to timeout LCDviewing
//--------------IR configuration----------------------------//
ReceiverIR ir_rx(PTD4);
RemoteIR::Format format;
//--------------Serial OUTPUT to screen---------------------//
Serial pc(USBTX, USBRX); // tx, rx
//--------------Interrupts----------------------------------//
InterruptIn flowmtr1(PTA5);
//--------------Variable Declaration's----------------------//
bool menu_alert = false, menu_realview = false, menu_status = false,
     menu_temp = false, menu_stop = false, start = false, phase1 = false,
     phase2 = false, phase3 = false, step1 = false, step2 = false, step3 = false, flowmeterON = false;
bool overflow = false, _heat_HLT = false, LCDviewing = false, MLT_diluting = false, kettleBOIL = false;
uint8_t buf[16];
volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;
int phase1RunCnt, phase2RunCnt, phaseRunCnt = 0, check_min, viewTIME, whichScreen, LCDiteration, kettleBoilingSTART;
//---------------I/O pin configurations---------------------//
DigitalOut v4(PTE29);//Valve 4 which is connected to MLT's T piping
DigitalOut v5(PTD0);//Valve 5 which is connected to Kettle piping
DigitalOut v6(PTD1);//Valve 6 which is connected to Kettle
DigitalOut v1(PTE20);//Valve 1 from which the water goes to HLT and is the valce connected to the tap
DigitalOut v3(PTE23);//Valve 3 which is connected to MLT's T piping
DigitalOut v2(PTE5); //Valve 2 which is connected to HLT
DigitalOut p1(PTD2);//1st pump
DigitalOut p2(PTE21);// 2nd pump
DigitalOut h1(PTE22);//HLT heater
DigitalOut h2(PTE30);//Kettle heater
AnalogIn overflow_HLT(PTB0); // overflow reader for the HLT tank
AnalogIn empty_MLT(PTB1);  // Empty reader for the MLT tank
//----------------RTC---------------------------------------//
DS1307 my1307(PTE0,PTE1); // start DS1307 class and give it pins for connections of the DS1307 device
int sec = 0;
int min = 0;
int hours = 0;
int day = 0;
int date = 0;
int month = 0;
int year = 0;
//------------------Temp-Sensor------------------------------//
DigitalInOut temperature_pin(TEMP_PIN);
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
//-----------------------------------------------------------//


void rpm()
{

    NbTopsFan++;  //This function measures the rising and falling edge of the

}

bool HLT()
{
    int flag = 0;
    for(int i=0; i<10; i++) {
        float Calc = overflow_HLT;
        char HLT[10];
        sprintf(HLT,"%.1f is ",Calc);
        float check_[10];
        check_[i] = Calc;
        if (check_[i] == 0.0) {
            flag++;
        }
    }
    if(flag > 0) {
        return(true);
    } else {
        return(false);
    }
}
bool MLT()
{
    int flag = 0;
    for(int i=0; i<10; i++) {
        float Calc = empty_MLT;
        char HLT[10];
        sprintf(HLT,"%.1f is ",Calc);
        float check_[10];
        check_[i] = Calc;
        if (check_[i] == 0.0) {
            flag++;
        }
    }
    if(flag > 0) {
        return(true);
    } else {
        return(false);
    }
}

void flowmtr1_counter()
{
    flowmtr1.rise(NULL);
    int save_it = (NbTopsFan * 60 / 7.5); //(Pulse frequency) / 7.5Q, = flow rate litre per second
    Calc = Calc + save_it;
    //char in[50];
    //sprintf(in,"%d is ",Calc);
    //pc.printf(in);
    NbTopsFan = 0;
    flowmtr1.rise(&rpm);
}

void test_rw(int test)
{
    if (test == 0) pc.printf("Last R/W operaion passed!\n\r");
    else pc.printf("Last R/W operation failed!\n\r");
}

void phase3_setup()
{
    pc.printf("Phase 3 setup");
    v4 = 0xff;
    pc.printf("v4 off");
    p2 = 0xff;
    pc.printf("pump2 off");
    MLT_diluting = 1;
}

void phase3_MLT_diluting_routine()
{
    //If condition that turns the v4 and p2 OFF.
    if (empty_MLT) {
        pc.printf("Emptying MLT");
        v4 = 0x00;
        pc.printf("v4 off");
        p2 = 0x00;
        pc.printf("pump2 off");
        h2 = 0xff;
        pc.printf("heater2 off");
        test_rw(my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year));
        kettleBoilingSTART = min;
        kettleBOIL = true;
    }
}

void kettleBoilingRoutine()
{
    test_rw(my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year));
    if (kettleBoilingSTART + 60 == min) {
        pc.printf("kettle boiling for 60 minutes done!");
        h2=0x00;
        p2=0x00;
        v4=0x00;
    }
}

void  phase1_phase2_step3()
{
    pc.printf("In phase1_phase2_step3");
    v3 = 0xff;
    v2 = 0x00;
    p1 = 0xff;
    test_rw(my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year));
    check_min = min;
    if (phase3 == false) {
        step3 = true;
        pc.printf("Step3 TRUE");
    } else if(phase3 == true) {
        phase3_setup();
        pc.printf("phase3_setup()");
    }
}

void flowmeter1(int qty)
{
    if (Calc == qty) {
        v2=0x00;
        p1=0x00;
        pc.printf("under flowmeter1 & call phase1_phase2_step3 ");
        phase1_phase2_step3();
    }
}

void phase1_step2()
{
    v2 = 0xff;
    p1 = 0xff;
    flowmeterON = true;
    pc.printf("_phase1_step2()_");
}

void waterValve()
{
    pc.printf("In waterValve()");
    phase1RunCnt++;
    v1 = 0xff;
    overflow = 1;
}

void phase1_phase2_step3_timecheck()
{
    test_rw(my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year));
    if(check_min + 30 == min) {
        phaseRunCnt++;


        if(phaseRunCnt == 1)phase1 = 0,phase2 = 1,phase3=0;
        if(phaseRunCnt == 2)phase1 = 0,phase2 = 0,phase3=1;
        //if(phaseRunCnt == 3)phase1 = 0,phase2 = 0,phase3=0;
        pc.printf("_In phase1_phase2_step3_timecheck() DONE_");
        waterValve();
        step3 = 0;
    }
}
void OneWireReset()   // reset.  Should improve to act as a presence pulse
{
    temperature_pin.output();
    temperature_pin = 0;     // bring low for 500 us
    wait_us(500);
    temperature_pin.input();
    wait_us(500);
}

void OneWireOutByte(unsigned char d)   // output byte d (least sig bit first).
{
    for(int n=8; n!=0; n--) {
        if ((d & 0x01) == 1) { // test least sig bit
            temperature_pin.output();
            temperature_pin = 0;
            wait_us(5);
            temperature_pin.input();
            wait_us(60);
        } else {
            temperature_pin.output();
            temperature_pin = 0;
            wait_us(60);
            temperature_pin.input();
        }

        d=d>>1; // now the next bit is in the least sig bit position.
    }

}

unsigned char OneWireInByte()   // read byte, least sig byte first
{
    unsigned char d = 0, b;
    for (int n=0; n<8; n++) {
        temperature_pin.output();
        temperature_pin = 0;
        wait_us(5);
        temperature_pin.input();
        wait_us(5);
        b = temperature_pin;
        wait_us(50);
        d = (d >> 1) | (b << 7); // shift d to right and insert b in most sig bit position
    }
    return d;
}
void _heat_check_HLT(int heat)  //start retrieving temp from HLT tank
{
    // sets the digital pin as input (logic 1) make sure external pullup resistor 4K7
    OneWireReset();
    OneWireOutByte( 0xcc);  //Skip ROM command
    OneWireOutByte( 0x44); // perform temperature conversion, strong pullup for one sec

    OneWireReset();
    OneWireOutByte( 0xcc);
    OneWireOutByte( 0xbe);   //Read Scratchpad

    LowByte = OneWireInByte();
    HighByte = OneWireInByte();
    TReading = (HighByte << 8) + LowByte;
    SignBit = TReading & 0x8000;  // test most sig bit
    if (SignBit) { // negative
        TReading = (TReading ^ 0xffff) + 1; // 2's comp
    }
    Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

    Whole = Tc_100 / 100;  // separate off the whole and fractional portions
    Fract = Tc_100 % 100;

    if (SignBit) { // If its negative
        pc.printf("-");
    }
    pc.printf("%d", Whole);
    if(heat == Whole) {
        h1 = 0x00;
        phase1_step2();
        if(phase3 == 1) {
            phase1_phase2_step3();
        }
    }
    pc.printf(".");
    if (Fract < 10) {
        pc.printf("0");
    }
    pc.printf("%d", Fract);
    pc.printf("\r\n");

}

void overflow_check()
{
    pc.printf("in overflow_check()");
    if(HLT()) {
        pc.printf("FILLED");
        v1 = 0x00;
        overflow = 0;
        _heat_HLT = 1;
        h1 = 0xff;
    }
}

void LCDrunner()
{

    display.FullScreenBMP(Menu_trial_startbut_Stop);
    wait(2);

    wait(2);
    display.FullScreenBMP(Menu_trial_startbut_RealTimeView);
    wait(2);
    display.FullScreenBMP(Menu_trial_startbut_Alert);
    wait(2);
    display.FullScreenBMP(Menu_trial_startbut_Status);
    wait(2);

}

void rtc()
{
    test_rw(my1307.gettime( &sec, &min, &hours, &day, &date, &month, &year));
    pc.printf("seconds read are %.2D \n\r",sec);
    pc.printf("min read are %.2D \n\r",min);
    pc.printf("hour read are %.2D \n\r",hours);
    pc.printf("day read are %.2D \n\r",day);
    pc.printf("date read are %.2D \n\r",date);
    pc.printf("month read are %.2D \n\r",month);
    pc.printf("year read are %.2D \n\r",year);
    pc.printf("SerPrinter");
}

void LCDcall()
{
    if(whichScreen == 1) {
        //temp alert
        //phase alert
        //overflow alert


        if(LCDviewer.read() == 5) {
            menu_alert = 0;
            LCDviewing = 0;
            LCDviewer.stop();
        }
    }
    if(whichScreen == 2) {
        LCDiteration++;
        if(LCDiteration == 1) {
            display.ClearScreen();
            display.SelectFont(System5x7,BLACK,ReadData);
            display.GotoXY(60,0);
            if (overflow == 1) {
                display.PrintString(" HLT filling");
                display.GotoXY(1,0);
                display.PrintString("up");
            }
            if(_heat_HLT == 1) {
                if(phase1 == true) {
                    display.GotoXY(60,0);
                    display.PrintString(" Heating HLT");
                    display.GotoXY(1,0);
                    display.PrintString("to 122'F");
                } else if(phase2 == true) display.PrintString(" Heating HLT to 154'F");
                else if(phase3 == true) display.PrintString(" Heating HLT to 168'F");
            }
            if(step3 == true) {
                display.PrintString(" In Step3 checking time");//phase1_phase2_step3_timecheck();
            }
            if(flowmeterON == true) {
                if(phase1 == true)display.PrintString(" Filling water upto 20 quarts");
                if(phase2 == true)display.PrintString(" Filling water upto 18 quarts");
                if(phase3 == true)display.PrintString(" Filling water upto 20 quarts");
            }
        }
        viewTIME = LCDviewer.read();
        if(viewTIME == 5) {
            menu_status = 0;
            LCDviewing = 0;
            LCDviewer.stop();
            LCDviewer.reset();
            display.ClearScreen();
            LCDiteration = 0;
            display.FullScreenBMP(Menu_trial_startbut_Stop);
            viewTIME = 0;
        }
    }
    if(whichScreen == 4) {
        LCDiteration++;
        if(LCDiteration == 1) {
            display.ClearScreen();
            display.SelectFont(System5x7,BLACK,ReadData);
            display.GotoXY(60,0);  //(60, 0)
            display.PrintString(" temp -");
            display.GotoXY(1,0);  //(60, 0)
            display.PrintString("122");
        }
        viewTIME = LCDviewer.read();
        if(viewTIME == 5) {
            menu_temp = 0;
            LCDviewing = 0;
            LCDviewer.stop();
            LCDviewer.reset();
            display.ClearScreen();
            display.FullScreenBMP(Menu_trial_startbut_Stop);
            viewTIME = 0;
            LCDiteration = 0;
        }
    }

}

void IR_function(void)
{
    if (ir_rx.getState() == ReceiverIR::Received) {
        ir_rx.getData(&format, buf, sizeof(buf) * 16);
        pc.printf("\n\rgot>> ");
        for (int i=0; i<sizeof(buf); i++) {
            pc.printf("0x%02X, ", buf[i]);
            //pc.printf("%i",i);
        }
        if(menu_stop == true && buf[2] == 0x01) {
            overflow = 0;
            flowmeterON = 0;
            step3 = 0;
            _heat_HLT = 0;
            pc.printf("Stopped");
            display.FullScreenBMP(starts);
            menu_stop = false;
            buf[2] = NULL;
        }
        if(buf[2] == 0x01) {
            start = 1;
            waterValve();
            pc.printf("Started");
            display.FullScreenBMP(Menu_trial_startbut_Stop);
            menu_stop = true;
            buf[2] = NULL;
        }
        if(buf[2] == 0x0A && start == 1 ) {//1 button
            display.FullScreenBMP(Menu_trial_startbut_Temp);
            menu_temp = 1, menu_status = 0, menu_alert = 0, menu_realview = 0;
            _heat_check_HLT(122);
        }
        if(buf[2] == 0x1F && start == 1) {//3 button
            display.FullScreenBMP(Menu_trial_startbut_Status);
            menu_status = 1, menu_temp = 0, menu_alert = 0, menu_realview = 0;
        }
        if(buf[3] == 0xFF && start == 1) {//7 button
            display.FullScreenBMP(Menu_trial_startbut_Alert);
            menu_alert = 1, menu_status = 0, menu_realview = 0, menu_temp = 0;
        }
        if(buf[2] == 0x19 && start == 1) {// 9 button
            display.FullScreenBMP(Menu_trial_startbut_RealTimeView);
            menu_realview = 1;
        }
        if(buf[2] == 0x04) {
            for(int i=0; i<4; i++) {
                if(menu_alert == 1) {
                    LCDviewing = 1;
                    whichScreen = 1;
                    LCDviewer.start();
                }
                if(menu_status == 1) {
                    LCDviewing = 1;
                    whichScreen = 2;
                    LCDviewer.start();
                }
                if(menu_realview == 1) {
                    LCDviewing = 1;
                    whichScreen = 3;
                    LCDviewer.start();
                }
                if(menu_temp == 1) {
                    LCDviewing = 1;
                    whichScreen = 4;
                    LCDviewer.start();
                }
            }

        }
        switch (format) {
            case RemoteIR::UNKNOWN:
                pc.printf("????");
                break;
            case RemoteIR::NEC:
                pc.printf("NEC");
                break;
            case RemoteIR::AEHA:
                pc.printf("AEHA");
                break;
            case RemoteIR::SONY:
                pc.printf("SONY");
                break;
        }
    }
}

int main()
{
    display.ClearScreen();
    display.FullScreenBMP(pic);
    wait(2);
    display.FullScreenBMP(brew1);
    wait(2);
    display.FullScreenBMP(starts);
    wait(2);
    memset(buf, 0x00, sizeof(buf));
    v5 = 0xff;
    flowmtr1_wait.attach(&flowmtr1_counter, 1.0);
    temperature_pin.output();
    temperature_pin = 0;
    temperature_pin.input();
    //LCDrunner();
    while(1) {
        IR_function();
        //_heat_check_HLT(122);
        if(overflow == 1) {
            overflow_check();
        }
        if(_heat_HLT == 1) {
            if(phase1 == true) {
                h1 = 0xff;
                _heat_check_HLT(122);
            } else if(phase2 == true) _heat_check_HLT(154);
            else if(phase3 == true) _heat_check_HLT(168);
        }
        if(step3 == true) {
            phase1_phase2_step3_timecheck();
        }
        if(flowmeterON == true) {
            if(phase1 == true)flowmeter1(20);
            if(phase2 == true)flowmeter1(18);
            if(phase3 == true)flowmeter1(20);
        }
        if(LCDviewing == 1) {
            LCDcall();
        }
        if(MLT_diluting == 1) {
            phase3_MLT_diluting_routine();
        }
        if (kettleBOIL) {
            kettleBoilingRoutine();
        }
    }
}

// Example of how to put Text on LCD
//display.DrawBitmap(mikro_test,5,5,BLACK);
08 Nov 2013

The KS0108 display has two controllers. They share most pins, but have separate chip select pins _CS1, _CS2.

// KS0108 (PinName _RST,PinName _DI, PinName _RW, PinName _E, PinName _CS1, PinName _CS2, PinName DB0, PinName DB1, PinName DB2, PinName DB3, PinName DB4, PinName DB5, PinName DB6, PinName DB7);
KS0108  display(PTC3,PTD6, PTE31, PTA17, PTC5, PTC4, PTA16, PTC17, PTC16, PTC13, PTC12, PTC11, PTC10, PTC6);

When half the display is ''gone'' I would check for either a faulty or shorted CS line (PTC5 or PTC4) or check if one of the two controllers is dead.

09 Nov 2013

Hi Wim thanks a lot for a healthy suggestion, well the complete GLCD display works but as I said after the code that turns other things like tip122's ON only then the GLCD's half display is gone(PLEASE SEE THE ATTACHED VIDEO /media/uploads/Nishant/20131109_104828_22_feet_rd-1-.mp4 ) most probably meaning as you said the PTC5 or PTC4 lines would be short

09 Nov 2013

Checked on the PTC5 and PTC4 and other cables going to and fro from the kl25z board can't see any glitch or problem. So what else is there? HAve you seen the video?

09 Nov 2013

Judging by the video it looks like one controller suddenly quits. This is probably due to a spurious reset or powerglitch. That would normally affect both controllers, but sometimes one may be more sensitive than the other. I would check resetline, make sure it is pulled up strong enough, perhaps add small cap for buffering. Also check power and gnd lines. Add some capacitor buffers or filters close to the display. You may have to use separate supplies for the outputs you are driving. What is circuitry for drivers, could there be a glitch going back into the kl25z outputpin. You said you measured voltagelevel and it is healthy. However, a multimeter is way too slow to detect a microsecond glitch which can reset the controller. How close is the displayboard to any relais or powerlines. There may be EMC issues directly affecting a nearby controller that results in reset. Do you have the same problem when the enclosure is opened and the display is some distance from the electronics. In that case some shielding or better cable routing may solve the problem.

11 Nov 2013

Hi Wim,

Your reply is healthy enough. I already put a 25uF and a decoupling cap on the logic level power supply to the LCD BUT NOT NEAR it as Im using socket to connect to the LCD. I was also thinking about the powerglitch since pushing the IR remotes button activates a function that inturn run output pin to open the TIP122 which in turn takes supply from a regulated voltage 5v the same which is used to power the LCD, So I will try to use a separate only for GLCD logic level power and tell you the result! Till then it would be kind of you to keep a look on thread!

Thanks!

11 Nov 2013

Wim That worked!

11 Nov 2013

Nishant Sood wrote:

Wim That worked!

Great!

You may want to experiment some more to find the optimal solution wrt stability:

  • Use separate GND and powerlines to all devices. Merge power and gnd lines only at a single central node
  • Shield or twist power and gnd lines to avoid picking up noise in a noisy industrial environment
  • Note that mbed itself is also sensitive to noise. Several reports mentioned that the reset button or nRst pin on mbed picked up noise resulting in spurious resets. Make sure you shield and pull-up the pin or even the switch.
  • Add some decoupling Cs on input pins if you dont have high update rates.
  • Ground or pull down all unused input pins

Regards, Wim