crazykiwi

E-Bike

Sep 20th, 2021 (edited)
624
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 10.17 KB | None | 0 0
  1. /*
  2.  * ##############################
  3.  * ####### E-BIKE PROJECT #######
  4.  * ##############################
  5.  *
  6.  * Author : J
  7.  * Date : June - July 2020
  8.  * Updated : August 2021
  9.  *
  10.  * Version : 1.1
  11.  *
  12.  * For Arduino Nano
  13.  *
  14.  * ##############################
  15.  */
  16.  
  17.  
  18. #include <SPI.h>
  19. #include <RFID.h>
  20. #include <EEPROM.h> //only for debugging
  21.  
  22. //definition of pins for Arduino Nano
  23. #define SS_PIN 10
  24. #define RST_PIN 9
  25.  
  26. //variables for inputs and outputs
  27. const byte BUZZER = 2,              //Alarm buzzer
  28.            RELAY = 3,               //Main relay
  29.            LIMIT_SPD = 4,           //Speed limiter (/!\ mandatory in CH /!\)
  30.            THROTTLE_BT = 6,         //Throttle button input
  31.            TRIAC_CTRL = A1,         //Triac for the LED lamps
  32.            BT_VOLTAGE = A6,         //Voltage of the power button
  33.            RELAY_VOLTAGE = A5,      //Voltage of the battery
  34.            THERMISTOR = A4;         //Temperature sensor
  35. const byte BIN_THROTTLE[4] = {A0, 5, 7, 8};
  36.  
  37. //customizable settings (can be modified according to your preferences)
  38. const byte  MAIN_BADGE[5]   = {0, 0, 0, 0, 0};
  39. const byte  BACKUP_BADGE[5] = {0, 0, 0, 0, 0};
  40. boolean     BIN_THROTTLE_MAX[4] = {true, true, false, false};   //max value to ESC
  41. boolean     BIN_THROTTLE_MIN[4] = {false, false, true, true};   //min value to ESC
  42. const int   MAX_TEMP = 796;         //max value for the thermistor security (default 796 = 60°C)
  43. const int   LOW_VOLT_1 = 651;       //low voltage : step 1 (default 651 = 35V)
  44. const int   LOW_VOLT_2 = 614;       //low voltage : step 2 (default 614 = 33V)
  45. const int   LOW_VOLT_3 = 578;       //low voltage : step 3 (default 578 = 31V)
  46. const int   LOW_VOLT_X = 520;       //extremely low voltage, immediate power off (default 520 = 28V)
  47. const byte  MAX_TIME_REBOOT = 60;   //max time (in seconds) for a reboot without the need of the RFID card (default 60)
  48.  
  49. //system variables (do not modify them)
  50. byte        cur_badge[5];
  51. byte        num_badge = 0;          //0 for incorrect card, 1 if main card, 2 if backup card
  52. boolean     locked = true;
  53. boolean     acceleration = true;    //slows down throttle acceleration
  54. boolean     bin_throttle[4] = {false, false, true, true};       //value sent to ESC
  55. int         voltage = -1;
  56. int         count_voltage = 5;
  57. int         count_shutdown = 0;
  58. int         battery_discharge = 0;  //battery discharge state
  59. int         count_throttle = 1;
  60.  
  61. RFID rfid(SS_PIN, RST_PIN);
  62.  
  63.  
  64. void setup()
  65. {
  66.   //Serial.begin(9600); //only for debugging : Serial.println("")
  67.   SPI.begin();
  68.   rfid.init();
  69.  
  70.   //definition of all pinModes (I/O)
  71.   pinMode(BUZZER, OUTPUT);
  72.   pinMode(RELAY, OUTPUT);
  73.   pinMode(LIMIT_SPD, OUTPUT);
  74.   pinMode(THROTTLE_BT, INPUT_PULLUP);
  75.   pinMode(TRIAC_CTRL, OUTPUT);
  76.   pinMode(BT_VOLTAGE, INPUT); //analog
  77.   pinMode(RELAY_VOLTAGE, INPUT); //analog
  78.  
  79.   for(byte i = 0; i < 4; i++)
  80.   {
  81.       pinMode(BIN_THROTTLE[i], OUTPUT);
  82.       digitalWrite(BIN_THROTTLE[i], LOW);
  83.   }
  84.  
  85.   //sets the outputs to initial state
  86.   digitalWrite(RELAY, LOW);
  87.   digitalWrite(LIMIT_SPD, HIGH);
  88.   digitalWrite(TRIAC_CTRL, LOW);
  89.  
  90. }
  91.  
  92.  
  93. void loop()
  94. {
  95.  
  96.   /*
  97.    * Bike is locked
  98.    */
  99.   while(locked)
  100.   {
  101.     if (rfid.isCard()) {    //unlocking
  102.      
  103.       if(readRFID() && (num_badge == 1 || num_badge == 2)) {
  104.        
  105.         buzzer(true);
  106.         if(num_badge == 2 || digitalRead(THROTTLE_BT) == LOW) digitalWrite(LIMIT_SPD, LOW);
  107.         digitalWrite(RELAY, HIGH);
  108.         throttleReset();
  109.         delay(100);
  110.         voltage = analogRead(RELAY_VOLTAGE);
  111.        
  112.         for(byte i = 0; i < 20; i++) {
  113.           if(analogRead(BT_VOLTAGE) < 102) {    //executed once, despite being in a for loop
  114.             digitalWrite(TRIAC_CTRL, HIGH);
  115.             delay(100);
  116.             digitalWrite(TRIAC_CTRL, LOW);
  117.             locked = false;
  118.             i = 20;
  119.           }
  120.           //security : user forgot to put the power switch in the initial position
  121.           if(i == 19) {
  122.             digitalWrite(RELAY, LOW);
  123.             while(true) {
  124.               buzzer(false);
  125.               locked = true;
  126.             }
  127.           }
  128.           delay(500);
  129.         }
  130.        
  131.       } else {
  132.        
  133.         buzzer(false);
  134.        
  135.       }
  136.     }
  137.    
  138.     delay(100);
  139.    
  140.   }
  141.  
  142.   /*
  143.    * Bike is unlocked
  144.    */
  145.   while(!locked)
  146.   {
  147.     if(count_voltage == 25) {
  148.       count_voltage = 0;
  149.       ctrlBattery();
  150.       ctrlTemp();
  151.     } else {
  152.       count_voltage++;
  153.     }
  154.     ctrlShutdown();
  155.     ctrlThrottle();
  156.     delay(250);
  157.   }
  158. }
  159.  
  160. /*
  161.  * Compares card to registered cards
  162.  */
  163. boolean compareBadge()
  164. {
  165.  
  166.   if(
  167.     MAIN_BADGE[0] == cur_badge[0] &&
  168.     MAIN_BADGE[1] == cur_badge[1] &&
  169.     MAIN_BADGE[2] == cur_badge[2] &&
  170.     MAIN_BADGE[3] == cur_badge[3] &&
  171.     MAIN_BADGE[4] == cur_badge[4] )
  172.     {
  173.       num_badge = 1;
  174.       return true;
  175.     }
  176.    
  177.   if(
  178.     BACKUP_BADGE[0] == cur_badge[0] &&
  179.     BACKUP_BADGE[1] == cur_badge[1] &&
  180.     BACKUP_BADGE[2] == cur_badge[2] &&
  181.     BACKUP_BADGE[3] == cur_badge[3] &&
  182.     BACKUP_BADGE[4] == cur_badge[4] )
  183.     {
  184.       num_badge = 2;
  185.       return true;
  186.     }
  187.    
  188.   return false;
  189.  
  190. }
  191.  
  192. /*
  193.  * Reads RFID card and compares it to registred cards
  194.  */
  195. boolean readRFID()
  196. {
  197.   if (rfid.readCardSerial()) {
  198.     for(byte i = 0; i < 5; i++) {
  199.       cur_badge[i] = rfid.serNum[i]; //copy of the 5 bytes of the card in cur_badge
  200.     }
  201.     rfid.halt();
  202.     return compareBadge();
  203.   }
  204.   rfid.halt();
  205. }
  206.  
  207. /*
  208.  * Activates the buzzer (true = OK ; false = alarm)
  209.  */
  210. void buzzer(boolean noise)
  211. {
  212.   if(noise) {
  213.     tone(BUZZER, 523, 50);
  214.     delay(50);
  215.     tone(BUZZER, 783, 50);
  216.     delay(50);
  217.     tone(BUZZER, 1046, 50);
  218.     delay(50);
  219.     tone(BUZZER, 1568, 50);
  220.     delay(50);
  221.     tone(BUZZER, 2093, 70);
  222.     delay(250);
  223.   } else {
  224.     tone(BUZZER, 370, 50);
  225.     delay(100);
  226.     tone(BUZZER, 370, 300);
  227.     delay(1000);
  228.   }
  229. }
  230.  
  231. /*
  232.  * Resets the throttle output
  233.  */
  234. void throttleReset()
  235. {
  236.   printThrottle(BIN_THROTTLE_MIN);
  237. }
  238.  
  239. /*
  240.  * Updates the trottle output depending on the button input
  241.  * TODO : use an enum for count_throttle
  242.  */
  243. void ctrlThrottle()
  244. {
  245.   if(digitalRead(THROTTLE_BT) == LOW) {                       //throttle button pressed
  246.     if(count_throttle == 1 || count_throttle == 0) {          //  if 1 : stopped, if 0 : accelerating
  247.       if(acceleration) {                                      //    waits
  248.         for(int i = 3; i >= 0; i--) {                         //      adds 1 to binary throttle array
  249.           bin_throttle[i] = !bin_throttle[i];
  250.           if(bin_throttle[i]) {
  251.             i = -1;
  252.           }
  253.         }
  254.         if(count_throttle == 1) {
  255.           count_throttle = 0;
  256.         }
  257.         if(bin_throttle[0] == BIN_THROTTLE_MAX[0] &&          //      throttle max (= 2)
  258.            bin_throttle[1] == BIN_THROTTLE_MAX[1] &&
  259.            bin_throttle[2] == BIN_THROTTLE_MAX[2] &&
  260.            bin_throttle[3] == BIN_THROTTLE_MAX[3])
  261.         {
  262.           count_throttle = 2;
  263.         }
  264.       }
  265.       acceleration = !acceleration;
  266.     }
  267.     if(count_throttle < 0 && count_throttle >= -5) {          //  if 2 : stable throttle output (no acceleration)
  268.       count_throttle = 2;
  269.     }
  270.     printThrottle(bin_throttle);
  271.   } else {                                                    //throttle button not pressed
  272.     if(count_throttle != 1) {
  273.       throttleReset();
  274.     }
  275.     if(count_throttle < 1 && count_throttle > -5) {           //  waiting time, from 0 to -5 (1.25 seconds)
  276.       count_throttle--;
  277.     } else if(count_throttle == -5 || count_throttle == 2) {  //  end of waiting time, throttle completely released
  278.       count_throttle = 1;
  279.       for(int i = 0; i < 4; i++) {
  280.         bin_throttle[i] = BIN_THROTTLE_MIN[i];
  281.       }
  282.     }
  283.   }
  284. }
  285.  
  286. /*
  287.  * Outputs the given value on the throttle output
  288.  */
  289. void printThrottle(boolean throttle[4])
  290. {
  291.   for(int i = 0; i < 4; i++) {
  292.     digitalWrite(BIN_THROTTLE[i], throttle[i]);
  293.   }
  294. }
  295.  
  296. /*
  297.  * Controls the battery voltage
  298.  */
  299. void ctrlBattery()
  300. {
  301.   voltage = analogRead(RELAY_VOLTAGE);
  302.  
  303.   //Extremely low voltage security (<28V)
  304.   if(voltage < LOW_VOLT_X) {
  305.     digitalWrite(RELAY, LOW);
  306.     buzzer(false);
  307.   }
  308.  
  309.   //Low voltage security (steps at 35V, 33V and 31V)
  310.   if(voltage < LOW_VOLT_1 && battery_discharge < 2) {
  311.     battery_discharge++;
  312.     if(battery_discharge == 2) {
  313.       buzzer(false);
  314.     }
  315.   }
  316.   if(voltage < LOW_VOLT_2 && battery_discharge > 1 && battery_discharge < 4) {
  317.     battery_discharge++;
  318.     if(battery_discharge == 4) {
  319.       buzzer(false);
  320.     }
  321.   }
  322.   if(voltage < LOW_VOLT_3 && battery_discharge > 3) {
  323.     battery_discharge++;
  324.     if(battery_discharge >= 6) {
  325.       buzzer(false);
  326.       digitalWrite(RELAY, LOW);
  327.       buzzer(false);
  328.     }
  329.   }
  330. }
  331.  
  332. /**
  333.  * Shutdown system if the power button is pressed
  334.  */
  335. void ctrlShutdown()
  336. {
  337.   if(analogRead(BT_VOLTAGE) > 102) {
  338.     count_shutdown++;
  339.     if (count_shutdown == 4) {
  340.       buzzer(false);
  341.       digitalWrite(RELAY, LOW);
  342.       delay(2000);
  343.       eventualReboot();
  344.     }
  345.   } else if(count_shutdown != 0) {
  346.     count_shutdown = 0;
  347.   }
  348. }
  349.  
  350. /**
  351.  * To be called after shutdown, reboot without security if triggered less than 1 min after shutdown
  352.  */
  353. void eventualReboot()
  354. {
  355.   byte buttonPressed = 0;
  356.   boolean inLoop = true;
  357.  
  358.   for(byte i = 0; i < MAX_TIME_REBOOT; i++) {
  359.     delay(1000);
  360.     if(i % 10 == 0) buzzer(false);
  361.    
  362.     if(digitalRead(THROTTLE_BT) == LOW) {
  363.       buttonPressed++;
  364.       if(buttonPressed >= 5) {                                //Reboot
  365.         digitalWrite(LIMIT_SPD, HIGH);
  366.         throttleReset();
  367.         buzzer(true);
  368.         count_shutdown = 0;
  369.         count_throttle = 1;
  370.         digitalWrite(RELAY, HIGH);
  371.         inLoop = false;
  372.         i = MAX_TIME_REBOOT + 1;
  373.       }
  374.     } else if(buttonPressed != 0) {
  375.       buttonPressed = 0;
  376.     }
  377.   }
  378.  
  379.   while(inLoop) {                                             //Time out : reboot impossible
  380.         buzzer(false);
  381.         delay(10000);
  382.       }
  383. }
  384.  
  385. /*
  386.  * Controls the temperature of the battery and the electronics (shutdown if > 60°C)
  387.  */
  388. void ctrlTemp()
  389. {
  390.   if(analogRead(THERMISTOR) >= MAX_TEMP) {
  391.     buzzer(false);
  392.     digitalWrite(RELAY, LOW);
  393.   }
  394. }
Add Comment
Please, Sign In to add comment