phillip_bourdon234

SkittleSorterMain.c

Jul 1st, 2020 (edited)
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.56 KB | None | 0 0
  1. // A video demonstration of this project can be found here: https://bit.ly/2Wfsdqs
  2.  
  3. /*
  4.     PARTS USED:
  5.  
  6.     [1] PIC18F4520
  7.     [5] LEDs (1 clear, 1 blue, 1 yellow, 1 red, 1 green)
  8.     [2] SG90 Servo Motors
  9.     [1] TCS34725 Color Sensor
  10.     [1] 9v Battery
  11.     [1] 5v 1A Power supply
  12.     [1] Elegoo 9v power supply module
  13.     [5] 220 resistors
  14.     [2] 10k resistors
  15.     [40+] jumper wires
  16.     [1] Plastic Funnel
  17.     Lots of cardboard
  18.     Lots of hot glue
  19.  */
  20.  
  21. #include <xc.h>
  22. #include <pic18f4520.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <stdbool.h>
  26. #include <stdint.h>
  27. #include "SkittleSorterConfigBits.h"
  28.  
  29. void __interrupt() HIGH_ISR(void);
  30. int interruptCounter = 0;
  31.  
  32. void bitSetupOscillator(void);
  33. void bitSetupLED(void);
  34. void bitSetupI2C(void);
  35. void bitSetupPWM(void);
  36. void bitSetupInterrupt(void);
  37.  
  38. void PWM_Set(uint16_t duty, char specifiedServo);
  39.  
  40. void i2cIdleCheck(void);
  41. void i2cStart(void);
  42. void i2cStop(void);
  43. void i2cRepStart(void);
  44. void i2cWrite(uint8_t data);
  45. uint8_t i2cRead(uint8_t ack);
  46.  
  47. void enableColorSensor(void);
  48. void setColorSensorInterrupt(bool i);
  49. void getRawData(uint16_t *redHigh, uint16_t *greenHigh, uint16_t *blueHigh,
  50.                 uint16_t *clearHigh);
  51.  
  52. void moveSpecificServo(uint16_t servoBaseVal, char specifiedServo);
  53. void handleLEDs(char red, char orange, char yellow, char green, char purple);
  54.  
  55. void main(void)
  56. {
  57.     uint16_t servoSlideVal;
  58.     uint16_t red;
  59.     uint16_t green;
  60.     uint16_t blue;
  61.     uint16_t clear;
  62.    
  63.     uint16_t *pRed = &red;
  64.     uint16_t *pGreen = &green;
  65.     uint16_t *pBlue = &blue;
  66.     uint16_t *pClear = &clear;
  67.    
  68.     bitSetupOscillator();
  69.     bitSetupLED();  
  70.     bitSetupI2C();
  71.     bitSetupPWM();
  72.     bitSetupInterrupt();
  73.    
  74.     enableColorSensor();
  75.    
  76.     while(1)
  77.     {
  78.         if(interruptCounter == 2)
  79.         {
  80.             setColorSensorInterrupt(false);
  81.        
  82.             getRawData(pRed, pGreen, pBlue, pClear);
  83.        
  84.             setColorSensorInterrupt(true);
  85.         }
  86.         else
  87.         {
  88.             red = green = blue = 0;
  89.         }
  90.        
  91.         if(clear == 0)
  92.         {
  93.             red = green = blue = 0;
  94.         }
  95.         else
  96.         {
  97.             red = (float)red / clear * 255.0;
  98.             green = (float)green / clear * 255.0;
  99.             blue = (float)blue / clear * 255.0;
  100.         }
  101.        
  102.         if(red > 100 && blue >= 47) //red
  103.         {
  104.             servoSlideVal = 25;
  105.             handleLEDs(1,0,0,0,0);
  106.             moveSpecificServo(servoSlideVal, SERVO_SLIDE);
  107.         }
  108.         else if(red > 100 && blue < 47 && green < 70) //orange
  109.         {
  110.             servoSlideVal = 33;
  111.             handleLEDs(0,1,0,0,0);
  112.             moveSpecificServo(servoSlideVal, SERVO_SLIDE);
  113.         }
  114.         else if(red >= 80 && green > 80 && blue < 45) //yellow
  115.         {
  116.             servoSlideVal = 40;
  117.             handleLEDs(0,0,1,0,0);
  118.             moveSpecificServo(servoSlideVal, SERVO_SLIDE);
  119.         }
  120.         else if(green > 110 && red < 80) //green
  121.         {
  122.             servoSlideVal = 47;
  123.             handleLEDs(0,0,0,1,0);
  124.             moveSpecificServo(servoSlideVal, SERVO_SLIDE);
  125.         }
  126.         else if(green > 80 && blue > 63 && red > 79) //purple
  127.         {
  128.             servoSlideVal = 56;
  129.             handleLEDs(0,0,0,0,1);
  130.             moveSpecificServo(servoSlideVal, SERVO_SLIDE);
  131.         }
  132.         else
  133.         {
  134.             handleLEDs(0,0,0,0,0);
  135.         }
  136.     }
  137.     return;
  138. }
  139.  
  140. void __interrupt() HIGH_ISR()
  141. {
  142.     INTCONbits.GIEH = 0;  
  143.    
  144.     if(INTCONbits.TMR0IF)
  145.     {
  146.        interruptCounter ++;
  147.        if(interruptCounter == 1)
  148.        {
  149.            moveSpecificServo(44, SERVO_BASE);
  150.        }
  151.        if(interruptCounter == 3)
  152.        {
  153.            moveSpecificServo(25, SERVO_BASE);
  154.        }
  155.        if(interruptCounter == 4)
  156.        {
  157.            moveSpecificServo(73, SERVO_BASE);
  158.            interruptCounter = 0;
  159.        }
  160.        INTCONbits.TMR0IF = 0;
  161.     }
  162.    
  163.     INTCONbits.GIEH = 1;
  164. }
  165.  
  166. void bitSetupInterrupt()
  167. {
  168.     RCONbits.IPEN = 1;
  169.    
  170.     INTCONbits.TMR0IE = 1;
  171.     INTCON2bits.TMR0IP = 1;
  172.     T0CONbits.TMR0ON = 0; //turn timer off
  173.     T0CONbits.T08BIT = 1; //configure timer to an 8 bit timer
  174.     T0CONbits.T0CS = 0; //sets the clock source to the internal oscillator
  175.     T0CONbits.PSA = 0; //assign prescaler
  176.     T0CONbits.T0PS = 0b111; //sets prescaler value 1:2  
  177.     T0CONbits.TMR0ON = 1;
  178.    
  179.     INTCONbits.GIEH = 1;
  180. }
  181.  
  182. void bitSetupOscillator()
  183. {
  184.     OSCCONbits.IRCF = 0b011; //500kHz
  185.     OSCCONbits.SCS = 0b10;
  186.     while(!OSCCONbits.IOFS);
  187. }
  188.  
  189. void bitSetupLED()
  190. {
  191.     TRISE = 0;
  192.     TRISDbits.RD0 = 0;
  193.     TRISDbits.RD1 = 0;
  194.     LATE = 0;
  195.     LATDbits.LD0 = 0;
  196.     LATDbits.LD1 = 0;
  197. }
  198.  
  199. void bitSetupI2C()
  200. {
  201.     TRISCbits.RC3 = 1; //SCL
  202.     TRISCbits.RC4 = 1; //SDA
  203.    
  204.     SSPSTATbits.SMP = 1; //disables slew rate
  205.     SSPSTATbits.CKE = 0; //disables SMBus
  206.    
  207.     SSPCON1bits.SSPM = 0b1000; //I2C Master mode clock = FOSC/(4 * (SSPADD + 1))
  208.     SSPADD = 11; //100kHz
  209.     SSPCON1bits.SSPEN = 1; //enables serial port and SDA/SCL pins
  210. }
  211.  
  212. void bitSetupPWM()
  213. {
  214.     TRISCbits.RC1 = 0;
  215.     TRISCbits.RC2 = 0;
  216.     T2CONbits.T2OUTPS = 0x00; //Postscale = 0
  217.     T2CONbits.T2CKPS = 0b10; //Prescaler = 16
  218.     PR2 = 156; //appropriate PR2 value to get a 50Hz pwm frequency
  219.    
  220.     CCP2CONbits.DC2B = 0; //clears the last 2 bits of the pwm duty cycle
  221.     CCP2CONbits.CCP2M = 0b1100; //puts the CCP into pwm mode
  222.     CCPR2L = 0; //clears the first 8 bits of the pwm duty cycle
  223.    
  224.     CCP1CONbits.DC1B = 0;
  225.     CCP1CONbits.CCP1M = 0b1100;
  226.     CCPR1L = 0;
  227.    
  228.     T2CONbits.TMR2ON = 1;
  229. }
  230.  
  231. void PWM_Set(uint16_t duty, char specifiedServo)
  232. {
  233.     if(specifiedServo == 1)
  234.     {
  235.         CCP2CONbits.DC2B = (uint8_t)(duty & 0x0003); //parses the last 2 bits of the pwm cycle
  236.         CCPR2L = (uint8_t)(duty >> 2);
  237.     }
  238.     else
  239.     {
  240.         CCP1CONbits.DC1B = (uint8_t)(duty & 0x0003);
  241.         CCPR1L = (uint8_t)(duty >> 2);      
  242.     }
  243. }
  244.  
  245. void i2cIdleCheck()
  246. {
  247.     while((SSPCON2 & 0x1F) || (SSPSTAT & 0x04)); // waits until
  248.                                                  // the i2c bus is in
  249.                                                  // an idle state.
  250. }
  251.  
  252. void i2cStart()
  253. {
  254.     i2cIdleCheck();
  255.     SSPCON2bits.SEN = 1; //initiates a start command
  256. }
  257.  
  258. void i2cStop()
  259. {
  260.     i2cIdleCheck();
  261.     SSPCON2bits.PEN = 1; //initiates a stop command
  262. }
  263.  
  264. void i2cRepStart()
  265. {
  266.     i2cIdleCheck();
  267.     SSPCON2bits.RSEN = 1; //initiates a repeat start command
  268. }
  269.  
  270. void i2cWrite(uint8_t data)
  271. {
  272.     i2cIdleCheck();
  273.     SSPBUF = data; //loads data into buffer
  274.     while(SSPSTATbits.BF != 0); //makes sure that the data leaves the buffer
  275.     while(SSPCON2bits.ACKSTAT != 0); //makes sure that the master receives an ACK from slave
  276. }
  277.  
  278. uint8_t i2cRead(uint8_t ack)
  279. {
  280.     uint8_t receive = 0;
  281.     i2cIdleCheck();
  282.     SSPCON2bits.RCEN = 1; //puts master into receive mode
  283.     while(SSPSTATbits.BF != 1); //waits until buffer is full
  284.     receive = SSPBUF; //loads data from buffer into variable
  285.     SSPCON2bits.ACKEN = ack;
  286.     return receive;
  287. }
  288.  
  289. void enableColorSensor()
  290. {
  291.     __delay_ms(500);
  292.    
  293.     i2cStart();
  294.     i2cWrite(TCS34725_WRITE_ADDRESS);
  295.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_ATIME);
  296.     i2cWrite(0xEB); //sets the wait time to 50ms
  297.     i2cStop();
  298.    
  299.     i2cStart();
  300.     i2cWrite(TCS34725_WRITE_ADDRESS);
  301.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_CONTROL);
  302.     i2cWrite(0x01); //sets the gain to 4x
  303.     i2cStop();
  304.    
  305.     i2cStart();
  306.     i2cWrite(TCS34725_WRITE_ADDRESS);
  307.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_ENABLE);
  308.     i2cWrite(TCS34725_ENABLE_PON); //powers on the colorSensor
  309.     i2cStop();
  310.     __delay_ms(3);
  311.    
  312.     i2cStart();
  313.     i2cWrite(TCS34725_WRITE_ADDRESS);
  314.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_ENABLE);
  315.     i2cWrite(TCS34725_ENABLE_PON | TCS34725_ENABLE_AEN); //enables the color
  316.                                                          //sensors interrupts
  317.     i2cStop();
  318.     __delay_ms(500);
  319. }
  320.  
  321. void getRawData(uint16_t *redHigh, uint16_t *greenHigh, uint16_t *blueHigh,
  322.                 uint16_t *clearHigh)
  323. {
  324.     uint8_t redLow;
  325.     uint8_t greenLow;
  326.     uint8_t blueLow;
  327.     uint8_t clearLow;
  328.    
  329.     i2cStart();
  330.     i2cWrite(TCS34725_WRITE_ADDRESS);
  331.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_BDATAL);
  332.     i2cRepStart();
  333.     i2cWrite(TCS34725_READ_ADDRESS);
  334.      
  335.     blueLow = i2cRead(1); //reads the first 8 bits of the 16 bit BDATA register
  336.     *blueHigh = i2cRead(0);//reads the last 8 bits of the 16 bit BDATA register
  337.     i2cStop();
  338.    
  339.     *blueHigh <<= 8;
  340.     *blueHigh |= blueLow;
  341.      
  342.     i2cStart();
  343.     i2cWrite(TCS34725_WRITE_ADDRESS);
  344.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_GDATAL);
  345.     i2cRepStart();
  346.     i2cWrite(TCS34725_READ_ADDRESS);
  347.      
  348.     greenLow = i2cRead(1);
  349.     *greenHigh = i2cRead(0);
  350.     i2cStop();  
  351.    
  352.     *greenHigh <<= 8;
  353.     *greenHigh |= greenLow;
  354.      
  355.     i2cStart();
  356.     i2cWrite(TCS34725_WRITE_ADDRESS);
  357.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_RDATAL);
  358.     i2cRepStart();
  359.     i2cWrite(TCS34725_READ_ADDRESS);
  360.      
  361.     redLow = i2cRead(1);
  362.     *redHigh = i2cRead(0);
  363.     i2cStop();  
  364.    
  365.     *redHigh <<= 8;
  366.     *redHigh |= redLow;
  367.    
  368.     i2cStart();
  369.     i2cWrite(TCS34725_WRITE_ADDRESS);
  370.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_CDATAL);
  371.     i2cRepStart();
  372.     i2cWrite(TCS34725_READ_ADDRESS);
  373.      
  374.     clearLow = i2cRead(1);
  375.     *clearHigh = i2cRead(0);
  376.     i2cStop();  
  377.    
  378.     *clearHigh <<= 8;
  379.     *clearHigh |= clearLow;
  380.    
  381.     __delay_ms(50);
  382. }
  383.  
  384. void setColorSensorInterrupt(bool i)
  385. {
  386.     uint8_t r;
  387.     i2cStart();
  388.     i2cWrite(TCS34725_WRITE_ADDRESS);
  389.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_ENABLE);
  390.     i2cRepStart();
  391.     i2cWrite(TCS34725_READ_ADDRESS);
  392.     r = i2cRead(0); //reads current interrupt state
  393.     i2cStop();
  394.    
  395.     if(i)
  396.     {
  397.         r |= TCS34725_ENABLE_AIEN; //this line ensures that r will = 1
  398.     }
  399.     else
  400.     {
  401.         r &= ~TCS34725_ENABLE_AIEN; //this line ensures that r will = 0
  402.     }
  403.    
  404.     i2cStart();
  405.     i2cWrite(TCS34725_WRITE_ADDRESS);
  406.     i2cWrite(TCS34725_COMMAND_BIT | TCS34725_ENABLE);
  407.     i2cWrite(r);
  408.     i2cStop();
  409. }
  410.  
  411. void moveSpecificServo(uint16_t servoBaseVal, char specifiedServo)
  412. {
  413.     PWM_Set(servoBaseVal, specifiedServo);
  414. }
  415.  
  416. void handleLEDs(char red, char orange, char yellow, char green, char purple)
  417. {
  418.     LATEbits.LE1 = red;
  419.     LATEbits.LE2 = orange;
  420.     LATEbits.LE0 = yellow;
  421.     LATDbits.LD0 = green;
  422.     LATDbits.LD1 = purple;
  423. }
Add Comment
Please, Sign In to add comment