De opdracht was om een 'precarious' robot te creëren – een robot die, in mijn interpretatie, een gevoel van onzekerheid en onvoorspelbaarheid zou uitstralen. Om dit te bereiken, heb ik een robot gemaakt die opzettelijk 'grillig' is in zijn gedrag. Met een Arduino heb ik een robotje geprogrammeerd waarin de robot met een kans van 70% een commando negeert en met 30% kans uitvoert. De robot kan vier richtingen op (L, F, B, R) op basis van commando’s als 'L5' of 'F2', wat bijdraagt aan het onvoorspelbare en dynamische karakter.
Bibliotheken (#include):
#include <WiFi.h>: Deze regel importeert de bibliotheek die nodig is om verbinding te maken met een WiFi-netwerk. Hiermee kun je de Arduino verbinden met je thuis- of werknetwerk.
#include <WiFiUdp.h>: Deze bibliotheek is nodig voor UDP (User Datagram Protocol) communicatie via WiFi. UDP is een protocol voor het verzenden van berichten (packets), die niet gegarandeerd aankomen, maar dit maakt de communicatie snel.
#include <Servo.h>: Deze bibliotheek zorgt voor de aansturing van servo motoren. Je kunt er servo motoren mee positioneren op specifieke hoeken, die dan een bepaalde snelheid opleveren.
WiFi-instellingen:
const char* ssid = "x";
const char* password = "x";
Deze regels definiëren de constante strings voor de SSID (naam) en het wachtwoord van je WiFi-netwerk. Je moet de x hier vervangen door je eigen netwerknaam en wachtwoord.
Servo-objecten en -pinnen:
Servo leftServo;
Servo rightServo;
const int leftServoPin = 9;
const int rightServoPin = 10;
Hier worden objecten (leftServo en rightServo) gemaakt van de Servo klasse. Deze objecten gebruik je om de servo motoren aan te sturen. Ook worden de pins gedefinieerd waar de servo motoren op zijn aangesloten.
UDP-instellingen:
WiFiUDP Udp;
unsigned int localPort = 4210;
char incomingPacket[255];
WiFiUDP Udp;: Maakt een object aan voor de UDP-communicatie.
unsigned int localPort = 4210;: Specificeert de poort waarop de Arduino luistert naar UDP-berichten (4210 is een voorbeeld, je kunt dit aanpassen).
char incomingPacket[255];: Maakt een buffer aan om de inkomende berichten op te slaan.
Snelheidsinstellingen:
const int LEFT_FORWARD_SPEED = 0;
const int LEFT_BACKWARD_SPEED = 180;
const int RIGHT_FORWARD_SPEED = 180;
const int RIGHT_BACKWARD_SPEED = 0;
const int STOP_SPEED = 90;
Deze variabelen zijn constanten en definiëren de posities van de servo's die overeenkomen met vooruit, achteruit en stoppen. De exacte getallen kunnen variëren afhankelijk van de servo's die je gebruikt. Je kunt zelf experimenteren wat de juiste standen zijn voor jouw setup. De standen bepalen hoe de servo draait (snelheid en richting).
setup() functie:
void setup() {
Serial.begin(9600);
Serial.println("Verbinden met WiFi...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
// ... (rest van de setup code)
}
Serial.begin(9600);: Start seriële communicatie voor het printen van debug informatie.
Serial.println("Verbinden met WiFi...");: Print een bericht om aan te geven dat de verbinding met WiFi wordt gestart.
WiFi.begin(ssid, password);: Start de WiFi verbinding met de opgegeven ssid en password.
while (WiFi.status() != WL_CONNECTED) { ... }: Wacht tot de verbinding tot stand is gebracht.
delay(1000);: Wacht 1 seconde.
Serial.print(".");: Print een punt om te laten zien dat het nog steeds bezig is met verbinden.
Udp.begin(localPort);: Start de UDP server op het lokale poortnummer.
loop() functie:
int packetSize = Udp.parsePacket();
if (packetSize) {
int n = Udp.read(incomingPacket, 255);
if (n > 0) {
incomingPacket[n] = 0;
}
Serial.print("Ontvangen commando: ");
Serial.println(incomingPacket);
int packetSize = Udp.parsePacket();: Controleert of er een nieuw pakket is binnengekomen en slaat de grootte ervan op.
if (packetSize): Als er een pakket is ontvangen.
int n = Udp.read(incomingPacket, 255);: Leest de data in de buffer.
if (n > 0) { incomingPacket[n] = 0; }: Voegt een null-terminator (\0) toe aan het einde van de buffer om er een geldige C-string van te maken. Dit is nodig voor functies zoals atoi() die C-strings verwachten.
Serial.print(...) en Serial.println(...): Print debug informatie.
if (incomingPacket[0] == 'V') {
int duration = atoi(&incomingPacket[1]);
moveForward(duration);
// ... (andere commando's)
}
Hier wordt de ontvangen string gecontroleerd. incomingPacket[0] is de eerste letter die de actie aangeeft (V voor vooruit, A voor achteruit, etc.).
int duration = atoi(&incomingPacket[1]);: De functie atoi() (ASCII to integer) wordt gebruikt om het deel van de string na de eerste letter, die de duur in seconden aangeeft, om te zetten in een getal.
Bewegingsfuncties (moveForward, moveBackward, turnLeft, turnRight):
Deze functies stellen de servo's in op de juiste posities, zodat de robot beweegt of draait in de gewenste richting, voor de gespecificeerde tijd, en roepen vervolgens de stopfunctie aan.
stopMoving() functie:
Deze functie zet beide servo’s naar de stop positie en wacht een halve seconde zodat het volledig tot stilstand komt.
Arduino code:
#include <WiFi.h>
#include <WiFiUdp.h>
#include <Servo.h>
// WiFi-instellingen
const char* ssid = "x";
const char* password = "x";
// Maak servo-objecten voor beide servo's
Servo leftServo;
Servo rightServo;
// Definieer de pinnen voor de servo's
const int leftServoPin = 9; // Verander indien nodig
const int rightServoPin = 10; // Verander indien nodig
// UDP-instellingen
WiFiUDP Udp;
unsigned int localPort = 4210; // Lokale poort waarop de Arduino luistert
char incomingPacket[255]; // Buffer voor inkomende packets
// Snelheidsinstellingen
const int LEFT_FORWARD_SPEED = 0; // Pas dit aan voor linker servo snelheid
const int LEFT_BACKWARD_SPEED = 180;
const int RIGHT_FORWARD_SPEED = 180; // Pas dit aan voor rechter servo snelheid
const int RIGHT_BACKWARD_SPEED = 0;
const int STOP_SPEED = 90; // Stoppositie
void setup() {
Serial.begin(9600);
Serial.println("Verbinden met WiFi...");
// Verbind met WiFi-netwerk
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
// Verbinding is gemaakt
Serial.println("\nVerbonden met WiFi!");
// Toon het IP-adres
Serial.print("IP-adres: ");
Serial.println(WiFi.localIP()); // Toon het IP-adres
Udp.begin(localPort); // Begin met het luisteren naar UDP-pakketten op de lokale poort
Serial.print("Luisteren op UDP-poort ");
Serial.println(localPort);
// Verbind de servo's met hun pinnen
leftServo.attach(leftServoPin);
rightServo.attach(rightServoPin);
}
void loop() {
// Controleer of er een nieuw pakket is ontvangen
int packetSize = Udp.parsePacket();
if (packetSize) {
// Lees het pakket in
int n = Udp.read(incomingPacket, 255);
if (n > 0) {
incomingPacket[n] = 0; // Voeg een null-terminator toe
}
Serial.print("Ontvangen commando: ");
Serial.println(incomingPacket); // Gebruik println om de ontvangen gegevens weer te geven
// Verwerk de ontvangen commando's
if (incomingPacket[0] == 'V') { // Vooruit
int duration = atoi(&incomingPacket[1]); // Haal de tijd op
moveForward(duration);
} else if (incomingPacket[0] == 'A') { // Achteruit
int duration = atoi(&incomingPacket[1]); // Haal de tijd op
moveBackward(duration);
} else if (incomingPacket[0] == 'L') { // Links draaien
int duration = atoi(&incomingPacket[1]); // Haal de tijd op
turnLeft(duration);
} else if (incomingPacket[0] == 'R') { // Rechts draaien
int duration = atoi(&incomingPacket[1]); // Haal de tijd op
turnRight(duration);
} else {
Serial.println("Ongeldig commando. Gebruik V, A, L, of R gevolgd door de tijd.");
}
}
}
// Functie om vooruit te bewegen
void moveForward(int seconds) {
leftServo.write(LEFT_FORWARD_SPEED);
rightServo.write(RIGHT_FORWARD_SPEED);
delay(seconds * 1000);
stopMoving();
}
// Functie om achteruit te bewegen
void moveBackward(int seconds) {
leftServo.write(LEFT_BACKWARD_SPEED);
rightServo.write(RIGHT_BACKWARD_SPEED);
delay(seconds * 1000);
stopMoving();
}
// Functie om links te draaien
void turnLeft(int seconds) {
leftServo.write(LEFT_BACKWARD_SPEED);
rightServo.write(RIGHT_FORWARD_SPEED);
delay(seconds * 1000);
stopMoving();
}
// Functie om rechts te draaien
void turnRight(int seconds) {
leftServo.write(LEFT_FORWARD_SPEED);
rightServo.write(RIGHT_BACKWARD_SPEED);
delay(seconds * 1000);
stopMoving();
}
// Functie om te stoppen
void stopMoving() {
leftServo.write(STOP_SPEED);
rightServo.write(STOP_SPEED);
delay(500);
}
;
Code om de commando's uit te voeren:
import socket
# Vervang dit door het IP-adres van je Arduino
UDP_IP = "....."
UDP_PORT = 4210
# Maak een UDP-socket aan
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
command = input("Voer een commando in (bijv. 'V2' voor vooruit 2 seconden, 'A2' voor achteruit 2 seconden): ")
if command: # Zorg ervoor dat er een invoer is
sock.sendto(command.encode(), (UDP_IP, UDP_PORT))
print(f"Verzonden commando: {command}")
Videos: