I haven’t seen any threads about copycat in a while, so I figure I’ll share what I know. My team used a simplified version of copycat for the past two years as a backup to the code we couldn’t get working. It’s quite simple.
The idea is that you push a button in user control mode, then it writes to EEPROM the values you send to your motors. In autonomous mode, you play back the recording and that’s your autonomous mode.
put this in your user_routines.c()
void storemotors(void)
{
static char lr = 0;
if (lr==0) //alternate writing lmotor & rmotor
{
writeEE(address, lmotor); //writes the motor value to EEPROM
lr=1;
}else
{
writeEE(address, rmotor);
lr=0;
}//endif
address++; //increments address
}//end storemotors
char readEE(unsigned short address) {
// Load address into address register
EEADRH = ((address>>8)&0x03); //Bits 2-7 are masked off since EEPROM is only 1KB
EEADR =(address&0xFF);
//Configuration as per manual
EECON1bits.EEPGD =0;
EECON1bits.CFGS =0;
EECON1bits.RD =1;
return EEDATA;
}
void writeEE(unsigned short address, char data)
{
EEADRH = ((address>>8)&0x03);
EEADR =(address&0xFF);
EEDATA = data;
//Configuration as per manual
EECON1bits.EEPGD =0;
EECON1bits.CFGS =0;
EECON1bits.WREN =1;
INTCONbits.GIE = 0;
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1;
INTCONbits.GIE = 1;
EECON1bits.WREN = 0;
}
put this in your user_routines_fast()
void readmotors(void)
{
static char lr = 0;
if (lr == 0)
{
lmotor = readEE(address2);
lr = 1;
}else
{
rmotor = readEE(address2);
lr=0;
}//endif
address2++;
}//end readmotors
address and address2 are unsigned shorts defined in user_routines.c and _fast.c respectively. lmotor is the pwm you used for your left motor and rmotor is the address you used for your right motor.
you can alias lmotor and rmotor like this:
#define lmotor pwm01
#define rmotor pwm02
that should save you some cutting and pasting.
you call storemotors() so long as a certain button, like p1_sw_top, is pushed. That way, as long as the button is pushed, you’re recording the data you send to the motors. call storemotors() only once you’re done processing data and are ready to send it to the pwms.
like this:
if (writebutton && (address <= 1023)) {storemotors();}
//stores data in EEPROM for recall in auto mode
you call readmotors() in user_autonomous_code(). It reads out data from the EEPROM directly into the motors.
like this:
if (address2 <= 1023) {readmotors();} //reads data from EEPROM to motors
else {lmotor = rmotor = 127;}
that’s it. simple. The only problem you might run into is that it takes a while to write to the EEPROM. If you try to write two bits of data right after the other, it won’t write the second bit. This is why I only write one motor per cycle. It definitely took me a while to figure that one out.
This is a really simplified version. It can only record one autonomous mode. The 1023 bytes of space should definitely allow you fifteen seconds of recording time. If not, you can always call storemotors and readmotors every other loop. My goal here is to help you understand copycat, not to provide you with the most function.
this code has not been tested on the new compiler, so if there’s a big problem please tell me.
Please post if you have questions! If you have better versions of copycat please share, and explain too!