Cuando trabajamos con microcontroladores las comunicaciones seriales son de mucha utilidad, sin embargo la mayor limitación la tenemos en la distancia que podemos cubrir de manera eficiente con un conductor físico o incluso un enlace de radio. Suponga que necesitamos enviar órdenes de control desde cualquier parte del mundo a un sistema con distintas placas que tiene a bordo un Arduino o un PIC18Fxx o cualquier microcontrolador de gama baja o media que no posee conectividad TCP-IP. La solución inmediata podría ser cambiar de arquitectura y colocar hardware compatible con TCP-IP sin embargo esto aparte de ser costoso toma tiempo una migración de todo un sistema a un nivel superior de conectividad. Partiendo del concepto que cualquier micrcontrolador (por mas básico que sea) tiene un puerto UART podemos implementar una solución mucho mas económica que nos permitiría controlar esta placa desde cualquier lugar del mundo. En el ejemplo propuesto tenemos un PIC18Fxx que debe encender/apagar un LED conectado en RB0, a su vez este PIC está vinculado por medio de su puerto serial a un transmisor LORA que envía comandos a un receptor LORA conectado al puerto serial de un computador, en el ejemplo usamos una placa Raspberry PI. En la placa Raspberry se ejecuta un socket de red que sirve como puente entre TCP-IP y el propio enlace LORA, la única limitación que tenemos aquí es la distancia de cobertura del enlace LORA entre el PIC con la placa Raspberry pero el envío de comandos lo podemos realizar desde cualquier lugar sin importar la distancia. Para este ejemplo el socket que envía los comandos tiene solo solo dos botones que envían cada uno un byte de control y el PIC los interpreta para encender o apagar el LED que tiene conectado. Solo es necesario colocar la dirección IP donde queremos enviar los datos y el socket se conecta con su receptor sin importar donde se encuentre y transfiere los datos al microcontrolador. El socket que se vincula con el microcontrolador debe correr en el computador que tiene vinculados los enlaces LORA pero el emisor puede correr en cualquier computador que tenga instalado un interprete Python 3. El código completo del socket que controla el microcontrolador es el siguente.
# -*- coding: utf-8 -*-importtimeimportsocketimportsysfromtkinter.messageboximportshowinfofromtkinterimport*importtkinterastkfromtkinterimportttk,fontUDP_PORT=8080sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)defconfigurar_IP():globalUDP_IPUDP_IP=dato_dir.get()boton.focus_set()defapagar():sock.sendto('4'.encode('utf-8'),(UDP_IP,UDP_PORT))defencender():sock.sendto('5'.encode('utf-8'),(UDP_IP,UDP_PORT))ventana=Tk()ventana.title('UDP')ventana.config(bg="Steel Blue")ventana.geometry("200x290")ventana.resizable(0,0)label_IP=Label(ventana,text="Ingrese IP del servidor",bg="Steel Blue",fg="white",font=("Helvetica",12))label_IP.place(x=15,y=10)label_firtec=Label(ventana,text="www.firtec.com.ar",bg="Steel Blue",fg="white",font=("Helvetica",10))label_firtec.place(x=43,y=235)dato_dir=StringVar()caja=Entry(ventana,textvariable=dato_dir,width=15,justify=tk.CENTER)caja.place(x=33,y=40)caja.focus_set()boton=Button(ventana,text="Conectar",command=configurar_IP)boton.place(x=55,y=70)fuente=font.Font(weight='bold')label_voltios=Label(ventana,text="Puerto: 8080",bg="Steel Blue",fg="white",font=("Helvetica",10))label_voltios.place(x=58,y=100)boton_0=Button(ventana,font=fuente,text=' Encender LED ',command=encender)boton_0.pack()boton_0.place(x=20,y=130)boton_1=Button(ventana,font=fuente,text=' Apagar LED ',command=apagar)boton_1.pack()boton_1.place(x=20,y=180)ventana.mainloop()
Para el microcontrolador PIC el código escrito en Mikro C es el siguiente.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/****************************************************************************** Descripción : Lectura de datos de receptor LORA.** Target : 40PIN PIC18F4620 con un LED conectado en RB0** Compiler : MikroC para PIC v 7.1** XTAL : 40MHZ - (XTAL 10Mhz con PLLx4)** www.firtec.com.ar *****************************************************************************/// Pines asignados al LCDsbitLCD_RSatLATE1_bit;sbitLCD_ENatLATE2_bit;sbitLCD_D4atLATD4_bit;sbitLCD_D5atLATD5_bit;sbitLCD_D6atLATD6_bit;sbitLCD_D7atLATD7_bit;sbitLCD_RS_DirectionatTRISE1_bit;sbitLCD_EN_DirectionatTRISE2_bit;sbitLCD_D4_DirectionatTRISD4_bit;sbitLCD_D5_DirectionatTRISD5_bit;sbitLCD_D6_DirectionatTRISD6_bit;sbitLCD_D7_DirectionatTRISD7_bit;// Variables del programavolatilecharDato=0,bandera=0,Kbhit=0;voidISR_UART()iv0x0008icsICS_AUTO{chartxt[15];if(PIR1.RCIF){Dato=Uart1_Read()&0xFF;if(Dato=='4'){PORTB.B0=0;bandera=1;}if(Dato=='5'){PORTB.B0=1;bandera=2;}PIR1.RCIF=0;}}/*********************************************************** Esta función ajusta los valores por defecto de la* pantalla LCD y coloca los carteles iniciales.**********************************************************/voidDisplay_Init(){LCD_Init();LCD_Cmd(_LCD_CLEAR);Lcd_Cmd(_LCD_CURSOR_OFF);Lcd_Out(1,1,"Comandos por LORA");delay_ms(2000);}/*********************************************************** Esta es la función principal del programa.* Configura pines, comparadores, canales analógicos y se* llama al resto de las funciones.**********************************************************/voidmain(){chark=0,t;TRISB0_bit=0;CMCON|=7;ADCON1=0x0f;Display_Init();UART1_Init(9600);INTCON.GIE=1;INTCON.PEIE=1;PIE1.RCIE=1;Lcd_Out(2,1,"LED: ??");while(1){if(bandera==1){Lcd_Out(2,5,"Apagado ");bandera=0;}if(bandera==2){Lcd_Out(2,5,"Encendido");bandera=0;}}}
El siguiente es el resultado del ejemplo funcionando.
En el mundo de los microcontroladores las conexiones seriales son de uso común sin embargo cuando la conexión es cableada tenemos la limitación de la distancia y el montaje del propio cable. Una conexión mediante LORA permite extender el alcance y ademas no tenemos los problemas generados por el propio cable. Este simple ejemplo envía a un microcontrolador PIC18F4620 dos comandos, uno para poner un pin a nivel alto y otro para desactivar el mismo pin. Las órdenes son generadas desde un código Python que se ejecuta en una placa Raspberry PI que los envía a un transmisor LORA. El código para el PIC ha sido escrito en Mikro C para PIC y es el siguiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/********************************************************************************* Descripción : Recibe comandos de un enlace LORA.** Target : 40 PIN PIC18F4620 ** Compiler : MikroC para PIC v 7.1** XTAL : 40MHZ - (XTAL 10Mhz con PLLx4)** www.firtec.com.ar********************************************************************************/// Pines asignados al LCDsbitLCD_RSatLATE1_bit;sbitLCD_ENatLATE2_bit;sbitLCD_D4atLATD4_bit;sbitLCD_D5atLATD5_bit;sbitLCD_D6atLATD6_bit;sbitLCD_D7atLATD7_bit;sbitLCD_RS_DirectionatTRISE1_bit;sbitLCD_EN_DirectionatTRISE2_bit;sbitLCD_D4_DirectionatTRISD4_bit;sbitLCD_D5_DirectionatTRISD5_bit;sbitLCD_D6_DirectionatTRISD6_bit;sbitLCD_D7_DirectionatTRISD7_bit;// Variables del programavolatilecharDato=0,bandera=0,Kbhit=0;voidISR_UART()iv0x0008icsICS_AUTO{chartxt[15];if(PIR1.RCIF){Dato=Uart1_Read()&0xFF;// Lee dato recibidoif(Dato=='4'){PORTB.B0=0;bandera=1;}if(Dato=='5'){PORTB.B0=1;bandera=2;}PIR1.RCIF=0;// Borra bandera de interrupción}}/*********************************************************** Esta función ajusta los valores por defecto de la* pantalla LCD y coloca los carteles iniciales.**********************************************************/voidDisplay_Init(){LCD_Init();LCD_Cmd(_LCD_CLEAR);Lcd_Cmd(_LCD_CURSOR_OFF);Lcd_Out(1,1,"Comandos por LORA");delay_ms(2000);}/*********************************************************** Esta es la función principal del programa.* Configura pines, comparadores, canales analógicos y se* llama al resto de las funciones.**********************************************************/voidmain(){chark=0,t;TRISB0_bit=0;CMCON|=7;ADCON1=0x0f;Display_Init();UART1_Init(9600);INTCON.GIE=1;INTCON.PEIE=1;PIE1.RCIE=1;Lcd_Out(2,1,"LED: ??");while(1){if(bandera==1){Lcd_Out(2,5,"Apagado ");bandera=0;}if(bandera==2){Lcd_Out(2,5,"Encendido");bandera=0;}}}
Su funcionamiento es muy sencillo, LORA solo envía dos posibles datos, el carácter "4" o el "5" que son usados para encender o apagar un LED conectado en el pin RB0 del PIC. Por otro lado tenemos el código Python corriendo en Raspberry PI con dos botones encargados de enviar los respectivos comandos para actuar sobre el pin del microcontrolador.
El código para Python 3 es el siguiente.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# =========================================================================# - Controla el estado de un pin del Microcontrolador.# - El control se hace enviando comandos por un enlace LORA.# - Firtec Argentina# - www.firtec.com.ar# ==========================================================================importerrnoimporttimefromserialimportSerialfromtkinterimport*fromtkinterimportttkfromtkinterimportttk,fontpuerto=Serial("/dev/ttyS0",baudrate=9600,timeout=0.2)ifpuerto.isOpen()==False:puerto.open()puerto.flushInput()puerto.flushOutput()defapagar():puerto.write(b'4')defencender():puerto.write(b'5')classAplicacion():def__init__(self):globaladdrglobalsockglobalventanagloballabel_IP_remotoventana=Tk()ventana.title(' Comandos LORA')ventana.config(bg="Steel Blue")ventana.geometry("390x230")ventana.resizable(0,0)self.fuente=font.Font(weight='bold')label_firtec=Label(ventana,text="www.firtec.com.ar",bg="Steel Blue",fg="white",font=self.fuente)label_firtec.place(x=100,y=150)label_rotulo_texto=Label(ventana,text="Enviando comandos por LORA",bg="Steel Blue",fg="white",font=self.fuente)#font=("Helvetica", 12))label_rotulo_texto.place(x=45,y=20)self.fuente=font.Font(slant='italic')boton_0=Button(ventana,font=self.fuente,text=' Encender LED ',command=encender)# Boton del LEDboton_0.pack()boton_0.place(x=20,y=70)# Coordenada del Botón 1boton_1=Button(ventana,font=self.fuente,text=' Apagar LED ',command=apagar)# Boton del LEDboton_1.pack()boton_1.place(x=200,y=70)# Coordenada del Botón 2ventana.mainloop()defmain():mi_app=Aplicacion()return0if__name__=='__main__':main()
En ocasiones puede ser necesario llevar un historial de los datos de un sensor, el ejemplo propuesto (parte del material de estudio de nuestros cursos) lee los datos de un sensor DHT22 y mediante el puerto UART a 9600 baudios se conecta con un enlace LORA. Este los transmite a una placa Raspberry PI donde se ejecuta MariaDB, el servidor web Apache y PHP. En lugar de Raspberry PI podríamos tener un simple computador sin embargo para no esclavizar un computador en una tarea redundante hemos decidido ocupar una placa Raspberry. El microcontrolador PIC ha sido programado con MikroC para PIC y el código completo es el siguiente.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/****************************************************************************** Descripción : Lectura de temperatura y humedad con un sensor DHT22.** Target : 40PIN PIC18F4620 con sensor DHT22 en pin RE0** Compiler : MikroC para PIC v 7.1** XTAL : 40MHZ - (XTAL 10Mhz con PLLx4)** NOTA : El pin de datos del sensor se conecta al pin 8 (RE0)** (Librerias C_Type, Sprintf y LCD)*****************************************************************************/// Pines asignados al LCDsbitLCD_RSatLATE1_bit;sbitLCD_ENatLATE2_bit;sbitLCD_D4atLATD4_bit;sbitLCD_D5atLATD5_bit;sbitLCD_D6atLATD6_bit;sbitLCD_D7atLATD7_bit;sbitLCD_RS_DirectionatTRISE1_bit;sbitLCD_EN_DirectionatTRISE2_bit;sbitLCD_D4_DirectionatTRISD4_bit;sbitLCD_D5_DirectionatTRISD5_bit;sbitLCD_D6_DirectionatTRISD6_bit;sbitLCD_D7_DirectionatTRISD7_bit;// Conexiones del sensorsbitDHT22_Bus_InatRE0_bit;sbitDHT22_Bus_OutatRE0_bit;sbitDHT22_Bus_DiratTRISE0_bit;// Variables del programacharDHT22_Data[5]={0,0,0,0,0};unsignedinthumedad=0,temperatura=0;volatilecharDato=0,Kbhit=0;chartemp_humedad[12];/********************************************************************************* Esta función es el servicio de interrupción para la recepción de caracteres.* (En este ejemplo no se reciben datos pero si fuera el caso la función ya está* disponible para su implementación).*********************************************************************************/voidISR_UART()iv0x0008icsICS_AUTO{if(PIR1.RCIF){// Verifica la bandera de RXDato=Uart1_Read();// Lee dato recibidoKbhit=1;// Indica que se ha recibido un datoPIR1.RCIF=0;// Borra bandera de interrupción}}/******************************************************** Esta función lee los dato desde el sensor DHT22 ********************************************************/charLeer_DHT22(unsigned*humedad,unsigned*temperature){chari=0,j=1;chartiempo_espera=0;charsensor_byte;DHT22_Bus_Out=0;delay_ms(100);DHT22_Bus_Dir=1;// Establece Bus como entradaDHT22_Bus_Dir=0;// Establece Bus como salidaDHT22_Bus_Out=1;// Bus en alto por 100 milisegundosDelay_ms(100);// Espera 100msDHT22_Bus_Out=0;// Inicia señal baja min: 0.8ms, tip: 1ms, max: 20msDelay_ms(2);// Espera 2msDHT22_Bus_Out=1;// Bus en altoDHT22_Bus_Dir=1;// Bus como entrada// Libera el bus por un tiempo min: 20us, tip: 30us, max: 200ustiempo_espera=200;while(DHT22_Bus_In==1){Delay_us(1);if(!tiempo_espera--){return1;}//ERROR: El sensor no responde}// Señal de respuesta del sensor min: 75us, tip: 80us, max: 85uswhile(!DHT22_Bus_In){// Responde en un tiempo bajoDelay_us(85);}while(DHT22_Bus_In){// Responde en un tiempo altoDelay_us(55);}i=0;// Obtener 5 bytesfor(i=0;i<5;i++){j=1;for(j=1;j<=8;j++){// Se leen 8 bits desde el sensorwhile(!DHT22_Bus_In){Delay_us(1);}Delay_us(30);sensor_byte<<=1;// Agregar el byte bajoif(DHT22_Bus_In){sensor_byte|=1;delay_us(45);while(DHT22_Bus_In){Delay_us(1);}}}DHT22_Data[i]=sensor_byte;}*humedad=(DHT22_Data[0]<<8)+DHT22_Data[1];*temperature=(DHT22_Data[2]<<8)+DHT22_Data[3];return0;}/*********************************************************** Esta función ajusta los valores lídos desde el sensor* y los muestra en la pantalla LCD**********************************************************/voidMostrar_Datos(unsignedhumedad,unsignedtemperatura){chartxt[15];floattemporal_1,temporal_2;temporal_1=humedad/10.0;Lcd_Out(1,1,"Humed.:");sprintf(txt,"%2.1f ",temporal_1);// Formato para la humedadLcd_Out(1,9,txt);Lcd_Chr(1,14,0x25);temporal_2=temperatura/10.0;Lcd_Out(2,1,"Temp. :");sprintf(txt,"%2.1f ",temporal_2);// Formato para la temperaturaLcd_Out(2,9,txt);// En la siguiente línea se ensambla una trama con la temperatura // y humedad separados por una coma (,).sprintf(temp_humedad,"%2.1f,%2.1f ",temporal_2,temporal_1);UART1_Write_Text(temp_humedad);Lcd_Chr(2,14,0x43);}/*********************************************************** Esta función ajusta los valores por defecto de la* pantalla LCD y coloca los carteles iniciales.**********************************************************/voidDisplay_Init(){LCD_Init();LCD_Cmd(_LCD_CLEAR);Lcd_Cmd(_LCD_CURSOR_OFF);Lcd_Out(1,3,"Sensor DHT22");Lcd_Out(2,1,"Sensor???");delay_ms(2000);LCD_Cmd(_LCD_CLEAR);}/*********************************************************** Esta es la función principal del programa.* Configura pines, comparadores, canales analógicos y se* llama al resto de las funciones.* También configura el funcionamiento de la UART**********************************************************/voidmain(){chark=0,t;CMCON|=7;ADCON1=0x0f;Display_Init();UART1_Init(9600);// Configura la UART a 9600 baudios.INTCON.GIE=1;INTCON.PEIE=1;PIE1.RCIE=1;while(1){if(Leer_DHT22(&humedad,&temperatura)==0)Mostrar_Datos(humedad,temperatura);else{LCD_Cmd(_LCD_CLEAR);Lcd_Cmd(_LCD_CURSOR_OFF);Lcd_Out(1,1,"ERROR en el");Lcd_Out(2,1,"Sensor!!!");}Delay_ms(1000);// Espera 1 segundo}}
Para simplificar el procesamiento los datos del sensor son concatenados en una cadena con dos campos, uno para el valor de temperatura y otro para la humedad separados por una coma. La cadena final que será transmitido por LORA se almacena en temp_humedad y la linea de código que concatena los valores es la siguiente.
Del lado de Raspberry tenemos un programa en Python 3 que es el encargado de procesar los datos recibidos por LORA y también escribir los datos en la base de datos y este es su código.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
importtime# Modulo para el manejo de tiemposfromserialimportSerial# Modulo para el manejo de la UARTimportRPi.GPIOimportmysql.connectorasmariadb# Conexión entre Python y la base de datosdb=mariadb.connect(host="localhost",user="firtec",passwd="1234",db="DHT22")# Credencialescur=db.cursor()# Instancia para la base de datostemperatura=0# Variables usadas en el programahumedad=0GPIO.setwarnings(False)# Ignora las advertenciasGPIO.setmode(GPIO.BCM)# Los pines serán referidos como Broadcompuerto=Serial("/dev/ttyS0",baudrate=9600,timeout=0.2)# Configura la UART en Raspberry PIifpuerto.isOpen()==False:# El puerto esta en uso?puerto.open()puerto.flushInput()puerto.flushOutput()datos_viejos=0while1:try:datos_lora=puerto.readline().decode('utf-8').rstrip()if(datos_lora!=''):if(datos_viejos!=datos_lora):datos_viejos=datos_loratemperatura=datos_lora.split(",")[0]# Separa los campos usando el separador (,)humedad=datos_lora.split(",")[1]print('Datos del PIC & Lora:')print(datos_lora)print('========================')try:# Accede la base de datos escribiendo los datos en la tabla “sensor” cur.execute("""INSERT INTO sensor(Temperatura, Humedad) VALUES(%s, %s)"""%(temperatura,humedad))db.commit()except:db.rollback()except(KeyboardInterrupt,SystemExit):puerto.close()GPIO.cleanup()raise
Para poder acceder a los datos desde cualquier computador en la red necesitamos de un sitio web con PHP bajo el control del Apache.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<html><head><title>DHT22</title></head><body><FONTCOLOR="teal"><H1align="center">SensorDHT22+PICconPHP</h1></FONT><H5align="right">by.FirtecArgentina</h5><hrsize="2"align="center"noshade=""><!---------------------IniciacódigoPHP-------------------------><?php// Permisos para acceder a la base de datos (dir, usuario,pass, bd)$conn=mysqli_connect('localhost','firtec','1234','DHT22');if(!$conn){echo"Error: No se pudo conectar a MySQL.".PHP_EOL;echo"errno de depuración: ".mysqli_connect_errno().PHP_EOL;echo"error de depuración: ".mysqli_connect_error().PHP_EOL;exit;}?><!----------------------TerminacódigoPHP------------------------><tableborder="5"align="center"><!--CreatablaHTML--><tralign="center"bottom="middle"><!--filaalineadoalcentro--><td>Temperatura</td><!--tdcreacolumnallamadaTemperatura--><td>Humedad</td><!--tdcreacolumnallamadaHumedad--><td>Fecha_Hora</td><!--tdcreacolumnallamadaFecha_Hora--></tr><!--Findelafilaconcuatrocolumnas--><!--------------------InicianuevocódigoPHP---------------------><?php// Consulta la tabla sensor y guarda en $datos la info leída.$datos_sensor=mysqli_query($conn,"SELECT * FROM sensor");// Los valores contenidos en $datos_sensor son vectorizados en un $dato_arraywhile($dato_array=mysqli_fetch_array($datos_sensor)){?><!--FinPHP--><tr><tdalign="center"><?phpecho$dato_array["Temperatura"];?></td><tdalign="center"><?phpecho$dato_array["Humedad"];?></td><td><?phpecho$dato_array["Fecha"];?></td></tr><?php}?></table><hrsize="2"align="center"noshade=""></body><!--------------------InicianuevocódigoPHP---------------------><?php$version=apache_get_version();// Obtiene la versión de Apacheecho"$version\n";// Muestra la versión de ApacheechoPHP_OS;// Muestra el sistema operativo?><!--FincódigoPHP--></html>
Resultado obtenido con el ejemplo.
Para crear la base de dato usamos phpMyAdmin por su simpleza. La base de datos se llama DHT22, contiene solo una tabla que se llama sensor con tres columnas, una para la temperatura otra para la humedad y otra para le fecha y hora.
Todo esto y mucho mas encontrará en nuestros Libros Técnicos.
Los motores paso a paso se pueden ver como motores eléctricos sin escobillas. Es típico que todos los bobinados del motor sean parte del estator, y el rotor puede ser un imán permanente o, en el caso de los motores de reluctancia variable, un cilindro sólido con un mecanizado en forma de dientes parecido a un engranaje construido con un material magnéticamente dócil como el hierro dulce. La conmutación de las bobinas se maneja con un controlador o driver que a su vez recibe información desde un microcontrolador. La frecuencia que se aplica a las bobinas está dentro del espectro de audio y se pueden lograr grandes velocidades con estos motores. Estos motores paso a paso tienen un comportamiento muy diferente al de los motores de corriente continua. En primer lugar, no giran libremente, los motores paso a paso avanzan girando por pasos determinados por un tren de pulsos. También se diferencian de los motores comunes de continua en la relación par motor. Los motores de continua no son buenos para ofrecer un buen torque a baja velocidad sin la ayuda de una reducción mecánica, sin embargo los motores paso a paso trabajan de manera opuesta siendo su mayor capacidad de torque a baja velocidad.
Los motores paso a paso tienen una característica adicional, el llamado par de detención, que no existe en los motores de continua. El torque de detención hace que un motor paso a paso se mantenga firme en su posición cuando no está girando, esta característica es muy útil cuando el motor deja de moverse y, mientras está detenido, la fuerza de carga permanece aplicada a su eje eliminando la necesidad de un mecanismo de freno mecánico. Los motores paso a paso requieren de trenes de pulsos aplicados convenientemente en sus bobinas, esto significa que hacer girar un motor paso a paso no es tan simple como en un motor de continua al que solo basta con aplicar voltaje y este empieza a girar. Se requiere un circuito de control, que será el responsable de convertir las señales de avance y sentido de giro en la correcta secuencia de activación de los bobinados. El siguiente es un ejemplo simple para mover un motor de este tipo con un popular driver fabricado por Pololu, el A4988 de uso común en la plataforma Arduino y las impresoras 3D.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# =========================================================# - Ejemplo para el manejo de un motor Paso a Paso# - Driver A4988# - Firtec Argentina# - www.firtec.com.ar# =========================================================# -*- coding: utf-8 -*-importtimeimportRPi.GPIOasGPIOGPIO.setmode(GPIO.BOARD)GPIO.setwarnings(False)pinDir=24# Pin para el sentido de giropinStep=26# Pin para los pasosnumSteps=220# Número de pasos del motormicroPausa=0.003# Tiempo entre los pasosGPIO.setup(pinDir,GPIO.OUT)GPIO.setup(pinStep,GPIO.OUT)whileTrue:GPIO.output(pinDir,0)# La dirección puede ser (0 o 1)forxinrange(0,numSteps):GPIO.output(pinStep,True)time.sleep(microPausa)GPIO.output(pinStep,False)time.sleep(microPausa)time.sleep(microPausa)GPIO.output(pinDir,1)# Cambio del sentido de giroforxinrange(0,numSteps):GPIO.output(pinStep,True)time.sleep(microPausa)GPIO.output(pinStep,False)time.sleep(microPausa)GPIO.cleanup()# Sale prolijamente
En el vídeo se puede ver el resultado obtenido al ejecutar el programa.