TFT display with CLI Command Line Interface

There is wide range of TFT displays available for ATmega processors. Displays distinguish them selves by resolution, dimensions and serie or parallel interfaces.

Availability Fig 1 : TFT energy monitoring display

For an ATmega328 processors an 8bit parallel display consumes all IO pins except the Series TTL interface and one Analog IO. The good thing is that with this processor its possible to build a relative simple low volume general purpose TFT display.

Many controller interfaces require a combination of digital and Analog IOs interfacing to various sensors and a reasonable sized display to display results and status of the  sensors. By having a display with a Txt Rx communication interface space is saved on the IOS needed to control external sensors.

The display on the right is a 3.5 Inch 320 x 480 resolution ILI9488 display controlled by a ATmega328 processor. The code exist out the following functions

  • The screen layout software
  • A Command Line Interpreter (CLI)
  • A real time clock.

The CLI is responsible for reading values from the TTL Rx Tx interface and displaying them on the TFT screen. The screen is grouped in Battery, Grid/Net and Photovotaic related values. It can read all parameters defined on the TFT screen like:

  • Battery : voltage current, SoC, battery cycle count, battery health values
  • Grid/Net :  voltage current, power energy values and power factor
  • Photovotaic : voltage current, power Energy, panel temperature values 
  • Time and date values.

The TFT libary used to implement the program consumes a reasonable percentage of all program memory on a ATmega 328 but after finalizing the code sufficient program and RAM space is left over for some extra functions. The code uses 27.7K program space and around 1.1K RAM code.

For the ones interested below the basic code for the CLI copy it in your sketch and have fun.

#define CR         0x0D	                // \r
#define LF         0x0A                 // \n
#define SPACE      0x20                 // " "
#define OPT        0x25                 // %


typedef struct cmds {
	String      str;
	void       (*pt2function)(char);
} 	commands;

	commands    cmd[] = {{"",},{"settm",settm}, {"batt",batt}, {"net",net}, {"pv",pv} };

void readstream(byte state){
uint8_t	n=1;
	if (Serial.available()!=0){
		while (Serial.peek()==LF || Serial.peek()==CR || Serial.peek()==SPACE) Serial.read();   // Read all Cr, Lf,spaces out of the stream until first characters 
		cmd[0].str=Serial.readStringUntil(SPACE);                                               // Read Command string until first space
		while( cmd[0].str!=cmd[n].str && n<=sizeof(cmd)/sizeof(cmd[0]))  n++;                   // Find Command in the cmd array list.
		if (n>sizeof(cmd)/sizeof(cmd[0])) return;                                               // If command not found, terminate the cammand processing 
		while ((Serial.available()!=0 && (Serial.peek()!=LF || Serial.peek()!=CR ))) {          // Check stream has no Cr/Lf characters 
			if (Serial.read()==OPT) cmd[n].pt2function(Serial.read());                          // If stream is Option sign Call function pointed by cmd[0] and read option parameter
			else Serial.read();                                                                 // IF not option characters read stream
		}
	}
}

void settm(char par){
int8_t  n;
	switch (par){
		case 'T' :{ for (n=2; n>=0; n--) *(&RTC.time.sec+n)=Serial.parseInt();	}               // read three times data from the stream to the time struct sec, min, hr.
		break;
		case 'D' :{ for (n=0; n<=2; n++) *(&RTC.time.mday+n)=Serial.parseInt()%100; }            // read three times data from the stream to the time struct date, month, year (years needs MOD 100
		break;
		case 'C' :{ RTC.derror=RTC.derror+Serial.parseFloat()/24; }
		break;
	     
	}
}

Examples of commands are : Set the time : settm %T 06:05:10 %D 11/12/1962
Other commands are but not seen in this code : batt %V 12.56 %I 23.25 %E 2534.1
net and PV