werken met binaire waardes

Arduino specifieke Software
Berichten: 68
Geregistreerd: 28 Aug 2012, 15:14

werken met binaire waardes

Berichtdoor Nald » 18 Dec 2012, 22:36

Hallo,

Ik had thuis nog een NES controller liggen en met behulp van deze thread heb ik hem aan de praat gekregen.

http://arduino.cc/forum/index.php/topic,8481.0.html#0

Alleen ik zit met een praktisch probleem

Als ik de toetsen indruk dan krijg ik de volgende codes:
01111111 =A
10111111 =B
11011111 =Select
11101111 =Start
11110111 =Up
11111011 =Down
11111101 =Left
11111110 = Right

Simpel gezegd de "0"verplaatst zich. Op zich is dit niet moeilijk hier kan ik simpele if-voorwaarden aan hangen.

Alleen als ik 2 toetsen indruk dan krijg ik 2 nulletjes, is op zich heel verklaarbaar, maar wat moet ik ermee? Moet ik nu alle mogelijkheden uitschrijven of zijn er simpelere oplossingen? Soort van optellen.

Heeft iemand informatie hoe ik hiermee moet werken of waar ik dit kan vinden? Van handige tips sites of zoekwoorden? Ik loop hier namelijk vaker tegenaan.

Alvast bedankt

Advertisement

Berichten: 77
Geregistreerd: 06 Okt 2012, 10:57

Re: werken met binaire waardes

Berichtdoor Beamer » 19 Dec 2012, 10:30

Je kunt het naar mijn idee afvangen met een XOR (exclusive or) functie
Arduino gebruikt daar het ^ teken voor.
Als je dan per toets een IF statement ,maakt en met een XOR je huidige waarde toetst aan de waarde voor de betreffende toets hoef je niet alle combinaties te beschrijven.
Elk IF statement beoordeelt dan od de toets is ingedrukt, daar kun je dan een actie aanhangen.
Vervolgens ga je dan naar je volgende IF statement.
Voor 8 toetsen ben je dan met 8 IF statements klaar.

Ik heb dit nog niet geprobeerd, maar kan me voorstellen dat je het ongeveer zo zou moeten doen (correct me if i'm wrong)

IF (ReadValue ^ 01111111 ==TRUE) ;//is toets A gedrukt ? waarbij ReadValue je huidige toestwaarde is
'doe actie voor toets A;
ENDIF
en dan de volgende.

Ik weet niet of de syntax correct is, maar dit schiet me zo te binnen.

Succces

Gebruikers-avatar
Berichten: 700
Geregistreerd: 05 Mrt 2012, 21:56
Woonplaats: Appingedam

Re: werken met binaire waardes

Berichtdoor pjh » 19 Dec 2012, 10:35

Er valt veel over binaire waardes te schrijven, maar belangrijk is waar je het nodig hebt in je sketch.
Voor direct de 'theorie' in te duiken, wil ik van jouw 'toerts codes' naar een arduino sketch komen.

01111111 =A
10111111 =B
11011111 =Select
11101111 =Start
11110111 =Up
11111011 =Down
11111101 =Left
11111110 = Right


Dat zijn 8 enen e/o nullen.
Elk knopje veroorzaakt een NUL op een VASTE positie.

Wanneer er geen knopjes worden ingedrukt, zal de code 11111111 zijn
Dit levert 256 combinaties op. Bijvoorbeeld
01110111 of 11010011 of 10011001 enzovoort.

Net als een normaal decimaal getal, staan de kleinere getallen rechts.
Bijvoorbeeld: 34 = 30 + 4

Maar hoe zit dat digitaal / binair?

Welnu, bij 34 weet je het meteen: de 3 staat voor 10 x een drie, omdat de positie ervoor (waar de 4 staat) 0-9 kan bevatten.
Decimaal 451 is 4 x 10 x 10 + 5 x 10 + 1 x 1 = 400 + 50 + 1
11111111 = 10000000 + 1000000 + 100000 + 10000 + 1000 + 100 + 10 + 1
10000000 = 1 x 10 x 10 x 10 x 10 x 10 x 10 x 10
1000000 = 1 x 10 x 10 x 10 x 10 x 10 x 10
100000 = 1 x 10 x 10 x 10 x 10 x 10
10000 = 1 x 10 x 10 x 10 x 10
1000 = 1 x 10 x 10 x 10
100 = 1 x 10 x 10
10 = 1 x 10
1 = 1 x 1


Maar bij binaire 11 moet je eraan wennen: de eerste 1 is niet 1x10, maar 1 x 2, omdat de positie ervoor 0-1 kan bevatten.
Bij binair 111 staat de eerste 1 niet voor 1 x 10 x 10, maar voor 1 x 2 x 2 = 4

In jouw code heb je 8 bits
Binaire 1111 staat niiet voor 1 x 10 x 10 x 10 + 1 x 10 x 10 + 10 + 1, maar voor 1 x 2 x 2 x 2 + 1 x 2 x 2 + 1 x 2 + 1 = 8 + 4 + 2 + 1 = 15

Wanneer je een BYTE neemt, (8 bits) dan kun je het maximale getal van : 11111111 maken
Binair 11111111 schrijf je in een arduino sketch als B11111111 (met een hoofdletter)

11111111 = 10000000 + 1000000 + 100000 + 10000 + 1000 + 100 + 10 + 1
10000000 = 1 x 2 x 2 x 2 x 2 x 2 x 2 x 2 = 128 decimaal
1000000 = 1 x 2 x 2 x 2 x 2 x 2 x 2 = 64 decimaal
100000 = 1 x 2 x 2 x 2 x 2 x 2 = 32 decimaal
10000 = 1 x 2 x 2 x 2 x 2 = 16 decimaal
1000 = 1 x 2 x 2 x 2 = 8 decimaal
100 = 1 x 2 x 2 = 4 decimaal
10 = 1 x 2 = 2 decimaal
1 = 1 = 1 decimaal

Binair 11111111 is decimaal 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255. Met de nul erbij dus 256 verschillende getallen.

Bij elke BIT die je toevoegt, krijg je 2 x meer combinatie mogelijkheden.
1 bit = 2 mogelijkheden
2 bits = 2 x 2 mogelijkheden (00, 01, 10, 11)
3 bits = 2 x 2 x 2 mogelijkheden ( 000, 001, 010, 011, 100, 101, 110, 111)
et cetera

Hier nogmaals jouw tabel:
01111111 =A
10111111 =B
11011111 =Select
11101111 =Start
11110111 =Up
11111011 =Down
11111101 =Left
11111110 = Right


Bijvoorbeeld Down = 11111011
Binair geschreven: = 11111111 - 100
Decimaal geschreven = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 - 4
Decimaal geschreven = 255 - 4
Decimaal geschreven = 251 decimaal

Dan wordt jouw tabel
Afbeelding

FIJN, zul je zeggen, dan weet ik dat Rechts 254 is, maar dat levert me niet een 'toegang' tot meerdere knoppen tegelijkertijd.
MAAR, we kunnen bovenstaande ook omdraaien, om alle combinaties van knoppen in een eenvoudige arduino sketch uit te lezen.
IMMERS:

ALS 'Right' = 254 = 255 - 1
en 'Left' = 253 = 255 -2
Dan is 'Right' en 'Left' vast 255 - 1 - 2, dus 252

Als je 252 binair schrijft krijg je
B11111100 = 252 = 255 - 2 - 1

GELUKKIG zijn er in de 'Arduino' taal zogenaamde 'bit operators', waarmee je direct een bit in een byte kunt aansturen.
dat is FIJN, want dan hoef je die vermoeiende omrekening naar decimaal niet te maken.

WANT:
Afbeelding
Althans, dat is de bit die naar NUL wordt getrokken.

Hier de bitoperators van de arduino taal:
Afbeelding

MAAR VOOR WE DIT TOEPASSEN, eerst een doel:

Jij hebt links, rechts boven en onder op je knoppen,
Daar wil ik N, NO, O, ZO, Z, ZW, W, NW van maken. 8 windrichtingen, omdat rechts-boven anders zo lang wordt.

Eenvoudig:

Afbeelding

wordt vervolgd....
Ik zie nu de post van BEAMER, Hij schrijft:
Je kunt het naar mijn idee afvangen met een XOR (exclusive or) functie
Arduino gebruikt daar het ^ teken voor.


En dat is helemaal juist. (natuurlijk)
Je wil namelijk weten waar de nullen staan, en niet de enen.

Stel, ik doe een XOR met al je knopjes, dan krijg je dit:

Afbeelding

Hier de windrichtingen weer:
Afbeelding

Omdat de windrichtingen alleen de eerste 4 bits van RECHTS bezetten, laat ik de eerste vier weg.
Omdat de eerste 4 bits 16 combinaties kunnen maken, completeer ik de tabel:

Afbeelding

WORDT VERVOLGD...
-----------------
En dan nu naar Arduino-code......

Wat moeten we programmeren?
1. Allereerst een aanname: er is een variabele van 8 bits, genaamd CODE
Code: Alles selecteren
byte CODE;

void setup(){
}

void loop(){
}


2. We maken een string-array aan, die alle WINDRICHTINGEN op volgorde van de bovenstaande tabel heeft.
Code: Alles selecteren
byte CODE;
String windrichtingen[] = {
  O, W, OW, Z, ZO, ZW, ZWO, N, NO, NW, NWO, NZ, NZO, NZW, NZWO };

void setup(){
}

void loop(){
}


3. Nu moeten we de CODE veranderen in een WINDRICHTING. Ik maak hiervoor een eigen functie, die ik CnWR() noem (Acroniem voor Code naar WindRichting)
Code: Alles selecteren
byte CODE;
String windrichtingen[] = {"O", "W", "OW", "Z", "ZO", "ZW", "ZWO", "N", "NO", "NW", "NWO", "NZ", "NZO", "NZW", "NZWO" };

void setup(){
}

void loop(){
}

String CnWR(byte deWaardeVan_CODE){
  byte WR;
 
  return (windrichtingen[WR]);
}


Er gebeurt nu nog niks. De loop is leeg en de CnWR functie heeft alleen een INTERNE variabele WR en deWaardeVan_CODE.
Met deze twee ingredieneten gaan we verder koken.

4. We moeten van deWaardeVan_CODE naar WR, die aangeeft welke string uitgeprint moet worden.
Omdat de windrichtingen op volgorde liggen, hoeven we alleen na te bootsen wat we hierboven hebben gedaan.

A. De eerste 4 bits moeten we eraf hakken
B. De overgebleven bits veranderen we de nullen in enen.
==> als het goed is, hebben we dan WR te pakken.

Code: Alles selecteren
byte CODE;
String windrichtingen[] = {"WINDSTIL", "O", "W", "OW", "Z", "ZO", "ZW", "ZWO", "N", "NO", "NW", "NWO", "NZ", "NZO", "NZW", "NZWO" };

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

void loop(){
  for(CODE=0;CODE<16;CODE++){
    Serial.println(CnWR(CODE));
  }
  while(1);
}

String CnWR(byte deWaardeVan_CODE){
  byte WR;
  WR = deWaardeVan_CODE & B00001111;
  WR = WR ^ B00001111;
  return (windrichtingen[WR]);
}


In de loop loopt een teller van 0 naar 16. Omdat dit dus met 0000 begint = alle knopje ingedrukt, geeft de sketch onderstaande output
NZWO
NZW
NZO
NZ
NWO
NW
NO
N
ZWO
ZW
ZO
Z
OW
W
O
WINDSTIL

Zoals je ziet: alle windrigtingen,
= alle knoppen ingedrukt,
= CODE = 0
= laatste string in array, omdat je met de XOR alle nullen in enen omzet.

Nog even deze toelichten:
WR = deWaardeVan_CODE & B00001111;
WR = WR ^ B00001111;


Met de eerste opdracht zeg ik dat van alle 8 bits, alleen die bits doormogen, die beiden aanstaan. Daarmee vallen de de eerste 4 bits (van links gezien) af.
Met de tweede opdracht wordt de XOR uitgevoerd op de laatste vier bits.

Ik hoop dat het helpt.
groet,
paul

Berichten: 68
Geregistreerd: 28 Aug 2012, 15:14

Re: werken met binaire waardes

Berichtdoor Nald » 19 Dec 2012, 20:26

Jeetje wat een uitleg, maar om heel eerlijk te zijn snap ik er niet veel van. Toevallig heb ik hem ook op een ander form geplaatst en daar kreeg ik onderstaande oplossing. Wat is het verschil?

Code: Alles selecteren
void loop()
{
  int x = readNes(); // dit weet je blijkbaar hoe dat moet

   x = ~x; // klap alle bitje om 0->1 en vice versa

  if ( x & b00000001) Serial.println("Right");
  if ( x & b00000010) Serial.println("Left");
  if ( x & b00000100) Serial.println("Down");
  if ( x & b00001000) Serial.println("Up");
  if ( x & b00010000) Serial.println("Start");
  if ( x & b00100000) Serial.println("Select");
  if ( x & b01000000) Serial.println("B");
  if ( x & b10000000) Serial.println("A");
}

Gebruikers-avatar
Berichten: 700
Geregistreerd: 05 Mrt 2012, 21:56
Woonplaats: Appingedam

Re: werken met binaire waardes

Berichtdoor pjh » 20 Dec 2012, 07:59

Bovenstaande code is omslachtig en beantwoord je vraag niet. Het bevat precies de if...then structuur die je niet wilde ( in je eerste bericht) en levert je niet mee knoppen combi's op.

Berichten: 68
Geregistreerd: 28 Aug 2012, 15:14

Re: werken met binaire waardes

Berichtdoor Nald » 20 Dec 2012, 14:15

De bedoeling is niet dat ik meer knopfuncties krijg, maar dat ik kan zien of ik 2 knoppen indruk of 1 en welke 2 ik indruk

bv 10101111. hoe haal ik hieruit dat B en start is ingedrukt, zonder dat ik alle mogelijkheden moet uitschrijven.

Gebruikers-avatar
Berichten: 700
Geregistreerd: 05 Mrt 2012, 21:56
Woonplaats: Appingedam

Re: werken met binaire waardes

Berichtdoor pjh » 20 Dec 2012, 21:05

Je laatste code doet precies dat. Immers:

10101111 wordt 01010000 door x = ~x;

Vervolgens wordt 01010000 vergeleken met alle knopjes. Waarbij

B01010000 & B00010000 = waar, dus Serial.println("Start");
B01010000 & B01000000 = waar dus Serial.println("B");

de rest is onwaar en print niet.
Output zal dus

Start
B

Zijn...

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: owuaozono, RussellAlets en 28 gasten