Začátečník C - ADC převodník ATmega8 - hodnota příliš lítá

Zdravím. tak jsem se zas pustil do dalšího pokusu. Naprogramovat si volt/ampér-metr do mojeho regulovatelného zdroje. Multiplex 6ti segmentove už funguje krásně. ADC bohužel už tak krásně neposlouchá. Normálně nahodím ADC přibližně takto:
taktovací kmitoče CPU je 4MHz, děličku pro ADC mám :128, tedy 31250Hz takt ADC převodníku, což odpovídá přibližně 2403 vzorků za sekundu.
Referenci mám nastavenou interní 2.56V
ADC mi převádí, bez problémů, jen ta navzorkovaná hodnota sebou mele zleva doprava jak xyz.
GND a AGND mám spojené přímo. Mezi AREF a AGND mám kondík 100nF. AVCC má proti AGND taky 100nF kondík, a na hlavní napájení je připojené přes 53uH indukčnost. (původně jsem tam neměl žádnou, pak odpor 470R, a teďka 53uH). Sitace se skoro neliší.
Zatím mám rozchozený jen voltmetr (ampérmetr bude indeticky potom).
Voltmetr má být do 51.2V. (2.56V na vstupu ADC je 1024, a vydělím-li hodnotu ADC 2ma, získám 512. Tedy 51.2 protože na displeji mám rozsvícený DP mezi 2 a 3tí číslicí).
Hodnota zobrazovaná na displeji je tedy hodnota ADC dělená dvěmi. Přesto mi hodnota lítá o ±1V na displeji, což je ±10 zobrazovaného čísla, a krát 2 ±20 hodnota vzorku z ADC převodníku - což je podle mě dost zlé.
Možná já jsem troubovitý, a něco jsem nedomyslel,…
Berte v úvahu ještě prosím to, že je to moje skutečně první seznámení s ADC, dosud jsem ADC na nic nepoužíval.
Jak se tedy dá “bojovat” s tímto mě záhadným a nevysvětlitelným problémem?
Dík moc, Honza
PS: pokud byste chtěli zdroják, řekněte, ale v něm si myslím že chyba na 99.9% není.

Neadí, nikdo nereaguje… tak si hraju sám no :slight_smile:
Dodělal jsem tam průměrování 16ti vzorků, a hnedka ta hodnota pěkně poslušně stojí. (sice občas desetinky poskočí, ale neni to tak děsný, jak před tím).
Nyní se snažím napasovat stejné algoritmy i na “ampermetr”. Bohužel mi to nějak nefunguje… Snad přijdu na to čím to je.
KDyž mám ADC v režimu kdy spouštím vzorky ručně, tak když spustím a počkám na dovzorkování jednoho vzorku, musím chvilku počkat, než začnu další vzorek? (tady možná dělám chybu)

EDIT: čtu si znovu datasheet, a přišel jsem i na další, asi chybu: mám podtaktovaný ten ADC. Píše se fclk v rozmezí 50-200kHz, a já tam mám jen 31kHz. Zkusím to upravit, třeba to najednou půjde.

Je mozny, že S/H obvod při tak malý frekvenci hodnotu neudrží, ale stejně by neměla lítat o 4 bity.
Nedávno jsem zprovozňoval A/D a meze pro známého, který měl na testování parametrů A/D zaměřenou BP. Jesli se dobře pamatuju, tak mu tam vyšlo efektivní rozlišení asi 4 bity (8ksps). Na druhou stranu to bylo jen tak naházený na nepájivém poli a nebyl použitej “Noise Canceler”. Nepamatuji si už ale spektrální složení toho šumu, nicméně tam myslím byla i 100Hz složka (usměrněné napájení). Ta zhoršovala celkové výsledky. Výkyvy v krátkých intervalech byly snad do 10ti LSB. Těžko říct, čím je to u tebe.

Kdybys chtěl tím procesorem ten zdroj i řídit, pak už by nebyl klouzavej průměr 16ti hodnot to pravý. Za tu dobu, než procesor zjistí přetížení už nemusí bejt co chránit.

ne, svůj zdroj programu psanym v Cčku (kdovíjak přeloženému) nesvěřím. A tomu přiblblýmu ADC co má údajně přesnost ±1LSB tak to ani nááhodou.
Jdu se mejt, pak tu vylepím zdroják, a mrkněte mi prosím na to, chyba by se měla nacházet někde zde:
všiměte si čsáti, kde načítám data z ADC0 a ADC1. Respektive to přepínání těch ADC, a čtení hodnot. Tam je někde chyba !
KDyž zakomentuju třeba tu část snímání z ADC0, tak mi ampérmetr (ADC1) měří naprosto kráásně. Pokud zakomentuju ADC1, tak voltmetr (což je ADC0) funguje taky bez problému. Jakmile mám ale odkomentované oba úseky, všecko jde do řiťy, jednotlivé vzorky z ADC0 a ADC1 se křížem navzájem ovlivňují, a už fakt nevim co s tim. Pěkně tu už kvůli tomu zuřim půl odpoledne, a stále žádný pokrok.

Létající hodnoty jse mvyřešil průměrováním 16ti vzorků. (do sumarizační proměnné nasčítám 16 vzorků, a pak je dělím 16ti)
díkes (za chvíli zdroják, nejdřív ale vlezu do sprchy) :slight_smile:

Ked prepnes MUX, tak chvilu pockaj. Toto sa deje, ked mas makke zdroje meraneho napatia. Ked by si dal priamo na vstupy AD OZ, potom by sa Ti to spravalo korektne. Ale kedze si sa rozhodol merat 51,2V, na vstupe mas velky delic a ten velky odpor nestihne nabyt S/H kapacitu. To nie je chyba AD, to je jednoducho principialny fakt. Cas nabitia na spravnu hodotu samozrejme zavisi od hodonty, ktora predtym na tom S/H kondiku bola. Preto sa to javi, ako by napatia “pretekali” do susednych kanalov.
Ja to robim tak, ze nastavim pre AD autotriger a po novu hodnotu si pridem za 1ms. Vyzdvihnem ju, prepnem kanal a zase sa pre novu hodnotu z dalsieho kanala zastavim az za jednu ms. Preddelic mam nastaveny na 128, Xtal pouzivam 14,7456MHz. Hodnota je velmi stabilna i bez priemerovania. To vsak kvoli filtracii 50/100Hz robim tiez. Ked je preddelic nastaveny na hodotu nizsiu ako 64, meranie je velmi silne zanesene sumom zasahujucim 5 dolnych bitov. Znizit sum odpojenim napajania inym periferiam som neskusal, nepotrebujem sledovat take rychle AD deje, tak neviem, ci by to pomohlo. Preddelic nastaveny na 128 poskytuje velmi stabilnu hodnotu i pri plnej praci procesora.

Co ma vsak velmi prekvapilo, kvantovy sum AD prevodnika (procesor na plny vuykon vratane komunikacie) je nizsi ako 1LSB. Pri pomalej zmene Uvst (kalibracnym vysielacom U) je hodnota v digitoch velmi stabilna az do dosiahnutia zhruba 1/4 - 1/5 LSB. Skusal som to namatkovo v roznych castiach vysledku prevodu.

Jo… já jsem si dal děličku :64, protože když jsem jí měl na 128, byl ADC podtaktovaný na 31kHz. A v datalistu píšou 50-200kHz. Takže nyní je to 62kHz.
Dávat delay mezi jednotlivým přepínám kanálu jsem už taky dělal. Dokonce 1 až 10ms, a stejně je to jak domluva s pařezem.
Makké zdroje napětí - no… zaítm tamk žádný dělič do 51V není. Mám tam potenciometr 10k vražený mezi zem a Vcc, a výstup potíku přímo na ADC.
Za chvíli sem dám ke zkontrolování zdroják. Včera mi totiž zas zdechnul noťas, a už se mi to nechtělo řešit.

Tak nakonec jsem sem zdroják nedal, protože jsem to tak nějak s odřenýma ušima vyřešil.
Průměruju 16 hodnot z ADC. a mezi přepínání kanálů ADC jsem hodil _delay_ms(2), což docela pomohlo. Sice s tím an 100% spokojený nejsem, ale takhle to stačí. zatím.
Dík za pomoc :wink:

Průměrování bude určitě zapotřebý, ale pro začátek bych je odstranil. Pokud ADC pracuje správně, po sobě jdoucí výsledky se od sebe neliší více jak o 1LSB. Poskakování hodnot o 20LSB je známkou nějaké chyby, která se dříve či později projeví i s tím průměrováním.
Možné příčiny:

  1. Signál na vstupu ADCx obsahuje jehly nebo vysoké frekvence. Lze je odstranit RC filterm.
  2. Napětí AVcc není dodstatečn odfiltrovano od Vcc. Používá se cívka 10uH a kond 100nF.
  3. Přes vývody GND tečou cizí vyrovnávací proudy.
  4. Ke čtení 16b dat z ADC se používá TEMP registr, stejný jako se používá při přístupu k 16b timeru. Může docházet ke kolizi při nesprávném pořadí čtení a zápisu 16b dat.
  5. Chybějící kond na AVref.
  6. Plovoucí úroveň na některém z nevyužitých pinů.

ad 1) nemám osciloskop, nevim.
ad 2) cívku mám 56uH (byla po ruce) a kond 100n
ad 3) to nevim jak zjistit. Mega budí multiplexem dokonce 6 LED segmentovek, takže proudy se tam valí docela slušné. Ale ttou zemí, nevím, zkusim s i s tím pohrát.
ad 4) vždycky čtu první ADCL a až pak ADCH.
as 5) n Aref mám 100nF kond proti Agnd
ad 6) veškeré nevyužité piny mi visí v luftě. Nikdy jsme to neřešil, a nebyl problém. Zkusím na nevyužité piny naházet logické nuly, třeba se něco zlepší.

Po sobě jdoucí vzorky - udělám jeden vzorek, přepnu kanál. Udělám vzorek, přepnu zpátky. TO bde asi kámen úrazu. Takhle udělám 32 vzorků (cikcak) (2x 16 vzorků pro dva kanály). Zkusím upravit algoritmus tak, aby dělal vždy 16 souvislých vzorků, a zbytečně tolikrát nepřepínal kanál. Třeba to pomůže.

Dík za užitečnou reakci :wink:

Jesli píšeš v C, tak stačí číst ADC do 16bit proměnný (unsigned int) jako celek, překladač zajistí správné uložení hodnoty. Navíc to bude mnohem rychlejší, než když budeš číst zvlášť ADCL a ADCH.

Co se týká pinů, tak jim alespoň zapínej pull-upy. Většinou to není problém (nejspíš to má mcu ošetřené jakýmsi “sebeudržujícím shmittem”), ale je lepší to zajistit. Neošetřený vstup totiž dokáže tvořit zajímavou neplechu v napájení - na to nejspíš Technik narážel.
Krásný text pro zájemce o tom má Texas Instruments
focus.ti.com/lit/an/scba004c/scba004c.pdf

Důležitá je kapacita na pinu referenčního napětí Vref a pak také kapacita na vstupu ,kterým měříte. Vstupní proud je totiž špičkově poměrně velký. Osvědčila se mi klasika 100n na obě pozice.

měl bych otázku k tématu:
MCU má většinou pro pro kanály ADC celý port - je možné I/O nevzužité jako vstupy ADC používat “normálně” - ne boje potřeba vždy před použitím příslušného pinu zakázat ADC a poté opět povolit?

A vlastně i dtruhou:
chystám se číst všech 8 ADC vstupů po sobě, ale nemělo by to trvat moc dlouho, takže bych raději ustoupil od vzorkování, nebo je aspoň omezil na minimum.Jak nejlépe na to? Když čtu toto téma tak zjišťuju, že to asi nebude jen tak .

Myslím, že A/d převod lze provést vždy. Nemělo by záležet v jakém režimu se pin nachází. A teké nevidím důvod, proč by pin nemohl fungovat jako výstup ikdyž ho zrovna měříš.

Při použití interního A/D se vzorkování nezbavíš stejně tak jako nezbytných prodlev. MCU má totiž jen 1 A/D a S/H obvod a jednotlivé vstupy jsou na S/H připojovány analogovým multiplexerem.

Dneska ve škole jsem měl noťas, tak jsem překopal zdroják.
Původně:

prepni kanal na ADC0
cekej na vzorek
zpracuj
prepni na ADC1
cekej na vzorek
zpracuj

A tohle se mlelo celkem 16x ve smyšce. Tedy z každého kanálu to vyrobilo 16 vzorků, které se pak průměrují. Nyní jsemvymyslel masivní zlepšovák, uznejte sami:

prepni na ADC0
prvni vzorek zahod
navzorkuj dalsich 16 vzorku

prepni na ADC1
prvni vzorek taky popelnice rulezz
a dalsich 16 vzroku

Takhle, je to mnohem úspornější, a i mnohem lepší. Zybtečně se nepřepíná kanál, takže i vzorkovací doby jsou hodněkrát kratší.
Ad to zahazovani prvniho vzorku: kdyz jsem to ve skole psal, vzpoomnel jsem si (ale nejsem si 100% jisty), ze jsem se v datasheetu někde bokem dočetl, že je výhodné první vzorek po přepnutí kanálu zahodit, protože většinou obsahuje “bláboly”.
Nyní zbývá ten zlepšovák vyzkoušet.

Mimochodem, protože jsem C začátečník, tak jsem si na tom docela hezky procvičil for cykly, a příkaz continue. Sice by šel napsat ještě rychlejší úsek progeamu bez použití podmínky s continue, ale já to tam chci takhle mít, a na závadu si myslím že to není.

char i;
prepni_ADC0();
for (i=0;i<17;i++)
{
  udelej_vzorek();
  if (i == 0) continue; //zahozeni vzorku c. 1
  zpracuj_vzorek();
}

**EDIT: To znamenko v cyklu for, to jsem se jen blbe upsal, samozrejme to v programu mam spravne, ale nyni uz vim, kde mam jednu velkou hrubku. **

Myslim, ze toto nepojde. Skor by to slo ako

char i;
prepni_ADC0();
for (i=0;i<17;i++)
{
  udelej_vzorek();
  if (i == 0) continue; //zahozeni vzorku c. 1
  zpracuj_vzorek();
}

alebo dokonca pre vsetky kanaly takto

[code]

// Definice makier s parametrami
#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))
#define RES(BAJT,BIT) ((BAJT) &= ~(1<<(BIT)))
#define NEG(BAJT,BIT) ((BAJT) ^= (1<<(BIT)))
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))

// Nastavenie AD referencie

#define SET_AD_REF_5V_INT  SET(ADMUX,REFS0);\
							    	RES(ADMUX,REFS1)	

#define SET_AD_REF_EXT  	RES(ADMUX,REFS0);\
						  			RES(ADMUX,REFS1)	

#define SET_AD_REF_2_5V_INT	SET(ADMUX,REFS0);\
						  			 	SET(ADMUX,REFS1)	


#define set_ad_kanal(kanal) (ADMUX = (ADMUX & 0xe0) + (0x1f & (uint8_t)kanal))


#define NORMOVANIE_AD_16B	RES(ADMUX,ADLAR)	

#define AKTIVUJ_AD 			SET(ADCSRA,ADEN)
#define SPUSTI_AD_PREVOD	SET(ADCSRA,ADSC)
#define AUTOTRIGER_AD		SET(ADCSRA,ADATE)

#define POMALY_PREVOD 6
#define RYCHLY_PREVOD 4
#define rychlost_ad_prevodu(deliaci_pomer)		ADCSRA &= ~0x07;\
																ADCSRA = ADCSRA | (0x07 & (uint8_t)deliaci_pomer)

#define STOP_AD (ADCSRA = 0) // zastav konverziu, aby sa neprepisala hodnota v ADCL a ADCH

#define POCET_AD_KANALOV 8

int main(void)
{
uint16_t pole_ad_vysledkov[POCET_AD_KANALOV];
SET_AD_REF_2_5V_INT;
NORMOVANIE_AD_16B;
rychlost_ad_prevodu(POMALY_PREVOD);

while(1) {
for( uint8_t = 0; i < POCET_AD_KANALOV; i++) pole_ad_vysledkov* = 0;

  for( uint8_t = 0; i < POCET_AD_KANALOV; i++) {
     set_ad_kanal(i);
     AKTIVUJ_AD;
     for(uint8_t j = 0; j < 17; j++) {
        SPUSTI_AD_PREVOD;
        while(TST(ADCSRA,ADSC));
        if (j > 0) pole_ad_vysledkov* += ADCW;
    }
  }

// tu si nejako tie vysledky spracuj

}
}
[/code]**

Tak, a jsem z toho převodníku zralej na mrtvici. Interní převodník v AVR už nikdy víc! Příště zkusím MCP3002 o kterém jsem něco zaslechl, že je prý dobrý.

Tak, a protože jsem nyní fakt pěkně n**ý, tak tu přikládám zdroják. Můžete mi na to kouknout ,pokud se vám bude chtít.



#include <avr/io.h>

#define F_CPU 4000000U
#include <util/delay.h>

#include <avr/interrupt.h>




char digit; //promenna udavajici aktualne zobrazenou segmentovku
char dig0, dig1, dig2, dig3, dig4, dig5; //jednotlive data na segmentovkach
int volty, ampery;  //zobrazovane udaje VOLTY a AMPERY
int v_cnt, a_cnt; //prumerovaci sumovace
char prvku; //promenna uchovavajici pocet sumovanych dat


ISR (TIMER0_OVF_vect)  //obsluha preruseni TIM0_OVF
{
  PORTB = 0b00111111;   //multiplex 6ti segmentovek
  switch (digit)
  {
    case 0:
	  PORTD = dig0;
      PORTB = 0b00111110;
	  break;
    case 1:
	  PORTD = dig1;
      PORTB = 0b00111101;
	  break;
    case 2:
	  PORTD = dig2;
      PORTB = 0b00111011;
	  break;
    case 3:
	  PORTD = dig3;
      PORTB = 0b00110111;
	  break;
    case 4:
	  PORTD = dig4;
      PORTB = 0b00101111;
	  break;
    case 5:
	  PORTD = dig5;
      PORTB = 0b00011111;
	  break;
  } 

  digit++;  //dalsi segmentovka
  if (digit == 6) digit = 0;  //pokud posledni, pak zas prvni
}



int main (void) 
{
  char k; //cyklova promenna
  
  DDRD = 0b01111111;
  PORTD = 0x00;
  DDRB = 0b00111111;
  PORTB = 0x3F;

  TCCR0 = (1<<CS01); //citac 1 on, divider 8
  TIMSK  = (1<<TOIE0);  //preruseni TIM0_OVF povolene

  sei();  //povoleni preruseni

  digit = 0;   //inicializace promennych

  dig0 = 0b00111111;
  dig1 = 0b00111111;
  dig2 = 0b00111111;
  dig3 = 0b00111111;
  dig4 = 0b00111111;
  dig5 = 0b00111111;

  volty = v_cnt = 0;
  ampery = a_cnt = 0;
  prvku = 0;

  //nastaveni ADC prevodniku
  ADMUX = (1<<REFS1)|(1<<REFS0);   //interni reference 2.56V
  ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1);  //ADC enabled, prescaler :64

  while (1)
  {
    _delay_ms(1);
    ADMUX = (1<<REFS1)|(1<<REFS0);  //ADC0
	_delay_ms(1);
	for (k=0;k<17;k++)
	{
	  adc_wait_converse();  //spustime a pockame na vzorek
	  if (k==0) continue;
      v_cnt += ADC;
	}
	
	_delay_ms(1);
	ADMUX = (1<<REFS1)|(1<<REFS0)|(1<<MUX0);  //ADC1
	_delay_ms(1);
	for (k=0;k<17;k++)
	{
	  adc_wait_converse();  //spustime a pockame na vzorek
	  if (k==0) continue;
      a_cnt += ADC;
	}	

	//2.56V~51.2V    2.56V~2.56A
	volty = v_cnt >> 5;  //prumeruj volty (deleni 16ti a jeste dvema)
	ampery = a_cnt >> 6; //prumerovani amperu (deleno 16ti a jeste ctyrma)
	v_cnt = a_cnt = 0; //vyprazdneni sumovacu
	preved_na_dig(); //prevedeni hodnoty na displej
	
    
	_delay_ms(25);

    
  }




  while (1) ;
}



char preved_hodnotu(char i)  //prevede cislo na data pro displej
{
  switch (i)
  {
    case 0:
	  return 0b01000000;
    case 1:
	  return 0b01111001;
    case 2:
	  return 0b00100100;
    case 3:
	  return 0b00110000;
    case 4:
	  return 0b00011001;
    case 5:
	  return 0b00010010;
    case 6:
	  return 0b00000010;
    case 7: 
	  return 0b01111000;
    case 8:
	  return 0b00000000;
    case 9: 
	  return 0b00010000;
    case 10:
	  return 0b01111111;
    default:
	  return 0b00111111;
  }
}

void preved_na_dig(void) //prevede hodnotu volty a ampery na display data
{
  int tmp1, tmp2;
  tmp1 = volty;
  tmp2 = ampery;

  dig0 = tmp1/100;		//nejprve preved volty:
  tmp1 -= dig0*100;
  dig1 = tmp1/10;
  tmp1 -= dig1*10;
  dig2 = tmp1; 

  dig3 = tmp2/100;		//pak preved ampery:
  tmp2 -= dig3*100;
  dig4 = tmp2/10;
  tmp2 -= dig4*10;
  dig5 = tmp2;

  //prevod cisel na display data
  if (dig0==0) dig0 = preved_hodnotu(10); else dig0 = preved_hodnotu(dig0);  //pokud prvni cifra voltu nulova, potom blank
  dig1 = preved_hodnotu(dig1);
  dig2 = preved_hodnotu(dig2);
  dig3 = preved_hodnotu(dig3);
  dig4 = preved_hodnotu(dig4);
  dig5 = preved_hodnotu(dig5);
}



void adc_wait_converse(void)
{
  ADCSRA |= (1<<ADSC);
  while (ADSC & (1<<ADSC)) ;
}

Už jsem dokonce přestavěl i multiplex, odpory u segmentů. Původně tam byly 33R odpory, a valil tam slušný proud, tak jsem myslel, že to tím bude. Vyměnil jsem tedy odpory za 470R, aby tam tekl pidi proud na segment, a houbeles, samozřejmě tohle závadu nezpůsobuje.
A dokonce se chystám pro vás nakreslit schéma, pač už ani nemám ponětí, kde dělám chybu. (schéma čekejte za chvíli)

A odkaz na schéma (cca 4MB) zde:
jan16.czela.net/zas_adc.jpg

Dík moc, za pomoc!

:arrow_right: administrator: přiloženy externí soubory
zas_adc.jpg

A odkial beries tu istotu, ze napatie na tych odporovych delicoch je ultra tuti fruti stabilne? Ved to beries z napajania!

Pouzi pre AD referenciu Ucc a povedz, co to robi. AD v ATmega je uplne skvely a v ramci svojich parametrov mam s nim len tie najlepsie skusenosti. Velmi jednoducho a dobre sa s nim pracujuce.
Ten zdrojak teraz nemam cas skumat, snad nabuduce.

Ak pouzijes speci 18b prevodnik s internou referenciou a privedies na to zasumene napatie, tak Ti to bude vzdy merat, co na to privedies.

Zdar, nijak podrobně jsem to neluštil, ale na konci mě kopnul zápis “while (ADSC & (1<<ADSC)) ;”
U megy8 se pin ADSC nachází v registru ADCSRA, to by mohla být jedna z chyb pokud jich bude více.
O řádek výš to máš správně, takže předpokládám překlep :wink:

edit:
Další chybu zatím nevidím.
Jen pár postřehů:
dig0 = 0b00111111;
dig1 = 0b00111111;

To lze zapsat do 1 řádku, ušetřil bys trochu psaní. Nicméně to tam již použité máš, takže o tom víš.
Dál až se budeš nudit, tak v mainu ve “while” je opakující se kód, který dělá stejnou věc.
Můžeš si zatrénovat a přepsat ten kód do funkce.

V kódu:
dig0 = tmp1/100; //nejprve preved volty:
tmp1 -= dig0*100;
ukládáš do tmp1 zbytek po dělení. Na to je v C operátor “dělení modulo” nebo-li “%”
tmp1 %= 100;

piityy: dík za užitečnou odpověď.
Ten zápis dole, to sem ale debil !!! Pravděpodobně tahle hovadina mi to cele rozesrává. A to sem tenhle zápis kontroloval taky 150x. A stejně jsem si toho nevším.

k tomu dig0, …, dig5 - v jednom řádku to nemám z jednoho prostého důvodu: timhle přiřazením totiž nastavuju to, co se zobrazí na chvíli na displeji, než se vyrobí první výsledek měření. Nyní tam mám samé pomlčky, ale původně jsem tam měl “HOnZiC”. Zápis od jednoiho řádku stejně asi rychlost programu nepřidá.

VIm že je v Cčku operátor %, a naschvál jsem ho tam nedal, protože dělení je strašně pomalé. A k tomu zbyteku se nedá dojít jinak, než dělením. Dělení sem tam sice už použil, ale to zpětné roznásobení a odečtení je rychlejší než to dělení. Teda aspoň doufám :slight_smile:

ten opakující se kod do funkce můžu dát, ale zas na to mám takový svůj argunemnt (nyní sice dost nepodstatný, že tu se na rychlsot programu moc nehraje), ale aby MCU zbytečně ukládal mraky blbostí do STACKu, a pak ještě kopíroval spousty čísle z a do SRAMky, mi příde trošku zbytečný.

Každopádě dík moc, za ten postřeh s tím ADSC. Jsem z toho děsně n**ý, že jsem si toho nevším, přestože jsem to kontroloval pořádně. (ale asi málo pořádně).

s tím kódem jasny, to bylo myšlený jen jako trening (vhodný pointer) :slight_smile:
Co se týká %, tak překladač není úplně blbej :wink: On to při dělení počítá stejně obojí. Když uvidí, že je to dál potřeba, tak by to nemusel zahodit a naopak by to mohlo být rychlejší. Ale to je třeba si zkusit v simulátoru…

Dál můžeš zkusit optimalizovat to dělení 100. To lze řešit jako dělení 4 (2 posuny vpravo) a pak dělení 25. Výhoda u tebe je to, že číslo je 10bit (což samo překladač neví). Po 2 posunech už zbývá jen 8bit a dělení bude rychlejší. Nejspíš by ale bylo nezbytné po těch posunech hodnotu překopírovat do 8bit proměnné, jinak bude překladač stejně dělit 16bit.
Je to psaní navíc, ale později v případě nedostatku výkonu by se taková úprava mohla vyplatit. Zase je třeba to ověřit v simulátoru.

Že si člověk takový chyby jako to ADSC nevšimne, když u toho celej den sedí, je normální. Dneska bys na to mrknul znova a koplo by tě to taky.