Working on a simple RC car that is capable of propotional speed and steering control. I will be building the chassis of the car from LEGO technic and will be using LEGO Power Functions motors. For steering I am using a high-torque servo motor since the LEGO Power Functions servo motors move in steps.
I have converted an old pistol grip 2.4Ghz remote control to an Arduino Nano based remote control using a nRF24L01+ transceiver module and wired the throttle and steering pots to A0 and A1. The remote control is powered by the original 4xAA battery pack.
On the car I am using an Arduino Uno with another nRF24L01+ transceiver module for comminucation, a L298N H-bridge speed controller for controlling the motors speed and a servo motor for steering. The H-bridge and Arduino are powered by a 12v Li-Ion battery (probably later upgraded to a 14,8v Li-Ion battery for more speed.
I am able to establish a connection between the two Arduinos and have sucessfully loaded some codes from other creators to control the servo with the remote control.
Yet my knowledge of writing and understanding these codes is very limited and I have not found a code that works for my setup (combining servo steering and H-bridge speed control over nRF24 transmission).
Now I am in need of some help to complete the codes. I need the Servo to be set up for proportional steering and the motors set up for proportional speed control. Also I want to be able to calibrate and map my analog inputs.
Receiver / Car code:
/* Radio Receiver
Adeept UNO with Motor Shield V2
Radio module: nRF24L01 + PA + LNA with antenna built in -USE 3V !!!! built in, 5V is fine ONLY with shield or adaptor, or bypass capacitor, see specs
L298N - 7.4 V input - two 46850 batteries , use whatever you like .
Can be done with any pair of UNOs - Written by Gallax
L298N is grounded to Uno.
Servo pin 3 or P4 on Adeept shield
CE 9 CSN 10 for Adeept shield
////////////L298N CONNECTIONS ON ADEEPT SHIELD OR UNO ////////////////
IN1 IN2 IN3 IN4 SPD1 SPD2
8 7 2 4 5 6
I didnt use RF24 Adaptor, shield has one built in. So this is universal for Unos.
* * ////////////////////// RF24 Adaptor or use this pinout :) /
__________________________________
|| 3V || 10 || 11 || NC || NC - not connected.
|| VCC-||-CSN-||- MOSI-||- IRQ ||
||_____||_____||_______||_______||
|| GND-||-CE -||- SCK -||- MISO ||
|| GND || 9 || 13 || 12 ||
||_____||_____||_______||_______||
///////////////////////////Servo connection //////////////////////////
Servo is connected to 5V, GND, pin is 2 (search for servo.attach for reference)
Adeept shield requires pin 2 = P4 - yes this was quite a job.
*/
#include <SPI.h>
#include <nRF24L01.h> // include RF24 libraries
#include <RF24.h> // This will need some tweaking. Excellent job.
#include <Servo.h> // Include Servo library
Servo servo; // creates servo object to control servo
// twelve servo objects can be created on most boards
RF24 radio(9, 10); // CE, CSN
const uint64_t pipe = 0xE8E8F0F0E1LL; // sets channel
// const byte address[6] = "00001"; // alternative
int data[8]; // create dataset array 8 bit
int enA = 5; // speed control A
int in1 = 8; // Motor A connections
int in2 = 7;
int enB = 6; // speed control B
int in3 = 2; // Motor B connections
int in4 = 4;
int xDir = 90; // initial direction for servo later
////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600); // start serial monitor for debugging
radio.begin(); // starts the radio
radio.openReadingPipe(0, pipe); // sets this RF24 as receiver
radio.setPALevel(RF24_PA_MIN); // sets radio signal strength
radio.setDataRate(RF24_250KBPS); // sets datarate to 250 kbps
radio.startListening(); // starts listening for data
/// ///////////// Set all the motor control pins to outputs/////////////////
pinMode(enA, OUTPUT); // speed control motor A on L298N
pinMode(enB, OUTPUT); // speed control motor B on L298N
pinMode(in1, OUTPUT); // motor A output - will become forward high
pinMode(in2, OUTPUT); // motor A output - will become forward low
pinMode(in3, OUTPUT); // motor B output - will become forward high
pinMode(in4, OUTPUT); // motor B output - will become forward low
servo.attach(3); //sets servo pin to 2 = P4 on Adeept Shield
}
//////////////////LISTEN, READ, MAPPING AND PRINTING DATA////////////////////
void loop() {
radio.startListening(); // receiver starts listening
if (radio.available()) { // if the radio has connection
radio.read(&data, sizeof(data)); // read all in the dataset, sizeof is for numeric purposes
int x = map(data[1], 0, 1024, 0, 180); // creates integer x, maps data[0], 0 is the first integer i used for the array, other than starting at 1
int y = map(data[0], 0, 1024, 0, 255); // now data is next in line at 1.
// maps data from 0 - 1024 --- converted by me to 0 - n where n = 180 or 255
Serial.print("x:"); // serial print text for reading
Serial.println(data[0]); // (note only one with ln)print data, if fails, check connections. (note only one with ln)
Serial.print("y:"); //prints text
Serial.print(data[1]); // prints the next piece of data
Serial.print("\t"); // i dunno, youll see why i didnt change this
/////////////////////IF DATA RECEIVED - SERVO CONTROLS//////////////////////
if ( data[1] == 0 ) { // if data 0 is equal to 0. servo turns left
xDir = 180; // see unit circle
servo.write(xDir); // TURN
delay(15); // small wait
}
if ( data[0] > 600 ) { // if data is greater than or equal to 600
xDir = 0; // dir is 0
servo.write(xDir); // TURN
delay(15); // rinse repeat
}
if (data[0] == 329 or data[0] == 328 ) { // more if data for x axis, (steering)
xDir = 90; // 90 is straight
servo.write(xDir); // no turn
delay(15); // small wait
}
/////////////////////IF DATA RECEIVED - MOTOR CONTROLS///////////////////////
if ( data[0] >= 530 ) {
analogWrite(enA, 255);
analogWrite(enB, 255);
// Set motors to maximum speed
// For PWM maximum possible values are 0 to 255
// Turn on motor A & B
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW); // GO MOTORS!
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
}
/********************************************************************/
else {
analogWrite(enA, 0);
analogWrite(enB, 0);
digitalWrite(in1, LOW); // STOP MOTORS
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}
/////////////////////////////////////////////////////////////////////
if ( data[0] <= 500 ) {
analogWrite(enA, 255);
analogWrite(enB, 255);
digitalWrite(in1, LOW); // BACKWARDS MOTORS
digitalWrite(in2, HIGH); // if failed Check your wires, motor faces up (red wire on top)
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
}
/////////////////////////////////////////////////////////////////////
else { // waiting for connection, or NOT connected
} // delete this else statement if it becomes an eyesore
}
}
//////////////// END /////////////////
Transmitter / Remote control code:
/* Radio Transmitter
Elegoo Uno with starter kit shield.
nRF24L01 + PA + LNA with antenna - USE 3V!!! you can only use 5V with adaptor
i used a 9v battery directly into the Uno.
Can be done with any pair of UNOs - Written by Gallax
////////////////////////// Joystick connection /////////////////////////////
GND -
5V or 3V -
X out - A0
Y out - A1
SW(button)- NC - not connected
//////RF24 Adaptor or use this pinout directly into the Uno:) / ////////
__________________________________
|| 3V || 8 || 11 || NC || NC - not connected.
|| VCC-||-CSN-||- MOSI-||- IRQ || note: remember CE 7 CSN 8
||_____||_____||_______||_______||
|| GND-||-CE -||- SCK -||- MISO ||
|| GND || 7 || 13 || 12 ||
||_____||_____||_______||_______||
*/
#include <SPI.h>
#include <nRF24L01.h> // include RF24 libraries
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const uint64_t pipe = 0xE8E8F0F0E1LL; // set channel
// const byte address[6] = "00001"; // also sets channel
int xPin = A0; // integer for joystick, x axis, analog pin A0
int yPin = A1; // integer for joystick, y axis, analog pin A5
// int x;
// int y;
int data[8]; // forming datagroup, 8 bits is enough for car
//////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600); // start serial monitor for debugging
radio.begin(); // start radio
radio.openWritingPipe(pipe); // this is the controller
radio.setPALevel(RF24_PA_HIGH); // High power
radio.setDataRate(RF24_250KBPS); // data rate 250 kb/s
radio.stopListening(); // stops listening to transmit
}
/////////////////////////////////////////////////////////////////////////////
void loop() {
xPin = analogRead(A0) - 15; // read x pin from joystick + calibration offset potmeter
yPin = analogRead(A1) + 81; // read y pin from joystick + calibration offset potmeter
data[0] = xPin; // defines xPin which is A0 as data
data[1] = yPin; // defines yPin which is A1 as data
radio.write(&data, sizeof(data)); // write 8 bits of data to receiver
// no mapping required for transmitter
Serial.print("x:"); // text for debugging
Serial.println(data[0]); // prints data notice this value is print line
Serial.print("y:"); //print the values with to plot or view
Serial.print(data[1]); // prints the next piece of data
Serial.print("\t"); // i dunno it works
}