hjælp til servo kontrol med timer (Læst 128953x)

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #255 Dato: November 22, 2011, 15:46:17 »
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

 

Offline pacman

  • Højpas filter
  • *****
  • Indlæg: 311
  • Antal brugbare Indlæg: 8
  • Jens Bauer (Forsøgs-person)
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #256 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.

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #257 Dato: November 23, 2011, 21:23:33 »
så nu er det nok gg (er der et maks for hvor mange gange man kan skrive til en avr?)
nu prøver jeg at teste det del for del.

har fået timeren til at køre på denne måde
Kode:


ISR(TIM0_OVF_vect)
{
volatile uint8_t count = 0 ;
count++;
if (count==30)
{
toggleLED1();
count=0;
TCNT0 =0;
}
}

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.

så nu vil jeg se om jeg kan finde ud af hvor i ADC det går galt for mig gg og så lige i ADC  :o gg

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

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

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

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.
« Senest Redigeret: November 24, 2011, 01:29:16 af jascore »

 

Offline pacman

  • Højpas filter
  • *****
  • Indlæg: 311
  • Antal brugbare Indlæg: 8
  • Jens Bauer (Forsøgs-person)
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #258 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. :)
« Senest Redigeret: November 25, 2011, 15:03:19 af pacman »

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #259 Dato: November 25, 2011, 14:47:15 »
Citér
-Så du har nok rigeligt med forsøg endnu.
gg du skulle bare vide


 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #260 Dato: November 25, 2011, 15:35:23 »
Citér
Jeg havde egentlig planer om at sætte en AVR op selv
Nej det skal du da ikke. lære også meget ved at prøve mig frem, så er mere end tilfreds med at du svare på mine spørgsmål og kommer med forslag. syntes selv de sidste par dage har bragt mig tættere på at forstå specielt adc delen. men har stadig ikke fundet ud af hvorfor den stopper/fryser derinde   :o
har for øvrigt også måske en design ændring der vil gøre det en del mere præcist, samtidig med at aflæsningerne af adc'er bliver lettere, da der ikke er brug for pot og dips.
jeg vil lige lufte det så jeg kan høre hvad du siger.

Jeg har modificeret en servo, så den kan køre kontinuerligt
hvis jeg så monterer en gevindstang på servoen så kan jeg jo få en møtrik til at køre frem og tilbage alt efter servoens omdrejningsretning, og der ved trække eller skubbe sprøjte stemplet.
giver det mening?
jeg mister godt nok positionsbestemmelse men får servoens fulde krafter og hastighedskontrol så det jeg mangler er egentlig bare en måde at bestemme hvor langt og hvordan.
dette kan jeg enten gøre ved kontakttryk, som kan indstilles på x antal ml og et når det er i bund. ellers kan jeg måske gøre det ved at instille pwm til at køre x antal ml i sek og så styre det på den måde.
Men den største fordel er at jeg får en linier bevægelse med langt flere krafter frem for servoarmens cirkel bevægelse

programmet er det samme stort set men når prototypen programmet er lavet kan man jo ændre det hele til at blive styrret vha 3 knapper og et visuelt feedback
1 plus knap, en minus knap og en vælg knap.

vil bare lige lufte det. har stadig tænkt mig at lave den her del færdig, for det kan godt være at det er den mest praktiske, og den anden kræver et visuelt feedback og derfor også nok en anden chip med flere ben
« Senest Redigeret: November 25, 2011, 15:40:24 af jascore »

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #261 Dato: November 25, 2011, 15:55:11 »
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

 

Offline pacman

  • Højpas filter
  • *****
  • Indlæg: 311
  • Antal brugbare Indlæg: 8
  • Jens Bauer (Forsøgs-person)
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #262 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. ;)

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #263 Dato: November 25, 2011, 17:52:22 »
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.

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?

 

Offline pacman

  • Højpas filter
  • *****
  • Indlæg: 311
  • Antal brugbare Indlæg: 8
  • Jens Bauer (Forsøgs-person)
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #264 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... ;)

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #265 Dato: November 25, 2011, 20:11:08 »
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?

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #266 Dato: November 25, 2011, 20:28:03 »
det er linjen ADCSRA |= (1 << ADSC);
der skaber problemer i initADC
kommenterer jeg den ud starter uret med at køre inittimer

 

Offline pacman

  • Højpas filter
  • *****
  • Indlæg: 311
  • Antal brugbare Indlæg: 8
  • Jens Bauer (Forsøgs-person)
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #267 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å.

 

Offline pacman

  • Højpas filter
  • *****
  • Indlæg: 311
  • Antal brugbare Indlæg: 8
  • Jens Bauer (Forsøgs-person)
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #268 Dato: November 25, 2011, 20:31:27 »
det er linjen ADCSRA |= (1 << ADSC);
der skaber problemer i initADC
kommenterer jeg den ud starter uret med at køre inittimer

Hmm, måske har vi stadig for mange ADC-interrupts per sekund. Vil lige kigge lidt på det.


 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #269 Dato: November 25, 2011, 20:40:22 »
kan man ikke lave en løsning hvor den kun aflæser adc værdierne når der trykkes på start knappen? der er jo ingen grund til at den kigger på dem når programmet er startet op, med mindre mam selvfølgelig vil ændre doseringen, men så ma man trykke på start når det er gjort. så skal ADC interruptne jo kun køres enten ved tryk på start, eller ved timer0elapsed