This machine consists of 2 servos controlling an aluminum arm with a pen attached. It is an attempted improvement on DM#1 by moving the weight back to the shoulder The belt used on this machine was completely unusable because it slipped and then all coordinates were useless. This caused the machine to leave the boundries and destroy itself. DM3 is a rebuild of this arm with a plastic chain and sprocket arrangement.
This machine consists of 2 servos controlling an aluminum arm with a pen attached.
I origionally developed this hardware using a DS5000 on a simsick.
Code
/*--------------------------------------------------------------------servo.c * Test program for drawing machines. * * This code is targeted at an 89S4051 and compiles with sdcc. * * Author: Donald Delmar Davis, * w/ Suggestions from to Bernard Winter and Dan Micheals * * Date: 28apr02 * * Status: alfa VERY alfa. * * Notes: This seems to work farely well. */ #include #define NSERVOS 3 #define SERVO0 P1.7 #define SERVO1 P1.6 #define SERVO2 P1.5 #define KFREQ 11059 #define STRIM - 693 #define ETRIM + 81 unsigned int DegreesX92delay(unsigned int DegreesX9); unsigned char CurrentServo; unsigned int SpaceDelay; unsigned int Servo0Delay; unsigned int Servo1Delay; unsigned int Servo2Delay; /* grid.h is calculated by joe2.c */ #include "grid.h" /*--------------------------------------------------------------------initservos * Initialize servo values and set up timers. * */ void initservos(unsigned char s0, unsigned char s1, unsigned char s2 ){ CurrentServo=0; SpaceDelay=65535-((20-(NSERVOS*2))*KFREQ)/12; Servo0Delay=DegreesX92delay(s0); Servo1Delay=DegreesX92delay(s1); Servo2Delay=DegreesX92delay(s2); // assembly here is // mostly to avoid having to define SERVO pins in both c and asxxx // eventually may rewrite routine in assembly. _asm clr SERVO0 clr SERVO1 clr SERVO2 _endasm; // should set flags individually to allow for other timer settings TMOD=0x01; //#%00000001 TCON=0x10; //#%00010000 TH0=0xFE; TL0=0; IE=0x82; //#%10000010 } /*--------------------------------------------------------------------servopulse * pulse servos sequentially. * */ void servopulse(void) interrupt 1 _naked { _asm clr TR0 push ACC push PSW push B clr SERVO0 clr SERVO1 clr SERVO2 mov A,_CurrentServo cjne A, #NSERVOS, $0001 mov A, #255 mov TL0,_SpaceDelay mov TH0,_SpaceDelay+1 sjmp $0007 $0001: jnz $0002 mov TL0,_Servo0Delay mov TH0,_Servo0Delay+1 setb SERVO0 sjmp $0007 $0002: cjne A, #1, $0003 mov TL0,_Servo1Delay mov TH0,_Servo1Delay+1 setb SERVO1 sjmp $0007 $0003: mov TL0,_Servo2Delay mov TH0,_Servo2Delay+1 setb SERVO2 $0007: inc A mov _CurrentServo,A pop B pop PSW pop ACC setb TR0 reti _endasm; } time1ms() /* not really a 1 ms delay with XTAL 11.0592MHz */ { int i; for (i = 0; i < 8 ; i++) ; } void delay(unsigned int n) /* do nothing n*1ms */ { int i; for (i=0; i< n ; i++) time1ms(); } unsigned int DegreesX92delay(unsigned int DegreesX9){ //delay(10); return 0-(690+(DegreesX9)); } void shoulder(unsigned int DegreesX9){ Servo0Delay=DegreesX92delay(DegreesX9 STRIM); } void elbow(unsigned int DegreesX9){ Servo1Delay=DegreesX92delay(DegreesX9 ETRIM); } void xit (unsigned char x,unsigned char y,unsigned int dly){ unsigned int s,e; unsigned char ds,de; s=angles[x][y][0]; e=angles[x][y][1]; shoulder(s);elbow(e);delay(dly); ds=(char) s - angles[x+1][y][0]; de=(char) e - angles[x+1][y][1]; ds=ds/3; de=de/3; shoulder(s+ds);elbow(e+de);delay(dly); shoulder(s);elbow(e);delay(dly); shoulder(s+ds);elbow(e+de);delay(dly); shoulder(s);elbow(e);delay(dly); shoulder(s+ds);elbow(e+de);delay(dly); shoulder(s);elbow(e);delay(dly); shoulder(s+ds);elbow(e+de);delay(dly); shoulder(s);elbow(e);delay(dly); shoulder(s+ds);elbow(e+de);delay(dly); } #if 0 #define GOTO(X,Y) shoulder(angles[X][Y][0]); elbow(angles[X][Y][1]); delay(dly); void xit (unsigned char x,unsigned char y,unsigned int dly){ unsigned char s,e,n; for (e=0;e<5;e++){ GOTO(x-1,y); GOTO(x-1,y+1); GOTO(x,y+2); GOTO(x+1,y+2); GOTO(x+2,y+1); GOTO(x+2,y); GOTO(x+1,y-1); GOTO(x,y-1); GOTO(x-1,y); } } #endif /*----------------------------------------------------------------------------main() * */ main(){ unsigned char d,e,x,y,n; initservos(angles[1][1][0],angles[1][1][1],90); d=0;e=0; for (n=0; n<50; n++){ for(x=0;x<15;x++){ if (d==0){ for(y=1;y<12;y++){ xit(x,y,500); } d=1; } else { for(y=11;y>0;y--){ xit(x,y,500); } d=0; } } e=0; } }
This is a timer I built using a gutted alarm clock and a 2051. I developed the hardware using a DS5000 based emulater and the 89s8252 based programmer that I built last fall.
Schematic
The emulator |
The programmer |
|
Testing with actual chip |
The carcas |
|
The finished product buried on the messy bench |
code
/*---------------------------------------------------------------------timer.c** This is the code for a soldering iron timer. * * C 2002 Donald Delmar Davis (delmar@digithink.com).** The hardware is built around the 20 pin atmel 89C2051. * (http://www.atmel.com/atmel/products/prod71.htm)* This program was compiled using sdcc (sdcc.sourceforge.com)** P1 is connected to the lower half of a 3.5 digit multiplexed clock display.* P3.0 is connected to the transister driving a relay.* P3.4-3.7 are connected to a BCD switch.* * P3.3 is connected to an off switch. (currently unimplimented).** The reset switch causes the machine to read the BCD switch. The timer * then counts down from 10 times the switch value plus 5 minutes. * ** Most of the work is done by the timer interupt which not only counts* time but also multiplexes the display. *----------------------------------------------------------------------------*/#include #define RELAY P3_0static unsigned int pulses;static unsigned char seconds,ones,tens;code unsigned char tens_b[] = {0x58,0x00,0x38,0x30,0x60,0x70,0x78,0x00,0x78,0x70};code unsigned char tens_a[] = {0xf0,0xb0,0xe0,0xf0,0xb0,0xd0,0xd0,0xf0,0xf0,0xf0};code unsigned char ones_b[] = {0x07,0x06,0x05,0x07,0x06,0x03,0x03,0x07,0x07,0x07};code unsigned char ones_a[] = {0x8b,0x80,0x8e,0x86,0x85,0x87,0x8f,0x80,0x8f,0x87};/*---------------------------------------------------pulse_count * Count "pulses" from timer1 also multiple the display. * timer1 is set up to count 9600 ticks per second. * * * This could probably be optimized to create cleaner assembly. * does the job just fine. */void pulse_count (void) interrupt 3 {pulses++;if (pulses==9600) { if (++seconds == 60) { if (ones==0){ ones=9; if (tens==0) { RELAY=0; P1=0; /* could power down here */ while (1) ; } else { tens--; } } else { ones--; } seconds=0; } pulses=0;}if (pulses&0x0001) { P1=tens_a[tens]|ones_a[ones];} else { P1=tens_b[tens]|ones_b[ones];}}main(){TMOD &= 0x0f; /* clear timer 1 control bits */TMOD |= 0x20; /* set timer 1 to mode 2 */ TL1 = -3; TH1 = -3; /* 9600bps with 11.059MHz crystal */TR1 = 1;P1=0x11;ones=0;tens=0;seconds=0;pulses=0 ;P3 = 0xff;RELAY=1;tens=(((~P3&0x80)>>1)|(~P3&0x38))>>3;ones=5;ET1=1; /* enable timer 1 interupt */EA=1; /* enable interupts */ while (1){; }}
Bootstrap 89×051 programmerThis is a result of many searches through the web to put together a 4051 programmer. Most of the programmers required a preprogrammed 4051. • Many of them used the reference circuit provided by atmel to supply the 0/5/12 programming voltage. This circuit used a 317 and a series of odd resister values which I had to fabricate using several less odd ones. •• I found a c based programmer which served as an algorythm. Unfortunately the source code was written for a commercial compiler. ••• |
|
So what the world needs now is another 89X051 programmer ••••This programmer uses an $7 Atmel AT89S8252 or AT89S53 which is programmed in circuit using Vona’s ’89prog’ and a 50cent Paralell Cable adapter. Asside from the Atmel which you can get from jdr microdevices or from digikey you can pretty much get everything else at radio shack. You could also probably use another in circuit programmer. I just figured this one out first. To make the programming more straight forward most of the pins required for programming are connected straight across (P1.0-7,P3.2-5) I may try to make a board which will work both as an adapter/emulator. The programming voltage circuit which uses common resistors values and general purpose transisters is from the burn project. It is written in the publically avaliable Small Device C Compiler. |
The 8051 has come along way since I was a student. Windowed eproms etc, I would go into it but eventually I would sound like one of those old IMSI 8080 owners talking about loading their bootstraps one bit at a time.
I have been working with the ds5000 and the atmel flash based family. A noticable issue with the 8051 is the lack of a decent public domain c compiler. For this reason I have shifted from the AVR with an eye on the motorolas.
4051 programmer | This is my first 89s8252 project | |
Soldering Iron Timer | This is the first thing I did with my development environment |