0
Offline
Newbie
Karma: 0
Posts: 8
Arduino rocks
|
 |
« on: August 16, 2010, 03:11:37 pm » |
I fly RC and wanted to break in a new gas engine. Being gas it takes about 2 gallons of fuel to do a good break in. Wanting to automate this to running on a test bench so I talked with the electronics group on RCGroups.com and went with the Arduino board. The program is a pseudo menu interface and functions can be stacked for a varied run sequence. Right now the function choices are; fullt(hrottle), idle, midt, center, menu, manual, stop; some take options. Manual drives the servo with the up down arrow keys. I'm using Putty for terminal interface ( my laptop is running Vista).
TODO: 1. Code isn't LMC, I think it's clumsy in many places and I've had an occasional glitch with passing options 2. Interface is crude, I'm thinking of adapting ansiterm or sdfruit. 3.Needs an interrupt routine to kill a run from the keyboard. I having trouble with this. Plan on also having an interrupt button at the Arduino; no racing for the PC in a panic. 4.Need to have a better understanding of the UART interface. I can't make the menu too verbose without the program locking. 5.If I get this far I may start interfacing some data recording; an RPM interface would be great.
[code] /**************************************************************************************/ #define PROGRAM "EngineRunIn" #define VERSION "0.9" /* * PROGRAM: EngineRunIn (YASP Yet Another Servo Program) * VERSION: 0.9 8/14/2010 * DESCRIPTION: Automate engine run-in program using command line arguements to vary throttle position * and duration. **************************************************************************************/ /* Throttle control */ #include <Servo.h> #include <stdio.h> /* we need fundamental FILE definitions and printf declarations */
#define SERVOPIN 2 /* pin used for servo */ #define PORTSPEED 38400 /* Baud rate */
/* tune these 2 to fit your installation */ #define LOWT 45 /* Low throttle. */ #define HIGHT 155 /* High throttle. */
#define NL "\r\n" #define PROMPT ">:" #define IFS ' ' /* Internal field separator */ #define CS ';' /* command separator */ #define BEL '\7' /* Bell */
#define DEBUG 0 /* 1 on, 0 off */ #define DELAY 1000 #define OPT_DELIM '-' /* Set up the serial port and servos. */ Servo Tservo; /* create servo object */ /* All the routines look at Lthrottle & Hthrottle ** Setup() routine can change Lthrottle & Hthrottle, ** used to determine travel setting for your installation. ** LOWT & HIGHT are then permanently changed */ int Lthrottle = LOWT; int Hthrottle = HIGHT;
int CPOS = Lthrottle; /* current servo position; tracked in every subroutine */ #define SERVOCENTER Hthrottle/2 /* Center servo */
/* cliBuildCommand */ #define MAX_COMMAND_LEN (32) /* max # of chars */ #define MAX_PARAMETER_LEN (32) #define COMMAND_TABLE_SIZE (32) /* for command_t */ #define TO_UPPER(x) (((x >= 'a') && (x <= 'z')) ? ((x) - ('a' - 'A')) : (x))
char gCommandBuffer[MAX_COMMAND_LEN + 1]; char gParamBuffer[MAX_PARAMETER_LEN + 1]; char strBuf[COMMAND_TABLE_SIZE + 1]; char functionBuf[COMMAND_TABLE_SIZE + 1]; char optionBuf[COMMAND_TABLE_SIZE + 1]; int gParamValue = false;
char *cmdptr = gCommandBuffer; char *optptr = gParamBuffer; char *str = strBuf; char *str1 = functionBuf; char *str2 = optionBuf;
/* PRINTF CODE */ static FILE uartout = {0} ; /* create a FILE structure to reference our UART output function */ /* create a output function; this works because Serial.write, ** although of type virtual, already exists. */ static int uart_putchar (char c, FILE *stream) {Serial.write(c) ;return 0 ;} /* sample code practice: ** printf("Alive %d sec\n\r", seconds ) ; ** printf("%d hello m%cworld\n", seconds,c); */
typedef struct { char const *name; void (*function)(void); } command_t;
command_t const gCommandTable[COMMAND_TABLE_SIZE] = { {"MENU", menu, }, {"BLIP", blip, }, {"B", blip, }, /* shortcut */ {"CENTER", centerservo, }, {"CNTR", centerservo, }, {"CYCLE", cycleservo, }, /* For testing, NOT on menu, may not work */ {"MIDT", midt, }, {"FULLT", fullt, }, {"IDLE", idle, }, {"EXIT", stopProgram, }, {"E", stopProgram, },/* shortcut */ {"STOP", stopProgram, }, {"S", stopProgram, },/* shortcut */ {"QUIT", stopProgram, }, {"Q", stopProgram, },/* shortcut */ {"KILL", stopProgram, }, {"K", stopProgram, },/* shortcut */ {"HELP", menu, }, {"SETUP", setupTravel, },/* write this */ {"MANUAL", manualT, }, {"M", manualT, },/* shortcut */ {NULL, NULL } };
void setup() { Tservo.attach(SERVOPIN); Serial.begin(PORTSPEED); /* opens serial port, sets data rate */
/* PRINTF STARTUP: fill in the UART file descriptor with pointer to writer. */ fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); stdout = &uartout ; /* The uart is the standard output device STDOUT. */
printf("%s%s Version: %s%s", NL, PROGRAM, VERSION, NL); prompt();
}
void loop() { char rcvChar; int bCommandReady = false;
if (Serial.available() > 0) { rcvChar = Serial.read(); /* Wait for a character. */ Serial.print(rcvChar); /* Echo the character back to the serial port. */ bCommandReady = BldCmds(rcvChar); /* Build a new command. */ }
/* Call the CLI command processing routine to verify the command entered */ /* and call the command function; then output a new prompt. */ if (bCommandReady == true) { bCommandReady = false; ProcessCmd(); prompt(); } cmdptr = &gCommandBuffer[0]; optptr = &gParamBuffer[0];
}/* END loop() */
int BldCmds(char nextChar) { static uint8_t idx = 0; //index for command buffer static uint8_t idx2 = 0; //index for parameter buffer enum { COMMAND, PARAM }; static uint8_t state = COMMAND; if ( (nextChar == ' ') || (nextChar == '\t')) /* skip space & tab */ return false; if( (nextChar == 'k') && (idx == 0) ) printf("GOT A K\n"); if ((nextChar == '\n') || (nextChar == '\r')) /* end of command line */ { gCommandBuffer[idx] = '\0'; gParamBuffer[idx2] = '\0'; idx = 0; idx2 = 0; state = COMMAND; return true; } gCommandBuffer[idx] = TO_UPPER(nextChar); idx++; return false; } /* END BldCmds */
void ProcessCmd(void) { int bCommandFound = false; int idx; /* Command & options */ while ((str = strtok_r(cmdptr, ";", &cmdptr)) != NULL) { /* semicolon delimiter */ /* Function w/o commands */ str1 = strtok_r(str, "-", &str); /* Options to function */ optptr = strtok_r(str, ";", &str);
for (idx = 0; gCommandTable[idx].name != NULL; idx++) {
if (strcmp(gCommandTable[idx].name, str1) == 0) {/* Found CMD */ strcpy(str1,gCommandBuffer); bCommandFound = true; break; } }
/* Check for options */ if ( optptr != '\0' ) { gParamValue = true; }
if (bCommandFound == true) { /* Execute command */ (*gCommandTable[idx].function)(); bCommandFound = false; }else { printf("\t\t[%s] Not Found",str1); bCommandFound = false; } gParamValue = false; delay(250); printf("%s", NL); } /* End while */ }/* END ProcessCmd */
void prompt() {printf("%s", PROMPT);}
/* blip throttle N times then return to start position */ void blip() { int c = 1, pos, cycles = 0, sleep= 700, blipthrottle = 0; char *opt;
printf("%sblip:", NL); if ( (CPOS < Lthrottle) || (CPOS > Hthrottle) ) { printf(" CPOS out of range%s", NL); return; } blipthrottle = CPOS * 1.4; if(blipthrottle > Hthrottle) blipthrottle = Hthrottle;
if (gParamValue == true) { opt = strtok_r(optptr, "-", &optptr); /* take only the first option */ /* Convert the parameter to an integer value. */ /* If the parameter is empty, cycles becomes 1 */ cycles = strtol(opt, NULL, 0); } else { cycles = 1; } pos = CPOS; /* save */ if(cycles > 1){ printf("BLIP RUN: [%d]",blipthrottle); } do { /* at least once */ if(cycles > 1){ printf("%d ", c); } //Tservo.write(Hthrottle); Tservo.write(blipthrottle);
delay(sleep); Tservo.write(pos); delay(sleep); c++; } while(c <= cycles); gParamValue = false; delay(DELAY); /* settle time */ CPOS = pos; /* restore */ }/* END blip() */
void help() { } void menu() {
printf("\tUsage:
|