//Zero2.ino char thisrobot[] ="Zero2 "; char thisprog[] ="Zero2"; /* Uno Sketch uses 14720 bytes (45%) of program storage space. Maximum is 32256 bytes. Global variables use 580 bytes (28%) of dynamic memory, leaving 1468 bytes for local variables. Maximum is 2048 bytes. set Serial terminal to 9600 baud Note - The Arduino Serial Monitor can't send [Esc]. If another Terminal is used which can send [Esc] then at GetCcmnd() this will be printed, which may print as a symbol or the Terminal may change it to "." ============================================================ History ------- 08 Jan 2019 - added copy to help 26 Jun 2017 - corrected Rdy from D7 to D6 (issue A PCB hung) 07 Jun 2017 - added [Z][digits] to send a byte to Zero2 added [T][digits] to Talk, send a phoneme(SP0256) byte to Zero2 added [S][digits] to Sound, send a sound(76489) byte to Zero2 25 May 2017 - program finished ============================================================ Zero2 ------- The arduino connects to the PC with the standard USB lead and connects to Zero2 using SoftwareSerial on pins 10(Rx),11(Tx), Rx and Tx are inverted to RS232 format using two BC 549 transistors with 1k pull-ups to 5v and 10k base resistors to incoming signals. Zero2's 12v motor supply is from the Aduino's Vin and the and 5v logic supply is from the Arduino's 5v. The 12v motor power is controlled by a relay driven by a BC549 on pin 8 which also lights an LED so I can see whether power is on. Umbilical - 1 - 0v,Rx,Tx,5v,0v,12v - 6 Write to Z2 - xx,A2,A1,A0,D3,D2,D1,D0 Read from Z2 - xx,Rdy,D5,D4,D3,D2,D1,D0 WRITE Address 0 - left motor - D3,D2 right motor - D1,D0 - [1,0,2,3]=forwards Address 1 - pen motor - D1,D0 [1,0,2,3]=clockwise Address 2 - hmi - Hh,Hl,iL,iR - 1=on Address 3 - speech low nibble Address 4 - speech/sound high nibble - write high nibble then low nibble Address 5 - sound low nibble READ Address 0 - lineSensor - D2,D1,D0 D2 left, D0 right Stepper motors - drive/pen - unipolar (5 wires) Impex ID31 (1983) 9904-112-31004, nominal 12v 7.5deg, 48 steps/rev, 65 ohm, 175ma/coil, max working 20mNm, holding 28mNm, 240step/s The 9v supply is turned off automatically when stopped to reduce power, p0 disables, p1 enables The LEDs run from 5v through a ULN2003. When the 9v supply is off after a '.' cmnd the LEDs light through the flyback diodes in the ULN2003 to 0v. ============================================================ Bugs - ============================================================ To do next - ============================================================= improvements? ------------- C - command, Clf line find, Cl follow line for distance '!' - use page3 Reacts for the next record, load, replay, or print [S][#byte] - say phoneme modify to Dan Michaels scheme [d][s] - distance step ?!!! ReActs ====== Reactions stored in EEPROM page 3 as 8 slots of 32 bytes, Reactions can have the same commands as Acts and ended with ".". When a sensor test is made in an Act and something is detected then the relevant Reaction is played then the Act continues. ============================================================= Primary commands used 012345678 ?$#.() BDFLPRUV abcfhilmnprsw COMMANDS ======== [Esc],[Q] - stop, quit operations, go to command mode [.] - stop, end current operation - recording, playing, input [(] - start of a Do, will show its location in EEPROM when played, eg (=263 If a jump to another Act is made from within a Do then the Do location will be shown eg (@267) and when returning the return location will be shown, eg (267) A jump to an Act from a Do will on . continue in the Do If a jump is made to an Act which contains another Do then that Do will become the current Do and the old Do will not be returned to [)] - end of a Do, will show its location in EEPROM when played, eg )=285 [0] - use page0 for the next cmnd or Act number [a][1-8] - Act to autorun on power on [1-8] Play act, or the Act to record, copy, load etc [V] - turn on 9v power [p][1] - autoPower on, automatically disconnect 9v when stopped [p][0] - autoPower off, 9v power always on [F]{digits}[,] - Forwards - if no digits then 1 [B]{digits}[,] - Backwards - if no digits then 1 [R]{digits}[,] - turn Right - if no digits then 1 - 1 mm is 1 degree [L]{digits}[,] - turn Left - if no digits then 1 - 1 mm is 1 degree [D] - Pen down [U] - Pen up [P] - initialise Pen [f][l]{digits}[,] - forward left - if no digits then 1 - 1 mm is 1/2 degree [f][r]{digits}[,] - forward right - if no digits then 1 - 1 mm is 1/2 degree [b][l]{digits}[,] - backward left - if no digits then 1 - 1 mm is 1/2 degree [b][r]{digits}[,] - backward right - if no digits then 1 - 1 mm is 1/2 degree [m][digits][,] - actual degrees for 360 degrees [w][0-9,0] - wait seconds, 0=10 [n][0-9,0] - nap tenths second, 0=10 [s][1-9] - steptime/2 [+] - speed-up, steptime -=1 >=1 [-] - speed-down, steptime +=1 [u] - speed-up, steptime -=1 >=stepmin [d] - speed-down, steptime *=2 [m] - set speed-max for speed-up to current speed [s] - save speed [i][o] - Indicators off [r] - Indicator R on [l] - Indicator L on [i][0] - Indicators off [1] - Indicator R on [2] - Indicator L on [3] - Indicators on [h][o] - horn off [h] - horn high tone [l] - horn low tone [n] - horn (both tones) [h][0] - horn off [1] - horn low [2] - horn high [3] - horns on [Z][digits][,] - send a byte to robot [S][digits][,] - sound 76489 [T][digits][,] - talk say phoneme [$][l] - return line status //[$][f] - return feeler status //[$][g] - return ground status [r][0 1-8] - record act, 0 use page0 [l][0 1-8] - load act, 0 use page0 [c][0 1-8][0 1-8] - copy Act to Act, 0 use page0 [?][?] - print acts [a] - '??' prints all acts [0] - prints acts 0, and changes '??' to just print current page - (for QL zero2 program) [b] - print behaviour - thisprog,autoAct,f_autoPower,steptime,stepmin,stepScale360 [d] - dump all acts to PC without descriptions, suitable for loading [h] - print help Notes [(] - will show its location in EEPRO< when played eg (=263 [)] - will show its location in EEPRO< when played eg )=285 If a call to another Act is made from within Mind then the location to return to will be shown, eg (267) Acts by default are stored in page 1, 0 changes to page 0 for the next command only. Page 0 ia EEPROM bytes 0-255, Page 1 is EEPROM bytes 256-511 etc. ============================================================= //== SECTIONS =============================================== //== NEW //== CHANGED //== INCLUDES // EEPROM.h - the Arduino EEPROM library //== PINS //== VARIABLES and CONSTANTS //== SETUP //== LOOP //== USER ROUTINES // Experiment() //until Quit // Xplore() //Wander() until Quit //== FUNCTIONS // GetCcmnd() //reads Serial or playing Act until Ccmnd != 0, prints Ccmnd // RecordCcmnd() // waitSecs() //read delay time from Act and wait // waitTenthsSecs() //read delay time from Act and wait //// PrintReActs() //// printReAct() // get1char() // getnum() // DumpActs() //Dump Acts, Print without names and length // loadAct() // copyAct() // Ccmnd <- PlayAct() // PrintAllActs() // printAct() // Act <- getAct() //called when recording, loading, printing and copying Acts // setEEPROMindexes(char Act) // changes EEPROMindex, ActEnd // badkey() // indicate invalid key //// WhiskerReact() // read Whisker sensors and avoid holes (if any) using avoidObstacles() behaviour rules //// BeardReact() // read Beard sensors and avoid obstacles (if any) using avoidHoles() behaviour rules // printHelp() //TAB FILES // //acts23.ino // // ACTS - WanderSteps(steps), Wander() // // RightStep(steps), LeftStep(steps) // // rock(repeats), shuffle(repeats) // hmi.ino // HORN - // LEDs - // movement.ino // MOVEMENT - Forward(), Backward(), turnRight(), turnLeft() // ForwardLeft(), ForwardRight() // BackwardLeft(), BackwardRight() // PenUp(), PenDown() // //system45.ino // // SYSTEM - disable_walking(), enable_walking(), toggle_f_walking(), // // initialiseEEPROM(), initialiseEEPROMbehaviours() //=========================================================== */ /*== NEW ==================================================== */ /*== CHANGED ================================================ */ //== INCLUDES =============================================== #include // to read and write internal EEPROM // EEPROM.update(address,bytevalue) // bytevalue =EEPROM.read(address) #include //== PINS =================================================== //pin0 Rx when connected to a SparkFun RS232 module can't have // a 1k protection resistor as doesn't then receive. //pin1 Tx //pin2 //pin3 SoftwareSerial Zserial(10, 11); // RX, TX const byte relayPin =8; //== VARIABLES and CONSTANTS ================================ boolean f_recording =false; //recording an Act boolean f_recordC =false; //record current Command boolean f_play =false; //Play current Act boolean f_react =false; //in a ReAct - set if a React is initiated. boolean f_doDefault =true; //true for the first loop boolean f_runDefault =false; //run Default when nothing else to do, not used in this program, boolean f_inDo =false; boolean f_printAll =true; //'??' prints all acts, false '??' prints current page boolean f_autoPower =true; //auto power down when stopped boolean f_penStateUp =true; //boolean f_bG =0; //auto sense Ground control //boolean f_bW =0; //auto sense Whiskers control //boolean f_bU =0; //auto sense Ultrasonic control const byte NL =10; //NewLine value const byte LF =10; //LineFeed value const byte CR =13; //Carriage Return value const byte Esc =27; //Esc key value char Act; //current Act as '1' - '8' char autoAct ='0'; //act to run on reset, poweron byte actIndex =0; //current Act number, set to default int EEPROMindex =-1; //index to moves in an Act in EEPROM, -1 => nothing to continue with #> //int ReactAt; //copy of EEPROMindex at React int ActEnd; //end address of current recording Act in EEPROM int moves =0; //current move char Ccmnd =0; //current Character command, default null command char stackCcmnd =0; byte epage; //the Act page for the current Act, default page =1 for Acts 1-8 and page =0 for 01-08 byte slotbase; //working slotbase long numValue =0; //temporary value in getnum() //needs to be long because of scale sums String numString =""; //temporary string in getnum() int steptime =20; //mSec between motor steps 2=fast int defaultsteptime =6; int stepmin =2; //max speed int msteps; //used in move routines int pensteptime =15; //delay msecs between pen steps byte Zaddr; byte Zdata; byte hornState =0; //0 =off byte LEDsState =0; //0 =off int DoAt =0; //EEPROM address always >1 since must be preceded by {x where x is act value '1' - '8' const byte mCode[4] ={1,0,2,3}; //1->0->2->3-> forwards byte RmotorAt =0; //array index byte LmotorAt =0; //array index int steps; //motor steps to move int stepScale360; const int stepScale360default =360; byte Zsense; //genersl sense retun; byte Zrdy; //Z Rdy D7 retun const byte EautoAct =1023; //address of copy in EEPROM, last available byte const byte EstepScale360hi =1022; //address of copy in EEPROM const byte EstepScale360lo =1021; //address of copy in EEPROM const byte Esteptime =1020; //address of copy in EEPROM //== SETUP ================================================== void setup() { pinMode(relayPin, OUTPUT); digitalWrite(relayPin, LOW); //turn off motor power Serial.begin(9600); // to communicate with Serial Monitor Serial.println(); Serial.println(thisprog); Zserial.begin(4800); // set the data rate for the SoftwareSerial port epage =1; //set to default page, Acts 1 - 8 autoAct =EEPROM.read(EautoAct); if (autoAct<'0' || autoAct>'8') { autoAct ='0'; EEPROM.update(EautoAct,autoAct); } //maybe uninitialised stepScale360 =(EEPROM.read(EstepScale360hi) *256) +EEPROM.read(EstepScale360lo); if (stepScale360 >400 || stepScale360 <0 ) { stepScale360 =stepScale360default; } //400 is some higher number, probably uninitialised EEPROM steptime =EEPROM.read(Esteptime); if (steptime<0 || steptime>20 ) {steptime =6; EEPROM.update(Esteptime,steptime); } } //== LOOP =================================================== void loop() { f_recordC =true; // record Command, default =true if (!f_play && f_autoPower) { digitalWrite(relayPin,LOW); } if (f_doDefault) // true on the first loop { f_doDefault =false; // don't do it again Ccmnd =autoAct; if(Ccmnd=='0') { f_runDefault =false; Ccmnd ='.'; } // '0' -> no autorun, can't run it so do stop } else { if (stackCcmnd !=0) { Ccmnd =stackCcmnd; stackCcmnd =0; } else { Serial.print(">"); //ready prompt GetCcmnd(); } } DoCommand: if(Ccmnd==255 || Ccmnd==-1 ) Ccmnd ='.'; //uninitialised EEPROM value, don't play it, change to '.' switch (Ccmnd) { case LF: f_recordC =false; break; //ignore and don't record linefeed case CR: f_recordC =false; break; //ignore and don't record carriage return case ' ': break; //strip space case ',': break; //strip comma case 'Q': // fall through case Esc: f_react =false; f_inDo =false; DoAt =0; //[Esc] key, fall through to '.' case '.': if (f_recording) { EEPROM.update(EEPROMindex,'.'); } //terminated string f_recording =false; stackCcmnd =0; //if (f_react) // end of ReAct //{ f_react =false; EEPROMindex =ReactAt; // f_play =true; // break; //} if (DoAt !=0) { Serial.print("("); Serial.print(DoAt); Serial.print(")"); EEPROMindex =DoAt; DoAt =0; f_inDo =true; break; } f_play =false; // end of Act Serial.println(); f_autoPower =true; digitalWrite(relayPin,LOW); //if (f_runDefault) { f_doDefault =true; } // #< break; case '(': f_inDo =true; Serial.print("="); Serial.println(EEPROMindex-1); break; case ')': f_inDo =false; Serial.print("="); Serial.println(EEPROMindex-1); break; case 'V': f_autoPower =0; digitalWrite(relayPin,HIGH); break; case 'p': if (f_recording) { RecordCcmnd(); } //so 'p' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case '0': f_autoPower =true; break; case '1': f_autoPower =false; break; default: f_autoPower =true; Ccmnd ='1'; break; } // end switch break; // case 'X': // if recording record 'X' otherwise do Xplore() until 'Q' or reset // if (!f_recording) { Xplore(); } break; case 'E': // if recording record 'E' otherwise do Experiment() until 'Q' or reset if (!f_recording) { Experiment(); } break; // case '!': epage =3; break; //reset to 1 at the end of setEEPROMindexes(char Act) case '0': epage =0; break; //reset to 1 at the end of setEEPROMindexes(char Act) case '1': // fall through case '2': // fall through case '3': // fall through case '4': // fall through case '5': // fall through case '6': // fall through case '7': // fall through case '8': if (!f_recording) { if (f_inDo) { DoAt =EEPROMindex; Serial.print("(@"); Serial.print(DoAt); Serial.print(")"); f_inDo =false; //because we are jumping to another Act } f_play =true; Act =Ccmnd; setEEPROMindexes(Act); } break; case 'F': if (f_recording) { RecordCcmnd(); } //so 'F' is recorded GetNum(); steps =numValue *2 *stepScale360 /360; Forward(); break; case 'B': if (f_recording) { RecordCcmnd(); } //so 'B' is recorded GetNum(); steps =numValue *2 *stepScale360 /360; Backward(); break; case 'R': if (f_recording) { RecordCcmnd(); } //so 'R' is recorded GetNum(); steps =numValue *2 *stepScale360 /360; turnRight(); break; case 'L': if (f_recording) { RecordCcmnd(); } //so 'L' is recorded GetNum(); steps =numValue *2 *stepScale360 /360; turnLeft(); break; //Pen case 'U': PenUp(); f_penStateUp =true; break; case 'D': PenDown(); f_penStateUp =false; break; case 'P': PenInitialise(); break; //forwards - direction case 'f': if (f_recording) { RecordCcmnd(); } //so 'f' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case 'l': if (f_recording) { RecordCcmnd(); } //so 'l' is recorded GetNum(); steps =numValue *4; ForwardLeft(); break; case 'r': if (f_recording) { RecordCcmnd(); } //so 'r' is recorded GetNum(); steps =numValue *4; ForwardRight(); break; default: badkey(); Serial.println("bad key"); Ccmnd ='?'; //so if recording then '?' is recorded } // end switch break; //back - direction case 'b': if (f_recording) { RecordCcmnd(); } //so 'b' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case 'l': if (f_recording) { RecordCcmnd(); } //so 'l' is recorded GetNum(); steps =numValue *4; BackwardLeft(); break; case 'r': if (f_recording) { RecordCcmnd(); } //so 'r' is recorded GetNum(); steps =numValue *4; BackwardRight(); break; default: badkey(); Serial.println("bad key"); Ccmnd ='?'; //so if recording then '?' is recorded } // end switch break; //wait case 'w': if (f_recording) { RecordCcmnd(); } //so 'w' is recorded GetCcmnd(); //get parameter if ( !isDigit(Ccmnd) ) { badkey(); Serial.print("?1"); Ccmnd ='1'; } //1=default waitSecs(Ccmnd -'0'); //'0' is 10 break; // if recording Ccmnd will be recorded //nap case 'n': if (f_recording) { RecordCcmnd(); } //so 'n' is recorded GetCcmnd(); //get parameter if ( !isDigit(Ccmnd) ) { badkey(); Serial.print("?1"); Ccmnd ='1'; } //default waitTenthsSecs(Ccmnd -'0'); //'0' is 10 break; // if recording Ccmnd will be recorded //speed case 's': if (f_recording) { RecordCcmnd(); } //so 's' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case '1': // fall through case '2': // fall through case '3': // fall through case '4': // fall through case '5': // fall through case '6': // fall through case '7': // fall through case '8': // fall through case '9': steptime =(Ccmnd-'0') *2; break; // and if recording record Ccmnd case '+': steptime -=1; steptime =max(steptime,1); break; // and if recording record '+' case '-': steptime +=1; break; // and if recording record '-' case 'u': steptime -=1; steptime =max(steptime,stepmin); break; // and if recording record 'u' case 'd': steptime *=2; break; // and if recording record 'd' case 'm': stepmin =steptime; break; // and if recording record 'm' case 's': EEPROM.update(Esteptime,steptime); break; //save // and if recording record 's' default: steptime =defaultsteptime; break; } break; //horn case 'h': if (f_recording) { RecordCcmnd(); } //so 'h' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case 'h': hornhigh(); break; case 'l': hornlow(); break; case 'n': horns(); break; case 'o': hornoff(); break; case '0': hornoff(); break; case '1': hornlow(); break; case '2': hornhigh(); break; case '3': horns(); break; default: hornoff(); Ccmnd ='o'; Serial.print("?o"); break; } // end switch break; //indicators case 'i': if (f_recording) { RecordCcmnd(); } //so 'i' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case 'r': LEDRon(); break; case 'l': LEDLon(); break; case 'o': LEDsoff(); break; case '0': LEDsoff(); break; case '1': LEDRon(); break; case '2': LEDLon(); break; case '3': LEDson(); break; default: LEDsoff(); Ccmnd ='o'; Serial.print("?o"); break; } // end switch break; //send byte case 'Z': if (f_recording) { RecordCcmnd(); } //so 'Z' is recorded GetNum(); tellZ_byte(numValue); break; //talk phoneme(SP0256) case 'T': if (f_recording) { RecordCcmnd(); } //so 'T' is recorded GetNum(); tellZ_talk(numValue); break; //sound(76489) case 'S': if (f_recording) { RecordCcmnd(); } //so 'S' is recorded GetNum(); tellZ_sound(numValue); break; //$sense case '$': if (f_recording) { RecordCcmnd(); } //so '$' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case 'l': read_line(); break; // case 'f': return_feelers(); break; // case 'g': return_ground(); break; // default: badkey(); // Serial.println("bad key"); // Ccmnd ='?'; //so if recording then '?' is recorded } // end switch case $ break; //record case 'r': f_recordC =false; if (!f_recording) { getAct(); if(Ccmnd=='.') { break; } setEEPROMindexes(Act); f_recording =true; } break; //autoAct case 'a': if (f_recording) { RecordCcmnd(); } //so 'a' is recorded GetCcmnd(); //get parameter switch (Ccmnd) { case '0': // fall through case '1': // fall through case '2': // fall through case '3': // fall through case '4': // fall through case '5': // fall through case '6': // fall through case '7': // fall through case '8': autoAct =Ccmnd; EEPROM.update(EautoAct,autoAct); break; default: badkey(); Ccmnd='0'; break; } // end switch break; //load case 'l': f_recordC =false; if (!f_recording) { loadAct(); } break; //copy case 'c': f_recordC =false; if (!f_recording) { copyAct(); } break; //move - stepscale case 'm': if (f_recording) { RecordCcmnd(); } //so 'm' is recorded GetNum(); if (numValue<340 || numValue>380 ) { badkey(); Ccmnd='?'; break; } EEPROM.update(EstepScale360hi,stepScale360 /256); EEPROM.update(EstepScale360lo,stepScale360 &255); break; case '?': f_recordC =false; if (!f_recording) { GetCcmnd(); //get parameter switch (Ccmnd) { case 'h': printHelp(); break; // print instructions case 'b': printBehaviour(); break; case '1': // fall through case '2': // fall through case '3': // fall through case '4': // fall through case '5': // fall through case '6': // fall through case '7': // fall through case '8': Act =Ccmnd; printAct(); break; case 'a': f_printAll =true; break; case '0': f_printAll =false; PrintActs0(); break; case '?': PrintAllActs(); break; case 'd': DumpActs(); break; // case '!': PrintReActs(); break; default: badkey(); printHelp(); Ccmnd='?'; break; } // end switch } // end if break; // case 'W': WhiskerReact(); break; // case 'G': BeardReact(); break; default: f_recordC =false; //don't record bad key badkey(); Serial.println("bad key"); break; } // end switch Record: if (f_recording && f_recordC) { RecordCcmnd(); } } //== END {LOOP} ============================================= //== USER ROUTINES ========================================== void Experiment() //until Quit { while(true) { //put your own routine here e.g. steps =2; Forward(); /* delay(steptime); Zdata =5; Zserial.write(Zdata); delay(steptime); Zdata =0; Zserial.write(Zdata); delay(steptime); Zdata =10; Zserial.write(Zdata); delay(steptime); Zdata =15; Zserial.write(Zdata); //delay(500); */ if(Quit()) { break; } } // end while } //---------------------------- void Xplore() //Wander() until Quit { /*while(true) { Wander(); if(Quit()) { break; } } // end while*/ } //== FUNCTIONS ============================================== void GetCcmnd() //reads Serial or playing Act until Ccmnd != 0, prints Ccmnd { Ccmnd =0; while(Ccmnd==0) { if (f_recording) { while(!Serial.available()) {} //wait for Serial Ccmnd =Serial.read(); } else //if (!f_recording) { if (Serial.available()) { Ccmnd =Serial.read(); //over-ride if Serial, null ignored } else { if (f_play || f_react) { Ccmnd =PlayAct(); //get Act or React Ccmnd } } } //end if (!f_recording) } //end while Ccmnd==0 Serial.print(Ccmnd); } //---------------------------- void RecordCcmnd() { EEPROM.update(EEPROMindex,Ccmnd); EEPROMindex++; if (EEPROMindex>=ActEnd) { f_recording =false; EEPROM.update(ActEnd,'.'); badkey(); } //terminated string } //---------------------------- void waitSecs(byte cmnd) //read delay time from Act and wait { if ( cmnd==0 ) { cmnd =10; } delay(cmnd *1000); } //---------------------------- void waitTenthsSecs(byte cmnd) //read delay time from Act and wait { if ( cmnd==0 ) { cmnd =10; } delay(cmnd *100); } //---------------------------- /*void PrintReActs() { Serial.println(); Serial.print("W & G, 1 indicates object or hole sensed LR"); for(Act ='1'; Act<='8'; Act++) { epage =3; printReAct(); } Serial.println(); }*/ //---------------------------- /*void printReAct() { Serial.println(); Serial.print("ReAct"); Serial.print(Act); Serial.print(" "); switch (Act) { case '1': Serial.print("U<="); Serial.print(SonarAwareAt); Serial.print(" "); break; case '2': Serial.print("U<="); Serial.print(SonarTooNear); Serial.print(" "); break; case '3': Serial.print("W11"); Serial.print(" "); break; case '4': Serial.print("W10"); Serial.print(" "); break; case '5': Serial.print("W01"); Serial.print(" "); break; case '6': Serial.print("G11"); Serial.print(" "); break; case '7': Serial.print("G10"); Serial.print(" "); break; case '8': Serial.print("G01"); Serial.print(" "); break; } // end switch setEEPROMindexes(Act); Ccmnd =EEPROM.read(EEPROMindex++); // -1 (=255) is uninitialised EEPROM value while(Ccmnd !='.' && Ccmnd !=-1) { Serial.print(Ccmnd); moves++; Ccmnd =EEPROM.read(EEPROMindex++); } EEPROMindex -=1; //step back to end of record just in case playing Serial.print(". - "); Serial.print(moves); //there are moves which take more than 1 character Serial.print(" bytes"); //so the space taken in EEPROM is really bytes moves =0; }*/ //---------------------------- void get1char() //never called { Ccmnd =0; do{ if(Serial.available()) Ccmnd =Serial.read(); }while(Ccmnd==0); Serial.println(Ccmnd); } //---------------------------- void GetNum() { GetCcmnd(); if ( !isDigit(Ccmnd) ) { stackCcmnd =Ccmnd; numValue =1; } else { numString = ""; do { if (Ccmnd==CR) { break; } if (f_recording) { RecordCcmnd(); } //so digit is recorded if ( isDigit(Ccmnd) ) { numString +=Ccmnd; } else { stackCcmnd =Ccmnd; break; } GetCcmnd(); } while (true); numValue =numString.toInt(); numString = ""; } //Serial.print(numValue); } //---------------------------- void printBehaviour() { Serial.println(); Serial.println(thisprog); // so we know which program is running Serial.print(autoAct); Serial.println(" autoAct"); Serial.print(f_penStateUp); if (f_penStateUp) { Serial.println(" pen is UP"); } else { Serial.println(" pen is DOWN"); } //Serial.print(f_runDefault); Serial.println(" autorun"); Serial.print(steptime); Serial.println(" steptime =step cmnd *2"); Serial.print(stepmin); Serial.println(" min steptime"); Serial.print(stepScale360); Serial.println(" stepScale360"); Serial.print(f_autoPower); Serial.println(" auto 9v power down"); //disp_freeram(); } //---------------------------- void DumpActs() //Dump Acts, Acts0, ReActs. Print without names and length { for(Act ='1'; Act<='8'; Act++) { setEEPROMindexes(Act); Serial.println(); Ccmnd =EEPROM.read(EEPROMindex++); // -1 (=255) is uninitialised EEPROM value while(Ccmnd !='.' && Ccmnd !=-1) { Serial.print(Ccmnd); Ccmnd =EEPROM.read(EEPROMindex++); } } for(Act ='1'; Act<='8'; Act++) { epage =0; setEEPROMindexes(Act); Serial.println(); Ccmnd =EEPROM.read(EEPROMindex++); // -1 (=255) is uninitialised EEPROM value while(Ccmnd !='.' && Ccmnd !=-1) { Serial.print(Ccmnd); Ccmnd =EEPROM.read(EEPROMindex++); } } /* for(Act ='1'; Act<='8'; Act++) { epage =3; setEEPROMindexes(Act); Serial.println(); Ccmnd =EEPROM.read(EEPROMindex++); // -1 (=255) is uninitialised EEPROM value while(Ccmnd !='.' && Ccmnd !=-1) { Serial.print(Ccmnd); Ccmnd =EEPROM.read(EEPROMindex++); } }*/ Serial.println(); } //---------------------------- void loadAct() { getAct(); // Ccmnd ->'.' - Quit, // '0' - sets Act0 (or , '!' ReAct) page then gets Act // '1' - '8' - sets Act page'1' - '8', - if (Ccmnd!='.') { setEEPROMindexes(Act); while(true) { while(!Serial.available()) {} Ccmnd =Serial.read(); //wait for Serial if(Ccmnd=='.' || Ccmnd==Esc) { break; } EEPROM.update(EEPROMindex,Ccmnd); EEPROMindex++; if (EEPROMindex>=ActEnd) { badkey(); break; } //ActEnd =EEPROMindex +31; } EEPROM.update(EEPROMindex,'.'); //terminated string } } //---------------------------- void copyAct() { getAct(); if (Ccmnd!='.') { setEEPROMindexes(Act); int fromEEPROMindex =EEPROMindex; int fromActEnd =ActEnd; getAct(); if (Ccmnd!='.') { setEEPROMindexes(Act); for(byte i =0; i<=fromActEnd -fromEEPROMindex; i++) { EEPROM.update(EEPROMindex +i,EEPROM.read(fromEEPROMindex +i)); } } } } //---------------------------- char PlayAct() { char _Ccmnd =EEPROM.read(EEPROMindex++); return _Ccmnd; } //---------------------------- void PrintActs0() { for(Act ='1'; Act<='8'; Act++) { epage =0; printAct(); } Serial.println(); } //---------------------------- void PrintAllActs() { byte currentpage =epage; if (!f_printAll) { for(Act ='1'; Act<='8'; Act++) { epage =currentpage; printAct(); } Serial.println(); } else { for(Act ='1'; Act<='8'; Act++) { epage =1; printAct(); } Serial.println(); for(Act ='1'; Act<='8'; Act++) { epage =0; printAct(); } Serial.println(); } } //---------------------------- void printAct() { Serial.println(); Serial.print("Act"); if(epage==0) { Serial.print('0'); } //for logical page0 Acts Serial.print(Act); Serial.print(" "); setEEPROMindexes(Act); Ccmnd =EEPROM.read(EEPROMindex++); // -1 (=255) is uninitialised EEPROM value while(Ccmnd !='.' && Ccmnd !=-1) { Serial.print(Ccmnd); moves++; Ccmnd =EEPROM.read(EEPROMindex++); } EEPROMindex -=1; //step back to end of record just in case playing Serial.print(". - "); Serial.print(moves); Serial.print(" bytes"); moves =0; } //---------------------------- void getAct() //called when recording, loading, printing and copying Acts, Ccmnd ->'.', '1' - '8' { Ccmnd =0; do { if(Serial.available()) { Ccmnd =Serial.read(); switch (Ccmnd) { case Esc: Ccmnd ='.'; //[Esc] key, fall through to '.' case '.': Serial.print("!"); break; //quit, print ! //ready prompt // case '!': epage =3; Ccmnd =0; break; //do it again to read Act case '0': epage =0; Ccmnd =0; break; //do it again to read Act case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': Act =Ccmnd; break; default: badkey(); Serial.print(" enter Act or '.'"); Ccmnd =0; } //end case } //end if Serial } while(Ccmnd==0); } //---------------------------- void setEEPROMindexes(char Act) // set EEPROM pointers { actIndex =Act -'1'; // ASCII to numeric, Act 1 == actIndex 0 EEPROMindex =(256 *epage) +(actIndex*32); ActEnd =EEPROMindex +31; epage =1; //back to default page for next Act number } //---------------------------- void badkey() // indicate invalid key { horns(); LEDRon(); delay(100); LEDsoff(); LEDLon(); delay(100); LEDsoff(); hornoff(); } //---------------------------- /* void WhiskerReact() // "W" read Whisker sensors and avoid obstacles (if any) using avoidObstacles() behaviour rules { readWhiskers(); queryObstaclesLR(); reactObstaclesLR(); } //---------------------------- void BeardReact() // "G" Ground - read Beard sensors and avoid holes (if any) using avoidHoles() behaviour rules { readBeard(); queryEdgeLR(); reactHolesLR(); } */ //--------------------------- boolean Quit() //check for Quit { if( Serial.available() ) { Ccmnd =Serial.read(); } if( Ccmnd=='Q' || Ccmnd=='.' || Ccmnd==Esc || Ccmnd=='#') { return true; } else { return false; } } //---------------------------- //== HELP TEXT ============================================== void printHelp() { Serial.println(); Serial.println(F("[Q],[Esc] - stop all")); Serial.println(F("[.] - stop, quit current operation - recording, playing, input, 9v Power off")); Serial.println(F("[(] - start of Do")); Serial.println(F("[)] - end of Do")); Serial.println(F("[p][0] - autoPower, automatically disconnect 9v when stopped")); Serial.println(F("[p][1] - 9v power always on, autoPower off")); Serial.println(F("[V] - turn on 9v power, set autoPower off")); Serial.println(F("[0] - use page0 for the next Act or command")); Serial.println(F("[a][1-8] - Act to autorun on power on")); Serial.println(F("[1-8] Play act, or the Act to record, copy, load etc")); Serial.println(F("[F]{digits}[,] - Forwards - if no digits then 1")); Serial.println(F("[B]{digits}[,] - Backwards - if no digits then 1")); Serial.println(F("[R]{digits}[,] - turn Right - if no digits then 1")); Serial.println(F("[L]{digits}[,] - turn Left - if no digits then 1")); Serial.println(F("[m][digits][,] - scale degrees for 360")); Serial.println(F("[D] - Pen down")); Serial.println(F("[U] - Pen up")); Serial.println(F("[P] - initialise Pen")); Serial.println(F("[f][l]{digits}[,] - forward left - if no digits then 1")); Serial.println(F("[f][r]{digits}[,] - forward right - if no digits then 1")); Serial.println(F("[b][l]{digits}[,] - backward left - if no digits then 1")); Serial.println(F("[b][r]{digits}[,] - backward right - if no digits then 1")); Serial.println(F("[m][digits][,] - actual steps for 360 steps")); Serial.println(F("[w][0-9,0] - wait seconds, 0=10")); Serial.println(F("[n][0-9,0] - nap tenths second, 0=10")); Serial.println(F("[s][1-9] - speed, steptime =speed cmnd *2")); Serial.println(F(" [+] - speed-up, steptime -=1 >=1")); Serial.println(F(" [-] - speed-down, steptime +=1")); Serial.println(F(" [u] - speed-up, steptime -=1 >=stepmin")); Serial.println(F(" [d] - speed-down, steptime *=2")); Serial.println(F(" [m] - set speed-max for speed-up to current speed")); Serial.println(F(" [s] - save speed")); Serial.println(F("[h][o] - horn off")); Serial.println(F(" [l] - horn low tone")); Serial.println(F(" [h] - horn high tone")); Serial.println(F(" [n] - horn (both tones)")); Serial.println(F("[h][0] - horn off")); Serial.println(F(" [1] - horn low tone")); Serial.println(F(" [2] - horn high tone")); Serial.println(F(" [3] - horn (both tones)")); Serial.println(F("[i][o] - indicators off")); Serial.println(F(" [R] - indicator R")); Serial.println(F(" [L] - indicator L")); Serial.println(F(" [n] - indicators LR")); Serial.println(F("[i][0] - indicators off")); Serial.println(F(" [1] - indicator R")); Serial.println(F(" [2] - indicator L")); Serial.println(F(" [3] - indicators LR")); Serial.println(F("[Z][digits][,] - send byte [digits] to robot")); Serial.println(F("[T][digits][,] - Talk phoneme byte [digits]")); Serial.println(F("[S][digits][,] - Sound byte [digits]")); Serial.println(F("[$][l] - return line status")); //Serial.println(F("[$][f] - return feeler status")); //Serial.println(F("[$][g] - return ground status")); Serial.println(F("[r][0 1-8] - record act, 0 use page0")); Serial.println(F("[l][0 1-8] - load act, 0 use page0")); Serial.println(F("[c][0 1-8][0 1-8] - copy act to act, 0 use page0")); //Serial.println(F("[S][#byte] - say phoneme")); Serial.println(F("[?][?] - print acts in current page")); Serial.println(F(" [0] - prints acts 0, and changes '??' to just print current page")); Serial.println(F(" [a] - '??' prints all acts")); Serial.println(F(" [b] - print behaviour")); Serial.println(F(" [d] - dump all acts to PC without descriptions, for reloading")); Serial.println(F(" [h] - print help")); } //=========================================================== /*****************Dan*************************/ // print integer value. /*void i_printf( int val ) { Serial.print(val); } // print string s1. void s_printf( char *s1 ) { Serial.print(s1); } /*********************************************/ /*void disp_freeram() { s_printf("-SRAM left: "); i_printf( freeRam() ); } /*********************************************/ /*int freeRam() { extern int __heap_start,*__brkval; int v; return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval); } /*********************************************/