In het eerste deel, september vorig jaar, heb ik beschreven wat ik wilde maken. Ik had toen nog niet alle motoren in huis, maar die zijn inmiddels lang geleden ontvangen. Vandaag ben ik er weer mee verder gegaan. Hieronder daarvan verslag: de uitvoering en de Arduino-code.

Hierboven de Arduino Nano met nRF24- en de joystickmodule die samen de afstandsbediening vormen.

En dan de robotwagen zelf. De mecanumwielen zijn gemarkeerd: L en R. Hierboven de L-gemarkeerde links en de R-gemarkeerde rechts geplaatst. Maar …. dan werkt het niet zoals het moet.

Hierboven de wielen geplaatst zoals het wel goed werkt. Aan de voorkant (boven in het plaatje) is het L-wiel links en het R-wiel rechts geplaatst. De achterwielen (dus onder in het plaatje) zijn onderling gewisseld: het R-wiel is links en het L-wiel is rechts geplaatst. Hiermee liggen alle zwarte rolletjes in de wielen overeenkomstig het schematische plaatje dat ook al in het vorige deel geplaatst is: zie hieronder.



Het bovenste deel van bovenstaand schema (waar de aansluitingen tussen de nRF24-module en de Arduino Nano uitgewerkt is) is van toepassing zowel op de besturingsmodule als op de wagen. Op de robotwagen is het de ontvanger, op de besturingsmodule de zender.
Software
Het aansturen van die radio-modules is eigenlijk heel simpel met de RF24-library. Er is maar weinig code voor nodig.
#include <SPI.h>
#include "printf.h"
#include "RF24.h"
RF24 radio(9,10);
const byte rxAddr[6] = "00001";
struct Data_Package {
int valx;
int valy;
// byte j1Button;
};
Data_Package data; //Create a variable with the above structure
void setup()
{
Serial.begin(9600);
Serial.print ("Robotwagen_besturing_2.ino");
radio.begin();
radio.setRetries(15, 15);
radio.openWritingPipe (rxAddr);
radio.setPALevel(RF24_PA_MIN);
radio.stopListening();
}
void loop()
{
//const char text[] = "Hello world";
data.valx = analogRead(A0);
data.valy = analogRead(A1);
radio.write(&data, sizeof(Data_Package));
//Serial.print("X = ");
//Serial.print(data.valx);
//Serial.print(" Y = ");
//Serial.println(data.valy);
//delay(1000); // slow transmissions down by 1 second
}
Nieuw voor mij was het struct-concept: het aanmaken van een pakketje te verzenden waardes. Aan de versturende kant en aan de ontvangende kant wordt die structuur bepaald en bekend gemaakt.
Hierboven zie je dat de struct “Data_Package” aangemaakt wordt voor opname van de x- en y-waarde van de joystick (evt. later nog aan te vullen met het resultaat van ingedrukte knoppen), dat de joystick vervolgens uitgelezen wordt (analogRead) en dat deze waardes in de “Data_Package” opgenomen worden.
struct Data_Package {
int valx;
int valy;
// byte Button1;
};
Data_Package data; //Create a variable with the above structure
Het pakketje wordt vervolgens door de nRF verstuurd: radio.write (&data, sizeof(Data_Package)).
/*
*
DRV8833-Dual-Motor-Driver-Module
*/
#include <RF24.h>
#include <SPI.h>
// 1e DRV8833 - fysiek rechts op de wagen
#define mLA2 2 // AIN1 motorLinksVoor1
#define mLA1 3 // AIN2 motorLinksVoor2
#define mRA2 4 // BIN1 motorRechtsVoor1
#define mRA1 5 // BIN2 motorRechtsVoor2
// 2e DRV8833 - fysiek links op de wagen
#define mLV2 A0 // AIN1 motorLinksAchter1
#define mLV1 A1 // AIN2 motorLinksAchter2
#define mRV2 A2 // BIN1 motorRechtsAchter1
#define mRV1 A3 // BIN2 motorRechtsAchter2
RF24 radio(9,10);
const byte rxAddr[6] = "00001";
struct Data_Package {
int valx;
int valy;
// byte Button1;
};
Data_Package data; //Create a variable with the above structure
void setup() {
SPI.begin();
Serial.begin(9600);
Serial.println ("Robotwagen_3.ino");
radio.begin();
radio.openReadingPipe(0, rxAddr);
radio.setPALevel(RF24_PA_MIN);
radio.startListening();
pinMode(mLV1,OUTPUT);
pinMode(mLV2,OUTPUT);
pinMode(mRV1,OUTPUT);
pinMode(mRV1,OUTPUT);
pinMode(mLA1,OUTPUT);
pinMode(mLA2,OUTPUT);
pinMode(mRA1,OUTPUT);
pinMode(mRA1,OUTPUT);
}
void loop() {
if (radio.available())
{
char text[32] = "";
radio.read(&data, sizeof(Data_Package));
Serial.print ("x waarde is ");
Serial.println (data.valx);
Serial.print ("y waarde is ");
Serial.println (data.valy);
if (data.valx >= 384 && data.valx <= 640 && data.valy <= 128){
Serial.println ("Vooruit!");
vooruit();
//resetData();
}
if (data.valx >= 384 && data.valx <= 640 && data.valy >= 896){
Serial.println ("Achteruit!");
achteruit();
//resetData();
}
if (data.valx <= 128 && data.valy >= 384 && data.valy <= 640){
Serial.println ("Linksaf!");
links();
//resetData();
}
if (data.valx >= 896 && data.valy >= 384 && data.valy <= 640){
Serial.println ("Rechtsaf!");
rechts();
//resetData();
}
if (data.valx > 896 && data.valy < 100){
Serial.println ("Schuin rechtsvoor!");
diag_rechts();
//resetData();
}
if (data.valx < 100 && data.valy < 200){
Serial.println ("Schuin linksvoor!");
diag_links();
//resetData();
}
if (data.valx < 100 && data.valy > 896){
Serial.println ("Schuin linksachter!");
diag_linksachter();
//resetData();
}
if (data.valx > 896 && data.valy > 896){
Serial.println ("Schuin rechtsachter!");
diag_rechtsachter();
//resetData();
}
if (data.valx >= 384 && data.valx <= 640 && data.valy >= 384 && data.valy < 640){
Serial.println ("Stop!");
//resetData();
stop();
}
//resetData();
}
}
void resetData(){
Serial.println ("Reset data");
data.valx = 512;
data.valy = 512;
// data.Button1 = LOW;
}
De wagen ontvangt het pakketje met x- en y-waardes radio.read(&data, sizeof(Data_Package)); en vervolgens wordt er bepaald wat er op basis van deze waardes gedaan moet worden: “welke richting moet ik uit!”
Voor elke richting (vooruit, achteruit, schuin-rechts-naar-voren, enz.) heb ik een procedure gemaakt. Hieronder de “procedure vooruit”.
void vooruit() {
digitalWrite(mLV1,HIGH);
digitalWrite(mLV2,LOW);
digitalWrite(mRV1,HIGH);
digitalWrite(mRV2,LOW);
digitalWrite(mLA1,HIGH);
digitalWrite(mLA2,LOW);
digitalWrite(mRA1,HIGH);
digitalWrite(mRA2,LOW);
}