Elektromer-meranie napätia a prúdu každú 1ms, výpis spotreby

Zdravím vás
V škole som dostal úlohu s ktorou neviem nejak pohnúť. Moje programátorske schopnosti sú minimalne. Mám za úlohu spraviť elektromer. meranie napätia a prúdu každú 1ms a vypis na displaji každu 1s vždy najväčiu hodnotu a vypis odberu vo watt minutach kazdú minutu. Mám to programovať na kite STK 500 mikroprocesor Atmega16 v jazyku C AVR studio. Mal by som merať spotrebu ledky. Ak viete dakujem za pomoc

:arrow_right: administrator: přejmenováno z "Elektromer"

Co jsou to minimální schpnosti? :slight_smile: svítit ledkou, číst tlačítka umíš?
K tomu kitu musíte mít nějaký doplňky. Bez zapojení se nehnem. Totiž jen s tím, co je na kitu k dispozici /zapojení/, mě tedy vskutku nenapadá jak požadovaná měření provést.

Tlačítka by som ešte zvladol, ale to k tomu nepotrebujem. Zapojenie je také, že na portA je pripojena LED na ktorej meriam prud a napätie. Na porteB alebo C je pripojený displej

mam auto, ma 4 kolesa, na hline… potrebujem nove pneumatiky ? asi take udaje si nam dal…musis uznat ze je ich dost malo… hod sem schmematko a myslim ze vyvojovy kit ma kniznice kde je ovladanie displeja, tlacidla ,praca s ad prevodnikom… daj schemu a mozeme ti zacat radit…

Atlan: nice :smiley: :smiley: Přesně něco v tom duchu jsem chtěl napsat.

rangy:
Alespoň náznak nějakých informací by tu naštestí byl. Na PORTA jsou vstupy AD, to je dobře.
Předpokládejme tedy, že je dioda zapojena tak, aby se na ní dalo něco měřit. Tedy Vcc -> odpor známé velikosti -> dioda -> GND. Případně můžou být dioda a odpor prohozeny. Vstup mcu musí být přípojen mezi odpor a diodu.
Jelikož měříš pouze 1 pin, převodník bude pracovat v “single-ended” režimu.
Aby ti převodník ukázal nějakou relevantní hodnotu, bude třeba, aby napětí na vstupu nepřekročilo Vref. Interní referenci 2.56V tedy asi moc nevyužijeme. Posláním tvého úkolu nejspíš není naprosto přesná změřená hodnota, nebál bych se tedy použít jako referenci Vcc.

Tyto informace ovšem stejně ještě nějakou dobu nevyužiješ.
Nejprve je třeba zprovoznit displej. Umíš s ním pracovat (vypsat na něj hodnotu nějaké proměnné)? Pokud ano, můžem to přeskočit. Jesli ne, potřebujem info (jesli je to součást kitu, budou k tomu dostupné příklady).
Typ (led/lcd)
Pokud LCD: s řadičem(typ)/bez(to by asi neriskovali :slight_smile:)
V obou případech připojení k mcu.

Frekvence mcu?

Ohladne displeju mam vsetko tam nieje problem. Je to 8Mhz atmega16

Výborně, tak to už zbývá jen nějaké to měření a pár výpočtů.
Pro začátek je třeba rozjet převodník.

  1. Povolit převodník (ADEN)
  2. nastavit referenci na AVCC
  3. nastavit analog. multiplexer na správný kanál (= kde je dioda, po resetu je ADC0)
  4. nastavit hodiny pro převodník (50-200kHz). 8MHz/200kHz = 40. Nejbližší vyšší je 64, tu použij. Taktovačka převodníku tedy bude 8MHz/64=125kHz, což je v požadovaném rozsahu.
  5. Spustit první převod (ADSC)
  6. Počkat na dokončení (ADIF == 1)
  7. Vynulovat ADIF (zápisem 1 do něho)
    8 ) Vyzvednout si výsledek převodu (registr ADC, popř. ADCL a ADCH)
    Mimochodem - všechno je to v datasheetu.
    … a pak třeba zobrazit na displeji. Registr ADC je 16bit velký(výsledek je na spodních 10ti bitech). Budeš tedy potřebovat proměnnou typu (unsigned) int.

Později bude potřeba ještě nastavit u převodníku autotrigger a jeho zdrojem bude timer.

Tak som sa snažil cosi spraviť, ale mam tam niekde chybu a neviem kde. Prevodník mam takto:

[code]#include <avr\io.h>
#include <stdio.h>
#include <stdint.h>

void adc_init(void)
{

}

uint16_t ReadChannel(uint8_t mux)
{
//uint8_t i;
uint16_t result;

ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
ADMUX = mux; // Kanal
ADMUX |= (1<<REFS1) | (1<<REFS0); // REF

ADCSRA |= (1<<ADSC); // urob prevod
while ( ADCSRA & (1<<ADSC) ) { ; // je uz koniec prevodu ?
}
result = ADCW; // Vysledok

return result;
}
[/code]

a ten vypis mam takto, ale vypisuje mi to nejaky nezmysel

[code]#include <avr\io.h>
#include <stdio.h>
#include <avr\pgmspace.h>
#include <stdint.h>
#include <stdlib.h>
#include “LCD4bit.h”

int main(void)
{

char txtbuf[32]="";



lcd_init();




   while(1)
		{


        uint16_t adcval;
		uint16_t re;
		uint32_t res;
		float res1;          



		lcd_goto(0);

		adcval = ReadChannel(0);
		sprintf(txtbuf," %x  ",adcval);
		lcd_writestr(txtbuf);

		res=adcval;
		re=adcval;

 		res = ((2560000*res)/512);   
 	
		


		lcd_goto(40);

		sprintf(txtbuf,"%ld",res);
		lcd_writestr(txtbuf);

		lcd_goto(0x15);


 		dtostrf( res1, 10, 8, txtbuf ); 
		lcd_writestr(txtbuf);



		}


return 0;

}
[/code]

Používáš interní referenci? Jelikož jsi nás neobšťastnil zapojením, nelze říct, zda to bude použitelné či nikoli. Každopádně při každém měření ji příkazem “ADMUX = mux;” vypneš. Jelikož pak potřebuje po zapnutí nějaký čas na ustálení (kteý jí nedáváš), dá se předpokládat, že budeš měřit nesmysly.

Opravdu potřebuješ mít možnost nastavit měřený kanál parametrem funkce? Bylo by jednodušší provést tahle nastavení v inicializaci (kam patří řádky “ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);” a “ADMUX |= (1<<REFS1) | (1<<REFS0);”) a pak s tím nemanipulovat.
Pokud je to třeba, nemůžeš požadovaný kanál do ADMUX zapsat přímo (vypnul by sis referenci). Je třeba pomocí “ADMUX &= 0b11100000; // mux chanel 0” vynulovat dolní bity a pak ty správný nastavit (ADMUX |= mux & 0b00011111;).
Ten while stačí takto: “while(ADCSRA & (1<<ADSC));” bez závorek. Proměnná “result” je také zbytečná. Lze napsat rovnou “return ADW;”.

To vypisování na displej máš celý “lehce” chaotický. DELETE a znova :slight_smile:
Převeď číslo z převodníku na řetězec (“itoa()”, podrobnosti v manuálu gcc) a ten pak vypiš.

Proměnný se deklarují na začátku funkce.

Oprava: funkce pro převod bude v tomto případě “utoa()”. Obě by zde sice fungovaly správně(hodnota nepřekročí 15bit), ale logicky vhodnější je tato.

Podla jednej knihy som sa snazil nieco spravit, ale mam tam jednu chybu pri tom utoa.

[code]#include <avr\io.h>
#include <stdio.h>
#include <stdlib.h>
#include <avr\pgmspace.h>
#include <stdint.h>
#include “LCD4bit.h”

void main(void)
{
unsigned int napatie;
unsigned char pom[5];

lcd_init();

	lcd_gotoxy(0,0);
		napatie = (int) (ADCW*4.888);
		utoa (napatie, pom);
		lcd_gotoxy (0,1);
		if (napatie <1000) lcd_gotoxy (1,1);
		if (napatie <100) lcd_gotoxy (2,1);
        if (napatie <10) lcd_gotoxy (3,1);
		lcd_puts (pom);


		


	while(1)
		{


        


			}
			return 0;

}[/code]

a zapojenie mam tak, ze na PA0 a GND mam pripojený potenciometer

Main máš deklarován jako void, nemůže tedy nic vracet (žádné return).

Vypadá to, že ani s výpisem proměnné na displej to nebude tak slavné že :slight_smile:.
Syntaxe utoa() je: char* utoa (unsigned int __val, char* __s, int __radix)
Stačí jen otevřít manuál překladače a dát najít “utoa”.

Zkus pro začátek rozjet jen výpis proměnné. Tvoji lcd knihovnu neznám, to je na tobě.

[code]#include <avr\io.h>
#include <stdlib.h> // obsahuje utoa()
//#include <avr\pgmspace.h> //zatím není třeba
#include “LCD4bit.h”

volatile unsigned int napatie;

void main(void)
{
// unsigned int napatie; // pro test bude globální a volatile pro zamezení nežádoucím optimalizacím
char pom[6];
// bez “unsigned” - zde má význam textu, nikoli celých kladných čísel
// max. hodnota uint v desitkove soustave je 65535
// => 5 číslic + ukončení stringu ==> min. delka je 6 ikdyz teoreticky by nemělo být 9999 překročeno.

napatie = 1234;
// char* utoa (unsigned int __val, char* __s, int __radix)
// __val = převáděné číslo, __s = pointer na string, zde pole char, __radix = číselná soustava řetězce, zde 10
utoa (napatie, pom, 10); 

lcd_init(); 
lcd_gotoxy(0,0);
/* pro test vynechat 
lcd_gotoxy(0,1);
if (napatie <1000) lcd_gotoxy (1,1); 
if (napatie <100) lcd_gotoxy (2,1); 
if (napatie <10) lcd_gotoxy (3,1); 
*/
lcd_puts (pom); 

while(1) 
{ 
	//

} 

}[/code]

Ked to takto spravim tak mi to vyhadzuje 2 chyby. jedna je undefined reference to ‘lcd_gotoxy’ a ta druha je ‘lcd_puts’

Práce s lcd je tvůj problém, nemám tu ovládací knihovnu, tak to nemůžu řešit. Jesli ti to předtim chodilo, tak přidávej věci, co jsem vyhodil (nejdřív hlavičkový soubory) než to pojede.
Když se nebude dařit, tak sem hoď celej projekt abych se mohl pokusit o překlad u sebe.

Jak to jde? Nějaký pokrok?

Takže uz mi to vypisuje hodnotu napätia, ale ma to jednu chybu. Vypis je v milivoltoch takže 4 čisla. Keď mám 1 a viac voltov v pohode, ale ked mam napr. 0,9 tam mi to vypiše 9000. Ďalšie čo musím spraviť je merať prúd na druhom kanáli a to taktiež vypísať najprv ako hodnotu napätia.

Pokud by šlo o měření výkonu 1 diody, tak tam ti při známém Vcc a známém odporu přeci stačí pouze jedno napětí (odpor nebo dioda). Vše ostatní lze dopočítat. Nebo máš v zadání, že má být program schopen měřit každou veličinu zvlášť (jak by tomu mělo ve skutečnosti být)?

S tím chybným výpisem bude třeba trochu pokoumat tu lcd knihovnu (jesli správně pracuje s ukončením textu). V proměnné je totiž číslo převedeno pomocí utoa() správně, tedy 3 cifry a koncová ‘\0’ označující konec řetězce. Případně by to mělo jít vypisovat po znacích.

Když tak sem tu knihovnu (nebo celej projekt) vlož a mrknu na to.

Dneska som sa dozvedel, že tam mám dať prúdový a napäťový delič aby to mohlo merať až do 40V. Hodnoty to má merať každú milisekundu a vypisovať každú sekundu najvyššiu hodnotu každú zvlašť.

Dali ti soudruzi taky schéma a rozsah měření proudu? Tam je totiž potřeba proud nějakým způsobem převést na napětí, které změří převodník. Minimálně převodní konstantu je třeba znát pokud by byl obvod neznámý.

Nie nič mi nedali. Schému si mam navrhnúť sám a o rozsahu tiež nič neviem. Včera mi akurát povedal, že keď mi to bude merať dve napätia mám za ním prísť niečo zmení a bude to ukazovať hodnotu prúdu.