Advertisement
Guest User

Untitled

a guest
Nov 19th, 2017
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.12 KB | None | 0 0
  1. // NRF24 based radio receiver for radio controlled tractors
  2. // by modelleicher
  3. // NRF24 Library: https://github.com/TMRh20/RF24
  4. // Inspiration by: "RC Tractor Guy" on youtube https://www.youtube.com/user/magicalmachines/videos
  5. // Also great thanks to Antony Cartwright for the best NRF24 tutorial on youtube (bare basics explanation) https://www.youtube.com/watch?v=Qn2YLSYz3WM
  6.  
  7. // work in progress, just a start for now.
  8. // March 2017
  9.  
  10.  
  11.  
  12. #include <SPI.h>
  13. #include "RF24.h"
  14.  
  15. #include <Servo.h>
  16.  
  17. // start of package and end of package symbols
  18. #define SOP '<'
  19. #define EOP '>'
  20.  
  21. // defining all the pins, change pins here if you use different pinout!
  22. #define PIN_driveMotor_dir1  5
  23. #define PIN_driveMotor_dir2  4
  24. #define PIN_driveMotor_pwm  3
  25.  
  26. #define PIN_steering_servo  7
  27.  
  28. #define PIN_lights_lowBeam  8
  29.  
  30. #define PIN_batt_readVcc  A0
  31.  
  32. // all the settings for deadzone on motor and limits on servos
  33. #define SET_driveMotor_deadZoneMax  132
  34. #define SET_driveMotor_deadZoneMin  124
  35.  
  36. // steering trim on Deutz D16006 - min 50 max 120
  37. #define SET_steering_servoMin  50
  38. #define SET_steering_servoMax  120
  39.  
  40.  
  41.  
  42. // right now we are only receiving 6 bytes..
  43. uint8_t dataPackage[7];
  44. // dataPackage[0] = adress
  45. // dataPackage[1] = steering (X Axis)
  46. // dataPackage[2] = lifting arms (Y Axis)
  47. // dataPackage[3] = lifting arms 2 (RX Axis)
  48. // dataPackage[4] = driving (RY Axis)
  49. // dataPackage[5] = 8 Buttons (2 Joystick Buttons and 6 unused)
  50. // dataPackage[6] = 8 more buttons (6 lights/general buttons and 2 unused)
  51.  
  52. // initialize the RF24
  53. RF24 radio(9, 10);
  54.  
  55. // again, the pipe. Important, Sender and Receiver have to use the same, obviously.
  56. const uint64_t pipe = 1;
  57.  
  58. // address
  59. byte address = B00000001;
  60.  
  61. // battery voltage reading
  62. int batt_internalVCC = 0;
  63. int batt_rawAnalogRead = 0;
  64. int batt_milisecondsLow = 0;
  65.  
  66. // not used yet
  67. int dt = 0;
  68. int lastMillis = 0;
  69.  
  70. // initialize the steering servo
  71. Servo servo1;
  72.  
  73. void setup() {
  74.   // serial for debug
  75.   Serial.begin(9600);
  76.   // begin radio
  77.   radio.begin();
  78.   // no need to set PA level anything higher than min as long as the communication is only one way.
  79.   radio.setPALevel(RF24_PA_MIN);
  80.   // debug
  81.   Serial.println("started..");
  82.   // since we are the receiver, open a reading pipe
  83.   radio.openReadingPipe(1, pipe);
  84.   // debug
  85.   Serial.println("opened..");
  86.   // start listening (now we are a receiver and listening for packets)
  87.   radio.startListening();
  88.   //debug
  89.   Serial.println("listening..");
  90.  
  91.   // attach the steering servo at pin 7
  92.   servo1.attach(PIN_steering_servo);
  93.  
  94.   //
  95.   pinMode(PIN_lights_lowBeam, OUTPUT);
  96.   digitalWrite(PIN_lights_lowBeam, LOW);
  97. }
  98.  
  99. void loop() {
  100.   // not used yet
  101.   dt = millis() - lastMillis;
  102.   lastMillis = millis();
  103.  
  104.   // check if there are packets received. radio.availiable() will return true if there is anything in the buffer
  105.   if (radio.available())
  106.   {
  107.     //read the data and store in dataPackage array.
  108.     radio.read(dataPackage, sizeof(dataPackage));
  109.  
  110.     // check if the address matches ours
  111.     if (dataPackage[0] == address)
  112.     {
  113.      
  114.    
  115.         // current array index to axis:
  116.         // 1 = X
  117.         // 2 = Y
  118.         // 3 = RX
  119.         // 4 = RY
  120.    
  121.         // control drive motor
  122.         if (dataPackage[4] > SET_driveMotor_deadZoneMax) // larger than 130 -> forwards
  123.         {
  124.             analogWrite(PIN_driveMotor_pwm, map(dataPackage[4], SET_driveMotor_deadZoneMax, 255, 0, 255)); // write the PWM value
  125.             // set direction:
  126.             digitalWrite(PIN_driveMotor_dir1, HIGH);
  127.             digitalWrite(PIN_driveMotor_dir2, LOW);
  128.         }
  129.         else if (dataPackage[4] < SET_driveMotor_deadZoneMin) // smaller than 120 -> backwards
  130.         {
  131.             analogWrite(PIN_driveMotor_pwm, map(dataPackage[4], SET_driveMotor_deadZoneMin, 0, 0, 255)); // write PWM value
  132.             // set direction:
  133.             digitalWrite(PIN_driveMotor_dir1, LOW);
  134.             digitalWrite(PIN_driveMotor_dir2, HIGH);      
  135.         }
  136.         else // stop driving
  137.         {
  138.             analogWrite(PIN_driveMotor_pwm, 0);
  139.             digitalWrite(PIN_driveMotor_dir1, LOW);
  140.             digitalWrite(PIN_driveMotor_dir2, LOW);    
  141.         }
  142.  
  143.    
  144.        
  145.         // map the steering value to servo min/max values
  146.         dataPackage[1] = map(dataPackage[1], 0, 255, SET_steering_servoMin, SET_steering_servoMax);
  147.         // set the servo value
  148.         servo1.write(dataPackage[1]);  
  149.  
  150.        
  151.          // send the data package to the trailer
  152.         sendImplementData(dataPackage);
  153.  
  154.        
  155.         // light
  156.         digitalWrite(PIN_lights_lowBeam, bitRead(dataPackage[6], 3));
  157.  
  158.     // debug
  159.     //Serial.println(dataPackage[1]);
  160.     //Serial.println(dataPackage[2]);
  161.     //Serial.println(dataPackage[3]);    
  162.     //Serial.println("----------------------");    
  163.     }
  164.   }
  165.   else
  166.   {
  167.      // this is called each time the loop runs and there is no data in the buffer from the NRF24
  168.   }
  169.  
  170.  
  171.   // check the battery voltage to not over discharge the lipo cells!
  172.   checkBatteryVoltage(dt);
  173.      
  174.  
  175.  
  176.   // not sure if the dalay is needet.
  177.   delay(10);
  178.  
  179.  
  180.  
  181. }
  182.  
  183. void checkBatteryVoltage(int dt)
  184. {
  185.          // since LiPo cells can take damage or even explove if over-discharged we need to monitor the voltage
  186.         // some LiPo cells come with protection circuits on the cell itself, but the cheap ones i use don't.
  187.         // also most multiple cell lipos dont. I use a 2S Lipo in this tractor.
  188.         // so we read the current battery voltage with analogRead and a voltage divider since the arduino runs on 3.3V and the LiPo fully charged has 8.4V
  189.         // My Arduino runs on 3.27V usually, that means that our lower limit of 6.6V is reached at a analogRead value of 687
  190.         // I did want to take the internal voltage into account but floating point math isn't that great on the arduino, and since i had a conservative number for the lower limit i think we'll be fine.
  191.         // you need to change this whole thing if you are not running the arduino off of a 3.3V regulator!!!
  192.        
  193.         //batt_internalVCC = getVCCReading();
  194.        
  195.         batt_rawAnalogRead = analogRead(PIN_batt_readVcc);
  196.         if (batt_rawAnalogRead <= 687)
  197.         {
  198.              Serial.println(batt_milisecondsLow);
  199.             batt_milisecondsLow = batt_milisecondsLow + dt;
  200.             if (batt_milisecondsLow > 1000) // battery is low for more than 1 second (to avoid shutting off on current spikes)
  201.             {
  202.                 goBlinkLowBatteryLights(); // blink the lights really fast to show that the battery is empty
  203.                 batt_milisecondsLow = 0; // reset the battery low timer.. So the lights will start again after 1 second until battery is changed
  204.             }
  205.         }
  206.         else
  207.         {
  208.             batt_milisecondsLow = 0;
  209.         }
  210.         //Serial.println(batt_rawAnalogRead);
  211. }
  212.  
  213. // send Implement data, serial communication by RC-Tractor Guy
  214. void sendImplementData(uint8_t dataPackage[16])
  215. {
  216.   Serial.write(SOP);
  217.   Serial.write(0x01);
  218.   Serial.write(dataPackage[1]);
  219.   Serial.write(dataPackage[2]);
  220.   Serial.write(dataPackage[3]);
  221.   Serial.write(dataPackage[4]);
  222.   Serial.write(dataPackage[5]);
  223.   Serial.write(dataPackage[6]);
  224.   Serial.write(dataPackage[7]);
  225.   Serial.write(dataPackage[8]);
  226.   Serial.write(dataPackage[9]);
  227.   Serial.write(dataPackage[10]);
  228.   Serial.write(EOP);
  229. }
  230.  
  231. void goBlinkLowBatteryLights()
  232. {
  233.  
  234.     digitalWrite(PIN_lights_lowBeam, HIGH);
  235.     delay(50);
  236.     digitalWrite(PIN_lights_lowBeam, LOW);
  237.     delay(250);
  238.     digitalWrite(PIN_lights_lowBeam, HIGH);
  239.     delay(50);
  240.     digitalWrite(PIN_lights_lowBeam, LOW);
  241.     delay(250);    
  242. }
  243.  
  244. // from RCTractorGuy Library, not used right now since i can't get the floating point stuff to work properly
  245. long getVCCReading(){
  246.   long result;
  247.   // Read 1.1V reference against AVcc
  248.   ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  249.   delay(2); // Wait for Vref to settle
  250.   ADCSRA |= _BV(ADSC); // Convert
  251.   while (bit_is_set(ADCSRA,ADSC));
  252.   result = ADCL;
  253.   result |= ADCH<<8;
  254.   result = (1126400L / result); // Back-calculate AVcc in mV
  255.   return result;
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement