#include <pic.h>
#include "mxapi.h"
#define TX_START 0xFF
#define TX_ESC 0xFE
#define ESC1 0b10000000
#define ESC2 0b01000000
#define TX_LT 0x01
#define TX_AX 0x02
#define TX_AS 0x03
#define TX_GZ 0x04
#define TX_AE 0x05
#define TX_ML 0x06
#define TX_MR 0x07
#define AX_OFFSET 512
#define AS_OFFSET 512
#define GZ_OFFSET 522
#define KP 0.4 // proportional
#define KD 0.5 // derivative
#define KS 4.0 // steering
#define FORWARD 1
#define REVERSE 0
void interrupt segwayctl() {
if (TMR1IF) {
TMR1H = 55535 >> 8;
TMR1L = 55535 & 0xFF;
RC1 = RC2 = 1;
TMR1IF = 0;
}
if (CCP1IF) {
RC1 = 0;
CCP1IF = 0;
}
if (CCP2IF) {
RC2 = 0;
CCP2IF = 0;
}
}
void tx(unsigned char addr, unsigned char byte1, unsigned char byte2) {
usart_write(TX_START);
if (byte1 == TX_START) {
usart_write(TX_ESC);
addr |= ESC1;
} else {
usart_write(byte1);
}
if (byte2 == TX_START) {
usart_write(TX_ESC);
addr |= ESC2;
} else {
usart_write(byte2);
}
usart_write(addr);
}
void main() {
signed int lmotor = 512, rmotor = 512;
signed int speed_offset = 0;
signed int turn = 0;
unsigned char tx_i = 1;
unsigned char dtmr;
unsigned char direction = FORWARD;
unsigned char rider;
signed int ax_adc, as_adc, gz_adc;
signed int ax_deg, as_deg, gz_vel;
float angle = 0, motor = 0;
GIE = PEIE = CCP1IE = CCP2IE = TMR1IE = 1;
T1CON = 1;
PR2 = 0xFF;
CCP1CON = CCP2CON = 0b1010;
TRISC1 = TRISC2 = 0;
TRISB1 = 1;
RBPU = 0;
T0CS = PSA = PS0 = 0;
PS2 = PS1 = 1;
usart_init(19200);
adc_init(ALL_ANALOG);
CCPR1H = (56523 + 512) >> 8;
CCPR1L = (56523 + 512) & 0xFF;
CCPR2H = (56523 + 512) >> 8;
CCPR2L = (56523 + 512) & 0xFF;
delay_ms(3000);
if(RB1 == 1)
{ while(usart_read() != TX_START); rider = usart_read();
}
while (1) {
dtmr = TMR0;
TMR0 = 0x00;
switch(tx_i) {
case(TX_LT): { tx(TX_LT, rider, dtmr); break;}
case(TX_AX): { tx(TX_AX, ax_adc >> 8, ax_adc & 0xFF); break; }
case(TX_AS): { tx(TX_AS, as_adc >> 8, as_adc & 0xFF); break; }
case(TX_GZ): { tx(TX_GZ, gz_adc >> 8, gz_adc & 0xFF); break; }
case(TX_AE): { tx(TX_AE, ((signed int)angle + 512) >> 8, ((signed int)angle + 512) & 0xFF); break; }
case(TX_ML): { tx(TX_ML, lmotor >> 8, lmotor & 0xFF); break; }
case(TX_MR): { tx(TX_MR, rmotor >> 8, rmotor & 0xFF); tx_i = 0; break; }
}
tx_i++;
ax_adc = adc_read(0);
gz_adc = adc_read(1);
as_adc = adc_read(2);
ax_deg = (ax_adc - AX_OFFSET) * 14 >> 5;
ax_deg += speed_offset;
as_deg = (as_adc - AS_OFFSET) * 14 >> 5;
gz_vel = (gz_adc - GZ_OFFSET) * 11 >> 5;
angle = 0.97 * (angle + (float)gz_vel * (float)dtmr * 0.000128);
angle += 0.03 * ((float)ax_deg);
motor += ((KP * angle) + (KD * (float)gz_vel));
if (motor <= -511) { motor = -511; }
else if (motor >= 511) { motor = 511; }
speed_offset = (int)(motor * 0.025);
lmotor = rmotor = 511 + (int)motor;
turn = (int)((float)as_deg * KS);
lmotor += turn;
rmotor -= turn;
if (lmotor < 547 && lmotor > 477 && direction == FORWARD) { lmotor = 547; }
else if (rmotor < 547 && rmotor > 477 && direction == REVERSE) { rmotor = 477; }
if (lmotor <= 547) { direction = FORWARD; }
else if (motor >= 466) { direction = REVERSE; }
if (lmotor > 1022) { lmotor = 1022; }
else if (lmotor < 0) { lmotor = 0; }
if (rmotor > 1022) { rmotor = 1022; }
else if (rmotor < 0) { rmotor = 0; }
if (0 == 1) {
rmotor = lmotor = 512;
motor = 0;
}
CCPR1H = (56523 + lmotor) >> 8;
CCPR1L = (56523 + lmotor) & 0xFF;
CCPR2H = (56523 + rmotor) >> 8;
CCPR2L = (56523 + rmotor) & 0xFF;
}
}