Garage Door Opener Program Idea Sketch (CY8CKIT-059)

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

=== precaution ===

There was a discussion/request for a garage door opener sample using PSoC 5LP (CY8CKIT-059)

Need help for coding a project for nursing home (senior home) using PSoC 5LP (using the CY8CKIT-059)...

As discussed in the thread, it is dangerous and probably prohibited to install/use the system developed by an amateur

especially without certification for such applications.

So this example is an idea sketch and is not intended to be used with real hardware which can cause a human injury or worse.

================

Having written above, here is my trial with CY8CKIT-059.

IMG_4545.JPG

schematic

002-schematic.JPG

Digital Input

SW : Switch button input to operate the system. (active-low)

full_open: Sensor switch which will detect that the garage door is fully open. (active-low)

full_close: Sensor switch which will detect that the garage door is fully close. (active-low)

motion: Input from the motion sensor. (Although IR E18-D50INK is active-high, I just used an active-low switch for this test)

Digital Output:

UP_MOTOR: Motor switch signal to open (up) the garage door. (active-high)

DOWN_MOTOR: Motor switch signal to close (down) the garage door (active-high)

Needless to say, these two output is too weak to drive real motor, external relays or drivers needed to be applied.

LCD and ADC1:

This was added to support the light sensor (LDR GL55) but as I don't have the LCD nor the Sensor

I only tested it with an external POT via UART.

UART:

As usual for monitoring the activity of the system.

Pins

003-Pins.JPG

code description

usual utility functions

void print(char *str) : print str to UART

void locate(int x, int y) : move cursor to position (x, y) in the serial terminal, supporting vt100 sequence

void cls(void) : reset and clear the screen of the serial terminal

void splash(char *str) : display start up message with the compiled date and time.

State Values

ST_DOOR_ERROR   /* An Error detected, the system is halted */

ST_DOOR_CLOSED   /* The door is totally closed */

ST_DOOR_CLOSING /* The door is in the middle of closing */

ST_DOOR_STOPPED /* The door is stopped somewhere between fully opened and fully closed */

ST_DOOR_OPENING /* The door is in the middle of opening */

ST_DOOR_OPENED   /* The door is totally opened */

Time parameters

DOOR_OPEN_DURATIN        300  The door closes automatically after opened for 5min without motion

MOTOR_UP_DURATION          60 The maximum running time of door opening motor

MOTOR_DOWN_DURATION     60 The maximum running time of door closing motor

SysTick related functions

CY_ISR(tick_callback) : called each 1ms by SysTick and keeping track of current_state_time

int find_empty_slot(void) : find an unused SysTick slot

void init_hardware(void)

initializes components, ADC1, LCD, UART and SysTick

also writes 0 to DOWN_MOTOR output and UP_MOTOR output

void measure_light(void)

measures light sensor's value using ADC1

print the result to LCD and UART

currently LCD is not used, to activate LCD change definition of USE_LCD from 0 to 1

void change_status(uint8_t current, uint8_t next)

reset current_state_time to 0

saves current status as prev_status

changes door_status from current to next

void poll_status(void)

check conditions of each switches

motion_flag : status of motion input

full_opened_flag : status of full_open input

full_closed_flag : status of full_closed input

if both full_opened_flag and full_closed_flag is true, treat it as error

and change_status to ST_DOOR_ERROR

void do_state_closed(void)

     process of when the door is fully closed.

     motion input is ignored

     SW input changes the state to ST_DOOR_OPENING

void do_state_closing(void)

     process of during the door is closing

     UP_MOTOR <= 0

     DOWN_MOTOR <= 1

     motion input changes the state to ST_DOOR_STOPPED

     SW input changes the state to ST_DOOR_STOPPED

     full_close input changes the state to ST_DOOR_CLOSED

     if current_state_time exceeds MOTOR_DOWN_DURATION changes the state to ST_DOOR_ERROR

void do_state_stopped(void)

     process of during the door is stopped bitween full_open and full_close

     motion input is ignored

     SW input (starts the movement in the reverse direction)

          if prev_status was ST_DOOR_OPENING changes the state to ST_DOOR_CLOSING

          if prev_status was ST_DOOR_CLOSING changes the state to ST_DOOR_OPENING

void do_state_opening(void)

     process of during the door is opening

     UP_MOTOR <= 1

     DOWN_MOTOR <= 0

     motion input changes the state to ST_DOOR_STOPPED (maybe this can be ignored though)

     SW input changes the state to ST_DOOR_STOPPED

     full_open input changes the state to ST_DOOR_OPNED

     if current_state_time exceeds MOTOR_UP_DURATION changes the state to ST_DOOR_ERROR

void do_state_opned(void)

     process of during the door is fully opened

     motion input resets current_state_time to 0

     SW input changes the state to ST_DOOR_CLOSING

     if current_state_time exceeds DOOR_OPEN_DURATION changes the state to ST_DOOR_CLOSING

main.c (the whole enchilada)

=======================

/***

* Prototype for a garage door opener

* This program is intended for experiment

* Not for the real use.

*

*/

#include "project.h"

#include "stdio.h"

#include "math.h"

void poll_status(void) ;

#define ESC '\033'

#define STR_BUF_LEN 32

char str[STR_BUF_LEN+1] ;

#define USE_LCD 0

void print(char *str)

{

    UART_PutString(str) ;

}

void locate(int x, int y)

{

    sprintf(str,"%c[%d;%dH",ESC,y,x) ;

    print(str) ;

}

void cls(void)

{

    print("\033c") ; /* reset */

    CyDelay(100) ;

    print("\033[2J") ; /* clear screen */

    CyDelay(100) ;

}

void splash(char *title)

{

    cls() ;

    if (title && *title) {

        print(title) ;

        print(" ") ;

    }

    snprintf(str, STR_BUF_LEN, "(%s %s)\n\r", __DATE__, __TIME__) ;

    print(str) ;

}

/*

* garage door specific

*/

#define ST_DOOR_ERROR   0x00

#define ST_DOOR_CLOSED  0x01

#define ST_DOOR_CLOSING 0x02

#define ST_DOOR_STOPPED 0x03

#define ST_DOOR_OPENING 0x04

#define ST_DOOR_OPENED  0x05

#define DOOR_OPEN_DURATIN   300 /* 5 min = 5 * 60  = 300 */

#define MOTOR_UP_DURATION   60

#define MOTOR_DOWN_DURATION 60

char *state_name[] = {

    "Door Error",

    "Door Closed",

    "Door Closing",

    "Door Stopped",

    "Door Opening",

    "Door Opened"

} ;

volatile int motion_flag = 0 ;

volatile uint32_t current_state_time = 0 ;

int sw_flag = 0 ;

int full_opened_flag = 0 ;

int full_closed_flag = 0 ;

uint8_t door_status = ST_DOOR_CLOSED ;

uint8_t prev_status = ST_DOOR_CLOSED ;

volatile uint32_t tick_count = 0 ;

volatile int sec_flag = 0 ;

volatile int poll_flag = 0 ;

int sys_tick_slot = 0 ;

CY_ISR(tick_callback)

{

    tick_count++ ;

    if ((tick_count % 1000) == 0) { /* 1sec passed */

        current_state_time++ ;

        sec_flag = 1 ;

    }

}

int find_empty_slot(void)

{

    int result = -1 ;

    uint32_t i ;

    for (i = 0 ; i < CY_SYS_SYST_NUM_OF_CALLBACKS ; i++ ) {

        if (CySysTickGetCallback(i) == NULL) {

            result = i ;

            break ;

        }

    }

    return(result) ;

}

void init_hardware(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

    DOWN_MOTOR_Write(0) ; /* down motor off */

    UP_MOTOR_Write(0) ;   /* up motor off */

   

    ADC1_Start() ;

   

    LCD_Start() ;

    UART_Start() ;

   

    sys_tick_slot = find_empty_slot() ;

    if (sys_tick_slot < 0) {

        print("Sorry No empty SysTick Slot available\n\r") ;

        while(1) { } /* halting here */

    } else {

        CySysTickStart() ;

        CySysTickSetCallback(sys_tick_slot, tick_callback) ;

    } 

}

void measure_light(void)

{

    float lux ;

    float32 raw, conv ;

    ADC1_StartConvert() ;

    ADC1_IsEndConversion(ADC1_WAIT_FOR_RESULT) ;

    raw = ADC1_GetResult16(0) ;

    conv = ((5.000000 * raw)/1024) * 0.232 ;

    lux = ((2500/conv) - 500) / 5 ;

    if (lux < 0) {

        lux = 0 ;

    }

    sprintf(str, "%d.%01d Lux", (int)lux, ((int)lux * 10)%10) ;

#if USE_LCD

    LCD_Position(1, 7) ;

    CyDelay(200) ;

#endif

//    locate(7, 1) ;

    print(str) ;

    print("\n\r") ;

}

void change_status(uint8_t current, uint8_t next)

{

    print("Status: ") ;

    print(state_name[current]) ;

    print(" -> ") ;

    print(state_name[next]) ;

    print("\n\r") ;

    current_state_time = 0 ;

    prev_status = current ;

    door_status = next ;

}

void poll_status(void)

{

    sw_flag = (SW_Read() == 0) ? 1 : 0 ;

    motion_flag = (motion_Read() == 0) ? 1 : 0 ; /* for testing, The sensor is active High */

    full_opened_flag = (full_open_Read() == 0) ;

    full_closed_flag = (full_close_Read() == 0) ;

    if (full_opened_flag && full_closed_flag) {

        print("Both full-open and full-close are active!\n\r") ;

        change_status(door_status, ST_DOOR_ERROR) ;

    }

}

void do_state_closed(void)

{

    UP_MOTOR_Write(0) ;

    DOWN_MOTOR_Write(0) ;

    if (motion_flag) {

        motion_flag = 0 ;

    } else if (sw_flag) {

        sw_flag = 0 ;

        change_status(ST_DOOR_CLOSED, ST_DOOR_OPENING) ;

    }

}

void do_state_closing(void)

{

    UP_MOTOR_Write(0) ;

    DOWN_MOTOR_Write(1) ;

    if (motion_flag) {

        motion_flag = 0 ;

        change_status(ST_DOOR_CLOSING, ST_DOOR_STOPPED) ;

    } else if (sw_flag) {

        sw_flag = 0 ;

        change_status(ST_DOOR_CLOSING, ST_DOOR_STOPPED) ;

    } else if (current_state_time > MOTOR_DOWN_DURATION) {

        print("Closing duration time exceeded!\r\n") ;

        change_status(ST_DOOR_CLOSING, ST_DOOR_ERROR) ;

    } else if (full_closed_flag) {

        print("Door fully closed!\n\r") ;

        change_status(ST_DOOR_CLOSING, ST_DOOR_CLOSED) ;

    }

}

void do_state_stopped(void)

{

    UP_MOTOR_Write(0) ;

    DOWN_MOTOR_Write(0) ;

    if (motion_flag) {

        motion_flag = 0 ;

        /* do nothing here */

    } else if (sw_flag) {

        CyDelay(50) ;

        sw_flag = 0 ;

        switch(prev_status) {

        case ST_DOOR_OPENING:

            change_status(ST_DOOR_STOPPED, ST_DOOR_CLOSING) ;

            break ;

        case ST_DOOR_CLOSING:

            change_status(ST_DOOR_STOPPED, ST_DOOR_OPENING) ;

            break ;

        default:

            change_status(ST_DOOR_STOPPED, ST_DOOR_ERROR) ;

            break ;

        }

    }

}

void do_state_opening(void)

{

    UP_MOTOR_Write(1) ;

    DOWN_MOTOR_Write(0) ;

    if (motion_flag) {

        motion_flag = 0 ;

        change_status(ST_DOOR_OPENING, ST_DOOR_STOPPED) ;

    } else if (sw_flag) { /* sw was pushed, stop openning */

        sw_flag = 0 ;

        change_status(ST_DOOR_OPENING, ST_DOOR_STOPPED) ;

    } else if (current_state_time > MOTOR_UP_DURATION) {

        print("Opening duration time exceeded!\r\n") ;

        change_status(ST_DOOR_OPENING, ST_DOOR_ERROR) ;

    } else if (full_opened_flag) {

        print("Door fully opened!\n\r") ;

        change_status(ST_DOOR_OPENING, ST_DOOR_OPENED) ;

    }

}

void do_state_opened(void)

{

    UP_MOTOR_Write(0) ;

    DOWN_MOTOR_Write(0) ;

    if (motion_flag) {

        motion_flag = 0 ;

        current_state_time = 0 ;

    } else if (sw_flag == 1) {

        sw_flag = 0 ;

        change_status(ST_DOOR_OPENED, ST_DOOR_CLOSING) ;

    } else if (current_state_time > DOOR_OPEN_DURATIN) {

        print("Idle Time Exceeded, Closing the door\n\r") ;

        change_status(ST_DOOR_OPENED, ST_DOOR_CLOSING) ;       

    }

}

void do_state_error(void)

{

    UP_MOTOR_Write(0) ;

    DOWN_MOTOR_Write(0) ;

    print("ERROR Condition Detected!\n\r") ;

    for (;;) { } /* halt here */

}

void do_state_machine(void)

{

    switch(door_status) {

    case ST_DOOR_CLOSED:  do_state_closed()  ; break ;

    case ST_DOOR_CLOSING: do_state_closing() ; break ;

    case ST_DOOR_STOPPED: do_state_stopped() ; break ;

    case ST_DOOR_OPENING: do_state_opening() ; break ;

    case ST_DOOR_OPENED:  do_state_opened()  ; break ;

    default:

        door_status = ST_DOOR_ERROR ;

        do_state_error() ;

        break ;

    }

}

int main(void)

{

    init_hardware() ;

   

    splash("CY8CKIT-059 garage door algorithm test") ;

   

    for(;;)

    {

/*

        if (sec_flag) {

            sec_flag = 0 ;

            measure_light() ;

        }

*/ 

        poll_status() ;

        if (motion_flag) {

            print("Motion Detected!\n\r") ;

            CyDelay(100) ; /* debouncing */

        } else if (sw_flag) {

            print("SW pushed!\n\r") ;

            CyDelay(100) ; /* debouncing */

        }

        do_state_machine() ;

        CyDelay(100) ;

    }

}

=======================

Tera Term log (test cases)

001-TeraTerm-log.JPG

First I tested the "normal" operation.

After resetting the board

(1) I pushed SW and the mode changed from Door Closed to Door Opening

(2) I pushed full_open and the mode changed from Door Opening to Door Opened

(3) I pushed SW and the mode changed from Door Opened to Door Closing

(4) I pushed full_close and the mode changed from Door Closing to Door Closed.

Then I tested door stop and reverse by the SW

(5) I pushed SW and the mode changed from Door Closed to Door Opening

(6) I pushed SW and the mode changed from Door Opening to Door Stopped

(7) I pushed SW and the mode changed from Door Stopped to Door Closing (Note: Direction is reversed)

(8) I pushed SW and the mode changed from Door Closing to Door Stopped

004-open-time-exceeded.JPG

I reset the system.

(9) I pushed SW and the mode changed from Door Closed to Door Opening

(10) I kept the system untouched more than a min.

Then UP_MOTOR_DURATION time exceeded and the mode changed from Door Opening to Door Error

005-close-time-exceeded.JPG

I reset the system

(11) I pushed SW and the mode changed from Door Closed to Door Opening

(12) I pushed full_open and the mode changed from Door Opening to Door Opened

(13) I pushed SW and the mode changed from Door Opened to Door Closing

(14) I kept the system untouched more than a min.

The DOWN_MOTOR_DURATION time exceeded and the mode changed from Door Closing to Door Error

006-Door-auto-close.JPG

I reset the system

(15) I pushed SW and the mode changed from Door Closed to Door Opening

(16) I pushed full_open and the mode changed from Door Opening to Door Opened

(17) I kept the system untouched more than 5 min (300 sec).

The DOOR_OPEN_DURATIN time exceeded and the mode changed from Door Opened to Door Closing

(18) I pushed full_close and the mode changed from Door Closing to Door Closed.

moto

1 Reply
ArPa_4801991
Level 1
Level 1
First like received

Arrivato gosaimas-ta!

Tanaka-san

I have tested your code, thanks a lot for your help and support.

Your help is greatly appreciated!

Arath