For now It is autonomous and the palm pilot just gets a free ride.
It uses a very popular technique of hacking a servo.
This is my first attempt at modifying servos I have photographed the stepps in this conversion. If I were to modify any part of this project it would be to use a multi turn trim pot in place of the matched resisters.
I had to adjust for this in code.
There are a few interesting points about this type of drawing machine.
Not the least of which is that there is no way to draw a horizontal
line directly. (insert figure here). Before I installed the switches
on this machine it continuously pushed its way out of the barracades that I supported with rather large rocks. This wheel set might make a good sumo candidate. It also dug a hole through several sheets of paper and proceeded to blead over several more sheets. Up to this point I had been using a sketch books to store the various trees of development. This machine damaged the work of 5 of its contemporaries.
From then on I took the finished work out of the books.
Currently the base is autonomous. Eventually the palm pilot will be the brains of the operation.
ahem *New 10 feb 03*
This is my first shift from sdcc and the 8051 to gcc and the AVR. Thanks to Dontronics and the simstick I just spent a manmonth or so learning the new software environment on my handy SDK500 and then swapped the dt107 with the 89S53 on it for one with the ATmega8.
See Also:
http://home1.gte.net/tdickens/68hc11/trp2/trp2.html
code
/*---------------------------------------------------------------------------------avrwander.c $Revision: 1.6 $ Author: Donald Delmar Davis Date: 08feb03 Purpose: Port of Penwander code from sdcc to avrgcc. Credits: AVR-GCC test program #4 (Author: Volker Oth) / Autonomous car program. */ //#if defined (__ATmega163__) //#define __AVR_ATmega163__ 1 #define __AVR_ATmega8__ 1 //#endif #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> //#define LTRIM -340 //#define RTRIM -120 #define LTRIM 750 #define RTRIM 750 #define F_CPU 8000000 /* 8Mhz */ #define PULSESPACE 0xFFFF - 20000 #define PULSECENTER (1900 + PULSESPACE) #define SERVOPORTPINS PORTC #define SERVOPORTDDR DDRC #define L_SERVO PINC4 #define R_SERVO PINC5 #define RDT(DEG) (1000+(10*(DEG))+PULSESPACE) //#define LDT(DEG) (1000+(10*(180-DEG))+PULSESPACE) #define LDT(DEG) (1000+(10*(DEG))+PULSESPACE) #define SWITCHPORTPULL PORTB #define SWITCHPORTPINS PINB #define SWITCHPORTDDR DDRB #ifdef __AVR_AT_Mega8__ /* switch defines for dt107 */ #define RIGHT_FRONT PINB5 #define LEFT_FRONT PINB4 #define RIGHT_REAR PINB3 #define LEFT_REAR PINB2 #else /* switch defines for sim100 */ #define RIGHT_FRONT PINB7 #define LEFT_FRONT PINB6 #define RIGHT_REAR PINB5 #define LEFT_REAR PINB4 #endif //#define UART_BAUD_RATE 9600 /* 9600 baud */ //#define UART_BAUD_SELECT (F_CPU/(UART_BAUD_RATE*16l)-1) typedef unsigned char u08; typedef char s08; typedef unsigned short u16; typedef short s16; typedef struct _todolist { u16 rwheel; u16 lwheel; u16 duration; struct _todolist *next; } todolist; /* uart globals */ static volatile u08 *uart_data_ptr; static volatile u08 uart_counter; unsigned char led; static volatile u16 rservo,lservo; static volatile u16 duration; static volatile todolist stufftodo[]={ { RDT(-50), LDT(0), 2500, (todolist *) &(stufftodo[4]) }, /* when right front hits back right tire */ { RDT(0), LDT(-50), 2500, (todolist *) &(stufftodo[4]) }, /* when left front hits back left tire */ { RDT(50), LDT(0), 2500, (todolist *) &(stufftodo[4]) }, /* when right rear hits fwd right tire */ { RDT(0), LDT(50), 2500, (todolist *) &(stufftodo[4]) }, /* when left rear hits fwd left tire */ { RDT(50),LDT(0),200, (todolist *) &(stufftodo[5]) }, { RDT(0),LDT(-50),200, (todolist *) &(stufftodo[6]) }, { RDT(-50),LDT(0),200, (todolist *) &(stufftodo[7]) }, { RDT(0),LDT(50),400, (todolist *) &(stufftodo[4]) } }; #define RFSWITCHTODO ( (todolist *) &(stufftodo[0]) ) #define LFSWITCHTODO ( (todolist *) &(stufftodo[1]) ) #define RRSWITCHTODO ( (todolist *) &(stufftodo[2]) ) #define LRSWITCHTODO ( (todolist *) &(stufftodo[3]) ) static volatile todolist *thingtodo=&(stufftodo[4]); /*;**********************Timer 1 overflow************** *;brings two servo lines hi, reloads servo position values *; *;_______|-|____ *; / *; | *; overflow here */ SIGNAL(SIG_OVERFLOW1) { sbi(SERVOPORTPINS,L_SERVO); sbi(SERVOPORTPINS,R_SERVO); outw(TCNT1,PULSESPACE); outw(OCR1A,rservo); outw(OCR1B,lservo); } SIGNAL(SIG_OUTPUT_COMPARE1A) { cbi(SERVOPORTPINS,L_SERVO); } SIGNAL(SIG_OUTPUT_COMPARE1B) { cbi(SERVOPORTPINS,R_SERVO); } SIGNAL(SIG_OVERFLOW2) { outb(TCNT2,0); /*(i dunno if this is necissary )*/ /* if (bit_is_clear(SWITCHPORTPINS,RIGHT_FRONT)){ thingtodo=RFSWITCHTODO; } else if (bit_is_clear(SWITCHPORTPINS,LEFT_FRONT)){ thingtodo=LFSWITCHTODO; } else if (bit_is_clear(SWITCHPORTPINS,RIGHT_REAR)){ thingtodo=RRSWITCHTODO; } else if (bit_is_clear(SWITCHPORTPINS,LEFT_REAR)){ thingtodo=LRSWITCHTODO; } else*/ if ((--duration)<=0) { thingtodo=thingtodo->next; } else { return; } rservo=thingtodo->rwheel+RTRIM; lservo=thingtodo->lwheel+LTRIM; duration=thingtodo->duration; } void main(void) { outb(TIMSK,(_BV(TOIE2)|_BV(TOIE1)|_BV(OCIE1A)|_BV(OCIE1B))); /* enable TCNT overflow */ outw(TCNT1,0xFF00); // idea is to start with an interupt (not sure if this wil work). outb(TCCR1A,0); outb(TCCR1B,2); // ck/8 duration=10; cbi(ASSR,AS2); outb(TCNT2,0x00); outb(TCCR2,3); // ck/1024 rservo=PULSECENTER+LTRIM; lservo=PULSECENTER+RTRIM; outb(SERVOPORTDDR,0xff); /* servoport = output */ outb(SERVOPORTPINS,0x00); /* switch outputs off */ outb(SWITCHPORTDDR,0x00); /* switchport = input */ // outb(SWITCHPORTPULL,0xff); /* Turn Pullups ON */ sei(); /* enable interrupts */ }