A personal repository of random information in compensation for a fatigued biological computer
Generic PIC16F / PIC18F PCB I made in 2007 repurposed for this application..
Has PIC18F4620 40 pin PDIP MCU onboard running at 5V/40mHZ
Simple firmware using CCS C IDE/Compiler
Fed the Parallel port output needed
Inputs from Mach3:
B0 = Z step
B1 = Z step direction
B2 = vacuum toggle/do it (GCode calls Mach3 vbscript macro to toggle pin)
B3 = unused
B4-B7 = Head/instruction selection prior to B0 or B2 action
Outputs:
RC0-3/RC4-7 Head up down pneumatic valve control
RD0-3, RD4-7 Head vacuum solenoid on
RE0-2: Z movement indicator & heartbeat LED
RA4: Mains Vacuum pump on / off - NOT IMPLEMENTED
RA5: Audio Buzzer on end of cycle
So..
Interrupts on B0 or B2 trigger actions
B0 interrupt sequence:
B2 responds to vacuum toggle instructions from Mach 3:
Additionally, we display a heartbeat on RE0
Future: Move to Plug And Program MC32MX64GP mainboard but need to ensure child PCB's are 3.3v compatible..
Programmed in CCS C:
#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 FullStep[8];
//int HalfStep1[8];
//int HalfStep2[8];
//int HalfStep3[8];
//int HeadPowerDownCounter;
int HeartBeatCounter;
int1 HeartBeat;
int CurrentHead;
//long Head0Position, Head1Position, Head2Position, Head3Position;
int1 Head0VacuumOn, Head1VacuumOn, Head2VacuumOn, Head3VacuumOn;
//long Head4Position, Head5Position, Head6Position, Head7Position;
int1 Head4VacuumOn, Head5VacuumOn, Head6VacuumOn, Head7VacuumOn;
// 20110907
// Inputs
// B0 is do move head up/down
// B1 is move direction
// B2 is vacuum toggle/do it
// B4-7 is 0-15 head/stepper selector
//Outputs
// C0-3/C4-7 are head pneumatic valves
// D0-3/C4-7 are Vacuum control solenoids
// E0-3 Display LEDs
// A4-5 = Buzzer & Vacuum pump SSR
void outputAllVacuums(void)
{
output_bit(PIN_D0,Head0VacuumOn);
output_bit(PIN_D1,Head1VacuumOn);
output_bit(PIN_D2,Head2VacuumOn);
output_bit(PIN_D3,Head3VacuumOn);
output_bit(PIN_D4,Head4VacuumOn);
output_bit(PIN_D5,Head5VacuumOn);
output_bit(PIN_D6,Head6VacuumOn);
output_bit(PIN_D7,Head7VacuumOn);
}
void setAllVacuums(int1 setting)
{
Head0VacuumOn = Head1VacuumOn = Head2VacuumOn = Head3VacuumOn = setting;
Head4VacuumOn = Head5VacuumOn = Head6VacuumOn = Head7VacuumOn = setting;
outputAllVacuums();
}
#int_ext //B0
void ext_isr(void)
{
switch (CurrentHead)
{
case 0:
if (input(PIN_B1))
{
output_bit(PIN_C0,1);
}
else
{
output_bit(PIN_C0,0);
}
break;
case 1:
if (input(PIN_B1))
{
output_bit(PIN_C1,1);
}
else
{
output_bit(PIN_C1,0);
}
break;
case 2:
if (input(PIN_B1))
{
output_bit(PIN_C2,1);
}
else
{
output_bit(PIN_C2,0);
}
break;
case 3:
if (input(PIN_B1))
{
output_bit(PIN_C3,1);
}
else
{
output_bit(PIN_C3,0);
}
break;
case 4:
if (input(PIN_B1))
{
output_bit(PIN_C4,1);
}
else
{
output_bit(PIN_C4,0);
}
break;
case 5:
if (input(PIN_B1))
{
output_bit(PIN_C5,1);
}
else
{
output_bit(PIN_C5,0);
}
break;
case 6:
if (input(PIN_B1))
{
output_bit(PIN_C6,1);
}
else
{
output_bit(PIN_C6,0);
}
break;
case 7:
if (input(PIN_B1))
{
output_bit(PIN_C7,1);
}
else
{
output_bit(PIN_C7,0);
}
break;
}
}
#int_ext2 //B2
void ext2_isr(void)
// toggle vacuum / do it
{
switch (CurrentHead)
{
// vacuum toggling
case 0:
Head0VacuumOn = !Head0VacuumOn;
output_bit(PIN_D0,Head0VacuumOn);
break;
case 1:
Head1VacuumOn = !Head1VacuumOn;
output_bit(PIN_D1,Head1VacuumOn);
break;
case 2:
Head2VacuumOn = !Head2VacuumOn;
output_bit(PIN_D2,Head2VacuumOn);
break;
case 3:
Head3VacuumOn = !Head3VacuumOn;
output_bit(PIN_D3,Head3VacuumOn);
break;
case 4:
Head4VacuumOn = !Head4VacuumOn;
output_bit(PIN_D4,Head4VacuumOn);
break;
case 5:
Head5VacuumOn = !Head5VacuumOn;
output_bit(PIN_D5,Head5VacuumOn);
break;
case 6:
Head6VacuumOn = !Head6VacuumOn;
output_bit(PIN_D6,Head6VacuumOn);
break;
case 7:
Head7VacuumOn = !Head7VacuumOn;
output_bit(PIN_D7,Head7VacuumOn);
break;
// toggle/do it signal for addresses 8-15 are canned functions
case 8: // Buzzer off
output_bit(PIN_A4,0);
setAllVacuums(0);
break;
case 9: // Buzzer on
output_bit(PIN_A4,1);
break;
case 10: // SSR off
output_bit(PIN_A5,0);
break;
case 11: // SSR on
output_bit(PIN_A5,1);
break;
}
}
void main()
{
//-------------------------------------
//Startup sequence
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
Output_A(0);
Output_C(0);
Output_D(0);
//Not all the step sequences below are used but we will leave them here
//for future use
HeartBeatCounter = 25;
HeartBeat = 0;
// Cycle through all the head selects so we can see startup on the
// the Stepper controller PCB & cycle all vacuum solenoids
for(CurrentHead = 0;CurrentHead<=7;++CurrentHead)
{
Output_D(1<<CurrentHead);
output_bit(PIN_A4,CurrentHead&1);
delay_ms(500);
}
Output_A(0);
Output_C(0);
Output_D(0);
// ext_int_edge(1,H_TO_L);
enable_interrupts(GLOBAL);
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT2);
// end startup squence
//-------------------------------------
while(1)
{
// constantly monitor head selection input and pass through to head select output
CurrentHead = (input(PIN_B7) << 3) + (input(PIN_B6) << 2) + (input(PIN_B5) << 1) + input(PIN_B4);
HeartBeatCounter -= 1;
if (!HeartBeatCounter)
{
HeartBeat = !HeartBeat;
output_bit(pin_e2,HeartBeat);
HeartBeatCounter = 25;
}
}
}