Control de un servomotor con Visual Basic

Saludos.
El proyecto que tengo es el siguiente, es una interfaz hecha en Visual Basic 2008, que envía datos por el puerto serial y se conecta con un max232 a un PIC16F876, y posteriormente se realiza el control para un servomotor, pero hay ciertos detalles que me gustaría que me ayudaran.

Aquí les anexo todos los archivos.

Bueno, en sí son 2 problemas:
1.- Me gustaría poder cambiar de puerto COM, a la interfaz le puse unos RadioButtons, según el RadioButton que se presione es el COM que se usará, pero el problema es que una vez iniciada la aplicación, se inicializa el puerto y no sé cómo cambiarlo.

Soy nuevo en esto de interfaces de Visual Basic, y bajé un tutorial donde venía como mandar datos por el puerto serial, pero no viene como poder cambiar el COM que utilizamos.
Así que requiero de su ayuda para resolver este problema.
Aquí anexo todos los archivos y el código fuente.

2.- El otro problema que tengo, es que cada vez que se presiona un botón para mover el servo se ejecuta lo siguiente:

Código:
Private Sub ButtonS1arriba_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonS1arriba.Click
        Dim mBuffer As Byte() = New Byte(0) {}
        mBuffer(0) = &H61   'Envia una a
        SerialPort1.Write(mBuffer, 0, mBuffer.Length)
    End Sub
Con esto me enviá un carácter, en este caso una 'a' pero me gustaría si me pueden ayudar en un código que me envié muchas 'a' mientras esta presionado el botón, porque de esta manera el servo se mueve pero le tengo que estar aplastando al botón.
Quisiera saber si hay la forma de sensar cuando el botón se queda presionado, y enviar muchas 'a'

Aquí anexo el código completo de Visual Basic.

Código:
Imports System.IO.Ports
Public Class Form1
    Public Sub New()
        InitializeComponent()
        'Abrir puerto mientras se ejecuta la aplicacion
        If Not SerialPort1.IsOpen Then
            Try
                SerialPort1.Open()
            Catch ex As System.Exception
                MessageBox.Show(ex.ToString())
            End Try
        End If
    End Sub
    Sub ConfiguracionPuerto()
        If RadioButton3.Checked Then       'Configura el tipo de puerto
            SerialPort1.PortName = "COM1"
        End If
        If RadioButton4.Checked Then
            SerialPort1.PortName = "COM2"
        End If
        If RadioButton5.Checked Then
            SerialPort1.PortName = "COM3"
        End If
        If RadioButton6.Checked Then
            SerialPort1.PortName = "COM4"
        End If
        If RadioButton7.Checked Then
            SerialPort1.PortName = "COM5"
        End If
        If RadioButton8.Checked Then
            SerialPort1.PortName = "COM6"
        End If
        If RadioButton9.Checked Then
            SerialPort1.PortName = "COM7"
        End If
        If RadioButton10.Checked Then
            SerialPort1.PortName = "COM8"
        End If
        If RadioButton11.Checked Then
            SerialPort1.PortName = "COM9"
        End If
        If RadioButton12.Checked Then
            SerialPort1.PortName = "COM10"
        End If
    End Sub
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        ConfiguracionPuerto()
    End Sub

    Private Sub ButtonS1arriba_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonS1arriba.Click
        Dim mBuffer As Byte() = New Byte(0) {}
        mBuffer(0) = &H61   'Envia una a
        SerialPort1.Write(mBuffer, 0, mBuffer.Length)
    End Sub

    Private Sub ButtonS1abajo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonS1abajo.Click
        Dim mBuffer As Byte() = New Byte(0) {}
        mBuffer(0) = &H62   'Envia una b
        SerialPort1.Write(mBuffer, 0, mBuffer.Length)
    End Sub
End Class
Para el caso del PIC, éste es el código fuente, está hecho con PICC de CCS:

PHP:
#include<16f876a.h>
#fuses XT,NOPROTECT,NOWDT,PUT
#use delay (clock=4000000)
#use fast_io(b)
#byte portb=0x06
#bit rb0=6.0
#use RS232(BAUD=9600,BITS=8,PARITY=N,XMIT=PIN_C6,RCV=PIN_C7)

void iniciar(void);

void main()
{
    set_tris_a(0xff);
    set_tris_b(0b11111110);
    portb=0;
    disable_interrupts(GLOBAL); 
    iniciar();
}
void iniciar(void)
{
   char caracter_recibido;
   long int tiempo_alto,tiempo_bajo;
   tiempo_alto=900; //damos el valor inicial para establecer el servo a 0 grados
   while(TRUE)
   {
      if(kbhit())  //prueba si a llegado un caracter
      {
        caracter_recibido=getc();   //Guarda el caracter
        if(caracter_recibido=='a')  //si es una a
        { 
           if(tiempo_alto<2100)
           {  tiempo_alto+=10; }       //incrementa el tiempo en alto
        }
        if(tiempo_alto>900)
        {
           if(caracter_recibido=='b')  //si es una b
           {  tiempo_alto-=10; }       //decrementa el tiempo en alto
        }
      }
      tiempo_bajo=20000-tiempo_alto; //establece el tiempo en bajo, como
                                     //el servo hitec maneja f=50hz en tiempo son
                                     //20000 microsegundos
      rb0=1;                   //empieza el PWM
      delay_us(tiempo_alto);
      rb0=0;
      delay_us(tiempo_bajo);
   }
}
 

Adjuntos

  • Control servo.zip
    182.8 KB · Visitas: 103
  • control con el virtual serial.gif
    control con el virtual serial.gif
    206.4 KB · Visitas: 56
  • Interfaz.gif
    Interfaz.gif
    35.3 KB · Visitas: 49
  • Simulacion en proteus.gif
    Simulacion en proteus.gif
    167 KB · Visitas: 47
Última edición por un moderador:
Hi, que version de VB utilizas?
1) para poder cambiar de COM, necesitas primero cerrar la conexion,
2) puedes utilizar un Timer para estar enviando un caracter, sin tener que presionar otra vez el boton.

:)
 
Saludos unikfriend agradesco tu respuesta tan rapida

Bueno estoy utilizando Visual Basic Express 2008,
Nose si me puedas ayudar un poco con el codigo para cerrar y volver a abrir el puerto para poderlo cambiar,
En cuanto a lo del timer no se como implementarlo en Visual Basic, si me puedes echar la mano te lo agradeceria, ya que soy novato en esto de Visual Basic
 
Hi, lo malo es que yo solo use hasta el VB6, ahora us VC++ para todos estos casos
pues intenta agrengando la intruccion close al inicio de configuracion y cada vez
que modifiques un valor de configuracion.

Sub ConfiguracionPuerto()

SerialPort1.Close ()

If RadioButton3.Checked Then 'Configura el tipo de puerto
SerialPort1.PortName = "COM1"
End If
If RadioButton4.Checked Then
SerialPort1.PortName = "COM2"
End If
 
hay diferentes eventos en VB
puedes utilizar el evento mousedown para que envies miestras estas presionado el boton izquierdo del raton envias "a" y cuando se de el evento mouseup dejas de enviar....
 
Saludos arturouc

Agradesco tu respuesta, pero la verdad nunca he manejado esos eventos mi pregunta es la siguiente,
por ejemplo en el codigo como le podria acer para detectar lo siguiete (pseudocodigo):

Si se preciona el boton entonces
-
Si se deja precionado el click del mouse
enviar
Si no
no enviar
-

Como quedaria en codigo:

Private Sub ButtonS1abajo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonS1abajo.Click
Dim mBuffer As Byte() = New Byte(0) {}
mBuffer(0) = &H62 'Envia una b
SerialPort1.Write(mBuffer, 0, mBuffer.Length)
End Sub

No se si tendras alguna sugerencia, agradeceria tu ayuda

¿?
 
Hi yeaa, es que para eso ocupas el evento MouseDown no el Click
como te comentaba para eso yo utilizaria un timer con el
MouseDown lo habilitas y con el MouseUp lo deshabilitas


:)
 
Private Sub ButtonS1abajo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonS1abajo.Click
Dim mBuffer As Byte() = New Byte(0) {}
mBuffer(0) = &H62 'Envia una b
SerialPort1.Write(mBuffer, 0, mBuffer.Length)
End Sub

No se si tendras alguna sugerencia, agradeceria tu ayuda

¿?

Lo que esta en rojo es el evento CLICK, necesitas usar el evento mousedown
como te dice Unikfriend habilitas un temporizador timmer1.enable=true y dentro del codigo
envias el caracter al microcontrolador.
cuando sueltes el boton izquierdo del raton, se produce otro evento el mouseup, en este
evento desabilitas el temporizador timmer1.enable=false y se deja de enviar el caracter

este es un ejemplo en VB6 que es lo que tengo...

Private Sub cmdHbilitaTimmer_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
tmrEnviaA.Enabled = True
End Sub

Private Sub cmdHbilitaTimmer_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
tmrEnviaA.Enabled = False
End Sub

Private Sub tmrEnviaA_Timer()
' muy importante el intervalo del temporizador
' ojo el puerto ya debe estar habierto

MSComm1.Output = "a" '' & Chr(13) & Chr(10)

' aqui va tu codigo para enviar los caracteres
' los estara enviando dependiendo de el intervalo del temporizador
End Sub
 
Última edición:
Gracias por tu ayuda arturouc provare los cambios y posteare los resultados

PREGUNTA: ya tienes la programacion del microcontrolador para el control del servomotor?
con que frecuencia envia pulsos el encoder que estas utilizando? ya integraste la ecuacion
de PID para el control de la posicion, velocidad y aceleracion?
te lo pregunto por que yo estoy haciendo lo mismo con vb6 pero estoy en la lectura del encoder
por que me envia 100 000 pulsos por seg (100 KHz) ya que resuelva este problema voy con lo
del PID.
este es el codigo de ejemplo que tengo en PIC BASIC PRO solo para 2 posiciones
Código:
'****************************************************************
'*  Name    : servodriver.BAS                                   *
'*  Date    : 21/11/2010                                        *
'****************************************************************
define osc 8   'declaracion del oscilador
Trisd = 255     'puerto D como entradas
Trisb = 0       'puerto B como salidas

Posicion var word  'Posicion a la que tiene que ir el servo
PosMenos var word  'Histeresis abajo
PosMas var word    'Histeresis arriba
Contador var word  ' Contador de pulsos del encoder
A var bit          'canal A del encoder 500 pulsos/r
B var bit          'canal B del encoder 500 pulsos/r
C var Bit          'canal C del encoder 500 pulsos/r
uA var bit         'variable para saber si cambio canal A
uB var bit         'variable para saber si cambio canal B
uC var bit         'variable para saber si cambio canal C
Giro var bit       'sentido de giro del servo

contador = 0
posicion=5000    'una posicion arbitraria
ua=0
ub=0
Cambio:          'cambiar sentido de giro
posmenos=posicion-15
posmas=posicion+15
portb=0

Inicio:
        ; si se presiona un pulsador se cambia la
        ;posicion a la que se debe de mover el servomotor
        if portd.1 =1 then  goto soltar
        if portd.0=1 then  ' LEE CANAL A  del encoder
            A=1     'activado
        else
            A=0     'desactivado
        endif 
        if portd.2=1 then ' LEE CANAL B   del encoder
            B=1     'activado
        else
            B=0     'desactivado
        endif               
        ;si el canal A mando un flanco de subida
        ;y el canal B esta activo giro=1
        IF UA=0 and A=1 and B=1 then giro=1
        ;si el canal A mando un flanco de subida
        ;y el canal B esta desactivado giro=0
        IF UA=0 and A=1 and B=0 then giro=0
        ;si cambia alguno de los canales del encoder
        ;es una posicion diferente y por lo tanto
        ;el contador se debe de incrementar
        ;dos canales de 500 pulsos con dos estados posibles
        ;me dan 2000 pulsos por revolucion (4 combinaciones)
        if A<>uA or B<>uB then
            if giro=1 then  contador =contador+1   'incremento
            if giro=0 then  contador =contador-1   'decremento
        endif
        
        uA=A   'ultimo estado del canal A
        uB=B   'ultimo estado del canal B
        
        if contador =posicion then  ' si llego a la posicion apago el motor
            portb.1 =0
            portb.2=0
        endif 
        
        if contador<posmenos then  ' giro en sentido =1
            portb.1=1 'se activa la salida para que gire el motor giro=1
        endif
       ;despues cambiare esto por PWM
       if Contador>posmas then     'giro en sentido =0
            portb.2=1 'se activa la salida para que gire el motor giro=0
         endif        
        goto inicio
Soltar:
        if portd.1=1 then goto Soltar
        ;cambio la posicion para que gire en sentido contrario
        if posicion=1000 then
            posicion=5000
        else
            posicion=1000
        endif        
        goto Cambio
end

este codigo lo publique en el post #835 del hilo curso programacion pic basic pro de este mismo foro

Hi yeaa, es que para eso ocupas el evento MouseDown no el Click
como te comentaba para eso yo utilizaria un timer con el
MouseDown lo habilitas y con el MouseUp lo deshabilitas


:)
Unikfriend
estabas haciendo algo muy parecido, como va tu proyecto para controlar el servo de 2800 rpm?
 
Última edición:
Hi Arturo,
No en realidad mi proyecto es algo muy distinto,
pero me interesa aprender acerca de los servos,
con que servo estas trabajando ?
:)


un servomotor SANYODENKI
de 24V 2.7A 3000 rpm. se trata de controlar la posicion del servomotor
el encoder
manda 2000 pulsos por revolucion a 3000 rpm = 100000 pulsos/seg
son dos canales del encoder de 500 pulsos/rev
 
Gracias Arturouc,
y donde lo conseguistes? son muy caros?

fui al parque industrial de la ciudad y tienen un lugar donde tiran todas las maquinas que ya no utilizan, me encontre una zavatech (maquina de SMT, montaje superficial de componentes electronicos) y de ahi los tome y me los regalaron por que para ellos es basura....
en todas las ciudades donde estan concentradas las empresas (parque industrial) puedes encontrar o incluso en alguna empresa especifica....

P.D. si son caros...
 
Saludos aqui les traigo el codigo completo de Visual Basic.NEt gracias a ustedes pude corregir el error

Imports System.IO.Ports
Imports System.Timers

Public Class Form1

Dim CaracterEnviado As Char = "" 'Caracter enviado
Dim mBuffer As Byte() = New Byte(0) {} 'Bufer para envio

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Timer1.Interval = 100 'Establecemos el periodo del timer
AddHandler Timer1.Elapsed, AddressOf Enviar 'Configura desbordamiento el timer va a Enviar()
End Sub

Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
SerialPort1.Close()
End Sub

Private Sub ConfiguracionPuerto()
Dim NombrePuerto As String
NombrePuerto = ""
SerialPort1.Close()
If RadioButton3.Checked Then 'Configura el tipo de puerto
NombrePuerto = "COM1"
End If
If RadioButton4.Checked Then
NombrePuerto = "COM2"
End If
If RadioButton5.Checked Then
NombrePuerto = "COM3"
End If
If RadioButton6.Checked Then
NombrePuerto = "COM4"
End If
If RadioButton7.Checked Then
NombrePuerto = "COM5"
End If
If RadioButton8.Checked Then
NombrePuerto = "COM6"
End If
If RadioButton9.Checked Then
NombrePuerto = "COM7"
End If
If RadioButton10.Checked Then
NombrePuerto = "COM8"
End If
If RadioButton11.Checked Then
NombrePuerto = "COM9"
End If
If RadioButton12.Checked Then
NombrePuerto = "COM10"
End If
If NombrePuerto = "" Then
MsgBox("Selecciona un puerto", vbInformation, "Error")
Else
SerialPort1.PortName = NombrePuerto 'Configura el COM a utilizar
If Not SerialPort1.IsOpen Then 'Si no se abre
Try 'Intenta abrirlo
SerialPort1.Open()
Catch ex As System.Exception
MessageBox.Show(ex.ToString()) 'Si no me muestra un mensaje de error
End Try
End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ConfiguracionPuerto()
End Sub

Private Sub ButtonS1arriba_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseDown
CaracterEnviado="a"
Enviar()
End Sub

Private Sub ButtonS1abajo_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseDown
CaracterEnviado="b"
Enviar()
End Sub

Private Sub ButtonS1arriba_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseUp
Timer1.Enabled = False
CaracterEnviado = “”
End Sub

Private Sub ButtonS1abajo_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseUp
Timer1.Enabled = False
CaracterEnviado = “”
End Sub

Private Sub Enviar()
Select Case CaracterEnviado
Case "a"
mBuffer(0) = &H61 'Envia una a
Case "b"
mBuffer(0) = &H62 'Envia una b
End Select
SerialPort1.Write(mBuffer, 0, mBuffer.Length) 'Envia el dato por el puerto
End Sub
End Class

Bueno gracias a ustedes pude completar el proyecto, espero les sirva, cualquier duda aganmela saber

Una disculpa pero faltaron algunas cosas en el post anterior aqui mando las correcciones:

Imports System.IO.Ports
Imports System.Timers

Public Class Form1

Dim CaracterEnviado As Char = "" 'Caracter enviado
Dim mBuffer As Byte() = New Byte(0) {} 'Bufer para envio
Dim Timer1 As New System.Timers.Timer() 'Declaramos un Timer

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Timer1.Interval = 100 'Establecemos el periodo del timer
AddHandler Timer1.Elapsed, AddressOf Enviar 'Configura desbordamiento el timer va a Enviar()
End Sub

Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
SerialPort1.Close()
End Sub

Private Sub ConfiguracionPuerto()
Dim NombrePuerto As String
NombrePuerto = ""
SerialPort1.Close()
If RadioButton3.Checked Then 'Configura el tipo de puerto
NombrePuerto = "COM1"
End If
If RadioButton4.Checked Then
NombrePuerto = "COM2"
End If
If RadioButton5.Checked Then
NombrePuerto = "COM3"
End If
If RadioButton6.Checked Then
NombrePuerto = "COM4"
End If
If RadioButton7.Checked Then
NombrePuerto = "COM5"
End If
If RadioButton8.Checked Then
NombrePuerto = "COM6"
End If
If RadioButton9.Checked Then
NombrePuerto = "COM7"
End If
If RadioButton10.Checked Then
NombrePuerto = "COM8"
End If
If RadioButton11.Checked Then
NombrePuerto = "COM9"
End If
If RadioButton12.Checked Then
NombrePuerto = "COM10"
End If
If NombrePuerto = "" Then
MsgBox("Selecciona un puerto", vbInformation, "Error")
Else
SerialPort1.PortName = NombrePuerto 'Configura el COM a utilizar
If Not SerialPort1.IsOpen Then 'Si no se abre
Try 'Intenta abrirlo
SerialPort1.Open()
Catch ex As System.Exception
MessageBox.Show(ex.ToString()) 'Si no me muestra un mensaje de error
End Try
End If
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
ConfiguracionPuerto()
End Sub

Private Sub ButtonS1arriba_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseDown
Timer1.Enabled = True
CaracterEnviado="a"
Enviar()
End Sub

Private Sub ButtonS1abajo_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseDown
Timer1.Enabled = True
CaracterEnviado="b"
Enviar()
End Sub

Private Sub ButtonS1arriba_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseUp
Timer1.Enabled = False
CaracterEnviado = “”
End Sub

Private Sub ButtonS1abajo_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Buttonarriba.MouseUp
Timer1.Enabled = False
CaracterEnviado = “”
End Sub

Private Sub Enviar()
Select Case CaracterEnviado
Case "a"
mBuffer(0) = &H61 'Envia una a
Case "b"
mBuffer(0) = &H62 'Envia una b
End Select
SerialPort1.Write(mBuffer, 0, mBuffer.Length) 'Envia el dato por el puerto
End Sub
End Class

Las sentencias que estan en negritas me faltaron en el post pasado
 
Última edición:
les propongo hacer un driver para controlar servomotores de CD con ciertas características:
rango determinado de corriente, rango de frecuencia de encoder, etc.
en verdad es lo que estoy haciendo para un robotde 5 GDL, ya lo tengo con motores paso a paso
les paso un link para que lo vean.
http://www.uts.edu.mx/archivoselectronicos/Video/ArchivosElectronicos\3VideoRobot_UTS\RP5E_UTS1.rar
voy a postear un hilo en el grupo de automatización y robótica cuando tenga 25 mensajes...jajaja...
 
les propongo hacer un driver para controlar servomotores de CD con ciertas características:
rango determinado de corriente, rango de frecuencia de encoder, etc.
en verdad es lo que estoy haciendo para un robotde 5 GDL, ya lo tengo con motores paso a paso
les paso un link para que lo vean.
http://www.uts.edu.mx/archivoselectronicos/Video/ArchivosElectronicos\3VideoRobot_UTS\RP5E_UTS1.rar
voy a postear un hilo en el grupo de automatización y robótica cuando tenga 25 mensajes...jajaja...

ok, me interesa aprender acerca de los servomotores, yo si me apunto,
lo que necesitaba saber era donde conseguir un servo, entonces los CD lo usan,
tu dices como empezamos.
:)
 
Unikfriend
ya viste el video?
.
.
.
en el Grupo de Automatizacion y Robotica
acabo de crear un hilo para este proyecto
espero que participen...
 
Última edición:
Atrás
Arriba