Aktyw Forum

Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.

Sprawdź punkty Zarejestruj się

[ATMEGA8][C] Ograniczenie prądowe

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 4 lip 2010, o 11:21

Kod: Zaznacz cały

#define Uref 2.66 // Nap ref #define Rpom 0.1 // Rez pom #define R1 100000 // Dziel - R1 100k ohm #define R2 7665 // Dziel - R2 7k5 ohm #define Temp_wl 50 // Temp wl wiat #define Temp_wy 30 // Temp wyl wiat #define Temp_max 50 // Temp wyl przek #define Temp_min 40 // Temp wl przek #define Imax 3.15 #include <avr/io.h> //#include <math.h> #include <stdio.h> #include <stdlib.h> #include "naglowkowy.h" void lcd_U_I(void); void lcd_P_R(void); void lcd_T_FAN(void); void lcd_TON_TOFF(void); char data0[8] = {0x0E, 0x11, 0x11, 0x11, 0x0A, 0x0A, 0x1B, 0x00}; //ohm numer 0 char data1[8] = {0x02, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; //stopien numer 1 char data2[8] = {0x00, 0x04, 0x15, 0x0E, 0x15, 0x04, 0x00, 0x00}; // gwiazdka char x; int i, ADC_H, ADC_L; float prad, napiecie, temperatura, ogran, pradogr; long ADC_temp, ADC_temp_sr; float Uin; int napiecie_int , napiecie_float; int prad_int , prad_float; int pradogr_int , pradogr_float; char menu = 0; char setup; int main(void) { Ust_Portow(); LCD_init(); ADC_init(); lcd_def_char(data0,0); lcd_def_char(data1,1); lcd_def_char(data2,2); pierwsza(); write_char(0b00000010); write_text(" Zas.30V"); druga(); write_text(" 3.15A"); write_char(0b00000010); Waitms(100); PORTB|= _BV(PB1); Waitms(500); PORTB &= ~_BV(PB1); czysc(); while(1) { prad = 0; napiecie = 0; temperatura = 0; ADC_temp = 0; ADC_temp_sr = 0; Uin = 0; pradogr = 0; ogran = 0; // pomiar wartosci ADC0 - napiecie for(i = 0 ; i < 20 ; i++) { ADCSRA|= _BV(ADSC); //start pojedynczej konwersji while(bit_is_set(ADCSRA,ADSC)){}; ADC_L = ADCL; ADC_H = ADCH; ADC_temp = ADC_H*256+ADC_L; ADC_temp_sr = ADC_temp_sr + ADC_temp; if(i==19) { ADC_temp = ADC_temp_sr/20; Uin = (Uref/1024)*ADC_temp; napiecie = ((R1+R2)/R2)*Uin; napiecie_int = napiecie; napiecie_float = (napiecie*100)-(napiecie_int*100); } } temperatura = 0; ADC_temp = 0; ADC_temp_sr = 0; Uin = 0; //prad = 0; // pomiar wartosci ADC1 ADMUX |= _BV(PC0); for(i = 0 ; i < 20 ; i++) { ADCSRA|= _BV(ADSC); //start pojedynczej konwersji while(bit_is_set(ADCSRA,ADSC)){}; ADC_L = ADCL; ADC_H = ADCH; ADC_temp = ADC_H*256+ADC_L; ADC_temp_sr = ADC_temp_sr + ADC_temp; if(i==19) { ADC_temp = ADC_temp_sr/20; Uin = (Uref/1024)*ADC_temp; prad = Uin/Rpom; prad_int = prad; prad_float = (prad*1000)-(prad_int*1000); } } temperatura = 0; ADC_temp = 0; ADC_temp_sr = 0; Uin = 0; ADMUX &= ~_BV(PC0); // pomiar wartosci ADC2 ADMUX |= _BV(PC1); for(i = 0 ; i < 20 ; i++) { ADCSRA|= _BV(ADSC); //start pojedynczej konwersji while(bit_is_set(ADCSRA,ADSC)){}; ADC_L = ADCL; ADC_H = ADCH; ADC_temp = ADC_H*256+ADC_L; ADC_temp_sr = ADC_temp_sr + ADC_temp; if(i==19) { ADC_temp = ADC_temp_sr/20; Uin = (Uref/1024)*ADC_temp; temperatura = Uin*90; } } ADMUX &= ~_BV(PC1); ADC_temp = 0; ADC_temp_sr = 0; Uin = 0; //prad = 0; // pomiar wartosci ADC3 ADMUX |= _BV(PC2); for(i = 0 ; i < 20 ; i++) { ADCSRA|= _BV(ADSC); //start pojedynczej konwersji while(bit_is_set(ADCSRA,ADSC)){}; ADC_L = ADCL; ADC_H = ADCH; ADC_temp = ADC_H*256+ADC_L; ADC_temp_sr = ADC_temp_sr + ADC_temp; if(i==19) { ADC_temp = ADC_temp_sr/20; pradogr = (Imax/1024)*ADC_temp; ogran = pradogr; pradogr_int = ogran; pradogr_float = (ogran*1000)-(pradogr_int*1000); } } ADMUX &= ~_BV(PC2); if(temperatura >= Temp_wl) { PORTB|= _BV(PB1); } if(temperatura <= Temp_wy) { PORTB &= ~_BV(PB1); } if(temperatura >= Temp_max) { PORTD &= ~_BV(PD0); } if(temperatura <= Temp_min) { PORTD|= _BV(PD0); } if(bit_is_clear(PINB,PB2)) { // while(bit_is_clear(PINB,PB2)){} Waitms(100); menu=menu+1; if(menu > 3) { menu=0; } } if(menu==0) // prad napiecie { lcd_U_I(); } if(menu==1) /// moc rezystancja { lcd_P_R(); } if(menu==2) // temp fan { lcd_T_FAN(); } if(menu==3) // temp on off { lcd_TON_TOFF(); } // if(bit_is_set(PINB,PB1)) // { // czysc(); // write_text("Fan ON "); // } } return 0; } void lcd_U_I(void) { pierwsza(); write_text(" "); write_data(napiecie_int); write_text("."); if(napiecie_float<10) { write_text("0"); } write_data(napiecie_float); write_text("V"); write_text(" "); write_data(pradogr_int); write_text("."); if(pradogr_float<10) { write_text("0"); } if(pradogr_float<100) { write_text("0"); } write_data(pradogr_float); write_text("A"); druga(); write_text(" "); write_data(prad_int); write_text("."); if(prad_float<10) { write_text("0"); } if(prad_float<100) { write_text("0"); } write_data(prad_float); write_text("A"); write_text(" "); if((napiecie*prad)<1) { write_data(napiecie*prad*1000); write_text(" mW "); } else { write_data(napiecie*prad); write_text(" W "); } } void lcd_P_R(void) { pierwsza(); write_text(" "); if((napiecie*prad)<1) { write_data(napiecie*prad*1000); write_text(" mW "); } else { write_data(napiecie*prad); write_text(" W "); } druga(); if(((napiecie/prad)>=1000000)||(napiecie==0)||(prad==0)) { write_text(" R > 1M"); write_char(0b00000000); write_text(" "); } else { write_text(" "); write_data(napiecie/prad); write_char(0b00000000); write_text(" "); } } void lcd_T_FAN(void) { pierwsza(); write_text(" "); write_data(temperatura); write_char(0b00000001); write_text("C "); druga(); if(bit_is_set(PINB,PB1)) write_text(" Fan ON "); if(bit_is_clear(PINB,PB1)) write_text(" Fan OFF "); } void lcd_TON_TOFF(void) { druga(); write_text(" ON "); write_data(Temp_wl); write_char(0b00000001); write_text("C "); pierwsza(); write_text(" OFF "); write_data(Temp_wy); write_char(0b00000001); write_text("C "); }


A co byś powiedział na zastosowanie TL431 jako zewnętrzenego źródła napięcia odniesienia???? Różne opinie czytałem jedni mówią że to coś daje a inni że nic :/

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 4 lip 2010, o 13:11

Jeśli tylko jeden kanał ADC szaleje, to nie jest wina Vref. Jak duże są te zmiany i jak to się zachowuje prze różnych położeniach suwaka?
Przełącz suwak potencjometru do innych kanałów (po odłączeniu pierwotnego źródła) i napisz co się dzieje.
Mieszanie arytmetyki zmienno- i stałoprzecinkowej to nie jest najlepszy pomysł. Jaką dokładność działań zmiennoprzecinkowych ma ten kompilator?

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 4 lip 2010, o 13:58

Na innych wejściach pomiar jest prawidłowy (0 to jest 0)...tylko na tym kanale od ograniczenia jak ustawie potencjometrem zero i wynik skacze od 0 do 0.045 nawet kiedy to wejście jest zwarte do masy.

Mógłbyś mi wyjaśnić dlaczego tak dziwnie jest zdefiniowany ADMUX od pomiaru napięcia???Niby wykonywany jest pomiar według schematu na PC0...a ADMUX od PC0 jest przypisany do pomiaru prądu :/

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 4 lip 2010, o 14:28

Nie mam pojęcia. Już pisałem, że moim zdaniem ustawianie ADMUX jest błędne. O ile używanie "|=" i "&=" można zrozumieć, bo w tym rejestrze są inne bity (REFS1, REFS0, ADLAR), to symbole PC0..PC2 nie zgadzają się z adresami ADC0..ADC2 i schematem.
Napisz do którego wejścia jest co jest podłączone i jakie wartości mają symb0ole PC0, PC1, PC2.

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 4 lip 2010, o 14:55

Podłączone jest tak jak na tym schemacie z pierwszej strony:

Obrazek


Jeśli dobrze rozumiem chodzi Ci o to:

PC0 - pomiar napięcia (dzielnik)
PC1 - pomiar prądu
PC2 - pomiar temperatury

Do PC3(ADC3) chciałem podłączyć wskazanie ograniczenia

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 4 lip 2010, o 19:00

Kod: Zaznacz cały

// pomiar wartosci ADC1 ADMUX |= _BV(PC0); // pomiar wartosci ADC2 ADMUX |= _BV(PC1); // pomiar wartosci ADC3 ADMUX |= _BV(PC2);
Zamiast tego wpisuj do ADMUX konkretną liczbę, bo teraz robi się z tego łamigłówka.

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 4 lip 2010, o 20:05

Czyli tak ?
ADMUX |= _BV(0);
ADMUX |= _BV(1);
ADMUX |= _BV(2);

Niewiem jakim cudem ale przy ustawieniu :

Kod: Zaznacz cały

ADMUX |= _BV(2);
i podpięciu suwaka do PC4 Atmegi pokazuje się ograniczenie prądowe

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 4 lip 2010, o 20:48

Na przykład dla ADC3:

Kod: Zaznacz cały

ADMUX = 0x43; /* 01 0 0 0011 */

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 4 lip 2010, o 21:12

Dlaczego kiedy w ADMUX jest ustawione wejście ADC2 jest odczytywane wejście ADC4 ?

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 5 lip 2010, o 09:47

Zamiast zadawać takie pytania, zastanów się co robisz źle.
Czy po podłączeniu suwaka do ADC3 i ustawieniu "ADMUX=0x43;" wyświetlana liczba zależy od położenia suwaka? Najlepiej usuń na razie to przeliczanie i wyświetlaj wynik przetwarzania bez przeliczania (powinno być stabilnie 0..1023).

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 5 lip 2010, o 15:22

Mam podpięte tak jak pisałem wyżej i wyświetlana liczba zależy od położenia suwaka...tylko dziwi mnie czemu tak jest dziwnie ten ADMUX ustawiany :/

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 5 lip 2010, o 18:04

Stabilnie?
ADMUX jest ustawiany normalnie. Po prostu błędnie korzystasz z funkcji (makra?) _BV lub stałej symbolicznej PC2.

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 5 lip 2010, o 19:09

Wskazanie jest stabilne z tym że tak jak napisałem wcześniej suwak mam podpięty do ADC4

Wpisałem to tak jak podałeś wyżej, tyle że teraz to wszędzie mi jakieś wyniki pokazuje :/ (a zasilacz mam odłączony!)

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 5 lip 2010, o 19:37

Pokaż definicję _BV, przypisanie wartości PC0..3 lub przekład na asembler tego programu (.s lub .asm).

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 6 lip 2010, o 19:17

Definicji _BV w kodzie nie widzę nigdzie...a takich plików o które pytasz też niema w folderze z programem :/

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 6 lip 2010, o 20:00

Google informuje, że
#define _BV(bit) (1 << (bit))
Zatem wynikiem _BV(PC2), gdzie PC2 prawdopodobnie ma wartość 2 jest 00000100.
ADMUX |= _BV(PC2) ustawia 2 bit w rejestrze ADMUX, czyli adresuje kanał ADC4.
Nie używaj makr/funkcji/stałych których nie znasz.

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 6 lip 2010, o 21:15

Przepraszam najmocniej ale to nie ja pisałem ten program skorzystałem z gotowego wsadu

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 29 wrz 2010, o 16:58

raczej z tabelki wynika że 3 bit adresuje

Awatar użytkownika
Tomasz Gumny
-
-
Posty: 685
Rejestracja: 4 lut 2004, o 23:31
Lokalizacja: Trzcianka/Poznań

Postautor: Tomasz Gumny » 30 wrz 2010, o 13:49

Ta tabelka?
Załączniki
1.JPG
1.JPG (12.24 KiB) Przejrzano 13104 razy

Faber33
-
-
Posty: 98
Rejestracja: 14 cze 2010, o 18:38
Lokalizacja: Warszawa

Postautor: Faber33 » 30 wrz 2010, o 14:19

licząć od lewej to się zgadza co mówisz:P

Wróć do „AVR/AVR32”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 43 gości