Arduino Code Receiver_CODE 👇 /* Gadget Podda 2023.01.12 */ #include #include #include #define enA 10 // Arduino pin D9 - CH6 on PCB board - PWM output #define in1 2 // D8 - CH5 #define in2 3 // D7 - CH4 #define in3 4 // D6 - CH3 #define in4 5 // D4 - CH1 #define enB 6 // D5 - CH2 - PWM output RF24 radio(7, 8); // nRF24L01 (CE, CSN) const byte address[6] = "00001"; unsigned long lastReceiveTime = 0; unsigned long currentTime = 0; // Max size of this struct is 32 bytes struct Data_Package { byte j1PotX; byte j1PotY; }; Data_Package data; //Create a variable with the above structure int steering, throttle; int motorSpeedA = 0; int motorSpeedB = 0; void setup() { pinMode(enA, OUTPUT); pinMode(enB, OUTPUT); pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); //Serial.begin(9600); radio.begin(); radio.openReadingPipe(0, address); radio.setAutoAck(false); radio.setDataRate(RF24_250KBPS); radio.setPALevel(RF24_PA_LOW); radio.startListening(); // Set the module as receiver resetData(); } void loop() { // Check whether we keep receving data, or we have a connection between the two modules currentTime = millis(); if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function } // Check whether there is data to be received if (radio.available()) { radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure lastReceiveTime = millis(); // At this moment we have received the data }
// Parse the data from the Joystic 1 to the throttle and steering variables throttle = data.j1PotY; steering = data.j1PotX;
// Throttle used for forward and backward control // Joystick values: 0 to 255; down = 0; middle = 127; up = 255 if (throttle < 110) { // Set Motor A backward digitalWrite(in1, HIGH); digitalWrite(in2, LOW); // Set Motor B backward digitalWrite(in3, HIGH); digitalWrite(in4, LOW); // Convert the declining throttle readings for going backward from 110 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed motorSpeedA = map(throttle, 110, 0, 0, 255); motorSpeedB = map(throttle, 110, 0, 0, 255); } else if (throttle > 140) { // Set Motor A forward digitalWrite(in1, LOW); digitalWrite(in2, HIGH); // Set Motor B forward digitalWrite(in3, LOW); digitalWrite(in4, HIGH); // Convert the increasing throttle readings for going forward from 140 to 255 into 0 to 255 value for the PWM signal for increasing the motor speed motorSpeedA = map(throttle, 140, 255, 0, 255); motorSpeedB = map(throttle, 140, 255, 0, 255); } // If joystick stays in middle the motors are not moving else { motorSpeedA = 0; motorSpeedB = 0; } // Steering used for left and right control if (steering < 110) { // Convert the declining steering readings from 140 to 255 into increasing 0 to 255 value int xMapped = map(steering, 110, 0, 0, 255); // Move to left - decrease left motor speed, increase right motor speed motorSpeedA = motorSpeedA - xMapped; motorSpeedB = motorSpeedB + xMapped; // Confine the range from 0 to 255 if (motorSpeedA < 0) { motorSpeedA = 0; } if (motorSpeedB > 255) { motorSpeedB = 255; } } if (steering > 140) { // Convert the increasing steering readings from 110 to 0 into 0 to 255 value int xMapped = map(steering, 140, 255, 0, 255); // Move right - decrease right motor speed, increase left motor speed motorSpeedA = motorSpeedA + xMapped; motorSpeedB = motorSpeedB - xMapped; // Confine the range from 0 to 255 if (motorSpeedA > 255) { motorSpeedA = 255; } if (motorSpeedB < 0) { motorSpeedB = 0; } } // Prevent buzzing at low speeds (Adjust according to your motors. My motors couldn't start moving if PWM value was below value of 70) if (motorSpeedA < 70) { motorSpeedA = 0; } if (motorSpeedB < 70) { motorSpeedB = 0; } analogWrite(enA, motorSpeedA); // Send PWM signal to motor A analogWrite(enB, motorSpeedB); // Send PWM signal to motor B } void resetData() { // Reset the values when there is no radio connection - Set initial default values data.j1PotX = 127; data.j1PotY = 127; }
// Initialize interface to the MPU6050 initialize_MPU6050(); // Call this function if you need to get the IMU error values for your module //calculate_IMU_error();
// Define the radio communication radio.begin(); radio.openWritingPipe(address); radio.setAutoAck(false); radio.setDataRate(RF24_250KBPS); radio.setPALevel(RF24_PA_LOW);
// Set initial default values data.j1PotX = 127; // Values from 0 to 255. When Joystick is in resting position, the value is in the middle, or 127. We actually map the pot value from 0 to 1023 to 0 to 255 because that's one BYTE value data.j1PotY = 127; data.j2PotX = 127; data.j2PotY = 127; data.j1Button = 1; data.j2Button = 1; data.pot1 = 1; data.pot2 = 1; data.tSwitch1 = 1; data.tSwitch2 = 1; data.button1 = 1; data.button2 = 1; data.button3 = 1; data.button4 = 1; } void loop() { // Read all analog inputs and map them to one Byte value data.j1PotX = map(analogRead(A1), 0, 1023, 0, 255); // Convert the analog read value from 0 to 1023 into a BYTE value from 0 to 255 data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255); data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255); data.j2PotY = map(analogRead(A3), 0, 1023, 0, 255); data.pot1 = map(analogRead(A7), 0, 1023, 0, 255); data.pot2 = map(analogRead(A6), 0, 1023, 0, 255); // Read all digital inputs data.j1Button = digitalRead(jB1); data.j2Button = digitalRead(jB2); data.tSwitch2 = digitalRead(t2); data.button1 = digitalRead(b1); data.button2 = digitalRead(b2); data.button3 = digitalRead(b3); data.button4 = digitalRead(b4); // If toggle switch 1 is switched on if (digitalRead(t1) == 0) { read_IMU(); // Use MPU6050 instead of Joystick 1 for controling left, right, forward and backward movements } // Send the whole data from the structure to the receiver radio.write(&data, sizeof(Data_Package)); } void initialize_MPU6050() { Wire.begin(); // Initialize comunication Wire.beginTransmission(MPU); // Start communication with MPU6050 // MPU=0x68 Wire.write(0x6B); // Talk to the register 6B Wire.write(0x00); // Make reset - place a 0 into the 6B register Wire.endTransmission(true); //end the transmission // Configure Accelerometer Wire.beginTransmission(MPU); Wire.write(0x1C); //Talk to the ACCEL_CONFIG register Wire.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range) Wire.endTransmission(true); // Configure Gyro Wire.beginTransmission(MPU); Wire.write(0x1B); // Talk to the GYRO_CONFIG register (1B hex) Wire.write(0x10); // Set the register bits as 00010000 (1000dps full scale) Wire.endTransmission(true); } void calculate_IMU_error() { // We can call this funtion in the setup section to calculate the accelerometer and gury data error. From here we will get the error values used in the above equations printed on the Serial Monitor. // Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values // Read accelerometer values 200 times while (c < 200) { Wire.beginTransmission(MPU); Wire.write(0x3B); Wire.endTransmission(false); Wire.requestFrom(MPU, 6, true); AccX = (Wire.read()
Arduino Code
Receiver_CODE 👇
/*
Gadget Podda
2023.01.12
*/
#include
#include
#include
#define enA 10 // Arduino pin D9 - CH6 on PCB board - PWM output
#define in1 2 // D8 - CH5
#define in2 3 // D7 - CH4
#define in3 4 // D6 - CH3
#define in4 5 // D4 - CH1
#define enB 6 // D5 - CH2 - PWM output
RF24 radio(7, 8); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
// Max size of this struct is 32 bytes
struct Data_Package {
byte j1PotX;
byte j1PotY;
};
Data_Package data; //Create a variable with the above structure
int steering, throttle;
int motorSpeedA = 0;
int motorSpeedB = 0;
void setup() {
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
//Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
radio.startListening(); // Set the module as receiver
resetData();
}
void loop() {
// Check whether we keep receving data, or we have a connection between the two modules
currentTime = millis();
if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
}
// Check whether there is data to be received
if (radio.available()) {
radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
lastReceiveTime = millis(); // At this moment we have received the data
}
// Parse the data from the Joystic 1 to the throttle and steering variables
throttle = data.j1PotY;
steering = data.j1PotX;
// Throttle used for forward and backward control
// Joystick values: 0 to 255; down = 0; middle = 127; up = 255
if (throttle < 110) {
// Set Motor A backward
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
// Set Motor B backward
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
// Convert the declining throttle readings for going backward from 110 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
motorSpeedA = map(throttle, 110, 0, 0, 255);
motorSpeedB = map(throttle, 110, 0, 0, 255);
}
else if (throttle > 140) {
// Set Motor A forward
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
// Set Motor B forward
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
// Convert the increasing throttle readings for going forward from 140 to 255 into 0 to 255 value for the PWM signal for increasing the motor speed
motorSpeedA = map(throttle, 140, 255, 0, 255);
motorSpeedB = map(throttle, 140, 255, 0, 255);
}
// If joystick stays in middle the motors are not moving
else {
motorSpeedA = 0;
motorSpeedB = 0;
}
// Steering used for left and right control
if (steering < 110) {
// Convert the declining steering readings from 140 to 255 into increasing 0 to 255 value
int xMapped = map(steering, 110, 0, 0, 255);
// Move to left - decrease left motor speed, increase right motor speed
motorSpeedA = motorSpeedA - xMapped;
motorSpeedB = motorSpeedB + xMapped;
// Confine the range from 0 to 255
if (motorSpeedA < 0) {
motorSpeedA = 0;
}
if (motorSpeedB > 255) {
motorSpeedB = 255;
}
}
if (steering > 140) {
// Convert the increasing steering readings from 110 to 0 into 0 to 255 value
int xMapped = map(steering, 140, 255, 0, 255);
// Move right - decrease right motor speed, increase left motor speed
motorSpeedA = motorSpeedA + xMapped;
motorSpeedB = motorSpeedB - xMapped;
// Confine the range from 0 to 255
if (motorSpeedA > 255) {
motorSpeedA = 255;
}
if (motorSpeedB < 0) {
motorSpeedB = 0;
}
}
// Prevent buzzing at low speeds (Adjust according to your motors. My motors couldn't start moving if PWM value was below value of 70)
if (motorSpeedA < 70) {
motorSpeedA = 0;
}
if (motorSpeedB < 70) {
motorSpeedB = 0;
}
analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
}
void resetData() {
// Reset the values when there is no radio connection - Set initial default values
data.j1PotX = 127;
data.j1PotY = 127;
}
beautiful work,
scheme connection???
👍
Arduino Code
Transmitter_CODE 👇
/*
Gadget Podda
2023.01.12
*/
#include
#include
#include
#include
// Define the digital inputs
#define jB1 1 // Joystick button 1
#define jB2 0 // Joystick button 2
#define t1 2 // Toggle switch 1
#define t2 4 // Toggle switch 1
#define b1 3 // Button 1
#define b2 9 // Button 2
#define b3 2 // Button 3
#define b4 3 // Button 4
const int MPU = 0x68; // MPU6050 I2C address
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY;
float angleX, angleY;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY;
float elapsedTime, currentTime, previousTime;
int c = 0;
RF24 radio(7, 8); // nRF24L01 (CE, CSN)
const byte address[6] = "00001"; // Address
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
byte j1PotX;
byte j1PotY;
byte j1Button;
byte j2PotX;
byte j2PotY;
byte j2Button;
byte pot1;
byte pot2;
byte tSwitch1;
byte tSwitch2;
byte button1;
byte button2;
byte button3;
byte button4;
};
Data_Package data; //Create a variable with the above structure
void setup() {
Serial.begin(9600);
// Initialize interface to the MPU6050
initialize_MPU6050();
// Call this function if you need to get the IMU error values for your module
//calculate_IMU_error();
// Define the radio communication
radio.begin();
radio.openWritingPipe(address);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_LOW);
// Activate the Arduino internal pull-up resistors
pinMode(jB1, INPUT_PULLUP);
pinMode(jB2, INPUT_PULLUP);
pinMode(t1, INPUT_PULLUP);
pinMode(t2, INPUT_PULLUP);
pinMode(b1, INPUT_PULLUP);
pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP);
pinMode(b4, INPUT_PULLUP);
// Set initial default values
data.j1PotX = 127; // Values from 0 to 255. When Joystick is in resting position, the value is in the middle, or 127. We actually map the pot value from 0 to 1023 to 0 to 255 because that's one BYTE value
data.j1PotY = 127;
data.j2PotX = 127;
data.j2PotY = 127;
data.j1Button = 1;
data.j2Button = 1;
data.pot1 = 1;
data.pot2 = 1;
data.tSwitch1 = 1;
data.tSwitch2 = 1;
data.button1 = 1;
data.button2 = 1;
data.button3 = 1;
data.button4 = 1;
}
void loop() {
// Read all analog inputs and map them to one Byte value
data.j1PotX = map(analogRead(A1), 0, 1023, 0, 255); // Convert the analog read value from 0 to 1023 into a BYTE value from 0 to 255
data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255);
data.j2PotY = map(analogRead(A3), 0, 1023, 0, 255);
data.pot1 = map(analogRead(A7), 0, 1023, 0, 255);
data.pot2 = map(analogRead(A6), 0, 1023, 0, 255);
// Read all digital inputs
data.j1Button = digitalRead(jB1);
data.j2Button = digitalRead(jB2);
data.tSwitch2 = digitalRead(t2);
data.button1 = digitalRead(b1);
data.button2 = digitalRead(b2);
data.button3 = digitalRead(b3);
data.button4 = digitalRead(b4);
// If toggle switch 1 is switched on
if (digitalRead(t1) == 0) {
read_IMU(); // Use MPU6050 instead of Joystick 1 for controling left, right, forward and backward movements
}
// Send the whole data from the structure to the receiver
radio.write(&data, sizeof(Data_Package));
}
void initialize_MPU6050() {
Wire.begin(); // Initialize comunication
Wire.beginTransmission(MPU); // Start communication with MPU6050 // MPU=0x68
Wire.write(0x6B); // Talk to the register 6B
Wire.write(0x00); // Make reset - place a 0 into the 6B register
Wire.endTransmission(true); //end the transmission
// Configure Accelerometer
Wire.beginTransmission(MPU);
Wire.write(0x1C); //Talk to the ACCEL_CONFIG register
Wire.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range)
Wire.endTransmission(true);
// Configure Gyro
Wire.beginTransmission(MPU);
Wire.write(0x1B); // Talk to the GYRO_CONFIG register (1B hex)
Wire.write(0x10); // Set the register bits as 00010000 (1000dps full scale)
Wire.endTransmission(true);
}
void calculate_IMU_error() {
// We can call this funtion in the setup section to calculate the accelerometer and gury data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
// Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
// Read accelerometer values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read()