Advertisement  

Saturday, 12 July 2025
     
 
Main Menu
Home Home
Shop Shop
News News
BASCOM-AVR BASCOM-AVR
BASCOM-8051 BASCOM-8051
Products Products
Application Notes Application Notes
Publications Publications
Links Links
Support Center Support Center
Downloads Downloads
Forum Forum
Resellers Resellers
Contact Us Contact Us
Updates Updates
MCS Wiki MCS Wiki
Online Help
BASCOM-AVR Help BASCOM-AVR Help
BASCOM-8051 Help BASCOM-8051 Help
Contents in Cart
Show Cart
Your Cart is currently empty.
Search the Shop

Products Search

User Login
Username

Password

If you have problem after log in with disappeared login data, please press F5 in your browser

RSS News
 
     
 

 
   
     
 
AN #150 - PID motor controller Print
PID Motor Control by G.De Luca
( delucagiovanni at interfree dot it )


Description of the board:

The board has been from me realized for moving contemporarily and 

independent way two motors brushed with relative encoder. 

The profiles with which it is possible to let move the motors are: control of position, control position with trapezoidal profile and continuous control of speed. 

To move the motor (one) in control of position we for example use the command: 

GO 1 +100000 

To move the motor (one) in trapezoidal control with a maximum speed of 125 we use the command: 

POS 1 +100000 125 

To move the two motors contemporarily in two different positions: 

MOVE +50000 -50000 

To change the values of the PID of the motor one: [kp] [ki] [kd]

SPID 1 500 10 500 

To let move the motors contemporarily with two different speeds: 

VELO 100 10 

To change the acceleration of the motor two with inclination of 30 degrees: 

SACC 2 30. 

To read the position from the encoder one: 

ENC 1

It is important that when the circuit is in power on, the motor, it doesn't move. 

If this happens, it is necessary to reverse the connections of the motor.


Schematic of the board:








Source program for BASCOM:

 

'///////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////
'
' PROGRAMMA PER IL CONTROLLO PID DI due MOTORI CON hp ENCODER HEDS-5540 100 IMPULSI GIRO
' data 28-05-2007 versione BASCOM 1.8.11.3
' la seriale in questa versione non interferisce con il timer 0-1
' poichč la trasmissione della posizione viene eseguita alla fine del
' ciclo PID all'interno del ciclo DO-LOOP MAIN
'
' GIOVANNI DE LUCA
' HTTP://delucagiovanni.interfree.it robot applications
' HTTP://WWW.LNS.INFN.IT nuclear phisics applications
' HTTP://www.youtube.com/tubincolo my video mobilerobots
' deluca@lns.infn.it  e-mail
'
'///////////////////////////////////////////////////////////////////////////////
'///////////////////////////////////////////////////////////////////////////////
'
' Input Format Command:
' Command [par1] [par2] [par3] Cr
'
' Out Format Command:
' [mot] [command], [par1]
'
' Input Commands From Windows Terminal [ 115200 , 8 , N , 1 ]
' No Case Sentitive
'.................................................................................................................
' Rstf  RESET CPU WITH WATCHDOG START
' Made WHO WROTE PROGRAMM GIOVANNI DE LUCA
' Ver VERSION OF PROGRAMM
' Skp [mot] [kp Value]  SET PROPORZIONAL PID 0-1000 MAX
' Ski [mot] [ki Value] SET INTEGRAL PID 0-100 MAX
' Skd [mot] [kd Value] SET DERIVATIVE PID 0-1000 MAX
' Vmax [mot] [vmax Value] SET MAX VELOCITY IN PROPORZIONAL VELOCITY PROFILE 0-255
' Svm [mot] [svm Value] SET MAX VELOCITY IN TRAPEZOIDAL MODE 0-255
' Spid [mot] [kp] [ki] [kd] SET PID MOTOR KP KI KD
' Stime[stime Value] SET PID EXECUTION TIME 0-10
' Smode[mot] [mode] SET SINGLE MODE FOR ONE MOTOR
' Svel [mot] [svel Value] SET MOTOR_ON WITH INTEGRAL VELOCITY PROFILE AND MOVE 0-255
' Velo [vel 1] [vel 2] SET TWO INDIPENDENT SPEED FOR MOTORS 0-255 0-255
' Spwm [mot] [spwm Value] SET MAX PWM OUT FOR TORQUE LIMIT 0-255
' Sacc [mot] [acc Value] SET ACCELERATION DEGREE 1-89 DEGREES
' Sang [mot] [angular Factor] SET ANGULAR FACTOR FOR VELOCITY PROFILE 1-100
' Go [mot] [position Value] GO TO POSITION IN POSITION MODE CONTROL +- 23 BITS
' Pos [mot] [position Value] [speed] SET POSITION IN TRAPEZOIDAL PROFILE 0-255
' Move [position 1] [position 2] MOVE MOTORS TO POS 1 POS 2 +-23 BITS TRAPEZOIDAL MODE
' Velp [position 1] [position 2] MOVE CONTINUOS POSITION WITH VARIBLE PROPORZIONAL VELOCITY
' Start START MOVE IF START_MOVE = FALSE
' Stop STOP MOVE AND MOTORS POWER DOWN
' Gmax [mot] GET MAX VELOCITY IN VELOCITY PROFILE MODE
' Gvm [mot] GET MAX VELOCITY IN TRAPEZOIDAL MODE
' Gve [mot] GET ABSOLUTE SPEED FROM ENCODER
' Enc [mot] READ ABSOLUTE ENCODER POSITION
' Gpid [mot] GET PID MOTOR VALUES
' Gtime  GET PID EXECUTION TIME
' Szp [mot] SET ZERO POSITION
' Idle [mot] POWER OFF MOTOR
' Gsm [mot] GET MOTOR STATE 0=STOP 1=MOVE
' Mode [mode] SET MODE PROFILE FOR 2 MOTOR 0,1,2,3,4
' Gmode GET PROFILE MODE SETTING
' Gpwm [mot] GET MAX PWM OUT
' Rpwm [mot]  READ REAL PWM OUT TO CONTROL MAX CURRENT
' Gacc [mot] GET ACCELERATION PROFILE IN DEGREE 1-89
' Gang [mot] GET ANGULAR FACTOR
' Rst [mot] RESET ENCODER
'.............................................................................................................

$prog &HFF , &H6F , &HD7 , &H00 'FUSE BITS
$regfile = "m32def.dat"
$crystal = 18432000  'over clocked CPU
$baud = 115200
$hwstack = 64
$swstack = 64
$framesize = 64
'-------------------------------------------------------------------------------
Const Si = 1
Const No = 0
Const Vb6 = No 'YES PER USARE LA SERIALE CON Visual Basic 6
' 'NO PER TERMINAL WINDOWS
'-------------------------------------------------------------------------------
'------------------- SUBROUTINE ------------------------------------------------
'-------------------------------------------------------------------------------
Declare Sub Hctl_2032(byval Mot As Byte)
Declare Sub Exe_pid(byval Mot As Byte , Byval Pid_setpoint As Long , Byval Pid_actual As Long)
Declare Sub Configura_pid(byval M As Byte , Byval Mot_kp As Long , Byval Mot_ki As Long , Byval Mot_kd As Long)
Declare Sub Init_parameter(byval M As Byte)
Declare Sub Calcola_trapezio(byval M As Byte)
Declare Sub Make_print(byval Mt As Byte , Byval Stringa As String , Byval Valore As Long)
Declare Sub Set_mode(byval Mode_control As Byte)
'-------------------------------------------------------------------------------
'------------------- CONFIGURAZIONI --------------------------------------------
'-------------------------------------------------------------------------------
'configuriamo il timer1 per pwm a 8 bit a freq = 565 hz con xtal=18mhz e prescale=1
'abbiamo  (18432000 / 256 = 72 Khz) (72 K / presc = 72 K) (72 K/2 pwm = 36 Khz)
'-------------------------------------------------------------------------------
Config Watchdog = 16
Stop Watchdog
Config Int0 = Falling
Config Int1 = Falling
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 '36.2 Khz pwm
Config Timer0 = Timer , Prescale = 64 '
On Timer0 Timer_0 '
On Int1 Int_1  '
On Int0 Int_0 '
On Urxc Rs232 '
Enable Timer0 'handler seriale
Enable Urxc  'abilita seriale
Enable Int0 'fine corsa motore 1
Enable Int1 'fine corsa motore 2
Enable Interrupts  'abilita tutti interrupts
'------------------- ALIAS -----------------------------------------------------
 Motor_pwm_1
Alias Pwm1a : Motor_pwm_1 = 0 'pwm out motore x
 Motor_pwm_2
Alias Pwm1b : Motor_pwm_2 = 0 'pwm out motore y
 
Ddrd.2 = 0 : Portd.2 = 1 'pullup x int 0
 
Ddrd.3 = 0 : Portd.3 = 1 'pullup x int 1
 Fc2_1
Alias Pinb.0 : Ddrb.0 = 0 'limit 1
 Fc2_2
Alias Pinb.1 : Ddrb.1 = 0 'limit 2
 Aux_0
Alias Pinb.2 : Ddrb.2 = 0 : Portb.2 = 1 'pullup aux per indirizzo scheda
 Aux_1
Alias Pinb.3 : Ddrb.3 = 0 : Portb.3 = 1 'pullup aux per indirizzo scheda
 Smt_1
Alias Portb.4 : Ddrb.4 = 1 'stato motore 1
 Smt_2
Alias Portc.6 : Ddrc.6 = 1 'stato motore 2
 Motor_dir_1
Alias Portd.6 : Ddrd.6 = 1 'direzione motore x
 Motor_dir_2
Alias Portd.7 : Ddrd.7 = 1 'direzione motore y
 Motor_led
Alias Portc.7 : Ddrc.7 = 1 'led test
 Hctl_xy
Alias Portc.0 : Ddrc.0 = 1 'selezione xy hctl2032
 Hctl_sel1
Alias Portc.1 : Ddrc.1 = 1 'selezione byte bit 0
 Hctl_sel2
Alias Portc.2 : Ddrc.2 = 1 'selezione byte bit 1
 Hctl_oe
Alias Portc.3 : Ddrc.3 = 1 'selezione oe hctl data
 Hctl_rst_1
Alias Portc.4 : Ddrc.4 = 1 'reset encoder x
 Hctl_rst_2
Alias Portc.5 : Ddrc.5 = 1 'reset encoder y
 Hctl_data
Alias Pina : Ddra = &H00 'porta input data encoder
'-------------------------------------------------------------------------------
Hctl_xy
= 0 'seleziona encoder x
Hctl_sel1
= 0 'selezione primo byte msb
Hctl_sel2
= 1  'seleziona primo byte msb
Hctl_oe
= 1 'no output enable
Hctl_rst_1
= 1 'no reset
Hctl_rst_2
= 1 'no reset
'---------------------------- COSTANTI -----------------------------------------
Const Mode_pos = 0
Const Mode_vel = 1
Const Mode_trp = 2
Const Mode_velp = 3
Const Mode_idle = 4
Const True = 1
Const False = 0
'---------------------- VARIABILI ----------------------------------------------
Dim Pid_kp(2) As Long
Dim Pid_ki(2) As Long
Dim Pid_kd(2) As Long
Dim Pid_scale(2) As Long
Dim Pid_prev_error(2) As Long
Dim Pid_integral_error(2) As Long
Dim Pid_error(2) As Long
Dim Ptemp(2) As Long
Dim Motore_setpoint(2) As Long
Dim Pid_out(2) As Long 'valore da assegnare a pwm
Dim Data_1 As Byte 'hctl used
Dim Data_2 As Byte 'hctl used
Dim Data_3 As Byte 'hctl used
Dim Data_4 As Byte 'hctl used
Dim Timer_pid As Byte 'sample timer pid
Dim Pos_encoder(2) As Long 'encoder position
Dim Old_encoder(2) As Long 'prewius encoder position
Dim New_speed(2) As Long 'velocita in ingresso pid
Dim Act_speed(2) As Long 'velocita attuale
Dim Acc_speed(2) As Long 'velocita accelerazione
Dim Pos_finale(2) As Long 'posizione trapezoidale finale
Dim Temp_enc As Long 'temp encoder position
Dim Comando As String * 30
Dim Comando_old As String * 30
Dim Char(20) As Byte
Dim Idt As Byte : Idt = 1
Dim N_cmd As Byte
Dim Cmd_ar(5) As String * 10
Dim Mode_ctrl As Byte 'mode control
Dim Mot_kp As Long
Dim Mot_ki As Long
Dim Mot_kd As Long
Dim Vel_pos(2) As Long
Dim Vel_neg(2) As Long
Dim Vel_last(2) As Long
Dim Rpwm(2) As Byte
Dim Fattore_acc(2) As Long
Dim Punto_p1(2) As Long
Dim Dir_diff(2) As Byte
Dim Diff_posizione(2) As Long
Dim Trap_1(2) As Long
Dim Trap_2(2) As Long
Dim New_encoder(2) As Long
Dim Deg(2) As Single
Dim Rad(2) As Single
Dim Vel_max(2) As Single
Dim Diff_2(2) As Long
Dim Max_pwm(2) As Byte
Dim Mot As Byte
Dim M As Byte
Dim Start_move As Bit
Dim Tx_enable As Bit
Dim Str_tx_1 As String * 20
Dim Flag_velocita As Bit
Dim Somma As Long
Dim Vmax_pos(2) As Long
Dim Vmax_neg(2) As Long
Dim Fattore_ang(2) As Long 'fattore angolare 0-99
Dim Differenza(2) As Long 'differenza
Dim Acc_speed_p(2) As Long 'accelerazione positiva x controllo velocita
Dim Acc_speed_n(2) As Long 'accelerazione negativa x controllo velocita
Dim Pid_time As Byte 'tempo max pid overflow
Dim Num_smt(2) As Byte 'numero di volte lettura motore fermo
'-------------------------------------------------------------------------------
Call Init_parameter(1)
Call Init_parameter(2)
Call Configura_pid(1 , 500 , 100 , 500) 'configura pid iniziale
Call Configura_pid(2 , 500 , 100 , 500) 'configura pid iniziale
'...................P....I......D
Print "(0 Motor Control by G.De Luca V1.0, 0)"
'-------------------------------------------------------------------------------
'---------------------- MAIN PROGRAM -------------------------------------------
'-------------------------------------------------------------------------------
Main
:
Do
 
If Tx_enable = 1 Then 'permetti la trasmissione
 Tx_enable
= 0
 
Print Str_tx_1 'trasmetti la stringa
 
End If
 
'.....qui controlliamo i fine corsa 2 dei motori
Loop
'-------------------------------------------------------------------------------
End
'-------------------------------------------------------------------------------
Int_0
: 'fine corsa 1 motore 1
 
Call Configura_pid(1 , 0 , 0 , 0)
 
Print "(1 FCM, 1)"
Return
'-------------------------------------------------------------------------------
Int_1
: 'fine corsa 1 motore 2
 
Call Configura_pid(2 , 0 , 0 , 0)
 
Print "(2 FCM, 1)"
Return
'-------------------------------------------------------------------------------
'---------------------- GESTIONE SERIALE ---------------------------------------
'-------------------------------------------------------------------------------
Rs232
:
 
#if Vb6
 
Input Comando Noecho 'se usato con vb6
 
#else
 Char
(1) = Inkey() 'se usato con terminal
 Char
(1) = Ucase(char(1))
 
If Char(1) = Chr(13) Then
 
Print
 
#endif
 
'...........................................................................
 
If Comando = "" Then Comando = Comando_old
 N_cmd
= Split(comando , Cmd_ar(1) , " ")
 M
= Val(cmd_ar(2))
 
'......................................................................
 
Select Case Cmd_ar(1)
 
Case "RSTF"
 
Print "(0 RST Program, 0)"
 
Start Watchdog
 
'..........................................................
 
Case "MADE"
 
Print "(0 De Luca Giovanni, 0)"
 
'..........................................................
 
Case "VER"
 
Print "(0 Ver 2.0 DEL 22-05-07, 0)"
 
'..........................................................
 
Case "SKP"
 Pid_kp
(m) = Val(cmd_ar(3))
 
Print "(" ; M ; " SKP, " ; Pid_kp(m) ; ")"
 
'..........................................................
 
Case "SKI"
 Pid_ki
(m) = Val(cmd_ar(3))
 
Print "(" ; M ; " SKI, " ; Pid_ki(m) ; ")"
 
'..........................................................
 
Case "SKD"
 Pid_kd
(m) = Val(cmd_ar(3))
 
Print "(" ; M ; " SKD, " ; Pid_kd(m) ; ")"
 
'..........................................................
 
Case "GO" 'vai in controllo posizione
 
If Mode_ctrl <> Mode_pos Then 'se mode <> da pos
 
Call Set_mode(mode_pos) 'setta a pos
 
End If
 M
= Val(cmd_ar(2))
 Pos_finale
(m) = Val(cmd_ar(3))
 
Print "(" ; M ; " GO, " ; Pos_finale(m) ; ")"
 
'..........................................................
 
Case "VMAX"
 Vmax_pos
(m) = Val(cmd_ar(3))
 Vmax_neg
(m) = -vmax_pos(m)
 
Print "(" ; M ; " VMAX, " ; Vmax_pos(m) ; ")"
 
'..........................................................
 
Case "GMAX"
 
Print "(" ; M ; " GMAX, " ; Vmax_pos(m) ; ")"

 
'..........................................................
 
Case "SVM" 'set max velocita in trp
 Vel_pos
(m) = Val(cmd_ar(3))
 Vel_last
(m) = Vel_pos(m)
 Vel_neg
(m) = -vel_pos(m)
 
Print "(" ; M ; " SVM, " ; Vel_pos(m) ; ")"
 
'..........................................................
 
Case "GVM"
 
Print "(" ; M ; " GVM, " ; Vel_pos(m) ; ")" 'get max velocita impostata
 
'..........................................................
 
Case "GVE"
 Tx_enable
= 1
 
Call Make_print(m , Cmd_ar(1) , Act_speed(m))
 
'..........................................................
 
Case "ENC"
 Tx_enable
= 1
 
Call Make_print(m , Cmd_ar(1) , Pos_encoder(m))
 
'..........................................................
 
Case "SPID" 'set pid parameter
 Pid_kp
(m) = Val(cmd_ar(3))
 Pid_ki
(m) = Val(cmd_ar(4))
 Pid_kd
(m) = Val(cmd_ar(5))
 
Print "(" ; M ; " SPID, " ; Pid_kp(m) ; " " ; Pid_ki(m) ; " " ; Pid_kd(m) ; ")"
 
'..........................................................
 
Case "GPID" 'get pid parameter
 
Print "(" ; M ; " GPID, " ; Pid_kp(m) ; " " ; Pid_ki(m) ; " " ; Pid_kd(m) ; ")" 'get pid parameter
 
'..........................................................
 
Case "STIME"
 Pid_time
= Val(cmd_ar(2))
 
Print "(" ; 0 ; " STIME, " ; Pid_time ; ")"
 
'..........................................................
 
Case "GTIME"
 
Print "(" ; 0 ; " GTIME, " ; Pid_time ; ")"
 
'..........................................................
 
Case "SZP" 'set zero position
 
Select Case M
 
Case 1
 Hctl_rst_1
= 0
  
Waitms 1
 Hctl_rst_1
= 1

 
Case 2
 Hctl_rst_2
= 0
 
Waitms 1
 Hctl_rst_2
= 1
 
End Select
 Pos_encoder
(m) = 0
 Old_encoder
(m) = 0
 Motore_setpoint
(m) = 0
 Pos_finale
(m) = 0
 New_speed
(m) = 0
 
Call Hctl_2032(m)
 
Print "(" ; M ; " SZP, " ; Pos_encoder(m) ; ")"
 
'..........................................................
 
Case "IDLE" 'metti in idle e disalimenta
 
Call Configura_pid(m , 0 , 0 , 0)
 
Print "(" ; M ; " IDLE, )"
 
'..........................................................
 
Case "GSM" 'get stato motore
 
If Act_speed(m) > 3 Or Act_speed(m) < -3 Then
 Tx_enable
= 1
 
Call Make_print(m , Cmd_ar(m) , 1) 'qui si muove
 
Else
 Tx_enable
= 1
 
Call Make_print(m , Cmd_ar(m) , 0) 'qui č fermo
 
End If
 
'..........................................................
 
Case "SMODE" 'set mode control
 Mode_ctrl
= Val(cmd_ar(3))

 
Select Case Mode_ctrl
 
Case Mode_pos
 
Call Configura_pid(m , 200 , 0 , 200) 'POSIZIONE 0
  Motore_setpoint
(m) = Pos_encoder(m)

 
Case Mode_vel
 
Call Configura_pid(m , 700 , 100 , 700) 'VELOCITA integrale 1

 
Case Mode_trp
 
Call Configura_pid(m , 500 , 100 , 500) 'TRAPEZOIDALE 2
 Pos_finale
(m) = Pos_encoder(m)

 
Case Mode_velp
 
Call Configura_pid(m , 100 , 10 , 100) 'VELOCITA proporzionale 3

 
Case Mode_idle
 
Call Configura_pid(m , 0 , 0 , 0) 'IDLE 4
 
End Select
 
Print "(0 MODE, " ; Mode_ctrl ; ")"
 
'..........................................................
 
Case "MODE"
 Mode_ctrl
= Val(cmd_ar(2)) 'tipo di controllo
 
Call Set_mode(mode_ctrl)
  
Print "(0 MODE, " ; Mode_ctrl ; ")"
 
'..........................................................
 
Case "GMODE" 'get mode control
 
Print "(0 GMODE, " ; Mode_ctrl ; ")"
 
'..........................................................
 
Case "SVEL" 'set velocita in vel mode
 
If Mode_ctrl <> Mode_vel Then 'se mode <> da trapezoidale
 
Call Set_mode(mode_vel)
 
End If
 Motore_setpoint
(m) = Val(cmd_ar(3)) 'valori -127 +127
 
Print "(" ; M ; " SVEL, " ; Motore_setpoint(m) ; ")"
 
'..........................................................
 
Case "VELO"
 
If Mode_ctrl <> Mode_vel Then 'se mode <> da trapezoidale
 
Call Set_mode(mode_vel)
 
End If
 Motore_setpoint
(1) = Val(cmd_ar(2)) 'valori -127 +127
 Motore_setpoint
(2) = Val(cmd_ar(3))
 
'..........................................................
  
Case "SPWM" 'max pwm per regolare la coppia massima
 Max_pwm
(m) = Val(cmd_ar(3))
 
Print "(" ; M ; " SPWM, " ; Max_pwm(m) ; ")"
 
'..........................................................
 
Case "GPWM" 'get pwm massimo
 
Print "(" ; M ; " GPWM, " ; Max_pwm(m) ; ")"
 
'..........................................................
 
Case "RPWM" 'get valore pwm uscita
 
Print "(" ; M ; " RPWM, " ; Rpwm(m) ; ")"
 
'..........................................................
  
Case "SACC"
 Deg
(m) = Val(cmd_ar(3))
 Rad
(m) = Deg2rad(deg(m))
 Rad
(m) = Tan(rad(m))
 Vel_max
(m) = Vel_pos(m) * 10
 Punto_p1
(m) = Vel_max(m) / Rad(m)
 Punto_p1
(m) = Punto_p1(m) * 10
 
Print "(" ; M ; " SACC, " ; Deg(m) ; ")"
 
'... Print "P1: " ; Punto_p1(m)
 
'..........................................................
 
Case "GACC" 'calcola pendenza accelerazione
 
Print "(" ; M ; " GACC, " ; Deg(m) ; ")"
 
'..........................................................
 
Case "SANG" 'imposta fattore angolare
 Fattore_acc
(m) = Val(cmd_ar(3))
 
Print "(" ; M ; " SANG, " ; Fattore_acc(m) ; ")"
 
'..........................................................
 
Case "GANG" 'leggi fattore angolare
 
Print "(" ; M ; " GANG, " ; Fattore_acc(m) ; ")"
 
'..........................................................
 
Case "POS"
 
If Mode_ctrl <> Mode_trp Then 'se mode <> da trapezoidale
 
Call Set_mode(mode_trp)
 
End If
  Pos_finale
(m) = Val(cmd_ar(3))
 Vel_pos
(m) = Val(cmd_ar(4))
 
Call Calcola_trapezio(m)
 Start_move
= True
 
'..........................................................
 
Case "MOVE"
 
If Mode_ctrl <> Mode_trp Then 'se mode <> da trapezoidale
 
Call Set_mode(mode_trp)
 
End If
  Pos_finale
(1) = Val(cmd_ar(2))
 Pos_finale
(2) = Val(cmd_ar(3))
 Vel_pos
(1) = Val(cmd_ar(4))
 Vel_pos
(2) = Val(cmd_ar(4))
 
Call Calcola_trapezio(1)
 
Call Calcola_trapezio(2)
 
Print "(0 MOVE, " ; Pos_finale(1) ; " " ; Pos_finale(2) ; ")"
 
'Start_move = False 'se si vuole avviare con start
 
'..........................................................
 
Case "VELP"
 
If Mode_ctrl <> Mode_velp Then 'se mode <> da velocita
 
Call Set_mode(mode_velp)
 
End If
  Acc_speed_p
(1) = Vmax_pos(1)
 Acc_speed_p
(2) = Vmax_pos(2)
 Acc_speed_n
(1) = Vmax_neg(1)
 Acc_speed_n
(2) = Vmax_neg(2)
 Fattore_ang
(1) = Fattore_acc(1)
 Fattore_ang
(2) = Fattore_acc(2)
 Pos_finale
(1) = Val(cmd_ar(2))
 Pos_finale
(2) = Val(cmd_ar(3))
 
'..........................................................
 
Case "SUM"
 Somma
= Val(cmd_ar(2))
 
'..........................................................
 
Case "START"
 Start_move
= True
 
Print "(0 START, 0)"
  
'..........................................................
 
Case "STOP"
 Mode_ctrl
= Mode_idle
 
Print "(0 STOP, 0)"
 
'..........................................................
 
Case "RST"
 
If M = 1 Then
 Hctl_rst_1
= 0
 
Waitms 1
 Hctl_rst_1
= 1
 
End If
 
If M = 2 Then
 Hctl_rst_2
= 0
 
Waitms 1
 Hctl_rst_2
= 1
 
End If
 
Call Hctl_2032(m)
 
Print "(" ; M ; " RST, " ; Pos_encoder(m) ; ")"
 
'..........................................................
 
Case Else
 
If Mode_ctrl <> Mode_velp Then 'se mode <> da trapezoidale
 
Call Set_mode(mode_velp)
 
End If
 Pos_finale
(1) = Pos_finale(1) + Somma
 Pos_finale
(2) = Pos_finale(2) + Somma
 
'..........................................................
  
End Select
 Comando_old
= Comando
 Comando
= ""
 
'......................................................................
 
#if Vb6
 
#else
 
Else
 Comando
= Comando + Chr(char(1))
 
Print Comando ; Chr(13);
 
End If
 
#endif
Return
'-------------------------------------------------------------------------------
'----------------------- esecuzione PID ----------------------------------------
'-------------------------------------------------------------------------------
'la routine seguente viene eseguita per i due motori in 500 uSec ad una freq di 280 hz
'il periodo di intervento PID č di 3.5 msec con timer_pid = 4
Timer_0
:
 
If Timer_pid = Pid_time Then
 Timer_pid
= 0
 
For Mot = 1 To 2
  Motor_led
= True
 
Call Hctl_2032(mot) 'LEGGI IL VALORE DALL'ENCODER
 Act_speed
(mot) = Pos_encoder(mot) - Old_encoder(mot) 'con 12 Volt ed encoder HEDS-5540
 Old_encoder
(mot) = Pos_encoder(mot) 'se Pos_encoder(1)=10000 abbiamo trap_1(1)=30000
 New_speed
(mot) = Pos_finale(mot) - Pos_encoder(mot) 'differenza per ogni campionamento
 Differenza
(mot) = Pos_finale(mot) - Pos_encoder(mot) 'questo calcolo serve x controllo continuo velocita
 
'------------------------------------------------------------------------
 
'///// se si cambia di segno prima togli velocita e poi accelera \
 
'------------------------------------------------------------------------
 
If Flag_velocita = True Then
 
'.....................................................................
 
If Pos_finale(mot) => Pos_encoder(mot) Then Dir_diff(mot) = True '--->
 
If Pos_finale(mot) < Pos_encoder(mot) Then Dir_diff(mot) = False '<---
 
'.....................................................................
 
If Dir_diff(mot) = True Then ' 99 / 100 = 0 'qui si ferma prima ma abbiamo la decellerazione
 
If Differenza(mot) <= 10000 Then Acc_speed_p(mot) = New_speed(mot) / Fattore_acc(mot) 'decellera
 
If Acc_speed_p(mot) <= 1 Then Acc_speed_p(mot) = 1
 
If New_speed(mot) => Vmax_pos(mot) Then New_speed(mot) = Vmax_pos(mot)
 
If New_speed(mot) => Acc_speed_p(mot) Then New_speed(mot) = Acc_speed_p(mot)
 
End If
 
'.....................................................................
 
If Dir_diff(mot) = False Then
 
If Differenza(mot) => -10000 Then Acc_speed_n(mot) = New_speed(mot) / Fattore_acc(mot) 'decellera
 
If Acc_speed_n(mot) => -1 Then Acc_speed_n(mot) = -1
 
If New_speed(mot) <= Vmax_neg(mot) Then New_speed(mot) = Vmax_neg(mot)
 
If New_speed(mot) <= Acc_speed_n(mot) Then New_speed(mot) = Acc_speed_n(mot)
 
End If
 
'.....................................................................
 
End If
 
'------------------------------------------------------------------------
 
If Flag_velocita = False Then
 
If Dir_diff(mot) = True Then
 New_encoder
(mot) = Trap_1(mot) - Pos_encoder(mot) '30000 - 10000 = 20000
 New_encoder
(mot) = Punto_p1(mot) - New_encoder(mot) '20000 - 20000 = 0
 
If Pos_encoder(mot) < Trap_1(mot) Then Acc_speed(mot) = New_encoder(mot) / Fattore_acc(mot) 'accelerazione prima di trap_1 -->
 
If Pos_encoder(mot) => Trap_2(mot) Then Acc_speed(mot) = New_speed(mot) / Fattore_acc(mot) 'decelerazione dopo trap_2 -->
 
If Acc_speed(mot) <= 1 Then Acc_speed(mot) = 1
 
If New_speed(mot) => Vel_pos(mot) Then New_speed(mot) = Vel_pos(mot) 'ferma su velocita massima
 
If New_speed(mot) => Acc_speed(mot) Then New_speed(mot) = Acc_speed(mot) 'riduci la velocita
 
End If 'mentre viene ridotta l'accelerazione
 
'........................................................................
 
If Dir_diff(mot) = False Then
 New_encoder
(mot) = Trap_1(mot) - Pos_encoder(mot) '80000 - 99000 = -20000
 New_encoder
(mot) = New_encoder(mot) + Punto_p1(mot) '21000 - 20000) = -1000
 New_encoder
(mot) = -new_encoder(mot) 'inverti di segno. qui new_encoder č negativo
 
If Pos_encoder(mot) => Trap_1(mot) Then Acc_speed(mot) = New_encoder(mot) / Fattore_acc(mot) 'accelerazione prima di trap_1 <--
 
If Pos_encoder(mot) < Trap_2(mot) Then Acc_speed(mot) = New_speed(mot) / Fattore_acc(mot) 'decelerazione dopo di trap_2 <--
 
If Acc_speed(mot) => -1 Then Acc_speed(mot) = -1
 
If New_speed(mot) <= Vel_neg(mot) Then New_speed(mot) = Vel_neg(mot) 'ferma su velocita negativa
 
If New_speed(mot) <= Acc_speed(mot) Then New_speed(mot) = Acc_speed(mot) 'riduci la velocita
 
End If
 
End If
 
'------------------------------------------------------------------------
 
Select Case Mode_ctrl
 
Case Mode_pos
 
Call Exe_pid(mot , Pos_finale(mot) , Pos_encoder(mot))
 
'...........................................................
 
Case Mode_vel
 
Call Exe_pid(mot , Motore_setpoint(mot) , Act_speed(mot))
 
'...........................................................
 
Case Mode_trp
 Motore_setpoint
(mot) = New_speed(mot)
 
If Start_move = 0 Then Motore_setpoint(mot) = 0
 
Call Exe_pid(mot , Motore_setpoint(mot) , Act_speed(mot))
 
'...........................................................
 
Case Mode_velp
 Motore_setpoint
(mot) = New_speed(mot)
 
Call Exe_pid(mot , Motore_setpoint(mot) , Act_speed(mot))
 
'...........................................................
 
Case Mode_idle
 
Call Configura_pid(mot , 0 , 0 , 0)
 
'..Pos_encoder(mot) = 0
 
'..Old_encoder(mot) = 0
 
'..Motore_setpoint(mot) = 0
 
'..Pos_finale(mot) = 0
 
'..New_speed(mot) = 0
 
If Mot = 1 Then Motor_pwm_1 = 0
 
If Mot = 2 Then Motor_pwm_2 = 0
 
End Select
 
'........................................................................
 
If Act_speed(1) > 2 Or Act_speed(1) < -2 Then 'se quasi fermo
 Num_smt
(1) = 0 'controlla se in movimento
 
Else
 
Incr Num_smt(1) 'se fermo, vedi x quanto tempo
 
End If

  
If Act_speed(2) > 2 Or Act_speed(2) < -2 Then 'se quasi fermo
 Num_smt
(2) = 0
 
Else
 
Incr Num_smt(2)
 
End If
 
'..........................................................................
 
If Num_smt(1) > 200 Then Num_smt(1) = 200 'non azzerra a 255
 
If Num_smt(2) > 200 Then Num_smt(2) = 200 'non azzerra a 255
  
If Num_smt(1) > 150 Then Smt_1 = 0 Else Smt_1 = 1
 
If Num_smt(2) > 150 Then Smt_2 = 0 Else Smt_2 = 1
 
'..........................................................................
 
Next Mot
End If
 
Incr Timer_pid
 Motor_led
= False
Return
'-------------------------------------------------------------------------------
'----------------------- CALCOLO DEL PID ---------------------------------------
'----------------------- tempo PER PID = 90 uSecondi ---------------------------
'-------------------------------------------------------------------------------
Sub Exe_pid(mot , Pid_setpoint , Pid_actual) '90 microsecondi

'.. Motor_led = True
 Pid_error
(mot) = Pid_setpoint - Pid_actual
 Pid_out
(mot) = Pid_error(mot) * Pid_kp(mot)
 Ptemp
(mot) = Pid_error(mot) - Pid_prev_error(mot)
 Pid_prev_error
(mot) = Pid_error(mot)
 Ptemp
(mot) = Ptemp(mot) * Pid_kd(mot)
 Pid_out
(mot) = Pid_out(mot) + Ptemp(mot)
 Ptemp
(mot) = Pid_integral_error(mot) * Pid_ki(mot)
 Pid_out
(mot) = Pid_out(mot) + Ptemp(mot)
 Pid_out
(mot) = Pid_out(mot) / Pid_scale(mot)

 
If Pid_out(mot) > 255 Then 'limita il valore a 8 bit
 Pid_out
(mot) = 255
 
Elseif Pid_out(mot) < -255 Then
 Pid_out
(mot) = -255
 
Else
 Pid_error
(mot) = Pid_error(mot) + Pid_integral_error(mot)
 
If Pid_error(mot) > 255 Then
 Pid_error
(mot) = 255
 
Elseif Pid_error(mot) < -255 Then
 Pid_error
(mot) = -255
 
End If
 Pid_integral_error
(mot) = Pid_error(mot)
 
End If

 
If Mot = 1 Then
 
If Pid_out(mot) => 0 Then Motor_dir_1 = 0 'setta la direzione del motore
 
If Pid_out(mot) < 0 Then Motor_dir_1 = 1
 Pid_out
(mot) = Abs(pid_out(mot)) 'calcola il valore assoluto
 
If Pid_out(mot) => Max_pwm(mot) Then Pid_out(mot) = Max_pwm(mot)
 Motor_pwm_1
= Pid_out(mot) 'imposta il pwm
 Rpwm
(mot) = Pid_out(mot) 'segnale uscita test
 
End If

 
If Mot = 2 Then
 
If Pid_out(mot) => 0 Then Motor_dir_2 = 0 'setta la direzione del motore
 
If Pid_out(mot) < 0 Then Motor_dir_2 = 1
 Pid_out
(mot) = Abs(pid_out(mot)) 'calcola il valore assoluto
 
If Pid_out(mot) => Max_pwm(mot) Then Pid_out(mot) = Max_pwm(mot)
 Motor_pwm_2
= Pid_out(mot) 'imposta il pwm
 Rpwm
(mot) = Pid_out(mot)  'segnale uscita test
 
End If
'.. Motor_led = False
End Sub
'-------------------------------------------------------------------------------
'---------------------- Configurazione pid -------------------------------------
'-------------------------------------------------------------------------------
Sub Configura_pid(m , Mot_kp , Mot_ki , Mot_kd)
 Pid_kp
(m) = Mot_kp
 Pid_ki
(m) = Mot_ki
 Pid_kd
(m) = Mot_kd
 Pid_scale
(m) = 100
End Sub
'-------------------------------------------------------------------------------
'----------------------- LETTURA HCTL 2032 -------------------------------------
'-------------------------------------------------------------------------------
Sub Hctl_2032(mot)
 
If Mot = 1 Then Hctl_xy = 0
 
If Mot = 2 Then Hctl_xy = 1

 Hctl_oe
= 0 'oe
 Hctl_sel1
= 0 'selezione primo byte msb
 Hctl_sel2
= 1 'seleziona primo byte msb
 Data_4
= Hctl_data 'msb byte

 Hctl_sel1
= 1
 Hctl_sel2
= 1
 Data_3
= Hctl_data '2nd byte

 Hctl_sel1
= 0
 Hctl_sel2
= 0
 Data_2
= Hctl_data '3rd byte

 Hctl_sel1
= 1
 Hctl_sel2
= 0
 Data_1
= Hctl_data 'lsb byte
 Hctl_oe
= 1

 Pos_encoder
(mot) = Data_1
 Temp_enc
= Data_2 * 256
 Pos_encoder
(mot) = Pos_encoder(mot) + Temp_enc
 Temp_enc
= Data_3 * 65536
 Pos_encoder
(mot) = Pos_encoder(mot) + Temp_enc
 Temp_enc
= Data_4 * 16777216
 Pos_encoder
(mot) = Pos_encoder(mot) + Temp_enc
End Sub
'-------------------------------------------------------------------------------
'------------------------- inizializza parametri -------------------------------
'-------------------------------------------------------------------------------
Sub Init_parameter(m)
 Pid_time
= 4 'tempo di pid
 Somma
= 1000
 Vmax_pos
(m) = 126
 Vmax_neg
(m) = -vmax_pos(m)
 Vel_pos
(m) = 126 'velocita iniziale
 Vel_last
(m) = Vel_pos(m) 'salva il valore last
 Vel_neg
(m) = -vel_pos(m) 'velocita negativa iniziale
 Flag_velocita
= False
 Start_move
= True 'start move attivo
 Max_pwm
(m) = 250 'massimo valore pwm in uscita
 Deg
(m) = 45 'pendenza accelerazione in grad(1)i
 Fattore_acc
(m) = 100
 Punto_p1
(m) = 20000  'punto 1
 Motore_setpoint
(m) = 0 'posizione iniziale = 0
 
If M = 1 Then Motor_pwm_1 = 0 'pwm x uscita = 0
 
If M = 2 Then Motor_pwm_2 = 0 'pwm y uscita = 0
 Mode_ctrl
= Mode_trp 'controllo trapezoidale
End Sub
'-------------------------------------------------------------------------------
'------------------------- CALCOLO DEL PROFILO TRAPEZIOIDALE -------------------
'-------------------------------------------------------------------------------
Sub Calcola_trapezio(m)
 
If Vel_pos(m) = 0 Then Vel_pos(m) = Vel_last(m)

 Rad
(m) = Deg2rad(deg(m)) 'trasforma in radianti i gradi pendenza
 Rad
(m) = Tan(rad(m)) 'calcola la tangente dell'angolo
 Vel_max
(m) = Vel_pos(m) * 10 'per calcolare la distanza del punto p1
 Punto_p1
(m) = Vel_max(m) / Rad(m)
 Punto_p1
(m) = Punto_p1(m) * 10

 
'.....Print "P1: " ; Punto_p1(m)

 Vel_neg
(m) = -vel_pos(m)
 Vel_last
(m) = Vel_pos(m)

 
Call Hctl_2032(m)

 Diff_posizione
(m) = Pos_finale(m) - Pos_encoder(m)
 Diff_posizione
(m) = Abs(diff_posizione(m))

 Fattore_acc
(m) = Punto_p1(m) / Vel_pos(m) 'messo qui ma prima era giu prima di print
 
'..........................................................aggiunto con ACC command
 Diff_2
(m) = Diff_posizione(m) / 2
 
If Punto_p1(m) > Diff_2(m) Then
 Punto_p1
(m) = Diff_2(m)
 Punto_p1
(m) = Punto_p1(m) / 2
 
End If
 
'..........................................................
 
If Pos_finale(m) => Pos_encoder(m) Then Dir_diff(m) = True '--->
 
If Pos_finale(m) < Pos_encoder(m) Then Dir_diff(m) = False '<---
 
'..........................................................
 
If Dir_diff(m) = True Then
 Trap_1
(m) = Pos_encoder(m) + Punto_p1(m)
 Trap_2
(m) = Pos_finale(m) - Punto_p1(m)
 
End If
 
'..........................................................
 
If Dir_diff(m) = False Then
 Trap_1
(m) = Pos_encoder(m) - Punto_p1(m)
 Trap_2
(m) = Pos_finale(m) + Punto_p1(m)
 
End If
 
'..........................................................
 
Print "(" ; M ; " POS, " ; Pos_finale(m) ; ")"
 
'...Print "Trapezio: " ; Trap_1(m) ; ", " ; Trap_2(m)
 
'...Print "Fatt ang: " ; Fattore_acc(m)
End Sub
'-------------------------------------------------------------------------------
Sub Make_print(mt , Stringa , Valore)
 Str_tx_1
= "(" + Str(mt) + " " + Stringa + ", " + Str(valore) + ")"
End Sub
'-------------------------------------------------------------------------------
Sub Set_mode(mode_control)
 
Select Case Mode_control
 
Case Mode_pos 'POSIZIONE 0
 Flag_velocita
= False
 
Call Configura_pid(1 , 200 , 0 , 200)
 
Call Configura_pid(2 , 200 , 0 , 200)
 Pos_finale
(1) = Pos_encoder(1)
 Pos_finale
(2) = Pos_encoder(2)

 
Case Mode_vel 'VELOCITA 1
 Flag_velocita
= False
 
Call Configura_pid(1 , 700 , 100 , 700)
 
Call Configura_pid(2 , 700 , 100 , 700)
  Motore_setpoint
(1) = 0
 Motore_setpoint
(2) = 0

 
Case Mode_trp 'TRAPEZOIDALE 2
 Flag_velocita
= False
  
Call Configura_pid(1 , 500 , 100 , 500)
 
Call Configura_pid(2 , 500 , 100 , 500)
 Pos_finale
(1) = Pos_encoder(1)
 Pos_finale
(2) = Pos_encoder(2)

 
Case Mode_velp 'VELOCITA PID 3
 Flag_velocita
= True
 
Call Configura_pid(1 , 400 , 100 , 400)
 
Call Configura_pid(2 , 400 , 100 , 400)
 Pos_finale
(1) = Pos_encoder(1)
 Pos_finale
(2) = Pos_encoder(2)

 
Case Mode_idle 'IDLE 4
 Flag_velocita
= False
 
Call Configura_pid(1 , 0 , 0 , 0)
 
Call Configura_pid(2 , 0 , 0 , 0)
 
End Select
 Mode_ctrl
= Mode_control
End Sub
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------