Vis indlæg

Denne sektion tillader dig at se alle indlæg oprettet af dette medlem. Bemærk at du kun kan se indlæg der er oprettet i områder du i øjeblikket har adgang til.


Beskeder - pacman

Sider: 1 [2] 3 4 ... 21
16
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 25, 2011, 20:30:10 »
nu har jeg jo lige et lille spørgsmål mere.
hvis jeg har forstået det rigtigt så gør et interrupt at avr stopper med det den er i gang med og udføre det der nu skal udføres i forbindelse med interruptet.
er det så ikke et problem hvis ISR(ADC_vect) fyrre 6000 interrupts af i sekundet og kigger på adc'erne så der samtidig er en ISR(TIM0_OVF_vect) der står og tæller løs på tnct0, bliver der ikke kamp om hvilket interrupt der har prioritet?

Det er egentlig rigtigt observeret.

Men 6000 interrupts i sekundet er indenfor den sikre grænse. :)

Derudover har den ene type interrupt nemlig prioritet over den anden type interrupt. Fx. INT0 har meget høj prioritet; så vidt jeg husker er der noget med rækkefølgen af interrupt-vektorerne stemmer overens med interrupt-prioriteten, så "reset" har højest prioritet (hvilket absolut giver mening).

Men husk hvad jeg nævnte tidligere, nemlig at der bliver sat et flag til interruptet.
Så du går faktisk aldrig glip af et interrupt, fordi flaget bliver først clear'et (af hardware) når dit interrupt startes.
-Der er derfor ingen grund til at være bekymret, med mindre du presser den op på over 200000 interrupts per sekund på en 1MHz frekvens. :)

Timer-interrupt 0 vil blive udført 125 gange i sekundet (når du indstiller den til TCNT0 = 256 - ((uint8_t) ((F_CPU / 64) / 125)); )
Antager vi at ADC-interruptet tager omkring 50 clock cycles, kan vi maks. udføre...
1MHz / 50 clock cycles = 20000 interrupts pr. sekund.

-Så du burde uden bøvl kunne sætte ADC'en til at køre op til 18000 interrupts per sekund, vil jeg anslå.

17
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 25, 2011, 18:17:10 »
Citér
Med hensyn til modifikation af servo kan jeg ikke vejlede dig
har modificeret den. servoen har et internt potmeter, som bruges til at bestemme pos sammen med de impulser, så det eneste der sker er at man stiller det potmeter i midterpos og disconnecter det fra den mekaniske del. Når man så sender impulser til servoen (de samme pwm som vi bruger nu) så vil servoen på grund af det disconnected pot ikke vide om possitionen er nået, og derfor blive ved med at køre. hastigheden bestemmes af hvor mange ms high er fra 1.5ms som er midterpos.

Det har du totalt styr på. Den dag hvor jeg har brug for at spørge om servo, ved jeg hvem jeg skal spørge. ;)
Citér

Citér
Tabellerne er beregnet sådan at de dækker et stykke ud over modstandenes idéelle værdier.
Oki super. det var bare fordi jeg ikke lige forstod hvordan den aflæses. Jeg går ud fra at de tal der fremkommer mellem hvert komma er de enkelte værdier som passer med en adc værdi, og tabellen retunerer dermed et tal der svare til den komma plads adc værdien svare til. men jeg forstår ikke at hvis min adc værdi nu aflæses til at være 1001 hvordan ved den så hvilken plads det er når ingen af tabel værdierne giver 1001?

Kort fortalt:
Den starter  i den ene høje af tabellen, og bliver ved med at vandre mod den lave ende, indtil den finder en værdi der er mindre end den værdi som du søger.

Hvis en modstand leverede værdien 1000, så vil der være 2 tabel-'entries' for denne værdi; fx. kunne den ene være 1300, den anden 850. Jo nærmere man kommer den lave ende, desto mere tæt ligger værdierne.

Først laves en tabel med 16 resultater med følgende formel:
i = værdi fra 1 til 16...

voltage[i] = (spænding * 1000 / i);

Dér skulle værdierne (rundet op) være...
    5000, 2500, 1667, 1250, 1000, 833, 714, 625, 556, 500, 455, 417, 385, 357, 333, 313.

Dernæst laves en tabel med ADC-resultaterne...
    adc_result[i] = 1023 * voltage[i] / 5000;
1023, 512, 341, 256, 205, 171, 146, 128, 114, 102, 93, 85, 79, 73, 68, 64.

Så laves en bundgrænse...
    adc_bottom[i] = (adc_result[i] + adc_result[i + 1]) / 2;
767, 426, 298, 230, 188, 158, 137, 121, 108, 98, 89, 82, 76, 71, 66, 32.

..og en top-grænse...
    adc_top[i] = (i > 0) ? ((adc_result[i - 1] + adc_result[i]) / 2) : 1023;
1023, 767, 426, 298, 230, 188, 158, 137, 121, 108, 98, 89, 82, 76, 71, 66.

Det er således top- og bund-grænserne du ser i tabellen.
Selvom de er beregnet til 5.0V, vil de være præcise selv hvis du kører 5.1V.
Dette er fordi ADC'ens reference-spænding er VCC, hvilket vil sige at den ikke kender forskel på VCC=5.0V og VCC=5.1V; den kender kun forskel på spænding i forhold til hvad VCC er. :)
Man kan sige at spændingen 5.0V er en midlertidig værdi for at vi mennesker bedre kan finde rundt i det, vi kunne lige så godt have valgt 1V eller 1000V... ;)

18
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 25, 2011, 16:05:43 »
har lige et spørgsmål til forståelse af tabeller
hvor fleksible er de?
hvis der f.eks i en tabel står (1024+512)/2, (512+414)/2 skal adc værdien så ramme et af disse tal, for hvad så hvis værdien er +-10 eller mere

Tabellerne er beregnet sådan at de dækker et stykke ud over modstandenes idéelle værdier.

Dette vil sige, at jeg har taget forbehold for at modstands-netværket ikke giver en præcis værdi, og så har jeg gået så langt til hver side, som muligt.
Værdierne skulle være sikre hvis du bruger modstande med 1% tolerance, hvilket også skulle være til at få fat i. :)

Den tabel du har fået, er beregnet, hvilket vil sige, at den ikke er baseret på målinger, som mine første tabeller var, så den er nok så korrekt som den kan blive.

Med andre ord: Tabellen er forberedt på at modstands-værdierne ikke er helt præcise. =)

Med hensyn til modifikation af servo kan jeg ikke vejlede dig, da jeg ikke kender så meget til servoer. Jeg har ikke selv prøve at bruge dem endnu, men det kan være det kommer en dag. ;)

19
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 25, 2011, 14:40:56 »
så nu er det nok gg (er der et maks for hvor mange gange man kan skrive til en avr?)

Ja, 10000 gange.. :)
-Så du har nok rigeligt med forsøg endnu.
Personligt har jeg ikke prøvet at skrive så mange gange at jeg har brugt en AVR op.

Citér
nu prøver jeg at teste det del for del.

god idé.

Citér
har fået timeren til at køre på denne måde
{snip}

Jeg havde egentlig planer om at sætte en AVR op selv, men har i øjeblikket vældig meget der presser fra alle sider, så jeg ved ikke om jeg kan få overskud / tid lige nu.

Citér
Samtidig har jeg kommenteret initADC(8); ud i main
count er sat til 30 for (f_cpu/64=15622)/256 = 61 hvis tnct0 tæller op til 256 så må count tælle op til 61 på 1 sek, så jeg togler hvert ½ sek.

Hmm, jeg tror jeg blev forvirret tidligere.

Prøv følgende:
Kode:
ISR(TIM0_OVF_vect)
{
    volatile uint8_t count = 0;
    if(0 == count--)
    {
        TCNT0 = 256 - ((uint8_t) ((F_CPU / 64) / 125));
        count = 125 - 1;
        sSeconds++;
        toggleLED1(); 
    }
}

Det er fordi...

F_CPU er 1000000.
F_CPU / 64 = 15625.
15625 / 125 = 125.
TCNT0 skal sættes til 256 - 125 = 131, fordi TCNT så tæller op fra 131 til 256.
Dette skal den gøre 125 gange for at ramme 1 sekund (derfor skal count resettes når den rammer 125).

Citér
Har lige et spørgsmål til en linje i adc
   ADCSRA = (1 << ADEN) | (1 << ADIF) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
så vidt jeg kan læse bør adc ligge mellem 50 og 200 Khz er jeg så ikke nød til at køre med en prescaler på  8-16 altså ADPS2, ADPS1, ADPS0 = 100 eller 011 ? lige nu er den 128, altså helt nede på 7,8 khz. men jeg er absålut ikke sikker. ADC'en er somsagt den jeg har flest problemer med at tyde

Ja, side 135 - det tror jeg du har ret i, ups. :)

Du kan roligt sætte den ned. ;)

Citér

et andet spørgsmål.
Hvis vi køre 8 bit opløsning på adv skal det så ikke være left aligned?
ADCSRB = (0 << ADTS2) | (0 << ADTS1) | (0 << ADTS0) | (0 << ADLAR); her er den right
og i
ISR(ADC_vect)
if(ADCSRB & (1 << ADLAR)) er den left

IF-sætningen kigger om den er left-aligned. Hvis ikke, så går den til else, hvor den håndterer at den er right-aligned. (Det er ihvertfald idéen, om den så gør hvad den får besked på...)

Vi vil nok helst have den right-aligned; det er nemmere i vores tilfælde.

Citér
Jeg er på meget usikker grund for jeg prøver bare at læse alle mulige tutorials og de er både fra atmega men mest fra tiny13

Du er nu ved at blive vældig skrap til AVR. =)

Citér
Så fandt jeg en lille ting som jeg er helt sikker på --- næsten  :o
i adc skal vi ikke bruge eller læse adc3value da den er sat op som ISR(PCINT0_vect) i main.c så retter #define ADC_FIRST og LAST til 1 og 2
samtidig fjerner jeg uint16_t getADC3Value() funktionen.

Jo, hvis det er en switch (startknap) der er koblet på PA3, så vil det være mest praktisk at læse den digitalt. :)

20
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 22, 2011, 16:10:02 »
kan man ikke risikere at man køge en cli mere end sei eller?
jeg tænker bare at hvis man f.eks køre en sei i main og så kører alle interrupts derud af men i setMinuteCountdown(uint16_t aMinuteCountdown) kører man så en cli uden en sei. har den så ikke stoppet interrupts og setMinuteCountdown bliver kaldt fra startDosing() som igen kaldes hver gang startknappen trykkes ned eller når tiden løber ud og timer0Elapsed kaldes

setMinuteCountdown skylder jeg en forklaring på...

Først: I setMinuteCountdown skulle der gerne være én cli og én sei. :)
Her er formålet at sikre at vi ikke får læst halvdelen af sMinuteCountdown eller halvdelen af sMinuteCoundownRestart, imens vi skriver værdierne.
Dette kan nemlig ske, fordi vores microcontroller er 8-bit, og kun læser/skriver én byte ad gangen, og på et hvilket som helst tidspunkt i programmet kan der ske et interrupt.

Dernæst, skal du have en lidt mere uddybende forklaring af hvordan timer og interrupt egentlig fungerer.

1: En timer sættes op til at køre en bestemt hastighed.
2: Hver timer kan give os nogle oplysninger, fx...
  A: Når timeren's tæller får 'overløb', dvs. når TCNT0 skifter fra 255 til 0 ved at den tæller én op.
    Når dette sker, sættes TOV0 bitten i TIFR0.
  B: Når timerens tæller rammer OCR0A (hvis vi altså har koblet COM0A0 og COM0A1 til), vil OCF0A bitten blive sat i TIFR0.
  C: Når timerens tæller rammer OCR0B (hvis vi altså har koblet COM0B0 og COM0B1 til), vil OCF0B bitten blive sat i TIFR0.
3: Hvis vi har koblet et fx. overflow interrupt på, ved at sætte TOIE0 bitten i TIMSK0, vil der ske et interrupt når TIFR0's TOV0 bit bliver sat.
4: Samme med OCIE0A og OCIE0B bittene i TIMSK0, de kobler Output Compare Interrupt's til, når de er 'sat', og disse interrupts kigger henholdsvis på OCF0A og OCF0B (Output Compare Flag 0 A / B).

På den måde har man mulighed for at kun have en timer kørende og ikke få interruptet til at udføre noget, selvom timeren kører. En timer kan også lave PWM uden at have et interrupt koblet på.
Man kan også manuelt få et interrupt til at blive kørt, ved at sætte en bit der hedder FOC0A/FOC0B (Force Output Compare 0 A/B)..

Hvis nu vi så antager at vi slukker for alle interrupts, så kører timerne videre, og de sætter flag som de plejer at gøre.
Tænder vi så for interrupts nogen tid efter, så vil disse interrupts straks blive udført, fordi flagene er allerede sat, og derfor går vi ikke glip af kørslerne, med mindre vi fx. er flere sekunder om at tænde for interrupts igen.

21
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 22, 2011, 15:41:26 »
Citér
Prøv at lave denne smule test-kode...
den er en lille smule langsomere end et sek. men et delay på 250ms er det ikke 250 ms ligemeget om den køre 8 mhz eller 1 mhz

Næh, ikke på en microcontroller, for det måles nemlig i forhold til clock-frekvensen.
Og hvis microcontrolleren står på 8MHz, og F_CPU's værdi er defineret til 1000000, så vil den blinke 8 gange i sekundet i stedet for 1 gang.

Citér

hvor skal jeg skrive det der med make fuse henne ?  ;D
taber ca 4 sek på et minut

Den er sådan set iorden, så du behøver ikke make fuse. Hvis du bruger WinAVR, kan du prøve at skrive det nede i bunden af vinduet, dér, hvor du har log og fejl-meddelelser, men jeg ved ikke om det vil fungere. -Jeg bruger jo selv et lidt anderledes system.

-Nu har vi konstateret at den kører 1MHz, som vi gerne vil have den til.
Hvorfor den så opfører sig så fjollet at køre interruptet alt for hurtigt, må vi lige finde ud af.

Jeg har prøvet at gå opsætningen igennem endnu en gang (og prøvet at skrive en ny opsætning, for at se hvordan jeg ville gøre det i dag), jeg fik samme resultat af opsætning, så jeg er ved at tro at der kan være noget andet, som påvirker interruptets tids-indstilling.

Jeg er nok nødt til lige at bruge lidt mere tid på det, inden jeg sender et kvalificeret svar. ;)

22
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 22, 2011, 12:38:29 »
når jeg køre avrdude skriver den avrdude: safemode: Fuses OK. og det er når der er compilet med den makefile hvor fuses sat til H:0xdf og L:0x62

Jeg husker ikke om den altid gør dette, eller om den kun gør det ved skrivning.

Hvis du har mulighed for at skrive følgende...

make fuse

Vil det indstille fuses som de er i Makefile. Denne kommando køres nemlig ikke normalt ved almindelig flashing.

Citér

Citér
Kan du se om lysdioden blinker (hurtigt) nu ?
Ja, når TCNT0 = 0 så blinker den hurtigt.

Har også prøvet den interne _delay_ms(10); sammen med en toggleLED
hvis TCNT0 = 255 og _delay_ms(1000) så er den ca tændt 1 sek og derfter slukket 1 sek så det er jo rigtigt nok men 1000 ms er jo 1 sek ligemeget om den køre 1 Mhz eller 8Mhz så det kan jo ikke bruges til så meget
[/quote]


Prøv at lave denne smule test-kode...

Kode:
while(1)
{
    _delay_ms(250);
    _delay_ms(250);
    toggleLED1();
}

Hvis microcontrolleren kører 1MHz, vil ovenstående LED blive tændt med 1 sekunds mellemrum, dvs. fra tænd-til-tænd vil være 1 sekund.

Derimod, hvis den blinker ca. 8 gange så hurtigt, kører microcontrolleren 8MHz.

23
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 22, 2011, 08:16:26 »
hvis jeg så sætter TCNT0 = 255; så flasher ledden faktisk helt nede i if(sSeconds >= 60)   funktionen
men det går meget stærkt og lige under sSeconds++; lyser den konstant, så det må køre sindsygt hurtigt systemet.
hvilket også bliver bekræftet ved at ledden blinker langsomere hvis jeg sætter if(sSeconds >= 255)

Du har lige fundet ud af noget vigtigt. :)

Prøv at sætte TCNT0 til 0, og hav en toggleLED lige efter.
Kan du se om lysdioden blinker (hurtigt) nu ?


Hmm, vent nu lige lidt... Har du på noget tidspunkt ændret chippens fuse-bits ?

24
Generel Elektronik / Sv: Afstandsmåler med SMS funktion
« Dato: November 21, 2011, 21:56:00 »
Hmm, hvordan tænker du at afstanden skal måles ?
Også ret vigtigt... Hvad skal der måles afstand til ?

Er det en afstand mellem to elektronik-dimser, eller er det en afstand fra en elektronik-dims til fx. en væg ?

25
Køb og Salg / Sv: Søger IRL1404ZPBF Mosfet, eller lin
« Dato: November 21, 2011, 21:53:36 »
Jeg ved det er længe siden, men jeg så først din tråd nu, da jeg gik ulæste tråde igennem.

Hvis du ikke allerede har fundet nogle, kan det være at DigiKey eller Elektronik-Lavpris kan hjælpe...
Prøv at se hos Elektronik-Lavpris, om der er noget af det du kan bruge.

26
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 21, 2011, 20:18:02 »
har prøvet at lade den stå i flere minutter og den togler ikke igen.
tiden der går før den togler når jeg har slukket den ved at trykke på start er random men ændre jeg på dip indstillingen så ændres det interval til noget meeeget længere

Hmm, det kan selvfølgelig være den blinker meget hurtigt. Prøv at sætte toggleLED ind lige før sSeconds = 0;

27
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 21, 2011, 19:22:08 »
ok fjernede startdosing efter sei, i main.
smed en setLES ind i startknapfunktionen så jeg er sikker på den slukker når jeg trykker.
der efter er der en toggleLED lige efter sSecond++

den slukker når jeg trykker på strtknap og tænder x antal sek efter igen. men så forbliver den tændt

Har du prøvet at vente på den i mere end 1 minut, for at se om den blinker med lange mellemrum ?
-Det kan nemlig godt være at Timer0 interruptet kører en forkert hastighed.

28
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 21, 2011, 19:00:07 »
Du er genial.
Nu sker der da noget.
hvis jeg smider toggleLED1(); ind lige efter sSeconds++;
så slukker led når jeg trykker på start. og så sker det fantastiske at led tænder igen efter x antal sek. nogle gange. andre gange bliver led lidt skarpere lige når der trykkes  :P

men forsinkelsen er altid mellem 10 og 26 sek og startknappen kan derefter aktiveres igen og enten gøre led skarpere eller slukke den i x sek. for det meste omkring 15 sek

Prøv at have toggleLED1(); inde lige efter sSeconds++, og vent, se hvor lang tid der går mellem hver gang den går fra tændt til slukket eller slukket til tændt.
Der skulle helst gå 1 sekund, dvs. 2 sekunder mellem hver 'tænd'.

29
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 21, 2011, 18:41:07 »
Æh, det var en and! :o

Der er intet galt dér alligevel.
Fordi...
Hvis adcCounter er mindre end 8, bliver der lagt én til, dvs. er den 7, bliver der lagt én til, og den bliver 8.

While... Så længe værdien er under 8, bliver den i while-løkken, og låser, men kun så længe værdien er mindre end 8. Den bliver nøjagtig 8, og derfor kommer den ud af while-løkken. (I teorien ihverfald).

HAH. Det er noget helt andet, der er galt. :)

Et interrupt bliver ikke afbrudt af et andet interrupt.

Så hvis vi er inde i et interrupt, fx. start-knap interruptet, så kan dette ikke afbrydes, fordi når man kommer ind i et interrupt, bliver interrupts slået fra globalt, dvs. bit 7 i SREG bliver sat til 0.
(Dette er fordi man vil undgå at et interrupt afbryder sig selv, hvis det er for lang tid om at udføre sin kode). Når interruptet så er færdigt, bliver interrupts så slået til igen.

Her er et forslag til løsning af problemet. (Nogle programmører vil have ganske gode argumenter mod at gøre det, men.. jeg gør det alligevel).

Hvad vi gør, er at vi slår interrupts til, før vi begynder at vente.
Men lige inden dette, så gemmer vi det gamle status-register (SREG), og når vi er færdige med at vente, sætter vi SREG til den gamle værdi, hvilket vil betyde at hvis interrupts var slået fra, bliver de slået fra igen, ellers bliver de ved med at være slået til.

Kode:
void waitSeconds(uint8_t aSeconds)
{
uint8_t oldSREG;

aSeconds = (aSeconds + sSeconds); /* add current second value to aSeconds */
if(aSeconds >= 60) /* we can't wait more than 59 seconds, so if the result is larger than 59... */
{
aSeconds -= 60; /* ...then subtract 60 */
}
oldSREG = SREG; /* save global interrupt flag */
sei(); /* enable interrupts */
while(aSeconds != sSeconds) /* wait until sSeconds has the same value as aSeconds */
{
}
SREG = oldSREG; /* restore global interrupt flag */
}

Kode:
void waitUntilADCStable()
{
uint8_t oldSREG;

oldSREG = SREG; /* save global interrupt flag */
sei(); /* enable interrupts */
while(adcCounter < ADC_STABLE) /* keep waiting, until ADC is reliable */
{
}
SREG = oldSREG; /* restore global interrupt flag */
}

(4 nye linier i hver rutine)

30
Generel Elektronik / Sv: hjælp til servo kontrol med timer
« Dato: November 21, 2011, 17:49:45 »
den lyser hele tiden når jeg prøver det du har skrevet. har også prøvet at lave
kan ikke se forskel på om den er svag eller skarp. men
hvis jeg sætter led til at være slukket i toppen og undlader at tænde den i bunden, forbliver den slukket. hvis jeg slukker den i starten af interrupt tænder den i bunden forbilver den tændt

Dette er en rigtig god nyhed.
Altså vil det sige at interruptet kører. :)

Citér
if (adcCounter ==#)
{
setLED1(0);
}
hvor # er 1-8 og den slukker som den skal og stopper ved 9 med at slukke

Også en ganske god nyhed, for den skal jo tælle op så længe adcCounter er mindre end 8.

Og så er der fundet en fejl til... Mere herom senere. ;)

Citér

sorry. jo den bliver svag, så interrupt må køre
trykker jeg så på startknappen, slukker den helt

Fint.

Prøv at nærlæs denne kode...
Kode:
    if(adcCounter < ADC_STABLE)
    {
        adcCounter++;
    }

Derefter prøv at nærlæs denne kode...
Kode:
    while(adcCounter < ADC_STABLE)
    {
    }

Ser rigtig godt ud, ikke, men der er faktisk en fejl. Lad os lige gøre det mere klart for os hvad der sker:
Så koden således ud...
Kode:
    if(adcCounter < 8)
    {
        adcCounter++;
    }

Hvad ville den maksimale værdi af adcCounter så være ?

... og ...

Kode:
    while(adcCounter < 8)
    {
    }

Hvad sker her ? :)

(Hvor mange kvajekager er jeg oppe på nu?) ;D

Sider: 1 [2] 3 4 ... 21