Ich entwickle gerade einen Roboter, der einen 2x2x2 Rubic Cube löst. Dies ist eine Sammlung von Kommentaren zum Roboterprogramm. Ich habe einmal eine Sammlung von Artikeln geschrieben, die durch den Artikel [hier] repräsentiert werden (https://qiita.com/Nyanyan_Cube/items/60f3699db96dba4a4bf5), aber seitdem wurde die Software erheblich aktualisiert, sodass ich ein neues Programm einführen werde. Überlegen.
Der entsprechende Code ist hier verfügbar [https://github.com/Nyanyan/soltvvo/tree/master/Soltvvo3.2].
"Lass uns einen Roboter bauen, der den Zauberwürfel löst!"
Aktualisierte Software für Rubik Cube Robot
Dieses Mal werden wir `` `soltvvo3_arduino.ino``` als Edition für Maschinenbedienung (Arduino) einführen.
Global platzierte Konstanten und Variablen.
const int magnet_threshold = 50;
const long turn_steps = 400;
const int step_dir[2] = {11, 9};
const int step_pul[2] = {12, 10};
const int sensor[2] = {14, 15};
const int grab_deg[2] = {74, 74};
const int release_deg[2] = {96, 96};
const int offset = 3;
char buf[30];
int idx = 0;
long data[3];
Die Konstante ist die Portnummer oder der Winkel des Servomotors. Variablen werden verwendet, um die angegebenen Werte zu teilen, indem sie durch Leerzeichen getrennt werden.
Schließen Sie die Servobibliothek in Bezug auf die Verwendung des Servomotors ein und definieren Sie `` `servo0, servo1```.
#include <Servo.h>
Servo servo0;
Servo servo1;
Installieren.
void setup() {
Serial.begin(115200);
for (int i = 0; i < 2; i++) {
pinMode(step_dir[i], OUTPUT);
pinMode(step_pul[i], OUTPUT);
pinMode(sensor[i], INPUT);
}
servo0.attach(7);
servo1.attach(8);
servo0.write(release_deg[0] + 5);
servo1.write(release_deg[1] + 5);
delay(70);
servo0.write(release_deg[0]);
servo1.write(release_deg[1]);
}
Definieren Sie Pin-Ein- und Ausgänge und bewegen Sie den Servomotor, um den Arm nach außen zu bewegen.
Es ist eine Funktion, die den Schrittmotor dreht. Ich habe ein trapezförmiges Laufwerk implementiert, aber aus diesem Grund ist es eine etwas uncoole Implementierung, die `` `delay``` ohne Verwendung von Timern usw. verwendet.
void move_motor(long num, long deg, long spd) {
bool hl = true;
if (deg < 0) hl = false;
digitalWrite(step_dir[num], hl);
long steps = abs(deg) * turn_steps / 360;
long avg_time = 1000000 * 60 / turn_steps / spd;
long max_time = 1500;
long slope = 50;
bool motor_hl = false;
long accel = min(steps / 2, max(0, (max_time - avg_time) / slope));
int num1 = (num + 1) % 2;
//Beschleunigung
for (int i = 0; i < accel; i++) {
motor_hl = !motor_hl;
digitalWrite(step_pul[num], motor_hl);
delayMicroseconds(max_time - slope * i);
}
//Normale Operation
for (int i = 0; i < steps * 2 - accel * 2; i++) {
motor_hl = !motor_hl;
digitalWrite(step_pul[num], motor_hl);
delayMicroseconds(avg_time);
}
//Verlangsamen
for (int i = 0; i < accel; i++) {
motor_hl = !motor_hl;
digitalWrite(step_pul[num], motor_hl);
delayMicroseconds(max_time - slope * accel + accel * (i + 1));
}
}
Grundsätzlich wird es nach folgendem Ablauf verarbeitet.
Kalibrieren Sie den Teil des Arms, der den Schrittmotor verwendet, so, dass er einen geeigneten Winkel hat. Verwenden Sie zu diesem Zeitpunkt den an der Armseite angebrachten Magneten und den an der Seite des Schrittmotors angebrachten Hallsensor (Magnetsensor).
void motor_adjust(long num, long spd) {
int max_step = 150;
int delay_time = 800;
bool motor_hl = false;
digitalWrite(step_dir[num], LOW);
while (analogRead(sensor[num]) <= magnet_threshold) {
motor_hl = !motor_hl;
digitalWrite(step_pul[num], motor_hl);
delayMicroseconds(delay_time);
}
while (analogRead(sensor[num]) > magnet_threshold) {
motor_hl = !motor_hl;
digitalWrite(step_pul[num], motor_hl);
delayMicroseconds(delay_time);
}
}
Die erste `` `while``` -Anweisung ist schwierig, aber selbst wenn bereits festgestellt wurde, dass sich der Arm in der richtigen Position befindet, kann der Winkel des Arms leicht abweichen, sodass der Arm einmal verschoben wird. ..
Die zweite `` `while``` -Anweisung dreht den Schrittmotor, bis sich der Magnet vor dem Hallsensor befindet.
Eine Funktion, die den Arm nach außen bewegt und das Rätsel löst.
void release_arm(int num) {
if (num == 0)servo0.write(release_deg[num] + offset);
else servo1.write(release_deg[num] + offset);
}
Es ist keine sehr schöne Art zu schreiben. Wenn Sie wissen, wie man schön schreibt, lassen Sie es mich bitte wissen. Für `Offset``` habe ich ein Überschwingen implementiert, um den Motor schneller zu bewegen, aber ich habe festgestellt, dass es nicht notwendig ist, beim Überschießen zum Zielwert zurückzukehren, und mit`
Offset``` hinzugefügt. Es ist geworden.
Es ist eine Funktion, die den Arm um die Mitte bewegt und das Puzzle greift.
void grab_arm(int num) {
if (num == 0)servo0.write(grab_deg[num] - offset);
else servo1.write(grab_deg[num] - offset);
delay(70);
if (num == 0)servo0.write(grab_deg[num]);
else servo1.write(grab_deg[num]);
}
Das mit `offset
erzeugte Überschwingen ist hier nützlich. Ich hoffe, das hilft dir dabei, das Rätsel schneller zu lösen (ich weiß nicht, wie effektiv es wirklich ist).
Die Hauptschleife empfängt den Befehl und ruft die entsprechende Funktion auf.
void loop() {
while (1) {
if (Serial.available()) {
buf[idx] = Serial.read();
if (buf[idx] == '\n') {
buf[idx] = '\0';
data[0] = atoi(strtok(buf, " "));
data[1] = atoi(strtok(NULL, " "));
data[2] = atoi(strtok(NULL, " "));
if (data[1] == 1000) grab_arm(data[0]);
else if (data[1] == 2000) release_arm(data[0]);
else if (data[1] == 0) motor_adjust(data[0], data[2]);
else move_motor(data[0], data[1], data[2]);
idx = 0;
}
else {
idx++;
}
}
}
}
Die aufzurufende Funktion hängt von der Art des Befehls ab.
Dieses Mal habe ich das Arduino-Programm vorgestellt, das den Aktuator tatsächlich bewegt. Ich denke, es ist teilweise unrein, wahrscheinlich wegen meiner mangelnden Sprachkenntnisse. Bitte geben Sie uns eine gute Möglichkeit, in die Kommentare zu schreiben.
Nächstes Mal werde ich die Hauptverarbeitung von Python erklären.
Recommended Posts