View previous topic :: View next topic |
Author |
Message |
DiegoCasso
Joined: 12 Apr 2015 Posts: 7
|
PWM with bluetooth |
Posted: Mon Apr 13, 2015 6:47 pm |
|
|
Hey there, I'm working on a school project and I need some help at this point. I'm making a bluetooth controlled car, this must be able to work with three different speeds - low, medium, high-, and it's speed must be measured and printed on the same app that controls it.
The app is not the problem, I have problems coding the PWM, and I'm using the TIMER1 to count the pulses delivered by an H21A1 optical sensor, I'm not sure if the bluetooth data receive/transmit program is ok. I would really appreciate any possible help.
I'm using a PIC16F628A.
Don't mind the comments in spanish, sorry .
Code: |
#include <Carrito sensor.h>
#include <stdio.h>
#use fast_io(B)
#use RS232(baud=9600, xmit=PIN_B2, rcv=PIN_B1) //Declaramos uso del UART y su baudaje, pines de transmisión y recepción
long pulsos; // Declaramos una variale para poder guardar valores grandes, en este caso las pulsaciones
long rpm=0;
float vlineal=0;
float kxh=0;
int velocidad;
unsigned char Dato=0;
/*Comunicación serial*/
//Función de Interrupción por Recepción
static void interrupt isr(void){ //Funcion para interrupcion por recepcion de la usart // Interrupt Service Routines
if(kbhit()==1){ //Se cumple si entra un dato por el pin receptor de la USART
Dato=getc(); //Si llega un dato guardalo en el registro Dato
}
}
//Inicio de programa de comunicación serial, este esta diseñado en MPLAB
//SECCIÓN DE FUNCIONES
//Función de Inicializacion de Módulo UART
void UARTinit9600 (void)
{
TXSTA= 0B00100100; // 0B00100100; // = 0X22 // TXEN=1, BRGH=1 --> Habilita Transmisión y Bajo Baudaje //
RCSTA= 0B10010000; // = 0X90 // SPEN=1, CREN=1 --> Habilita Puerto Serial y Recepción
SPBRG= 25; // BRGH=1
}
//Función de Inicializacion de las Interrupciones por Recepción
void InterruptsInit(void)
{
enable_interrupts(GLOBAL); // Habilitamos las Interrupciones Globales // BIT 7 - Registro INTCON
enable_interrupts(PERIPH); // Habilitamos las Interrupciones por Perifericos // BIT 6 - Registro INTCON
enable_interrupts(int_rda); // Habilitamos la Interrupcion por Recepcion del modulo USART l // BIT 5 - Registro RCIE
RCIF=0; // Apagamos la Bandera de Interrupcion // BIT 5 - Registro PIR1
}
//Rutina de Configuración General del Microcontrolador
void comunicacion_serial()
{
CMCON = 0B00000111;
//Eliminar posible LATCH o Basura en los Puertos
PORTB = 0B00000000; //Configuro el registro LATB - Se elimina posible basura o latch en el Puerto B
//FUNCIONES DE INICIALIZACION DE PERIFERICOS
UARTinit9600();
InterruptsInit();
}
void controles (void){
if (Dato=="n"){ //Aquí el carrito se mueve hacia el frente.
output_high(PIN_A2); //Primer motor avanza adelante.
output_low(PIN_A3);
output_high(PIN_B4); //Segundo motor avanza hacia adelante.
output_low(PIN_B5);
}
if (Dato=="s"){ //Aquí el carrito se mueve hacia el atrás.
output_low(PIN_A2); //Primer motor retrocede.
output_high(PIN_A3);
output_low(PIN_B4); //Segundo motor retrocede.
output_high(PIN_B5);
}
if (Dato=="e"){ //Aquí el carrito se mueve hacia la derecha.
output_high(PIN_A2); //Primer motor avanza adelante.
output_low(PIN_A3);
output_low(PIN_B4); //Segundo motor se detiene.
output_low(PIN_B5);
}
if (Dato=="o"){ //Aquí el carrito se mueve hacia la derecha.
output_low(PIN_A2); //Primer motor se detiene.
output_low(PIN_A3);
output_high(PIN_B4); //Segundo motor avanza adelante.
output_low(PIN_B5);
}
if (Dato=="x"){ //Aquí el carrito se mueve hacia la derecha.
output_low(PIN_A2); //Primer motor se detiene.
output_low(PIN_A3);
output_low(PIN_B4); //Segundo motor se detiene.
output_low(PIN_B5);
}
}
void reset (void){ //Esto lo había puesto anteriormente en el ciclo while, y es que necesito esa interrupción
//al 1 segundo para poder contar los pulsos por segundos y sacar la velocidad, no sé si se pueda hacer unafunción de interrupción interna.
pulsos=0; //Reiniciamos la variable a 0
set_timer1(0); //Reiniciamos la cuenta del timer a 0
}
void main(){
//Registros de Configuración Inicial
setup_timer_1(T1_EXTERNAL|RTCC_EXT_H_TO_L|RTCC_DIV_1); //Se configura el Timer1 como contador para interrupciones externas por flancos de bajada, y registra cada pulso
set_timer1(0); //Iniciamos el timer en 0 *Los pulsos deben entrar por RB7*
enable_interrupts(GLOBAL); //Se habilitan las interrupciones globales
set_tris_B(0x00); //Declaramos entradas y salidas en RA
set_tris_A(0x00); //Declaramos entradas y salidas en RB
output_low(PIN_A2); //Primer motor detenido.
output_low(PIN_A3);
output_low(PIN_B4); //Segundo motor detenido.
output_low(PIN_B5);
/*PWM*/
//Configuramos el como generador de PWM
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 49, 1);
port_b_pullups(TRUE);
//Se toma en cuenta la dirección del carrito
controles();
//Velocidad alta
if (Dato=="a"){
velocidad=50;
delay_ms(250);
set_pwm1_duty(velocidad);
}
//Velocidad baja
if (Dato=="b"){
velocidad=8;
delay_ms(250);
set_pwm1_duty(velocidad);
}
//Velocidad media
if (Dato=="m"){
velocidad=25;
delay_ms(250);
set_pwm1_duty(velocidad);
}
while(TRUE){
pulsos=get_timer1();
rpm=pulsos*60;
vlineal=rpm*0.035*0.10472;
kxh=(vlineal/1000)*3600;
output_high(PIN_B0); //Deja encendido el Led para saber que el carrito esta encendido
delay_ms(1000); //Al final del retardo tenemos el número de pulsos por segundo
reset(); //No sé si esté bien declarada asi la función para el reseteo del conteo del timer
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 13, 2015 7:02 pm |
|
|
This won't work:
Quote: |
if (Dato=="n"){ //Aquí el carrito se mueve hacia el frente.
output_high(PIN_A2); //Primer motor avanza adelante.
output_low(PIN_A3);
output_high(PIN_B4); //Segundo motor avanza hacia adelante.
output_low(PIN_B5);
}
|
In the C language, a character is represented by putting it in single-
quotes. If you use double-quotes, the compiled code will not do what
you want.
Do it like this:
Code: |
if (Dato== 'n'){ //Aquí el carrito se mueve hacia el frente.
output_high(PIN_A2); //Primer motor avanza adelante.
output_low(PIN_A3);
output_high(PIN_B4); //Segundo motor avanza hacia adelante.
output_low(PIN_B5);
}
|
Change all the other if() statements in your program to do it the same way. |
|
|
DiegoCasso
Joined: 12 Apr 2015 Posts: 7
|
|
Posted: Mon Apr 13, 2015 7:50 pm |
|
|
Ok I'll change it, are the other statements correct?? I don't really know how to connect PIN B4(CCP) to the motor driver, I've already search for the data sheet but it's not so clear. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 13, 2015 8:17 pm |
|
|
Quote: | I don't really know how to connect PIN B4(CCP) to the motor driver. |
1. Post a link to the data sheet for the motor driver.
2. Post a schematic of your project.
How to post an image on the CCS forum:
Go to this website: http://postimage.org/
Upload your image. Select family safe. Then click the first button for
"Hotlink to Forum" to get a link to the image.
Then go to the CCS forum and type Ctrl-V to paste the link into a post.
If postimage.org doesn't work in your country, then use Google to find
another free image hosting site for forums. |
|
|
DiegoCasso
Joined: 12 Apr 2015 Posts: 7
|
|
|
DiegoCasso
Joined: 12 Apr 2015 Posts: 7
|
|
Posted: Mon Apr 13, 2015 8:53 pm |
|
|
I cannot post the schematic of my project :/ the driver I'm using, the bluetooth module, and the H21A1 optical sensor are not in the component's list of Proteus. |
|
|
DiegoCasso
Joined: 12 Apr 2015 Posts: 7
|
|
Posted: Mon Apr 13, 2015 8:56 pm |
|
|
How can I change this statements to CCS?
Code: |
void UARTinit9600 (void)
{
TXSTA= 0B00100100; // 0B00100100; // = 0X22 // TXEN=1, BRGH=1 --> Habilita Transmisión y Bajo Baudaje //
RCSTA= 0B10010000; // = 0X90 // SPEN=1, CREN=1 --> Habilita Puerto Serial y Recepción
SPBRG= 25; // BRGH=1
}
void InterruptsInit(void)
{
RCIF=0; // Apagamos la Bandera de Interrupcion // BIT 5 - Registro PIR1
}
void comunicacion_serial()
{
CMCON = 0B00000111;
//Eliminar posible LATCH o Basura en los Puertos
PORTB = 0B00000000; //Configuro el registro LATB - Se elimina posible basura o latch en el Puerto B
//FUNCIONES DE INICIALIZACION DE PERIFERICOS
UARTinit9600();
InterruptsInit();
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Apr 13, 2015 11:26 pm |
|
|
Quote: |
How can I change this statements to CCS?
void UARTinit9600 (void)
{
TXSTA= 0B00100100; // 0B00100100; // = 0X22 // TXEN=1, BRGH=1 --> Habilita Transmisión y Bajo Baudaje //
RCSTA= 0B10010000; // = 0X90 // SPEN=1, CREN=1 --> Habilita Puerto Serial y Recepción
SPBRG= 25; // BRGH=1
}
|
I don't know what your oscillator frequency is. Assuming you're using
the internal oscillator at 4 MHz, then the CCS setup is like this:
Code: |
#include <16F628a.h>
#fuses INTRC_IO, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
|
Quote: | set_tris_B(0x00); //Declaramos entradas y salidas en RA |
This TRIS setting is incorrect. The 16F628A data sheet says:
Quote: | bits TRISB<2:1> have to be set in order to
configure pins RB2/TX/CK and RB1/RX/DT
as the UART. |
This means that TRISB should be set to 0x06.
You don't have to use #fast_io. If you delete the #fast_io line and
delete your set_tris_B() line, then the compiler will automatically
set the correct TRIS for the UART.
Quote: |
How can I change this statements to CCS?
void InterruptsInit(void)
{
RCIF=0; // Apagamos la Bandera de Interrupcion // BIT 5 - Registro PIR1
} |
I don't think you need this, but if you want to do it, then do it like this:
Code: | clear_interrupt(INT_RDA); |
Quote: |
How can I change this statements to CCS?
CMCON = 0B00000111; |
CCS already does this in the startup code that the compiler inserts
at the beginning of main(). You can see this in the .LST file.
Quote: |
How can I change this statements to CCS?
PORTB = 0B00000000; //Configuro el registro LATB - Se elimina |
The equivalent CCS code is shown below.
You are using #fast_io on PortB, so the CCS code will write to PortB only.
It will not change TRISB. The 16F628A does not have a LATB register,
so your comment is not correct. |
|
|
DiegoCasso
Joined: 12 Apr 2015 Posts: 7
|
|
Posted: Tue Apr 14, 2015 11:50 pm |
|
|
Man, you really saved my life. Thank you so much for your replies. The USART coding for the bluetooth conection was not done for CCS, a friend of mine code it on MPLAB but I needed to use CCS. So far I think my code will work fine, nevertheless, I'll make a final post of my code.
Thanks a lot. |
|
|
DiegoCasso
Joined: 12 Apr 2015 Posts: 7
|
|
Posted: Wed Apr 15, 2015 12:08 am |
|
|
I compiled and I only got some errors here:
Code: |
static void interrupt isr(void){ //Funcion para interrupcion por recepcion de la usart // Interrupt Service Routines
if(kbhit()==1){ //Se cumple si entra un dato por el pin receptor de la USART
Dato=getc(); //Si llega un dato guardalo en el registro Dato
}
}
|
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Wed Apr 15, 2015 7:48 am |
|
|
DiegoCasso wrote: | I compiled and I only got some errors here:
Code: |
static void interrupt isr(void){ //Funcion para interrupcion por recepcion de la usart // Interrupt Service Routines
if(kbhit()==1){ //Se cumple si entra un dato por el pin receptor de la USART
Dato=getc(); //Si llega un dato guardalo en el registro Dato
}
}
|
|
Look at #int_rda in the compiler manual |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Wed Apr 15, 2015 11:25 am |
|
|
Also, you don't need Kbhit() in an interrupt.
You would not be there unless an interrupt already already occurred.
The word interrupt standalone is not valid in CCS so I put an underscore to tie it to isr.
Static is also not needed.
Code: |
void interrupt_isr(void){ //Funcion para interrupcion por recepcion de la usart // Interrupt Service Routines
Dato=getc(); //Si llega un dato guardalo en el registro Dato
// add a flag here to indicate you have data
} |
_________________ Google and Forum Search are some of your best tools!!!! |
|
|
|