phillip_bourdon234

Electric_Skateboard_Main_Board.c

Mar 1st, 2021 (edited)
939
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.86 KB | None | 0 0
  1. //===================================================================================================================
  2. //                                                                      CODE FOR THE SKATEBOARD
  3. //===================================================================================================================
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include "stm32f10x.h"
  8. #include "system_stm32f10x.h"
  9. #include "GPIO_Driver.h"
  10. #include "NRF_Driver.h"
  11. #include "delay.h"
  12. #include "Servo_Driver.h"
  13.  
  14. #define NUM_LEDS 39 //you must add 1 to how many existing LED's you have.
  15.                                       //For example, if you have 5 LEDs, put 6 for this number.
  16.                                       //I implemented this because sometimes, a bit or two would bleed
  17.                                       //into the next LED, causing it to light up green when the user did not want
  18.                                       //to. This causes that last LED to deliberatly be set to zero.
  19.  
  20. #define RX_PIPE 1
  21. #define ADDR_HIGH 0xAABBCCDD
  22. #define ADDR_LOW 0xEE
  23. #define EN_D_PL_W 1
  24. #define EN_AUTO_ACK 1
  25. #define PL_W 3
  26. #define CHANNEL 0x7B
  27.  
  28. void init_PWM_TIM4(void); //neopixels
  29. void TIM4_IRQHandler(void);
  30. void strip_fill(uint32_t R, uint32_t G, uint32_t B, int start, int END);
  31. void strip_show(void);
  32. void strip_run(void);
  33. void strip_rainbow(void);
  34. void strip_fade(void);
  35. void strip_clear(void);
  36. void strip_ASU(void);
  37.  
  38. uint16_t map(uint16_t var, uint16_t var_low, uint16_t var_high, uint16_t low_thresh, uint16_t high_thresh);
  39.  
  40. volatile static uint16_t pwm_duty_cicle_neopixels = 0;
  41. volatile static int currentLED = 0;
  42. volatile static int currentRGB = 0;
  43. volatile static int resetFlag = 0;
  44.  
  45.  
  46. int static neoPixelBuffer[NUM_LEDS][24]; //this global 2D array appears in the TIM4_IRQHandler and
  47.                                                                                  //the strip_fill function.
  48.  
  49. int main()
  50. {
  51.     //RX MODE
  52.     uint8_t dataBuffer[4] = {240, 0, 0, 0};
  53.     uint16_t servo_microseconds = 1100;
  54.     uint16_t nrf_disconnection_counter = 0; //if this variable overflows, then
  55.                                                                              //the program knows that the user
  56.                                                                              //has lost connection with the board
  57.                                          //and will stop the board automatically
  58.    
  59.     //==========================================
  60.     GPIO_TYPE PWM_Output_Neopixels;
  61.     PWM_Output_Neopixels.port = PORTB;
  62.     PWM_Output_Neopixels.pin = 9;
  63.     PWM_Output_Neopixels.mode = OUTPUT;
  64.     PWM_Output_Neopixels.mode_type = OUTPUT_ALT_FUNCTION;
  65.     PWM_Output_Neopixels.speed = SPEED_50MHZ;
  66.     //==========================================
  67.    
  68.     init_gpio(PWM_Output_Neopixels);
  69.     servo_init(3, 4); //this inits a pwm signal (50hz) on timer 3 channel 4
  70.    
  71.     init_delay();
  72.     init_PWM_TIM4();
  73.    
  74.     nrf_init_pins(PORTA, 0, PORTA, 1); //these are the CE and CSN pins on the NRF module
  75.     nrf_init_reciever(RX_PIPE, ADDR_HIGH, ADDR_LOW, CHANNEL, EN_AUTO_ACK, EN_D_PL_W, 32);
  76.     nrf_cmd_act_as_RX();
  77.     nrf_cmd_listen();
  78.  
  79.     while(1)
  80.     {
  81.         //RX MODE
  82.        
  83.        
  84.         if(nrf_data_available())
  85.         {
  86.             nrf_disconnection_counter = 0; //getting into this if statement means that
  87.                                                                     //the nrf module has a connection and
  88.                                                                     //the nrf_disconnection_counter is reset
  89.             nrf_read(dataBuffer);
  90.             servo_microseconds = map(dataBuffer[1], 0, 255, 1100, 2000);
  91.         }
  92.         else
  93.         {
  94.             nrf_disconnection_counter += 1; //increment the nrf_disconnection_counter by 1. If the nrf module
  95.                                                                      //has had no connection for around 1 second, then the
  96.                                                                      //servo_microseconds variable is set to a value that
  97.                                                                      //will slowly stop the skateboard.
  98.             if(nrf_disconnection_counter > 100)
  99.             {
  100.                 servo_microseconds = 1100;
  101.                 nrf_disconnection_counter = 0;
  102.        
  103.             }
  104.         }
  105.         delayMs(10);
  106.        
  107.         if(dataBuffer[3] != 1)
  108.         {
  109.             servo_writeMicroseconds(servo_microseconds, 3, 4);
  110.         }
  111.         else
  112.         {
  113.             servo_writeMicroseconds(1000, 3, 4);
  114.         }
  115.            
  116.            
  117.         if(play_millis(100*1000) == 0) //this play_millis function equals 0 after the user identified time (in us)
  118.                                                                      //has past. It will stay zero until the play_millis function is called again
  119.         {
  120.             switch(dataBuffer[2])
  121.             {
  122.                 case 0:
  123.                     strip_fill(150, 0, 0, 0, NUM_LEDS); //RED
  124.                     strip_show();                  
  125.                 break;
  126.                
  127.                 case 1:
  128.                     strip_fill(0, 150, 0, 0, NUM_LEDS); //GREEN
  129.                     strip_show();
  130.                 break;
  131.                
  132.                 case 2:
  133.                     strip_fill(0, 0, 150, 0, NUM_LEDS); //BLUE
  134.                     strip_show();
  135.                 break;
  136.                
  137.                 case 3:
  138.                     strip_fill(150, 0, 150, 0, NUM_LEDS); //PURPLE
  139.                     strip_show();
  140.                 break;
  141.                
  142.                 case 4:
  143.                     strip_fill(150, 30, 0, 0, NUM_LEDS); //ORANGE
  144.                     strip_show();
  145.                 break;
  146.                
  147.                 case 5:
  148.                     strip_fill(150, 150, 150, 0, NUM_LEDS); //WHITE
  149.                     strip_show();
  150.                 break;
  151.                
  152.                 case 6:
  153.                     strip_ASU();   
  154.                 break;
  155.                
  156.                 case 7:
  157.                     strip_fade();
  158.                 break;
  159.    
  160.                 case 8:
  161.                     strip_run();
  162.                 break;
  163.                
  164.                 case 9:
  165.                     strip_rainbow();
  166.                 break;
  167.                
  168.                 case 10:
  169.                     strip_clear(); //turn LEDS off
  170.                 break;
  171.                
  172.             }
  173.         }
  174.     }
  175. }
  176.  
  177.  
  178. //This interupt service routine starts when strip_show is called
  179. //and produces the correct PWM signal to make the correct color that was specified
  180. //in the strip_fill function.
  181. void TIM4_IRQHandler()
  182. {
  183.     if(TIM4->SR & TIM_SR_UIF)
  184.     {      
  185.         TIM4->SR &= ~(TIM_SR_UIF);
  186.        
  187.         if(resetFlag != 1)
  188.         {  
  189.             if(neoPixelBuffer[currentLED][currentRGB] == 1 )
  190.             {
  191.                 pwm_duty_cicle_neopixels = 57; //creats a high pulse to satisfy the neopixels timing requirement for a 1   
  192.             }
  193.             else
  194.             {
  195.                 pwm_duty_cicle_neopixels = 27; //creats a high pulse to satisfy the neopixels timing requirement for a 0
  196.             }
  197.             currentRGB++;
  198.             TIM4->CCR4 = pwm_duty_cicle_neopixels;
  199.  
  200.             if(currentRGB>23) //the neopixel needs 24 bits for the color. 8 for red, 8 for green, 8 for blue
  201.             {                                   //once it has completed an etire color, it will move on to the next LED
  202.                 currentRGB = 0;
  203.                 currentLED++;
  204.             }
  205.         }      
  206.         resetFlag = 0;
  207.         TIM4->ARR = 700;
  208.     }
  209. }
  210.  
  211.  
  212. //this function "maps" the values from a given varibale, the range of values that that variable has,
  213. //and will return a new proportional value in the range of the users choice
  214. uint16_t map(uint16_t var, uint16_t var_low, uint16_t var_high, uint16_t low_thresh, uint16_t high_thresh)
  215. {
  216.     return (var -  var_low)*(high_thresh - low_thresh)/(var_high - var_low) + low_thresh;
  217. }
  218.  
  219. void init_PWM_TIM4(void)
  220. {  
  221.     //init timer and alternate function
  222.     RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
  223.     RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
  224.    
  225.     //init the ARR
  226.     TIM4->CR1 |= TIM_CR1_ARPE;
  227.    
  228.     //init interrupts
  229.     TIM4->CR1 |= TIM_CR1_URS;
  230.    
  231.     //update interrupt enable
  232.     TIM4->DIER |= TIM_DIER_UIE;
  233.    
  234.     //tell the NVIC to listen to interupts on the timer 4 IRQ number
  235.     NVIC_EnableIRQ(TIM4_IRQn);
  236.    
  237.     //enable PWM mode 1 and the preloader
  238.     TIM4->CCMR2 |= TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE;
  239.  
  240.     //PWM DC = CRR4/ARR
  241.     //enable duty cycle
  242.     TIM4->PSC = 0;
  243.     TIM4->ARR = 700; //this value must generate a frequency no larger than the reset time of the neopixel(see datasheet)
  244.     TIM4->CCR4 = pwm_duty_cicle_neopixels;
  245.    
  246.     //enable the update generation
  247.     TIM4->EGR |= TIM_EGR_UG;
  248. }
  249.  
  250. //The strip_fill funcion lights up the LEDs in the desired range.
  251. //For example, if you want the first 3 LEDs to be green, you would
  252. //say strip_fill(0, 255, 0, 0, 3).
  253. void strip_fill(uint32_t R, uint32_t G, uint32_t B, int start, int END)
  254. {
  255.   uint32_t grb = B | (R << 8) | (G << 16);
  256.  
  257.     if(END > NUM_LEDS) //if the user accidently inputs an end value that is higher than the
  258.     {                                    //NUM_LEDS macro, then END will be set to NUM_LEDS
  259.         END = NUM_LEDS;
  260.     }
  261.    
  262.   for(int j = start; j < END; j++)
  263.   {
  264.     for(int i = 0; i < 24; i++)
  265.     {
  266.       if( ((grb >> i) & 0x01) == 1)
  267.       {
  268.         neoPixelBuffer[j][23-i] = 1;
  269.       }
  270.       else
  271.       {
  272.         neoPixelBuffer[j][23-i] = 0;
  273.       }
  274.     }
  275.   }
  276. }
  277.  
  278. void strip_show()
  279. {
  280.     resetFlag = 1; //set reset flag so the function inside the interrupt isn't used
  281.    
  282.     TIM4->ARR = 6000; //set the ARR to a value that satisfies the data sheet of a low time of at most 50uS(+50us = reset command)
  283.     TIM4->CCR4 = 0; //set the pwm signal to low
  284.    
  285.     TIM4->CCER |= TIM_CCER_CC4E; //turn on pwm channel 4
  286.     TIM4->CR1 |= TIM_CR1_CEN; //turn on timer
  287.    
  288.     while(currentLED < NUM_LEDS); //wait until all the LEDS are set
  289.    
  290.     TIM4->CCER &= ~(TIM_CCER_CC4E); //turn off channel 4
  291.     TIM4->CR1 &= ~(TIM_CR1_CEN); //turn off timer
  292.  
  293.     currentLED = 0;
  294.     currentRGB = 0;
  295.    
  296. }
  297.  
  298. //lights up the first half of LEDs red, and the other half yellow
  299. void strip_ASU()
  300. {
  301.     strip_clear();
  302.     strip_fill(150, 0, 0, 0, NUM_LEDS/2);
  303.     strip_fill(150, 75, 0, NUM_LEDS/2, NUM_LEDS);
  304.     strip_show();
  305. }
  306.  
  307. //fades the LEDs from color to color
  308. void strip_fade()
  309. {
  310.     static uint8_t currentColor = 2;
  311.     static uint8_t currentColorCount = 0;
  312.    
  313.     if(currentColor > 150)
  314.     {
  315.         currentColor = 150;
  316.         currentColorCount++;
  317.     }
  318.     else if(currentColor < 2)
  319.     {
  320.         currentColor = 2;
  321.         currentColorCount++;
  322.     }
  323.    
  324.     if(currentColorCount > 5)
  325.     {
  326.         currentColorCount = 0;
  327.     }
  328.    
  329.     if(currentColorCount == 0)
  330.     {
  331.         currentColor+=2;
  332.         strip_fill(150, currentColor, 0, 0, NUM_LEDS);
  333.     }
  334.     else if(currentColorCount == 1)
  335.     {
  336.         currentColor-=2;
  337.         strip_fill(currentColor, 150, 0, 0, NUM_LEDS);
  338.     }
  339.     else if(currentColorCount == 2)
  340.     {
  341.         currentColor+=2;
  342.         strip_fill(0, 150, currentColor, 0, NUM_LEDS);
  343.     }
  344.     else if(currentColorCount == 3)
  345.     {
  346.         currentColor-=2;
  347.         strip_fill(0, currentColor, 150, 0, NUM_LEDS);
  348.     }
  349.     else if(currentColorCount == 4)
  350.     {
  351.         currentColor+=2;
  352.         strip_fill(currentColor, 0, 150, 0, NUM_LEDS);
  353.     }
  354.     else if(currentColorCount == 5)
  355.     {
  356.         currentColor-=2;
  357.         strip_fill(150, 0, currentColor, 0, NUM_LEDS);
  358.     }
  359.     strip_show();
  360.    
  361. }
  362.  
  363. //changes a single LED at a time on one half while changing the other half to a different color at a time.
  364. //this creates what looks like to be a "running" annimation of the LEDs
  365. void strip_run()
  366. {
  367.     static uint8_t runCount = 0;
  368.     static uint8_t colorCount = 0; 
  369.    
  370.     runCount++;
  371.  
  372.     if(runCount > (NUM_LEDS/2))
  373.     {
  374.         runCount = 1;
  375.         colorCount++;
  376.     }
  377.     if(colorCount > 2)
  378.         colorCount = 0;
  379.    
  380.     if(colorCount == 0)
  381.     {
  382.         strip_fill(75, 0, 150, NUM_LEDS-runCount, NUM_LEDS);
  383.         strip_fill(0, 150, 0, 0, runCount);
  384.     }
  385.     else if(colorCount == 1)
  386.     {
  387.         strip_fill(150, 75, 0, NUM_LEDS-runCount, NUM_LEDS);
  388.         strip_fill(0, 75, 150, 0, runCount);
  389.     }
  390.     else if(colorCount == 2)
  391.     {
  392.         strip_fill(150, 150, 150, NUM_LEDS-runCount, NUM_LEDS);
  393.         strip_fill(150, 0, 0, 0, runCount);
  394.     }
  395.        
  396.     strip_show();
  397.  
  398. }
  399.  
  400. //creates a plain rainbow effect to the LEDs (this function is proportional to the amount of LEDs present,
  401. //therefor you can change the amount of leds and not have to worry about messing up this animation)
  402. void strip_rainbow()
  403. {
  404.     const uint8_t colorOffset = (NUM_LEDS/9)+1;
  405.    
  406.     static uint8_t led_start = 0;
  407.     static uint8_t led_finish = 0;
  408.    
  409.     led_start = 0;
  410.     led_finish = 0;
  411.    
  412.     led_finish = led_finish + colorOffset;
  413.    
  414.     strip_fill(150,0,0,led_start,led_finish);
  415.    
  416.     led_start = led_finish;
  417.     led_finish = led_finish + colorOffset;
  418.    
  419.     strip_fill(150,37,0,led_start, led_finish);
  420.    
  421.     led_start = led_finish;
  422.     led_finish = led_finish + colorOffset;
  423.    
  424.     strip_fill(150, 112, 0, led_start, led_finish);
  425.    
  426.     led_start = led_finish;
  427.     led_finish = led_finish + colorOffset;
  428.    
  429.     strip_fill(0,150,0,led_start,led_finish);
  430.    
  431.     led_start = led_finish;
  432.     led_finish = led_finish + colorOffset;
  433.    
  434.     strip_fill(0,75,150,led_start, led_finish);
  435.    
  436.     led_start = led_finish;
  437.     led_finish = led_finish + colorOffset;
  438.    
  439.     strip_fill(0, 0, 150, led_start, led_finish);
  440.    
  441.     led_start = led_finish;
  442.     led_finish = led_finish + colorOffset;
  443.    
  444.     strip_fill(75,0,150,led_start,led_finish);
  445.    
  446.     led_start = led_finish;
  447.     led_finish = led_finish + colorOffset;
  448.    
  449.     strip_fill(150,0,150,led_start, led_finish);
  450.    
  451.     strip_show();
  452. }
  453.  
  454.  
  455. //sets the LEDs to no color. Be careful, even though the LEDs are off, the neopixels still draw current
  456. //because they are doing work to send zeros across each other.
  457. void strip_clear()
  458. {
  459.     strip_fill(0,0,0,0,NUM_LEDS);
  460. }
  461.  
  462.  
Add Comment
Please, Sign In to add comment