[Lego RCX] brick, Erika -> probleem uitlezen 2e sensor

Pagina: 1
Acties:

  • robbertb
  • Registratie: September 2000
  • Niet online
Ik weet niet of dit het juiste forum is, en of er hier mensen werken met Erika om de sensoren uit te lezen, maar ik probeer het toch omdat ik er niet uitkom.
De opdracht is om een doolhof op te lossen met een lego voertuigje. Het doolhoof bestaat uit zwarte lijnen, en de kruispunten zijn groen. Dit op een wit vel papier. Het lego voertuig heeft een RCX brick, 2 motoren en 2 lichtsensoren. Ik moet dus 3 kleuren kunnen onderscheiden.
Het uitlezen van sensor 2 gaat probleemloos en levert betrouwbare waarden op. Ga ik echter sensor 3 uitlezen, dan schommelt deze heel erg, zo erg dat ik er weinig mee kan.
Ik lees uit dmv:
code:
1
ERIKA_ad_select(AD_PORT321_SCAN_ACT_ACT_ACT);  (in erika_dummy)


En in thread1:
code:
1
2
3
4
5
6
7
8
  Port6 &= 0xFC;
  ERIKA_ad_start();
  for (i=0; i<20;i++);
  ERIKA_ad_stop();
  
    sensor3=(ERIKA_ad_get_port3()>>5);

    sensor2=(ERIKA_ad_get_port2()>>5);

Bovenstaande code komt niet geheel overheen met de code in de link hieronder. (dit voor de mensen die onderstaande link niet willen bekijken)

Zie voor volledige sourcecode:
http://members.home.nl/mediafiles/develop/

[ Voor 36% gewijzigd door robbertb op 22-10-2004 14:13 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
Storing op je AD converter ? Slechte bedrading ? Kapotte AD converter ?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • robbertb
  • Registratie: September 2000
  • Niet online
farlane schreef op 21 oktober 2004 @ 09:14:
Storing op je AD converter ? Slechte bedrading ? Kapotte AD converter ?
Volgens mij heeft het met de timing te maken. Want de waarde is redelijk goed nu maar valt om de zoveel tijd van een waarde rond 1500 inelkaar naar 280.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
robbertb schreef op 21 oktober 2004 @ 12:24:
Volgens mij heeft het met de timing te maken. Want de waarde is redelijk goed nu maar valt om de zoveel tijd van een waarde rond 1500 inelkaar naar 280.
Het zal idd even duren voordat de AD converter een stabiele waarde heeft aangenomen. Daarnaast zal nadat je de AD conversie gestopt is ook even moeten wachten totdat de waarde gelatched is.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • robbertb
  • Registratie: September 2000
  • Niet online
farlane schreef op 21 oktober 2004 @ 14:45:
[...]


Het zal idd even duren voordat de AD converter een stabiele waarde heeft aangenomen. Daarnaast zal nadat je de AD conversie gestopt is ook even moeten wachten totdat de waarde gelatched is.
Hij geeft ook steeds een goede waarde maar dan 2 keer fout en dan weer paar sec goed en dan weer 2x fout, heel regelmatig dus.
Ik heb het opgelost dmv een timertje te plaatsen, maar dit werkt niet supergoed, en erg netjes is het ook niet. Heb je nog een beter idee?

Ik heb even alles online gezet om het wat duidelijker te maken:
http://members.home.nl/mediafiles/develop/

Het gaat dan met name om de code in code.c. De rest is vrijwel standaard overgenomen van de voorbeelden van de erikasite.

[ Voor 18% gewijzigd door robbertb op 21-10-2004 23:12 ]


  • jan-marten
  • Registratie: September 2000
  • Laatst online: 16-05 13:55
Dit klinkt naar problemen met interrupts (timer interrupt) die bijvoorbeeld tijdelijk een andere thread probeert uit te voeren.

Ik kan de functie ERIKA_ad_get_port2 niet vinden.

Als je trouwens sensor 2 en 3 omdraait, gebeurt het dan ook?

Maar even wat nuttigers erbij melden:
Ik zie dat jij dit doet:
C:
1
2
3
  ERIKA_UINT16 sensor;
  ERIKA_UINT8 i;
  Port6 &= 0xFC; // waar deze regel wat overbodig is:

Die 3e regel wordt overschreven door de functie __INLINE__ void ERIKA_ad_select(ERIKA_UINT8 c) in include/h8/inline_d.h :
C:
1
2
3
4
5
6
7
8
9
10
__INLINE__ void ERIKA_ad_select(ERIKA_UINT8 c)    
{
    ADCSR &= 0xC0;
    ADCSR |= (c & 0x1F);
    /* bit 2,1,0 of port6(h8/3292) set to 1 if sensor (of port 1,2,3) is active, 0 if passive */
    Port6DdrShadow |= (c>>5);
    Port6Ddr=Port6DdrShadow;            
    Port6 &= 0xF8;
    Port6 |= (c>>5);
}


Ik weet trouwens niet of die regel waar je 20 cycles wacht nuttig is. Dit zou je beter op een andere manier kunnen doen (while(!ready);-achtig).

[ Voor 63% gewijzigd door jan-marten op 22-10-2004 10:26 . Reden: research :) ]


  • robbertb
  • Registratie: September 2000
  • Niet online
jan-marten schreef op 22 oktober 2004 @ 09:57:
Dit klinkt naar problemen met interrupts (timer interrupt) die bijvoorbeeld tijdelijk een andere thread probeert uit te voeren.
Ja zoiets dacht ik dus ook al, of dat de AD-converter nog niet klaar is met zijn werk ofzo.
Ik kan de functie ERIKA_ad_get_port2 niet vinden.
Dit is ook geen functie maar een functie aanroep in mijn methode "lees_sensor".
Als je trouwens sensor 2 en 3 omdraait, gebeurt het dan ook?
Ja, dus het ligt niet aan de sensor.
Als ik sensor 3 alleen uitlees (met ad_select3_single_act ofzoiets),dan gaat het wel goed. Maar het gaat ook heel regelmatig fout. Als ik de PERIODIC_THREAD_MAX verhoog naar 1000 ofzo dan gaat het ook fout alleen de intervallen zijn dan veel groter dat het fout gaat. Dus eens in de zoveel tijd is hij met iets anders bezig waardoor de leeswaarde van sensor 3 inklapt van een getal rond de 1600 naar 280.
Maar even wat nuttigers erbij melden:
Ik zie dat jij dit doet:
C:
1
2
3
  ERIKA_UINT16 sensor;
  ERIKA_UINT8 i;
  Port6 &= 0xFC; // waar deze regel wat overbodig is:

Die 3e regel wordt overschreven door de functie __INLINE__ void ERIKA_ad_select(ERIKA_UINT8 c) in include/h8/inline_d.h :
C:
1
2
3
4
5
6
7
8
9
10
__INLINE__ void ERIKA_ad_select(ERIKA_UINT8 c)    
{
    ADCSR &= 0xC0;
    ADCSR |= (c & 0x1F);
    /* bit 2,1,0 of port6(h8/3292) set to 1 if sensor (of port 1,2,3) is active, 0 if passive */
    Port6DdrShadow |= (c>>5);
    Port6Ddr=Port6DdrShadow;            
    Port6 &= 0xF8;
    Port6 |= (c>>5);
}
Ik heb heel veel geexperimenteerd met het weglaten of verplaatsen van dat "port6" en " ERIKA_ad_reset_end_flag();" helaas zonder resultaat, ja of de waarde bleef constant op 280 of sensoren deden niks of de sensoren gingen knipperen.
Ik weet trouwens niet of die regel waar je 20 cycles wacht nuttig is. Dit zou je beter op een andere manier kunnen doen (while(!ready);-achtig).
Daarme bedoel je dit stuk: ?
code:
1
2
3
  ERIKA_ad_start();
  for (i=0; i<20;i++);
  ERIKA_ad_stop();

Dit heb ik gewoon overgenomen uit een voorbeeld.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 17-05 17:19
robbertb schreef op 22 oktober 2004 @ 14:10:
Dus eens in de zoveel tijd is hij met iets anders bezig waardoor de leeswaarde van sensor 3 inklapt van een getal rond de 1600 naar 280.
Lijkt me dat je op dat moment geen stabiele waarde hebt in je bovenste byte oid. Of het onderste byte is al van een nieuwe meting, en het bovenste nog niet,

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • robbertb
  • Registratie: September 2000
  • Niet online
farlane schreef op 22 oktober 2004 @ 22:11:
[...]


Lijkt me dat je op dat moment geen stabiele waarde hebt in je bovenste byte oid. Of het onderste byte is al van een nieuwe meting, en het bovenste nog niet,
Maar het is ook vooral sensor op poort 3...
Heb je enig idee wat ik eraan kan doen of wat ik verkeerd heb gedaan in mijn code?

  • robbertb
  • Registratie: September 2000
  • Niet online
Nog even wat extra info, het gaat goed als ik 1 sensor uitlees, als ik er 2 uitlees (maakt niet uit welke 2 van de 3), dan geeft de 2e sensor instabiele waardes..

  • jan-marten
  • Registratie: September 2000
  • Laatst online: 16-05 13:55
Ik zou toch nog eens kijken naar de threads die je hebt runnen:

Thread0 - kan tijdelijk weg (leeg)
Thread1 - is je main-thread...
Thread2 - kan ook weg (leeg)

Zorg ervoor dat er geen interrupts binnen kunnen komen tijdens het inlezen (timer, external, etc). In 8051 gaat dat met EA (Enable All Interrups) op 0 te zetten.

Zorg ervoor, voordat je gaat meten, de waarde leesWaardeRechts ook gereset wordt.

Zorg ervoor dat sensor 2 en 3 om de beurt uitgelezen worden (denk dat dat wel uitkomst gaat bieden). IMO is threading hier ook voor gemaakt:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
char sensorTeller;
ERIKA_UINT16 sensorLinks, sensorRechts; /* ja, lekker global, lekker makkelijk :P */

/* Declare: */
sensorTeller=0; /* 0=links, 1=rechts */

/* lees_sensor() */
void lees_sensor (void)
{
  ERIKA_ad_start();
  /* for(.....); of while(notread); ofzoiets */
  ERIKA_ad_stop();
  if(sensorTeller==0)
  {
    sensorLinks=(ERIKA_ad_get_port3()>>5);
    sensorTeller=1;/* next sensor */
  }
  else /* if sensorTeller==1 */
  {
     sensorRechts=(ERIKA_ad_get_port2()>>5);
     sensorTeller=0; /* previous sensor */
  }
  ERIKA_ad_reset_end_flag();
}


Het idee begrijp je denk ik wel. Sensor 2 en 3 worden nu niet NA elkaar uitgelezen maar omstebeurt.

Het zijn maar een paar suggesties.

[ Voor 10% gewijzigd door jan-marten op 24-10-2004 17:56 . Reden: bla :), syntax horror ]


  • robbertb
  • Registratie: September 2000
  • Niet online
jan-marten schreef op 24 oktober 2004 @ 17:53:
Ik zou toch nog eens kijken naar de threads die je hebt runnen:

Thread0 - kan tijdelijk weg (leeg)
Thread1 - is je main-thread...
Thread2 - kan ook weg (leeg)

Zorg ervoor dat er geen interrupts binnen kunnen komen tijdens het inlezen (timer, external, etc). In 8051 gaat dat met EA (Enable All Interrups) op 0 te zetten.

Zorg ervoor, voordat je gaat meten, de waarde leesWaardeRechts ook gereset wordt.

Zorg ervoor dat sensor 2 en 3 om de beurt uitgelezen worden (denk dat dat wel uitkomst gaat bieden). IMO is threading hier ook voor gemaakt:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
char sensorTeller;
ERIKA_UINT16 sensorLinks, sensorRechts; /* ja, lekker global, lekker makkelijk :P */

/* Declare: */
sensorTeller=0; /* 0=links, 1=rechts */

/* lees_sensor() */
void lees_sensor (void)
{
  ERIKA_ad_start();
  /* for(.....); of while(notread); ofzoiets */
  ERIKA_ad_stop();
  if(sensorTeller==0)
  {
    sensorLinks=(ERIKA_ad_get_port3()>>5);
    sensorTeller=1;/* next sensor */
  }
  else /* if sensorTeller==1 */
  {
     sensorRechts=(ERIKA_ad_get_port2()>>5);
     sensorTeller=0; /* previous sensor */
  }
  ERIKA_ad_reset_end_flag();
}


Het idee begrijp je denk ik wel. Sensor 2 en 3 worden nu niet NA elkaar uitgelezen maar omstebeurt.

Het zijn maar een paar suggesties.
Grappig, dat om de beurt uitlezen had ik ook net vanmiddag bedacht, werkt wel beter maar nog niet perfect. Daarnaast heb ik het idee dat hij nu best wel traag geworden is. (met de metingen).
Wat je met "In 8051 gaat dat met EA (Enable All Interrups) op 0 te zetten." zei, is me niet echt duidelijk. Ik neem aan dat als ik "EA=0" invoer dat ik dan de melding krijg dat EA not declared is.
Weet je trouwens ook wat ik met "const ERIKA_UINT16 th_period[PERIODIC_THREAD_MAX]={" aanmoet?
Het lijkt me de duur die de thread mag zijn en eht andere getal is het aantal threads?

  • jan-marten
  • Registratie: September 2000
  • Laatst online: 16-05 13:55
Grappig, dat om de beurt uitlezen had ik ook net vanmiddag bedacht, werkt wel beter maar nog niet perfect. Daarnaast heb ik het idee dat hij nu best wel traag geworden is. (met de metingen).
Het aantal metingen per tijdseenheid per sensor is uiteraard gehalveerd. Dat klopt dus wel.

Wat je ook zou kunnen doen is het volgende:
thread0 - leest sensor 1 uit
thread1 - doet iets anders
thread2 - leest sensor 2 uit
thread3 - moet nog aangemaakt worden maar doet ook weer iets anders.

Ik weet niet in hoeverre de taken parallel draaien maar het lijkt mij logisch dat de volgorde 0, 1, 2, 3, 0, 1, 2, 3 een beetje aangehouden wordt. Thread1 kan dan berekeningen uitvoeren. Thread3 kan dan iets aansturen.
Wat je met "In 8051 gaat dat met EA (Enable All Interrups) op 0 te zetten." zei, is me niet echt duidelijk. Ik neem aan dat als ik "EA=0" invoer dat ik dan de melding krijg dat EA not declared is.
Ik bedoelde met EA=0 dat je de interrupts allemaal uitschakeld. Hier zal in erika wel een functie voor zijn.
Weet je trouwens ook wat ik met "const ERIKA_UINT16 th_period[PERIODIC_THREAD_MAX]={" aanmoet?
Het lijkt me de duur die de thread mag zijn en eht andere getal is het aantal threads?
Wat dat precies inhoud weet ik niet.

Als dit een simpele vorm van parralel taskin is dan kan het zijn dat er een Timer draait die bij elke interrupt (timer_overflow neem ik aan) de volgende thread start. Als de Timer zo is ingesteld dat een thread exact 200 cycles nodig heeft en je overschrijdt die waarde dan kan het zijn dat je huidige programma in de soep loopt. Dat is misschien wat er gebeurt (als er geen veiligheidsmechanisme is ingebouwt die checkt als de huidige thread nog draait...).

Ik meende dat er aan het einde van een thread meestal ook zoiets staat als threadState=finished en dat er in de Timer routine iets gebeurt als if (threadStat != finished) { // niets } else { // selecteer volgende thread } (pseudo code). Hoe dit in erika geregeld is weet ik zo niet...

Edit; ik heb nog nooit van erika gehoord :P laat staan mee gewerkt :)

[ Voor 3% gewijzigd door jan-marten op 25-10-2004 14:22 ]

Pagina: 1