#include
#include <xc.h>
#include"stdio.h"
#include "lcd.h"
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 8000000
#endif
#define ROW0 PORTCbits.RC0
#define ROW1 PORTCbits.RC1
#define ROW2 PORTCbits.RC2
#define ROW3 PORTCbits.RC3
#define COL0 PORTCbits.RC4
#define COL1 PORTCbits.RC5
#define COL2 PORTCbits.RC6
#define X_DIR_BIT PORTBbits.RB0
#define X_STEP_BIT PORTBbits.RB1
#define Y_DIR_BIT PORTBbits.RB2
#define Y_STEP_BIT PORTBbits.RB3
const unsigned char Z_seq[4] = {0x10,0x20,0x40,0x80};
static unsigned char zPos = 0;
unsigned int step_delay_extra_us = 600;
#define MAX_BLOQUES 40
#define EEPROM_COUNTER_ADDR 250
static unsigned char contador_bloques = 0;
char leer_tecla(void);
void pantalla_inicio(void);
void menu_navegable(void);
void pantalla_control_init(void);
void pantalla_control_update(char sx,char sy,char sz,char tecla);
void modo_manual(void);
void modo_grabacion(void);
void modo_reproduccion(void);
void moverX(unsigned char sentido);
void moverY(unsigned char sentido);
void moverZ(unsigned char sentido);
void parar_todos(void);
void EEPROM_Write(unsigned char addr, unsigned char data);
unsigned char EEPROM_Read(unsigned char addr);
void guardar_bloque_en_eeprom(unsigned char idx, unsigned char motor, unsigned char dir, unsign
ed char steps);
void guardar_contador_en_eeprom(unsigned char cnt);
unsigned char leer_contador_de_eeprom(void);
void lcd_print_uint3(unsigned int v);
void main(void)
{
ADCON1 = 0x07;
CMCON = 0x07;
TRISB = 0x00; PORTB = 0x00;
TRISD = 0x00; PORTD = 0x00;
TRISCbits.TRISC0 = 0;
TRISCbits.TRISC1 = 0;
TRISCbits.TRISC2 = 0;
TRISCbits.TRISC3 = 0;
TRISCbits.TRISC4 = 1;
TRISCbits.TRISC5 = 1;
TRISCbits.TRISC6 = 1;
TRISCbits.TRISC7 = 1;
PORTC &= 0xF0;
Lcd_Init();
__delay_ms(50);
pantalla_inicio();
unsigned char cnt = leer_contador_de_eeprom();
contador_bloques = (cnt <= MAX_BLOQUES) ? cnt : 0;
menu_navegable();
}
// PANTALLAS y MENU
void pantalla_inicio(void)
{
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("Brazo Robotico");
__delay_ms(10);
Lcd_Set_Cursor(2,8);
Lcd_Write_String("SG");
__delay_ms(1000);
}
void menu_navegable(void)
{
while (1) {
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("1-MANUAL 2-GRABAR");
Lcd_Set_Cursor(2,1);
Lcd_Write_String("3-REPRODUCIR");
char k = 0;
while (k == 0) {
k = leer_tecla();
__delay_ms(40);
}
if (k == '1') {
pantalla_control_init();
modo_manual();
}
else if (k == '2') {
contador_bloques = 0;
guardar_contador_en_eeprom(contador_bloques);
modo_grabacion();
}
else if (k == '3') {
modo_reproduccion();
}
__delay_ms(200);
}
}
//PANTALLA DE CONTROL
static char lastX = 0, lastY = 0, lastZ = 0, lastTecla = 0;
void pantalla_control_init(void)
{
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("X: Y: ");
Lcd_Set_Cursor(2,1);
Lcd_Write_String("Z: TECLA: ");
lastX = lastY = lastZ = lastTecla = 0;
}
void pantalla_control_update(char sx,char sy,char sz,char tecla)
{
if (sx != lastX) {
Lcd_Set_Cursor(1,3);
Lcd_Write_Char(sx);
lastX = sx;
}
if (sy != lastY) {
Lcd_Set_Cursor(1,8);
Lcd_Write_Char(sy);
lastY = sy;
}
if (sz != lastZ) {
Lcd_Set_Cursor(2,3);
if (sz == 'O') Lcd_Write_String("OPEN ");
else if (sz == 'C') Lcd_Write_String("CLOSE");
else Lcd_Write_String("STOP ");
lastZ = sz;
}
if (tecla != lastTecla) {
Lcd_Set_Cursor(2,13);
if (tecla == 0) Lcd_Write_String("--");
else Lcd_Write_Char(tecla);
lastTecla = tecla;
}
}
// MANUAL
void modo_manual(void)
{
char stateX='-', stateY='-', stateZ='S';
char tecla = 0;
while (1) {
char k = leer_tecla();
if (k == 0) {
stateX='-'; stateY='-'; stateZ='S';
tecla = 0;
} else {
switch(k){
case '2': moverX(1); stateX='>'; break;
case '8': moverX(0); stateX='<'; break;
case '4': moverY(1); stateY='>'; break;
case '6': moverY(0); stateY='<'; break;
case '1': moverZ(1); stateZ='O'; break;
case '3': moverZ(0); stateZ='C'; break;
case '5': parar_todos(); stateX='-'; stateY='-'; stateZ='S'; break;
case '#': return;
}
tecla = k;
}
pantalla_control_update(stateX,stateY,stateZ,tecla);
__delay_ms(10);
}
}
//GRABACIÓN
void modo_grabacion(void)
{
char prev = 0;
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("GRABANDO BLOQUES");
Lcd_Set_Cursor(2,1);
Lcd_Write_String("B:000/040 S:000");
while (leer_tecla() != 0) __delay_ms(40);
while (1) {
char k = leer_tecla();
Lcd_Set_Cursor(2,3);
lcd_print_uint3(contador_bloques);
Lcd_Set_Cursor(2,7);
Lcd_Write_String("/040");
if (k != 0 && prev == 0) {
unsigned char motor = 0, dir = 0;
unsigned int steps_count = 0;
if (k == '2') { motor = 1; dir = 1; }
else if (k == '8') { motor = 1; dir = 0; }
else if (k == '4') { motor = 2; dir = 1; }
else if (k == '6') { motor = 2; dir = 0; }
else if (k == '1') { motor = 3; dir = 1; }
else if (k == '3') { motor = 3; dir = 0; }
else if (k == '#') { __delay_ms(200); break; }
else { prev = k; __delay_ms(40); continue; }
while (leer_tecla() == k) {
if (motor==1) moverX(dir);
else if (motor==2) moverY(dir);
else if (motor==3) moverZ(dir);
steps_count++;
if (steps_count > 999) steps_count = 999;
Lcd_Set_Cursor(2,12);
lcd_print_uint3(steps_count);
__delay_ms(25);
}
if (steps_count > 0) {
if (contador_bloques < MAX_BLOQUES) {
unsigned char sbyte = (steps_count > 255) ? 255 : steps_count;
guardar_bloque_en_eeprom(contador_bloques,motor,dir,sbyte);
contador_bloques++;
guardar_contador_en_eeprom(contador_bloques);
}
}
}
prev = k;
__delay_ms(40);
}
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("Grabacion lista");
__delay_ms(800);
}
void modo_reproduccion(void)
{
while (1) {
unsigned char cnt = leer_contador_de_eeprom();
if (cnt > MAX_BLOQUES) cnt = 0;
contador_bloques = cnt;
if (contador_bloques == 0) {
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("Nada grabado");
__delay_ms(800);
return;
}
for (unsigned char i = 0; i < contador_bloques; i++) {
if (leer_tecla() == '#') return;
unsigned char base = i * 3;
unsigned char motor = EEPROM_Read(base+0);
unsigned char dir = EEPROM_Read(base+1);
unsigned char steps = EEPROM_Read(base+2);
Lcd_Clear();
Lcd_Set_Cursor(1,1);
Lcd_Write_String("Bloque ");
lcd_print_uint3(i+1);
Lcd_Write_String("/");
lcd_print_uint3(contador_bloques);
Lcd_Set_Cursor(2,1);
Lcd_Write_String("S:");
lcd_print_uint3(steps);
__delay_ms(100);
for (unsigned int s = 0; s < steps; s++) {
if (motor==1) moverX(dir);
else if (motor==2) moverY(dir);
else if (motor==3) moverZ(dir);
__delay_ms(25);
if (leer_tecla() == '#') return;
}
}
}
}
// ================= TECLADO =================
char leer_tecla(void)
{
const char teclas[4][3] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
for (int f = 0; f < 4; f++) {
PORTC &= 0xF0;
__delay_us(40);
PORTCbits.RC0 = (f==0);
PORTCbits.RC1 = (f==1);
PORTCbits.RC2 = (f==2);
PORTCbits.RC3 = (f==3);
__delay_us(20);
if (COL0) return teclas[f][0];
if (COL1) return teclas[f][1];
if (COL2) return teclas[f][2];
}
return 0;
}
// ================= MOTORES =================
void moverX(unsigned char sentido)
{
X_DIR_BIT = sentido;
X_STEP_BIT = 1; __delay_us(5);
X_STEP_BIT = 0; __delay_us(5);
if (step_delay_extra_us > 10) __delay_us(step_delay_extra_us);
}
void moverY(unsigned char sentido)
{
Y_DIR_BIT = sentido;
Y_STEP_BIT = 1; __delay_us(5);
Y_STEP_BIT = 0; __delay_us(5);
if (step_delay_extra_us > 10) __delay_us(step_delay_extra_us);
}
void moverZ(unsigned char sentido)
{
if (sentido) zPos = (zPos + 1) & 0x03;
else zPos = (zPos - 1) & 0x03;
PORTB = (PORTB & 0x0F) | Z_seq[zPos];
__delay_ms(4);
}
void parar_todos(void)
{
PORTB &= 0x0F;
X_STEP_BIT = 0;
Y_STEP_BIT = 0;
}
void EEPROM_Write(unsigned char addr, unsigned char data)
{
EEADR = addr;
EEDATA = data;
[Link] = 0;
[Link] = 1;
unsigned char gie = [Link];
[Link] = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
[Link] = 1;
while ([Link]);
[Link] = 0;
[Link] = gie;
}
unsigned char EEPROM_Read(unsigned char addr)
{
EEADR = addr;
[Link] = 0;
[Link] = 1;
return EEDATA;
}
void guardar_bloque_en_eeprom(unsigned char idx, unsigned char motor, unsigned char dir, unsign
ed char steps)
{
unsigned char base = idx * 3;
EEPROM_Write(base+0, motor);
EEPROM_Write(base+1, dir);
EEPROM_Write(base+2, steps);
}
void guardar_contador_en_eeprom(unsigned char cnt)
{
EEPROM_Write(EEPROM_COUNTER_ADDR, cnt);
}
unsigned char leer_contador_de_eeprom(void)
{
return EEPROM_Read(EEPROM_COUNTER_ADDR);
}
void lcd_print_uint3(unsigned int v)
{
if (v > 999) v = 999;
Lcd_Write_Char('0' + (v/100)%10);
Lcd_Write_Char('0' + (v/10)%10);
Lcd_Write_Char('0' + (v%10));
}