W CNC jednak określa się tak układ zabezpieczający maszynę przed uruchomieniem przypadkowym impulsem.
Na przykład stan komputerowego portu LPT jest nieustalony w momencie włączania zasilania oraz w momencie uruchamiania programu Mach czy Linuxcnc.
Zdarza się więc, że silniki wykonają wtedy przypadkowy ruch czy wrzeciono "samo" się włączy, co jest upierdliwe i niebezpieczne.
Dlatego wymyślono żeby użyć jako sygnału ENABLE nie poziomu napięcia, ale określonej częstotliwości.
Analogia z charge pump jest taka, że odbiornik trzeba "napompować" określoną liczbą impulsów żeby zmienić stan jego wyjścia, a brak ciągłego pompowania spowoduje jego "rozładowanie".
To trochę tak jak z pompowaniem dziurawego koła - trzeba ciągle dostarczać odpowiednią ilość powietrza, inaczej zrobi się flak.
Kiedyś zrobiłem układ analogowy na mosfecie z płyty głównej komputera. Takie mosfety pracują z napięciem bramki rzędu trzech woltów i mają sporą pojemność bramki, co ułatwia zaprojektowanie układu.
Ponieważ jest to nie na temat, więc tylko wkleję schemat, może się komuś przyda:

Dzisiaj natomiast doszedłem do wniosku, że nie chce mi się szukać części, które na pewno mam, tylko nie pamiętam gdzie, ani robić płytki, kiedy mogę zaprogramować ATtiny13, który mam pod ręką...
No i tak powstał dość prosty program:
Kod: Zaznacz cały
/*
TUXCNC GPL
Digital charge pump with differential output for ATtiny13
Toggle outputs at about 576 Hz with 9,6 MHz clock, watch out for this frequency - module will unstable.
Input PB1, outputs PB3 and PB4
*/
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t index = 0;
volatile uint8_t ignored = 100; // number of impulses ignored before change outputs
int main(void)
{
DDRB |= (1 << PB3) | (1 << PB4); //set output pins
PORTB |= (1<<PB1); // Enable input pull-up on INT0
MCUCR |= ((1<<ISC00) | (1<<ISC01)); // Trigger INT0 on rising edge
GIMSK |= (1<<INT0); // enable INT0 interrupt
TCCR0A = 0x00; // Timer0 normal mode
TCCR0B |= (1<<CS00)|(1<<CS01); // prescaler /64
TIMSK0 |= (1<<TOIE0); // enable Timer0 interrupt
SREG |= 0b10000000; // enable global interrupt
while(1){
if (index == ignored){
PORTB |= (1<<PB3);
PORTB &= ~(1<<PB4);
}
else{
PORTB &= ~(1<<PB3);
PORTB |= (1<<PB4);
}
} // endless loop
}
ISR(TIM0_OVF_vect) // Timer0 overload interrupt handler
{
index = 0; // not enough impulses - count again
}
ISR(INT0_vect) // External interrupt handler
{
TCNT0=0; // reset watchdog
if (index < ignored) index++; // count impulses if less than enought
}
Działa to w ten sposób, że wyjście się włącza jeśli w określonym czasie układ otrzyma określoną liczbę impulsów wejściowych i wyłącza jeśli w określonym czasie nie otrzyma żadnego impulsu wejściowego.
To w zupełności wystarcza.
Przy zegarze 9,6 MHz częstotliwość zadziałania wynosi około 570 Hz, co powinno być dobrą wartością. Należy jednak unikać pracy z częstotliwością graniczną, bo wtedy układ pozbawiony histerezy zaczyna wariować.
Czyli timer daje okno czasowe około 1,7 ms, jeżeli w tym czasie przyjdzie co najmniej 100 impulsów to włączy wyjście, a jeżeli w tym czasie nie przyjdzie żaden impuls, to wyjście wyłączy.
Wyjście jest komplementarne, zawsze na jednym pinie jest stan przeciwny niż na drugim.
Można sobie wybrać to wyjście które bardziej pasuje, albo użyć obu wyjść jako sygnału różnicowego.
Jeżeli chodzi o maksymalną częstotliwość sygnału wejściowego, to jest ona o rzędy wielkości większa niż potrzeba - u mnie działało aż do 4,5 MHz...
Oczywiście nie ma problemu żeby program sobie dostosować do własnych potrzeb, natomiast nie widzę sensu użycia Arduino Nano czy Uno. Czasy tanich chińskich klonów chyba skończyły się bezpowrotnie, więc nie ma żadnego uzasadnienia by użyć drogą i dużą płytkę zamiast taniego scalaka napędzanego wewnętrznym generatorem...
Aczkolwiek do ATtiny potrzebny jest programator, ale to już ani wielki problem, ani wielki wydatek...