Sari la conținut
ELFORUM - Forumul electronistilor

Termostat - PIC16F877


Postări Recomandate

Apelezi functia ADC_Init() dupa care ADCON1.F0 = 1; ( iti trebuie a doua valoare din tabela, ADC_Init() o sa seteze 0000 iar pt tine trebuie 0001 deci doar primul bit din ADCON1 trebuie trecut din 0 in 1). Si in cod folosesti ADC_Get_Sample(); , daca apelezi ADC_Read() o sa suprascrii ADCON1 din nou si o sa ai ca referinta pozitiva VDD.

Link spre comentariu
  • 1 lună mai târziu...
Salutare...am facut un nou program pentru termostatul meu...Logic cu ajutorul colegilor

Bandi si Mars ;acum mi s-au pus niste intrebari,de catre profesori

la care nici eu nu stiu raspuncul si as vrea sa il aflu:


1. In cat timp se face conversia AD?Cum se calculeaza?Care sunt limitele timpului

2.De ce s-a folosit copierea din ROM in RAM?nu era destula memorie?

3.Ce inseamna cei mai semnificativi biti?La ce folosesc....?


Astept cu nerabdare niste explicatii....

Mai jos este codul....astept corectari,sugestii si de asemenea mustrari :)))))




//Lcd pinout settings
sbit LCD_RS at RC6_bit;
sbit LCD_EN at RC5_bit;
sbit LCD_D7 at RC1_bit;
sbit LCD_D6 at RC2_bit;
sbit LCD_D5 at RC3_bit;
sbit LCD_D4 at RC4_bit;
//End LCD connections

//Pin direction
sbit LCD_RS_Direction at TRISC6_bit;
sbit LCD_EN_Direction at TRISC5_bit;
sbit LCD_D7_Direction at TRISC1_bit;
sbit LCD_D6_Direction at TRISC2_bit;
sbit LCD_D5_Direction at TRISC3_bit;
sbit LCD_D4_Direction at TRISC4_bit;
//End LCD direction configuration

#define LED_AV_dir TRISD0_bit //Iesire pentru releul de siguranta
#define LED_AV PORTD.F0
#define RELR_dir TRISD3_bit //Iesire pentru releul de incalzire
#define RELR PORTD.F3
#define RELV_dir TRISD7_bit //Iesire pentru releul de 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 buttonDelay 250

#define OUTPUT 0U
#define INPUT 1U

//enumeratie anonima pentru diferite stari
enum{
OFF=0, ON=1};

void hw_init() {
TRISA.F1 = 1; //intrare ADC pe RA01
TRISA.F1=0xFF;
ADCON1=0x80; //Toti pinii RA ca analogici si Vref = Vdd

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

LED_AV = OFF;
RELR = OFF;
RELV = OFF;

LCD_Init();
LCD_CMD(_LCD_CURSOR_OFF);
LCD_CMD(_LCD_CLEAR);
}

#define DISPLAY_REFRESH 500

//definire variabile globale
float temp;
float setTemp=25; //temperatura nominala setata initial
unsigned int Vin, val_temp,val_set_temp;
unsigned int long old_time_button = 0;
unsigned long display_time = 0;
char old_Pbutton = 0;
char old_Mbutton = 0;
char flash = 0;
volatile long int millis = 0, count = 0; //time var

//constante pentru scriere pe display
const char txt11[]=" TERMOSTAT ", txt21[]=" CU AFISAJ LCD ";
const char txt12[]="Temperatura=", txt22[]="Temp setata=",txt32[]=" ";
const char txt13[]=">INCALZIRE PORNITA", txt23[]=">VENTILATIE PORNITA", txt33[]="SUPRATEMPERATURA";
char txt[21];

//functie pentru copiere din ROM in RAM
void strcopy( const char *src, char *dst)
{
while (*src)
{
*(dst++) = *(src++);
}
*dst = 0;
}

//Timer1
//Prescaler 1:1; TMR1 Preload = 61036; Actual Interrupt Time : 1 ms
void InitTimer1(){
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0xEE;
TMR1L = 0x6C;
TMR1IE_bit = 1;
INTCON = 0xC0;
}

void Interrupt(){
if (TMR1IF_bit){
TMR1IF_bit = 0;
TMR1H = 0xEE;
TMR1L = 0x6C;
millis++;
if(count >= 500) {
flash = !flash;
count = 0;
}
else {
count++;
}
}
}

void get_ADC(){
static int i;
Vin = 0;
//facem o medie pentru 10 citiri
for(i = 0;i<10;i++){
Vin = Vin + ADC_Read(1);
}
Vin = Vin / 10;
temp = ((long)Vin * 4880) >> 10;
}

void start_lcd() {
strcopy(txt11,txt);
Lcd_Out(2, 1, txt);
strcopy(txt21,txt);
Lcd_Out(3, 1, txt);
Delay_ms(5000);
}

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

char strSetTemp[] = "00.0";
//buffer function for show float settemperature(referinta)
void SetTempToStr(float SetTemp, char *buff) {
val_set_temp = SetTemp*10; //convert setTemp in mV
buff[3] = val_set_temp % 10+48;
buff[1] = val_set_temp/10 % 10+48;
buff[0] = val_set_temp/100 % 10+48;
}

void digital_comand() {
//daca se apasa butonul de plus se incrementeaza cu 1 la fiecare 250ms
if(!Pbutton && (millis - old_time_button) > 250) {
if(old_Pbutton == 0) {
if(setTemp >= 0 && setTemp <= 44)
{
setTemp += 1;
}
old_time_button = millis;
old_Pbutton = 1;
}
else if(old_Pbutton == 1){
old_Pbutton = 0;
}
}
//daca se apasa butonul de minus se decrementeaza cu 1 la fiecare 250ms
if(!Mbutton && (millis - old_time_button) > 250) {
if(old_Mbutton == 0) {
if(setTemp>=1 && setTemp <= 45)
{
setTemp -= 1;
}
old_time_button = millis;
old_Mbutton = 1;
}
else if(old_Mbutton == 1){
old_Mbutton = 0;
}
}
}

void output_command() {
char hs = 30; //histerezis de 3 grade
char flag_emergency = 0; //flag pentru afisarea mesajului de avarie
//Daca temperatura depaseste 50 de garde se activeaza alta iesire si apare
//pe ecran un mesaj
if(val_temp >= (500 + hs)){
LED_AV = ON;
flag_emergency = 1;
if(flash == 1) {
strcopy(txt33,txt);
Lcd_Out(4, 3, txt);
}
else {
strcopy(txt32,txt);
Lcd_Out(4, 2, txt);
}
}
else if(val_temp <= (500 - hs))
{
LED_AV = OFF;
flag_emergency = 0;
strcopy(txt32,txt);
Lcd_Out(4, 2, txt);
}

//comanda relee
if(val_temp < (val_set_temp + hs) && val_temp > (val_set_temp - hs))
{
RELR = OFF;
RELV = OFF;
strcopy(txt32,txt);
Lcd_Out(2, 1, txt);
}
else if(val_temp <= (val_set_temp)){
RELR = ON; //start incalzire
RELV = OFF;
strcopy(txt13,txt);
Lcd_Out(2, 1, txt);
}
else if(val_temp >= (val_set_temp)){
RELV = ON; //start ventilatie
RELR = OFF;
strcopy(txt23,txt);
Lcd_Out(2, 1, txt);
}
}

void display_temp() {

//afisare temperatura citita
strcopy(txt12,txt);
Lcd_Out(1, 2, txt);
// daca au trecut cel putin 500ms facem refresh la temperatura afisata in timp real
if(display_time < millis) {
tempToStr(temp, &strtemp);
display_time = millis + DISPLAY_REFRESH;
}
LCD_Out(1, 14, strtemp);
LCD_Chr_Cp(223); //simbol character for degrees
LCD_Chr_Cp('C'); //Celsius character to end of row

//afisare temperatura setata
strcopy(txt22,txt);
Lcd_Out(3, 2, txt);
SetTempToStr(SetTemp, &strSetTemp);
LCD_Out(3,14, strSetTemp);
LCD_Chr_Cp(223); //simbol character for degrees
LCD_Chr_Cp('C'); //Celsius character to end of row
}

void main() {
hw_init();
start_lcd();
InitTimer1();
while(1) {
get_ADC();
display_temp();
digital_comand();
output_command();
}
}


Editat de catalin004
Link spre comentariu

  1. La pagina 114 din datasheet 16F877 este data formula de calcul pentru durata timpului de achizitie.

Copierea din ROM in RAM era necesara pentru aducerea datelelor stocate in memoria ROM in bufferul din memoria RAM.Stocarea variabilelor statice in ROM se face pentru economisirea spatiului de memorie din RAM.

In functie de ordinea de reprezentare a datelor big-endian (stores data big-end first) sau little-endian (stores data little-end first), MSB si LSB este diferit. In cazul little endian bitul de pe pozitia zero este LSB (least semnificative bit) iar bitul de pe pozitia cea mai mare este bitul MSB (most semnificative bit).Ordine de reprezentare trebuie sa fie cunoscuta in cazul anumitor transmisii de date, in cazul in care se citesc sau se scriu valori din zona de memorie, in cazul in care se folosesc arhitecturi diferite, etc.

Link spre comentariu
  • 3 săptămâni mai târziu...

Salutare....nu am mai avut timp de DSO18B20 , insa astazi vreau sa ma reapuc de treaba....nu inteleg mai nimic din acel cod, mai ales partea cu case-urile...cred ca sunt mai multi senzori...asa ca rog o mana de ajutor...cu un mic programel mai simplu pentru citrea temperaturii si pentru citirea codului intern al DSO

Link spre comentariu

Salut!

 

Cu o simpla cautare pe Internet gaseai ceva din care sa te inspiri.

 

De ex aici:

https://tutorial.cytron.io/2012/11/01/ds18b20-temperature-sensor/

Codul integral este aici: https://github.com/CytronTechnologies/SK40C_DS18B20

 

Codul este scris in HI-TECH C (compilator "expirat") dar daca il citesti cu atentie il poti folosi ca inspiratie.

Editat de mars01
Link spre comentariu

Am gasit ceva in libraria mikroC....cum am scris mai jos codul imi apare un 160 si se modifica daca incalzesc sau racesc...insa nu imi dau seama care este raportul de calcul...

  Lcd_Chr(3,13,223);                             // Different LCD displays have different char code for degree
                                                 // If you see greek alpha letter try typing 178 instead of 223

  Lcd_Chr(3,14,'C');

  //--- Main loop
  do {
    //--- Perform temperature reading
    Ow_Reset(&PORTE, 2);                         // Onewire reset signal
    Ow_Write(&PORTE, 2, 0xCC);                   // Issue command SKIP_ROM
    Ow_Write(&PORTE, 2, 0x44);                   // Issue command CONVERT_T
    Delay_us(120);

    Ow_Reset(&PORTE, 2);
    Ow_Write(&PORTE, 2, 0xCC);                   // Issue command SKIP_ROM
    Ow_Write(&PORTE, 2, 0xBE);                   // Issue command READ_SCRATCHPAD

    temp =  Ow_Read(&PORTE, 2);
    temp = (Ow_Read(&PORTE, 2) << 8) + temp;
    temp_whole = temp2write >> RES_SHIFT ;
    
    BytetoStr(temp, text);
        LCD_Out(3,2,text);

    Delay_ms(500);
  } while (1);
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