Sari la conținut

Citire ADC o anumita durata de timp!


dan_e

Postări Recomandate

Spre exemplu, as vrea sa anulez unui PIN ADC 10bit dintr-un microcontroler pe 8bit, fie el PIC sau Atmel, o tensiune DC cu ajutorul unui switch tact (adica sa o fac 0V), dupa aia MCU-ul sa iau o decizie pe un anume PIN de iesire (ex. sa aprinda LED-urile la un anume port, o jumatate de secunda) iar daca tin apasat acel switch mai mult timp sa tina LED-urile aprinse cat tin apasat pe buton ??

Ma gandeam la ceva de genul, in mikroC for AVR (dar ceva nu iese cum trebuie!):

unsigned int adc_rd;

void main() {

DDRB = 0xFF;     // setez portul B ca iesire

  while (1) {
    adc_rd = ADC_Read(1);    // culeg voltajul pe canalul 1 ADC
    
    if(adc_rd=0)  
         {  PORTB = adc_rd; }    // aprind led-urile conectate la PORT B la la intrarea ADC este 0 volti
    else
         {  PORTB = 0x00; )    // daca nu sunt 0 volti le sting
   
    Delay_us(1000); // intarziere o secunda - nu stiu daca e bine 1 sec. !!!      
    
  }
}

 

Link spre comentariu
Distribuie pe alte site-uri

@dan_e tu ai simulat codul de mai sus ? Atat timp cat ADC-ul citeste 0V led-urile stau aprinse si mai stau aprinse inca o secunda dupa ce butonul nu mai sta apasat. Nu asta vroiai ?

Link spre comentariu
Distribuie pe alte site-uri

ADC-ul trebuie initializat si adc_rd are o valoare intre 0 si 1023, care nu este bine sa fie asignata valorii unui port.

ADC-ul are la intrare o tensiune de cativa mV, rezultata din caderile de tensiune pe conductoare si contacte, dar si ADC-ul are o contributie prin caderea de tensiune intre alimentare masa HGND si GND, in concluzie din cele 1024 de trepte, poate in mod static, sunt la asa zisul zero intre 10-50 de trepte, astfel ca un cod functional ar trebui sa tina seama de aceste aspecte.

if (adc_rd<=50)  
         {  Nu portul PORTB il faceti unu ci bitul ales al portului 0,1,...7) = 0x01; }    // aprind led-urile conectate la PORT B la la intrarea ADC este la masa prin contact
else
         {  Nu portul PORTB il faceti zero ci bitul ales al portului 0,1,...7 = 0x00; }    // daca nu sunt 0 volti le sting

delay_ms(500);    //500mS

Cred ca ar trebui incercati mai intii cateva exemple simple gate facute, ca sa vedeti cam cum se manevreaza un uC si apoi sa aplicati la exemplul dvs.

@gsabac

 

Editat de gsabac
  • Like 1
  • Thanks 1
Link spre comentariu
Distribuie pe alte site-uri

Mersi, intr-adevar, in graba si pentru ca de la inceput credeam programul simplu, uitasem un initadc

Totusi, a incercat cineva vreodata sa foloseasca un TIMER care sa cronometreze cat timp e aplicata o anumita tensiune unui pin adc si apoi sa moduleze in durata impulsurile pe o alta iesire a microcontrolerului ? Ma gandeam sa generez un PWM pe OCCA01 si daca duty cicle este 100% asta sa inseamne 5V aplicat timp de 1secunda, daca e 0,1secunde, sa fie dutycicle numai 10%. Cum as putea sa fac asta ?

Link spre comentariu
Distribuie pe alte site-uri

cat e maximum de timp can ADC e max?

cat e perioada unui ciclu led?

 

Exemplu de raspuns 

La max ADC ledul sta aprins 1 secunda.

perioada totala e 1.5 secunde (adica la ADC max ledul va sta aprins 1 secunda din 1.5 s)

 

RR

int16_t timp_led_aprins; // variabila asta contorizeaza cat sta led-ul aprins in ms (la max ADC va sta aprins 1023 ms)
int16_t timp;  // varibila asta contorizeaza un ciclu complet de led si trebuie sa fie minim 1024


while(1){
timp_led_aprins = read_adc; //valoare 0-1024  
timp = 1500; 				// ciclu total 1.5s sau 1500ms
do{							// bucla asta se va executa la fiecare ms.
	
	if (timp_led_aprins > 0) {
		led_on();
		timp_led_aprins--; //decrementeaza contor timp led
	else {
		led_off();
		}

	timp--;  				//contor pentru iesire din bucla de timp
	delay_ms(1);
}while(timp>0); 

} //

 

PS - am citit mai atent ipoteza de lucru si se pare ca intelesem eu gresit - eu am inteles ca vrei sa ai led-ul aprins pentru o perioada de timp proportionala cu valoare ADC - asta face codul de mai sus (probabil nu e ce vrei tu dar il las acolo poate ajuta pe altcineva)

- cerintele tale sunt greu de inteles eu de pilda nu inteleg exact ce inseamna

"cat timp e aplicata o anumita tensiune unui pin adc " - ???  adica nu conteaza valoarea tensiunii atat timp cat ramane constanta evaluezi numai timpul cat sta constanta? daca ramane constanta 2 zile ? care e maximum de timp?  care e viteza de evaluare 1ms, 1s care e minimum care sa consider ca e constanta? 

RR

Editat de roadrunner
  • Thanks 1
Link spre comentariu
Distribuie pe alte site-uri

Recunosc ca nu inteleg mare lucru din ipoteza.

Quote

as vrea sa anulez unui PIN ADC 10bit dintr-un microcontroler pe 8bit, fie el PIC sau Atmel, o tensiune DC cu ajutorul unui switch tact (adica sa o fac 0V)

deci aplici o tensiune pe un pin ADC si vrei s-o anulezi ? adica s-o scurtcircuitezi la masa cu un switch?

pai nu e mai simplu sa pui un switch pe alt pin si sa ignori valoare ADC cat e apasat?

RR

 

Editat de roadrunner
  • Thanks 1
Link spre comentariu
Distribuie pe alte site-uri

Reformulez ipoteza de lucru:

1. la un pin ADC aplic o tensiune DC oarecare (0...5V) constanta timp de 1 secunda maxima, sa-mi genereze apoi un semnal PWM de o frecventa data de prescaler (nu are importanta frecventa asta acum in calcul) cu un factor de umplere 100%, dupa aia daca detecteaza o intrerupere a acestei tensiuni mai mare de 0,1 secunde sa genereze un 0 logic pe iesirea PWM, ca si cum duty cicly ar deveni 0% (starea asta de duty cicle 0% sa existe atat timp cat dispare tensiunea pe intrarea ADC);

2. la acelasi pin ADC daca scurtez timpul sub 1 secunda, atunci factorul de umplere PWM sa scada proprotional, astfel incat, spre exemplu la 0,1 secunde sa devina 10%. Si acelasi caz ca mai sus, daca simte o intrerupere mai mare de 0,1secunde pe intrarea ADC (adica tensiune 0V), factorul de umpere pe iesire sa fie minim, adica 0%.

 

Link spre comentariu
Distribuie pe alte site-uri

Acum 19 ore, dan_e a spus:

1. la un pin ADC aplic o tensiune DC oarecare (0...5V) ...[] dupa aia daca detecteaza o intrerupere a acestei tensiuni mai mare de 0,1 secunde sa genereze un 0 logic pe iesirea PWM, ca si cum duty cicly ar deveni 0% (starea asta de duty cicle 0% sa existe atat timp cat dispare tensiunea pe intrarea ADC)

In ipoteza asta de lucru tensiunea "DC oarecare" nu are cum sa aiba 0...5V si sa detecteze o intrerupere a acestei tensiuni mai mare de 0,1secunde, deoarece prin intreruperea tensiunii se subintelege ca ADC-ul va vedea 0V!!

In primul rand acel interval de tensiune a trebui sa inceapa de la 0 volti si ceva si nu zero volti. Asta ar fi o problema ipotezei. Deci, ar trebui reformulata.

In ceea ce priveste dezvoltarea codului ca sa faca ceea ce doriti in ipoteza de lucru, principali pasi care ar trebui urmati ar fi:

1) definirea pinului de iesire (avand in vedere ipoteza de lucru recomand un pin la care se poate genera un semnal PWM) - mai jos un exemplu de cod in Atmel Studio:

DDRB|=(1<<DDB0); // Setez pinul PB0 ca iesire

2) initADC - initializarea convertorului analogi digital - exemplu cod Attiny45 folosit de mine in proiectul TA1000PSv1:

void adc_init()
{
    ADMUX|=(1<<REFS1)    //Referinta 1.1V,
    | (1<<ADLAR);        //Deplaseaza rezultatul la stanga (cei mai semnificativi 8 biti in ADHC)
    ADCSRA|=(1<<ADPS2)|(1<<ADPS1) //Prescaler: F_CPU/64  == 125kHz
    | (1<<ADEN);        //Activeaza ADC-ul
}
uint8_t adc_read(uint8_t ch)
{
	ADMUX &= 0xE0; //Sterge vechiul canal
	ADMUX |= ch; //Seteaza noul canal
	ADCSRA|=(1<<ADSC); //Porneste conversia
	while(!(ADCSRA&(1<<ADIF))); //Asteapta sfarsitul conversiei
	return ADCH; //Returneaza rezultatul (pe 8 biti)
}
// Si apoi in bucla void main
{
  //...
  adc_init(); //Initializeaza ADC
  // bucla program
  ( 
    //cod
    }
    }

3) initPWM - initializarea PWM in structura programului:

TCCR0A|=(1<<COM0A1)|(1<<COM0A0)|(1<<COM0B1)|(1<<COM0B0)|(1<<WGM01)|(1<<WGM00);  // Configurez Timer0: Fast PWM 8bit, Non-inverting

Apoi codul programului va trebui sa citeasca tensiunea pe pinul ADC si sa cronometreze timpul expunerii acelei tensiuni. Deci, comentariu //cod din exemplul de mai sus va trebui sa contina ceva de genul care va trebui dezvoltat (nu uitati sa declarati variabilele de lucru la inceputul programului sub forma uint8_t i;):

do
    {    
    i = 0;
        i = adc_read(1); //Citeste canalul 1 ADC - este doar un exemplu numarul canalului
     //conditie   
    OCR0A = i;

    } while(1);

 

 

  • Thanks 1
Link spre comentariu
Distribuie pe alte site-uri

Ce mi se pare mie fara rost e ca folosesti un ADC dar nu te intereseaza valoare tensiunii ci timingul cand tensiunea se schimba in 0  sau iese din zero. Ca si cand incerci sa masori factorul de umplere de la un semnal PWM extern si vrei sa-l convertesti in alt semnal PWM. - nu stiu daca asta vrei cu adevarat dar daca asta e scopul atunci nu au nevoie de ADC. - folosesti comparator (intern / extern) sau GPIO sau intrarea de captura a unui timer. 

Toate metodele enumerate mai sus pot genera intreruperi si poti sa masori timing-ul unui semnal extern cu precizie mare si relativ simplu. Daca vrei neaparat sa folosesti ADC trebuie sa faci achizitii repetate la intervale precise ca sa vezi cand tesiunea se schimba in zero sau revine din zero.

RR

PS -

Quote

la acelasi pin ADC daca scurtez timpul sub 1 secunda

Un ADC masoara o tensiune in intervalul 0-Vref ce timp scurtezi? timpul intre doua conversii (adica frecventa de masurare) -??

Editat de roadrunner
  • Thanks 1
Link spre comentariu
Distribuie pe alte site-uri

Acum 20 ore, donpetru a spus:

 


// Si apoi in bucla void main
{
  //...
  adc_init(); //Initializeaza ADC
  // bucla program
  ( 
    //cod
    }
    }

 

Partea asta de //cod as fi vrut-o detaliata!! Aveti dreptate, intervalul nu e 0...5V, ci mai bine zis un 0,5...5V, deci nu se duce in 0V.

Acum 19 ore, roadrunner a spus:

Un ADC masoara o tensiune in intervalul 0-Vref ce timp scurtezi? timpul intre doua conversii (adica frecventa de masurare) -??

Nu ati inteles, eu vreau sa fac conversia unui timp de prezenta a tensiunii la un pin ADC in durata (durata fiind un factor de umplere a unui semnal PWM).

Link spre comentariu
Distribuie pe alte site-uri

ok, deci un eveniment e creat de scimbarea tesiunii la pinul ADC. 

Primul tip de eveniment este cand tesiunea la ADC devine 0, si alt tip de event este cand din 0 devine orice mai mare ca zero? -  ca sa poti masura trebuie sa stabilim care sunt evenimentele care pornesc timp-ul si care opresc timpul (ca la un cronometru)

RR

Link spre comentariu
Distribuie pe alte site-uri

Am un releu mic care intrerupe tensiunea pe pinul ADC din cand in cand, cand nivelul de apa intr-un recipient scade sub un anume nivel, si ma gandeam sa pornesc o pompa jongland cu semnalul PWM care comanda tranzistorul care comanda pompa.

Link spre comentariu
Distribuie pe alte site-uri

Nu ai nevoie de nici un ADC ca de fapt pe tine nu te intereseza valoarea tensiunii. Am ami scris mai sus dar nu ai clarificat in nici un fel. 

Daca vrei sa faci un control PWM (proportional) la pompa ai nevoie de un semanal propotional cu nivelul, ca sa obtii un semnal de eroare cu care sa poti face o bucla de control.

Ai un semnal proportional cu nivelul? care e acela ? un senzor de nivel nu-ti da un semnal proportional.

RR

Editat de roadrunner
Link spre comentariu
Distribuie pe alte site-uri

Tocmai asta era problema, ca am doua relee, unul pe nivelul de sus si unul pe nivelul de jos, de fapt nici nu stiu daca e corect sa le spun relee !!! Mai bine zis niste limitatoare de cursa sau ceva de genul asta. Cand recipientul e plin ambele stau inchise si ma gandeam sa ma leg de treaba asta. Cand recipientul e gol sunt deschise amandoua, cand e asa si asa, doar unul din relee e inchis si ma gandeam sa ma leg de starile astea ale limitatoarelor, adica:

starea 1 = 0 0 - recipient gol

starea 2 = 1 0 - recipient 1...99%

starea 3 - 1 1 - recipient plin - ambele limitatoare inchise care daca le-as conecta la o sursa de 5Vcc ar da un asazis 1 logic, de asta am zis 1 cu 1.

Precum spuneam, ma gandeam sa ma leg de timpul cat tensiunea e aplicata convertorului ca sa generez un semnal PWM cu factor de umplere variabil dar dupa cum ati spus si voi si am stat si eu si m-am gandit, cred ca ma complic. As putea incerca ceva mai simplu care sa actioneze ON-OFF pompa, nu?

Editat de dan_e
Link spre comentariu
Distribuie pe alte site-uri

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
  • Navigare recentă   0 membri

    • Nici un utilizator înregistrat nu vede această pagină.
×
×
  • Creează nouă...

Informații Importante

Folosim cookie-uri și tehnologii asemănătoare pentru a-ți îmbunătăți experiența pe acest website, pentru a-ți oferi conținut și reclame personalizate și pentru a analiza traficul și audiența website-ului. Înainte de a continua navigarea pe www.tehnium-azi.ro te rugăm să fii de acord cu: Termeni de Utilizare.

ATENTIE !!! Functionarea Tehnium Azi depinde de afisarea de reclame.

Pentru a putea accesa in continuoare site-ul web www.tehnium-azi.ro, va rugam sa dezactivati extensia ad block din browser-ul web al vostru. Dupa ce ati dezactivat extensia ad block din browser dati clic pe butonul de mai jos.

Multumim.

Apasa acest buton dupa dezactivarea extensiei Adblock