A personal repository of random information in compensation for a fatigued biological computer
Ebay CNC router from .cn
X, Y Z = Nema steppers, have 1.8deg step resolution.
Ball screws = 5mm pitch
Limit switches: unit comes with 6 microswitches but no fittings/wiring
Steppers and leadscrews coupled with 8mm - 8mm (5/16) couplings)
Mach3 compatible (parallel port) control board
labeled TB6560-3V2 and has no other identifying labels.
- allows setting of microstepping in 1, 1/2, 1/8, 1/16 by dip switches on each of A B C
- allows current configuration by dip switch on each of A B C
- Has 3 x Toshiba TB6560AH0 under the fan/heatsink
IO:
CNC side:
---
Control side:
Parallel port:
---
Limit switches/EStop
---
Port5
Note: not sure if EN here is in or out as doesn't appear to be an output linked to EN - P1 on the parallel port
-------------
Inputs A-C each have their own TB6560 output
Input E is passed out to 'Port 5' breakout which is 5V and isolated for power and probably signals as well..
not sure what happens to Input D...
Moto1 is passed to the relay..
Assume EN is global enable.. tied to Mach3 reset button..??
Limits switches are linked through to P10-13
--------------
Some other components:
EL817 Photocoupler on limit switches, and probably on Port 5 out CK & CW maybe
OTC 6N137 high speed single optocoupler x 6 on A-C DIR & CLK
-------------
We will use Port 5 to drive a secondary small Z axis (Sony DVD drive stepper motor), using a PIC18F4610 to convert CK & CW signals back to 4 line stepper bipolar signal via a SN754410
Crappy CCS C to read CW & CK from Port 5 and turn into bipolar steeper control (half steps only)
- CK is on B0, CW is on B1, Stepper output is d0-d3 (also writes 0's to D4-7) and heartbeat is on C0-3
#include <18F4610.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES H4 //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES PUT //Power Up Timer
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOLPT1OSC //Timer1 configured for higher power operation
#FUSES MCLR //Master Clear pin enabled
//#FUSES XINST //Extended set extension and Indexed Addressing mode enabled
#use delay(clock=40000000)
int HalfStep[8];
long position;
int heartbeat;
#int_ext
void ext_isr(void)
{
if (input(PIN_B1))
position += 1;
else
position -= 1;
output_d(HalfStep[(position&0b00000111)]);
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
HalfStep[0] = 0b00001000;
HalfStep[1] = 0b00001001;
HalfStep[2] = 0b00000001;
HalfStep[3] = 0b00000101;
HalfStep[4] = 0b00000100;
HalfStep[5] = 0b00000110;
HalfStep[6] = 0b00000010;
HalfStep[7] = 0b00001010;
position = 0;
heartbeat = 1;
output_d(0);
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
// TODO: USER CODE!!
while(1)
{
output_c(heartbeat);
delay_ms(200);
heartbeat = heartbeat << 1;
if (heartbeat > 0b0001000)
heartbeat = 1;
}
}
-----
We will have Moto1 - P14 relay driving a solid state relay which switches a fish tank pump on off for vacuum pickup.
-----
X Y Z:
Mach3 axis tuning screen asks no of steps per unit:
Lead screw pitch is 5mm, with microstepping set to 1/8
Steps per mm = ((360/1.8) * 8) / 5 = 200 * 8 / 5 = 320 steps per mm
Speed:
Genuine NEMA 23's have max RPM of 3000.. Mach3 has a setting for units per minute ie per mm in our case:
If we assume 1500 RPM:
- Lead screw pitch is 5mm, 1 revolution = 5mm, so theretical max speed is 1500 * 5 mm = 7500mm per minute, wow..
But.. this machine won't do that, gets the wobbles...
-----
20100908
Whoops, forgot to power down before disconnecting one of the steppers and control board went BANG and up in angry flame and smoke. Can't get one the same quick enough so purchased a different generic chinese 3 stepper control PCB using the same TB6560 IC's. Has totally different mapping to the Parallel port though...
So, thought it best if I separate out the none X Y Z stepper signals from all others..
Plan A: Bought a PCI Parallel port card (Dual parallel port) but having trouble getting Mach 3 to work with it so plan B
Plan B: Made a parallel breakout PCB, which allows me to remap stepper X Y Z and enables and breaks out the other pins for my own use..
We pass through All Enable, X Step, X Dir, Y Step, Y Dir, Z Step, Z Dir, all other pins are driven off the breakout either directly ie limit / estop switch or indirectly via PIC18F4610 processor
Pport | Mach 3 IO | FNF Use | 40P68 Connection | Other connection | Orig Controller | Note | Map to | Replacement controller | Map to |
1 | Output | All axis enable | All axis enable | 1 | X Step | 2 | |||
2 | Output | X Step | X Step | 2 | Y Enable | 1 | |||
3 | Output | X Dir | X Dir | 3 | Y Dir | 5 | |||
4 | Output | Y Step | Y Step | 4 | Z Dir | 7 | |||
5 | Output | Y Dir | Y Dir | 5 | Z Step | 6 | |||
6 | Output | Z Step | Z Step | 6 | Z Enable | 1 | |||
7 | Output | Z Dir | Z Dir | 7 | X Dir | 3 | |||
8 | Output | Head Step | B0 | A Step | Not available | Y Step | 4 | ||
9 | Output | Head Dir | B4 | A Dir | Not available | Relay | |||
10 | Input | X Limit | X Limit | Limit 10 | Input 1 | ||||
11 | Input | Y Limit | Y Limit | Limit 11 | Input 2 | ||||
12 | Input | Z Limit | Z Limit | Limit 12 | Input 3 | ||||
13 | Input | E Stop | E Stop | Limit 13 | Input 4 | ||||
14 | Output | Vacuum toggle | B1 | Relay | X Enable | 1 | |||
15 | Input | spare | |||||||
16 | Output | Head select | B5 | B Step | Passthrough? | ||||
17 | Output | Head select | B6 | B Dir | Passthrough? | ||||
18 | Gnd | 18 | 18 | ||||||
19 | Gnd | 19 | 19 | ||||||
20 | Gnd | 20 | 20 | ||||||
21 | Gnd | 21 | 21 | ||||||
22 | Gnd | 22 | 22 | ||||||
23 | Gnd | 23 | 23 | ||||||
24 | Gnd | 24 | 24 | ||||||
25 | Gnd | 25 | 25 | ||||||
Pickups - 5 Outputs available: | |||||||||
Step | 1 | B0 | |||||||
Direction | 1 | B4 | |||||||
Vacuum toggle | 1 | B1 | |||||||
Select head | 2 | B5 | 2 bits allows select 4 heads 0-3 | ||||||
B6 | |||||||||
Head 0 Stepper | C0-3 | ||||||||
Head 1 Stepper | C4-7 | ||||||||
Head 2 Stepper | D0-3 | ||||||||
Head 3 Stepper | D4-7 | ||||||||
Vacuum 0-3 | RA0-3 |
PIC18F4610 processor functionality (refer above mapping):
Functional input summary:
Code summary
Initialise:
B0 Int:
- Check 2 bit pickup head address on B5 & B6 (Head 0-3), check direction on B4, move selected head
B1 Int:
- Check 2 bit pickup head address on B5 & B6 (Head 0-3), toggle head vacuum (vacuum 0-3)
Maybe also, after every head move operation, set head stepper to 0 about 1/2 second after reach destination
20100909 code:
#include <18F4610.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES H4 //High speed osc with HW enabled 4X PLL
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES PUT //Power Up Timer
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES NOLPT1OSC //Timer1 configured for higher power operation
#FUSES MCLR //Master Clear pin enabled
//#FUSES XINST //Extended set extension and Indexed Addressing mode enabled
#use delay(clock=40000000)
int HalfStep[8];
int1 heartbeat;
long Head0Position, Head1Position, Head2Position, Head3Position;
int1 Head0VacuumOn, Head1VacuumOn, Head2VacuumOn, Head3VacuumOn;
// B0/EXT is step clk
// B4 is step dir
// B1/EXT1 is vacuum toggle
// B5/B6 are 2 bit head select
// Head 0 stepper is on C0-3
// Head 1 stepper is on C0-4
// Head 2 stepper is on D0-3
// Head 3 stepper is on D4-7
// Vacuums 0-3 are on RA0-3 (active low)
#int_ext
void ext_isr(void)
{
switch ((input(PIN_B6) << 1) + input(PIN_B5))
{
case 0:
if (input(PIN_B4))
Head0Position += 1;
else
Head0Position -= 1;
output_c(HalfStep[Head0Position&0b00000111]);
break;
case 1:
if (input(PIN_B4))
Head1Position += 1;
else
Head1Position -= 1;
output_c(HalfStep[Head1Position&0b00000111]<<4);
break;
case 2:
break;
if (input(PIN_B4))
Head2Position += 1;
else
Head2Position -= 1;
output_d(HalfStep[Head2Position&0b00000111]);
break;
case 3:
if (input(PIN_B4))
Head3Position += 1;
else
Head3Position -= 1;
output_d(HalfStep[Head3Position&0b00000111]<<4);
break;
}
}
#int_ext1
void ext1_isr(void)
{
switch ((input(PIN_B6) << 1) + input(PIN_B5))
{
case 0:
Head0VacuumOn = !Head0VacuumOn;
output_bit(PIN_A0,!Head0VacuumOn);
break;
case 1:
Head1VacuumOn = !Head1VacuumOn;
output_bit(PIN_A1,!Head1VacuumOn);
break;
case 2:
Head2VacuumOn = !Head2VacuumOn;
output_bit(PIN_A2,!Head2VacuumOn);
break;
case 3:
Head3VacuumOn = !Head3VacuumOn;
output_bit(PIN_A3,!Head3VacuumOn);
break;
}
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
HalfStep[0] = 0b00001010;
HalfStep[1] = 0b00001000;
HalfStep[2] = 0b00001001;
HalfStep[3] = 0b00000001;
HalfStep[4] = 0b00000101;
HalfStep[5] = 0b00000100;
HalfStep[6] = 0b00000110;
HalfStep[7] = 0b00000010;
Head0Position = Head1Position = Head2Position = Head3Position = 0;
Head0VacuumOn = Head1VacuumOn = Head2VacuumOn = Head3VacuumOn = 0;
output_c(0);
output_d(0);
output_bit(PIN_A4,input(PIN_B5));
output_bit(PIN_A5,input(PIN_B6));
output_bit(PIN_A0,!Head0VacuumOn);
output_bit(PIN_A1,!Head1VacuumOn);
output_bit(PIN_A2,!Head2VacuumOn);
output_bit(PIN_A3,!Head3VacuumOn);
heartbeat = 0;
output_d(0);
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
// TODO: USER CODE!!
while(1)
{
output_bit(PIN_e0,input(PIN_B5));
output_bit(PIN_e1,input(PIN_B6));
heartbeat = !heartbeat;
output_bit(pin_e2,heartbeat);
delay_ms(200);
}
}
20100910 Ok thats all working..
Modified 2 DVD stepper drive heads and put on vacuum feeds..
201001001
Modified an additional DVD stepper head and working with 3 heads now
20101101
IN the middle of major modifications
Now have 8 DVD drive stepper heads, redocumenting