Jump to content
chibiace

Nokia 5110 LCD ADC Graph

Recommended Posts

Hey, here is a little piece of code i cobbled together so that i could visualize my adc input and get a value reading along with it.

 

 

 

when the line reaches the end of the screen it starts again from the beginning and erases the old line, which was the simplest way i could think of doing it

 

the communication is bitbang and works on msp430g2231 and barely fits on there, tips on how to slim down my flashed code size would be very welcome.

 

thanks to other members on this forum whom i borrowed small bits and pieces from.

 

very fun to adjust the delays and amount of samples to see sine waves appear from a floating input pin.

 

post-60-0-55173200-1369153533_thumb.jpg

 

main.c:

#include "msp430g2231.h"
/*
Program for MSP430G2231 to display a Graph,ADC and Voltage on a Nokia 5110 Lcd
	       _____
	VCC  -| M G |- GND
	SCLK -| S 2 |- NC
	DIN  -| P 2 |- NC
	DC   -| 4 3 |- TEST
	CE   -| 3 1 |- RESET
	RST  -| 0   |- NC
	LED  -|_____|- ADC
*/
//Define Pins for LCD + Backlight LED and ADC
#define SCLK	BIT0
#define DIN	BIT1
#define DC	BIT2
#define CE	BIT3
#define RST	BIT4
#define LED	BIT5
#define ADC	BIT6

//Font for ADC and Voltage Display
static const char font[][5] = {
{0x40, 0x5f, 0x51, 0x5f, 0x40}  //0
,{0x40, 0x40, 0x40, 0x5f, 0x40} //1
,{0x40, 0x5d, 0x55, 0x57, 0x40} //2
,{0x40, 0x55, 0x55, 0x5f, 0x40} //3
,{0x40, 0x47, 0x44, 0x5f, 0x40} //4
,{0x40, 0x57, 0x55, 0x5d, 0x40} //5
,{0x40, 0x5f, 0x55, 0x5d, 0x40} //6
,{0x40, 0x41, 0x41, 0x5f, 0x40} //7
,{0x40, 0x5f, 0x55, 0x5f, 0x40} //8
,{0x40, 0x47, 0x45, 0x5f, 0x40} //9
,{0x40, 0x5e, 0x45, 0x5e, 0x40} //A
,{0x40, 0x5f, 0x51, 0x4e, 0x40} //D
,{0x40, 0x5f, 0x51, 0x51, 0x40} //C
,{0x40, 0x4f, 0x50, 0x4f, 0x40} //V
};

const int write = 1;
const int instruction = 0;
void init(void);
void clear(void);
void shift(unsigned int, unsigned char);
void cha(unsigned int ch);

int main(void) {

//Change me to suit.
unsigned int samples = 5;
unsigned int sampledelay = 1200;
unsigned int loopdelay = 60000; //delay cycles
unsigned int supplyvoltage = 3600; //mV

//Int Hell
int e;int i;unsigned int b=0b00000001;unsigned int j=0;int h;unsigned int l=5;

//Arduino Value Map 
long map(long x, long in_min, long in_max, long out_min, long out_max)
{return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;}

//Disable Watchdog Timer
WDTCTL = WDTPW + WDTHOLD; 
//Pin Directions
P1DIR |= SCLK+DIN+DC+CE+RST+LED;;
P1OUT |= LED;
//ADC Setup Channel 2, ADC10CLK/4
ADC10CTL1 = INCH_6 + ADC10DIV_3 ; 
//Vcc & Vss as reference
ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; 
ADC10AE0 |= ADC; 
ADC10CTL0 |= ENC + ADC10SC; 
init();
clear();

//Set Cursor
shift(instruction, 0x40 | 0);
shift(instruction, 0x80 | 0);
//Draw Font
cha(10); 				//A
cha(11); 				//D
cha(12); 				//C
shift(write, 0x4A); 			//:
for(e=0;e<34;e++){shift(write, 0x40);} 	//_____
cha(13); 				//V:
shift(write, 0x4A); 			//:
for(e=0;e<32;e++){shift(write, 0x40);} 	//_____

//Main Program Loop
while(1){

//ADC Read
e=0;
for(i=0;i<samples;i++){
ADC10CTL0 |= ADC10SC;
while(ADC10CTL1 & ADC10BUSY);
e=e+ADC10MEM;
__delay_cycles(sampledelay);
}
e=e/samples;

//Map ADC to graph
e=map(ADC10MEM,0,1023,0,40);

//Write ADC and Voltage values
shift(instruction, 0x40 | 0);
shift(instruction, 0x80 | 20);
cha((ADC10MEM)/1000%10);
cha((ADC10MEM)/100%10);
cha((ADC10MEM)/10%10);
cha((ADC10MEM)%10);
shift(instruction, 0x80 | 60);
h=(long)ADC10MEM*supplyvoltage/1023;
cha(h/1000);
shift(write, 0x50); //decimal point
cha(h/100%10);
cha(h/10%10);
cha(h/1%10);

//Clear lines
shift(instruction, 0x40 | 1);shift(instruction, 0x80 | j);shift(write, 0x00);
shift(instruction, 0x40 | 2);shift(instruction, 0x80 | j);shift(write, 0x00);
shift(instruction, 0x40 | 3);shift(instruction, 0x80 | j);shift(write, 0x00);
shift(instruction, 0x40 | 4);shift(instruction, 0x80 | j);shift(write, 0x00);
shift(instruction, 0x40 | 5);shift(instruction, 0x80 | j);shift(write, 0x00);

//Drawable values for graph
if (e<=40) {
    if (!e) e=1;
    e = 40-e;
    b = 1<<(e%8);
    l = (e/8)+1;
}

//Set cursor at write point and write shift(instruction, 0x40 | l); shift(instruction, 0x80 | j); shift(write,B); //"Scrolling" j++; if(j==85){j=0;} //Loop Delay __delay_cycles(loopdelay); }} //Clears the whole display void clear(){ int e; for(e=0;e<588;e++){shift(write,0x00);}} //Draws Font void cha(unsigned int ch){ int e; for(e = 0; e < 5; e++) { shift(write, font[ch][e]);} } void init(void){ P1OUT &= ~SCLK+DIN+DC+CE+RST; __delay_cycles(50000); P1OUT |= RST; P1OUT &= ~CE; //Sets up the display, your settings may vary: shift(instruction, 0x21); shift(instruction, 0xC5); shift(instruction, 0x12); shift(instruction, 0x20); shift(instruction, 0x09); shift(instruction, 0x0C); P1OUT |= CE; } //Serial Communication with LCD void shift(unsigned int mode, unsigned char byte){ if (mode==instruction){P1OUT &= ~DC;} else if(mode==write){P1OUT |= DC;} P1OUT &= ~CE; unsigned char i; for(i=0;i<=7;i++){ P1OUT &= ~SCLK; if(byte>127){P1OUT |= DIN;} else if(byte<128){P1OUT &= ~DIN;} P1OUT |= SCLK; byte = byte<<1; } P1OUT |= CE; }

Share this post


Link to post
Share on other sites

nice project, how about a video. what are u using to feed the device.

 

eliminating the 40 if() conditions reduces the text size from 2012 to 1404 (msp430gcc)

 

        if(e==38){b=0b00000100;l=1;};
        if(e==39){b=0b00000010;l=1;};
        if(e==40){b=0b00000001;l=1;};
        */
        if (e<=40) {
            if (!e) e=1;
            e = 40-e;
            b = 1<<(e%8);
            l = (e/8)+1;
        }//if

may be variable e, b and l does not need to be 16bit? "unsigned char" may do (if compiler didn't already optimize them).

 

 

Share this post


Link to post
Share on other sites

 

nice project, how about a video. what are u using to feed the device.

 

eliminating the 40 if() conditions reduces the text size from 2012 to 1404 (msp430gcc)

 

        if(e==38){b=0b00000100;l=1;};
        if(e==39){b=0b00000010;l=1;};
        if(e==40){b=0b00000001;l=1;};
        */
        if (e<=40) {
            if (!e) e=1;
            e = 40-e;
            b = 1<<(e%8);
            l = (e/8)+1;
        }//if

may be variable e, b and l does not need to be 16bit? "unsigned char" may do (if compiler didn't already optimize them).

 

 

 

 

yeah i knew all those ifs werent too good. i did play around with changing some to char but got some errors and no reduction in code size so i just kept them as ints.

the long i have for the voltage uses alot too. 

Share this post


Link to post
Share on other sites

thanks for the video.

 

kind of disappointing to see that it's quite slow.

 

 

may be clock it up to 16mhz, and only update the numbers after one sweep?

 

the display's refresh rate is not too great, plus i am clearing some other lines there. removing some of the delay will make it faster though. 

doing any average of the samples for the whole sweep might be interesting. 

and you know on scopes how you can see the overshoot when a power supply turns on, i can see it with mine but because the resolution is set quite low and there are no lines between dots its barely visible.

Share this post


Link to post
Share on other sites

lol trying 16mhz now, damn.  removed all cycle delays except for 1000 for one sample.

 

heres a video if your interested, had to turn the backlight off for the camera to see it. has a kind of phosphor effect to it.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×