Snellere IO via poort manipulatie

@sterretje

Ik ga nu leren hoe je de IO van de arduino sneller kan laten verlopen dan zon 100ms.

Wokwiki : https://wokwi.com/projects/447233633583327233

Is dit wat je bedoelde met het aansluiten ??

Dat is prima.

Je kunt het volgende programma gebruiken en kijken hoe snel het is als je op de traditionele manier pulsen genereert. We gebruiken nu slechts één pin.

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
uint8_t outPins[3] = { 3, 6, 11 };

void setup()
{
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(outPins); cnt++)
  {
    pinMode(outPins[cnt], OUTPUT);
  }
}
void loop()
{
  digitalWrite(outPins[0], HIGH);
  digitalWrite(outPins[0], LOW);
}

Kijk op de logic analyser hoe lang een puls hoog is en hoe lang een pulse laag. Voor het geval je het nog niet gevonden had, je kunt vergroten en verkleinen.
Je kunt de tijd meten met de cursors
image
en de cursors (links en rechts) verslepen om de tijden te meten.

Daarna kun je hetzelfde doen voor alle 3 de pinnen. Het maakt niet uit of je één pin hoog en laag maakt en dan de volgende of eerst all drie pinnen hoog maak en daarna alle drie laag.

Je kunt dan de tijd meten tussen het begin van een pin die hoog gaat en de volgende keer dat die pin weer hoog gaat.

oke

Als ik de getallen snap dan is het 4.4760 us hoog en 4.93700 laag

Dit is voor 1 pin

met 3 pinnen kom ik tot deze getallen

Hoog : 5 us
Laag : 22.04800

Dus alles bijelkaar gezet

aantal pinnen                         hoog                 laag 

1                                   4.4760 us              4.93700    
3                                   5us                   22.04800

Conclusie: met meerdere pinnen in gebruik duurt het langer dat de pin weer aangaat.

Voor 3 pinnen heb ik dit programma gebruikt.

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
uint8_t outPins[3] = { 3, 6, 11 };

void setup()
{
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(outPins); cnt++)
  {
    pinMode(outPins[cnt], OUTPUT);
  }
}
void loop()
{
  digitalWrite(outPins[0], HIGH);
  digitalWrite(outPins[0], LOW);

  digitalWrite(outPins[1], HIGH);
  digitalWrite(outPins[1], LOW);

  digitalWrite(outPins[2], HIGH);
  digitalWrite(outPins[2], LOW);
}

Één van je cursors staat eigenlijk verkeerd in het tweede plaatje. Je wilt meten van een opgaande flank tot de volgende opgaande flank of van een neergaande flank tot de volgende neergaande flank.

Je hebt het op de moeilijke manier gedaan door te rekenen; laat de computer (pulseview) dat voor je doen :wink:

Heb je ondertussen dit gelezen: https://docs.arduino.cc/retired/hacking/software/PortManipulation/. Snap je het? Denk je dat je het kunt toepassen op één pin (programma van bericht 2)?

Begrijp ik je nu goed :

dan is het 26.62400 us

En wat bedoel je met zelf rekenen en laat pulseView dat doen ?

ik heb de pagina doorgelezen en ga het vanavond of morgen toepassen.

oke

Even kijken of ik alles goed snap van die pagina

Ik denk dat dit zou kunnen werken :

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
uint8_t outPins[3] = { 3, 6, 11 };

void setup()
{

  DDRD = DDRD | 010010 
  DDRB = DDRB | 000010

  /*
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(outPins); cnt++)
  {
    //pinMode(outPins[cnt], OUTPUT);
   
  }
  */
}

void loop()
{
  PORTD = B010000;

  PORTD = B000000; 
  
  /*
  digitalWrite(outPins[0], HIGH);
  digitalWrite(outPins[0], LOW);

  digitalWrite(outPins[1], HIGH);
  digitalWrite(outPins[1], LOW);

  digitalWrite(outPins[2], HIGH);
  digitalWrite(outPins[2], LOW);
  */
}

?

Jij had twee tijden (laag en hoog) en die moet je bij elkaar optellen om de totale tijd te bepalen. In het plaatje van bericht 7 heeft pulseview je het totaal direct gegeven.

Kun je berekenen hoeveel keer per seconde je met deze benadering je de Arduino op deze manier een puls kunt laten geven op ieder van de drie pinnen?

Dat wordt dan 1 / 0.00002624 = 38.099 pulses met 3 pinnen.

Ik moet altijd even nadenken over die punt. In Nederland is dat 1000-tallen dus ja, dat is het maximum dat je kunt halen.

En dan kun je nu naar de volgende puzzel (zoals aangegeven); neem er je tijd voor. Je kunt de pinMode() in setup() laten zoals die is, het gaat me er meer om het schakelen van de pinnen van hoog naar laag sneller te maken.

oke

Als ik het goed begrepen heb, zou dit het werk kunnen doen

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
uint8_t outPins[3] = { 3, 6, 11 };

void setup()
{

  
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(outPins); cnt++)
  {
    pinMode(outPins[cnt], OUTPUT);
  }
}

void loop()
{
  PORTD = B00010000

  PORTB = B00000000; 
}

Hier doe ik iets fout

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
uint8_t outPins[3] = { 3, 6, 11 };

void setup()
{

  
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(outPins); cnt++)
  {
    pinMode(outPins[cnt], OUTPUT);
  }
}

void loop()
{
  PORTD = B00010000;

  PORTD = B00000000; 
}

Als ik nu naar pulseview ga , zie ik helemaal geen golf maar een vlakke lijn.

Je kunt niet tellen :wink: Het programma van bericht 13 stuurt pin 4 aan.

Veranderd en nog steeds een vlakke lijn.

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
uint8_t outPins[3] = { 3, 6, 11 };

void setup()
{

  
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(outPins); cnt++)
  {
    pinMode(outPins[cnt], OUTPUT);
  }
}

void loop()
{
  PORTD = B00100000;

  PORTD = B00000000; 
}

Misschien schijnt dit er wat licht op.

void setup()
{
  Serial.begin(11520);
  Serial.println(1, BIN);
  Serial.println(2, BIN);
}

En laat loop leeg !!

Dat geeft 01 and 10
Wacht eens , "moet" ik van de andere kant tellen

Als je het snapt kun je weer terug gaan naar je origineel wmen het aanpassen.

nee, van de andere kant tellen, lost het "probleem" ook niet op

 PORTD = B00000100;

Dat is pin 2. Men begint te tellen vanaf 0 (minst significante bit).

B00000100
 76543210