#include "pic16f628.h" typedef unsigned int word; word at 0x2007 __CONFIG = _CP_OFF & _WDT_ON & _BODEN_ON & _PWRTE_ON & _EXTCLK_OSC & _MCLRE_ON & _LVP_OFF ; #define HZ 1000 /* CLK is osc/4 */ #define CLK 1000000 #define HZ_T 65535-(CLK/HZ) #define HZ_L (HZ_T % 255) #define HZ_H (HZ_T / 256) #define M0_SPEED_MIN 15 #define M0_SPEED_MAX 25 #define M1_SPEED_MIN 15 #define M1_SPEED_MAX 25 #define M0_DELTA_DELAY 100 #define M0_DELTA_T 1 #define M1_DELTA_DELAY 100 #define M1_DELTA_T 1 #define ClrWdt() do { _asm clrwdt _endasm; } while(0) volatile unsigned short m0_speed=0; /* steps per second... */ volatile unsigned short m0_spd_count=0; /* number of ticks since last pulse */ volatile unsigned short m0_count=0; /* number of steps total */ volatile unsigned short m0_togo=0; /* number of steps remaining */ volatile unsigned char m0_direction=0; /* 0 or 1, just the pin output */ volatile unsigned char m0_phase=0; /* 0 stopped; 1 ramp up, 2 stable 3, ramp down */ volatile unsigned char m0_stepoff=0; /* should we shutoff the step */ volatile unsigned short m0_speed_max=M0_SPEED_MAX; volatile unsigned short m0_speed_min=M0_SPEED_MIN; volatile unsigned short m0_rampup=0; /* number of pulses we used from speed min to max */ volatile unsigned short m0_delta_delay=M0_DELTA_DELAY; /* number of Hz between changes */ volatile unsigned short m0_delta_t=M0_DELTA_T; /* amount of change in steps per second */ volatile unsigned short m0_delta_count=0; volatile unsigned char m0_move=0; volatile unsigned short m1_speed; /* steps per second... */ volatile unsigned short m1_spd_count; /* number of ticks since last pulse */ volatile unsigned short m1_count; /* number of steps total */ volatile unsigned short m1_togo; /* number of steps remaining */ volatile unsigned char m1_direction; /* 0 or 1, just the pin output */ volatile unsigned char m1_phase; /* 0 stopped; 1 ramp up, 2 stable 3, ramp down */ volatile unsigned char m1_stepoff; /* should we shutoff the step */ volatile unsigned short m1_speed_max; volatile unsigned short m1_speed_min; volatile unsigned short m1_rampup; /* number of pulses we used from speed min to max */ volatile unsigned short m1_delta_delay; /* number of Hz between changes */ volatile unsigned short m1_delta_t; /* amount of change in steps per second */ volatile unsigned short m1_delta_count; volatile unsigned char m1_move; static void set_step(unsigned char m, unsigned char i) { if (m== 0 ) { RA0=i; } else if (m == 1 ) { RB5 = i; }; } static void set_dir(unsigned char m, unsigned char i) { if (m== 0 ) { RA1=i; } else if (m == 1 ) { RB6 = i; }; } static void set_power(unsigned char m, unsigned char i) { if (m== 0 ) { RA2=i; } else if (m == 1 ) { RB7 = i; }; } void intr () interrupt 0 { if (TMR1IF) { /* tmr1 has overflowed, first we reset it */ TMR1ON=0; TMR1L=HZ_L; TMR1H=HZ_H; TMR1ON=1; TMR1IF=0; /* now we handle the post processing */ if (m0_stepoff) { set_step(0,0); m0_stepoff=0; if (m0_phase == 0 ) { set_power(0,0); }; }; /* are we running */ if (m0_phase != 0 ) { /* first handle any speed change */ if (m0_phase == 1 && m0_togo < m0_count/2 ) { m0_phase=3; }; if (m0_phase == 1 ) { if (m0_delta_count > m0_delta_delay) { m0_delta_count =0; m0_speed = m0_speed + m0_delta_t; if (m0_speed >= m0_speed_max) { m0_phase = 2; m0_rampup = m0_count - m0_togo; m0_speed = m0_speed_max; }; }; m0_delta_count++; }; if (m0_phase == 2 && m0_togo < m0_rampup ) { m0_phase=3; m0_delta_count = 0; }; if (m0_phase == 3 ) { if (m0_delta_count > m0_delta_delay ) { m0_delta_count = 0; m0_speed = m0_speed - m0_delta_t; if (m0_speed <= m0_speed_min) { /* don't change phase, only do that when we run out of pulses */ m0_speed=m0_speed_min; }; }; m0_delta_count++; }; /* phases are handled. determine if it's time to step the motor. */ m0_spd_count++; if (m0_speed == 0 ) { m0_phase = 0; /* odd, shouldn't see this */ } else if (m0_spd_count > (HZ / m0_speed)) { m0_spd_count=0; /* steptime */ set_step(0,1); m0_stepoff=1; m0_togo--; if (m0_togo == 0 ) { /* no more moving */ m0_move = 2 ; /* send ok */ m0_speed = 0; m0_phase = 0; }; }; }; }; } static void varset(unsigned char m, unsigned short val, unsigned char var) { if (m == 0 ) { switch (var) { case 2: m0_speed_min=val; break; case 3: m0_speed_max=val; break; case 4: m0_delta_delay = val; break; case 5: m0_delta_t = val; break; }; }; } static void move(unsigned char m, unsigned short steps, unsigned char dir) { if (m==0) { m0_phase=0; m0_spd_count=0; m0_rampup=0; m0_delta_count=0; if (steps != 0 ) { m0_speed = m0_speed_min; m0_count= steps; m0_togo = steps; m0_direction = dir; /* set to full power here */ set_power(0,1); set_dir(0,dir); m0_phase= 1; m0_move = 1; /* flag move started */ } else { m0_speed=0; m0_count=0; m0_togo=0; m0_move = 0; }; }; /* } else if (m == 1 ) { m1_phase=0; m1_spd_count=0; m1_rampup=0; m1_delta_count=0; if (steps > 0 ) { m1_speed = m1_speed_min; m1_count=steps; m1_togo = steps; m1_direction = dir; m1_phase=1; set_power(m,1); m1_move = 1; } else { m1_speed=0; m1_count=0; m1_togo=0; m1_move = 0; }; }; */ } void main() { unsigned char m=0; unsigned char rx_phase=0; unsigned char rx_motor=0; unsigned char work_dir=0; unsigned short work_count=0; unsigned char work_char=0; unsigned char tx_phase=0; ClrWdt(); /* set motors to off, this will be done by the C init of the global variables */ /* setup port config */ PORTA=0; PORTB=0; CMCON = 7; /* Comparator off, pins to I/O */ /* no interrupts for now */ PIE1=0; INTCON = 0; OPTION_REG=128; /* prescaler on Timer0, pull-ups on B disabled */ /* set port direction bits */ /* we use port A for our 2 motors */ TRISA=0; /* Setup USART pins */ TRISB=0; TRISB1=1; TRISB2=1; for (m=0; m++; m<2) { set_power(m,0); set_step(m,0); }; /* setup USART */ SYNC = 0; BRGH = 1; SPBRG = 25; RX9 = 0; SPEN = 1; TXIE = 0 ; RCIE = 0 ; TXEN = 1; CREN = 1; /* Setup timer1 */ TMR1ON=0; TMR1IF=0; T1CKPS0=0; T1CKPS1=0; T1OSCEN=0; TMR1CS=0; TMR1L=HZ_L; TMR1H=HZ_H; /* enable the timer, start interrupts */ TMR1IF=0; TMR1ON=1; TMR1IE=1; /* set variables */ /* main loop, wait for input, process, control motor and send responses */ GIE=1; PEIE = 1; while(1) { ClrWdt(); // if (m0_phase == 0 ) { // work_dir++; if (work_dir > 1) {work_dir = 0;}; // move(0,120,work_dir); // }; /* first process any incoming data */ if (RCIF) { work_char = RCREG ; switch(rx_phase) { case(0): if (work_char == 'x' ) { rx_motor=0 ; rx_phase++;} else if (work_char == 'y' ) {rx_motor=1; rx_phase++;}; break; case(1): /* direction */ if (work_char == '+' ) { work_dir=0 ; rx_phase++;} else if (work_char == '-' ) {work_dir=1; rx_phase++;} else if (work_char == 'a' ) {work_dir=2; rx_phase++;} else if (work_char == 'b' ) {work_dir=3; rx_phase++;} else if (work_char == 'c' ) {work_dir=4; rx_phase++;} else if (work_char == 'd' ) {work_dir=5; rx_phase++;} else rx_phase = 0; break; case(2): work_count=0; rx_phase++; case(3): if (work_char == 13 || work_char == 10 || work_char == ',' ) { if (work_dir > 1 ) { varset(rx_motor,work_count,work_dir); } else { move(rx_motor,work_count,work_dir); }; work_count=0; rx_phase=0; } else if (work_char >= '0' && work_char <= '9' ) { work_count = (work_count * 10 ) + (work_char - '0'); } else { /* invalid character */ rx_phase = 0 ; }; break; }; }; /* do we want to send anything */ /* first, ok to send... */ if (TXIF) { switch (tx_phase) { case(0): /* see if anything is pending */ if (m0_move== 1 ) { m0_move = 0; /* send xgo\n */ tx_phase = 1; break; }; if (m0_move== 2 ) { m0_move = 0; /* send xok\n */ tx_phase = 5; break; }; if (m1_move== 1 ) { m1_move = 0; /* send ygo\n */ tx_phase = 9; break; }; if (m1_move== 2 ) { m1_move = 0; /* send yok\n */ tx_phase = 10; break; }; // tx_phase=0; break; case(1): TXREG='x'; tx_phase++; break; case(2): TXREG='g'; tx_phase++; break; case(3): TXREG='o'; tx_phase++; break; case(4): TXREG=10; tx_phase=0; break; case(5): TXREG='x'; tx_phase++; break; case(6): TXREG='o'; tx_phase++; break; case(7): TXREG='k'; tx_phase++; break; case(8): TXREG=10; tx_phase=0; break; case(9): TXREG='y'; tx_phase=2; break; case(10): TXREG='y'; tx_phase=6; break; case(11): TXREG='.'; tx_phase=0; break; }; }; }; }