Vast een simpel Arduino vraagje, maar het werkt niet.


buckfast_beekeeper

Golden Member

goto maakt spaghetti code.

c code:

Keyboard.begin()

Kan je vergelijken met gosub.

Van Lambiek wordt goede geuze gemaakt.

Even een update mensen,

Het is een deel van een groter geheel.
Ik had uit een forum oid gehaald dat het constant in bedrijf houden van een aanvraag van een library, zoals deze van het keyboard, belastend zou zijn voor de processor.
Ik kan me indenken dat het in deze setting juíst een onnodige extra handeling is.

Ik heb het geprogrammeerd in een ProMicro omdat ik daarvan de HID optie wil gebruiken.
Al eerder probeerde ik met een PIC toetsaanslagen te simuleren, zodat ik een alternatief voor een toetsenbord kon maken.
In dat topic van lang geleden werd de HID funktie binnen sommige Arduino's aangehaald.
Dus nu maar eens de overstap gemaakt.

Zometeen komen er meer condities waaronder er bepaalde karakters zullen worden verzonden alszijnde toetsaanslagen.

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

keyboard.end() hoef je alleen te gebruiken als je geen keyboard meer wilt naspelen met je arduino.

deze code moet direct werken:
https://www.arduino.cc/en/Reference/KeyboardBegin

GMT+1

Probeer dit maar eens, ik heb er wat commentaar aan toe gevoegd.

c code:


#include <Keyboard.h>

void setup() {
  pinMode(3,INPUT_PULLUP);
  pinMode(4,INPUT_PULLUP);
  pinMode(5,INPUT_PULLUP);

  //Serial.begin(9600);	//We gebruiken geen serieel dus waarom deze initialiseren?
  Keyboard.begin();
  
  delay(5000);	//Waarom wil je deze delay?
}

void loop() 
{
	static bool buttonPrevState = false;	//Static onthoud de waarde in deze variabele, even google gebruiken.
	
	bool buttonState = digitalRead(5);		//Lees de knop uit en sla deze op.
	
	if(buttonState != buttonPrevState )		//Als de knop veranderd is
	{
		if(buttonState == 0)				//En de knop is ingedrukt, (Effectief een opgaande flank detectie)
		{
			Keyboard.write('a');
			Keyboard.print("bbb");
		}
		
		if(buttonState == 1)				//En de knop is niet ingedrukt, (Effectief een neergaande flank detectie)
		{
			//Hier doen we niets
		}
		
		
		buttonPrevState = buttonState;
		delay(500);	//Antie dender, werkt wel is niet heel netjes
	}

	//Keyboard.end();		Waarom zouden we de keyboard willen stoppen?
}




Op 7 januari 2019 19:43:46 schreef Progger:
keyboard.end() hoef je alleen te gebruiken als je geen keyboard meer wilt naspelen met je arduino.

deze code moet direct werken:
https://www.arduino.cc/en/Reference/KeyboardBegin

Ik weet alweer wat de reden was om niet de keyboard constant ingeschakeld te houden. Stel dat ik moet debuggen en mijn ProMicro is nog altijd druk bezig met zijn "toetsenbord" mijn laptop over te nemen, dan kom ik daar niet meer uit.
Om die reden werd het (iig tijdens het testen) afgeraden het keyboard constant actief te houden.

Daarom (en daarmee meteen het antwoord op de tussen de regels door vraag van Hardbass) heb ik ook een delay van 5 secondes erin gezet.
Ik kan dan bij een reboot nog 5 secondes mijn aangepaste code proggen vóór de Arduino is opgestart en het programma allemaal tekst op mijn scherm spuugt.
Ja, hij is gekoppeld met mijn laptop om gedragingen te monitoren. Daarom ook de 9600 seriele snelheid. Uiteindelijk is het ook een apparaat wat verbonden blijft met een PC.

Let wel op nu...
Het is een uitgekleed stukje van een code die ik wil gebruiken.
Het hele programma komt er anders uit te zien. :9
Ik ben aan het freubelen wat ik allemaal kan met de functies die ik her en der leer.

Misschien nog wel iets waar ik nieuwsgierig over ben.
Hoe kan ik een Arduino resetten naar fabinst, zonder dat ik daarvoor een seriele verbinding met mijn PC moet opzetten?

De genoemde 5 seconden pauze kan ik nu gebruiken om het apparaat opnieuw te proggen, maar als mijn keyboard functie belemmert dat ik mijn ProMicro kan benaderen/aanpassen, moet ik wel iets hebben waarmee ik dat ongedaan kan maken dmv fabinst oid. :S

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

Men kan er een 'lege' sketch in schieten, met enkel setup() en loop(). Dan doet hij niets meer.
Dat is niet precies hetzelfde als de situatie na het programmeren van een bootloader en het zetten van de fuses in een lege chip, maar in deze context gelijk.
Voor het leegmaken van eventueel gebruikte EEPROM bestaan voorbeeld sketches.

Het lijkt echter dat de suggestie van de Arduino site om de keyboardemulatiefunctie zo te maken dat je hem via een schakelaar aan een pin kunt activeren, in de praktijk praktisch is.

Jemig, proggen met een leeg programma, was niet iets wat in mij op was gekomen idd. :-)
Maar toch... Het apparaat is plots een doorrammend toetsenbord en die spuugt steeds letters op mijn scherm, waardoor ik niets kan proggen.
Het is iig een failsafe om die 5 seconden in te lassen.

Als straks het programma draait, zal ik bekijken of ik het steeds laat aanroepen of dat hij standaard op de achtergrond draait.

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

Je populaire taalgebruik maakt het wel lastig leesbaar....

Dat uitsturen van karakters kun je toch onder voorwaarde doen, of maar eenmalig, wat je wilt. Je hoeft het niet zo te maken dat je continue karakters binnen krijgt.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein

Ik zou de regel:

static bool buttonPrevState = false; //Static onthoud de waarde in deze variabele, even google gebruiken.

direct na de include regel zetten

@angela, Dat kan maar daarmee wordt het ook meteen een globale variabelen. Daarmee is hij overal in je code berijkbaar. Omdat we de variabele enkel in de functie "loop" gebruiken is het netter om deze static te maken en bovenaan in de functie te zetten. Persoonlijk probeer ik zoveel mogelijk zonder gobale variabelen te programmeren.

@Fantomaz, Met mijn code typt hij toch enkel letters als je de knop indrukt? Al kan ik me zo voorstellen dat bij een groter ingewikkelder programma je niet altijd in de hand hebt. Je kunt ook met een knop de keyboardend aanroepen.

Op 9 januari 2019 21:29:09 schreef flipflop:
Je populaire taalgebruik maakt het wel lastig leesbaar....

Ik zal er op letten. Tx

Hardbass en Angela,
Ik ben behoorlijk beginnend hoor!
Als uiteindelijk het programma klaar is, zal de ProMicro onder bepaalde omstandigheden tekst naar een PC sturen, waarop hij middels USB is aangesloten.

Omdat ik nu aan het proberen ben hoe hij tekst kan versturen, heb ik geen als-dan of wat voor regels dan ook daaraan gehangen.

Anders nog wat...
Ik vind het wel lastig om niet meer met Goto's te kunnen werken.
Ik heb vaak meerdere cases of If/Then statements waarbij ik onder bepaalde condities naar een ander deel van het programma moet.
Ik kan het niet zo 123 duiden en een voorbeeld heb ik ook nog niet zo liggen.

Als ik bijvoorbeeld een If/Then statement heb wat "waar" is, hoe kan ik dan naar een zeker deel van het programma gaan?

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

Worst case heb je bijvoorbeeld een "state" variabele. In Loop doe je dan case (state) ... en waar je naar een andere plek moet, doe je state= <andere state> en "break". De arduino-main roept dan je loop opnieuw aan en je gaat de code in van de nieuwe state.

Over globale variabelen en waarom het gevaarlijk is..

stel even dat je het met een variabele "i" doet (dat is wel heel ongebruikelijk, maar het maakt een goed voorbeeld.

Je doet ergens:

c code:

for (i=0;i<10;i++) {
   do_something ();
   do_somethingelse ();
  }

Goed. Prima! Maar nu in je functie do_something schrijf je:

code:


void do_something (void)
{
  for (i=0;i<20;i++)
    toggle_led ();
}

Maar terwijl je dit schrijft denk je: Zo straks nog even i declareren, maar als het puntje bij het paaltje komt... vergeten!

Normaliter krijg je dan "variabele i niet gedefinieerd" maar met een globale i, is dat ineens niet meer zo. En je 10x loop gaat nu om onverklaarbare reden maar 1x in de rondte! En het verneukeratieve is dat je kan kijken totdat je een ons weegt, maar de fout zit NIET in de code die niet werkt.... (die met de do_something() aanroep en de for lus die tot 10 telt).

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Interessant, Rew...
Maar ik weet niet eens wat die code behoort te doen.
Daarvoor heb ik me teweinig ingelezen.

Gokje...
Die i is 0 in het begin. Elke keer dat het program dit voorbij gaat (het loopje dus) wordt variabele i met 1 vermeerderd tot een max van 10?

Je tweede coder zou hetzelfde doen, maar dat kanik er niet uithalen.
En dan nog wat... i declareren geef je aan...
Ik gok dat je daarmee aangeeft of i een byte of word oid aan data kan bevatten?
En doe je dat niet is het gewoon een bit?

En dat Void do something... Dat is een oneindige loop?
Ik bedoel... Hoe verlaat je die loop als je niet weet wat de condities zijn om de loop te verlaten. Of gebeurd dat in dat geval met een Break?

[Bericht gewijzigd door Fantomaz op 10 januari 2019 20:21:03 (17%)]

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

Er is een loop waar je 10x doorheen loopt. In die loop roept ie 2 functies aan. In die functie gebeurt uiteraard ook iets. Een functie ga je in, en bij het einde kom je weer terug waar je vandaan kwam. Dus geen goto nodig. Dat is sinds Basic in 1980 niet meer gebruikelijk en onnodig.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein

Ik geloof je meteen, Flipflop.

Ik kan me op dit moment niet indenken dat het ook zonder kan.
Voorbeelden heb ik zo niet liggen en misschien zal ik ze ook niet krijgen als ik het creatief op kan lossen.

Waarvan ik nu al weet dat ik het er zwaar mee ga krijgen:

loopje van volgordes
A
B
C
D
E: bepaalde conditie? Ja, dan terug naar C. Nee, dan naar D
F: Bepaalde conditie? Nee, dan terug naar C. Ja, dan naar D.
G: Handelingen, daarna terug naar A.

Heel grof genomen nu. Die handeling bij G. gaat wel lukken.
Die andere verwijzingen lijken me lastig. Dwz, zulke zaken deed ik altijd met een Goto.

En dan nog wat tav het declareren.
Uit een cursusverhaal begreep ik dat ik niet per se op voorhand een variabele hoef te declareren?
In jullie voorbeeld komt plotseling "i" om de hoek kijken. Die behoeft niet eerder gedeclareerd te worden, tenzij het een bijzondere variabele is?

[Bericht gewijzigd door Fantomaz op 10 januari 2019 20:59:58 (19%)]

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

Als je het zo schetst zou ik denken aan een state machine:

c code:



void loop() {
  
  static int state = 0; // Statische variabele om bij te houden waar wij zijn. Begin de eerste keer op 0. 
  
  switch (state) { // ga naar case n afhankelijk van de state
   
    case 0: //  A & B
      A(); // doe functie A 
      B(); // doe functie B
      state = 1; // Ga door naar state 1. 
    break; // verlaat deze switch(state). 

    case 1: //  C 
      C(); 
      state = 2; 
    break;  
    
    case 2: //  D 
      D(); 
      state = 3; 
    break; 
    
    case 3: // E
      E(); 
      if (conditie) {
        state = 1; 
      } else {
        state = 2; 
      }
    break; 

    case 4: // F (merk op dat F en G in het gegeven voorbeeld niet bereikbaar zijn)
      F(); 
      if (conditie) {
        state = 2; 
      } else {
        state = 1; 
      }
    break;

    case 5: // G
      G(); 
      state = 0; // terug naar het begin
    break;
    
  }

}

Houd in het achterhoofd dat de microcontroller de hele tijd rond blijft rennen in loop().

Met enum zou men de staten namen kunnen geven, dat is, samen met logische namen voor de functies goed voor de leesbaarheid maar voor simpele dingen doe ik het zelf ook zo.

Het zijn goede vragen, maar houd bij het zoeken naar antwoorden in gedachten dat het algemene programmeer vragen zijn, niet specifiek voor Arduino of zelfs maar C.

even geprobeerd je code om te werken:

pic basic code:

A
B
C
D
E: als X dan goto C. else goto D
F: als Y dan goto C. else goto D
G: Handelingen, daarna terug naar A.

ik denk dat dit dicht in de buurt komt:
snap je dat dit vele malen beter te lezen is als kris kras GOTO door je code heen?

c code:

loop(){ 
 A
 B
 C While(Y){
 D while(X){
  E
 }
 F
}
}
GMT+1
Shiptronic

Golden Member

Helaas vind ik die pic basic duidelijker te volgen ;)

Wie de vraag stelt, zal met het antwoord moeten leren leven.

Die sprongen in je voorbeeld moet je niet willen. Dat wordt chaos.
Die stappen A, B etc zou je kunnen zien als taken. Stel A is het schrijven naar display, B is het scannen van het keyboard, C is het uitlezen van temp.sensor, etc. Als je wilt communiceren van de ene naar de andere taak dan doe je dat via variabelen. Bv temp.sensor schrijft de temp ergens neer. Het display proces leest het weer uit en zet het op het display. Zo KAN het, kan ook anders.

Wat jij eigenlijk wilt met dat springen is gewoon het aanroepen van een functie. Een complexere operatie breng je onder in die functie. In je hoofdprogramma staat dan alleen (bv) print("pietje") maar in de functie een hele rits andere instructies.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein

Op 10 januari 2019 22:47:03 schreef Shiptronic:
Helaas vind ik die pic basic duidelijker te volgen ;)

True... ;-)

Het is lastig om specifiek te zijn met wat ik wil.
Niet zo zeer omdat ik weer eens niet alles wil laten zien, maar meer omdat ik mogelijk beren op de weg zie die er niet zijn.
Ik mijmer regelmatig tijdens het autorijden hóe ik wát wil doen.
Ik ben zelf ook van de loopjes en loopjes binnen loopjes.
Maar soms loop ik tegen situaties aan waarbij ik van de ene loop naar de andere moet. AArgh... Lastig uit te leggen.

Ik probeer het zo uit te tekenen...
Een loop in een loop waar ergens diep binnenin een conditie moet bestaan die het process halverwege een ander loopje moet brengen.

Weet je...
Ik kan hier wel uit komen door er een variabele aan te knopen die wanneer deze "hoog" is, door alle statements kan loodsen, maar een Goto zou hierin veel gemakkelijker zijn.
Echt niet in een constante loop, maar onder bepaalde omstandigheden.
Een Break is ook zoiets... Die springt uit een actieve loop zonder aan de oorspronkelijke condities te voldoen.
Anyway... Daar is wel wat mee te doen.
Ik vond het alleen jammer dat het begrip GoTo een beetje ter ziele is gegaan. :-)

[update]
Hij bestaat nog altijd, incl. de bijbehorende waarschuwing.
Goed te weten. :-)
https://www.arduino.cc/reference/en/language/structure/contr...ture/goto/
[/update]

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

Waarom post je niet even een concreet voorbeeld van iets wat je wilt maken. We zitten nu een beetje in algemene termen dingen uit te leggen, maar dat muntje valt nog steeds niet. Je denkt in een verkeerde richting met je gotos. Je denkt spagetti.

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein

die paarse lijn kun je compleet weglaten door de bovenste rode loop afhankelijk te maken van de variabele, maar dan NIET.

dus als je de paarse lijn wilt uitvoeren, breek je uit de 3e rode, sla je de 1e rode over en ben je er ook.

GMT+1

Ik ben het in die zin even met FlipFlop eens dat ik eerst een voorbeeld moet aandragen.
En dat heb ik nog niet omdat ik op voorhand verwachtte tegen problemen aan te lopen.

Ik heb op de Arduino pagina gezocht naar de GoTo functie en die wordt inderdaad gebruikt wanneer je diep genesteld zit, een aantal loops diep.

Ik kan wel voorwaardes scheppen in elke voorgaande loop om het programma om te leiden, maar dat maakt het juist onoverzichterlijker.
* Fantomaz is wel een beetje van de warp zones. :-)

Voor alsnog zet ik dit in de ijskast.
Als ik inderdaad uitkom op een diep genestelde loop vanwaar ik onder omstandigheden naar een totaal ander deel van het programma moet gaan, leg ik dat voorbeeld hier voor, mét de GoTo oplossing.
Dan wil ik graag weten hoe jullie dat zouden doen.

Ik moet hier weer vaker komen... Wat kun je zo'n forum als deze gaan missen. :-)

...en dan zeggen wij wel dat die goto er onherroepelijk uit moet, niet nodig is en not-done. Och, heb ik het nu al gezegd! :-)

"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein