Archive for Digital Electronics

Digital Thermometer monitoring up to 10 different areas

facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Hello, こんにちは,

私の日本語があまり上手くありませんが許して下さい.

One day i was talking with a client and he mentioned that he has a chicken egg incubator and that it is hard to keep track of the temperature inside. I offered my help to build a device that can display the temperature of all the incubators on the same screen.

これは10の分野のためのデジタル温度計です。それがPIC18F4620マイクロコントローラ、LM35温度センサとDigole12864ZW LCDを使用しています。記事の終わりには、Cのソースコード、HEXファイルとPCBレイアウトを見つけることができます。

For this task i used a PIC18F4620 and a Digole 12864ZW graphic LCD. Sensor units (LM35) are separate and i will not discuss it in this article.

The below image (figure 1) shows the electronic schematic of the monitor. J1-10 are 3 pin terminal blocks like the ones in figure 2. Each terminal block provides +5V and ground connection and a pin for sensor data.

Temperature Monitor Digole 12864ZW PIC18F

Figure 1

3 pin TBlock Connector

Figure 2

The circuit is very simple each sensor is connected to one of the ADC inputs of the PIC18F4620 through a 100 ohms resistor and the rest is basically software. The LCD is configured to work in parallel 8 bit mode because it is easier and the microcontroller has enough I/O pins available.

Working with the display was a bit hard in the beginning as the documentation isn’t really clear on some aspects. There weren’t many resources from other DIY-ers that used this display either. I got it to work in graphic mode using a XLCD library from Microchip and Application Maestro to configure it. You can use this library for text mode with no modifications.

I will cover the graphic mode of the Digole LCD in a future article describing in detail how it works.

Once you have generated the XLCD files using application Maestro (setting the data port to port D, RS pin to RB5, RW pin to RB6 and EN pin to RB7, delay mode), you will need to modify XLCD.c file and specifically XLCDinit() function. You can delete it if you want and copy the one below:

void XLCDInit(void)
{
_vXLCDreg=1;

XLCD_DATAPORT_TRIS  = 0x00;
XLCD_DATAPORT = 0;
XLCD_RSPIN_TRIS =0;                        
XLCD_ENPIN_TRIS =0;
XLCD_RWPIN_TRIS =0;
XLCD_RSPIN  =0;                            
XLCD_ENPIN  =0;
XLCD_RWPIN=0;                              
XLCDDelay15ms();
XLCD_DATAPORT   = 0b00110000;  
XLCDDelay4ms();
XLCD_DATAPORT   = 0b00110000;  
XLCDDelay4ms();
XLCDCommand(0x0C);
XLCDDelaylcd();   
XLCDCommand(0x01);
XLCDDelay15ms();  
XLCDCommand(0x06);
XLCDDelaylcd();
XLCDCommand(0x34);
XLCDDelay15ms();    
XLCDCommand(0x36);
XLCDDelay15ms(); 

_vXLCDreg=0;
return;
}

I created functions to display digits and some special characters. Basically these functions accept coordinates as their arguments and draws the specific pixels at the proper address. An example of such a function is below:

void display1(int x, int y)
{
        if(y<27)
    {
            XLCDCommand(0x80 | y);
            XLCDCommand(0x80 | x);
                XLCDPut(0b00000000);
                XLCDPut(0b00000000);
            XLCDCommand(0x80 | y+1);
            XLCDCommand(0x80 | x);
                XLCDPut(0b00000000);
                XLCDPut(0b00000000);
            XLCDCommand(0x80 | y+2);
            XLCDCommand(0x80 | x);
                XLCDPut(0b11111000);
                XLCDPut(0b00000000);
            XLCDCommand(0x80 | y+3);
            XLCDCommand(0x80 | x);
                XLCDPut(0b00000000);
                XLCDPut(0b00000000);

    }            
    else
    {
            XLCDCommand(0x80 | y-27);
            XLCDCommand(0x88 | x);
                XLCDPut(0b00000000);
                XLCDPut(0b00000000);
            XLCDCommand(0x80 | y-26);
            XLCDCommand(0x88 | x);
                XLCDPut(0b00000000);
                XLCDPut(0b00000000);
            XLCDCommand(0x80 | y-25);
            XLCDCommand(0x88 | x);
                XLCDPut(0b11111000);
                XLCDPut(0b00000000);
            XLCDCommand(0x80 | y-24);
            XLCDCommand(0x88 | x);
                XLCDPut(0b00000000);
                XLCDPut(0b00000000);

    }    
}

As can be seen XLCDCommand sets the address and XLCDPut sets the value. These functions are defined in XLCD library from Microchip. The condition set for y coordinate is needed because of the way the LCD is made. It is split in two horizontally. Data width is 16 bits sent in two transmissions of 8 bits each.

Each bit in the 16 bits word represents the state of a pixel so you always draw 8 pixels with each instruction. This can be annoying when trying to write values that change dynamically. So you can’t control one pixel at the time horizontally, but you can control each vertical line. This is why i turned the display on a side and it proved much easier to draw the graphs.

digole 12864ZW PIC18F LCD

digole 12864ZW PIC18F LCD

digole 12864ZW PIC18F LCD

The role of SW1 push button is to switch between the screens on Digole 12864ZW showing time graphs and bar graph for each of the 10 sensors. The program verifies the state of SW1 on each loop so it will require to hold the button for about 1second. Also holding too long might cause the screen to go beyond the area you need.

The button is verified with the switch(counter) function in main(). Case 0 is the first screen displaying all the sensors. Cases 1 -> 10 correspond to individual areas and call the zone(area) function, where area takes a value between 0 and 9.

Here is how the zone(area) function looks like:

void zone(int area)
{
        int i;
        int val_t;
        int val_mem;
        xygraph(); // function that displays the time chart
        bargraph(); // function that displays the bargraph
        // below instructions display 0 Celsius
        XLCDCommand(0x80 | 30);
        XLCDCommand(0x80 | 4);            
        XLCDPut(0b00000000);
        XLCDPut(0b11100000);
        XLCDCommand(0x80 | 29);
        XLCDCommand(0x80 | 4);            
        XLCDPut(0b00000000);
        XLCDPut(0b10100000);
        XLCDCommand(0x80 | 28);
        XLCDCommand(0x80 | 4);            
        XLCDPut(0b00000000);
        XLCDPut(0b11100000);
        XLCDCommand(0x80 | 26);
        XLCDCommand(0x80 | 4);            
        XLCDPut(0b00000000);
        XLCDPut(0b01110000);
        XLCDCommand(0x80 | 25);
        XLCDCommand(0x80 | 4);            
        XLCDPut(0b00000000);
        XLCDPut(0b10001000);
        XLCDCommand(0x80 | 24);
        XLCDCommand(0x80 | 4);            
        XLCDPut(0b00000000);
        XLCDPut(0b10001000);
        XLCDCommand(0x80 | 26);
        XLCDCommand(0x80 | 6);            
        XLCDPut(0b01110000);
        XLCDPut(0b00000000);
        XLCDCommand(0x80 | 25);
        XLCDCommand(0x80 | 6);            
        XLCDPut(0b10001000);
        XLCDPut(0b00000000);
        XLCDCommand(0x80 | 24);
        XLCDCommand(0x80 | 6);            
        XLCDPut(0b10001000);
        XLCDPut(0b00000000);
        if(SW == 0) // Checking button
        {
            counter++;
        }
        switch(area) //display the area number
        {
            case 0: display0(6,17);break;
            case 1: display1(6,17);break;
            case 2: display2(6,17);break;
            case 3: display3(6,17);break;
            case 4: display4(6,17);break;
            case 5: display5(6,17);break;
            case 6: display6(6,17);break;
            case 7: display7(6,17);break;
            case 8: display8(6,17);break;
            case 9: display9(6,17);break;
        }
        //level display
        val_t=ADC_Read(area); //read the sensor specific to that area
        val_mem=val_t*48; //convert to degrees
        chart(val_mem); // plot value on xychart
        showtemp(val_mem,5,35); // displays the temperature
        showlevel(val_mem); // displays level on bar graph

        for(i=0;i<25;i++) // delay
        {
        XLCDDelay15ms();
        }

}

 

At the end of the article you can download the full C file without the XLCD library also the hex file. Below you can see a version of double sided PCB layout, images are not mirrored:

PCB Temperature Monitor

top silk

PCB Temperature Monitor

Top Copper

PCB Temperature Monitor

Bottom Copper

On the PCB J13 corresponds to SW1 in the schematic.

Temp Monitor PIC18LH4620 Digole 12864ZW

Thank you for visiting,

ご覧いただきありがとうございます。

 

 

Using Digole 12864ZW LCD with PIC18F

PIC18F interface with digole 12864ZW PIC18Fとグラフィック ディスプレイのインターフェイス facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Hello, こんにちは,

私の日本語があまり上手くありませんが許して下さい.

PIC18Fとグラフィック ディスプレイのインターフェイス

Digole 12864ZW is a 128×64 pixels graphic LCD that can be found at attractive prices and this is why it started appearing in projects across the web. It is based on ST7920 chip which is not so well known and to me it wasn’t the easiest to work with.

私は、グラフィックモードでDigole12864ZWを使用する方法について記述します。C18コンパイラとPIC18F4620を使用しています。

ここで、LCDのデータシートです。

The documentation for this display can be found here. You can find a couple of examples on how to use this display and some attempts on making a library and most of this information is for interfacing with arduino. For PIC interfacing i couldn’t find much info.

The module has a 20 pin connection, each described below. Vout i havent used and left it unconnected. For contrast you can use V0 (pin 3) by connecting it to Vdd through a 10k variable resistor. However to get it to work you will need to enable jumper J1 from the back of the module as in figure 1.

Pin # Function
1 Vss
2 Vdd
3 V0
4 RS
5 RW
6 EN
7 DB0
8 DB1
9 DB2
10 DB3
11 DB4
12 DB5
13 DB6
14 DB7
15 PSB
16 NC
17 RST
18 VOUT
19 BLA
20 BLK
Digole 12864ZW PIC18F contrast

Figure 1

As per the datasheet the display can be used in many ways and this is a strong feature. I used it the traditional way 8 bits parallel. For this, PSB pin must be connected to Vdd, i also connected RST pin to Vdd as i will reset the display in software. The rest of the connections are the same as with any 16×2 alphanumeric displays.

コントラストが機能するためには、J1を有効にする必要があります。写真1を参照してください。

Microchip XLCD library is a great starting point to using the Digole 12864ZW with a PIC microcontroller. I used Application Maestro to set up the library. As mentioned we will use 8 bits interface in delay mode. Set the ports and pins and the rest doesn’t really matter.

アプリケーションマエストロとのXLCDファイルの設定。

Application Maestro XLCD

Figure 2

Once done pressing Ctrl+G will generate the library files to be included in your project. You will need the XLCD.h, XLCD.c and XLCD.def. Now this Digole display can run in text mode with this library with major issues.To get to each line though you will need to go to specific addresses.

To use the LCD in graphic mode we will need to change the XLCDinit function in XLCD.c file. You can comment the one you have now and then copy paste the function below:

以下のコードでXLCD.cファイルにXLCDInitコードを交換してください。

void XLCDInit(void)
{
_vXLCDreg=1;

XLCD_DATAPORT_TRIS  = 0x00; 
XLCD_DATAPORT = 0;
XLCD_RSPIN_TRIS =0;                         
XLCD_ENPIN_TRIS =0;
XLCD_RWPIN_TRIS =0;
XLCD_RSPIN  =0;                             
XLCD_ENPIN  =0;
XLCD_RWPIN=0;                               
XLCDDelay15ms(); 
XLCD_DATAPORT   = 0b00110000;   
XLCDDelay4ms();
XLCD_DATAPORT   = 0b00110000;   
XLCDDelay4ms(); 
XLCDCommand(0x0C); 
XLCDDelaylcd();   
XLCDCommand(0x01); 
XLCDDelay15ms();  
XLCDCommand(0x06); 
XLCDDelaylcd();
XLCDCommand(0x34); 
XLCDDelay15ms();    
XLCDCommand(0x36); 
XLCDDelay15ms(); 

_vXLCDreg=0;
return;
}

The other two functions we will use from the XLCD library are XLCDCommand and XLCDPut, which are used to pass a command to the display and a value respectively. Using these functions you don’t have to worry about controlling RS , RW and EN.

After calling the XLCDinit() function in main() you have now setup the display in graphic mode. To start drawing you need first 2 XLCDCommand instructions that set the pixel address and then 2 XLCDPut instructions to draw the pixels.

In figure 3 you can see the address map of Digole 12864ZW in the operating mode described above. It can be observed the horizontally you cannot address pixels individually but in groups of 16 and values you can write in groups of 8. The 1st byte represents the byte in the first XLCDPut instruction and the 2nd byte the value in the 2nd instruction. You cannot make 1 byte to start at the middle of the address location. We have 8 addresses of 16 pixels each horizontally 8×16=128 pixels and 64 lines =>128×64 resolution.

Digole12864ZWグラフィックアドレスマップ

Digole 12864 Address Map アドレスマップ

Figure 3

//Example:

/* In figure 3 there are 4 red pixels. To set the pixel we need the following instructions:

Note that we are in region where x=0 => */

XLCDCommand(0b10010010); // 1st instruction

XLCDCommand(0b10000001); // 2nd instruction

XLCDPut(0b00110001); // 1st byte, red pixels are 1 in value

XLCDPut(0b00000010); // 2nd byte, red pixel is 1 in value

/* As you can see the position of the pixels in the two bytes are the positions of 1 in the XLCDPut values */

So to draw a horizontal line of a specific length you will need to take in consideration the fact that you will always set all 16 bits in one of the 8 horizontal addresses.

//Example: Draw line from pixel 41 to end of screen at line 10

/* x = 41/16 = 2; x_r = 41%16 = 9; This means we will start the line from the 2nd byte of horizontal address 010. y = 10 => H_ADDRESS = 0b10000010 */

// lets draw the first part of line 

int index_x, index_y, i;

index_y = 10;

index_x = 41/16;

XLCDCommand(0x80 | index_y); // V_ADDRESS

XLCDCommand(0x80 | index_x); //H_ADDRESS

XLCDPut(0x00); //1st byte is zero

XLCDPut(0x7F); //x_r%8 = 1 => values is 0xFF >> 1 meaning 0b01111111

//now draw to end of screen

for(i=3;i<8;i++)

{

XLCDCommand(0x80 | index_y);

XLCDCommand(0x80 | i);

XLCDPut(0xFF);

XLCDPut(0xFF);

}

Another good reason to use graphic mode is to create your own fonts for text. In its own text mode the display’s characters are very large and can only fit 4 lines. I have created my own set of characters of 7×7 pixels. I have used the fact that each horizontal address has two bytes so that i can fit a character’s width in one byte and leave 1 empty pixel as space. In Figure 4 you can see the W character and its pixel representation. It uses 1 byte on 7 lines so 7 bytes.

 

Character map DIgole 12864 display

Figure 4

This way each character can be represented as a vector of 7 bytes:

int chW[7]={ 146, 146, 146, 146, 146, 170, 68 };

To display a string i separate each character and based on its value i fill a matrix of [7][8] dimension representing a text line on the display. To use it easily the matrix is declared as follows:

union writebyte
{
struct
{
char LowByte;
char HighByte;
};

}linebytes[7][8];

This way you can easily call XLCDPut functions with LowByte or HighByte as arguments. Here is the case for W within the character switch function:

case ‘w':
{
for(j=0;j<7;j++)
{
if(k%2 == 0)
{
linebytes[j][k/2].LowByte=chW[j];
}
else
{
linebytes[j][k/2].HighByte=chW[j];
}
}
}break;

where j is the line number and k is the character number. Below you can see how it looks like:

 PIC18Fとグラフィック ディスプレイのインターフェイス

 PIC18Fとグラフィック ディスプレイのインターフェイス interfacing PIC18F with Digole 12864ZW

 PIC18Fとグラフィック ディスプレイのインターフェイス interfacing PIC18F with Digole 12864ZW

 

In the zip archive below you can find the font.h containing definitions for characters seen above and an example code for PIC18F4620 that displays the message stored in msg[] variable.

I will add more characters and functions with time but i hope this was helpful for anyone trying to interface Digole 12864ZW LCD to a PIC18F.

フォントの収集とPIC18F4620用のサンプル·コード

Digole 12864W sample code for PIC18F4620

Thank you for visiting,

ご覧いただきありがとうございます。

Using Software SPI with TFT Touchscreen

facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Hello,

In the previous article i wrote how you could implement a software SPI communication. These days i tried this solution with a TFT touchscreen using TSC2046 driver. This will also work for ADS7843 driver.

Basically you will need to call the Get_Value_SSPI function described in the previous article. As argument if we look in datasheet of TSC2046 or ADS7843 we see we need 0xD0 for x values and 0x90 for y values.

Example:

UINT16 TS_X, TS_y;

int x,y;

TS_X = Get_Value_SSPI(0xD0);

TS_Y = Get_Value_SSPI(0x90);

/* TS_X, TS_Y hold the ADC values from the touchscreen driver we need to convert them to coordinates. I cut last two digits as i dont need high precision and then scaled the values to correspond to a 800×480 TFT */

x=(TS_X/100)*1.26;

y=(TS_Y/100)*0.76;

I recorded a video of how it works, hope you enjoy it:

Thank you for visiting.