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

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 #210 Dato: November 18, 2011, 18:56:47 »
Citér
Timer0.c:39: warning: 'SIG_OVERFLOW0' appears to be a misspelled signal handler
Prøv i Timer0.c at ændre... {snip}
Har ikke en SIGNAL (SIG_INT0), men en SIGNAL (SIG_OVERFLOW0) /*This interrupt occurs when TCNT0 wraps to 0*/
hvis jeg ændre den til ISR(INT0_vect) får jeg stadig samme fejl.

Alle gode gange to-og-en-halv...

-Jeg forvirrede mig selv med at jeg på et tidspunkt havde brugt INT0 til start-knap. :D

Prøv TIM0_OVF_vect - den er måske bedre... ;)
Citér

De andre fejl er rettet og fungerer fint.
lavede en void waitSeconds(uint8_t aSeconds); i timer0.h
waitSeconds er jo en del at timerfunktionen der holder øje med døgnet så syntes ikke den skulle fjernes fra timer0.c hvor den bruges.
og fejlen forsvandt da jeg lavede linjen i timer0.h

Dette er det korrekte sted. :)

Du kan se en oversigt over interrupt-vektorer og navne på AVR-GCC's side.

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #211 Dato: November 18, 2011, 19:15:19 »
det var jeg også kommet frem til i min post på tidligere side he he men tak for svaret på mit spørgsmål  :P

Min strømforsyning er 5v 2 amp så den klarer nok jobbet
« Senest Redigeret: November 18, 2011, 19:44:59 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 #212 Dato: November 18, 2011, 23:30:01 »
kan jeg gøre flg.
lave en led.c med flg
Kode:
void setLED1(uint8_t aState)
{
    PORTA = aState ? (PORTA & ~(1 << PA7)) : (PORTA | (1 << PA7));
}
void setLED2(uint8_t aState)
{
    PORTA = aState ? (PORTA & ~(1 << PA6)) : (PORTA | (1 << PA6));
}
void setLED3(uint8_t aState)
{
    PORTA = aState ? (PORTA & ~(1 << PA5)) : (PORTA | (1 << PA5));
}
void setLED4(uint8_t aState)
{
    PORTA = aState ? (PORTA & ~(1 << PA4)) : (PORTA | (1 << PA4));
}

og en led.h med
prototypes på de 4 setLED1(uint8_t aState)

Så laver jeg en #include "led.h" i alle *.c
alt det lader jeg bare være en fast del af programmet, så det er der når og hvis der skal udvides

for at teste kan jeg så ikke bare redigerer i den *.c hvor der er noget jeg vil teste, og tilføje
Kode:
uin16_t val = det_der_skal_testes();
void toggleled()
{
uint16_t val = getADC2Value();
if(val >= 1)
{
setLED1(1);  /* turn LED1 on */
val = val - 1;
}
else
{
setLED1(0);  /* turn LED1 off */
}
if(val >= 2)
{
setLED2(1);  /* turn LED2 on */
val = val - 2;
}
else
{
setLED2(0);  /* turn LED2 off */
}
if(val >= 3)
{
setLED3(1);  /* turn LED3 on */
val = val - 3;
}
else
{
setLED3(0);  /* turn LED3 off */
}
if(val >= 4)
{
setLED4(1);  /* turn LED4 on */
val = val - 4;
}
else
{
setLED4(0);  /* turn LED4 off */
}
}

jeg har svært ved at se hvordan keg kan compile og teste 1 modul ad gangen da de alle er vævet sammen og er afhængige af værdier fra andre end sig selv

Når jeg gør det på den måde, ser det ud til at selve start knap funktionen ikke virker.
jeg kan tænde og slukke led 1 på pa7 ved at skrive setLED1(1); eller setLED1(0); i starten af main.c (som det sidste i init main) men hvis jeg skriver setLED1(1); nede i ISR(PCINT0_vect) funktionen så sker der intet når jeg trykker på start knappen. er dog ikke helt sikker på at min led rutiner er globale

Min main.c ser således ud
Kode:
#include <avr/io.h>
#include <avr/interrupt.h>
#include "main.h"
#include <util/delay.h>
#include "Servo.h"
#include "ADC.h"
#include "Timer0.h"
#include "Dosing.h"
#include "leds.h"
int main()
{
    GPIOR2 = SERVO_ENABLED; /* This must be the first code executed; no code goes before it, and GPIOR2 is not to be changed from now */
initADC(8); /* initialize ADC, we'll use the 8-bit precision for now */
    initTimer0();
    initDosing();
    initServo();
sei(); /* globally enable interrupts */
    PCMSK0 |= (1<<PCINT3); /*Set PA3 as the pin to use*/
MCUCR = (1 << ISC01) | (0 << ISC00); /* interrupt on INT0 pin, falling edge */
GIMSK  |= (1<<PCINT3);
setLED1(1);
while(1)
{
/* we don't really need to do anything here. Everything is handled by the interrupts */
}
    return(0); /* (never reached) */
}
ISR(PCINT0_vect)
{
    uint8_t pinValue;
    pinValue = PINA & (1 << PINA3);                             /* read value of input-pin */
    if(pinValue) /* we're only interested if button is pressed */
    {
        _delay_ms(10.);                                          /* wait 10 ms */
        pinValue = PINA & (1 << PINA3);                         /* read value of input-pin */
        if(pinValue) /* only update settings when button value is stable */
        {
setLED1(0);  /* turn LED1 off */
            startDosing();   
        }
    }
}
« Senest Redigeret: November 19, 2011, 01:16:13 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 #213 Dato: November 19, 2011, 06:33:22 »
kan jeg gøre flg.
lave en led.c med flg
{snip}
og en led.h med prototypes på de 4 setLED1(uint8_t aState)
Så laver jeg en #include "led.h" i alle *.c

Ser fint ud.

Det kunne være godt med...
Kode:
void initLED()
{
    DDRA |= (1 << DDA4) | (1 << DDA5) | (1 << DDA6) | (1 << DDA7);
}

og så kalde denne fra main(), fx. lige efter GPIOR2 = ...;


Citér
for at teste kan jeg så ikke bare redigerer i den *.c hvor der er noget jeg vil teste, og tilføje
{snip}

God idé. :)

Mit forslag til ovennævnte rutine er...

1: undgå at bruge globale variabler, men i stedet giv parametre (argumenter) til rutinen.
2: en smart lille forkortelse:
Kode:
void setLEDs(uint8_t aValue)
{
    PORTA = (PORTA & ~(1 << PA4) | (1 << PA5) | (1 << PA6) | (1 << PA7)) | (aValue << PA4);
}


PA4 har så værdi 1, PA5 har værdi 2, PA6 har værdi 4, PA7 har værdi 8.
Når de lyser, lægger du værdierne for dem sammen, fx. vil...
setLEDs(11);
få PA4 + PA5 + PA7 til at lyse, hvilket giver...
1 + 2 + 8 = 11...
[/quote]

jeg har svært ved at se hvordan keg kan compile og teste 1 modul ad gangen da de alle er vævet sammen og er afhængige af værdier fra andre end sig selv
[/quote]

Forståeligt nok. =)

Hvis jeg selv har rodet mig ud i store problemer, laver jeg et nyt selvstændigt program, og i dette selvstændige program laver jeg den del jeg vil teste.

Fx. til at starte med, ville jeg tage et selvstændigt modul (noget der ikke har andet vævet ind i sig), nemlig ADC'en.
ADC.h og ADC.c er selvstændigt bygget op (det er med vilje at heg har presset dig til at holde det hele modulært opbygget).

ADC.c og ADC.h kan indbygges i et andet program, og når de er testet og virker, så kan man gå videre til næste modul, fx. Timer0.c og Timer0.h.

Citér
Når jeg gør det på den måde, ser det ud til at selve start knap funktionen ikke virker.
jeg kan tænde og slukke led 1 på pa7 ved at skrive setLED1(1); eller setLED1(0); i starten af main.c (som det sidste i init main) men hvis jeg skriver setLED1(1); nede i ISR(PCINT0_vect) funktionen så sker der intet når jeg trykker på start knappen. er dog ikke helt sikker på at min led rutiner er globale

Min main.c ser således ud
Kode:
/* {snip} */
int main()
{
    GPIOR2 = SERVO_ENABLED; /* This must be the first code executed; no code goes before it, and GPIOR2 is not to be changed from now */
initADC(8); /* initialize ADC, we'll use the 8-bit precision for now */
    initTimer0();
    initDosing();
    initServo();
sei(); /* globally enable interrupts */
    PCMSK0 |= (1<<PCINT3); /*Set PA3 as the pin to use*/
MCUCR = (1 << ISC01) | (0 << ISC00); /* interrupt on INT0 pin, falling edge */
GIMSK  |= (1<<PCINT3);
setLED1(1);
while(1)
{
/* we don't really need to do anything here. Everything is handled by the interrupts */
}
    return(0); /* (never reached) */
}
ISR(PCINT0_vect)
{
    uint8_t pinValue;
    pinValue = PINA & (1 << PINA3);                             /* read value of input-pin */
    if(pinValue) /* we're only interested if button is pressed */
    {
        _delay_ms(10.);                                          /* wait 10 ms */
        pinValue = PINA & (1 << PINA3);                         /* read value of input-pin */
        if(pinValue) /* only update settings when button value is stable */
        {
setLED1(0);  /* turn LED1 off */
            startDosing();   
        }
    }
}

Ikke at det er noget der får programmet til ikke at virke, men jeg vil anbefale at rokere lidt om, plus at ændre linien MCUCR = ...:

Kode:
    	PCMSK0 |= (1<<PCINT3);								/*Set PA3 as the pin to use*/
MCUCR = MCUCR & ~((1 << ISC01) | (1 << ISC00)) | (1 << ISC01) | (0 << ISC00); /* interrupt on INT0 pin, falling edge */
GIMSK  |= (1<<PCINT3);
sei(); /* globally enable interrupts */

linien som skriver i MCUCR ændrer nu ikke ved de andre bits i dette register (de var 0 i forvejen, men hvis du en dag kigger tilbage på koden, trækker du ikke en ting med over i et nyt progam, som kan give dig bøvl).
sei(); er sat sidst, fordi PCINT0 er et interrupt, og vi vil gerne 'have ro' mens vi sætter interrupts op.

Når så det er gjort, skal du vide at....
MCUCR registret har intet med Pin Change interrupt at gøre.
Den har kun med INT0, altså Pin B2 at gøre, så fjern den linie fuldstændig. :)

Derudover...
Kode:
	GIMSK  |= (1<<PCINT3);
[code]

Se side 50 i databladet. :)
Derefter se side 52.

(Den slags har jeg selv haft meget bøvl med, [fnis])

Prøv så følgende...

I main's while(1):
[code]while(1)
{
    setLED0(0);
    setLED1(0);
    setLED2(0);
    setLED3(0);
}

...i PCINT0:
Kode:

ISR(PCINT0_vect)
{
    uint8_t pinValue;
    pinValue = PINA & (1 << PINA3);                             /* read value of input-pin */
    setLED0(1);
    if(pinValue) /* we're only interested if button is pressed */
    {
        setLED1(1);
        _delay_ms(10.);                                          /* wait 10 ms */
        pinValue = PINA & (1 << PINA3);                         /* read value of input-pin */
        if(pinValue) /* only update settings when button value is stable */
        {
            setLED2(1);
            startDosing();   
        }
    }
}

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #214 Dato: November 19, 2011, 15:45:58 »
 :D
Citér
   GIMSK  |= (1<<PCINT3);
Se side 50 i databladet. :)
Derefter se side 52.

(Den slags har jeg selv haft meget bøvl med, [fnis])

skal GIMSK hedde
GIMSK  |= (1<<PCINT0);
og er ikke helt sikker på om SREG er noget jeg skal sætte op?
« Senest Redigeret: November 19, 2011, 15:54:36 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 #215 Dato: November 19, 2011, 15:51:15 »
skal GIMSK hedde
GIMSK  |= (1<<PCINT0);

Nej. :)

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #216 Dato: November 19, 2011, 16:41:51 »
gg så prøver jeg lige den her istedet
GIMSK  |= (1<<PCIE0);

Hvis GIMSK kun har 3 muligheder int0 PCIE1 og PCIE0 hvorfor melder compiler så ikke fejl når jeg skriver andet.

WEEEEEEEE der sker noget. men den mangler at registrerer led 3. men den tænder godt nok led 4 i startDosing();   (dog ikke altid. men 90% af gangene) og altid 2. gang hvis ikke første

pinValue = PINA & (1 << PINA3);
if(pinValue)
          {
      setLED3(1);
      setLED2(0);                              /* turn LED1 off */
                startDosing();   
          }
« Senest Redigeret: November 19, 2011, 17:13:25 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 #217 Dato: November 19, 2011, 17:47:55 »
gg så prøver jeg lige den her istedet
GIMSK  |= (1<<PCIE0);

Meget bedre. :)

Citér
Hvis GIMSK kun har 3 muligheder int0 PCIE1 og PCIE0 hvorfor melder compiler så ikke fejl når jeg skriver andet.

Dette skyldes at PCIE1 og PCIE1 kun er talværdier.
Du kunne i teorien også skrive...

GIMSK = 172;

Men det er noget mere forståeligt at bruge de macroer / definitioner, som tilhører GIMSK ifølge databladet.


Citér
WEEEEEEEE der sker noget. men den mangler at registrerer led 3. men den tænder godt nok led 4 i startDosing();   (dog ikke altid. men 90% af gangene) og altid 2. gang hvis ikke første

Lyder godt. Fejlene må vi lige kigge på, den er nødt til at gøre det samme hver gang, så man kan stole på den. ;)

Hvis nu din programmerings-enhed er koblet på, samtidig med at du tester, kan den være årsag til at den ene LED ikke tændes.
Prøv at koble programmerings-enheden fra, for lige at afprøve teorien. ;)

Citér

pinValue = PINA & (1 << PINA3);
if(pinValue)
          {
      setLED3(1);
      setLED2(0);                              /* turn LED1 off */
                startDosing();   
          }

Det kan være det er tid til at du sender mig en opdatering af hvordan filerne ser ud nu.
Det er bedst, hvis du højre-klikker på mappen og vælger at komprimere den til et zip-arkiv.
-På den måde får du også en backup af hvordan det hele ser ud på nuværende tidspunkt, hvis nu der skulle gå ged i et eller andet. :)


 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #218 Dato: November 19, 2011, 17:52:20 »
Det vil jeg gøre. tusind tak.

lige et spørgsmål mens jeg pakker og sender.
er der en hurtig måde man kan toggle et led så den tænder og slukker hver gang sekund skifter ? noget bit shift eller noget
« Senest Redigeret: November 19, 2011, 19:24:29 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 #219 Dato: November 19, 2011, 19:47:18 »
lige et spørgsmål mens jeg pakker og sender.

Du skulle på nuværende tidspunkt have modtaget en mindre modifikation af koden - ikke noget afsindig vigtig, men bare 'housekeeping', og så en rettelse af Makefile, som havde en fejl i 'clean' funktionen.

Citér
er der en hurtig måde man kan toggle et led så den tænder og slukker hver gang sekund skifter ? noget bit shift eller noget

AVR har sådan en smart feature (som jeg mener at PIC også har, for den sags skyld), at skriver man til INPUT porten, vil alle de bits, man skrive, blive togglet til det modsatte.

Så du kan...
Kode:
    PINA |= (1 << PA4);  /* toggle LED on/off */

(PINA - også kaldet PORTINA - er dér, hvor du læser værdier, mens PORTA er dér, hvor du normalt skriver værdier)

Den stump kode kan du prøve at sætte ind i ISR(TIM0_OVF_vect), lige efter sSeconds++;

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #220 Dato: November 19, 2011, 20:13:42 »
tusind tusind tak  :P

 

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 #221 Dato: November 19, 2011, 20:17:17 »
tusind tusind tak  :P

Bare hyggelig (dette er den norske måde at sige velbekomme)

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #222 Dato: November 19, 2011, 20:26:08 »
 :)
men den toggler desværre ikke hvert sek. den lyser bare konstant det betyder vel at timeren ikke kører som den skal  :o

 

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 #223 Dato: November 19, 2011, 23:06:03 »
:)
men den toggler desværre ikke hvert sek. den lyser bare konstant det betyder vel at timeren ikke kører som den skal  :o

Hmm, det kan være den bare er vældig langsom.
Prøv at vente 8-10 sekunder, og se så om den slukker...

Ihvertfald har jeg lige fundet en lille fejl:

Prøv at åbne Timer0.c...
I ISR(TIM0_OVF_vect) står noget med F_CPU / 64, dvs, her regner vi med at vi bruger prescaler clk/64!
Går vi ned i initTimer0, og kigger på TCCR0B = ..., ser vi at CS02, CS01 og CS00 er sat til 010, dvs. prescaler = clk / 8.
Derfor skal vi lige have rettet (0 << CS00) til (1 << CS00), og kommentaren 2 linier ovenover skal hedde PRESCALER64 istedet for PRESCALER8.

Dette burde få timeren til at køre i korrekt hastighed.

 

Offline jascore

  • Jordet Basic
  • **
  • Indlæg: 157
  • Antal brugbare Indlæg: 0
    • Vis profil
Sv: hjælp til servo kontrol med timer
« Svar #224 Dato: November 19, 2011, 23:12:25 »
super. fantastisk.
prøver det fluks


Man skulle næsten tro at min avr er brændt af eller noget. når jeg sætter prescaler til det som du sagde, så lyser alle leds hvad enten jeg sætter dem til off eller ej ?!?!  :-[
« Senest Redigeret: November 19, 2011, 23:57:25 af jascore »