Vast een simpel Arduino vraagje, maar het werkt niet.

Hallo Mensen,

Ik heb een stukje code deels overgenomen en ondanks alle vergelijkingen met andere stukjes code, werkt het niet.
Het gaat om iets simpels als het "herkennen" van een drukknop aanslag.
Drukknop wordt ingedrukt en er moet wat gebeuren.
Maar dat gebeurt niet.

code:
#include <Keyboard.h>

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

  Serial.begin(9600);
  delay(5000);
}

void loop() {

Keyboard.begin();
//if (digitalRead(5) == 0)
 // {
    Keyboard.write('a');
    Keyboard.print("bbb");
    delay(500);
 // }
Keyboard.end();
}


Ik laat wat letter verschijnen in mijn serial monitor en zoals het hier aangegeven staat, werkt het gewoon.
na 5 sec begint hij elke halve seconde "abbb" te spugen.
Maar hij moet dat pas doen wanneer ik de toets aan poort 5 heb ingedrukt.
Deze drukknop trekt poort 5 naar null, maar dat lijkt niet te werken.
Doe ik iets verkeerd in de code?
boe
De test is nu uitgecommend, dus die doet inderdaad niets. Verder is het vermoedelijk onhandig en niet de bedoeling om de keyboard lib voortdurend op de maximale snelheid te (de-) activeren.
In de voorbeelden start men de keyboard emulatie eenmailig op met keyboard.begin() in de setup().
Klopt Aart,

Dat komt uit het stukje uitgebreidere code waarbij maar incidenteel een karakter wordt aangesproken. Zo nu en dan moest er wat geplaatst worden dus zou de processor niet continue belast zijn met het keyboard deel.

Inmiddels heb ik de fout kunnen tackelen.
Die breadboardjes hebben die dubbele banen links en rechts lopen, nietwaar?
Die zijn over de lengte onderbroken, halverwege. |:-(

Ik kon me dat vaag nog herinneren.
Mijn druktoetsen waren nooit met GND verbonden.

Valtweermee...

Maar als ik dan meteen mijn volgende vraag kan neerleggen.
Meer een stukje verbazing, eigenlijk.
Bestaat er geen goto mogelijkheid binnen de Arduino wereld?
Ik red me wel redelijk met de loops, maar meerdere loopjes binnen een grote loop redden het misschien niet altijd (hier toevallig wel hoor) en met dat ik aan het rommelen was, realiseerde ik me dat ik zoiets al Goto of Gosub nog nergens ben tegengekomen.
boe
Om drie knoppen uit te lezen heb je toch geen library nodig.
En inderdaad de comments.
BVZ

Golden Member

Op 6 januari 2019 21:48:23 schreef Fantomaz:

Maar als ik dan meteen mijn volgende vraag kan neerleggen.
Meer een stukje verbazing, eigenlijk.
Bestaat er geen goto mogelijkheid binnen de Arduino wereld?

Gelukkig niet.

Je kunt wel een functie creëren en aanroepen die aan het eind (return) automatisch terugkeert naar de plaats vanaf waar je hem aangeroepen hebt.
Volgens mij heeft het tenzij je tegen geheugenbeperkingen aanloopt weinig voordeel het USB keyboad voortdurend te laten verdwijnen, maar ik kan mij daarin vergissen.

De taal waar je nu in werkt is C, met wat impliciet meegecompileerde Arduino libraries. Er bestaat een goto in C, maar ik wist dat ook niet voordat ik er nu naar zocht en zou eerst eens zien of er geen elegantere oplossing is.
Fantomaz, wat is de reden dat je die keyboard lib gebruikt? Snap je wel wat dat doet? Ik had er nog nooit van gehoord, nooit gebruikt ook. Printen naar uart kun je gewoon met Serial.print("blabla") doen.

goto is natuurlijk een super no-go :-)

[Bericht gewijzigd door flipflop op 6 januari 2019 22:14:29 (11%)]

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

Golden Member

goto maakt spaghetti code.

c code:
Keyboard.begin()


Kan je vergelijken met gosub.
Honing kan je importeren, bestuiving niet.
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.
boe
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
boe
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.
boe
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?
boe
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%)]

boe
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%)]

boe
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