Wat te veranderen om de twee leds te gebruiken om tot 3 te tellen

hoi,

Sorry voor zoveel vragen maar het werken zonder delay vindt ik nog wat lastig.

IK heb dit : Wokwi - Online ESP32, STM32, Arduino Simulator

hoe kan ik de code veranderen zodat het digitaal tot 3 telt met 1 - 2 seconden aan per getal.

Heel erg bedankt alvast

Kijk eens naar onderstaande demo. Het gebruikt print statements in plaats van LED. De belangrijke regels zijn de if statements.

uint8_t counter;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  if (counter & 0x02)
  {
    Serial.print("1");
  }
  else
  {
    Serial.print("0");
  }

  if (counter & 0x01)
  {
    Serial.print("1");
  }
  else
  {
    Serial.print("0");
  }

  Serial.println("");

  counter++;
  if (counter == 4)
  {
    counter = 0;
  }

  delay(1000);
}

Nu wil je waarschijnlijk naar die 8 LEDs toe en dan zou je die blokjes moeten herhalen. Daarom is het beter een andere oplossing te kiezen waar je met een for-loop door de bits kunt lopen.

uint8_t counter;
const uint8_t numBits = 2;
void setup()
{
  Serial.begin(115200);
}

void loop()
{
  for (uint8_t cnt = numBits; cnt > 0; cnt--)
  {
    if (counter & (1 << (cnt -1)))
      Serial.print("1");
    else
      Serial.print("0");
  }

  Serial.println();

  counter++;
  if (counter == 4)
  {
    counter = 0;
  }

  delay(1000);
}

De rest van de puzzel laat ik even aan jou over; je kunt een array van pinnen gebruiken voor de LEDs en cnt gebruiken om een element uit dat array te pikken en de pin hoog of laag te maken.

Bestudeer het en vraag wat je niet begrijpt.

Ik ga het bestuderen.
Maar wat ik bedoel is hoe zorg ik ervoor als ik geen delay gebruik , de led die ik wil laat branden 1 sec brandt en dan een "pauze" heeft van 1 sec.

Met delay zou ik dit doen

digitalWrite(pin1, high) 
delay(1000) 
DigitalWrite(pin1, low) 
delay(1000) 

ik zie dus niet hoe ik hetzelfde doe maar dan zonder de delay te gebruiken.
En hoort Counter dan geen beginwaarde ergens te hebben ?

En ik zie nog steeds niet hoe ik kan zorgen dat de juiste led brandt.
Het lijkt erop dat jij van de laatste naar de eerste led gaat

Ik blijf vast zitten op deze code :

uint8_t counter;
const uint8_t numBits = 2;
int LEDPIN_RED = 6 ; 
int LEDPIN_BLUE = 4 ; 

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  for (uint8_t cnt = numBits; cnt > 0; cnt--)
  {
    if (counter & (1 << (cnt -1)))
      Serial.print("1");
    else
      Serial.print("0");
  }

  Serial.println();

  counter++;
  if (counter == 4)
  {
    counter = 0;
  }

  delay(1000); 
}

Ik had begrepen dat je een binaire teller wilde maken en dacht dat je met het binaire stuk vast zat. Het demo programma demonstreert het binaire teller gedeelte.

Ik heb delay() gebruikt omdat ik voor de demo lui ben. Als je blink-without-delay begrijpt is het eenvoudig om de implementatie te veranderen. Als je blink-without-delay nog niet begrijpt moet je dat eerst onder de knie krijgen voordat je verder gaat.

Als je een uitleg nodig hebt van blink-without-delay moet je het laten weten. Ik weet niet zeker of je je wokwi programma doet wat je ervan verwacht; voor mijn gevoel zit er iets niet goed maar ik weet niet wat het programma veronderstelt wordt te doen.

counter is een globale variabele en globale variabelen worden geïnitialiseerd met 0 als je niet specifiek een specifieke waarde meegeeft.

Op dit moment doet het niet wat ik verwacht. Was aan het toewerken naar de binaire teller.
Eerst een kleine om daarna het meer complex te maken.

Wat ik begrijp tot nu toe, is dat je een interval stelt
daarna laat je de interne klok lopen en checked of de interval verlopen is.
Met een led snap ik hoe het werkt, maar zoals ik al probeer te vragen zie ik niet hoe ik dan 2 leds' kan besturen die dan aangaan als ik wil en weer uitgaan wanneer ik wil.

Als ik dit ga begrijpen, kan ik denk ik ook verder werken aan de binaire teller.

Wat er naar mijn mening fout gaat met je wokwi programma is het volgende.

(1)
In loop() kijk je of het tijd is om de rode LED om te schakelen.

  if (millis() > nextTick)
  {
    nextTick += INTERVAL;
    digitalWrite(LEDPIN_RED, !digitalRead(LEDPIN_RED));
  }

Nee, het is nog geen tijd.

(2)
Dan kijk je of het tijd is om de blauwe LED om te schakelen.

  if (millis() > nextTick)
  {
    nextTick += INTERVAL;
    digitalWrite(LEDPIN_BLUE, !digitalRead(LEDPIN_BLUE));
  }

Terug naar (1), door naar (2), terug naar (1) enz.

Uiteindelijk zal de seconde verstreken zijn. Dat kan zijn zijn aan het begin van loop() of tussen de twe testen (if) of aan het eind van loop(). Laten we zeggen dat dat gebeurt vlak voordat je (1) controleert. De rode LED zal nu omgeschakeld worden en je zet een nieuwe start tijd.

Je komt weer bij (2) terecht maar omdat je net een nieuwe start tijd gezet hebt zal de conditie niet waar zijn en wordt de blauwe LED dus niet omgeschakeld worden.

Weer een aantal keer (1) en (2) totdat er een seconde verstreken is; dit keer bv tussen (1) en (2). Dus zal de blauwe LED nu omgeschakeld worden en een nieuwe tijd zal gezet worden. Als een resultaat is er geen kans dat de rode LED omgeschakeld worden voordat er weer een seconde verstreken is.

Als je de twee LEDs volledig onafhankelijk van elkaar wilt laten knipperen zul je twee nextTime variabelen moet gebruiken (bv nextTimeRed en nextTimeBlue); als je ook nog verschillende intervallen nodig hebt zul je ook twee INTERVAL constanten nodig hebben.

Het zal een zooitje worden als je dit voor acht LEDs wilt doen, dan ben je beter af met een andere benadering.

dat zie ik,
Dan wordt de code een mooi zootje met 8 keer een nextTime en 8 keer een interval.
Eens goed nadenken en experimenteren hoe het dan op te lossen.
Makkelijke oplosing is dan toch delay te gebruiken maar om te oefenen is het ook goed om eens buiten de gebaande paden te kijken.

En oefenen is de enigste manier om te leren hoe iets kan zonder delay te gebruiken.
Kan heel handig zijn denk ik als de projecten echt complex worden.

en eens goed nadenken hoe ik dan dit kan combineren met de andere code zodat ik een binaire code heb die met een aantal leds kan werken.

Arrays van structs of arrays van classes zijn je vriend :wink: Ben je bekend met arrays en structs (en/of classes)?

Het gebruik van delay staat los van je andere zaken zoals de problematische wokwi code.

in c++ ben ik iets bekend met arrays, structs en classes.

oke, de bedoeling is oefenen met het werken zonder delay maar blijkbaar neem ik een iets te grote stap.

Heb even nagedacht maar zorgt een array van classes ook niet voor een messy code.
Eerst de classes aanmaken en daarna nog in een array stoppen enz.

Je begrijpt de benadering van blink-without-delay. Ik denk dat je eigenlijk twee problemen hebt.

  1. In een poging om meerdere LEDs te laten knipperen ben je een beetje de mist in gegaan zoals ik eerder beschreef.
  2. En dat heeft je aandacht een beetje afgeleid van het eigenlijke doel, de teller.

Voor de teller heb je slechts één timing nodig. je loop() zou er zou er ongeveer zo uit moeten zien

void loop()
{
  if (millis() > nextTick)
  {
    nextTick += INTERVAL;

    // update counter
    ...
    ...

    // display counter value on LEDs
    ...
    ...
  }
}

Hierbij een aangepaste versie voor het onafhankelijk knipperen (niet nodig voor de teller).

uint8_t ledpinRed = 6;
uint32_t nextTickRed;
uint32_t intervalRed = 333;
uint32_t ledpinBlue = 4;
uint32_t nextTickBlue;
uint32_t intervalBlue = 666;

void setup()
{
  pinMode(ledpinRed, OUTPUT);
  pinMode(ledpinBlue, OUTPUT);
  nextTickRed = millis() + intervalRed;
  nextTickBlue = millis() + intervalBlue;
}

void loop()
{

  if (millis() > nextTickRed)
  {
    nextTickRed += intervalRed;
    digitalWrite(ledpinRed, !digitalRead(ledpinRed));
  }

  if (millis() > nextTickBlue)
  {
    nextTickBlue += intervalBlue;
    digitalWrite(ledpinBlue, !digitalRead(ledpinBlue));
  }
}

Één opmerking:
nextTick += INTERVAL; zal je bij de millis() overflow (dus na zo'n 49 dagen) een probleem opleveren. De reden is dat nextTick ineens van een heel groot getal naar een klein getal gaat en millis() op dat moment nog een heel groot getal is en de conditie dus nog steeds waar is.
Het is beter of iets te gebruiken als

if(millis() - lastTime >= INTERVAL)
{
  lastTime = millis();
}

Dank je

IK denk dat je de variable ledPinRed vergeten bent te declaren,

Ik ga eens dit goed bestuderen om te kijken of ik dit idee kan gebruiken van de teller.
eerst met 2 led's en dan steeds uitbreiden tot het werkt met 8 led's .
en het idee is nog steeds om te kijken of ik het kan laten werken maar dan zonder delay te gebruiken.

En eens goed nadenken welke kleine stappen ik kan doen om van deze code naar een teller toe te komen.

Nee
Simpel voorbeeld

// macro to calculate number of elements in an array of any size
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

// struct for LED
struct LED
{
  uint8_t pin;              // the pin
  uint32_t lastTime;        // last time that timing lapsed
  const uint32_t interval;  // interval
};

LED leds[] = {
  { 6, 0, 666 },
  { 4, 0, 333 },
};

void setup()
{
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(leds); cnt++)
  {
    pinMode(leds[cnt].pin, OUTPUT);
  }
}

void loop()
{
}

Door gebruik te maken van een for-loop blijft je programma schoon. Geen twee of acht regels om de pinMode te zetten voor je LEDs.

Zou kunnen werken met het idee wat jij eerder gaf,
Dan kan ik de loop variable gebruiken om te kijken of een led aan of uit moet,

Eens met experimenteren de komende dagen in de wiki

Nog heel veel te leren over de arduino en over c++
En over "complexe" problemen oplossen.

Maar omdat het een hobby is , heb ik tijd genoeg.

Zit er mee te spelen maar krijg dit niet gecompileerd

// macro to calculate number of elements in an array of any size
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
uint32_t nextTickRed;
uint32_t nextTickBlue;

// struct for LED
struct LED
{
  uint8_t pin;              // the pin
  uint32_t lastTime;        // last time that timing lapsed
  const uint32_t interval;  // interval
};

LED leds[] = {
  { 6, 0, 666 },
  { 4, 0, 333 },
};

void setup()
{
  for (uint8_t cnt = 0; cnt < NUMELEMENTS(leds); cnt++)
  {
    pinMode(leds[cnt].pin, OUTPUT);
    nextTickRed = millis() + leds[0,0];
    nextTickBlue = millis() + leds[1][0];
  }
}

void loop()
{
  if (millis() >  leds[0][0])
  {
    nextTickRed += leds[0]->interval;
    digitalWrite(leds[0][0], !digitalRead(leds[0][0]));
  }
}

Blijkbaar heb ik nog te weinig ervaring met structs.
Mag ik een hint ?

leds is een één-dimensionaal array. Kijk eens hoe de elementen van een struct benaderd worden in de for-loop in setup().

Saw it.
De leds gaan nu wel aan maar nog niet uit.

Ga nu slapen en morgen kijken hoe dit op te lossen

Nee, ik zie niet wat ik verkeerd gedaan heb.
Mag ik een tip ?

In reactie op welk bericht is dat?