Si bien es cierto, ya habíamos realizado una serie de tarjetas plc con microcontroladores de atmel y de esp32, pero aún no habíamos logrado hacer con los microcontroladores de stm32. Asi que hoy vamos a desbloquear ese miedo y haremos un plc con un microcontrolador de la familia stm32. entonces, empezaremos haciendo un plc específicamente con el microcontrolador stm32F103C8T6, que es un microcontrolador básico de esta familia, y según vamos avanzando con las versiones, iremos desarrollando con otros micros más potentes de esta línea.
DATOS TECNICOS
- Tensión de alimentación……………………….…………24VDC
- Corriente de alimentación………………….……………90mA
- Entadas digitales 15-24VDC……………………….……8
- Salidas RLY…………………………………………………………6
-
- Tensión AC…………..……….………………….….……250V
- Corriente AC…………………………………………….5A
- Tensión DC………………………………………………30V
- Corriente DC……………………………………………5A
-
- Salidas PMW (24V)……………………………………………………………3
- Entorno de programación………………………..………..STM32 cube, Arduino IDE
- Condiciones ambientales min……………………….….-40°
- Condiciones ambientales max…………………..……….150°
- Empotrable………………………………….……………………Sí
- Puerto Usb…………………………………………………………………SÍ
- Comunicacion I2C……………………………………………………..Sí
- doble nucleo………………………………………………………………..Sí
- Programación directa (PC-PLC with ESP32)…………Sí
LISTA DE MATERIALES
No. | Quantity | Comment | Designator | Footprint | Value | Manufacturer Part | Supplier Part | Supplier |
1 | 2 | 470uF | C1,C17 | CAP-SMD_BD10.0-L10.3-W10.3-LS11.3-FD | 470uF | VT1V471M1010 | C310845 | LCSC |
2 | 2 | 1uF | C2,C18 | C1206 | 1uF | CL31B105KBHNNNE | C1848 | LCSC |
3 | 26 | 100nF | C3,C4,C5,C6,C7,C8,C9,C10,C11,C12, C13,C15,C16,C19,C21,C22,C23,C24, C25,C26,C27,C28,C32,C33,C34,C35 |
C0603 | 100nF | CC0603KRX7R9BB104 | C14663 | LCSC |
4 | 2 | 220uF | C14,C20 | CAP-SMD_BD6.3-L6.6-W6.6-LS7.2-R-RD | 220uF | RVE1C221M0607 | C99836 | LCSC |
5 | 1 | 1uF | C29 | C0603 | 1uF | CL10A105KB8NNNC | C15849 | LCSC |
6 | 4 | 20pF | C30,C31,C36,C37 | C0603 | 20pF | CL10C200JB8NNNC | C1648 | LCSC |
7 | 2 | HCZZ0126-4 | CN1,CN2 | CONN-TH_XH2.54-4P | HCZZ0126-4 | C7433754 | LCSC | |
8 | 7 | SS210 | D1,D2,D3,D4,D7,D8,D9 | SMA_L4.3-W2.6-LS5.2-RD | SS210 | C14996 | LCSC | |
9 | 2 | BZT52C3V3 | D5,D6 | SOD-123_L2.7-W1.6-LS3.7-RD | BZT52C3V3 | C173413 | LCSC | |
10 | 3 | M7 | D10,D11,D12 | SMA_L4.3-W2.6-LS5.2-RD | M7 | C95872 | LCSC | |
11 | 6 | 1N4148WS | D13,D14,D15,D16,D17,D18 | SOD-323_L1.8-W1.3-LS2.5-RD | 1N4148WS | C2128 | LCSC | |
12 | 1 | BSMD1206-100-24V | F1 | F1206 | BSMD1206-100-24V | C910830 | LCSC | |
13 | 1 | ZX-PZ2.54-2-3PZZ | H1 | HDR-TH_6P-P2.54-V-M-R2-C3-S2.54-1 | ZX-PZ2.54-2-3PZZ | C7501274 | LCSC | |
14 | 1 | PZ254V-11-04P | H2 | HDR-TH_4P-P2.54-V-M | PZ254V-11-04P | C2691448 | LCSC | |
15 | 2 | 68uH | L1,L2 | IND-SMD_L7.1-W6.6-1 | 68uH | PSPMAA0605H-680M-IGF | C2983094 | LCSC |
16 | 18 | KT-0805G | LED1,LED2,LED3,LED4,LED5,LED6,LED7, LED8,LED9,LED10,LED11,LED12,LED13, LED14,LED15,LED16,LED17,LED18 |
LED0805-R-RD | KT-0805G | C2297 | LCSC | |
17 | 10 | WJ128V-5.0-2P | P1,P2,P6,P7,P8,P9,P10,P11,P12,P13 | CONN-TH_2P-P5.00_WJ128V-5.0-2P | WJ128V-5.0-2P | C8269 | LCSC | |
18 | 3 | WJ128V-5.0-3P | P3,P4,P5 | CONN-TH_3P-P5.00_WJ128V-5.0-3P | WJ128V-5.0-3P | C8270 | LCSC | |
19 | 3 | AO3401A | Q1,Q2,Q3 | SOT-23_L2.9-W1.3-P1.90-LS2.4-BR | AO3401A | C15127 | LCSC | |
20 | 6 | MMBT3904 | Q4,Q5,Q6,Q7,Q8,Q9 | SOT-23-3_L2.9-W1.3-P1.90-LS2.4-BR | MMBT3904 | C20526 | LCSC | |
21 | 10 | 10kΩ | R1,R2,R3,R4,R5,R6,R7,R8,R9,R10 | R1206 | 10kΩ | 1206W4F1002T5E | C17902 | LCSC |
22 | 2 | 680Ω | R11,R12 | R0805 | 680Ω | 0805W8F6800T5E | C17798 | LCSC |
23 | 2 | 330Ω | R13,R14 | R0805 | 330Ω | 0805W8F3300T5E | C17630 | LCSC |
24 | 24 | 10kΩ | R15,R16,R17,R18,R19,R20,R21,R22, R40,R42,R43,R44,R55,R56,R57,R58, R59,R60,R67,R68,R69,R70,R71,R72 |
R0603 | 10kΩ | 0603WAF1002T5E | C25804 | LCSC |
25 | 23 | 1kΩ | R23,R24,R25,R26,R27,R28,R29,R30, R31,R32,R33,R34,R35,R48,R50,R52, R54,R73,R74,R75,R76,R77,R78 |
R0603 | 1kΩ | 0603WAF1001T5E | C21190 | LCSC |
26 | 3 | 100kΩ | R36,R37,R41 | R0603 | 100kΩ | 0603WAF1003T5E | C25803 | LCSC |
27 | 2 | 20Ω | R38,R39 | R0603 | 20Ω | 0603WAF200JT5E | C22950 | LCSC |
28 | 9 | 220Ω | R45,R46,R47,R61,R62,R63,R64,R65,R66 | R0603 | 220Ω | 0603WAF2200T5E | C22962 | LCSC |
29 | 9 | 4.7kΩ | R49,R51,R53,R79,R80,R81,R82,R83,R84 | R0805 | 4.7kΩ | 0805W8F4701T5E | C17673 | LCSC |
30 | 6 | RC-124DM1 | RLY1,RLY2,RLY3,RLY4,RLY5,RLY6 | RELAY-TH_RC-XXXXM | RC-124DM1 | C358574 | LCSC | |
31 | 1 | TS-1187A-B-A-B | SW1 | SW-SMD_4P-L5.1-W5.1-P3.70-LS6.5-TL-2 | TS-1187A-B-A-B | C318884 | LCSC | |
33 | 17 | TLP127(TPL,U,F) | U1,U2,U3,U4,U5,U6,U7,U8,U13,U14, U15,U16,U17,U18,U19,U20,U21 |
SOP-4_L3.6-W4.4-P2.54-LS7.0-BR | TLP127(TPL,U,F) | C5001 | LCSC | |
34 | 1 | LM2594M-5.0 | U9 | SOP-8_L4.9-W3.9-P1.27-LS6.0-BL | LM2594M-5.0 | C2904795 | LCSC | |
35 | 1 | LM2594M-3.3 | U10 | SOP-8_L4.9-W3.9-P1.27-LS6.0-BL | LM2594M-3.3 | C3029048 | LCSC | |
36 | 1 | SN74HC541PWR | U11 | TSSOP-20_L6.5-W4.4-P0.65-LS6.4-BL | SN74HC541PWR | C6758 | LCSC | |
37 | 1 | STM32F103C8T6 | U12 | LQFP-48_L7.0-W7.0-P0.50-LS9.0-BL | STM32F103C8T6 | C8734 | LCSC | |
38 | 2 | SN74HC14PWR | U22,U23 | TSSOP-14_L5.0-W4.4-P0.65-LS6.4-BL | SN74HC14PWR | C6821 | LCSC | |
39 | 1 | LM358DR2G | U24 | SOIC-8_L5.0-W4.0-P1.27-LS6.0-BL | LM358DR2G | C7950 | LCSC | |
40 | 1 | MICRO 4P DIP | USB1 | MINI-USB-SMD_MICRO-4P-DIP | MICRO 4P DIP | C456008 | LCSC | |
41 | 1 | 32.768kHz | X1 | FC-135R_L3.2-W1.5 | 32.768kHz | Q13FC13500004 | C32346 | LCSC |
42 | 1 | 8MHz | X2 | CRYSTAL-SMD_L5.0-W3.2 | 8MHz | X50328MSB2GI | C115962 | LCSC |
CODIGO
TEST ENTRADAS DIGITALES Y SALIDAS A RELAY
#include "main.h" void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1) { GPIO_PinState buttonStates[6]; GPIO_TypeDef* buttonPorts[6] = {GPIOB, GPIOB, GPIOB, GPIOB, GPIOB, GPIOB}; uint16_t buttonPins[6] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_10, GPIO_PIN_11, GPIO_PIN_12}; GPIO_TypeDef* ledPorts[6] = {GPIOB, GPIOA, GPIOA, GPIOB, GPIOB, GPIOB}; uint16_t ledPins[6] = {GPIO_PIN_15, GPIO_PIN_8, GPIO_PIN_15, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5}; for (int i = 0; i < 6; i++) { buttonStates[i] = HAL_GPIO_ReadPin(buttonPorts[i], buttonPins[i]); HAL_GPIO_WritePin(ledPorts[i], ledPins[i], (buttonStates[i] == GPIO_PIN_SET) ? GPIO_PIN_SET : GPIO_PIN_RESET); } } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8|GPIO_PIN_15, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_10 |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : PB15 PB3 PB4 PB5 */ GPIO_InitStruct.Pin = GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : PA8 PA15 */ GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void Error_Handler(void) { __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */
LECTURA ANALOGICA Y SALIDA PWM (LCD I2C)
#include "main.h" #include "adc.h" #include "i2c.h" #include "tim.h" #include "gpio.h" #include "Lcd_i2c.h" #include "stdio.h" char buf_lcd[18]; uint8_t duty_pwm = 0; uint8_t porcentaje_duty = 0; void SystemClock_Config(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_TIM2_Init(); MX_I2C1_Init(); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,0); Lcd_Init(); while (1) { HAL_ADC_Start(&hadc1); int valor_adc = HAL_ADC_GetValue(&hadc1); duty_pwm = (uint8_t)((valor_adc*99)/4095); porcentaje_duty = (uint8_t)((duty_pwm*100)/99); __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,duty_pwm); Lcd_Set_Cursor(1,1); sprintf(buf_lcd, "Analog in: %u ", valor_adc); Lcd_Send_String(buf_lcd); Lcd_Set_Cursor(2,1); sprintf(buf_lcd, "pwm: %u ", duty_pwm); Lcd_Send_String(buf_lcd); HAL_Delay(50); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */