Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Ashok R
Published © CC BY-NC-ND

Micron UV Robotic Arm

An autonomous UV Robotic Arm handles cleaning, sanitizing surfaces in any environment.

IntermediateShowcase (no instructions)Over 3 days537
Micron UV Robotic Arm

Things used in this project

Hardware components

Cypress CY8CKIT-044 PSoC® 4 M-Series Pioneer Kit
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×3
Arduino UNO Click Shield
MIKROE Arduino UNO Click Shield
×1
MikroE Eink Display
×1
LED (generic)
LED (generic)
×2
Jumper wires (generic)
Jumper wires (generic)
×1
Craft Wood
×1

Software apps and online services

PSoC Creator
Cypress PSoC Creator
Image2Lcd

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)
Hacksaw Blade

Story

Read more

Custom parts and enclosures

3D Concept Design

Schematics

Schematic

Code

Main Code

C/C++
/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include "project.h"
#include "spi_comm.h"
#include "tle94112.h"
#include "pwm.h"
#include "ssd1608.h"
#include "images.h"

void TimerCounterStart();
void uv_config_table();
void uv_config_printer();
void uv_config_gym();
void uv_cleaning(uint8_t mode);
uint8_t motion_detected=0;
uint16_t debug[10];

uint8_t mode =0;

CY_ISR_PROTO(GPIOIsrHandler);

CY_ISR(GPIOIsrHandler)
{
    /* Clear pending Interrupt */
    isr_GPIO_ClearPending(); 
    
    SW1_ClearInterrupt();
    
  
   mode++;
   GLED_Write(1);
   if(mode >2) mode =0;

   switch(mode)
{
    case 0:  
    eink154_displayImage(gImage_epd_table);
    uv_config_table();
    break;
    case 1:
    eink154_displayImage(gImage_epd_print);
    uv_config_printer();
    break;
    case 2:
    eink154_displayImage(gImage_epd_gym);
    uv_config_gym();
    break;
}
    
}

CY_ISR(TC_InterruptHandler)
{
    /* Clears the Timer terminal count interrupt */
    Timer_ClearInterrupt(Timer_INTR_MASK_TC);
    
    GLED_Write(0);
    CyDelay(1000);
    uv_cleaning(0);
    uv_cleaning(0);
    CyDelay(1000);
    GLED_Write(1);
    
}

void uv_cleaning(uint8_t mode)
{ 
    setangle(0,0,60);
    CyDelay(1000);
    setangle(0,130,60);
    CyDelay(1000);    
}


void uv_config_table()
{
    setangle(0,60,60);
    setangle(1,150,60);
    setangle(2,80,60); 
    
}

void uv_config_printer()
{
    
    setangle(0,60,60);
    setangle(1,10,60);
    setangle(2,40,60);    
    
}

void uv_config_gym()
{
    
    setangle(0,60,60);
    setangle(1,90,60);
    setangle(2,100,60);    
    
}

void set_timeout(uint8_t mode)
{
    if(mode == 1)
    {
        RLED_Write(0);
        GLED_Write(1);
        motion_detected = 1;
    }
    else
    {
        RLED_Write(1);
        
        if(motion_detected)
        {
        TimerCounterStart();
        //clean
        motion_detected=0;
        }
    }
 		   
    
}


void TimerCounterStart()
{
    
    /* Starts the timer */
    Timer_Start();
    
    /* Enable interrupt component and set up handler */
    TC_Interrupt_StartEx(TC_InterruptHandler);
    
}

int main(void)
{
    
    	/* Proximity sensor state. */
	uint8 proximity  = INACTIVE;
    
	/* This variable is used to implement a software counter. If the value
	 * of this counter is greater than 100, the proximity sensor was inactive
	 * for more than 3s. */
	uint8 softCounter = RESET;

	/* Variable to store the WDT match value. */
	uint16 currentCountVal = ZERO;

	/* Variable to determine whether to update the WDT match value. */
	uint8 updateMatch = UPDATE_100MS;
    
    //isr_GPIO_Start();
    
      /* Sets up the GPIO interrupt and enables it */
    isr_GPIO_StartEx(GPIOIsrHandler);

    
    CyGlobalIntEnable; /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    
       /* Start SPIS and SPIM components operation */
    SPIM_Start();
    
 /* Sets up the GPIO interrupt and enables it */

    PWM_1_Start();
    PWM_2_Start();

    DC_Write(1);
    RES_Write(1);
    
    
	/* Enable and start the CapSense block. */
	CapSense_Start();

	/* Initialize the baselines of all CapSense widgets. */
	CapSense_InitializeSensorBaseline(CapSense_SENSOR_PROXIMITYSENSOR_0__PROX);

    
    eink154_startConfig();
    eink154_setLut();
    eink154_displayImage(gImage_epd_table);
    

    while(1)
    {      
      
        
/* Update the baseline of the proximity sensor. */
		CapSense_UpdateSensorBaseline(CapSense_SENSOR_PROXIMITYSENSOR_0__PROX);

		/* Scan the proximity sensor. */
		CapSense_ScanSensor(CapSense_SENSOR_PROXIMITYSENSOR_0__PROX);

		/* Wait till the scan is complete*/
		while(CapSense_IsBusy())
		{
			/* Put the PSoC 4200M in Sleep power mode while the CapSense is scanning.
			 * The device wakes up using the interrupt generated by CapSense CSD Component
			 * after scanning. */
			CySysPmSleep();
		}

		/* Check if proximity sensor is active. */
		proximity = CapSense_CheckIsSensorActive(CapSense_SENSOR_PROXIMITYSENSOR_0__PROX);

		if(proximity == ACTIVE)
		{
			/* Set the LED at a brightness level corresponding
			 * to the proximity distance. */
			//LED1_SetBrightness(ON);
            set_timeout(1);
			/* Update the WDT if required. */
			if(updateMatch == UPDATE_30MS)
			{
				/* Configure the wake up period to 30ms and update WDT match value. */
		    	CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, WDT_MATCH_VALUE_30MS);

				/* Read the current count value of the WDT. */
			    currentCountVal = CySysWdtReadCount(CY_SYS_WDT_COUNTER0);

				/* Reset the counter if the count value is greater than
				 * the match value */
			    if (currentCountVal > WDT_MATCH_VALUE_30MS)
			    {
			        CySysWdtResetCounters(CY_SYS_WDT_COUNTER0_RESET);
				}

				/* Provide a delay to allow the changes on WDT register to take
				 * effect. This is approximately 4 LFCLK cycles. */
				CyDelayUs(ILOX4);

				/* Next update to the WDT match value is required only when
				 * switching to 100ms scan interval. */
				updateMatch = UPDATE_100MS;
			}

			/* Reset the software counter if proximity is detected. */
			softCounter = RESET;

			/* Put CPU in sleep mode after displaying output on LED. */
			//CySysPmSleep();
		}
		else /* Proximity sensor is inactive. */
		{
			/* Switch off the LED if proximity is not detected. */
			//LED1_SetBrightness(OFF);
            set_timeout(0); 
			/* Increment the software counter every 30ms if proximity is not detected. */
			softCounter++;

			/* Set the maximum limit for the soft counter. */
			if(softCounter >= MAX_VALUE)
			{
				/* Set the maximum limit for the softCounter. */
				softCounter = MAX_VALUE;

				/* Update the WDT if required. */
				if(updateMatch == UPDATE_100MS)
				{
					/* Proximity sensor is inactive for more than 3s.
					 * Increase Deep-Sleep duration to 100ms and update WDT match value. */
			    	CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, WDT_MATCH_VALUE_100MS);

					/* Read the current count value of the WDT. */
				    currentCountVal = CySysWdtReadCount(CY_SYS_WDT_COUNTER0);

					/* Reset the counter if the count value is greater than
					 * the match value */
				    if (currentCountVal > WDT_MATCH_VALUE_100MS)
				    {
				        CySysWdtResetCounters(CY_SYS_WDT_COUNTER0_RESET);
					}

					/* Provide a delay to allow the changes on WDT register to take
					 * effect. This is approximately 4 LFCLK cycles. */
					CyDelayUs(ILOX4);

					/* Next update to the WDT match value is required only when
					 * switching to 30ms scan interval. */
					updateMatch = UPDATE_30MS;
				}
			}        
        
        
     }   
    }

    

}



/* [] END OF FILE */

SPI Code

C/C++
/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include "spi_comm.h"



uint16_t spi_write(uint8_t *data , uint32_t length)
{
   uint8 rxBuffer[2];
    uint8 dummyBuffer[2]={0};
   uint16 status;
    uint32 i;
  /* Start transfer */
    SPIM_SpiUartPutArray(data, length);
    

  // Wait for the transmission to complete

    while(0 != (SPIM_SpiUartGetTxBufferSize() | SPIM_SpiIsBusBusy()))

    {

    }
    
    return (status);

    
}


uint16 spi_read(uint8_t *data, uint8_t length)
{
    uint8 rxBuffer[2];
    uint16 status;
    uint32 i;
    
    SPIM_SpiUartClearRxBuffer();
    
    /* Start transfer */
    SPIM_SpiUartPutArray(data, length);

       
    /* Wait for the end of the transfer. The number of transmitted data
    * elements has to be equal to the number of received data elements.
    */
    while (length != SPIM_SpiUartGetRxBufferSize())
    {
    }
    /* Read data from the RX buffer */
    i = 0u;
    while (0u != SPIM_SpiUartGetRxBufferSize())
    {
        rxBuffer[i] = SPIM_SpiUartReadRxData();
        i++;
    }
    
    status = rxBuffer[1];
    status = status<<8;
    status |= rxBuffer[0];


    return (status);
}

Credits

Ashok R

Ashok R

37 projects • 102 followers
Hobbyist/Engineer/Director/Animatior

Comments