CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Easy Graphics on 128x64 LCD using Digole Serial Adapter

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Easy Graphics on 128x64 LCD using Digole Serial Adapter
PostPosted: Wed Dec 03, 2014 1:38 pm     Reply with quote

I connected the Digole Universal Graphic Serial LCD Adapter to a 16F882 PIC and wrote a test program.
Operation was the same as their I2C board that I used on a 1602 type 2x16 LCD and I was able to use the same program, just changed the 4 wires around. See my other project in this forum
"I2C on Digole serial control module for LCDs"
I used address 0x4E not 0x27 as before. Apparently something to do with 7 bits. Can someone explain this? I thought only Teletypes used 7 bits.
The I2C jumper must be made on the board or it won't work, and the p for parallel jumper must be made on the LCD or there will be lots of noise and streaks and garbage showing on the LCD.
After a bit of experimenting I had the following demo program running. It shows various text displays, makes a rather pretty pattern and overwrites it, then makes a windshield wiper display which illustrates how to delete certain parts of a display.
I have progressed into trying to do this using math but now have an out of RAM error which I hope someone can help me with. This problem starts after this post. This program works.

Code:
////////////////////////////////////////////////////////////////////////////////////////
// File  Graphics Demo.c                                                          //
// Digole Serial Adapter for 128x64 Graphic LCD                                      //
// Demo draws Text, floating point formatting, growing circles, and windshield wiper  //
// 2 Dec 2014                                                              WORKING    //
////////////////////////////////////////////////////////////////////////////////////////

/* Pre-processor directives */
 #include <16F882.H>
 #include <math.h>
 #fuses INTRC_IO, NOWDT, PUT, NOPROTECT, BROWNOUT, MCLR
 #use delay (clock=1000000)
 #use I2C (master, SCL=PIN_C3, SDA=PIN_C4)
 #byte portc = getenv("SFR:PORTC")
 

// define I2C address
#define LCD_WRT_ADDR 0X4E               // LCD display
#define buff_size 22                    // characters per line plus one
   
// Function prototypes
    void clear_LCD (void);                      // Clear LCD
    void cursor(short ctrl);                    // Turn cursor ON(1) or OFF(0)
    void ctrl_start (int ctrl);               // Turn Start Screen ON or OFF
    void control_addr (short ctrl);             // Turn on mode
    void text_position (int line, int column);  // set start for next text
    void set_font (char size);                  // set font size
    void send_str(char buff[buff_size]);        // Send string to LCD
    void draw_line(int x, int y, int x1, int y1);  // draw a line from x,y to x1,y1
   
// The main function
void main(void)
 {
// declare variables
  char i,j;
  int x_pos[12]={112,104,96,86,75,64,53,42,32,24,16};   // x positions
  int y_pos[12]={24,16,9,5,2,1,2,5,9,16,24};            // y positions
  set_tris_c (0x00);                 // all outputs
  short ON=TRUE;
  short OFF=FALSE;
  int1 fill=OFF;
  char buff[buff_size];
  float BV=12.43;

// Setup start screen. Only do these one at a time and only once
// then comment out and re-program to get rid of Digole screen.
//  control_addr(OFF);                  // control startup display
//  ctrl_start(OFF);                    // turn Digole screen ON/OFF
//  cursor(ON);                         // turn cursor ON
//  delay_ms(2000);                     // for 2 seconds

// Start the alphanumeric display sequence
  clear_LCD();                          // clear the LCD
  sprintf(buff, "Graphics Demo");         // place text string in buffer
  send_str(buff);                       // display text array
  delay_ms(2000);                       // for 2 seconds
 
  text_position(0,1);                   // start second line
  set_font(10);                         // change text to size 10
  sprintf(buff, "123456789012345678901"); // place text string in buffer
  send_str(buff);                       // display text array
  delay_ms(2000);                       // for 2 seconds
  text_position(0,3);                   // start of 4th line 
  sprintf(buff, "disp floating point"); // place text string in buffer
  send_str(buff);                       // display text array
  cursor(OFF);                          // turn cursor OFF
  text_position(0,4);                   // start of 5th line   
  sprintf(buff, "in different position"); // place text string in buffer
  send_str(buff);                       // display text array
  delay_ms(2000);                       // for 2 seconds 
  text_position(4,5);                   // 5th column, 6th line     
  sprintf(buff, "Battery %5.2fv", BV);  // place text string in buffer
  send_str(buff);                       // display formatted floating point
  delay_ms(4000);                       // for 4 seconds
// display growing circle
  clear_LCD();                          // clear screen
  sprintf(buff, "Growing Circle:");     // display "Growing Circle"
  send_str(buff);
  delay_ms(4000);
  clear_LCD();
  delay_ms(1000);
       
// draw the circles
While (1)
{
for (j=1; j<=2; J++)
 {
  for (i=5; i<30; i++)
  {
  I2C_START ();                // start I2C
  I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
  I2C_WRITE ('C');
  I2C_WRITE ('C');
  I2C_WRITE (32+i);
  I2C_WRITE (32);
  I2C_WRITE (i);
  I2C_WRITE (fill);            // set fill, 0=OFF, 1=ON
  I2C_STOP ();                 // stop I2C
  delay_ms(250);
  }
 fill = fill ^ ON;              // alternate fill On & OFF
 }

// Draw a winshield wiper
  clear_LCD();                       // sets font back to default
  set_font(10);                      // change text to size 10
  sprintf(buff, "Windshield Wiper"); // place text string in buffer
  send_str(buff);                   // display text array
  delay_ms(2000);                   // for 2 seconds
  while(1)
  {
   for (i=0;i<=10;i++)
   {
   draw_line(63,63,x_pos[i],y_pos[i]);
   delay_ms(500);
   clear_LCD();
   }
   for(i=9;i>0;i--)
   {
   draw_line(63,63,x_pos[i],y_pos[i]);
   delay_ms(500);
   clear_LCD();
   }
  }                               // end of while loop
 }                               // end of while loop
}                              // end of main function

// Functions
// Clear Display
void clear_LCD (void)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('C');             // C CL to clear display
   I2C_WRITE ('L');             // L
   I2C_STOP ();                 // stop I2C
   }
// Turn cursor ON or OFF
void cursor(short ctrl)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('C');             // C, CS0 to control cursor
   I2C_WRITE ('S');             // S
   I2C_WRITE (0);            // 1=ON, 0=OFF
   I2C_STOP ();                 // stop I2C
   }
// Control Start Screen
void ctrl_start (short ctrl)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('D');             // D DSSb to ccontrol Digole screen
   I2C_WRITE ('S');             // S
   I2C_WRITE ('S');             // S
   I2C_WRITE (ctrl);            // 1=ON, 0=OFF
   I2C_STOP ();                 // stop I2C
   }
// Display Configuration: Control address display
void control_addr (short ctrl)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE (0x44);            // D, to display I2C address
   I2C_WRITE (0x43);            // C
   I2C_WRITE (ctrl);            // 1=on, 0 to turn off
   I2C_STOP ();                 // stop I2C
   }
// set position of next text
void text_position(int line, int column)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('T');            // T, TP set text position
   I2C_WRITE ('P');            // P
   I2C_WRITE (line);            // line position
   I2C_WRITE (column);          // column position
   I2C_STOP ();                 // stop I2C
   }
// Set Font Size
void set_font (char size)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('S');
   I2C_WRITE ('F');
   I2C_WRITE (size);
   I2C_STOP ();                 // stop I2C
   }
// send string to LCD
void send_str(char buff[buff_size])
   {
   int i;
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE('T');              // send TT for text coming
   I2C_WRITE('T');
    for (i=0; i<buff_size; i++)
   {
   I2C_WRITE(buff[i]);          // start with a Z
   }
   I2C_WRITE(0);
   I2C_STOP ();                 // stop I2C   
   }
// draw a line from x,y to x1,y1   
void draw_line(int x, int y, int x1, int y1)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('L');
   I2C_WRITE ('N');
   I2C_WRITE (x);
   I2C_WRITE (y);   
   I2C_WRITE (x1);
   I2C_WRITE (y1);
   I2C_STOP ();                 // stop I2C
   }
// end


I have no affiliation with Digole, I just like their products and they provide good service.


Last edited by rovtech on Wed Dec 03, 2014 8:34 pm; edited 2 times in total
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Problems with math functions
PostPosted: Wed Dec 03, 2014 2:07 pm     Reply with quote

I tried to replace the x,y points with math generated points but I get a "Not enough RAM for all variables" error. I really only want x and y to be integers and would like to round them off to such.
I draw 19 lines from the point 63,63 (bottom center) every 10 degrees from 0 to 180 degrees but CCS C uses radians hence the strange numbers i use to calculate. From 63,63 origin the calculations x=63cos(angle), y=63sin(angle) for lines 64 pixels long (0 to 63).
Also the reference of 63,63 must be converted to the LCD top left at 0,0 so the add and subtract from 63.
Can some math genius tell me how I can simplify this to use less RAM.

Code:
// The main function
void main(void)
 {
// declare variables
  char i,j;
  set_tris_c (0x00);                 // all outputs
  char buff[buff_size];
  float angle, x, x1, y;

  clear_LCD();                          // clear the LCD

// Draw vector lines
  while(1)
  {
   for (i=0;i<=18;i++)
   {
   angle=i*.165;
   x1=63*cos(angle);
   y=63*sin(angle);
   if(i<=8)
     x=63+x1;
   else
     x=63-x1;
    y=63-y;
   draw_line(63,63,x,y);
   delay_ms(500);
   }
  }                              // end of while loop
}                             // end of main function
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 03, 2014 3:35 pm     Reply with quote

Quote:
#include <16F882.H>

Your PIC is the lowest one in the 16F887 family. It only has 128 bytes of
ram. That's your problem. If you want to stay with the 28-pin package,
I suggest that you upgrade to the 16F886, since it has 368 bytes of ram.
You will also get 4x the ROM as well.

Quote:
I used address 0x4E not 0x27 as before. Apparently something to do with 7 bits. Can someone explain this? I thought only Teletypes used 7 bits.

Teletype is irrelevant. See this thread for more details:
http://www.ccsinfo.com/forum/viewtopic.php?t=45628&start=2
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Switch to 16F1938
PostPosted: Wed Dec 03, 2014 6:51 pm     Reply with quote

Thanks, I did not realize how little RAM it has.
I switched to a 16F1938 which has 1024 RAM and is pin compatible.
My math seems OK as I am now displaying the sweep lines.
I need to be able to calculate positions on the screen for returns from a scanning sonar.
I asked Microchip why they were so skimpy with RAM and they said it was expensive. I don't understand this as I can get 5GB on a USB for $5.
Can you comment on the 7 bit address issue on the I2C adapters? I just don't understand since everything else about them is 8 bit.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Dec 03, 2014 7:37 pm     Reply with quote

They wanted a byte-oriented protocol. They needed a R/W bit.
That leaves 7 bits free in that byte for the address.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Math method works
PostPosted: Wed Dec 03, 2014 8:26 pm     Reply with quote

Here is the math method of a windshield wiper effect of drawing lines.
There were mistakes in the first attempt. This one seems to work. I will have to think on the 63 and 64. The compiler converts floating to integer; I'm not sure if this is the correct way.

Code:
// The main function
void main(void)
 {
// setup ports
  set_tris_c (0x00);                 // all outputs
// declare variables
  char i=0;
  float xx;
  int y,x;
  float angle;
   
// Start the display sequence
   clear_LCD();                          // clear the LCD
   delay_ms(400);

// Draw vector lines
  while(1)
  {
   for (i=0;i<=19;i++)
// go counterclockwise in 10 degree steps
   {
   angle=i*.175;
   xx=63*cos(angle);
   x=xx;                      // make integer
   xx=63*sin(angle);
   y=xx;                      // make integer
   x=63+x;                  // counterclockwise
   y=63-y;
   draw_line(63,63,x,y);
   delay_ms(400);
   }
   clear_LCD();             // clear the LCD
// go clockwise in 10 degree steps
   for (i=0;i<=19;i++)
   {
   angle=i*.175;
   xx=63*cos(angle);
   x=xx;                      // make integer
   xx=63*sin(angle);
   y=xx;                      // make integer
   x=63-x;                   // clockwise
   y=63-y;
   draw_line(63,63,x,y);
   delay_ms(400);
   }
   clear_LCD();             // clear the LCD
  }                     // end of while loop
}                     // end of main function
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Thu Dec 04, 2014 1:44 am     Reply with quote

5GB on USB, is flash, not RAM.
The 16F882, costs only a dollar in quantity. For 5$, you could be using a PIC like the PIC33EP256MU806, with 256KB of ROM, 28KB of RAM and dozens of peripherals.
The small PIC's are built for mass use at low cost. It's always much easier for a one off application to use one bigger than you need rather than trying to shoehorn into a small chip. Save this for jobs were 100000 units are to be made and saving a cent matters.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PIC options
PostPosted: Thu Dec 04, 2014 2:58 pm     Reply with quote

Thanks for the suggestion. I will keep it in mind if the need ever arises.
Can I use it with PCM?

I have used a 64 pin surface mount PIC on an adapter board, which worked, but it was not as convenient as DIP packages. Surface mount are tedious to solder, cannot be easily replaced, and take a lot of room. Sockets are available, but are big and expensive.

I prefer to dedicate a PIC to a task and have a master handling several other PICs on I2C. I have a project that needs 5 LCDs so will put each on a serial adapter and drive them all from one PIC on 2 wires. Features can be added on another board then connected to the I2C lines.

I never ran out of memory before, but then a famous man once said he couldn't see anyone needing more than 64k of memory on a PC.

I will standardize on the 16F1938 for small projects, and the 16F1939 if I need more outputs. I try to keep things simple.
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 6:45 am     Reply with quote

couple years ago I 'standardized' on the 18LF46K22 as my 'goto' PIC. Yes, overkill for 99% of the projects BUT 40 pins does give a lot of options, especially when you consider 2 HW UARTS, 2SPI, lots of memory,etc. I'm not into the 'smaller is better' thing,heck can't read the numbers on the DIPS anymore.Bigger is better...allows more room to fthe 'extra' stuff the client wants or the programmer needs( one-more-pin).
Another benefit of using a bigger PIC, is you build a library of code YOU use all the time AND you KNOW it works, so using the same PIC over and over is a good thing.
You can waste a LOT of expensive R&D time getting 'familiar' with a new PIC only to find out it won't quite do the job.arrgh....BTDT...so while a bigger PIC costs more per piece you can save a lot of $$$ in producing quicker code,getting the project done and out the door.

just food for thought.

Jay
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Distributed hardware
PostPosted: Fri Dec 05, 2014 8:04 am     Reply with quote

Thanks for the thoughts Jay,
no one answered my question of PCM compatibility. Is your 18LF46K22 PCM compatible? I will upgrade if I have to but what I have works for my ROV hobby.
My control console uses a 40 pin PIC to read 16 switches, 3 pots, and display on 5 LCDs as well as a bunch of other stuff. I use a lot of octal latches because that is the way I knew when I started over 5 years ago. These I2C LCD drivers, and some I2C to 8 bit boards at $1 each will simplify the design.
The console sends commands to the ROV and gets data, like compass and depth, back on RS485 on a twisted pair. Video is returned on another twisted pair, and high voltage is sent down to a converter on another twisted pair to charge the battery.
The ROV has a master 40 pin PIC that handles the communications with the surface and disseminates, using I2C, the commands to three 28 pin PICs that control 5 motors and 2 servos with PWM. Reading battery parameters, compass, clinometers, pressure transducers, and other items ties up the PICs so if only one was used my updates with the surface would be too slow. Another PIC is soon to be added to control a robot arm and will be located within the arm so I2C makes sense here as well. A scanning sonar requires yet another PIC, maybe two.
I just don't see one giant board with one PIC trying to do everything. I may be wrong but my method allows me to add features with just 4 wires without touching the existing design, except a bit of software.
I am spread pretty thin with machining, electronic design, drawing schematics, laying out boards, writing software, and learning new skills all the time. Then there are my other projects...
You guys are my only useful source for help in programming so are much appreciated.
I will edit this post later and add a link where you can see photos if you are interested.

You can see photos of my ROV project at the link below. Search on "Peter & Janice Bunge", "Peter Bunge" and ROVMKR. I don't know why Yahoo started putting my name in my posts. My latest post with a photo of the LCD has not appeared yet.

https://groups.yahoo.com/neo/groups/robotrov/conversations/messages


Last edited by rovtech on Fri Dec 05, 2014 9:06 am; edited 2 times in total
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 8:42 am     Reply with quote

you'd need to upgrade to pcwhd... maybe search for a 16 series PIC with more features and check with CCS website to see what PCM currently is good for, things change mighty fast these days !

I also had to upgrade to a PICkit3 as my trust PICstart+ didn't pgm newer chips...

Your 'distributed control' method is a sound design,allows for easy expansion and yet have a solid 'core' ! Heck, if it ain't broke, no need to fix it ! I'm still on a 4.xxx version of compiler and never 'upgrade' anything unless I really,really need to.

cheers
Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Dec 05, 2014 2:57 pm     Reply with quote

Quote:
no one answered my question of PCM compatibility. Is your 18LF46K22 PCM compatible?

This page shows which compiler is required for each PIC:
http://www.ccsinfo.com/devices.php?page=devices
Short answer: 18F requires PCH compiler, either as a separate command-
line compiler or part of a combined IDE package.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group