Skip to main content

DIY Arduino Transmitter and receiver

 



Hey,

In today's blog we are going to make Transmitter and receiver using Arduino.


REQUIRED STUFF FOR TRANSMITTER:

Arduino pro mini

2 × joystick module

2 × toggle switch

Potentiometer

NRF24L01 Transceiver

HT7333 3.3v voltage regulator

AMS1117 3.3v Voltage regulator


SCHEMATIC FOR TRANSMITTER:


CODE FOR TRANSMITTER:

  1. #include <SPI.h>
  2. #include <nRF24L01.h>
  3. #include <RF24.h>
  4. #include <Wire.h>
  5. // Define the digital inputs
  6. #define jB1 1 // Joystick button 1
  7. #define jB2 0 // Joystick button 2
  8. #define t1 7 // Toggle switch 1
  9. #define t2 4 // Toggle switch 1
  10. #define b1 8 // Button 1
  11. #define b2 9 // Button 2
  12. #define b3 2 // Button 3
  13. #define b4 3 // Button 4
  14. const int MPU = 0x68; // MPU6050 I2C address
  15. float AccX, AccY, AccZ;
  16. float GyroX, GyroY, GyroZ;
  17. float accAngleX, accAngleY, gyroAngleX, gyroAngleY;
  18. float angleX, angleY;
  19. float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY;
  20. float elapsedTime, currentTime, previousTime;
  21. int c = 0;
  22. RF24 radio(5, 6); // nRF24L01 (CE, CSN)
  23. const byte address[6] = "00001"; // Address
  24. // Max size of this struct is 32 bytes - NRF24L01 buffer limit
  25. struct Data_Package {
  26. byte j1PotX;
  27. byte j1PotY;
  28. byte j1Button;
  29. byte j2PotX;
  30. byte j2PotY;
  31. byte j2Button;
  32. byte pot1;
  33. byte pot2;
  34. byte tSwitch1;
  35. byte tSwitch2;
  36. byte button1;
  37. byte button2;
  38. byte button3;
  39. byte button4;
  40. };
  41. Data_Package data; //Create a variable with the above structure
  42. void setup() {
  43. Serial.begin(9600);
  44. // Initialize interface to the MPU6050
  45. initialize_MPU6050();
  46. // Call this function if you need to get the IMU error values for your module
  47. //calculate_IMU_error();
  48. // Define the radio communication
  49. radio.begin();
  50. radio.openWritingPipe(address);
  51. radio.setAutoAck(false);
  52. radio.setDataRate(RF24_250KBPS);
  53. radio.setPALevel(RF24_PA_LOW);
  54. // Activate the Arduino internal pull-up resistors
  55. pinMode(jB1, INPUT_PULLUP);
  56. pinMode(jB2, INPUT_PULLUP);
  57. pinMode(t1, INPUT_PULLUP);
  58. pinMode(t2, INPUT_PULLUP);
  59. pinMode(b1, INPUT_PULLUP);
  60. pinMode(b2, INPUT_PULLUP);
  61. pinMode(b3, INPUT_PULLUP);
  62. pinMode(b4, INPUT_PULLUP);
  63. // Set initial default values
  64. 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
  65. data.j1PotY = 127;
  66. data.j2PotX = 127;
  67. data.j2PotY = 127;
  68. data.j1Button = 1;
  69. data.j2Button = 1;
  70. data.pot1 = 1;
  71. data.pot2 = 1;
  72. data.tSwitch1 = 1;
  73. data.tSwitch2 = 1;
  74. data.button1 = 1;
  75. data.button2 = 1;
  76. data.button3 = 1;
  77. data.button4 = 1;
  78. }
  79. void loop() {
  80. // Read all analog inputs and map them to one Byte value
  81. 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
  82. data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
  83. data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255);
  84. data.j2PotY = map(analogRead(A3), 0, 1023, 0, 255);
  85. data.pot1 = map(analogRead(A7), 0, 1023, 0, 255);
  86. data.pot2 = map(analogRead(A6), 0, 1023, 0, 255);
  87. // Read all digital inputs
  88. data.j1Button = digitalRead(jB1);
  89. data.j2Button = digitalRead(jB2);
  90. data.tSwitch2 = digitalRead(t2);
  91. data.button1 = digitalRead(b1);
  92. data.button2 = digitalRead(b2);
  93. data.button3 = digitalRead(b3);
  94. data.button4 = digitalRead(b4);
  95. // If toggle switch 1 is switched on
  96. if (digitalRead(t1) == 0) {
  97. read_IMU(); // Use MPU6050 instead of Joystick 1 for controling left, right, forward and backward movements
  98. }
  99. // Send the whole data from the structure to the receiver
  100. radio.write(&data, sizeof(Data_Package));
  101. }
  102. void initialize_MPU6050() {
  103. Wire.begin(); // Initialize comunication
  104. Wire.beginTransmission(MPU); // Start communication with MPU6050 // MPU=0x68
  105. Wire.write(0x6B); // Talk to the register 6B
  106. Wire.write(0x00); // Make reset - place a 0 into the 6B register
  107. Wire.endTransmission(true); //end the transmission
  108. // Configure Accelerometer
  109. Wire.beginTransmission(MPU);
  110. Wire.write(0x1C); //Talk to the ACCEL_CONFIG register
  111. Wire.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range)
  112. Wire.endTransmission(true);
  113. // Configure Gyro
  114. Wire.beginTransmission(MPU);
  115. Wire.write(0x1B); // Talk to the GYRO_CONFIG register (1B hex)
  116. Wire.write(0x10); // Set the register bits as 00010000 (1000dps full scale)
  117. Wire.endTransmission(true);
  118. }
  119. void calculate_IMU_error() {
  120. // 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.
  121. // Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
  122. // Read accelerometer values 200 times
  123. while (c < 200) {
  124. Wire.beginTransmission(MPU);
  125. Wire.write(0x3B);
  126. Wire.endTransmission(false);
  127. Wire.requestFrom(MPU, 6, true);
  128. AccX = (Wire.read() << 8 | Wire.read()) / 4096.0 ;
  129. AccY = (Wire.read() << 8 | Wire.read()) / 4096.0 ;
  130. AccZ = (Wire.read() << 8 | Wire.read()) / 4096.0 ;
  131. // Sum all readings
  132. AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
  133. AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
  134. c++;
  135. }
  136. //Divide the sum by 200 to get the error value
  137. AccErrorX = AccErrorX / 200;
  138. AccErrorY = AccErrorY / 200;
  139. c = 0;
  140. // Read gyro values 200 times
  141. while (c < 200) {
  142. Wire.beginTransmission(MPU);
  143. Wire.write(0x43);
  144. Wire.endTransmission(false);
  145. Wire.requestFrom(MPU, 4, true);
  146. GyroX = Wire.read() << 8 | Wire.read();
  147. GyroY = Wire.read() << 8 | Wire.read();
  148. // Sum all readings
  149. GyroErrorX = GyroErrorX + (GyroX / 32.8);
  150. GyroErrorY = GyroErrorY + (GyroY / 32.8);
  151. c++;
  152. }
  153. //Divide the sum by 200 to get the error value
  154. GyroErrorX = GyroErrorX / 200;
  155. GyroErrorY = GyroErrorY / 200;
  156. // Print the error values on the Serial Monitor
  157. Serial.print("AccErrorX: ");
  158. Serial.println(AccErrorX);
  159. Serial.print("AccErrorY: ");
  160. Serial.println(AccErrorY);
  161. Serial.print("GyroErrorX: ");
  162. Serial.println(GyroErrorX);
  163. Serial.print("GyroErrorY: ");
  164. Serial.println(GyroErrorY);
  165. }
  166. void read_IMU() {
  167. // === Read acceleromter data === //
  168. Wire.beginTransmission(MPU);
  169. Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
  170. Wire.endTransmission(false);
  171. Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  172. //For a range of +-8g, we need to divide the raw values by 4096, according to the datasheet
  173. AccX = (Wire.read() << 8 | Wire.read()) / 4096.0; // X-axis value
  174. AccY = (Wire.read() << 8 | Wire.read()) / 4096.0; // Y-axis value
  175. AccZ = (Wire.read() << 8 | Wire.read()) / 4096.0; // Z-axis value
  176. // Calculating angle values using
  177. accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) + 1.15; // AccErrorX ~(-1.15) See the calculate_IMU_error()custom function for more details
  178. accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) - 0.52; // AccErrorX ~(0.5)
  179. // === Read gyro data === //
  180. previousTime = currentTime; // Previous time is stored before the actual time read
  181. currentTime = millis(); // Current time actual time read
  182. elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
  183. Wire.beginTransmission(MPU);
  184. Wire.write(0x43); // Gyro data first register address 0x43
  185. Wire.endTransmission(false);
  186. Wire.requestFrom(MPU, 4, true); // Read 4 registers total, each axis value is stored in 2 registers
  187. GyroX = (Wire.read() << 8 | Wire.read()) / 32.8; // For a 1000dps range we have to divide first the raw value by 32.8, according to the datasheet
  188. GyroY = (Wire.read() << 8 | Wire.read()) / 32.8;
  189. GyroX = GyroX + 1.85; //// GyroErrorX ~(-1.85)
  190. GyroY = GyroY - 0.15; // GyroErrorY ~(0.15)
  191. // Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
  192. gyroAngleX = GyroX * elapsedTime;
  193. gyroAngleY = GyroY * elapsedTime;
  194. // Complementary filter - combine acceleromter and gyro angle values
  195. angleX = 0.98 * (angleX + gyroAngleX) + 0.02 * accAngleX;
  196. angleY = 0.98 * (angleY + gyroAngleY) + 0.02 * accAngleY;
  197. // Map the angle values from -90deg to +90 deg into values from 0 to 255, like the values we are getting from the Joystick
  198. data.j1PotX = map(angleX, -90, +90, 255, 0);
  199. data.j1PotY = map(angleY, -90, +90, 0, 255);
  200. }
 SCHEMATIC FOR RECEIVER:

CODE FOR
 RECEIVER:

  1. #include <SPI.h>
  2. #include <nRF24L01.h>
  3. #include <RF24.h>
  4. RF24 radio(10, 9); // nRF24L01 (CE, CSN)
  5. const byte address[6] = "00001";
  6. unsigned long lastReceiveTime = 0;
  7. unsigned long currentTime = 0;
  8. // Max size of this struct is 32 bytes - NRF24L01 buffer limit
  9. struct Data_Package {
  10. byte j1PotX;
  11. byte j1PotY;
  12. byte j1Button;
  13. byte j2PotX;
  14. byte j2PotY;
  15. byte j2Button;
  16. byte pot1;
  17. byte pot2;
  18. byte tSwitch1;
  19. byte tSwitch2;
  20. byte button1;
  21. byte button2;
  22. byte button3;
  23. byte button4;
  24. };
  25. Data_Package data; //Create a variable with the above structure
  26. void setup() {
  27. Serial.begin(9600);
  28. radio.begin();
  29. radio.openReadingPipe(0, address);
  30. radio.setAutoAck(false);
  31. radio.setDataRate(RF24_250KBPS);
  32. radio.setPALevel(RF24_PA_LOW);
  33. radio.startListening(); // Set the module as receiver
  34. resetData();
  35. }
  36. void loop() {
  37. // Check whether there is data to be received
  38. if (radio.available()) {
  39. radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
  40. lastReceiveTime = millis(); // At this moment we have received the data
  41. }
  42. // Check whether we keep receving data, or we have a connection between the two modules
  43. currentTime = millis();
  44. 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
  45. resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone has a throttle up and we lose connection, it can keep flying unless we reset the values
  46. }
  47. // Print the data in the Serial Monitor
  48. Serial.print("j1PotX: ");
  49. Serial.print(data.j1PotX);
  50. Serial.print("; j1PotY: ");
  51. Serial.print(data.j1PotY);
  52. Serial.print("; button1: ");
  53. Serial.print(data.button1);
  54. Serial.print("; j2PotX: ");
  55. Serial.println(data.j2PotX);
  56. }
  57. void resetData() {
  58. // Reset the values when there is no radio connection - Set initial default values
  59. data.j1PotX = 127;
  60. data.j1PotY = 127;
  61. data.j2PotX = 127;
  62. data.j2PotY = 127;
  63. data.j1Button = 1;
  64. data.j2Button = 1;
  65. data.pot1 = 1;
  66. data.pot2 = 1;
  67. data.tSwitch1 = 1;
  68. data.tSwitch2 = 1;
  69. data.button1 = 1;
  70. data.button2 = 1;
  71. data.button3 = 1;
  72. data.button4 = 1;
  73. }
Making electronics project is too pretty simple with Us.

Join and Make with Us.

Comments

Popular posts from this blog

How To Make Pac- Man Game Using Arduino

Hello Guys , In This Post We Will Tell You How To Make A Arduino Based Pac- Man Game. For More Awesome Arduino Projects Subscribe Our Blog. #Microelectronics Components Required- 1-Arduino Uno / Nano  2-Display Module  3- Joystick Module  4- Jumper Wire   Circuit Diagram Is Given Below- Source Code- //Nokia 5110 LCD PacMan Game #include <LCD5110_Graph.h> #include <avr/pgmspace.h> #define RST 12    // RESET #define CE  13    // CS #define DC  11    // Data/Command #define DIN  10   // MOSI #define CLK  9    // SCK LCD5110 myGLCD(CLK, DIN, DC, RST, CE); // LCD5110(SCK, MOSI, DC, RST, CS); extern uint8_t SmallFont[]; const uint8_t pacman1[] PROGMEM={ 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3E, 0x1C,   // 0x0010 (16) pixels 0x0C, 0x00, 0x00, 0x00, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ...

Controlling A Servo Motor Using MPU 6050 Sensor .

Hello guys, In this post we are going to tell you that how you can control servo motor using MPU Sensor. Please subscribe to our blog, so that you can't miss any update from us.Join us @Microelectronics. Code and circuit diagram is given post. Material required- 1-MPU Sensor 2-An Arduino 3-Servo motor  4-Some jumper wires Circuit diagram- Source code- // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files // for both classes must be in the include path of your project #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" //#include "MPU6050.h" // not necessary if using MotionApps include file // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation // is used in I2Cdev.h #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE     #include "Wire.h" #endif #include <Servo.h> Servo myservo;  // create servo object to control a servo   // class default I2C address is 0x...