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 */
}