Blog

  • Drawing Machine #12

    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.

  • Drawing Machine #14

    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.

  • Drawing Machine #13

    This is the second attempt to write the AVR code based on a technique based on the autonomous vehicle project described at http://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s1999/gurnee/index.htm

    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 */
    
    }
  • Drawing Machine #11

    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 Machines (2002-2003)

    Drawing Machines

    I 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,
    insecure, and obsolete before it is finished.

    Since I couldnt make welding pay my bills I came to a few conclusions.

    1. Computers should be fun and intertesting.
    2. When I move a brick sized object somthing should happen.
    3. I have a hardware / software degree. I am supposed to know how to do this stuff.

    It was either this or a snipercam.


    Drawing Machine number 1
    A servo based drawing arm

    Drawing Machine number 2
    An attempt to improve on #1
    Drawing Machine #3 Attempt #3 at improvment
    Drawing Machine #4 Attempt #4 at improvment

    Drawing Machine number 5
    Recreating Marvin Green’s entry into Robothon95 “Art ‘Bot” Competition

    Drawing Machine number #6
    Experimenting with servo control of vibration based movement
    Drawing Machine number #7(a-e) Further experiments in this direction.

    Drawing Machine #8(a-c)
    Initial forey into pen rovers based on Mindstorms “art-bot”

    Drawing Machine number #9
    A hacked servo based “pen” computer.
    Drawing Machine number #10? First crack at weighted drawing arm
    Drawing Machine number #11 Replacing processor in Dm1 with AVR

    Drawing Machine number #12
    A better stepper motor based rover.

    Drawing Machine number #13
    Weighted drawing arm
    Drawing Machine #14 Etchy Sketchy

    See Also:

  • Drawing Machine #9

    Drawing machine #9 is another rover based machine.This machine will eventually be driven by the palm pilot.

     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 */
    
    }
  • Drawing Machine #8

    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)
  • Drawing Machine #5

    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.

  • Drawing Machine #6

    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.

  • Drawing Machine # 3

    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.