Sandwich IoT
Published © GPL3+

Prototype a Creative Vending Machine

This tutorial will show you how to prototype a vending machine in a low-code approach based on Tuya’s LZ201 Cat.1 module and MCU SDK.

BeginnerFull instructions provided2 days841
Prototype a Creative Vending Machine

Things used in this project

Hardware components

74HC165
8-bit parallel-input and serial-output shift register, used to determine motor rotation direction.
×1
74HC595
8-bit serial-input and parallel-output shift register, used to output the control signal to motors.
×1
FDS9945
N-channel MOSFET used to drive the motor.
×1
FDS9958
P-channel MOSFET used to drive the motor.
×1
LZ201-CN
Tuya's LZ201-CN Cat.1 cellular module can establish communication between the vending machine and the Tuya IoT Cloud.
×1
STM32
Microcontroller IC used to control the system.
×1
Motor
The gear motor used to control a product falling.
×1
ST-LINK
An in-circuit debugger and programmer for the STM32 microcontroller.
×1

Software apps and online services

Tuya Smart app
https://developer.tuya.com/cn/docs/iot/tuya-smart-app-smart-life-app-advantages?id=K989rqa49
Sample code
https://github.com/Tuya-Community/tuya-iotos-embeded-mcu-demo-4g-vending-machine

Story

Read more

Code

Code snippet #9

Plain text
 /***********************************************************
 *   Function:  HC595Send
 *   Input:     uint16_t
 *   Output:    none
 *   Return:    none
 *   Notice:    Output 16-bit data through pins of the two 74HC595 shift registers.
 ***********************************************************/
void HC595Send(uint16_t data)
{
    uint8_t j;
    LOCK_RESET;
    delay_us(10);
    for (j = 16; j > 0; j--)
    {
		SHIFT_RESET;
        delay_us(10);

        if(data & 0x8000)
        {
            INDATA_SET;
        }
        else
        {
            INDATA_RESET;
        }

        delay_us(10);
        data <<= 1;
        SHIFT_SET;
        delay_us(10);
    }
    LOCK_SET;
    delay_us(10);
}

Code snippet #10

Plain text
 /***********************************************************
 *   Function:  HC595Send
 *   Input:     uint16_t
 *   Output:    none
 *   Return:    none
 *   Notice:    Output 16-bit data through pins of the two 74HC595 shift registers.
 ***********************************************************/
void HC595Send(uint16_t data)
{
    uint8_t j;
    LOCK_RESET;
    delay_us(10);
    for (j = 16; j > 0; j--)
    {
		SHIFT_RESET;
        delay_us(10);

        if(data & 0x8000)
        {
            INDATA_SET;
        }
        else
        {
            INDATA_RESET;
        }

        delay_us(10);
        data <<= 1;
        SHIFT_SET;
        delay_us(10);
    }
    LOCK_SET;
    delay_us(10);
}

Code snippet #15

Plain text
/*****************************************************************************
Function name: dp_download_m_num_handle
Feature description: a processing function for DPID_M_NUM.
Input parameters: value indicates the data source
                : length: the length of the data
Return parameters: Return SUCCESS on success, and ERROR on failure
Instruction: For the send-only data point, the results must be sent to the cloud after the operation is completed.
*****************************************************************************/
static unsigned char dp_download_m_num_handle(const unsigned char value[], unsigned short length)
{
    // Example: This is a data point of raw type.
    unsigned char ret;
		const unsigned char error[6]={"ERROR1"};
    /*
    // Process data of raw type.
    
    */
		if((length==6)&&(value[0]<11)&&(value[1]<10))
		{
			IoT_receive[Q_U3.rear].data[0]=value[0];
			IoT_receive[Q_U3.rear].data[1]=value[1];
			IoT_receive[Q_U3.rear].data[2]=value[2];
			IoT_receive[Q_U3.rear].data[3]=value[3];
			IoT_receive[Q_U3.rear].data[4]=value[4];
			IoT_receive[Q_U3.rear].data[5]=value[5];
			F_TASK_MOTOR_OPEN++;
			rear_inc(&Q_U3);
		}
		else
		{
			mcu_dp_raw_update(DPID_R_NUM,error,6);
		}
    // Return the result of the operation.
    ret = mcu_dp_raw_update(DPID_M_NUM,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}

Code snippet #16

Plain text
/*****************************************************************************
Function name: dp_download_m_num_handle
Feature description: a processing function for DPID_M_NUM.
Input parameters: value indicates the data source
                : length: the length of the data
Return parameters: Return SUCCESS on success, and ERROR on failure
Instruction: For the send-only data point, the results must be sent to the cloud after the operation is completed.
*****************************************************************************/
static unsigned char dp_download_m_num_handle(const unsigned char value[], unsigned short length)
{
    // Example: This is a data point of raw type.
    unsigned char ret;
		const unsigned char error[6]={"ERROR1"};
    /*
    // Process data of raw type.
    
    */
		if((length==6)&&(value[0]<11)&&(value[1]<10))
		{
			IoT_receive[Q_U3.rear].data[0]=value[0];
			IoT_receive[Q_U3.rear].data[1]=value[1];
			IoT_receive[Q_U3.rear].data[2]=value[2];
			IoT_receive[Q_U3.rear].data[3]=value[3];
			IoT_receive[Q_U3.rear].data[4]=value[4];
			IoT_receive[Q_U3.rear].data[5]=value[5];
			F_TASK_MOTOR_OPEN++;
			rear_inc(&Q_U3);
		}
		else
		{
			mcu_dp_raw_update(DPID_R_NUM,error,6);
		}
    // Return the result of the operation.
    ret = mcu_dp_raw_update(DPID_M_NUM,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}

Code snippet #1

Plain text
 /***********************************************************
 *   Function:  USART3_Init
 *   Input:     uint32_t pclk2,uint32_t bound
 *   Output:    none
 *   Return:    none
 *   Notice:    USART initialization
 ***********************************************************/
void USART3_Init(uint32_t pclk2,uint32_t bound)
{  	 
	float temp;
	uint16_t mantissa;
	uint16_t fraction;	   
	temp=(float)(pclk2*1000000)/(bound*16);// Get USARTDIV.
	mantissa=temp;  			    // Get the integer part.
	fraction=(temp-mantissa)*16; // Get the decimal part.  
	mantissa<<=4;
	mantissa+=fraction; 

	RCC->APB2ENR|=1<<3;   // Enable the clock for PORTB.
	RCC->APB1ENR|=1<<18;  // Enable the clock for USART3.
	GPIOB->CRH&=~(0xf<<8|0xf<<12);
	GPIOB->CRH|=0X0B<<8|8<<12;// // Configure GPIO state.   
	GPIOB->ODR|=1<<11;

	RCC->APB1RSTR|=1<<18;   // Reset USART3.
	RCC->APB1RSTR&=~(1<<18);// Stop reset.    	   
	// Set baud rate.
	USART3->BRR=mantissa; // Set baud rate.  
	USART3->CR1|=0X200C;  // No parity, and 1 stop bit. 			USART3->CR1|=1<<8;    // Enable PE interrupt.
	USART3->CR1|=1<<5;    // Enable the RXNE interrupt.     	
	MY_NVIC_Init(1,2,USART3_IRQn,2);// Group 2 		  
} 	

Code snippet #2

Plain text
 /***********************************************************
 *   Function:  USART3_Init
 *   Input:     uint32_t pclk2,uint32_t bound
 *   Output:    none
 *   Return:    none
 *   Notice:    USART initialization
 ***********************************************************/
void USART3_Init(uint32_t pclk2,uint32_t bound)
{  	 
	float temp;
	uint16_t mantissa;
	uint16_t fraction;	   
	temp=(float)(pclk2*1000000)/(bound*16);// Get USARTDIV.
	mantissa=temp;  			    // Get the integer part.
	fraction=(temp-mantissa)*16; // Get the decimal part.  
	mantissa<<=4;
	mantissa+=fraction; 

	RCC->APB2ENR|=1<<3;   // Enable the clock for PORTB.
	RCC->APB1ENR|=1<<18;  // Enable the clock for USART3.
	GPIOB->CRH&=~(0xf<<8|0xf<<12);
	GPIOB->CRH|=0X0B<<8|8<<12;// // Configure GPIO state.   
	GPIOB->ODR|=1<<11;

	RCC->APB1RSTR|=1<<18;   // Reset USART3.
	RCC->APB1RSTR&=~(1<<18);// Stop reset.    	   
	// Set baud rate.
	USART3->BRR=mantissa; // Set baud rate.  
	USART3->CR1|=0X200C;  // No parity, and 1 stop bit. 			USART3->CR1|=1<<8;    // Enable PE interrupt.
	USART3->CR1|=1<<5;    // Enable the RXNE interrupt.     	
	MY_NVIC_Init(1,2,USART3_IRQn,2);// Group 2 		  
} 	

Code snippet #3

Plain text
 /***********************************************************
 *   Function:  USART3_IRQHandler
 *   Input:     none
 *   Output:    none
 *   Return:    none
 *   Notice:    USART interrupt handler function. Receive one byte of data in interrupt mode.
 ***********************************************************/
void USART3_IRQHandler(void)
{
	if(USART3->SR&(1<<5))// Received data.
	{
		uart_receive_input((unsigned char)(USART3->DR));
	}
}

Code snippet #4

Plain text
 /***********************************************************
 *   Function:  USART3_IRQHandler
 *   Input:     none
 *   Output:    none
 *   Return:    none
 *   Notice:    USART interrupt handler function. Receive one byte of data in interrupt mode.
 ***********************************************************/
void USART3_IRQHandler(void)
{
	if(USART3->SR&(1<<5))// Received data.
	{
		uart_receive_input((unsigned char)(USART3->DR));
	}
}

Code snippet #5

Plain text
 /***********************************************************
 *   Function:  Uart3_PutChar
 *   Input:     uint8_t
 *   Output:    none
 *   Return:    uint8_t
 *   Notice:    Send one byte of data to check whether a timeout has happened.
 ***********************************************************/
uint8_t Uart3_PutChar(uint8_t data)
{
	uint8_t ret=1;
	uint16_t timeout=0x8000;

	USART3->DR = data;
	while((USART3->SR&1<<6)! =1<<6)// Wait until the transmission is completed.
	{
		timeout--;
		if( 0 == timeout )
		{
			ret = 1;
			break;
		}
	}

	if( 0 != timeout )
	{
		ret = 0;
	}
	return ret;
}
/**
 * @brief  Send serial data
 * @param[in] {value}  The one byte of data to be sent by UART.
 * @return Null
 */
void uart_transmit_output(u8 value)
{
    //#error "Specify the UART transmission function and delete this line"
	Uart3_PutChar(value);
/*
    // Example:
    extern void Uart_PutChar(u8 value);
    Uart_PutChar(value);                                    // UART transmission function
*/
}

Code snippet #6

Plain text
 /***********************************************************
 *   Function:  Uart3_PutChar
 *   Input:     uint8_t
 *   Output:    none
 *   Return:    uint8_t
 *   Notice:    Send one byte of data to check whether a timeout has happened.
 ***********************************************************/
uint8_t Uart3_PutChar(uint8_t data)
{
	uint8_t ret=1;
	uint16_t timeout=0x8000;

	USART3->DR = data;
	while((USART3->SR&1<<6)! =1<<6)// Wait until the transmission is completed.
	{
		timeout--;
		if( 0 == timeout )
		{
			ret = 1;
			break;
		}
	}

	if( 0 != timeout )
	{
		ret = 0;
	}
	return ret;
}
/**
 * @brief  Send serial data
 * @param[in] {value}  The one byte of data to be sent by UART.
 * @return Null
 */
void uart_transmit_output(u8 value)
{
    //#error "Specify the UART transmission function and delete this line"
	Uart3_PutChar(value);
/*
    // Example:
    extern void Uart_PutChar(u8 value);
    Uart_PutChar(value);                                    // UART transmission function
*/
}

Code snippet #7

Plain text
 /***********************************************************
 *   Function:  HC165In
 *   Input:     none
 *   Output:    none
 *   Return:    uint8_t
 *   Notice:    Read values of the eight pins of 74HC165 and return 8-bit data.
 ***********************************************************/
uint8_t HC165In(void)
{
	uint8_t i,dat=0;
	CP_SET;
	PL_RESET;
	delay_us(10);
	PL_SET;	
	delay_us(10);
	for(i=0;i<8;i++)
	{
		dat=dat<<1;
		if(ODATA==1)
		{
			dat=dat+1;
		}
		CP_RESET;
		delay_us(10);		
		CP_SET;
		delay_us(10);		
	}
	CP_RESET;
	return dat;
}

Code snippet #8

Plain text
 /***********************************************************
 *   Function:  HC165In
 *   Input:     none
 *   Output:    none
 *   Return:    uint8_t
 *   Notice:    Read values of the eight pins of 74HC165 and return 8-bit data.
 ***********************************************************/
uint8_t HC165In(void)
{
	uint8_t i,dat=0;
	CP_SET;
	PL_RESET;
	delay_us(10);
	PL_SET;	
	delay_us(10);
	for(i=0;i<8;i++)
	{
		dat=dat<<1;
		if(ODATA==1)
		{
			dat=dat+1;
		}
		CP_RESET;
		delay_us(10);		
		CP_SET;
		delay_us(10);		
	}
	CP_RESET;
	return dat;
}

Github

https://github.com/Tuya-Community/tuya-iotos-embeded-mcu-demo-4g-vending-machine

Credits

Sandwich IoT
40 projects • 4 followers
Contact

Comments

Please log in or sign up to comment.