|
|
View previous topic :: View next topic |
Author |
Message |
rovtech
Joined: 24 Sep 2006 Posts: 262
|
Easy Graphics on 128x64 LCD using Digole Serial Adapter |
Posted: Wed Dec 03, 2014 1:38 pm |
|
|
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
|
Problems with math functions |
Posted: Wed Dec 03, 2014 2:07 pm |
|
|
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
|
|
Posted: Wed Dec 03, 2014 3:35 pm |
|
|
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
|
Switch to 16F1938 |
Posted: Wed Dec 03, 2014 6:51 pm |
|
|
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
|
|
Posted: Wed Dec 03, 2014 7:37 pm |
|
|
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
|
Math method works |
Posted: Wed Dec 03, 2014 8:26 pm |
|
|
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: 19537
|
|
Posted: Thu Dec 04, 2014 1:44 am |
|
|
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
|
PIC options |
Posted: Thu Dec 04, 2014 2:58 pm |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Fri Dec 05, 2014 6:45 am |
|
|
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
|
Distributed hardware |
Posted: Fri Dec 05, 2014 8:04 am |
|
|
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: 9241 Location: Greensville,Ontario
|
|
Posted: Fri Dec 05, 2014 8:42 am |
|
|
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
|
|
Posted: Fri Dec 05, 2014 2:57 pm |
|
|
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. |
|
|
|
|
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
|