Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Microchip Graphics Library! Displaying voltage!

Status
Not open for further replies.

drkidd22

Member
So I've moved on to microchip's graphics library and I have a setup that's currently working pretty well. I have the ADC to enabled to read voltage coming from a potentiometer. This all works well.

My only issues is trying to send the voltage to the screen, I'm stuck here. I'm not sure if I have to call a Gol function or what, any help will be appreciated.
 
So I got this thing going now, but I'm having a little problem. The displayed value on LCD gets all messed up, after it has been running for about a sec or when I try to tweak the pot, I can see it change on the display but it gets all screwed up.

Code:
//This is what I'm running on my main code and how I send the voltage to the display. 
while(1)     
 {               . 
if (GOLDraw()) {            // Draw GOL object           
}   
readADC (ADCprt);//Read the ADC; This comes from the POT   
sprintf(val, "%5.3f",(float) Result*1.0); //Convert	
OutTextXY( (100)>>1,(100)>>1,val);	//Set disp location to send value and send it to the dispaly.  
    }   
  
//This is the ADC init and read functions. 
void initADC (int mask)  
{       
AD1PCFG     =    mask;  //mask = 0xFFFE       
AD1CON1    =    0x00E0;       
AD1CSSL      =    0;      
AD1CON2    =    0;       
AD1CON3    =    0x1F02;       
AD1CON1bits.ADON = 1;   
}  

void readADC (int ch)   
{   
AD1CHS = ch;   
AD1CON1bits.SAMP = 1;   
while (!AD1CON1bits.DONE);             
Result = ADC1BUF0; 
Result = (Result*5)/1024;  //Where 5 is VCC
 }
 
Last edited:
Ok first things first FLOAT doesnt work really on sprintf for C18... not sure why but i know it doesnt to get value from a float. You have to do something like
Code:
#define MULTIPLIER 100 

long lWhole=0; // Stores digits left of decimal
unsigned long ulPart=0; // Stores digits right of decimal

lWhole=(long)((double)MyVal);
ulPart=(long)((double)MyVal*MULTIPLIER)-lWhole*MULTIPLIER;
 
Last edited:
Sorry, but I didn't mention, I'm not using pic18.
I'm using PIC24FJ128GA010
I'm also using C30 and the microchip graphics library.
 
Code:
//This is what I'm running on my main code and how I send the voltage to the display. 

long voltage_x1000;	// Use a name that means something

void main( void )
{
long displayed_value;	// Used to keep a record of what is displayed on the screen so we don't constantly write to the display... writing to a display is SLOOOOOOW

	while(1)     
	{                
		GOLDraw();
		readADC (ADCprt);//Read the ADC; This comes from the POT   
		if (voltage_x1000 != displayed_value)
		{
			displayed_value = voltage_x1000;
			sprintf(val, "%5u.%03u", voltage_x1000 / 1000, voltage_x1000 % 1000);	//Convert	
			SetColor(BLACK);		// Set color to background color
			Bar( 50, 50, 100, 75 );		// Erase old text
			SetColor( WHITE );		// Set desired font color
			SetFont( (void*)&GOLFontDefault );	// Set desired font
			OutTextXY( (100)>>1,(100)>>1,val);		//Set disp location to send value and send it to the dispaly.  
		}
	}   
}
  
//This is the ADC init and read functions. 
void initADC (int mask)  
{       
	AD1PCFG     =    mask;  //mask = 0xFFFE       
	AD1CON1    =    0x00E0;       
	AD1CSSL      =    0;      
	AD1CON2    =    0;       
	AD1CON3    =    0x1F02;       
	AD1CON1bits.ADON = 1;   
}  

void readADC (int ch)   
{   
	AD1CHS = ch;   
	AD1CON1bits.SAMP = 1;   
	while (!AD1CON1bits.DONE);             
	voltage_x1000 = ADC1BUF0; 
	voltage_x1000 *= 5;		// VCC is 5v
	voltage_x1000 *= 1000;		// scale up by 1000
	voltage_x1000 /= 1024;		// convert counts to mV
}

You'll also need to make sure you have a heap defined
 
Last edited:
I have the heap defined at 3000 as in the tutorial from the microchip library.
I will be trying the code you posted right now.

Thanks.
 
I'm almost there, its working much better, thanks a lot. I think I might need to add a delay because the last three decimal places I can see them changing, maybe the delay will help stabilize it.
 
I'm starting to believe that the regulator is not regulating pretty stable adding to my problems. I will add a bigger cap and see if that helps, but it's working a much better, thank for your help
 
Now that you have that working, a cleaner way to do text on the display is to use the static text widget. This is how I handle my display (this might take some debugging... it's all from memory)...

Code:
// In display.h...
enum text_widget_ids
{
	ID_ST_MEANINGFUL_NAME_1=1,	// Start your widget id's at 1
	ID_ST_MEANINGFUL_NAME_2,
	ID_ST_MEANINGFUL_NAME_3,
	ID_ST_SPLASH_TEXT,
	ID_ST_ADC_DISPLAY,
	
	// add new ID's above this line
	END_OF_ST_WIDGET_LIST,
	NBR_ST_WIDGETS=END_OF_ST_WIDGET_LIST-1,
};
#define MAX_TXT_LENGTH	20

enum draw_states
{
	DRAW_STATE_CLEAR=0;
	DRAW_STATE_CREATE_ITEMS,
	DRAW_STATE_REFRESH,
};
typedef enum draw_states draw_state_type;

extern void Service_Display( void );

// In display.c...
char display_buffer[NBR_ST_WIDGETS][MAX_TXT_LENGTH+10];	// add 10 bytes in case of accidental overflows
int last_drawn_display;

GOL_SCHEME *white_on_blue;
GOL_SCHEME *white_on_black;

void Draw_Screen_1( void );
void Draw_Screen_2( void );
void Draw_ADC_Screen( void );
void Draw_Power_Down_Screen( void );
void Draw_Startup_Screen( void );
void Init_Schemes( void );

void Init_Schemes( void )
{
static unsigned char initialized = FALSE;

	GOLFree();	// blow away all of the widgets

	if (!initialized)
	{
		initialized = TRUE;

		white_on_blue = GOLCreateScheme();
		white_on_black = GOLCreateScheme();

		white_on_blue -> TextColor0 = WHITE;
		white_on_blue -> CommonBkColor = SCREEN_SELECTED_COLOR;
		white_on_blue -> pFont = (void*)&verdana_14;
		
		white_on_black -> TextColor0 = WHITE;
		white_on_black -> CommonBkColor = SCREEN_NOT_SELECTED_COLOR;
		white_on_black -> pFont = (void*)&verdana_14;
		
	}
}

void Service_Display( void )
{
	switch (app_state)	// I have app_state defined elsewhere.  app state is used to
	{			// control the flow of the program... app_state may be
		case STARTUP:	// WAIT_FOR_USER_INPUT, or MEASURE_ADC_VALUE, or STARTUP, etc
			Draw_Startup_Screen();
			break;

		case MEASURE_ADC_VALUE:
			Draw_ADC_Screen();
			break;

		case POWER_DOWN:
			Draw_Power_Down_Screen();
			break;
	}
}

void Draw_Startup_Screen( void )
{
static draw_state_type draw_state;


	if (last_drawn_display != __LINE__)	// this will detect when the screen changes
	{
		last_drawn_display = __LINE__-2;
		draw_state = DRAW_CLEAR;
	}

	case DRAW_STATE_CLEAR:
		SetColor( BACKGROUND_COLOR );
		ClearDevice();
		draw_state = DRAW_CREATE_ITEMS;
		break;

	case DRAW_CREATE_ITEMS:
		StCreate( ID_ST_SPLASH_TEXT, 10, 10, GetMaxX()-10, 20, ST_DRAW | ST_CENTER_ALIGN, display_buffer[ID_ST_SPLASH_TEXT], white_on_black );

		sprintf( display_buffer[ID_ST_SPLASH_TEXT], "My Awesome Program!" );
		break;

	case DRAW_STATE_REFRESH:
		GOLDraw();
		break;
}

void Draw_ADC_Screen( void )
{
static draw_state_type draw_state;
static int initialized = FALSE;
static int last_displayed_voltage;
static int adc_update_counter = 0;

#define ADC_UPDATE_DELAY	(250/SERVICE_DISPLAY_DELAY)	// SERVICE_DISPLAY_DELAY should be defined as the number of mS between calls to Service_Display
								// That will make this delay equal to 250 mS (refresh the display 4 times per second)


	if (last_drawn_display != __LINE__)	// this will detect when the screen changes
	{
		last_drawn_display = __LINE__-2;
		draw_state = DRAW_CLEAR;
		initialized = FALSE;
	}

	case DRAW_STATE_CLEAR:
		SetColor( BACKGROUND_COLOR );
		ClearDevice();
		draw_state = DRAW_CREATE_ITEMS;
		break;

	case DRAW_CREATE_ITEMS:
		StCreate( ID_ST_ADC_DISPLAY, 10, 10, GetMaxX()-10, 20, ST_DRAW | ST_CENTER_ALIGN, display_buffer[ID_ST_ADC_DISPLAY], white_on_black );
		break;

	case DRAW_STATE_REFRESH:
		if (((last_displayed_voltage != voltage_x1000) && (adc_update_counter < ADC_UPDATE_DELAY)) || !initialized)
		{
			adc_update_counter = 0;
			last_displayed_voltage = voltage_x1000;
			sprintf( display_buffer[ID_ST_ADC_DISPLAY], "%5u.%03u", voltage_x1000 / 1000, voltage_x1000 % 1000 );
			SetState( (STATICTEXT*)GOLFindObject(ID_ST_ADC_DISPLAY), ST_DRAW );
		}
		
		if (adc_update_counter < ADC_UPDATE_DELAY)
			adc_update_counter++;	

		initialized = TRUE;
		GOLDraw();
		break;
}

// in main.c
void main( void )
{
	Init_Stuff();
	Init_Display_Timer();

	while (1)
	{
		Do_Stuff_1();
		Do_Stuff_2();
		Do_Stuff_3();

		if (Display_Timer_Expired())
		{
			Init_Display_Timer();
			Service_Display();
		}
	}
}

Color graphic displays are slow to draw on. You can almost see each pixel being drawn, especially on the PIC24. I like to keep local copies of EVERYTHING on the display so that I can do a comparison between what is on the display and what I want displayed. It takes a significant chunk of ram as it means I have to duplicate nearly all of my variables, but ram is cheap and doing a comparison on variables (even if it is a string comparison) is a HELL of a lot faster than drawing a string on a display. The alternative to keeping duplicates of everything is to "simply" update the display whenever a value that you want to display changes. I found this to be a HUGE mistake (which is why I put simply in quotes) as it adds to a lot of variable and state checking to see if the thing I'm trying to update is even on the screen. I now segregate my code into application type stuff and display. The application stuff isn't even aware of the display at all. The display code monitors what the application is doing (via app_state) and changes what is on the display to suit the current situation.

This code is a good bit more complex that just using OutTextXY, but it allows you to easily set left, right, and center justification, change your gol scheme on the fly, it'll handle erasing the text on the screen for you, etc. This will become very important if your display gets to be very busy.
 
Last edited:
@birdman0_o

Thanks, I will do that, I saw that in some book I'm reading and will implement it and see how it works.

@Noggin

Kool, thanks for the input I really appreciated, I will be adding a few more things to it, I got a couple thermistors to measure water temp in my bathroom pipes and another one inside the computer case, so I will play around with these now that I'm on the right track. Thanks for all your help guys.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top