Kne'x Rubiks Cube Solver
1 Wat gaat het doen?
Ik wil een Rubik's Cube 3x3x3 oplosser gaan maken. Die moet als volgt gaan werken: eerst geeft je aan de computer aan welke kleuren waar zitten, de computer maakt hier dan vervolgens een 3D model van en lost hem op. Daarna geeft hij aan de Arduino door welke handelingen gedaan moeten worden, waarop de Arduino de motoren aan stuurt zodat de kubus draait. De bedoeling is dus dat, zodra hij af is, hij een gescrabbelde kubus zonder hulp kan oplossen wanneer je deze erin zet. Een Rubik's Cube oplosser heeft minimaal 3 handjes nodig en een ondersteuning die weg gehaald kan worden om alle vlakken te kunnen draaien, dit zijn dus minimaal 5 motortjes die zowel linksom als rechtsom moeten kunnen.
2 In welke stappen ga ik werken?
Constructie, die de motoren en de kubus ondersteunt.
Mechanisch, dit zijn de motoren en de tandwielen die de kubus moeten draaien, en het klemmen van een ronde naar een rechte beweging moeten overbrengen.
Elektrisch, De motoren moeten worden aangesloten, evenals het printplaatje.
Arduino, Die zorgt dat hij alle nodige handelingen verricht als er een vlak gedraaid moet worden.
Computer, Die de kubus oplost en de Arduino vertelt welk vlak er gedraaid moet worden om de kubus op te lossen.
Mechanisch, dit zijn de motoren en de tandwielen die de kubus moeten draaien, en het klemmen van een ronde naar een rechte beweging moeten overbrengen.
Elektrisch, De motoren moeten worden aangesloten, evenals het printplaatje.
Arduino, Die zorgt dat hij alle nodige handelingen verricht als er een vlak gedraaid moet worden.
Computer, Die de kubus oplost en de Arduino vertelt welk vlak er gedraaid moet worden om de kubus op te lossen.
3 Hoe je een Rubik's Cube kan draaien, en hoe dit heet
4 Het proces
4.1 Constructie
De
constructie word nu merendeels gemaakt van K'nex, omdat dit gewoon
makkelijk te hanteren is. Alleen de vingers worden gemaakt van
aluminium. De constructie is er puur om alles bij elkaar te houden.
4.2 Mechanisch
Er
moesten nog wat dingen uitgevonden worden bijvoorbeeld hoe de
draaibeweging in een rechte beweging moest worden omgezet.
4.3 De opbouw van de motoren
Het onderstel van de motor (Hier rechts afgebeeld)
word van K'nex gemaakt, zodat het makkelijk gemaakt kan worden.
Door middel van 2 tandwielen word de draaiende
beweging van de as gehaald, en kan er op een andere plaats (Onder de
motor) door middel van een potmeter gekeken worden in welke stand de
“Vinger” staat.
De vinger word gemaakt van aluminium en wordt aan
het uiteinde van het rode stokje gemonteerd, dat zowel met het blauwe
tandwiel als met de motor is verbonden.
4.3.2 De Linker en rechter motor
De
linker en rechter motorarm kunnen, zoals u hier ziet op de foto, heen
en weer. De Rubik's Cube wordt tussen deze 2 armen gedaan. Tijdens de
hele oplosfase blijft hij klemmen en verandert hij dus niet. Hij
hoeft dus alleen heen en weer te kunnen om de kubus te kunnen
plaatsen of weg te halen.
De
kubus zit aan de bovenste arm (Oranje). Deze wordt met 2
verschillende tandwielen over gedragen naar de potmeter (Rood).
Hierdoor kan ik de stand van een vlak van de Rubik's Cube met de
potmeter berekenen.
Het eindresultaat van
deze arm, met de motor weggelaten. Deze komt op de grijze stukjes in
het midden tussen de 2 witte ringen.
4.4 Elektrisch
4.4.1 Mijn eigen motoren
Ik
heb 2 draadjes aan de contacten van de motor, waar normaal de
batterijen aan zitten, gesoldeerd, zodat als ik hier stroom opzet de
motor gaat draaien.
4.4.2 Nep batterijen voor in de geleende motoren
Ik heb ook van vrienden motoren geleend, die niet willen dat de motor word omgebouwd. Hiervoor heb ik nep batterijen gemaakt, deze gaan op de plek waar normaal de batterijen gaan.
4.4.2.1 De Nep batterijen
4.4.2.2 Het klepje hiervoor
Alles word vervolgens afgedekt door een klepje. Aan dit klepje zit ook een kroonsteentje voor het makkelijk los en vast maken van de motoren. Dit alles word vastgehouden door een schroefje die op de plek zit waar deze vroeger ook zat (en een beetje plakband omdat anders het moertje kapot gaat).
4.4.2.3 Het geheel
Het geheel van de nep batterijen en het klepje zie je hier links, deze motor is klaar om in de Rubik's Cube Solver gebruikt te worden. De motor kabeltjes hoeven alleen aangesloten te worden.
4.4.2 De printplaat
4.4.2.1 De ompolers
4.4.2.2 De Transistor
4.5 Arduino
Waar heb ik welke poorten voor nodig?
Links (L)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
Voor (F)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
Rechts (R)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
Voor Klamp (FC)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
Links (L)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
Voor (F)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
Rechts (R)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
Voor Klamp (FC)
Links / rechts draaien
Snelheid van het draaien
Potentiaal meter (Analoge Ingang)
4.5.1 Wat de pc doorgeeft aan de Arduino om vlakken te draaien
Front =
F
Front inverse = Fi
Left = L
Left inverse = Li
Right = R
Right inverse = Ri
Up = F-los, (RLi) F-klemmen F F-los (RiL) F-klemmen
Up inverse = F-los, (RLi) F-klemmen Fi F-los (RiL) F-klemmen
Down = F-los, (RiL) F-klemmen F F-los (RLi) F-klemmen
Down inverse = F-los, (RiL) F-klemmen Fi F-los (RLi) F-klemmen
Back = F-los, (R2L2) F-klemmen F F-los (R2L2) F-klemmen
Back inverse = F-los, (R2L2) F-klemmen F F-los (R2L2) F-klemmen
Front inverse = Fi
Left = L
Left inverse = Li
Right = R
Right inverse = Ri
Up = F-los, (RLi) F-klemmen F F-los (RiL) F-klemmen
Up inverse = F-los, (RLi) F-klemmen Fi F-los (RiL) F-klemmen
Down = F-los, (RiL) F-klemmen F F-los (RLi) F-klemmen
Down inverse = F-los, (RiL) F-klemmen Fi F-los (RLi) F-klemmen
Back = F-los, (R2L2) F-klemmen F F-los (R2L2) F-klemmen
Back inverse = F-los, (R2L2) F-klemmen F F-los (R2L2) F-klemmen
4.5.2 Codes die ik gebruik voor het oplossen
Het
oplossen van een kubus is, als je alleen maar na denkt, heel
moeilijk. Daarom bestaan er algoritmes. Deze algoritmes verwisselen
van te voren bekende blokjes. Zo wordt het oplossen een stuk
gemakkelijker. Ik heb deze dan in de computer geprogrammeerd, en
wanneer hij ze moet toepassen. Er zijn veel soorten en sets met
algoritmen, dit zijn degenen die ik heb gebruikt.
www.jellewie.weebly.com/3x3x3
www.jellewie.weebly.com/3x3x3
4.7.2 Het oplossen
4.5.3 Potmeter motor experiment
Ik
heb een test opgezet om twee dingen te leren: het werken met de
Arduino zelf, maar ook hoe deze de gegevens van de potmeter uitleest
en met deze informatie de motoren aanstuurt. De bedoeling van deze
test is dat je een potmeter draait. Met de gegevens van een andere
potmeter draait de motor naar dezelfde stand als jij; draai jij naar
90º naar links, gaat de motor ook 90º naar links.
De potmeters zijn aangesloten op A0 en A1. Dit zijn analoge poorten, hiermee kan ik op schaal van 0-1023 (1024 standen) uitlezen. De motorsnelheid staat op pin 11 met een schaal van 0-255 (256 standen). De links rechts is aangesloten op pin 13, dit is een analoge output in verband met dat ik er alleen aan en uit voor gebruik.
De potmeters zijn aangesloten op A0 en A1. Dit zijn analoge poorten, hiermee kan ik op schaal van 0-1023 (1024 standen) uitlezen. De motorsnelheid staat op pin 11 met een schaal van 0-255 (256 standen). De links rechts is aangesloten op pin 13, dit is een analoge output in verband met dat ik er alleen aan en uit voor gebruik.
De
Arduino code
int
PinPot1 = 1; // Vertel waar potmeter 1 analoog aangesloten zit
int PinPot2 = 0; // Vertel waar potmeter 2 analoog aangesloten zit
int LinksRechts = 13; // Vertel waar de links rechts schakelaar zit
int AanUit = 11; // Vertel waar de aan en uit zit
int Speed = 0; // Namen aan nummers koppelen, zodat je weet wat je doet
int Graden = 0;1
int GaNaarGraden = 0;
int Afwijking = 0;
void setup() {
Serial.begin(9600); // Data verbinding met computer starten
pinMode(LinksRechts, OUTPUT); // Vertel dat de LingsRechts (Pin 13) een uitgang is
}
void loop() {
Graden = analogRead(PinPot1); // Lees potmeter 1
GaNaarGraden = analogRead(PinPot2); // Lees potmeter 2
Graden = map(Graden, 0, 1023, 0, 255); // Herschaal potmeter 1 naar 0-255
GaNaarGraden = map(GaNaarGraden, 0, 1023, 0, 255); // Herschaal ook potmeter 2
Afwijking = GaNaarGraden - Graden; // Bereken de afwijking tussen 1 en 2
Speed = Afwijking ; // Hoe groter de afwijking hoe meer snelheid
if (Speed < -1) { // Bekijk of de afwijking links of rechts is
TEMPLinksRechts = 1;
} else if (Speed >1){
TEMPLinksRechts = 2;
}
Speed = abs (Speed); // Zorg dat motor speheid altijd positief is
if (Speed < 10) { Speed = 0; } // Als motor er bijna is stop hem
else Speed = Speed + 70; // minimale stroom
if (Speed > 150) { Speed = 150; } // Maximale stroom
analogWrite(AanUit, Speed); // Geef de motor stroom
delay(100) // vertraging zodat hij niet onnodig herberekend
}
int PinPot2 = 0; // Vertel waar potmeter 2 analoog aangesloten zit
int LinksRechts = 13; // Vertel waar de links rechts schakelaar zit
int AanUit = 11; // Vertel waar de aan en uit zit
int Speed = 0; // Namen aan nummers koppelen, zodat je weet wat je doet
int Graden = 0;1
int GaNaarGraden = 0;
int Afwijking = 0;
void setup() {
Serial.begin(9600); // Data verbinding met computer starten
pinMode(LinksRechts, OUTPUT); // Vertel dat de LingsRechts (Pin 13) een uitgang is
}
void loop() {
Graden = analogRead(PinPot1); // Lees potmeter 1
GaNaarGraden = analogRead(PinPot2); // Lees potmeter 2
Graden = map(Graden, 0, 1023, 0, 255); // Herschaal potmeter 1 naar 0-255
GaNaarGraden = map(GaNaarGraden, 0, 1023, 0, 255); // Herschaal ook potmeter 2
Afwijking = GaNaarGraden - Graden; // Bereken de afwijking tussen 1 en 2
Speed = Afwijking ; // Hoe groter de afwijking hoe meer snelheid
if (Speed < -1) { // Bekijk of de afwijking links of rechts is
TEMPLinksRechts = 1;
} else if (Speed >1){
TEMPLinksRechts = 2;
}
Speed = abs (Speed); // Zorg dat motor speheid altijd positief is
if (Speed < 10) { Speed = 0; } // Als motor er bijna is stop hem
else Speed = Speed + 70; // minimale stroom
if (Speed > 150) { Speed = 150; } // Maximale stroom
analogWrite(AanUit, Speed); // Geef de motor stroom
delay(100) // vertraging zodat hij niet onnodig herberekend
}
4.5.4 Commando experiment
Bestuur
door middel van seriële signalen de Arduino aan. Als je bijvoorbeeld
“L” stuurt leest de Arduino dit als “76” en geeft vervolgens
de tekst “Left” terug. Dit kan ik later gebruiken om vanaf de
computer bewegingen aan te sturen.
De
Arduino code
int ReadIncomming_1 = 0; // Namen aan nummers koppelen
int ReadIncomming_2 = 0;
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
if (Serial.available() > 0) { // Voer alleen uit als er iets gestuurd word
ReadIncomming_1 = Serial.read(); // Lees het commando 1 en onthou het
ReadIncomming_2 = Serial.read(); // Lees het commando 2 en onthou het
if (ReadIncomming_1 == 76) { // Als 1 = L
if (ReadIncomming_2 == 105) { // Als 1=L & 2= i
Serial.print("Left Inverse"); // Geef "Left Inverse" als feedback
} else if (ReadIncomming_2 == 82) { // Als 1=L & 2= R
Serial.print("Left + Right Inverse"); // Geef "Left + Right Inverse" als feedback
} else // Als 1=L & 2= ?
Serial.print("Left"); // Geef "Left" als feedback
} else if (ReadIncomming_1 == 70) { //Als 1 = F
if (ReadIncomming_2 == 105) { // Als 1=F & 2= i
Serial.print("Front Inverse"); // Geef "Front Inverse" als feedback
} else // Als 1=F & 2= ?
Serial.print("Front"); // Geef "Front" als feedback
} else if (ReadIncomming_1 == 82) { //Als 1 = R
if (ReadIncomming_2 == 105) { // Als 1=R & 2= i
Serial.print("Right Inverse"); // Geef "Right Inverse" als feedback
} else if (ReadIncomming_2 == 76) { // Als 1=R & 2= L
Serial.print("Right + Left Inverse"); // Geef "Right + Left Inverse" als feedback
} else // Als 1=R & 2= ?
Serial.print("Right"); // Geef "Right" als feedback
}
}
delay(100); // vertraging zodat hij niet onnodig herberekend
}
int ReadIncomming_2 = 0;
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
if (Serial.available() > 0) { // Voer alleen uit als er iets gestuurd word
ReadIncomming_1 = Serial.read(); // Lees het commando 1 en onthou het
ReadIncomming_2 = Serial.read(); // Lees het commando 2 en onthou het
if (ReadIncomming_1 == 76) { // Als 1 = L
if (ReadIncomming_2 == 105) { // Als 1=L & 2= i
Serial.print("Left Inverse"); // Geef "Left Inverse" als feedback
} else if (ReadIncomming_2 == 82) { // Als 1=L & 2= R
Serial.print("Left + Right Inverse"); // Geef "Left + Right Inverse" als feedback
} else // Als 1=L & 2= ?
Serial.print("Left"); // Geef "Left" als feedback
} else if (ReadIncomming_1 == 70) { //Als 1 = F
if (ReadIncomming_2 == 105) { // Als 1=F & 2= i
Serial.print("Front Inverse"); // Geef "Front Inverse" als feedback
} else // Als 1=F & 2= ?
Serial.print("Front"); // Geef "Front" als feedback
} else if (ReadIncomming_1 == 82) { //Als 1 = R
if (ReadIncomming_2 == 105) { // Als 1=R & 2= i
Serial.print("Right Inverse"); // Geef "Right Inverse" als feedback
} else if (ReadIncomming_2 == 76) { // Als 1=R & 2= L
Serial.print("Right + Left Inverse"); // Geef "Right + Left Inverse" als feedback
} else // Als 1=R & 2= ?
Serial.print("Right"); // Geef "Right" als feedback
}
}
delay(100); // vertraging zodat hij niet onnodig herberekend
}
4.7 Computer
De
computer verzameld alle data en rekent uit welke draaien er aan de
kubus gedaan moeten worden om deze op te lossen. Het programma geeft
vervolgens elke keer een stap door aan de Arduino via een seriële
verbinding. De Arduino geeft een signaaltje terug als deze op de
doorgeven stand is beland, zodat de computer de volgende stand door
kan geven.
De
interface van het programma is hieronder afgebeeld, met op de
volgende pagina de gehele uitleg van wat alle knoppen en dingen doen.
4.7.1 Interface van het oplos programma
4.7.3 De seriële verbinding
De
Computer stuurt in ASCII, (een 7 Bit computer communicatie taal) een
signaal naar de Arduino. Dit signaal bestaat uit 4 cijfers.
De volgorde en betekenis hiervan is als volgt:
[1e] 0/1 De stand van de klem op F
[2e] 0/1/2/3 De positie van L
[3e] 0/1/2/3 De positie van F
[4e ]0/1/2/3 De positie van R (# * 90 = Graden)
Als de Arduino start staat hij op 1111, dit houd in dat hij geklemd is, en alle motoren op stand 1 (90 graden) staan.
De volgorde en betekenis hiervan is als volgt:
[1e] 0/1 De stand van de klem op F
[2e] 0/1/2/3 De positie van L
[3e] 0/1/2/3 De positie van F
[4e ]0/1/2/3 De positie van R (# * 90 = Graden)
Als de Arduino start staat hij op 1111, dit houd in dat hij geklemd is, en alle motoren op stand 1 (90 graden) staan.
4.8 De adapter
De
Arduino heeft 250mA nodig. Dit haalt hij gewoon uit de communicatie
kabel, omdat deze toch altijd aangesloten moet zijn om te werken. De
motoren die ieder 300mA zijn als ze op volle toeren draaien kunnen
echter de stroom niet uit zo'n kabel halen. Deze stroom komt voor hen
uit een externe 5V voeding. De motoren zullen nooit de volle 4 *
300mA = 1200mA nodig hebben, omdat de motoren nooit allemaal tegelijk
op volle toeren zullen draaien.
5 Testen en afstellen
Voor het eiken, testen en afstellen van de motoren heb ik een ander programma geschreven. Hier kun je met behulp van knoppen de motor posities bedienen.
Voor het afstellen zet je de motor en het programma gelijk. Dus als hij op de computer op stand 3 staat, moet dat ook in het echt het geval zijn.
Als je op de knoppen met nummers drukt, beweegt de daarbij behorende motor (zie plaatje bij 4.7.3)
Het gekleurde vlak kan een aantal kleuren hebben;
Groen = hij staat op de aangegeven positie
Orange = Draaien naar die positie
Blauw = Een Correctie word uitgevoerd
Rood = Fout bij het ontvangen
Voor het afstellen zet je de motor en het programma gelijk. Dus als hij op de computer op stand 3 staat, moet dat ook in het echt het geval zijn.
Als je op de knoppen met nummers drukt, beweegt de daarbij behorende motor (zie plaatje bij 4.7.3)
Het gekleurde vlak kan een aantal kleuren hebben;
Groen = hij staat op de aangegeven positie
Orange = Draaien naar die positie
Blauw = Een Correctie word uitgevoerd
Rood = Fout bij het ontvangen
6 Aanpassingen, Wat ging en moest er anders dan gedacht?
- De kubus moest niet alleen door 2 vingers en een ondersteun worden vastgehouden, want op deze manier zou je niet alle kanten kunnen draaien. Daarom moet hij aangepast worden zodat hij minimaal 3 vingers heeft om hem te draaien, want als links en rechts samen draaien, draait de hele kubus om, waardoor je bij de andere vlakken kan.
- De vingers die de kubus draaien moeten door een potmeter gemeten worden, zodat de weerstand van de potmeter kan worden omgezet naar graden in de Arduino zodat hij weet hoeveel graden de motor moet draaien.
- De stokjes van de vingers moesten langer en met tandwielen zodat ik met een potmeter de stand van de vingers kon bepalen.
-
Over het elektische gedeelte moest ik toch veel meer schijven dan
dat ik verwachtte, deels omdat het printplaatje hier natuurlijk ook
onder valt, maar ook omdat ik nep batterijen heb gemaakt voor de
motoren, en mijn eigen motoren heb omgebouwd.
-
De Linker en rechter motor moesten anders, omdat hij niet met 3
aluminium vingers zoals ooit bedoeld de kubus goed kan vasthouden.
Hij valt er namelijk uit als hij een cube flip doet.
- Zoals hier rechts uitgebeeld, draait de arm 45 graden met de motor mee als deze die 45 graden naar links draait (zoals het rode stipje doet). Maar als je hem 45 graden terug draait, wijkt de arm z'n 20 graden af, terwijl het rode stipje wel de volledige 45 graden heeft gedaan. Hierdoor moest ik de Links en Rechtse beweging op de Arduino splitsen zodat ik kan zeggen dat hij +20 graden moet draaien als hij de andere kant op gaat.
- De camera functie was te hoog gegrepen. Maar dit is nog wel een leuk project voor later.
7 Download documentatie
Download het word bestand (bijna hetzelfde als deze pagina)
Visual basic Programma, of Alleen de .exe
Arduino Programma
Visual basic Programma, of Alleen de .exe
Arduino Programma
Powered by
JelleWie (Ikzelf)
K'nex (De opbouw)
Rubiks Cube (De kubus en het probleem)
Visual Basic (Het interface op de Computer & de oplosser)
Arduino (Die de motoren aanstuurt)
Accenda (Het bedrijf dat de tijd en ondersteuning leverde)
JelleWie (Ikzelf)
K'nex (De opbouw)
Rubiks Cube (De kubus en het probleem)
Visual Basic (Het interface op de Computer & de oplosser)
Arduino (Die de motoren aanstuurt)
Accenda (Het bedrijf dat de tijd en ondersteuning leverde)