I finally said to heck with it and abandoned my previous stepper based system. This is an avr based design with one avr providing the step function as an 12c device.
This is a sort of meditation inspired by the etchasketch.
Date: Fri, 21 Feb 2003 16:17:06 -0800 (PST) From: D. Delmar Davis <feurig@fromhell.com> To: D*** S********* <girlfriend@fromhell.com> Subject: Re: click click On Fri, 21 Feb 2003, D*** S******** wrote: > so what's inside an etchasketch? > i've always wanted to know! > Aluminum powder and plastic pellets the size off a pin in diameter (~1mm). which ohio art swears is non toxic (I trilled holes and vacumed as much as possible out before making a big hole in the back. There is also a pully system (which I think I reassembled correctly). I have a diagram of it at. |
Code
/*---------------------------------------------------------------------------------13.c $Revision: 1.2 $ Author: Donald Delmar Davis Date: 08feb03 Purpose: port of sketchy 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 ETRIM -200 #define STRIM -100 #define F_CPU 8000000 /* 8Mhz */ #define PULSESPACE 0xFFFF - 20000 #define PULSECENTER (1900 + PULSESPACE) #define SDLY(DEG) (1000+(11*(DEG))+PULSESPACE) #define EDLY(DEG) (1000+(10*(DEG))+PULSESPACE) #ifdef __AVR_AT_Mega8__ /* switch defines for dt107 */ #define SERVOPORTPINS PORTB #define SERVOPORTDDR DDRB #define E_SERVO PINB1 #define S_SERVO PINB2 #else /* switch defines for sim100 */ #define SERVOPORTPINS PORTB #define SERVOPORTDDR DDRB #define E_SERVO PINB1 #define S_SERVO PINB0 #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 shoulder; u16 elbow; 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 sservo,eservo; static volatile u16 duration; static volatile todolist stufftodo[]={ { SDLY(-50), EDLY(0), 2500, (todolist *) &(stufftodo[4]) }, /* when right front hits back right tire */ { SDLY(0), EDLY(-50), 2500, (todolist *) &(stufftodo[4]) }, /* when left front hits back left tire */ { SDLY(50), EDLY(0), 2500, (todolist *) &(stufftodo[4]) }, /* when right rear hits fwd right tire */ { SDLY(0), EDLY(50), 2500, (todolist *) &(stufftodo[4]) }, /* when left rear hits fwd left tire */ { SDLY(00),EDLY(45),800, (todolist *) &(stufftodo[5]) }, { SDLY(10),EDLY(45),100, (todolist *) &(stufftodo[6]) }, { SDLY(20),EDLY(45),100, (todolist *) &(stufftodo[7]) }, { SDLY(30),EDLY(45),100, (todolist *) &(stufftodo[8]) }, { SDLY(40),EDLY(45),100, (todolist *) &(stufftodo[9]) }, { SDLY(50),EDLY(45),100, (todolist *) &(stufftodo[10]) }, { SDLY(60),EDLY(45),100, (todolist *) &(stufftodo[11]) }, { SDLY(70),EDLY(45),100, (todolist *) &(stufftodo[12]) }, { SDLY(80),EDLY(45),100, (todolist *) &(stufftodo[13]) }, { SDLY(90),EDLY(45),800, (todolist *) &(stufftodo[14]) }, { SDLY(90),EDLY(50),100, (todolist *) &(stufftodo[15]) }, { SDLY(90),EDLY(40),100, (todolist *) &(stufftodo[16]) }, { SDLY(90),EDLY(45),800, (todolist *) &(stufftodo[17]) }, { SDLY(80),EDLY(45),100, (todolist *) &(stufftodo[18]) }, { SDLY(70),EDLY(45),100, (todolist *) &(stufftodo[19]) }, { SDLY(60),EDLY(45),100, (todolist *) &(stufftodo[20]) }, { SDLY(50),EDLY(45),100, (todolist *) &(stufftodo[21]) }, { SDLY(40),EDLY(45),100, (todolist *) &(stufftodo[22]) }, { SDLY(30),EDLY(45),100, (todolist *) &(stufftodo[23]) }, { SDLY(20),EDLY(45),100, (todolist *) &(stufftodo[24]) }, { SDLY(10),EDLY(45),100, (todolist *) &(stufftodo[25]) }, { SDLY(00),EDLY(45),800, (todolist *) &(stufftodo[26]) }, { SDLY(00),EDLY(50),100, (todolist *) &(stufftodo[27]) }, { SDLY(00),EDLY(40),100, (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,E_SERVO); sbi(SERVOPORTPINS,S_SERVO); outw(TCNT1,PULSESPACE); outw(OCR1A,eservo); outw(OCR1B,sservo); } SIGNAL(SIG_OUTPUT_COMPARE1A) { cbi(SERVOPORTPINS,E_SERVO); } SIGNAL(SIG_OUTPUT_COMPARE1B) { cbi(SERVOPORTPINS,S_SERVO); } SIGNAL(SIG_OVERFLOW2) { outb(TCNT2,0); /*(i dunno if this is necissary )*/ if ((--duration)<=0) { thingtodo=thingtodo->next; } else { return; } sservo=thingtodo->shoulder+STRIM; eservo=thingtodo->elbow+ETRIM; 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 eservo=PULSECENTER+ETRIM; sservo=PULSECENTER+STRIM; outb(SERVOPORTDDR,0xff); /* servoport = output */ outb(SERVOPORTPINS,0x00); /* switch outputs off */ sei(); /* enable interrupts */ }
This really isnt a new drawing machine. It is a replacement of the simstick in dm1 with a dt107 and an atmel Mega8. This is my first crack at the avr servo driving.
/*$Revision: 1.3 $ timings The idea here is that the maximum pulse is about 2ms. if we map the timings so that 255=2ms then the usable servo pulse is between */ #include <io.h> #include <interrupt.h> #include <signal.h> #define NSERVOS 3 uint_8 servodelay[NSERVOS+1]; /* max of 8 */ uint_8 currentservo=0; uint_8 servoport=0; uint_8 servoportmask=0x07; uint_8 skipbeat=10-(NSERVOS/2); SIGNAL(SIG_OVERFLOW0) /* signal handler for tcnt0 overflow interrupt */ { if (currentservo==NSERVOS) { if (!(--skipbeat)) { skipbeat=10-(NSERVOS/2); servoport=1; currentservo=0; outp(servodelay[currentservo],TCNT0); outp(servoport,PORTB); } } else { servoport<<1; currentservo++; outp(servodelay[currentservo],TCNT0); } } int main(void) { outp(0xff,DDRB); /* use all pins on PortB for output */ outp((1<<TOIE0), TIMSK); /* enable TCNT0 overflow */ outp(0, TCNT0); /* reset TCNT0 */ outp(5, TCCR0); /* count with cpu clock/1024 */ led = 1; /* init variable representing the LED state */ sei(); /* enable interrupts */ for (;;) {} /* loop forever */ } |
Drawing MachinesI have been working as a unix system admin for close to 10 years now much of it on the net where everything is transient, rushed, Since I couldnt make welding pay my bills I came to a few conclusions.
It was either this or a snipercam.
See Also:
|
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 */ }
These are my initial attempts at working through a rover based drawing machine. They were inspired largly by the Lego Mindstorms (TM) Art-Bot project that my then 6.5 year old son built and programmed with very little assistance from me. After playing with a Robotix based pen rover I decided to try to build a stepper based one from the parts of a printer.
I abandoned this project when SDCC kept modifying the code I was attempting to use. It kept optimizing out loops which would wait for a timer interupt based variable changes. (curse evilyn the code modifying dog). By the time I had a prototype of done and hammered it with code resulting in mostly jitters the piece has mostly fallen appart. Iwill more than likely build a fresh one once I identify the appropriate matched stepper moters and start over using avr-gcc.
(And find a better picture of this thing) |
This is an attemt to recreate an art-bot submitted by Marvin Green to Robothon 95. The description is of a vibrator motor and a plastic cup. It actually works qutie well. |
This is an attemt to control vibration based movement by mounting motor on a servo.
This experiment was not very successfull in realizing controll and destroyed itself in the process.
I purchased a chain and sprocket set from ServoCity while it didnt slop like the belt it stretched and was flexible in ways that make it useless.