Songs and driving scripts are now stored in and read from PROGMEM. This means we can use large scripts (for calibration or as consistent cleaning routes) without running out of memory.
//Starwars' Imperial March
const uint8_t imperialMarch[] PROGMEM = {
N_A4, 32, N_A4, 32, N_A4, 32, N_F4, 23, N_C5, 10, N_A4, 32, N_F4, 23, N_C5, 10, N_A4, 42, 0 , 32, N_E5, 32, N_E5, 32, N_E5, 32, N_F5, 23, N_C5, 10, N_G4S, 32,
N_F4, 23, N_C5, 10, N_A4, 42, 0 , 32, N_A5, 32, N_A4, 19, N_A4, 10, N_A5, 32, N_G5S, 21, N_G5, 11, N_F5S, 8, N_F5, 8, N_F5S, 16, 0 , 21, N_A4S, 16, N_D5S, 32,
N_D5, 21, N_C5S, 11, N_C5, 8, N_B4, 8, N_C5, 16, 0 , 23, N_F4, 16, N_G4S, 32, N_F4, 23, N_A4, 8, N_C5, 32, N_A4, 24, N_C5, 8, N_E5, 42, 0 , 32, N_A5, 32,
N_A4, 19, N_A4, 10, N_A5, 32, N_G5S, 21, N_G5, 11, N_F4S, 8, N_F5, 8, N_F4S, 16, 0 , 21, N_A4S, 16, N_D5S, 32, N_D5, 21, N_C5S, 11, N_C5, 8, N_B4, 8, N_C5, 16,
0 , 23, N_F4, 16, N_G4S, 32, N_F4, 24, N_C5, 8, N_A4, 32, N_F4, 24, N_C5, 8, N_A4, 42, 0 ,42
};
//macGyver theme song!
const uint8_t macGyver[] PROGMEM = {
N_B3, 16, N_E4, 16, N_A4, 16, N_B4, 16, N_A4, 16, N_B3, 16, N_E4, 16, N_B3, 16, 0 , 16, N_E4, 16, N_A4, 16, N_B4, 16, N_A4, 16, N_E4, 16, N_B3, 16, N_E4, 16,
0 , 16, N_E4, 16, N_A4, 16, N_B4, 16, N_A4, 16, N_B3, 16, N_E4, 16, N_B3, 32, 0 , 16, N_A4, 16, N_D5, 16, N_C5, 16, N_D5, 16, N_C5, 16, N_B4, 16, N_A4, 16,
N_B4, 48, N_A4, 76, 0 , 4, N_A4, 48, N_G4, 76, 0 , 4, N_B4, 14, 0 , 2, N_B4, 48, N_A4, 76, 0 , 4, N_A4, 48, N_G4, 32, N_A4, 72, 0 , 8, N_C5, 12,
0 , 2, N_C5, 12, 0 , 2, N_C5, 12, 0 , 2, N_C5, 12, 0 , 2, N_C5, 12, 0 , 2, N_C5, 12, 0 , 2, N_B4, 64, N_F4S, 16, N_A4, 32, N_G4, 80, N_C5, 14,
0, 2, N_C5, 32, N_B4, 32, N_C5, 16, N_B4, 16, N_A4, 16, N_G4, 16, N_E5, 32, N_A4, 64, N_C5, 14, 0 , 2, N_C5, 80, N_F4S, 16, N_A4, 32, N_G4, 76, N_C5, 14,
0, 2, N_C5, 32, N_B4, 32, N_C5, 16, N_B4, 16, N_G4, 16, N_E5, 32, N_A4, 64, N_B4, 64, N_C5, 16, N_B4, 16, N_A4, 16, N_C5, 32, N_B4, 16, N_A4, 16, N_D5, 32,
N_C5, 16, N_B4, 16, N_D5, 32, N_C5, 16, N_B4, 16, N_E5, 32, N_D5, 16, N_E5, 16, N_F5S,32, N_B4, 32, N_G5S, 48,N_F5S, 32, N_F5, 32, N_B4, 32, N_G5, 16, N_E5, 16,
N_B4, 16, N_F5S, 16,N_D5, 16, N_A4, 16, N_E5, 16, N_C5, 16, N_G4, 16, N_D5, 16, N_B4, 16, N_G4, 16, N_C5, 16, N_E4, 16, N_B4, 16, N_D4, 16, N_C5, 16, N_B4, 16,
N_A4, 16, N_G4, 16, N_A4S, 32,N_A4, 32, N_G5, 16, N_G4, 16, N_D5, 16, N_G4, 16, N_D5S, 16,N_D4S, 16, N_A4S, 16,N_A4, 16, N_G4, 16, N_G3, 16, N_D4, 16, N_G3, 16,
N_D4S, 16,N_G3, 16, N_A3S, 16,N_A3, 16, N_G3, 14, 0 , 2, N_G3, 14, 0 , 2, N_G3, 14,0 , 2, N_G3, 14, 0 , 2, N_G3, 14, 0 , 2, N_G3, 14, 0 , 2,
N_G3, 14, 0 , 2
};const uint8_t Square[] PROGMEM = {
RMDriveF, 20, //50cm
RMTurnL, 64, //quarter turn L
RMDriveF, 20, //50cm
RMTurnL, 64, //quarter turn L
RMDriveF, 20, //50cm
RMTurnL, 64, //quarter turn L
RMDriveF, 20, //50cm
RMTurnL, 64, //quarter turn L
RMDriveF, 20, //50cm
RMTurnR, 64, //quarter turn R
RMDriveF, 20, //50cm
RMTurnR, 64, //quarter turn R
RMDriveF, 20, //50cm
RMTurnR, 64, //quarter turn R
RMDriveF, 20, //50cm
RMTurnR, 64, //quarter turn R
RMDriveF, 20, //50cm
RMHalt //Stop
};
const uint8_t Empty[] PROGMEM = {
//RMDriveRawBL, 50, 50, 32, //Velocity: reverse 150, Arc: Left 500mm, Time 32*128ms=4sec
RMDriveR, 40,
RMTurnL, 64,
RMDriveF, 16,
RMTurnL, 128,
RMHalt
};
const uint8_t CallibrationRun[] PROGMEM = {
//RMDriveRawBL, 50, 50, 32, //Velocity: reverse 150, Arc: Left 500mm, Time 32*128ms=4sec
RMDriveR, 40,
RMTurnL, 128,
RMTurnL, 128,
RMTurnR, 128,
RMTurnR, 128,
RMDriveF, 16,
RMHalt
};With snippets..
const uint8_t *p_songPointer;
int p_songNumberOfBytes;
const uint8_t *p_scriptPointer;
unsigned long p_undockedTimer;
void playScript(const uint8_t *script);
void playMusic(const uint8_t *song, size_t songNumberOfBytes);
void Roomba632::playScript(const uint8_t *script){
//memcpy(script,script,sizeof(script));
p_scriptPointer = script;
p_startScriptFlag = true;
}
void Roomba632::playMusic(const uint8_t *song, size_t songNumberOfBytes){
//set music to be played
p_songPointer = song;
p_songNumberOfBytes = songNumberOfBytes;
p_playMusicFlag = true;
}
static int songPointerIndex;
static uint8_t maxIndex, i;
static int musicState = musicInit;
static unsigned long commandTimerMusic, musicTimer, songTime;
switch (musicState){
case musicInit:
songPointerIndex = 0;
musicState = musicWriteSongHeader;
commandTimerMusic = millis();
break;
case musicWriteSongHeader:
if ((millis() - commandTimerMusic) > COMMANDTIMEOUT){
Serial.write(OCSong);
Serial.write(1);
songTime = 0;
if ((p_songNumberOfBytes-songPointerIndex)<MAXSONGLENGTH){
maxIndex = (p_songNumberOfBytes-songPointerIndex);
}
else{
maxIndex = MAXSONGLENGTH;
}
Serial.write(maxIndex/2); //number of notes
musicState = musicWriteNotes;
i = 0;
commandTimerMusic = millis();
}
break;
case musicWriteNotes:
if ((millis() - commandTimerMusic) > COMMANDTIMEOUT){
if(i < maxIndex){
Serial.write(pgm_read_byte(p_songPointer + songPointerIndex));
if(songPointerIndex % 2 != 0){
songTime += pgm_read_byte(p_songPointer + songPointerIndex);
if (pgm_read_byte(p_songPointer + songPointerIndex) != 0){
songTime -= 2;
}
}
songPointerIndex++;
i++;
}
else{
musicState = musicStartSong;
}
commandTimerMusic = millis();
}
break;
..
int Roomba632::ScriptHandler(){
int16_t velocity, radius;
uint8_t scriptDistance, scriptAngle, scriptTime;
static uint8_t scriptRepeat;
static int scriptState = RMIdle, p_programCounter; //program counter for scripts;
static unsigned long scriptTimer, waitingTime;
switch (scriptState){
case RMIdle: //0
if (p_startScriptFlag){
p_startScriptFlag = false;
scriptState = RMStart;
}
break;
case RMStart: //1
if(OImode == Off){
Serial.write(OCstart);
OImode = Passive;
scriptState = RMStarting;
}
else{
p_programCounter= 0; //Reset script
scriptState = pgm_read_byte(p_scriptPointer + p_programCounter);
}
scriptTimer = millis();
break;
case RMStarting://2
if ((millis() - scriptTimer) > COMMANDSTARTTIMEOUT){
if (OImode < Safe){
Serial.write(OCSafemode);
OImode = Safe;
}
p_programCounter= 0; //Reset script
scriptState = pgm_read_byte(p_scriptPointer + p_programCounter);
scriptTimer = millis();
}
break;
case RMHalt: //3 scriptable
if ((millis() - scriptTimer) > COMMANDMODETIMEOUT){
Serial.write(OCStop);
OImode = Off;
scriptTimer = millis();
scriptState = RMHalting;
}
break;
case RMHalting: //4
if((millis() - scriptTimer) > COMMANDSTARTTIMEOUT){
p_programCounter = 0;
scriptState = RMIdle;
}
break;
case RMDriveF: //5 scriptable verb + noun
if ((millis() - scriptTimer) > COMMANDMODETIMEOUT){
scriptDistance = pgm_read_byte(p_scriptPointer + p_programCounter +1); //Distance in steps of 25mm (gives maximum of 6.375m)
waitingTime = scriptDistance * DISTANCESCALAR;
velocity = 250; //mm/s
radius = 32767; //Drive straight
SendDriveCommand(velocity, radius);
scriptTimer = millis();
scriptState = RMDrivingF;
}
break;
case RMDrivingF://6
if((millis() - scriptTimer) > waitingTime){
p_programCounter = p_programCounter + 2;
scriptState = pgm_read_byte(p_scriptPointer + p_programCounter);
scriptTimer = millis();
}
break;*less limited
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.