Sari la conținut
ELFORUM - Forumul electronistilor

Termostat - PIC16F877


catalin004

Postări Recomandate

Acum se pare ca este ok....o sa modific in loc de 5000 (vref) 4880

#include "LCD_config.h"
float temp;
int tmp;

void get_ADC(){
tmp = ADC_Read(0);              //Read ADC voltage
temp = ((long)tmp*5000)/1023;   //
temp = temp/10;                //Convert mV in Celsius
}

char strTemp[] = "00.0" ;
void tempToStr(float temp, char *buffer) {
  int value = (int)temp;
  buffer[3] = value % 10+48;
  buffer[1] = value/10 % 10+48;
  buffer[0] = value/100 % 10+48;
}

void main(){
TRISA.F0 = 1;                //ADC input to RA01
TRISA=0xFF;
ADCON1=0x80;                 //ADC  reference to 5V Vdd

ADC_Init();                  //ADC start
LCD_Init();                  //LCD Init
LCD_Cmd(_LCD_CURSOR_OFF);
LCD_Cmd(_LCD_CLEAR);

LCD_Out(2,1, "Merge nenea!");
           for(;;){
                  get_ADC();
                  tempToStr(temp, &strTemp); // conversie a unui nr tip FLOAT intr-un STRING
                  delay_ms(200);
                  LCD_Out(1, 1, strTemp);  // afisarea string-ului  
                  }
}

Bun....am rezolvat....acum trebuie sa fac 2 pagini, adica o sa am 3 butoane...

o sa am + - si set....intr-o pagina se va seta temperatura de referinta, iar in prima pagina se va face afisarea si un mesaj Ex: wait for warm sau wait for could....as dori niste sfaturi...

Editat de catalin004
Link spre comentariu

 

Aveti functia definita de 2 ori, linia "void tempToStr(float, char*);" trebuie stearsa.

 

 

Incearca te rog sa compilezi programul in cazul in care functiile sunt asezate ca mai jos. Mai compileaza fara erori oare? Eu zic ca nu, dar daca acea linie care tu spui ca este gresita este prezenta (si asezata la inceputul programului) atunci programul se va compila.

Acea linie se numeste prototipul functiei.

Nu toate programele se realizeaza in ordinea: declaratie variabile, declaratii si definitii functii, functia main().

#include "LCD_config.h"

float temp;
int tmp;

void get_ADC(){
  tmp = ADC_Read(0);              //Read ADC voltage
  temp = ((long)tmp*5000)/1023;   //
  temp = temp/10;                //Convert mV in Celsius
}

char strTemp[] = "00.0" ;

void main(){
  TRISA.F0 = 1;                //ADC input to RA01
  TRISA=0xFF;
  ADCON1=0x80;                 //ADC  reference to 5V Vdd

  ADC_Init();                  //ADC start
  LCD_Init();                  //LCD Init
  LCD_Cmd(_LCD_CURSOR_OFF);
  LCD_Cmd(_LCD_CLEAR);

  LCD_Out(2,1, "Merge nenea!");
  for(;;){
    get_ADC();
    tempToStr(temp, &strTemp); // conversie a unui nr tip FLOAT intr-un STRING
    delay_ms(200);
    LCD_Out(1, 1, strTemp);  // afisarea string-ului
  }
}

void tempToStr(float temp, char *buffer) {
  int value = (int)temp;
  buffer[3] = value % 10+48;
  buffer[1] = value/10 % 10+48;
  buffer[0] = value/100 % 10+48;
}
Link spre comentariu

Mie nu imi dadea eroare...doar ca nu imi afisa pe display ceva concret...doar hieroglife....cum am spus mai sus mergea...se pare ca acum am eroare la programul dvs

Merge si cu acea linie si fara...d

post-218154-0-62545300-1510314987_thumb.png

Editat de catalin004
Link spre comentariu

Exact punctul meu de vedere.

Ca sa fiu mai clar pentru ca se pare ca te-am incurcat.

 

Atunci cand functiile sunt utilizate in ordinea urmatoare:

1. declar si definesc functia

2. utilizarea functiei in programul principal main()

 

Numai este neaparat necesar ca sa fie utilizat si prototipul functiei.

 

Dar atunci cand functiile sunt folosite intr-o ordine diferita, de ex:

1. apelez functia in programul principal main()

2. declar si definesc corpul functiei

Este absolut necesara includerea in program (undeva la inceputul sau) a prototipului functiei.

 

In cazul de mai sus, daca se include prototipul functiei, programul se va compila corect.

Adica asa:

#include "LCD_config.h"

void tempToStr(float, char*);

float temp;
int tmp;

void get_ADC(){
  tmp = ADC_Read(0);              //Read ADC voltage
  temp = ((long)tmp*5000)/1023;   //
  temp = temp/10;                //Convert mV in Celsius
}

char strTemp[] = "00.0" ;

void main(){
  TRISA.F0 = 1;                //ADC input to RA01
  TRISA=0xFF;
  ADCON1=0x80;                 //ADC  reference to 5V Vdd

  ADC_Init();                  //ADC start
  LCD_Init();                  //LCD Init
  LCD_Cmd(_LCD_CURSOR_OFF);
  LCD_Cmd(_LCD_CLEAR);

  LCD_Out(2,1, "Merge nenea!");
  for(;;){
    get_ADC();
    tempToStr(temp, &strTemp); // conversie a unui nr tip FLOAT intr-un STRING
    delay_ms(200);
    LCD_Out(1, 1, strTemp);  // afisarea string-ului
  }
}

void tempToStr(float temp, char *buffer) {
  int value = (int)temp;
  buffer[3] = value % 10+48;
  buffer[1] = value/10 % 10+48;
  buffer[0] = value/100 % 10+48;
}
Editat de mars01
Link spre comentariu

Da....am citit si eu intr-o carte, si scrie ca daca o functie se declara dupa functia main, atunci trebuie definit prototipul functiei la inceput...altfel nu o va recunoaste...insa daca se declara inainte de main nu mai trebuie declarat prototipul...cred ca imi amintesc bine treaba asta...deci prefer sa o declar la inceput...prezint programul care merge...chiar si cu linia aceea

#include "LCD_config.h"
float temp;
int tmp;

void get_ADC(){
tmp = ADC_Read(1);              //Read ADC voltage
temp = ((long)tmp*4880)/1023;   //
temp = temp;                //Convert mV in Celsius
}

void tempToStr(float, char*);
char strTemp[] = "00.0" ;
void tempToStr(float temp, char *buffer) {
  int value = (int)temp;
  buffer[3] = value % 10+48;
  buffer[1] = value/10 % 10+48;
  buffer[0] = value/100 % 10+48;
}

void main(){
TRISA.F1 = 1;                //ADC input to RA01
TRISA=0xFF;
ADCON1=0x80;                 //ADC  reference to 5V Vdd

ADC_Init();                  //ADC start
LCD_Init();                  //LCD Init
LCD_Cmd(_LCD_CURSOR_OFF);
LCD_Cmd(_LCD_CLEAR);

LCD_Out(2,1, "Merge nenea!");
           for(;;){
                  get_ADC();
                  tempToStr(temp, &strTemp); // conversie a unui nr tip FLOAT intr-un STRING
                  delay_ms(200);
                  LCD_Out(1, 1, strTemp);  // afisarea string-ului
                  LCD_Chr_Cp(223);
                  LCD_Chr_Cp('C');
                  }
}
Link spre comentariu

Da este o limitatie a limbajului C, "vede" doar metodele declarate anterior fata de C++ / Java / etc.. unde poti apela in prima functie declarata si ultima functie.

 

Pentru a crea mai multe pagini eu sa proceda in felul urmator:

 

- activez timer0 la 1ms si incep sa le numar ( functia millis() din arduino)

- declar o variabila prin care setez care pagina o vreau

- intr-o functie verific valoarea paginii dorite si decid ce scriu pe LCD

- in loop-ul principal din millis verific cat timp a trecut de la ultima afisare si daca a trecut mai mult decat un anumit timp setat chem functia de afisare care va decide care pagina va fi afisata, un 250ms / 500ms zic e e destul.

- tot in loop-ul principal verific starea butoanelor si daca se apasa + sau - schimb valoarea variabilei care decide pagina selectata. In cazul in care pagina deja este a doua atunci incrementez si temperatura de referinta, astfel la prima apasare se va chimba doar pagina pentru vizualizare fara a incrementa valoarea.

- tot in loop mai verific daca pagina selectata este a doua si daca a trecut un anumit timp de la ultima apasare de buton, sa zicem 15s schimb inapoi pe pagina 1.

Editat de Bandi Szasz
Link spre comentariu

da...pare ok...insa sa o luam cu inceputul....prima data cum fac sa setez temp adica stiu sa fac i++ sau - cu butoanele...dar cum memorez ? adica cum memorez temp setata? tot cu pointer?

ce inseamna ca verificam pagina?

Link spre comentariu

Cred ca asa se face...ma gandeam sa fac si un debounce pe butoane insa am inteles ca nu trebuie sa lucrez cu delay-uri...este necesar debounce?sau daca este musai trebuie sa fac si intrerupere...parei?idei?

#define Pbutton_dir TRISC0_bit
#define Pbutton PORTC.F0
#define Mbutton_dir TRISC1_bit
#define Mbutton PORTC.F0
#define Warning_dir TRISC7_bit
#define Warning PORTC.F6

void set_temp(){
static unsigned int setTemp=30;
if(!Pbutton){
//increment ++
              if(setTemp>=0 && setTemp<=59)
              {
              setTemp++;
              }
              else
              {
              //do nothing
              }
             }
if(!Mbutton){
//decrement --
            if(setTemp>=1 && setTemp<=60)
              {
              setTemp--;
              }
              else
              {
              //do nothing
              }
            }
if(setTemp>=60){
                Warning = 1;
                }
                else
                {
                Warning = 0;
                }
}
               
 

si afisare settemp...i-am dat o valoare initiala la 30...asta ca sa am ceva setat...oricum o sa fac probabil si un buton de start (un comutator), care sa pornesc termostatul doar la initializarea lui...

In legatura cu meniul, ma gandeam la ceva total diferit:switch case, iar timerul sa revina in default, sau case: 1

Editat de catalin004
Link spre comentariu

Temperatura de referinta se tine intr-o variabila simpla ( int sau float, depinde daca vreti si zecimale sau nu). La buton trebuie facut debounce in general, sunt cazuri in care merge si fara dar e mai bine daca exista. Verificati libraria Button din mikroC are tot ce va trebuie inclusiv debounce. La buton se poate introduce si un delay de 1-2ms, de obicei se evita delay-urile mari de sute de ms, pentru buton se poate pune linistit in mic delay.

 

Daca o sa am timp in seara asta o sa va scriu un mic exemplu cum as face eu si sa "furati' de acolo cateva idei si solutii, imi ieste mult mai usor sa explic pe un cod scris decat asa teoretic in vorbe.

Editat de Bandi Szasz
Link spre comentariu

Nu am apucat sa va scriu codul in weekend, dar imi fac azi timp pana seara.

 

ADC-ul cu Vref de 5V are o precizie de 4.88mV, LM35 are la iesire 10mV/C deci este corect findca in acei 10mV/C incap doar doua valori de ADC cu pas de 4.88mV. Pentru o precizie mai mare trebuie o referinta externa pentru ADC, cam pe la 2.5V care ar venii cu o precizie de 2.44mV deci in pasi de aprox. 0.2C

Editat de Bandi Szasz
Link spre comentariu

Aveti aici un mic exemplu de cod de unde sa va inspirati, posibil sa fie greseli in el find scris in notepad pentru ca nu am in momentul de fata acces la MikroC.


#define DISPLAY_REFRESH 250
#define BUTTON_RESET 10000


volatile unsigned long millis = 0;
unsigned long display_time = 0;
unsigned long button_time = 0;
char display_page = 1;
float refTemp = 0;
bit button1_old, button2_old;

void Interrupt(){
  if (TMR0IF_bit){
    TMR0IF_bit = 0;
    TMR0 = 6;
    millis++;
  }
}

void InitTimer0(){ // trebuie recalculata pentru frecventa folosita
  OPTION_REG = 0x4;
  TMR0 = 6;
  INTCON = 0xA0;
}

void display_temp() { // Afisare temperatura curenta
	
}

void display_refTemp() { // Afisare temperatura setata
	
}

void refreshDisplay() {
  if(display_time < millis) { // daca au trecut cel putin 250ms facem refresh la display
	
	if (display_page == 1) {
		display_temp();
	} else if (display_page == 2) {
		display_refTemp();
	}
	
	display_time = millis + DISPLAY_REFRESH;
  }  	
}



void buttonPress(char button) {
	
   if (display_page == 1) { // daca pagina actuala este 1 schimbam pe pagina 2 pt vizualizare
	display_page = 2;
	return;
   }   
	// altfel incrementam sau decrementam
	
  if (button == 1) { // incrementam cu pasi de 0.5C
	refTemp += 0.5;    
  }
  if (button == 2) { // decrementam cu pasi de 0.5C
	refTemp -= 0.5;    
  }	
}

void checkButtons() {
	if(Button(&PORTC, 6, 1, 0)) {  // buton + pe PORTC - 6 cu debounce de 1ms
	  if (button1_old == 0) {
	    buttonPress(1);
		button_time = millis; // retinem cand am apasat ultima data pe buton 
	    button1_old = 1;
	  }
	} else if(button1_old) { // prin verificarea "button1_old" va trebuii sa dam drumul la buton pentru al lua din nou in considerare
		button1_old = 0;
	} 
	
	if(Button(&PORTC, 5, 1, 0)) {  // buton - pe PORTC - 5 cu debounce de 1ms
	  if (button1_old == 0) {
	    buttonPress(2);
		button_time = millis;
	    button2_old = 1;
	  }
	} else if (button2_old) {
		button2_old = 0;
	}
	
	if (button_time + BUTTON_RESET < millis) { // daca au trecut 10s de la ultima apasare si pagina este a 2-a il schimbam pe 1
		if (display_page == 2) {
		  display_page = 1;
		}
	}	
}


void main() {
	
InitTimer0();	
button1_old = button2_old = 0; 	
while(1) {
  refreshDisplay();
  checkButtons();
}	
}
Link spre comentariu

multumesc...intru la studii...pana o sa folosesc metoda dvs o sa pun si metoda mea pe forum, insa fara pagini

#include "LCD_config.h"
#define LED1_dir TRISD0_bit              //LED pentru avarie >60 grade
#define LED1 PORTD.F0
#define RELR_dir TRISD3_bit              //iesire releu incalzire(cuplare rezistenta)
#define RELR PORTD.F3
#define RELV_dir TRISD7_bit             //iesire releu ventilator(racire)
#define RELV PORTD.F7

#define Pbutton_dir TRISC7_bit           //increment buton
#define Pbutton PORTC.F7
#define Mbutton_dir TRISC0_bit           //decrement buton
#define Mbutton PORTC.F0

#define OUTPUT 0
#define INPUT 1

//anonymous enumeration
enum{
OFF=0, ON=1};

float temp;
int tmp;
unsigned int setTemp=30.0;       //temperatura setata initial

void get_ADC(){
tmp = ADC_Read(1);              //Read ADC voltage
temp = ((long)tmp*4880)/1023;   //
}

//buffer function for show float temperature
void tempToStr(float, char*);
char strTemp[] = "00.0" ;
char strSetTemp[] = "00.0";
void tempToStr(float temp, char *buffer) {
  int value = (int)temp;
  buffer[3] = value % 10+48;
  buffer[1] = value/10 % 10+48;
  buffer[0] = value/100 % 10+48;
}

void digital_comand(){
if(!Pbutton){
//increment ++
            delay_ms(10);
            if(!Pbutton){
                          if(setTemp>=0 && setTemp<=59){
                                                         setTemp++;
                                                         }
                         }
              else
              {
              //do nothing
              }
             }
if(!Mbutton){
//decrement --
            delay_ms(10);
            if(!Mbutton){
                         if(setTemp>=1 && setTemp<=60){
                                                        setTemp--;
                                                      }
                         }
              else
              {
              //do nothing
              }
            }
//if temp >60 degrees
if(temp>=600){
                  LED1 = ON;
   //             LCD_Out(2,0, "1234567890123456");
                  LCD_Out(2,0, "                ");
                  LCD_Out(2,0, "    WARNING!    ");
                  }
                  else{
                       LED1 = OFF;
                       //show setTemp
                       ByteToStr(SetTemp, strSetTemp);
                       LCD_Out(2,0, "                ");
                       LCD_Out(2,3, "SetTemp=");
                       LCD_Out(2,11, &strSetTemp);
                       LCD_Chr_Cp(223);      //simbol character for degrees
                       LCD_Chr_Cp('C');      //Celsius character to end of row
                  }
}

//comanda relee in functie de temperatura
void REL_out(){
static unsigned int Stemp;
Stemp = Settemp*10;  //convertire temperatura setata in mV
if(temp<STemp){
                 RELR = ON;
                 }
                 else
                 {
                 RELR = OFF;
                 }
if(temp>STemp){
                 RELV = ON;
                 }
                 else
                 {
                 RELV = OFF;
                 }
}

//initializare hardware
void hw_init(){
TRISA.F1 = 1;                //ADC input to RA01
TRISA.F1=0xFF;
ADCON1=0x80;                 //ADC  reference to 5V Vdd

LED1_dir = OUTPUT;
RELR_dir = OUTPUT;
RELV_dir = OUTPUT;
Pbutton_dir = INPUT;
Mbutton_dir = INPUT;

LED1 = OFF;
RELR = OFF;
RELV = OFF;
}


void main(){
hw_init();
ADC_Init();                  //ADC start
LCD_Init();                  //LCD Init
LCD_Cmd(_LCD_CURSOR_OFF);
LCD_Cmd(_LCD_CLEAR);
LCD_Out(1,4, "Temp=");
           for(;;){
                  get_ADC();
                  digital_comand();
                  REL_out();
                  //show readTemp
                  tempToStr(temp, &strTemp); // conversie a unui nr tip FLOAT intr-un STRING
                  delay_ms(200);
                  LCD_Out(1, 9, strTemp);  // afisarea string-ului
                  LCD_Chr_Cp(223);
                  LCD_Chr_Cp('C');
                  }
}
Editat de catalin004
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări