|
|
View previous topic :: View next topic |
Author |
Message |
Rodrigo
Joined: 26 Feb 2018 Posts: 2
|
Pic does not send signal to servos |
Posted: Mon Feb 26, 2018 11:28 pm |
|
|
I'm new to this, I would like some help. I'm making a robot arm with servos. It should have the position set by entering the degree of movement from a 4x4 matrix keyboard. The degrees should be displayed on an LCD.
I have a problem because the entered degrees are displayed on the lcd, but the pic does not output to the servos.
I am using a PIC18F4550.
I hope I have your help, I post my code below...
Code: |
#include <18f4550.h>
#device ICD = TRUE
#device ADC=10
#use delay (clock=48000000)
#use i2c(Master,Fast=100000, sda=PIN_D6, scl=PIN_D7,force_sw)
#include <i2c_Flex_LCD.h>
#include <kb4x4.h> //LIBRERIA DE TECLADO
#fuses HSPLL,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,USBDIV,PLL5,CPUDIV1,DEBUG,ICSP1 // configura fuses
#USE FAST_IO(B)
#byte trisb=0x86
#byte portb=0x06
#byte trisc=0x87
#byte portc=0x07
#define use_portb_kbd TRUE //Configuración puerto b control teclado
#bit Bit_PWM0 = PORTC.0 //Bit 0 puerto C Salida modulación 0
#bit Bit_PWM1 = PORTC.1 //Bit 1 puerto C Salida modulación 1
#bit Bit_PWM2 = PORTC.2 //Bit 2 puerto C Salida modulación 2
#bit Bit_PWM3 = PORTC.3 //Bit 3 puerto C Salida modulación 3
#bit Bit_PWM4 = PORTC.4 //Bit 4 puerto C Salida modulación 4
#bit Bit_PWM5 = PORTC.5 //Bit 5 puerto C Salida modulación 5
#bit Bit_PWM6 = PORTC.6 //Bit 6 puerto C Salida modulación 6
#bit Bit_PWM7 = PORTC.7 //Bit 7 puerto C Salida modulación 7
/********************** Prototipos de las funciones ***************************/
void main (void); //función principal
void generacion_pwm (void); //genera señales moduladas para control de servos
void presentacion (void); //mensaje de presentación
/********************** Variables para generación PWM *************************/
int8 PWM0=0,PWM1=0,PWM2=0,PWM3=0,PWM4=0,PWM5=0,PWM6=0,PWM7=0; //Valores de las señales PWM
int8 control_PWM=0;
/******************************************************************************/
/******************* FUNCIÓN GENERACIÓN MODULACIONES PWM **********************/
#int_Timer0
void generacion_pwm(){
control_PWM++; //Incremento cada rebose del timer0
if (control_PWM==0){ //inicio del ciclo con todos los pulsos pwm a 1
Bit_PWM0=1;
Bit_PWM1=1;
Bit_PWM2=1;
Bit_PWM3=1;
Bit_PWM4=1;
Bit_PWM5=1;
Bit_PWM6=1;
Bit_PWM7=1;
}
//Finalizará el pulso de modulación según el valor del correspondiente pwm
if (control_PWM==PWM0) Bit_PWM0=0;
if (control_PWM==PWM1) Bit_PWM1=0;
if (control_PWM==PWM2) Bit_PWM2=0;
if (control_PWM==PWM3) Bit_PWM3=0;
if (control_PWM==PWM4) Bit_PWM4=0;
if (control_PWM==PWM5) Bit_PWM5=0;
if (control_PWM==PWM6) Bit_PWM6=0;
if (control_PWM==PWM7) Bit_PWM7=0;
set_timer0(255); //Carga del contador
}
/******************************************************************************/
/************************* PRESENTACIÓN LCD ***********************************/
void presentacion (){
lcd_clear(); //Clear Display
printf(LCD_PUTC,"\1%s","Introduce");
printf(LCD_PUTC,"\2%s"," num. de servo ");
}
/******************************************************************************/
/******************** FUNCIÓN PRINCIPAL ***************************************/
void main(){
set_tris_c(0b00000000); // Configura PIN_C1 como salida
int x; //Valor ASCII de la tecla pulsada
int tecla; //Valor numérico de la tecla pulsada
int servo; //Número de servo
int16 angulo; //Ángulo del servo
int16 centenas; //variable para las centenas del ángulo
int decenas,unidades; //Variable para las decenas y unidades del ángulo
int pwm; //valor de la modulación por teclado
trisc=0x00; //Puerto C como salida de datos
pwm0=7; //Impulso de 0,8 msg de pwm0 posición 0º
pwm1=7; //Impulso de 0,8 msg de pwm1 posición 0º
pwm2=7; //Impulso de 0,8 msg de pwm2 posición 0º
pwm3=7; //Impulso de 0,8 msg de pwm3 posición 0º
pwm4=7; //Impulso de 0,8 msg de pwm4 posición 0º
pwm5=7; //Impulso de 0,8 msg de pwm5 posición 0º
pwm6=7; //Impulso de 0,8 msg de pwm6 posición 0º
pwm7=7; //Impulso de 0,8 msg de pwm7 posición 0º
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32); //Configuración interrupción generación PWM
enable_interrupts(INT_TIMER0); //Habilitación interrupción generación pwm
enable_interrupts(GLOBAL); //Habilitación de las interrupciones
port_b_pullups(TRUE); //Habilitación resistencias pullups puerto b
lcd_init(); //Inicialización del lcd
kbd_init(); //Inicialización del teclado
presentacion (); //Muestra mensaje de inicio en lcd
while (true){
x=kbd_getc(); //En "x" valor ASCII de la tecla pulsada
if (x!=0&&x!='9'&&x!='8'&&x!='*'&&x!='#'){ //Si se pulsa tecla numérica 0 a 7 ...
servo=x-48; //Valor ASCII se pasa a valor numerico de servo
printf(lcd_putc,"\fServo = %d\n", servo); //...muestra el valor pulsado
printf(LCD_PUTC,"\2%s","introduce angulo");
while (x!='*'){ //Espera a introducir ángulo y aceptar con *
x=kbd_getc();
tecla=x-48;
if (x!=0&&x!='*'&&x!='#'){ //Solo se toman los valores numéricos
//A cada tecla pulsada se desplaza posición decimal y se muestra
centenas=decenas;
decenas=unidades;
unidades=tecla;
printf(lcd_putc,"\f Angulo = %ld%d%d\n", centenas, decenas, unidades);
printf(LCD_PUTC,"\2%s","* para aceptar");
}
}
angulo=(centenas*100)+(decenas*10)+unidades;
if (angulo>180) angulo=180; //No acepta valores >180º
pwm=(angulo/13)+7; //Ajuste modulación en función del valor introducido
centenas=decenas=unidades=0;
//Según número de servo introducido se le aplica el ángulo elegido
switch(servo){
case 0: pwm0=pwm; break;
case 1: pwm1=pwm; break;
case 2: pwm2=pwm; break;
case 3: pwm3=pwm; break;
case 4: pwm4=pwm; break;
case 5: pwm5=pwm; break;
case 6: pwm6=pwm; break;
case 7: pwm7=pwm; break;
}
printf(lcd_putc,"\fServo %d\n", servo);
printf(lcd_putc," Angulo %ld", angulo);
delay_ms(200);
presentacion();
}
}
} |
_________________ Roy |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Feb 27, 2018 2:04 am |
|
|
First thing:
Code: |
#byte trisb=0x86
#byte portb=0x06
#byte trisc=0x87
#byte portc=0x07
|
These are all wrong. The values you have are for a PIC16, not a PIC18. This is why we always say 'use the register names':
Code: |
#byte trisb=getenv("SFR:TRISB")
|
etc..
So the code is not going to work.
Then there is a problem with your timer interrupt. The timer is running in 16bit mode. So it'll count from 255 (which you set it to in the interrupt), to 65535, then interrupt at 65536 (0). So 65281 counts. The timer is running off Fosc/(4*32) 375000Hz, so will interrupt every 375000/65281 = 5.744* per second. Going to be over a second pulse at a count of 7.....
If you were running in 8bit mode, much faster, but it'll almost certainly never then get out of the interrupt. Just one count of 32 machine cycles between interrupts... :(
If '7' is meant to be the zero degree output (1mSec), then you want an interrupt at 143uSec. 1714 counts of the Fosc/4 feeding the timer. Using /32, 53 counts. So:
Code: |
setup_timer_0(T1_INTERNAL|T0_DIV_32|T0_8_BIT);
//select 8bit mode
//for the timer setup, and then:
set_timer0(203);
//to make it trigger at the interval required
|
Should give about the right timing. |
|
|
Rodrigo
Joined: 26 Feb 2018 Posts: 2
|
Ayuda... |
Posted: Tue Feb 27, 2018 1:55 pm |
|
|
Friend, I have already modified the register names and it still does not output to the servos.
Could you explain to me more, or help me with the code in the timer part?
Thank you!!! _________________ Roy |
|
|
guy
Joined: 21 Oct 2005 Posts: 297
|
|
Posted: Fri Mar 02, 2018 1:29 pm |
|
|
Hola Rodrigo.
Start by checking that the registers and setup are correct - send 1ms pulse every 20ms to one servo (no interrupts):
output_high()
delay_ms(1)
output_low()
delay_ms(19)
If the setup is working ok you can debug the timer and logic easily with an oscilloscope. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|