#include <18F2550.h>
#DEVICE ADC = 10
#include <stdlib.h>
#fuses INTRC_IO,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,NOCPD
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, STREAM=COM_A, parity=N, bits=8)
#define TX_485_ENABLE PIN_C0
char p, term[2], command[20] = "", values[10] = "";
char action;
int k = 0, contador1 = 0, newdistance = 0, winche = 0, dir = 0;
int cmxcheck = 11, mdif = 0;
int32 epoch = 0, timeon = 0, timeupd = 0, lastcmd = 0;
int16 checks = 0, cms = 0, oldchecks = 0;
int1 newcommand = 0, newsecond = 0, readsensor = 0, count = 0, checktime = 0;
float value = 0, meters = 0, distance[2];
int pic, picsaved;
//funciones 485
void USART_activa_tx(void){
output_high(TX_485_ENABLE);
delay_ms(1);
}
void USART_activa_rx(void){
delay_ms(1);
output_low(TX_485_ENABLE);
delay_ms(1);
}
// subrutina de interrupción del timer1
#int_TIMER1
void TIMER1_isr(){
contador1++;
if(contador1 == 2){
newsecond = 1;
contador1 = 0;
}
set_timer1(3036);
}
//interrupcion por usart del pic
#INT_RDA
void usart_modem(void)
{
newcommand = 0;
if (kbhit(COM_A))
{
if(p == '#') {
command[k] = '\0';
newcommand = 1;
k = 0;
}else{
command[k] = p;
k++;
}
}
}
//variables a cero
void to_zero()
{
readsensor = 0;
meters = 0;
checks = 0;
cms = 0;
}
//mueve el winche
void move()
{
to_zero();
if(winche == 0)
{
if(dir == 0)
{
output_bit(PIN_B7, 1);
output_bit(PIN_B5, 1);
readsensor = 1;
}
if(dir == 1)
{
output_bit(PIN_B6, 1);
output_bit(PIN_B4, 1);
readsensor = 1;
}
}
if(winche == 1)
{
if(dir == 0)
{
output_bit(PIN_B3, 1);
output_bit(PIN_B1, 1);
readsensor = 1;
}
if(dir == 1)
{
output_bit(PIN_B2, 1);
output_bit(PIN_B0, 1);
readsensor = 1;
}
}
}
//detiene todos los motores
void stop_all()
{
output_bit(PIN_B7, 0);
output_bit(PIN_B5, 0);
output_bit(PIN_B6, 0);
output_bit(PIN_B4, 0);
output_bit(PIN_B3, 0);
output_bit(PIN_B1, 0);
output_bit(PIN_B2, 0);
output_bit(PIN_B0, 0);
}
//detiene un winche
void stop()
{
to_zero();
if(winche == 0)
{
if(dir == 0)
{
output_bit(PIN_B7, 0);
output_bit(PIN_B5, 0);
}
if(dir == 1)
{
output_bit(PIN_B6, 0);
output_bit(PIN_B4, 0);
}
}
if(winche == 1)
{
if(dir == 0)
{
output_bit(PIN_B3, 0);
output_bit(PIN_B1, 0);
}
if(dir == 1)
{
output_bit(PIN_B2, 0);
output_bit(PIN_B0, 0);
}
}
}
//cuenta vueltas y calcula distancia recorrida 3|4|0$2$|#
void check_distance()
{
value = read_adc();
if(value < 500)
{
if(count == 1)
{
checks++;
count = 0;
timeon = epoch;
if(dir == 0){
USART_activa_tx();
printf("%f\r\n", (distance
[winche
] + meters
)); USART_activa_rx();
}
else{
USART_activa_tx();
printf("%f\r\n", (distance
[winche
] - meters
)); USART_activa_rx();
}
}
cms = checks * cmxcheck;
meters = cms / 100.0;
count = 0;
}else{
count = 1;
}
if(meters >= mdif)
{
if(dir == 0){
USART_activa_tx();
printf("%f\r\n", (distance
[winche
] + meters
)); USART_activa_rx();
}
else{
USART_activa_tx();
printf("%f\r\n", (distance
[winche
] - meters
)); USART_activa_rx();
}
distance[winche] = newdistance;
stop();
USART_activa_tx();
USART_activa_rx();
lastcmd = epoch;
}
if(checks == oldchecks && readsensor == 1 && (epoch - timeon) > 2)
{
if(action != 1){
if(dir == 0){
USART_activa_tx();
printf("%f\r\n", (distance
[winche
] + meters
)); USART_activa_rx();
distance[winche] = distance[winche] + meters;
}else{
USART_activa_tx();
printf("%f\r\n", (distance
[winche
] - meters
)); USART_activa_rx();
distance[winche] = distance[winche] - meters;
}
}else{
distance[winche] = 0;
USART_activa_tx();
printf("%f\r\n", distance
[winche
]); USART_activa_rx();
}
stop();
USART_activa_tx();
USART_activa_rx();
lastcmd = epoch;
}
oldchecks = checks;
}
//lleva el winche a la posicion cero
void reset()
{
to_zero();
if(winche == 0)
{
output_bit(PIN_B6, 1);
output_bit(PIN_B4, 1);
}
if(winche == 1)
{
output_bit(PIN_B2, 1);
output_bit(PIN_B0, 1);
}
dir = 1;
readsensor = 1;
}
//se apaga motor de subida/bajada despues de 30 segundos
void check_time(){
if((epoch - timeupd) > 30){
checktime = 0;
if(winche == 0){
output_bit(PIN_B4, 0);
output_bit(PIN_B5, 0);
}else{
output_bit(PIN_B0, 0);
output_bit(PIN_B1, 0);
}
USART_activa_tx();
USART_activa_rx();
lastcmd = epoch;
}
}
/********* Programa Principal *********/
void main(void)
{
//activo lectura entrada analógica
setup_port_A(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
//activo todos los pines A como entradas
set_tris_a(0xFF);
//activo todos los pines B como salidas
set_tris_b(0b00000000);
//activo PIN_C7 como entrada
set_tris_c(0b10000000);
//pines C0 a C5 apagados, C6 y C7 no se tocan
output_B(0b00000000);
output_bit(PIN_C0, 0);
output_bit(PIN_C1, 0);
output_bit(PIN_C2, 0);
output_bit(PIN_C3, 0);
output_bit(PIN_C4, 0);
output_bit(PIN_C5, 0);
//configuración reloj interno del pic
setup_oscillator(OSC_4MHZ);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
port_b_pullups(False);
//activo interrupciones
enable_interrupts(GLOBAL);
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER1);
//cargo el timer
set_timer1(3036);
//grabo id del pic
picsaved = 4;
//aviso de conexión
USART_activa_tx();
printf("Conected %d\r\n", picsaved
); USART_activa_rx();
//distancias en cero
distance[0] = 0;
distance[1] = 0;
lastcmd = 0;
while(TRUE)
{
//cuenta los segundos
if(newsecond){
epoch++;
newsecond = 0;
}
//chequeo de distancia recorrida
if(readsensor && distance[winche] != newdistance)
check_distance();
//chequeo tiempo de subida o bajada
if(checktime == 1) check_time();
//si hay un nuevo comando lo analizo y ejecuto
if(newcommand)
{
newcommand = 0;
if(pic == picsaved)
{
if(action == 1) // reset
{
newdistance = 0;
mdif = 20 - newdistance;
timeon = epoch;
set_adc_channel(winche);
if(newdistance != distance[winche]){
reset();
}else{
USART_activa_tx();
USART_activa_rx();
}
}
if(action == 2) // setear distancia
{
set_adc_channel(winche);
USART_activa_tx();
USART_activa_rx();
lastcmd = epoch;
}
if(action == 3) // obtener distancia
{
USART_activa_tx();
printf("%f\r\n", distance
[winche
]); USART_activa_rx();
}
if(action == 4) // mover un winche
{
set_adc_channel(winche);
mdif = newdistance - distance[winche];
dir = 0;
if(newdistance > distance[winche]) mdif = newdistance - distance[winche];
if(newdistance < distance[winche]){
mdif = distance[winche] - newdistance;
dir = 1;
}
timeon = epoch;
if(newdistance != distance[winche]) {
move();
}else{
USART_activa_tx();
USART_activa_rx();
}
}
if(action == 5) // apagar todos los motores
{
stop_all();
checktime = 0;
USART_activa_tx();
USART_activa_rx();
}
if(action == 6) // subir camara
{
if(winche == 0){
output_bit(PIN_B4, 1);
}else{
output_bit(PIN_B0, 1);
}
timeupd = epoch;
checktime = 1;
USART_activa_tx();
USART_activa_rx();
}
if(action == 7) // bajar camara
{
if(winche == 0){
output_bit(PIN_B5, 1);
}else{
output_bit(PIN_B1, 1);
}
timeupd = epoch;
checktime = 1;
USART_activa_tx();
USART_activa_rx();
}
}
}
}
}