Svetelektro.com

Svetelektro.com

Meno:
Heslo:
SVETELEKTRO • ATtiny45 převod ADC

ATtiny45 převod ADC

C,C++,C#

Moderátori: psichac, Moderátori

ATtiny45 převod ADC

Odoslaťod jirka.jirka. » 25 Sep 2016, 14:16

Zdravím přátelé.

Mám malý problém s ADC-čkem u ATtiny45. Napsal jsem si jednoduchý program, který má za úkol měřit napětí na dvou hall sondách ACS712.
Tyto sondy mají na výstupu napětí 2,5V a podle proudu potom buť zvyšují výstup, nebo snižují.

Takže dejme tomu, že defaultně mám na vstupu hodnotu 2,5V. Referenci mám externí 3V. Potom hodnota ADC bude 853. Jakmile připojím zátěž, tak na výstupu budu mít třeba 2,6V, což odpovídá ADC = 887.

Pokud dojde k tomu, že hodnota výchozí je menší než aktuálně naměřená, dojde k překlopení výstupu.

Program takhle funguje, ale mám problém s tím, že místo toho, aby byl výstup trvale seplý (pokud teče proud), tak mi výstup pulzuje. Proto se obracím sem, jestli někdo v těch mých pár řádcích neuvidí nějakou chybu. Díky moc

Init ADC.
Kód: Vybrať všetko
void init_adc()
{
   /* Nastaveni externi reference na pinu PB0 */
   ADMUX |=  (1 << REFS0);
   ADMUX &= ~(1 << REFS1);

   /* povoli ADC */
   ADCSRA |= (1 << ADEN);

   /* preruseni od ADC */
   ADCSRA |= (1 << ADIF);

   /* nastavi delicku na 64 (125kHz) */
   ADCSRA |= (1 << ADPS2);
   ADCSRA |= (1 << ADPS1);
   ADCSRA &=~(1 << ADPS0);
}


Fce pro výčet hodnoty ADC
Kód: Vybrať všetko
unsigned int Read_ADC(unsigned char channel){
   
   // vloz cislo kanala, vymaskuj nepouzite bity
   ADMUX &= 0xF0;
   ADMUX |= channel & 0x0F;
   
   // Start prevodu
   ADCSRA |= (1 << ADSC);
   
   // ceka, dokud se neskonci konverze
   while(!(ADCSRA & (1<<ADIF)));
   
   //  navratova hodnota - vysledok ad prevodu
   return ADC;
   
}


Komplet program:
Kód: Vybrať všetko
/*
* DEKM.c
*
* Created: 25.9.2016 10:55:13
* Author : Jirka
*/

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include <avr/wdt.h>

#define      OUT1   PB1
#define      OUT2   PB3

unsigned int Read_ADC(unsigned char channel){
   
   // vloz cislo kanala, vymaskuj nepouzite bity
   ADMUX &= 0xF0;
   ADMUX |= channel & 0x0F;
   
   // Start prevodu
   ADCSRA |= (1 << ADSC);
   
   // ceka, dokud se neskonci konverze
   while(!(ADCSRA & (1<<ADIF)));
   
   //  navratova hodnota - vysledok ad prevodu
   return ADC;
   
}

void init_adc()
{
   /* Nastaveni externi reference na pinu PB0 */
   ADMUX |=  (1 << REFS0);
   ADMUX &= ~(1 << REFS1);

   /* povoli ADC */
   ADCSRA |= (1 << ADEN);

   /* preruseni od ADC */
   ADCSRA |= (1 << ADIF);

   /* nastavi delicku na 64 (125kHz) */
   ADCSRA |= (1 << ADPS2);
   ADCSRA |= (1 << ADPS1);
   ADCSRA &=~(1 << ADPS0);
}

void init_output()
{
   DDRB |= (1 << OUT1);   //tento piny jako vystupni
   DDRB |= (1 << OUT2);   //tento piny jako vystupni

   PORTB |= (1 << OUT1) | (1 << OUT2);   //nastavi pullup odpory

}

int main(void)
{
   /* inicializace ADC */
   init_adc();
   /* inicializace vystupu */
   init_output();
   /* povoleni preruseni */
   sei();

   uint16_t adc1 = 0, adc2 = 0, initADC1 = 0, initADC2 = 0, pomocna1 = 0, pomocna2 = 0;
   pomocna1 = Read_ADC(1);
   pomocna2 = Read_ADC(2);

   pomocna1 = 0; pomocna2 = 0;
   for (int i = 0; i < 5; i++)
   {
      pomocna1 += Read_ADC(1);   //po zapnuti vyctu hodnotu z ADC pro lepsi stabilitu
      _delay_ms(1);
      pomocna2 += Read_ADC(2);   //po zapnuti vyctu hodnotu z ADC pro lepsi stabilitu
      _delay_ms(1);
   }
   initADC1 = pomocna1 / 5;
   initADC2 = pomocna2 / 5;

    /* Replace with your application code */
    while (1)
    {
      /* prumer z 5 hodnot */
      pomocna1 = 0;   pomocna2 = 0;
      for (int i = 0; i < 5; i++)
      {
         pomocna1 += Read_ADC(1);
         _delay_ms(2);
         pomocna2 += Read_ADC(2);
         _delay_ms(2);
      }
      adc1 = pomocna1 / 5;
      adc2 = pomocna2 / 5;
         
      if (adc1 > (initADC1+10 ) )   //hodnota 850 prevedeno na napeti (850*3)/2^10 = 2,49V (kde 10 odpovida zmene napeti o 0,03V)
         PORTB &= ~(1 << OUT1);
      else
         PORTB |= (1 << OUT1);

      if (adc2 > (initADC2+10) )
         PORTB &= ~(1 << OUT2);
      else
         PORTB |= (1 << OUT2);
    }
}

Prílohy
fuses.PNG
Nastavení pojistek
jirka.jirka.
Obrázok používateľa
Pokročilý člen
Pokročilý člen
Príspevky: 925
Založený: 17.10.2008
Bydlisko: Zlín
Karma: 9

Re: ATtiny45 převod ADC

Odoslaťod StavJi » 25 Sep 2016, 14:33

Víš jaké hodnoty ti to měří? Máš možnost si je poslat?

Jinak já používám něco takového

Kód: Vybrať všetko
unsigned int ADC_Read(unsigned char pin)
{
   ADMUX = (1 << REFS0) | (1 << ADLAR) | (7 & pin);   // reference = AVcc, zarovnání vlevo, nastavení PINu
   _delay_us(10);   // počkat (eliminuje ovlivňování kanálů), čekání na nabití ADC kapacity
   ADCSRA |= (1 << ADSC);   // start převodu
   while((ADCSRA & (1 << ADSC)) != 0);   // čekání na konec převodu
   ADMUX = (1 << REFS0) | (1 << ADLAR) | 15;   // přepnutí vstupu na 0V (eliminuje ovlivňování kanálů)
   return ((ADCL >> 6) | (ADCH << 2));   // pro ADLAR=0: ((ADCH << 8) | ADCL);
}
}


Jinak ten kód je celkem hnus hlavně ten klouzavej filtr s těma delay funkcema v hlavní smyčce. Klouzavej filtr se počítá pomocí bitových operací http://petr-kubac.blog.cz/1308/matemati ... avy-prumer . A místo delay funkcí můžeš použít jeden časovač nastavenej třeba na 1 ms pomocí kterého nastavuješ co se má dělat. Třeba vzorkovat tlačítka, měřit, překreslovat LCD atd.
StavJi
Okoloidúci
Okoloidúci
Príspevky: 35
Založený: 22.01.2014
Bydlisko: Olomouc
Karma: 0

Re: ATtiny45 převod ADC

Odoslaťod jirka.jirka. » 25 Sep 2016, 14:43

jj. Ty delay teď ostraňuju. Taky se mi to moc nelíbilo. Ale když ten program nemá dělat nic jiného, tak jsem to zkoušel skrze ně.
jirka.jirka.
Obrázok používateľa
Pokročilý člen
Pokročilý člen
Príspevky: 925
Založený: 17.10.2008
Bydlisko: Zlín
Karma: 9

Re: ATtiny45 převod ADC

Odoslaťod StavJi » 25 Sep 2016, 17:30

Jako jestli na to nebude nic navazovat a bude to dělat jen to co jsi poslal, tak nevidím problém proč to dělat složitější. Spíš pro příště nebo při nějakém rozšíření.
StavJi
Okoloidúci
Okoloidúci
Príspevky: 35
Založený: 22.01.2014
Bydlisko: Olomouc
Karma: 0

Re: ATtiny45 převod ADC

Odoslaťod jirka.jirka. » 25 Sep 2016, 17:38

No toto má pouze monitorovat dva ADC kanály. Podle toho rozhodnout jak nastavit výstup. Teď se snažím rozchodit ten klouzavý průměr, ale nedaří se.


Nemáte někdo nějaký příklad, jak ADC hodnot tento klouzavý průměr udělat?
jirka.jirka.
Obrázok používateľa
Pokročilý člen
Pokročilý člen
Príspevky: 925
Založený: 17.10.2008
Bydlisko: Zlín
Karma: 9

Re: ATtiny45 převod ADC

Odoslaťod Najgel » 25 Sep 2016, 18:02

Vždy sčítaj 2 čísla a vydeľ dvoma. (Read1 + Read2 ) / 2= Vysledok1 ... (Vysledok1 + Read3 )/2 = Vysledok2 ... (Vysledok2 + Read4)/2 = Vysledok3 atd...
Keď neodpisujem tak tu nie som, alebo som a neodpisujem :D

MPLAB & PIC
Tevo Tarantula 3D
Ponúkam 3D tlač.

UNIZA 4.ročník
Najgel
Obrázok používateľa
Zaslúžilý člen
Zaslúžilý člen
Príspevky: 1493
Vek: 22.61
Založený: 02.07.2010
Bydlisko: Námestovo, Žilina(škola)
Karma: 30

Re: ATtiny45 převod ADC

Odoslaťod vosa » 26 Sep 2016, 00:02

Uz dlho som nekodil. Mozem sa opytat preco su tam zapnute prerusenia? Ak k nejakemu dojde a premenne nemas volatilne, tak sa resetnu.

K prispevku od Najgela. Myslim, ze iterativny priemer sa pocita inak: http://www.heikohoffmann.de/htmlthesis/node134.html
Pre delenie dvojkou potom pouzi binarny shift, kedze sa robi v cykle.
vosa
Obrázok používateľa
Nový člen
Nový člen
Príspevky: 57
Založený: 24.10.2012
Bydlisko: Bratislava
Karma: 1

Re: ATtiny45 převod ADC

Odoslaťod jirka.jirka. » 01 Okt 2016, 20:49

Zdravím páni. Opět jsem se vrátil k tomu měření na hallových sondách.

Mám ACS712 - 5A.

Ale, program se chová pořád trošku divně.

Výstup na hallově sondě je bez procházejícího proudu 2,47V (Vcc/2). Pokud přivedu zátěž (odběr cca 200mA), tak na výstupu mám napětí 2,5V. Což je rozdíl 30mV.

Jako první co udělám při zapnutí AVR je, že si změřím výstupní napětí (tzn. bez připojené zátěže). Potom jsem si vytvořil TIMER, který má periodu 10ms, kde nastavuju příznak, ať mi změří napětí a toto potom stále porovnávám. Mám externí referenci 3V. Hodnota na ACS drží, na tu jsem koukal hned jako první.

Tzn. hodnota 30mV je převedeno do ADC hodnoty = 10.
A porovnávám hodnotu:
Kód: Vybrať všetko
if (adc1 > (initADC1 + 10) )
         PORTB &= ~(1 << OUT1);
      else
         PORTB |= (1 << OUT1);


A nyní, když mám na výstupu napětí vyšší než 2,5V, tak mi výstup kmitá (tzn. že program mi spíná a rozpíná kontakt). Pouze pokud zátěž adekvátně snížím (tzn. zvýším protékající proud) na výstupu je tudíž vyšší napětí, tak se mi výstup přepne do log 1. Ale tady se bavíme o proudu cca 400mA. Však se na výstup podívejte sami.
Obrázok

Zde je komplet program, bez inicializačních funkcí.
Kód: Vybrať všetko

unsigned int Read_ADC(unsigned char channel){
   
   ADMUX = (1 << ADLAR) | (7 & channel);   // reference = AVcc, zarovnání vlevo, nastavení PINu
   _delay_us(25);   // počkat (eliminuje ovlivňování kanálů), čekání na nabití ADC kapacity
   ADCSRA |= (1 << ADSC);   // start převodu
   while((ADCSRA & (1 << ADSC)) != 0);   // čekání na konec převodu
   ADMUX = (1 << ADLAR) | 15;   // přepnutí vstupu na 0V (eliminuje ovlivňování kanálů)
   return ((ADCL >> 6) | (ADCH << 2));   // pro ADLAR=0: ((ADCH << 8) | ADCL);
}

volatile char flag = 0;
ISR (TIMER0_COMPA_vect)   //preruseni nastane kazdych 10ms
{
   flag = 1;
}

uint16_t initADC1 = 0, initADC2 = 0;
uint16_t pomocna1 = 0, pomocna2 = 0, adc1 = 0, adc2 = 0;
int main(void)
{
   /* inicializace ADC */
   init_adc();
   /* inicializace vystupu */
   init_output();
   /* inicializace timeru */
   init_timer();
   /* povoleni preruseni */
   sei();

   for (int i = 0; i < 10; i++)
   {
      pomocna1 += Read_ADC(1);   //po zapnuti vyctu hodnotu z ADC pro lepsi stabilitu
      pomocna2 += Read_ADC(2);   //po zapnuti vyctu hodnotu z ADC pro lepsi stabilitu
   }
   initADC1 = pomocna1 / 10;
   initADC2 = pomocna2 / 10;

    while (1)
    {
      if (flag == 1)
      {
         adc1 = Read_ADC(1);
         adc2 = Read_ADC(2);
         flag = 0;
      }

      /* nastavuje vystupy, podle namereneho napeti */
      if (adc1 > (initADC1 + 10) )   //hodnota 850 prevedeno na napeti (850*3)/2^10 = 2,49V (kde 10 odpovida zmene napeti o 0,03V)
         PORTB &= ~(1 << OUT1);
      else
         PORTB |= (1 << OUT1);

      if (adc2 > (initADC2 + 10) )
         PORTB &= ~(1 << OUT2);
      else
         PORTB |= (1 << OUT2);

    }
}


Zde jsou pouze inicializační funkce.
Kód: Vybrať všetko
void init_adc()
{
   /* Nastaveni externi reference na pinu PB0 */
   ADMUX |=  (1 << REFS0);
   ADMUX &= ~(1 << REFS1);
   /* preruseni od ADC */
   ADCSRA |= (1 << ADIF);
   /* nastavi delicku na 64 (125kHz) */
   ADCSRA |= (1 << ADPS2);
   ADCSRA |= (1 << ADPS1);
   ADCSRA &=~(1 << ADPS0);
   /* povoli ADC */
   ADCSRA |= (1 << ADEN);
}

void init_timer()
{
   // CTC mode
   TCCR0A |= (1 << WGM01);
   //1024 prescaller
   TCCR0B |= (1 << CS00);
   TCCR0B &= ~(1 << CS01);
   TCCR0B |= (1 << CS02);
   // OCR0A interrupt only.
   TIMSK |= (1 << OCIE0A);
   //10ms
   OCR0A = 79;
}

void init_output()
{
   DDRB |= (1 << OUT1);   //tento piny jako vystupni
   DDRB |= (1 << OUT2);   //tento piny jako vystupni

   PORTB |= (1 << OUT1) | (1 << OUT2);   //nastavi pullup odpory
}
jirka.jirka.
Obrázok používateľa
Pokročilý člen
Pokročilý člen
Príspevky: 925
Založený: 17.10.2008
Bydlisko: Zlín
Karma: 9

Re: ATtiny45 převod ADC

Odoslaťod peterple » 01 Okt 2016, 21:59

ten prúd záťaže je teda jednosmerný, keď píšeš že sa nemení? Nie je tam ani žiadne PWM?
Najjednoduchšie je si logovať namerané hodnoty na sériový port a sledovať terminálom. Takto len hádaš čo sa asi vnútri deje.
Ak sa ti to nedá tak by som zaviedol hysteréziu a postupne ju zvyšoval. Tak by sa tiež dalo nepriamo zistiť v akom rozsahu prevodník hádže čísla. Alebo si ukladať min a max a zobrazovať si to na LCD. Bez debugu sa takéto veci zle vyvíjajú.
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.
peterple
Ultimate člen
Ultimate člen
Príspevky: 1521
Vek: 50.98
Založený: 25.06.2013
Bydlisko: Krajné
Karma: 43

Re: ATtiny45 převod ADC

Odoslaťod jirka.jirka. » 01 Okt 2016, 22:03

Vím že bez debugu to jde špatně, ale nemám teď nic po ruce. Mám jenom attiny45, hallovku a USBasp. Zbytek zůstal doma. A kdy se vrátím domů to sám netuším.

Takže jsem tuto konverzi trošku poladil. Je vidět zlepšení, ale pořád ten výstup není optimální.

Upravil jsem inizializaci ADC:
Kód: Vybrať všetko
void init_adc()
{
   /* Nastaveni externi reference na pinu PB0 */
   ADMUX |=  (1 << REFS0);
   ADMUX &= ~(1 << REFS1);
   /* preruseni od ADC */
   ADCSRA |= (1 << ADIF);
   /* nastavi delicku na 64 (125kHz) */
   ADCSRA |= (1 << ADPS2);
   ADCSRA |= (1 << ADPS1);
   ADCSRA &=~(1 << ADPS0);
   /* povoli ADC */
   ADCSRA |= (1 << ADEN);
   ADCSRA |= (1<<ADSC);   // zapne konverzi
   while (ADCSRA & (1<<ADSC) ) { }  // ceka na dokonceni konverze
   (void) ADCW;   //"vycte se ADCW"
}


Dále jsem upravil vyčítání ADC:
Kód: Vybrať všetko
uint16_t ADC_Read( uint8_t channel )
{
   // Vyber kanalu
   ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
   ADCSRA |= (1<<ADSC);            // Zapne konverzi
   while (ADCSRA & (1<<ADSC) ) { }  // ceka na dokonceni konverze
   return ADCW;                    // navrati hodnotu ADC
}


Teď jdu zkusit ten klouzavý průměr, ale myslím si, že tímto to nebude. Zde by mě mohl stačit i klasický aritmetický průměr.

Jinak proud je stejnosměrný. Aspoň že tak.
jirka.jirka.
Obrázok používateľa
Pokročilý člen
Pokročilý člen
Príspevky: 925
Založený: 17.10.2008
Bydlisko: Zlín
Karma: 9

Re: ATtiny45 převod ADC

Odoslaťod peterple » 01 Okt 2016, 22:09

tak si to pošli von sériovo na nejaký pin (MOSI) a naber to skopom a je.
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.
peterple
Ultimate člen
Ultimate člen
Príspevky: 1521
Vek: 50.98
Založený: 25.06.2013
Bydlisko: Krajné
Karma: 43

Re: ATtiny45 převod ADC

Odoslaťod jirka.jirka. » 01 Okt 2016, 22:16

Naštěstí mám na PB3 jenom tranzistor, takže hned zítra tam pověsím převodník a budu si posílat data po sériovce a budu moudřejší. Aspoň budu vědět, co vyčítám.
jirka.jirka.
Obrázok používateľa
Pokročilý člen
Pokročilý člen
Príspevky: 925
Založený: 17.10.2008
Bydlisko: Zlín
Karma: 9

Re: ATtiny45 převod ADC

Odoslaťod peterple » 01 Okt 2016, 22:19

ja by som teraz vyskúšal urobiť mrtvé pásmo +-1 potom +-2 atd
na niekoľko pokusov by si mohol zistiť o koľko ti to tam lieta.
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.
peterple
Ultimate člen
Ultimate člen
Príspevky: 1521
Vek: 50.98
Založený: 25.06.2013
Bydlisko: Krajné
Karma: 43

Re: ATtiny45 převod ADC

Odoslaťod jirka.jirka. » 01 Okt 2016, 23:21

No takže úpravou přerušení od TIMERu, úpravou předděličky u ADC, přidání krátkého delay do vyčítání ADC a průměrováním hodnot, jsem se dopracoval stabilnímu řešení. Od 130mA mám výstup trvale v log. 1. Zítra ještě mrknu na ty hodnoty ADC přes UART ať vím co se té v té Attině honí za hodnoty.

Výčet hodnot z ADC a průměrování:
Kód: Vybrať všetko
uint16_t ADC_Read( uint8_t channel )
{
   // Vyber kanalu
   ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
   ADCSRA |= (1<<ADSC);            // Zapne konverzi
   while (ADCSRA & (1<<ADSC) ) { }  // ceka na dokonceni konverze
   return ADCW;                    // navrati hodnotu ADC
}


uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples )   //jenom jednoduchy prumer
{
   uint32_t sum = 0;

   for (uint8_t i = 0; i < nsamples; ++i ) {
      sum += ADC_Read( channel );
      _delay_us(10);
   }

   return (uint16_t)( sum / nsamples );
}


Init ADC
Kód: Vybrať všetko
void init_adc()
{
   /* Nastaveni externi reference na pinu PB0 */
   ADMUX |=  (1 << REFS0);
   ADMUX &= ~(1 << REFS1);
   /* preruseni od ADC */
   ADCSRA |= (1 << ADIF);
   /* nastavi delicku na 128 (62,5kHz) */
   ADCSRA |= (1 << ADPS2);
   ADCSRA |= (1 << ADPS1);
   ADCSRA |= (1 << ADPS0);
   /* povoli ADC */
   ADCSRA |= (1 << ADEN);
   ADCSRA |= (1<<ADSC);   // zapne konverzi
   while (ADCSRA & (1<<ADSC) ) { }  // ceka na dokonceni konverze
   (void) ADCW;   //"vycte se ADCW"
}


Init Timer
Kód: Vybrať všetko
void init_timer()
{
   // CTC mode
   TCCR0A |= (1 << WGM01);
   //1024 prescaller
   TCCR0B |= (1 << CS00);
   TCCR0B &= ~(1 << CS01);
   TCCR0B |= (1 << CS02);
   // OCR0A interrupt only.
   TIMSK |= (1 << OCIE0A);
   //79 = 10ms; 39 = 5ms; 23 = 3ms; 8 = 1ms
   OCR0A = 39;
}


A nakonec nekonečná smyčka:
Kód: Vybrať všetko
while (1)
    {
      if (flag == 1)
      {
         adc1 = ADC_Read_Avg(1, 60);
         adc2 = ADC_Read_Avg(2, 60);
         flag = 0;
      }

      /* nastavuje vystupy, podle namereneho napeti */
      if (adc1 > (initADC1 + 2) )   //hodnota 850 prevedeno na napeti (850*3)/2^10 = 2,49V (kde 10 odpovida zmene napeti o 0,03V)
         PORTB &= ~(1 << OUT1);
      else
         PORTB |= (1 << OUT1);

      if (adc2 > (initADC2 + 2) )
         PORTB &= ~(1 << OUT2);
      else
         PORTB |= (1 << OUT2);
    }
jirka.jirka.
Obrázok používateľa
Pokročilý člen
Pokročilý člen
Príspevky: 925
Založený: 17.10.2008
Bydlisko: Zlín
Karma: 9

Re: ATtiny45 převod ADC

Odoslaťod Zahor1 » 08 Mar 2017, 22:48

Občas sa hrám s arduinom. Mal som podobný problém
RGB dióda sa mala stievať, meniť farbu podľa intenzity osvetlenia, na to tam boli 3 fotoodpory, namiesto toho aby sa stiemavali jednotlivé farby podľa hodnoty fotoodporu kdejako blikala a bola neustálená.
Vyriešil som to vyhladením (spriemerovaním) hodnôt potom to už nebol problém.
je to kód Arduina ale pointa je jednoduchá. Využil som na to základ z tohto kódu.

http://www.instructables.com/id/Arduino-EMF-Detector/
https://cdn.instructables.com/ORIG/FPD/ ... HVHG23.txt
moja verzia má 3 kanály RGB a počet načítaných hodnôt na spriemerovanie je 128 (viac nepustila pamäť arduina )

Kód: Vybrať všetko

#define sample 128

const int ledzelenypin=9;
const int ledcervenypin=11;
const int ledmodrypin=10;
const int cervenySpin=A0;
const int zelenySpin=A1;
const int modrySpin=A2;
const int ledpin=13;
int cervena=0;
int modra=0;
int zelena=0;


//spriemerovanie hodnot
float hodnotar;
float hodnotag;
float hodnotab;

int arrayr[sample];
int arrayg[sample];
int arrayb[sample];

unsigned long averagingr;
unsigned long averagingg;
unsigned long averagingb;

//autokalibrácia podla svetla
int mincervena=1023;
int maxcervena=0;
int minzelena=1023;
int maxzelena=0;
int minmodra=1023;
int maxmodra=0;
int hodnotasenzoru;
int unsigned long intervalkalib;

void setup() {
  // put your setup code here, to run once:
Serial.begin (9600);
pinMode(ledzelenypin , OUTPUT);
pinMode(ledcervenypin , OUTPUT);
pinMode(ledmodrypin , OUTPUT);
pinMode(ledpin , OUTPUT);
digitalWrite(ledpin, LOW);
//zaciatok kalibrácie
delay (1000);
blik(1);
//cervena
Serial.println("kalibracia cervena ");
intervalkalib=millis();
digitalWrite(ledpin, HIGH);
while (millis() < intervalkalib+5000) {
hodnotasenzoru = analogRead(cervenySpin) ;
if (hodnotasenzoru > maxcervena)maxcervena=hodnotasenzoru;
  if (hodnotasenzoru < mincervena)mincervena=hodnotasenzoru;
}

digitalWrite(ledpin, LOW);
delay (1000);
blik(2);

//zelena
Serial.println("kalibracia zelena ");
intervalkalib=millis();
digitalWrite(ledpin, HIGH);
while (millis() < intervalkalib+5000) {
hodnotasenzoru = analogRead(zelenySpin) ;
if (hodnotasenzoru > maxzelena)maxzelena=hodnotasenzoru;
  if (hodnotasenzoru < minzelena)minzelena=hodnotasenzoru;
}

digitalWrite(ledpin, LOW);
delay (1000);
blik(3);

//modra
Serial.println("kalibracia modra ");
intervalkalib=millis();
digitalWrite(ledpin, HIGH);
while (millis() < intervalkalib+5000) {
hodnotasenzoru = analogRead(modrySpin) ;
if (hodnotasenzoru > maxmodra)maxmodra=hodnotasenzoru;
  if (hodnotasenzoru < minmodra)minmodra=hodnotasenzoru;
}

digitalWrite(ledpin, LOW);
delay (1000);

}

void loop() {
  // put your main code here, to run repeatedly:

//nacitanie retazcov na priemerovanie
for(int i = 0; i < sample; i++){
   //cervena
   arrayr[i] = analogRead(cervenySpin);
   averagingr += arrayr[i];
 
   //zelena
   arrayg[i] = analogRead(zelenySpin);
   averagingg += arrayg[i];

   //modra
   arrayb[i] = analogRead(modrySpin);
   averagingb += arrayb[i];   
}

//spriemerovanie
//cervena
hodnotar = averagingr / sample;
hodnotar = constrain(hodnotar, mincervena, maxcervena);
cervena = map(hodnotar, mincervena, maxcervena, 0, 255);
averagingr=0;

//zelena
hodnotag = averagingg / sample;
hodnotag = constrain(hodnotag, minzelena, maxzelena);
zelena = map(hodnotag, minzelena, maxzelena, 0, 255);
averagingg=0;

//modra
hodnotab = averagingb / sample;
hodnotab = constrain(hodnotab, minmodra, maxmodra);
modra = map(hodnotab, minmodra, maxmodra, 0, 255);
averagingb=0;

//vypis na obrazovku co sa deje 
Serial.print("Data \t Cervena: ");
Serial.print(hodnotar);
Serial.print("\t Zelena: ");
Serial.print(hodnotag);
Serial.print("\t Modra: ");
Serial.println(hodnotab);

Serial.print("Hodnota RGB \t Cervena: ");
Serial.print(cervena);
Serial.print("\t Zelena: ");
Serial.print(zelena);
Serial.print("\t Modra: ");
Serial.println(modra);

//zapísanie hodnot PWM
analogWrite (ledcervenypin, cervena);
analogWrite (ledzelenypin, zelena);
analogWrite (ledmodrypin, modra);

}
void blik(int x) {
for(int j = 0; j < x; j++){
digitalWrite(ledpin, HIGH);
delay (500);
digitalWrite(ledpin, LOW);
delay (500); 
}
}


..... a skúsili ste to najskôr vypnúť a zapnúť?
Zahor1
Okoloidúci
Okoloidúci
Príspevky: 19
Vek: 42.74
Založený: 04.03.2017
Karma: 0


Naspäť na C,C++,C#

Kto je prítomný

Užívatelia prezerajúci si toto fórum: Žiadny registrovaný používateľ a 0 hostí.

cron
Forums ©
Autor stránky je Ondrej Závodský(zawin), o graficky design sa stará Ľuboš Fabo(BUFU).

TOPlist

Powered by Copyright © UNITED-NUKE CMS. All Rights Reserved.
Čas potrebný k spracovaniu stránky 0.82 sekúnd