|
|
View previous topic :: View next topic |
Author |
Message |
younder
Joined: 24 Jan 2013 Posts: 53 Location: Brazil
|
Shadow in the S6A0069 16x2 LCD |
Posted: Thu Jul 11, 2013 6:10 pm |
|
|
Hi Everyone!
I could not fix the "shadow" that appears when any variable value changes in the blue LCD (S6A0069). Sliding texts is even worse.
In the image below you can see the back shadow in purple when changing from 850Rpm to 900Rpm.
It might be related to currently LCD update rate that I'm using (100ms), but the strange part is that I had no issue with the hd44780 controller by usuing the same update rate! Video (Sorry only in portuguese) available at http://www.youtube.com/watch?v=mJWwJaoi9q0
I've already tried the post below,( but did not work too...)
http://ccsinfo.com/forum/viewtopic.php?t=25961&highlight=&sid=862da1013c12444a90c72d7eb2fd61ca
CCS Version is 4.114, full code is below.
Any help from the experts would be really appreciated!
Thanks in advance!
Hugo
Code: |
#include <18f4550.h>
#device ADC=10
#use delay (clock=48000000)
#include <flex_lcd.h>
#fuses HS, NOWDT, NOPROTECT, NOBROWNOUT, NOLVP, PUT // configura fuses
#include <usb_bootloader.h>
#priority INT_TIMER1, INT_EXT, INT_TIMER0
//Input Pin Map
#Define RPM_PULSE PIN_B0 //Tachometer Pulse - Pulso do Conta Giros
#Define FUEL_PULSE PIN_B1 //Carburetor Fuel Flow Pulse - Pulso medidor de gasolina
#Define SPEED_PULSE PIN_B2 //Speed Sensor pulse - Pulsos Sensor de velocidade
#Define HAND_BREAK_ACTIVE PIN_B3 //Hand Break On Lamp - Lâmpada Freio de mão puxado
#Define 4X4_LOCK_ON PIN_B4 //4wd Lock active - Bloquêio diferencial central ligado
#Define BRAKE_OIL_LAMP PIN_B5 //Brake system oil monitoring - Lâmpada reservatório óleo de freio
#Define LEFT_DOOR_OPEN PIN_B6 //Left door open - Porta esquerda aberta
#Define RIGHT_DOOR_OPEN PIN_B7 //Right door open - Porta direita aberta
#Define ENTER PIN_C0 //Enter Button - Botão de Enter
#Define UP PIN_C1 //Up Button - Botão Seta p/ cima
#Define DOWN PIN_C2 //Down Button - Botão Seta p/ baixo
#Define BAT_VOLTAGE_LEVEL PIN_A0 //AN_00 12V battery level - Tensão da bateria
#Define FUEL_LEVEL PIN_A1 //AN_01 Fuel tank level - Nível do combustível
#Define OIL_PRESSURE PIN_A2 //AN_02 Engine Oil Pressure - Pressão do óleo do motor
#Define ENGINE_TEMP PIN_A3 //AN_03 Engine Temperature - Temperatura do Motor
#Define ENGINE_WATER_TEMP PIN_A5 //AN_04 Engine Water Temperature - Temperatura da água do motor
#Define ALTERNATOR_CURRENT PIN_E0 //AN_05 Alternator´s current - Corrente do Alternador
#Define CAR_LOAD_CURRENT PIN_E1 //AN_06 Car´s load current - Corrente da carga instalada
#Define AIR_TEMPERATURE PIN_E2 //AN_07 Internal Air Temperature - Temperatura do Ar Interna
//Output Pin Map
#Define USB_5V PIN_A4 //5Volts Supply to USB Port - Tomada 5v para porta usb
#Define RELAY_01 PIN_C6 //Relay #01 - Relê 01
#Define RELAY_02 PIN_C7 //Relay #02 - Relê 02
#Define BUZZER PIN_D0 //Enter Button - Botão de Enter
#Define LAMP_SHIFT_LIGHT PIN_D1 //Up Button - Botão Seta p/ cima
// =============================================================
// Shift Text to Left and display it on LCD - Corre texto para esquerda e mostra no display
// =============================================================
Char*text00=" "; // Global Variable Text 00 - Variavel Global Texto 00
void Shift_Info_Text()
{
static int i=0;
for ( i=0 ; i<30 ; i++ )
{
if (i==0) Text00[29]=Text00[i];
else Text00[i-1]=Text00[i];
}
}
// *****************************************************
// =============================================================
// Clock Logic - Lógica do Relógio
// =============================================================
unsigned int S, M, H; // Global variable clock variables - variáveis globais do relógio
Char colon=':'; // Global variable colon - variável global dois pontos do relógio
int1 Clock_Adjustment_Active=0; // Global variable clock adjustment active - variáveis global ajuste do relogio ativo
void Clock()
{
static int i=0;
IF (Clock_Adjustment_Active==0) {
S++;
IF (S>=60) {
S=0;
M++;
IF (M>=60) {
M=0;
H++;
IF (H>=24) H=0;
}
}
}
}
// *****************************************************
// =============================================================
// Printf to LCD Display - Imprime informações no Display LCD
// =============================================================
unsigned int Active_Screen_Nr=0; // Global Variable Active Screen Number - Variavel Global Numero da Tela Ativa
Unsigned int16 EngineTemp=0,EngineTemp_Av=0,OilPressure=0,OilPressure_Av=0,WaterTemp=0,WaterTemp_Av=0,AirTemp=0,AirTemp_Av_temp=0,AirTemp_Av=0; // Global Variable Analog Inputs - Variaveis Globlais entradas analógicas
Unsigned int16 BatVoltage=0,BatVoltage_Av=0; // Global Variable Analog Inputs - Variaveis Globlais entradas analógicas
Unsigned int8 FuelTankLevel=0,FuelTankLevel_Av=0; // Global Variable Analog Inputs - Variaveis Globlais entradas analógicas
Unsigned int16 AlternatorCurrent=0,AlternatorCurrent_Av=0,LoadCurrent=0,LoadCurrent_Av=0;
Unsigned long RPM=0, Speed=0, Trip=0, Ins_consumption=0, Avg_consumption=0, test=0; // Global Variable RPM Display - Variavel Global RPM
Char*Info=" "; // Global Variable Function Information - Variavel Global Texto da Função
Char *BarGraph=" ";
void LCD_Display()
{
Switch(Active_Screen_Nr)
{
case 1 : lcd_load_custom_chars(1), printf(LCD_PUTC,"\f%3.1w\003\001\005 %3LD Km/h\n%02u%c%02u\002\004 %4LD Rpm",AirTemp_Av,Speed,H,colon,M,RPM); break; //LCD Display SPEED/RPM
case 2 : lcd_load_custom_chars(2), printf(LCD_PUTC,"\f%3.1w\003\001 \004 %2D Lts \n%02u%c%02u\002Aut.:%3LDKm",AirTemp_Av,FuelTankLevel_Av,H,colon,M,Trip); break; //LCD Display FUEL TANK LEVEL/KMS TO EMPTY
case 3 : lcd_load_custom_chars(3), printf(LCD_PUTC,"\f%3.1w\003\001\004 %3.1w L/h\n%02u%c%02u\002\005 %3.1w L/h",AirTemp_Av,Ins_consumption,H,colon,M,Avg_consumption); break; //LCD Display INSTANTANEOUS CONSUMPTION/AVERAGE CONSUPMTION
case 4 : lcd_load_custom_chars(4), printf(LCD_PUTC,"\f%3.1w\003\001Ar/Combust\n%02u%c%02u\002%c%c%c%c%c%c%c%c%c%c",AirTemp_Av,H,colon,M,BarGraph[0],BarGraph[1],BarGraph[2],BarGraph[3],BarGraph[4],BarGraph[5],BarGraph[6],BarGraph[7],BarGraph[8],BarGraph[9]); break; //OXIGEN SENSOR //LCD Display AIR/FUEL Mixture
case 5 : lcd_load_custom_chars(5), printf(LCD_PUTC,"\f%3.1w\003\001\004 M.%3.1w\003\n%02u%c%02u\002\004 A.%3.1w\003",AirTemp_Av,EngineTemp_Av,H,colon,M,WaterTemp_Av); break; //LCD Display ENGINE TEMPERATURE/WATER TEMPERATURE
case 6 : lcd_load_custom_chars(6), printf(LCD_PUTC,"\f%3.1w\003\001\004 %3.1w Vdc\n%02u%c%02u\002\005%2LDA \006%2LDA",AirTemp_Av,BatVoltage_Av,H,colon,M,LoadCurrent_Av,AlternatorCurrent_Av); break; //LCD Display BATTERY LEVEL/CAR CURRENT LOAD & ALTERNATOR CURRENT
}
}
// *****************************************************
// =============================================================
// "Interrupcao Timer0"
// =============================================================
Float Actual_Value_Tmr0=0.0; // Global variable that contains tmr0 accumulated timer - variável global com tempo atual do Timer 0
#INT_TIMER0 // Definition that next line will be associated to Timer0 interrupt - linha que define que a próxima função será associada à interrupção do TIMER0
void timer0() // Function called automaticaly - esta função não precisará ser chamada. Será executada automaticamente.
{
Actual_Value_Tmr0=Actual_Value_Tmr0+1.39810133333333; //1.39810133333333=Tempo Total para overflow to contator (TMR0 16bits) = (Tempo de cada incremento * 65536)
}
// *************************************************************
// =============================================================
// "Interrupcao Timer1", executada a cada 10ms
// =============================================================
int1 Pulse_50ms=0; // Global variable - variável global com pulso de clock de 50ms
int1 Pulse_100ms=0; // Global variable - variável global com pulso de clock de 100ms
int1 Pulse_200ms=0; // Global variable - variável global com pulso de clock de 200ms
int1 Pulse_500ms=0; // Global variable - variável global com pulso de clock de 500ms
int1 Pulse_1000ms=0; // Global variable - variável global com pulso de clock de 1000ms
#INT_TIMER1 // Definition that next line will be associated to Timer1 interrupt - linha que define que a próxima função será associada à interrupção do TIMER1
void timer1() // Function called automaticaly every 100ms - esta função não precisará ser chamada. Será executada automaticamente.
{
static int8 Counter50=0;
static int8 Counter100=0;
static int8 Counter500=0;
set_timer1(50536 + get_timer1()); //Pulso de clock de 100ms @ 48 MHz
//50ms Clock generator - Gerador de Pulso de 50ms
Counter50++;
if (Counter50==5) Pulse_50ms=!Pulse_50ms, Counter50=0;
//100ms&200ms Clock generator - Gerador de Pulso de 100ms
Counter100++;
if (Counter100==10) Pulse_100ms=1;
if (Counter100==20)
{
Pulse_200ms=!Pulse_200ms;
Pulse_100ms=0;
Counter100=0;
if ((Clock_Adjustment_Active==0)&&(Active_Screen_Nr>6)) Shift_Info_Text(); //call Shift Text routine if: 1-) Not Clock Setup Active and 2-) Info Text Cmd Active
}
//500ms&1s Clock generator - Gerador de Pulso de 500ms
Counter500++;
if (Counter500==50) Pulse_500ms=1, colon=':';
if (Counter500==100)
{
Pulse_1000ms=!Pulse_1000ms;
Pulse_500ms=0;
Counter500=0;
colon=' ';
if (Clock_Adjustment_Active==0) Clock();
}
}
// *************************************************************
// =============================================================
// "Interrupcao Timer2", executada a cada
// =============================================================
//#INT_TIMER2 // Definition that next line will be associated to Timer2 interrupt - linha que define que a próxima função será associada à interrupção do TIMER2
//void timer2() // Function called automaticaly every 100ms - esta função não precisará ser chamada. Será executada automaticamente.
// {
// output_toggle(PIN_C0);
// }
// *************************************************************
// =============================================================
// "External Interrupt Pin_B0", Interrupção Externa Pino B0
// =============================================================
Float TimeCount_Total=0.0;
Float Pulse_Lenght[10]={0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
#INT_EXT // Definition that next line will be associated to External interrupt - linha que define que a próxima função será associada à interrupção externa
void ext_isr(void) // Function called automaticaly @ Pin_B0 rise edge detection - função executada automaticamente a cada detecção de borda de subida no pino B0.
{
Static Signed int i=0;
TimeCount_Total=Actual_Value_Tmr0+(get_timer0()*0.0000213333333333333); //0.0000213333333333333=Tempo de "cada" Incremento do contador Timer0 (Período) = 1/((F.Oscilador/4) / Prescaler)
set_timer0(0); //Clear Actual "Counter" Timer0
Actual_Value_Tmr0=0; //Clear Actual "Time" Timer0
Pulse_Lenght[i]=TimeCount_Total;
i++;
If (i>=10) i=0;
clear_interrupt(INT_EXT);
}
// *************************************************************
// =============================================================
// "One Shot Rising, OSR", Generates rising edge pulse every 50ms - Gera pulso na borda de subida do clock de 50ms
// =============================================================
int1 Edge_50ms; //Global variable - Variável global pulso 50ms (Borda de subida)
void Function_Edge_50ms() //Function declaration - Declaração da função
{
static int1 aux50; //Auxiliar Variable - Variável local usada para intertravamento
if (Pulse_50ms) //If pulse is true - Se Pulso está Ligado
{
if (aux50==0) Edge_50ms=1; else Edge_50ms=0; //and aux50 is false then Edge_50ms=TRUE for only one scan - e aux50 em Zero, Pulso de Subida vai pra 1
aux50=1; //Next scan Edge_50ms will be false - Coloca variavel auxiliar em 1 que vai zerar borda de subida no próximo scan
}
else aux50=0; //Clear aux50 till next rising edge detection - Espera por novo pulso
}
// *************************************************************
// =============================================================
// "One Shot Rising, OSR", Generates rising edge pulse every 100ms - Gera pulso na borda de subida do clock de 100ms
// =============================================================
int1 Edge_100ms; //Global variable - Variável global pulso 100ms (Borda de subida)
void Function_Edge_100ms() //Function declaration - Declaração da função
{
static int1 aux100; //Auxiliar Variable - Variável local usada para intertravamento
if (Pulse_100ms) //If pulse is true - Se Pulso está Ligado
{
if (aux100==0) Edge_100ms=1; else Edge_100ms=0; //and aux100 is false then Edge_100ms=TRUE for only one scan - e aux100 em Zero, Pulso de Subida vai pra 1
aux100=1; //Next scan Edge_100ms will be false - Coloca variavel auxiliar em 1 que vai zerar borda de subida no próximo scan
}
else aux100=0; //Clear aux100 till next rising edge detection - Espera por novo pulso
}
// *************************************************************
// =============================================================
// "One Shot Rising, OSR", Generates rising edge pulse every 200ms - Gera pulso na borda de subida do clock de 200ms
// =============================================================
int1 Edge_200ms; //Global variable - Variável global pulso 200ms (Borda de subida)
void Function_Edge_200ms() //Function declaration - Declaração da função
{
static int1 aux200; //Auxiliar Variable - Variável local usada para intertravamento
if (Pulse_200ms) //If pulse is true - Se Pulso está Ligado
{
if (aux200==0) Edge_200ms=1; else Edge_200ms=0; //and aux200 is false then Edge_200ms=TRUE for only one scan - e aux200 em Zero, Pulso de Subida vai pra 1
aux200=1; //Next scan Edge_200ms will be false - Coloca variavel auxiliar em 1 que vai zerar borda de subida no próximo scan
}
else aux200=0; //Clear aux200 till next rising edge detection - Espera por novo pulso
}
// *************************************************************
// =============================================================
// "One Shot Rising, OSR", Generates rising edge pulse every 500ms - Gera pulso na borda de subida do clock de 500ms
// =============================================================
int1 Edge_500ms; //Global variable - Variável global pulso 500ms (Borda de subida)
void Function_Edge_500ms() //Function declaration - Declaração da função
{
static int1 aux500; //Auxiliar Variable - Variável local usada para intertravamento
if (Pulse_500ms) //If pulse is true - Se Pulso está Ligado
{
if (aux500==0) Edge_500ms=1; else Edge_500ms=0; //and aux500 is false then Edge_500ms=TRUE for only one scan - e aux500 em Zero, Pulso de Subida vai pra 1
aux500=1; //Next scan Edge_500ms will be false - Coloca variavel auxiliar em 1 que vai zerar borda de subida no próximo scan
}
else aux500=0; //Clear aux500 till next rising edge detection - Espera por novo pulso
}
// *************************************************************
// =============================================================
// "One Shot Rising, OSR", Generates rising edge pulse every 1000ms - Gera pulso na borda de subida do clock de 1000ms
// =============================================================
int1 Edge_1000ms; //Global variable - Variável global pulso 1000ms (Borda de subida)
void Function_Edge_1000ms() //Function declaration - Declaração da função
{
static int1 aux1000; //Auxiliar Variable - Variável local usada para intertravamento
if (Pulse_1000ms) //If pulse is true - Se Pulso está Ligado
{
if (aux1000==0) Edge_1000ms=1; else Edge_1000ms=0; //and aux1000 is false then Edge_1000ms=TRUE for only one scan - e aux1000 em Zero, Pulso de Subida vai pra 1
aux1000=1; //Next scan Edge_1000ms will be false - Coloca variavel auxiliar em 1 que vai zerar borda de subida no próximo scan
}
else aux1000=0; //Clear aux500 till next rising edge detection - Espera por novo pulso
}
// *************************************************************
// =============================================================
// "Timer ON Delay", Temporizador com retardo para ativar (em milisegundos)
// TON.SP = Setpoint
// TON.PV = Timer counter value - Tempo atual
// TON.Q = Timer output - Sáida do Temporizador 1= Setpoint atingido
// TON.R = Reset - Zera temporizador
// =============================================================
const int8 TimerArray=2;
Typedef Struct {
int8 SP;
int8 PV;
int8 Q;
int8 R;
int8 EN;
} TON_Struct;
TON_Struct TON[TimerArray]={{0,0,0,0,0},{0,0,0,0,0}}; //Timer array declaration - define a quantidade de temporizadores que poderão ser usadas no programa
void Timer(int8 IN_TON_Nr,int8 IN_SP) //Timer Function - Declaração da função
{
static int8 temp[TimerArray];
static int8 Edge_EN[TimerArray];
//------------------------------------ //TON[X].EN=1 ->Generates Edge Rising pulse for Reset Timer
if (TON[IN_TON_Nr].EN) {
if (temp[IN_TON_Nr]==0) Edge_EN[IN_TON_Nr]=1; else Edge_EN[IN_TON_Nr]=0;
temp[IN_TON_Nr]=1;
}
else temp[IN_TON_Nr]=0;
//-----------------------------------
TON[IN_TON_Nr].SP=IN_SP; // Initializes .SP according called Timer - Copia Setpoint do TON chamadado
if (TON[IN_TON_Nr].PV>=TON[IN_TON_Nr].SP) TON[IN_TON_Nr].Q=1, TON[IN_TON_Nr].EN=0; // If .PV reaches .SP, Output .Q is True - Se Contador >= Setpoint seta saída "Q"
if ((Edge_50ms)&&(TON[IN_TON_Nr].EN)&&(TON[IN_TON_Nr].PV<TON[IN_TON_Nr].SP)) TON[IN_TON_Nr].PV=(TON[IN_TON_Nr].PV+1); // Increment counter every 100ms - Inicia contagem de tempo, incrementa a cada 100ms
if ((TON[IN_TON_Nr].R)||(Edge_EN[IN_TON_Nr])) TON[IN_TON_Nr].PV=0, TON[IN_TON_Nr].Q=0, TON[IN_TON_Nr].R=0; //If .R is True, Clear Timer - Reseta e Zera variáveis do contador quando TON[x].R=1
}
// *************************************************************
// =============================================================
// Scale Function - Função de Escalonamento
// =============================================================
Float Scale(float In_Min_A,float In_Max_A,float In_Min_B,float In_Max_B,float In_Process_input) //Scale Function - Declaração da função de escalonamento
{
static float Dif_A, Dif_B, Razao;
//Difference A
Dif_A=In_Max_A-In_Min_A;
//Difference B
Dif_B=In_Max_B-In_Min_B;
//Difference A / Difference B
Razao=Dif_A/Dif_B;
//Out_Scaled_value
return(((In_Process_input/Razao)+(In_Min_B*2))-((In_Min_A/Razao)+In_Min_B));
}
// *************************************************************
// =============================================================
// Average Function - Função de Cálculo de Média
// =============================================================
/*
const int8 AvArrayLenght=8;
Typedef Struct {
int16 Temp[10];
} Average_Struct;
Average_Struct Av_Calc[AvArrayLenght]={{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0}}; //array initialization
Float Average(int8 AvCalcNr,float Analog_IN) //Scale Function - Declaração da função de escalonamento
{
static unsigned int i[AvArrayLenght], j;
static float Av_Value_temp[AvArrayLenght],Av_Value[AvArrayLenght];
j=i[AvCalcNr];
if (Edge_100ms)
{
Av_Calc[AvCalcNr].Temp[j]=Analog_IN;
Av_Value_temp[AvCalcNr]+=Av_Calc[AvCalcNr].Temp[j];
if (j==9)
{
Av_Value[AvCalcNr]=Av_Value_temp[AvCalcNr]/10;
Av_Value_temp[AvCalcNr]=0;
}
j++;
If (j>=10) j=0;
}
i[AvCalcNr]=j;
return(Av_Value[AvCalcNr]);
}
// *************************************************************
*/
// =============================================================
// Average Function - Função de Cálculo de Média NEW
// =============================================================
const int8 AvArrayLenght=8;
Float Average(int8 AvCalcNr,float Analog_IN,int8 NrOfSamples) //Scale Function - Declaração da função de escalonamento
{
static unsigned int i[AvArrayLenght], j=0;
static float Av_Value_temp[AvArrayLenght],Av_Value[AvArrayLenght];
j=i[AvCalcNr];
//if (Edge_100ms)
// {
Av_Value_temp[AvCalcNr]+=Analog_IN;;
if (j==(NrOfSamples-1))
{
Av_Value[AvCalcNr]=Av_Value_temp[AvCalcNr]/NrOfSamples;
Av_Value_temp[AvCalcNr]=0;
}
j++;
If (j>=NrOfSamples) j=0;
// }
i[AvCalcNr]=j;
return(Av_Value[AvCalcNr]);
}
// *************************************************************
// =============================================================
// Round Function - Função de arredondamento
// =============================================================
Long Round(int16 In_var) //Round Function - Declaração da função de arredondamento
{
static unsigned int VAR_Digit[4],i=0;
static unsigned int16 temp=0, Result=0;
temp=In_var;
for ( i=0 ; i<4 ; i++ )
{
VAR_Digit[i] = temp%10 ;
temp /= 10 ;
}
IF (VAR_Digit[0]>5) VAR_Digit[0]=10; else VAR_Digit[0]=0; //Round last Variable digit either to Zero or Ten
Result=(((long)VAR_Digit[3]*1000)+((long)VAR_Digit[2]*100)+(VAR_Digit[1]*10)+VAR_Digit[0]);
return(Result);
}
// *************************************************************
// =============================================================
// A/D Function - Função de leitura A/D
// =============================================================
Long Read_AD(int Channel)
{
Static Long Analog_Value;
Switch(Channel)
{
case 0 : input(BAT_VOLTAGE_LEVEL), setup_adc_ports(AN0); break;
case 1 : input(FUEL_LEVEL), setup_adc_ports(AN0_TO_AN1); break;
case 2 : input(OIL_PRESSURE), setup_adc_ports(AN0_TO_AN2); break;
case 3 : input(ENGINE_TEMP), setup_adc_ports(AN0_TO_AN3); break;
case 4 : input(ENGINE_WATER_TEMP), setup_adc_ports(AN0_TO_AN4); break;
case 5 : input(ALTERNATOR_CURRENT), setup_adc_ports(AN0_TO_AN5); break;
case 6 : input(CAR_LOAD_CURRENT), setup_adc_ports(AN0_TO_AN6); break;
case 7 : input(AIR_TEMPERATURE), setup_adc_ports(AN0_TO_AN7); break;
//case 8 : input(PIN_B2), setup_adc_ports(AN0_TO_AN8); break;
//case 9 : input(PIN_B3), setup_adc_ports(AN0_TO_AN9); break;
//case 10 : input(PIN_B1), setup_adc_ports(AN0_TO_AN10); break;
//case 11 : input(PIN_B4), setup_adc_ports(AN0_TO_AN11); break;
//case 12 : input(PIN_B0), setup_adc_ports(ALL_ANALOG); break;
default: return(0);
}
set_adc_channel(channel);
delay_us(50);
Analog_Value = read_adc();
setup_adc_ports(NO_ANALOGS);
return(Analog_Value);
}
// *************************************************************
void main()
{
//Variables - Declaração das variáveis
signed long ADC_0,ADC_1,ADC_2,ADC_3,ADC_4,ADC_5,ADC_6,ADC_7, counter=0,temp2=0; // signed long
float Average_Pulse_Lenght=0;
unsigned int i, Setup_mode=2, Hold_exit_stup=0, shift_counter=0, Count_EN_Random=0; //RPM_Digit[4]
int1 Display_Shifted_Info=0,Start_Info_Shif=0,Edge_Add_Active_Text_Nr=0, Random_Display_Mode_Active=0;
int1 aux1=0,aux2=0,aux3=0,aux4=0,Edge_Adjust=0,Edge_Select=0,Edge_Beep_ON=0;
//fuel tank
unsigned int8 FuelTank_Mem[50], FuelTank_Mem_Count[50],Moda=0,FuelTank_Moda=0,FuelTankLevel_Av2=0; //FuelTank_Mem_Av[6]
//unsigned int16 FuelTank_Moda_Av=0;
unsigned int8 k=0,n=0; //a=0
Char pbar="\004";
Char ibar="\005";
Char rbar="\006";
Char blank="\007";
Char*text01=" 1 Consumo Instantaneo ";
Char*text02=" 2 >> Consumo Medio << ";
Char*text03=" 3 Nivel Do Combustivel";
Char*text04=" 4 Rotacoes Por Minuto ";
Char*text05=" 5 Temperatura Do Motor";
Char*text06=" 6 Temperatura Da Agua ";
Char*text07=" 7 Tensao Da Bateria ++";
// Initialize 16x2 LCD Display- inicializa display LCD 16x2
lcd_init();
//Configure Timer0 - Configura Timer0
setup_timer_0 (T0_INTERNAL | T0_DIV_256 ); //Configures timer0 - Configura o timer1 para clock interno e prescaler dividindo por 256
enable_interrupts(INT_TIMER0);
//Configure Timer1 - Configura Timer1
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8); //Configures timer1 - Configura o timer1 para clock interno e prescaler dividindo por 8
enable_interrupts(INT_TIMER1); //Enable Timer1 interrupt - Habilita a interrupção do timer1
//Configure Timer2 - Configura Timer2
// (1/20000000)*4*1*24 = 004.8 us or 208333,33 Hz
// (1/20000000)*4*4*254 = 204.0 us or 4901,96 Hz
// (1/20000000)*4*16*254= 816.0 us or 1225,49 Hz
// setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
// setup_timer_2(T2_DIV_BY_16, 254, 1); //Configures timer2 for PWM - Configura o timer2 para CCP1 como PWM
// enable_interrupts(INT_TIMER2); //Enable Timer2 interrupt - Habilita a interrupção do timer2
// set_pwm1_duty(ADC_2); // This sets the time of the pulse (deve ser chamado no main loop)
//Configure External Interrupt - Configura Interrupção externa no pino B0
ext_int_edge(H_TO_L); // ext_int_edge(1,H_TO_L) p/ External Int. #1
clear_interrupt(INT_EXT); // clear_interrupt(INT_EXT1) p/ External Int. #1
enable_interrupts(INT_EXT); // enable_interrupts(INT_EXT1) p/ External Int. #1
//Set AD for Internal Clock - Configura o AD para clock interno
setup_adc(ADC_CLOCK_INTERNAL);
//Set GIE&PEIE bits and Enable all interrupts - Habilita todas as interrupções
enable_interrupts(GLOBAL);
//Initialize Text00 Array
for (i=0;i<=29;++i) Text00[i]=Text01[i];
//Initialize TON'S
TON[0].EN=1;
//Read eeprom
FuelTankLevel_Av=read_eeprom(1); //Lê eeprom, nivel do tanque
AirTemp_Av=(read_eeprom(2)*2); //Lê eeprom, temperatura ar
S=read_eeprom(40); //Lê eeprom, SEGUNDOS
M=read_eeprom(41); //Lê eeprom, MINUTOS
H=read_eeprom(42); //Lê eeprom, HORAS
//Initialize Fuel Tank Level Mem. Average Array
// for (i=0;i<=6;++i) FuelTank_Mem_Av[i]=FuelTankLevel_Av;
// =============================================================
// Clock Adjustment - Ajuste do Relógio
// =============================================================
if (input(ENTER)==0)
{
delay_ms(10); //debouncing time
Clock_Adjustment_Active=1;
}
do {
Function_Edge_50ms(); //Call Edge 50ms Function
//Adjust Edge Bit
if (input(UP)==1)
{
delay_ms(20); //debouncing time
if (aux1==0) Edge_Adjust=1; else Edge_Adjust=0;
aux1=1;
}
else aux1=0, Edge_Adjust=0; //Hold=0
//Setup mode Edge bit
if (input(ENTER)==0)
{
delay_ms(20); //debouncing time
if (aux2==0) Edge_Select=1; else Edge_Select=0;
aux2=1;
}
else aux2=0, Edge_Select=0;
//Setup Mode: 0: Adjust Seconds , 1: Adjust Minutes, 2: Adjust Hours
if (Edge_Select) {
Setup_mode++;
if (Setup_mode>2) Setup_mode=0;
}
//Adjust Seconds
if (Setup_mode==0) {
if (Edge_Adjust) S++;
IF (S>=60) S=0;
}
//Adjust Minutes
if (Setup_mode==1) {
if (Edge_Adjust) M++;
IF (M>=60) M=0;
}
//Adjust Hours
if (Setup_mode==2) {
if (Edge_Adjust) H++;
IF (H>=24) H=0;
}
// Display current setup mode
If (Setup_mode==0) {if (Edge_50ms) printf(LCD_PUTC,"\f->Ajustar Seg.\n%02u%c%02u%c%02u ",H,':',M,':',S);}
If (Setup_mode==1) {if (Edge_50ms) printf(LCD_PUTC,"\f->Ajustar Min.\n%02u%c%02u%c%02u ",H,':',M,':',S);}
If (Setup_mode==2) {if (Edge_50ms) printf(LCD_PUTC,"\f->Ajustar Hora\n%02u%c%02u%c%02u ",H,':',M,':',S);}
//exit setup function
if (input(ENTER)==0)
{
delay_ms(10); //debouncing time
if (Edge_50ms) {
Hold_exit_stup++;
if (Hold_exit_stup>=20) Clock_Adjustment_Active=0,Count_EN_Random=21, printf(LCD_PUTC,"\f RELOGIO \n AJUSTADO!! "), delay_ms(1500); //Exit setut and enable clock
}
} else Hold_exit_stup=0;
} While (Clock_Adjustment_Active==1);
// *************************************************************
// =============================================================
// Welcome Msg
// =============================================================
printf(LCD_PUTC,"\f Sistema \n -------------- ");
delay_ms(800);
printf(LCD_PUTC,"\f Interativo \n -------------- ");
delay_ms(800);
printf(LCD_PUTC,"\f de Informacoes \n -------------- ");
delay_ms(800);
printf(LCD_PUTC,"\f LADA NIVA \n -------------- ");
delay_ms(1200);
printf(LCD_PUTC,"\f By Hugo Silva \nNIVA GalinhaReia");
delay_ms(2000);
// *************************************************************
while(1)
{
//Function Call - Chamadas das funções
//------------------------------------------------------
Function_Edge_50ms();
Function_Edge_100ms();
Function_Edge_200ms();
Function_Edge_500ms();
Function_Edge_1000ms();
if (Edge_100ms) LCD_Display();
// *****************************************************
//Enable or Disable Ramdom Display mode
//------------------------------------------------------
if (input(ENTER)==0)
{
delay_ms(10); //debouncing time
if (Edge_50ms) {
Count_EN_Random++;
if (Count_EN_Random==20) {
Random_Display_Mode_Active=!Random_Display_Mode_Active;
if (Random_Display_Mode_Active==1){
printf(LCD_PUTC,"\f MODO ALEATORIO \n LIGADO!! ");
output_high(BUZZER);
delay_ms(300);
output_low(BUZZER);
}
else
{
printf(LCD_PUTC,"\f MODO ALEATORIO \n DESLIGADO! ");
Active_Screen_Nr--; //Because after releasing ENTER, Active_Text_Nr will be incremented
output_high(BUZZER);
delay_ms(300);
output_low(BUZZER);
delay_ms(90);
output_high(BUZZER);
delay_ms(300);
output_low(BUZZER);
}
delay_ms(1500);
TON[0].EN=1;
//Active_Screen_Nr--; //Because after releasing ENTER, Active_Text_Nr will be incremented
}
}
} else Count_EN_Random=0;
// *****************************************************
//Add Active_Text_Nr (Random Mode Enabled)
//------------------------------------------------------
if (((TON[1].Q==1)&&(Random_Display_Mode_Active==1))||((input(ENTER)==1)&&(Random_Display_Mode_Active==0))){
if (aux3==0) Active_Screen_Nr++, Edge_Add_Active_Text_Nr=1; else Edge_Add_Active_Text_Nr=0;
aux3=1;
If (Active_Screen_Nr>6) Active_Screen_Nr=1;
}
else aux3=0;
if (Edge_Add_Active_Text_Nr) {
If (Active_Screen_Nr==1) for (i=0;i<=29;++i) Text00[i]=Text01[i];
If (Active_Screen_Nr==2) for (i=0;i<=29;++i) Text00[i]=Text02[i];
If (Active_Screen_Nr==3) for (i=0;i<=29;++i) Text00[i]=Text03[i];
If (Active_Screen_Nr==4) for (i=0;i<=29;++i) Text00[i]=Text04[i];
If (Active_Screen_Nr==5) for (i=0;i<=29;++i) Text00[i]=Text05[i];
If (Active_Screen_Nr==6) for (i=0;i<=29;++i) Text00[i]=Text06[i];
shift_counter=0;
}
// *****************************************************
// Shift Text to Left and display it on LCD - Corre texto para esquerda e mostra no display
//------------------------------------------------------
if ((Edge_50ms)&&(input(ENTER)==1))
{
Info[0]=Text00[0];
Info[1]=Text00[1];
Info[2]=Text00[2];
Info[3]=Text00[3];
Info[4]=Text00[4];
Info[5]=Text00[5];
Info[6]=Text00[6];
Info[7]=Text00[7];
Info[8]=Text00[8];
Info[9]='\0';
}
// *****************************************************
// Custom Clock Pulse for automatic screen change (Generates 100ms pulse clock every 5,3s)
//------------------------------------------------------
Timer(0,53); // Timer(#,Setpoint x 100ms) -> Timer 0 Declaration with 5,3s of setpoint
if (TON[0].Q) TON[1].EN=1; //TON[1].EN=1 ->Enable, Reset and Start Timer
Timer(1,1); // Timer(#,Setpoint x 100ms) -> Timer 1 Declaration with 100ms of setpoint
if (TON[1].Q) TON[0].EN=1; //TON[0].EN=1 ->Enable, Reset and Start Timer
// *****************************************************
//Calculates RPM Average Value - Calcula Média do RPM para mostrar no Display
//------------------------------------------------------
Average_Pulse_Lenght=(Pulse_Lenght[0]+Pulse_Lenght[1]+Pulse_Lenght[2]+Pulse_Lenght[3]+Pulse_Lenght[4]+Pulse_Lenght[5]+Pulse_Lenght[6]+Pulse_Lenght[7]+Pulse_Lenght[8]+Pulse_Lenght[9])/10.0;
temp2=((1.0/Average_Pulse_Lenght)/2.0)*60.0;
RPM=Round(temp2);
/*
for ( i=0 ; i<4 ; i++ )
{
RPM_Digit[i] = temp2%10 ;
temp2 /= 10 ;
}
IF (RPM_Digit[0]>5) RPM_Digit[0]=10; else RPM_Digit[0]=0; //Round last RPM digit either to Zero or Ten
RPM=(((long)RPM_Digit[3]*1000)+((long)RPM_Digit[2]*100)+(RPM_Digit[1]*10)+RPM_Digit[0]);
*/
// *****************************************************
//Read all analog inputs
//------------------------------------------------------
//Analog input 00
If (Active_Screen_Nr==6)
{
If (Edge_50ms) { ADC_0=Read_AD(0); // Read AD Channel - Le Canal AD
BatVoltage=Scale(0,1023,0,158, ADC_0); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value) 15,637v=5v NO RES. 4K7
BatVoltage_Av=Average(0,BatVoltage,5); // Display calculated average value
}
}
else //Still processing in Background at lower scan rate
{
If (Edge_1000ms) { ADC_0=Read_AD(0); // Read AD Channel - Le Canal AD
BatVoltage=Scale(0,1023,0,158, ADC_0); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value) 15,637v=5v NO RES. 4K7
BatVoltage_Av=Average(0,BatVoltage,5); // Display calculated average value
}
}
//Analog input 01
If (Edge_100ms) { ADC_1=Read_AD(1); // Read AD Channel - Le Canal AD
if (ADC_1>487) ADC_1=487;
if (ADC_1<80) ADC_1=80;
FuelTankLevel=Scale(487,80,0,42, ADC_1); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
FuelTankLevel_Av2=Average(1,FuelTankLevel,5); // Display calculated average value
}
If (Edge_500ms)
{
if (k<50) //Array of 50 samples of fuel tank level
{
FuelTank_Mem[k]=FuelTankLevel_Av2; //FuelTankLevel
k++; //increment k
}
}
if (k>=50) //if k reachs last position
{
if (n<50) //check all stored samples looking for value repeatability
{
for ( i=0 ; i<50 ; i++ ) //check all stored samples looking for value repeatability
{
if (FuelTank_Mem[i]==FuelTank_Mem[n]) FuelTank_Mem_Count[n]++ ; //add position counter every repeated value
}
}
n++;
if (n>=50)
{
for ( i=0 ; i<50 ; i++ )
{ //loop to identify which position had more values repeated
//if (Moda<FuelTank_Mem_Count[i]) Moda=FuelTank_Mem_Count[i],FuelTank_Moda=FuelTank_Mem[i]; //Memorize the fuel tank level of the position found above;
if (Moda<FuelTank_Mem_Count[i]) Moda=FuelTank_Mem_Count[i],FuelTankLevel_Av=FuelTank_Mem[i];
}
/*
//-----------------------------------------------------------------------
FuelTank_Mem_Av[a]=FuelTank_Moda; //Array to Calculate Fuel Tank Mem Average
a++;
for (i=0;i<6;++i) FuelTank_Moda_Av+=FuelTank_Mem_Av[i];
FuelTankLevel_Av=FuelTank_Moda_Av/6;
FuelTank_Moda_Av=0;
if (a>=6) a=0;
//------------------------------------------------------------------------
*/
for ( i=0 ; i<50 ; i++ ) FuelTank_Mem_Count[i]=0,FuelTank_Mem[i]=0; //Clear all variables, re-start over again
k=0,n=0,Moda=0; //clear k,n and Moda
}
}
Trip=5*FuelTankLevel_Av;
test=ADC_1;
//Analog input 02
If (Active_Screen_Nr==4)
{
If (Edge_50ms) { ADC_2=Read_AD(4); // Read AD Channel every 50ms - Le Canal AD a cada 50ms
OilPressure=Scale(4,203.6,0,10, ADC_2); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
//OilPressure_Av=Average(2,OilPressure,2);
}
//Bargraph to indicate Oxigen sensor level
if (OilPress ure>0) BarGraph[0]=pbar; else BarGraph[0]=".";
if (OilPressure>1) BarGraph[1]=pbar; else BarGraph[1]=".";
if (OilPressure>2) BarGraph[2]=pbar; else BarGraph[2]=".";
if (OilPressure>3) BarGraph[3]=ibar; else BarGraph[3]=blank;
if (OilPressure>4) BarGraph[4]=ibar; else BarGraph[4]=blank;
if (OilPressure>5) BarGraph[5]=ibar; else BarGraph[5]=blank;
if (OilPressure>6) BarGraph[6]=ibar; else BarGraph[6]=blank;
if (OilPressure>7) BarGraph[7]=rbar; else BarGraph[7]=".";
if (OilPressure>8) BarGraph[8]=rbar; else BarGraph[8]=".";
if (OilPressure>9) BarGraph[9]=rbar; else BarGraph[9]=".";
}
//Analog input 03
If (Active_Screen_Nr==5)
{
If (Edge_100ms) { ADC_3=Read_AD(3); // Read AD Channel - Le Canal AD
if ((ADC_3>785)||(ADC_3<0)) ADC_3=785;
EngineTemp=Scale(785,630,500,900, ADC_3); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value) 7.5V=0Deg(3,75V) 6.1V=90Deg(3,05v) 10K E 10K
EngineTemp_Av=Average(3,Engine_Temp,30); // Display calculated average value
}
}
else //Still processing in Background at lower scan rate
{
If (Edge_1000ms) { ADC_3=Read_AD(3); // Read AD Channel - Le Canal AD
if ((ADC_3>785)||(ADC_3<0)) ADC_3=785;
EngineTemp=Scale(785,630,500,900, ADC_3); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value) 7.5V=0Deg(3,75V) 6.1V=90Deg(3,05v) 10K E 10K
EngineTemp_Av=Average(3,Engine_Temp,30); // Display calculated average value
}
}
//Analog input 04
If (Active_Screen_Nr==5)
{
If (Edge_100ms) { ADC_4=Read_AD(4); // Read AD Channel - Le Canal AD
WaterTemp=Scale(0,307.2,0,1500, ADC_4); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
WaterTemp_Av=Average(4,WaterTemp,30); // Display calculated average value
}
}
else //Still processing in Background at lower scan rate
{
If (Edge_1000ms) { ADC_4=Read_AD(4); // Read AD - Le Canal AD
WaterTemp=Scale(0,307.2,0,1500, ADC_4); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
WaterTemp_Av=Average(4,WaterTemp,30); // Display calculated average value
}
}
//Analog input 05
If (Active_Screen_Nr==6)
{
If (Edge_100ms) { ADC_5=Read_AD(5); // Read AD Channel - Le Canal AD
AlternatorCurrent=Scale(0,1005,-50,50, ADC_5); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
AlternatorCurrent_Av=Average(5,AlternatorCurrent,15); // Display calculated average value
}
}
else //Still processing in Background at lower scan rate
{
If (Edge_1000ms) { ADC_5=Read_AD(5); // Read AD Channel - Le Canal AD
AlternatorCurrent=Scale(0,1005,-50,50, ADC_5); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
AlternatorCurrent_Av=Average(5,AlternatorCurrent,15); // Display calculated average value
}
}
//Analog input 06
If (Active_Screen_Nr==6)
{
If (Edge_100ms) { ADC_6=Read_AD(6); // Read AD Channel - Le Canal AD
LoadCurrent=Scale(0,1005,-50,50, ADC_6); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
LoadCurrent_Av=Average(6,LoadCurrent,15); // Display calculated average value
}
}
else //Still processing in Background at lower scan rate
{
If (Edge_1000ms) { ADC_6=Read_AD(6); // Read AD Channel - Le Canal AD
LoadCurrent=Scale(0,1005,-50,50, ADC_6); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
LoadCurrent_Av=Average(6,LoadCurrent,15); // Display calculated average value
}
}
//Analog input 07
If (Edge_100ms) { ADC_7=Read_AD(7); //Read AD Channel - Le Canal AD
AirTemp=Scale(0,307.2,0,1500, ADC_7); // Out_Scaled_Value=(IN_Min,IN_Max,OUT_Min,OUT_Max,IN_Input_Value)
AirTemp_Av_temp=Average(7,AirTemp,30);
}
If (AirTemp_Av_temp>0) AirTemp_Av=AirTemp_Av_temp;
// *****************************************************
//Beep Sound when ENTER pressed - Som do Bip quando Enter Pressionado
// *****************************************************
if (input(ENTER)==1)
{
delay_ms(10); //debouncing time
if (aux4==0) Edge_Beep_ON=1;
aux4=1;
}
else aux4=0, Edge_Beep_ON=0, TON[2].R=1;
if (Edge_Beep_ON==1) {
output_high(BUZZER);
delay_ms(20);
output_low(BUZZER);
Edge_Beep_ON=0;
}
//------------------------------------------------------
//Write eeprom
//------------------------------------------------------
if (Edge_1000ms) {
write_eeprom(1, FuelTankLevel_Av); //Grava na eeprom, nível do tanque
write_eeprom(2, (AirTemp_Av/2)); //Grava na eeprom, temperatura do ar
write_eeprom(40, S); //Grava na eeprom, SEGUNDOS
write_eeprom(41, M); //Grava na eeprom, MINUTOS
write_eeprom(42, H); //Grava na eeprom, HORAS
}
// *****************************************************
If (TON[0].Q) output_high(LAMP_SHIFT_LIGHT); ELSE output_low(LAMP_SHIFT_LIGHT);
If (input(DOWN)==0) output_high(USB_5V); ELSE output_low(USB_5V);
}
}
|
_________________ Hugo Silva |
|
|
younder
Joined: 24 Jan 2013 Posts: 53 Location: Brazil
|
Flex LCD Code |
Posted: Thu Jul 11, 2013 6:17 pm |
|
|
Code: |
// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver. Change these
// pins to fit your own board.
#define LCD_DB4 PIN_D5 // D5 D5
#define LCD_DB5 PIN_D4 // D4 D4
#define LCD_DB6 PIN_D3 // D3 D7
#define LCD_DB7 PIN_D2 // D2 D6
#define LCD_E PIN_D6 // D6 C6
#define LCD_RS PIN_D7 // D7 C7
//#define LCD_RW PIN_D6
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.
//#define USE_LCD_RW 1
//========================================
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line
void lcd_load_custom_chars(void);
int8 const LCD_INIT_STRING[4] =
{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};
//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));
delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);
}
//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.
#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3
retval = 0;
output_high(LCD_E);
delay_cycles(1);
retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
output_low(LCD_E);
return(retval);
}
#endif
//---------------------------------------
// Read a byte from the LCD and return it.
#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;
output_high(LCD_RW);
delay_cycles(1);
high = lcd_read_nibble();
low = lcd_read_nibble();
return( (high<<4) | low);
}
#endif
//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);
#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif
if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);
delay_cycles(1);
#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif
output_low(LCD_E);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------
void lcd_init(void)
{
int8 i;
output_low(LCD_RS);
#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(15);
for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}
}
//----------------------------
void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
if(y != 1)
address = lcd_line_two;
else
address=0;
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
//-----------------------------
void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,2);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;
lcd_gotoxy(x,y);
// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));
output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);
return(value);
}
#endif
//=============================================
// Special Character Function
// This table holds the data for the LCD custom chars.
// It can only hold a maximum of 8 custom characters.
//
// Octal numbers 000 to 007 must be used with the "escape"
// backslash to display a custom char with printf.
// The line below displays the degrees symbol with \002.
// The "F" is for Fahrenheit. The "%3d" displays the
// temperature. The \f clears the LCD before displaying
// anything.
// Display temperature on top line of LCD.
// printf(lcd_putc, "\f %3d \002F \n", temperature);
const int8 custom_chars_Screen_1[] =
{
// Char Number 0 -- Not Used
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000 // ........
// Char Number 1 -- Screen Position 1
0b00011011, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 2 -- Screen Position 2
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 3 -- Degrees Celcius
0b00011000, // ........
0b00011000, // ........
0b00000111, // ........
0b00000100, // ........
0b00000100, // ........
0b00000100, // ........
0b00000111, // ........
0b00000000, // ........
// Char Number 4 -- RPM
0b00001110, // ........
0b00010001, // ........
0b00011001, // ........
0b00010101, // ........
0b00000010, // ........
0b00000001, // ........
0b00000001, // ........
0b00000000, // ........
// Char Number 5 -- Speed
0b00000001, // ........
0b00000001, // ........
0b00011111, // ........
0b00000000, // ........
0b00011110, // ........
0b00000001, // ........
0b00011110, // ........
0b00000000 // ........
};
const int8 custom_chars_Screen_2[] =
{
// Char Number 0 -- Not Used
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000 // ........
// Char Number 1 -- Screen Position 1
0b00000100, // ........
0b00000000, // ........
0b00011011, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 2 -- Screen Position 2
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 3 -- Degrees Celcius
0b00011000, // ........
0b00011000, // ........
0b00000111, // ........
0b00000100, // ........
0b00000100, // ........
0b00000100, // ........
0b00000111, // ........
0b00000000, // ........
// Char Number 4 -- Fuel Icon
0b00011111, // ........
0b00010001, // ........
0b00010001, // ........
0b00011111, // ........
0b00001110, // ........
0b00001110, // ........
0b00011111, // ........
0b00000000, // ........
};
const int8 custom_chars_Screen_3[] =
{
// Char Number 0 -- Not Used
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000 // ........
// Char Number 1 -- Screen Position 1
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00011011, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 2 -- Screen Position 2
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 3 -- Degrees Celcius
0b00011000, // ........
0b00011000, // ........
0b00000111, // ........
0b00000100, // ........
0b00000100, // ........
0b00000100, // ........
0b00000111, // ........
0b00000000, // ........
// Char Number 4 -- Instantaneous Consumption
0b00000100, // ........
0b00000100, // ........
0b00001110, // ........
0b00011111, // ........
0b00011111, // ........
0b00001110, // ........
0b00000000, // ........
0b00000000 // ........
// Char Number 5 -- Average Consumption
0b00000100, // ........
0b00001110, // ........
0b00010101, // ........
0b00010101, // ........
0b00010101, // ........
0b00001110, // ........
0b00000100, // ........
0b00000000, // ........
};
const int8 custom_chars_Screen_4[] =
{
// Char Number 0 -- Not Used
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000 // ........
// Char Number 1 -- Screen Position 1
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00011011, // ........
0b00000000, // ........
// Char Number 2 -- Screen Position 2
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 3 -- Degrees Celcius
0b00011000, // ........
0b00011000, // ........
0b00000111, // ........
0b00000100, // ........
0b00000100, // ........
0b00000100, // ........
0b00000111, // ........
0b00000000, // ........
// Char Number 4 -- P Icon with bar
0b00001110, // ........
0b00001010, // ........
0b00001110, // ........
0b00001000, // ........
0b00000000, // ........
0b00011111, // ........
0b00011111, // ........
0b00000000, // ........
// Char Number 5 -- I Icon with bar
0b00001110, // ........
0b00000100, // ........
0b00000100, // ........
0b00001110, // ........
0b00000000, // ........
0b00011111, // ........
0b00011111, // ........
0b00000000, // ........
// Char Number 6 -- R Icon with bar
0b00001100, // ........
0b00001010, // ........
0b00001100, // ........
0b00001010, // ........
0b00000000, // ........
0b00011111, // ........
0b00011111, // ........
0b00000000, // ........
// Char Number 7 -- Blank
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00001110, // ........
0b00000000, // ........
};
const int8 custom_chars_Screen_5[] =
{
// Char Number 0 -- Not Used
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000 // ........
// Char Number 1 -- Screen Position 1
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 2 -- Screen Position 2
0b00011011, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 3 -- Degrees Celcius
0b00011000, // ........
0b00011000, // ........
0b00000111, // ........
0b00000100, // ........
0b00000100, // ........
0b00000100, // ........
0b00000111, // ........
0b00000000, // ........
// Char Number 4 -- Temperature Icon
0b00000100, // ........
0b00000110, // ........
0b00000100, // ........
0b00000110, // ........
0b00000100, // ........
0b00011111, // ........
0b00010101, // ........
0b00000000, // ........
};
const int8 custom_chars_Screen_6[] =
{
// Char Number 0 -- Not Used
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000, // ........
0b00000000 // ........
// Char Number 1 -- Screen Position 1
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 2 -- Screen Position 2
0b00000100, // ........
0b00000000, // ........
0b00011011, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
0b00000100, // ........
0b00000000, // ........
// Char Number 3 -- Degrees Celcius
0b00011000, // ........
0b00011000, // ........
0b00000111, // ........
0b00000100, // ........
0b00000100, // ........
0b00000100, // ........
0b00000111, // ........
0b00000000, // ........
// Char Number 4 -- Baterry
0b00011111, // ...OOOOO
0b00011011, // ...OO.OO
0b00010001, // ...O...O
0b00011011, // ...OO.OO
0b00011111, // ...OOOOO
0b00010001, // ...O...O
0b00011111, // ...OOOOO
0b00000000, // ........
// Char Number 5 -- Load Current
0b00010001, // ........
0b00011111, // ........
0b00010001, // ........
0b00000000, // ........
0b00010001, // ........
0b00010001, // ........
0b00011111, // ........
0b00000000, // ........
// Char Number 6 -- Alternator Current
0b00011111, // ........
0b00010100, // ........
0b00011111, // ........
0b00000000, // ........
0b00010001, // ........
0b00010001, // ........
0b00011111, // ........
0b00000000, // ........
};
void load_custom_chars(int8 Active_Screen_Nr)
{
int8 i;
// Set address counter pointing to CGRAM address 0.
lcd_send_byte(0, 0x40);
// Load custom lcd character data into CGRAM.
// It can only hold a maximum of 8 custom characters.
Switch(Active_Screen_Nr)
{
case 1 : for(i = 0; i < sizeof(custom_chars_Screen_1); i++) lcd_send_byte(1, custom_chars_Screen_1[i]); break;
case 2 : for(i = 0; i < sizeof(custom_chars_Screen_2); i++) lcd_send_byte(1, custom_chars_Screen_2[i]); break;
case 3 : for(i = 0; i < sizeof(custom_chars_Screen_3); i++) lcd_send_byte(1, custom_chars_Screen_3[i]); break;
case 4 : for(i = 0; i < sizeof(custom_chars_Screen_4); i++) lcd_send_byte(1, custom_chars_Screen_4[i]); break;
case 5 : for(i = 0; i < sizeof(custom_chars_Screen_5); i++) lcd_send_byte(1, custom_chars_Screen_5[i]); break;
case 6 : for(i = 0; i < sizeof(custom_chars_Screen_6); i++) lcd_send_byte(1, custom_chars_Screen_6[i]); break;
}
// Set address counter pointing back to the DDRAM.
lcd_send_byte(0, 0x80);
}
void lcd_load_custom_chars(int8 Actual_screen)
{
static int8 Actual_screen_mem=0;
static int1 Actual_screen_edge=0;
if (Actual_screen!=Actual_screen_mem) load_custom_chars(Actual_screen);
Actual_screen_mem=Actual_screen;
}
|
_________________ Hugo Silva |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 11, 2013 9:14 pm |
|
|
The line above doesn't make an array. It makes a pointer. If you want
an array, you need to declare it. Example:
There are several places in your program with false "arrays" like this.
You need to fix all of them. |
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Thu Jul 11, 2013 10:20 pm |
|
|
Just a comment on the update rate - I don't think I would go less than 250 ms. Less than that and even if the display can handle it, your eyes typically can not deal with numbers changing that fast. 500ms would probably be even better. There are some things like rpm that are often better displayed with an analog type meter (either a real one or an led type bar graph). 499, 500, 502, 498, 503 all in less than a second generally will simply confuse your eyes (and brain).
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Fri Jul 12, 2013 5:16 am |
|
|
Mikey's right about the update rate. consider an LCD clock. The colon between the hrs and min flashes at a 1hz rate( 1/2 sec on, 1/2 off).Any faster and it'd be 'blurry'.LCD DVMs typically update at 3 HZ.
Same holds true for digital tachs, 1-2 readings per second.
It's a case where faster is not better.
hth
jay |
|
|
younder
Joined: 24 Jan 2013 Posts: 53 Location: Brazil
|
|
Posted: Sun Jul 21, 2013 3:05 pm |
|
|
Guys thanks for the replys, and I agree that 250ms should be fine in most of the applications... The point is that in that particular application I'd like to have the texts sliding in at least 200ms for a better and fast reading of the messages... and as you can see in the video (link above) it was working ok with 200ms update rate.... however after I've replaced to the new one I could not make it work again...Just do not know why or if it's related to the new controller S6A0069. _________________ Hugo Silva |
|
|
|
|
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
|