Domáci prístroj pre magnetoterapiu
V časopise Amatérske rádio (číslo PE05/2012) ma zaujala jednoduchá konštrukcia prístroja pre domácu magnetoterapiu. Autor článku písal, že sa mu podarilo vyliečiť si tenisový lakeť, a vyrobil viacero exemplárov prístroja aj pre svojich známych (aj lekárov) a dostal len pozitívne ohlasy. Na tomto prístroji sa mi páčilo, že frekvencia impulzov je nastaviteľná, a že všetky súčiastky sa dajú vydolovať zo starých TV vrakov, prípadne ich má každý amatér-elektrotechnik v "šuflíkových zásobách".
Zobral som teda schému a vyskúšal ju na breadboarde. Fungovala na prvé zapojenie. Ako aplikačnú cievku som použil vychyľovaciu cievku z TV. Má feritové jadro, indukčnosť asi 15 mH a odpor 5 ohmov. Impulzy je cítiť po priblížení permanentného magnetu, ako ukazujem na videu nižšie. Tak sa dá overiť, že prístroj skutočne funguje a do cievky idú impulzy.
Prístroj som vylepšil o meranie frekvencie a časovač vypnutia. Ako inak, na to som využil AVR ATmega8. Na obrázkoch a videu ukazuje frekvenciu červený displej, a ostávajúci čas ukazuje zelený displej. Ešte je tam červená LED, ktorá bliká do rytmu impulzov, a potenciometer na reguláciu frekvencie. Zostávajúci čas sa dá nastaviť 4 tlačidlami: +1min, -1min, +5min, -5min. Rozsah frekvencie je od 1 do asi 80 Hz. Podľa tejto stránky by taký rozsah mal stačiť.
Nasleduje schéma zapojenia. Ak nepožaduješ meranie frekvencie a časovač, možno spodnú časť s AVR spolu s tranzistorom MOSFET a relé vypustiť. Použitý MOSFET tranzistor môže byť temer hocijaký tranzistor s kanálom typu N enhancement-mode. Ja som mal poruke 2SK2962, ale verím, že napr. 2N7000 by fungoval tiež. Malo by to fungovať aj s obyčajným NPN tranzistorom, ale potom treba pridať do bázy rezistor (neskúšal som).
Displej by mal byť so spoločnou anódou.
Pozor - tranzistor TIP122 sa pri vyšších frekvenciách zahrieva, je dobré dať mu aspoň malý chladič.
Napájanie je 5V DC zo sieťového adaptéra. Odber v špičkách (keď ide prúd do cievky) môže dosiahnuť až 1 A.
Ako som písal, o meranie frekvencie a časovač vypnutia sa stará mikrokontrolér Atmel ATmega8. Namiesto kryštála je použitý interný RC oscilátor na 8 MHz. Ušetrili sa dva piny a nepožaduje sa nejaká brutálna presnosť hodín MCU. Pri programovaní MCU treba poistky (fuses) nastaviť takto:
- HIGH: 0xD9
- LOW: 0xE4
A tu je komplet program.
#include "hw.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#define _BV(bit) (1 << (bit)) // _BV macro is not defined for atmega8 so define it here
// BTNx is 1 if respective button is pressed
#define BTN0() (bit_is_clear(PIND, 0))
#define BTN1() (bit_is_clear(PIND, 1))
#define BTN2() (bit_is_clear(PIND, 2))
#define BTN3() (bit_is_clear(PIND, 3))
#define SEC_MIN 0
#define SEC_MAX 99 * 60 + 59
volatile unsigned char freq1 = 0; // second digit of frequency display
volatile unsigned char freq10 = 0; // first digit of frequency display
volatile unsigned char activeseg = 0; // indicates active display segment (used for multiplexing)
volatile unsigned int sec = 20 * 60; // default timer countdown: 20min and counting down
volatile unsigned int btn0cycles = 0; // these 4 are here to support one-time push and push-and-hold on the buttons
volatile unsigned int btn1cycles = 0;
volatile unsigned int btn2cycles = 0;
volatile unsigned int btn3cycles = 0;
#define _s_A 0
#define _s_B 1
#define _s_C 2
#define _s_D 3
#define _s_E 4
#define _s_F 5
#define _s_G 6
#define _s_dot 7
const unsigned char segs[] =
{
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F), // 0
_BV(_s_B) | _BV(_s_C), // 1
_BV(_s_A) | _BV(_s_B) | _BV(_s_D) | _BV(_s_E) | _BV(_s_G), // 2
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_G), // 3
_BV(_s_B) | _BV(_s_C) | _BV(_s_F) | _BV(_s_G), // 4
_BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_F) | _BV(_s_G), // 5
_BV(_s_A) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), // 6
_BV(_s_A) | _BV(_s_B) | _BV(_s_C), // 7
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_E) | _BV(_s_F) | _BV(_s_G), // 8
_BV(_s_A) | _BV(_s_B) | _BV(_s_C) | _BV(_s_D) | _BV(_s_F) | _BV(_s_G), // 9
};
void addOrSubtractSeconds(int num)
{
int result = sec + num;
if (result >= SEC_MAX)
{
result = SEC_MAX;
}
else if (result <= SEC_MIN)
{
result = SEC_MIN;
}
sec = result;
}
int main(void)
{
unsigned int i = 0;
DDRB = 0xFF; // PD0-7 are outputs
DDRC = 0b00111111; // PC0-PC5 are outputs, PC6-PC7 are inputs (unused)
DDRD = 0b10000000; // PD7: output to drive relay, PD0-PD3: buttons input
// show empty display at the beginning
PORTB = 0xFF;
PORTC = 0xFF;
// PORTB: segments
// PORTC: common anodes
// TIMER0 configuration
TCCR0 |= _BV(CS01) | _BV(CS02); // configure clock source for TIMER0 on pin T0
// TIMER1 configuration
TIMSK |= _BV(TOIE1); // enable overflow interrupt
TCCR1B |= _BV(CS11); // configure prescaler to 8 and start timer
// TIMER2 (display multiplexing) configuration
TIMSK |= _BV(TOIE2); // enable overflow interrupt
TCCR2 |= _BV(CS21); // configure prescaler to 8 and start timer
sei(); // enable global interrupts
// turn on relay initially
PORTD |= _BV(7);
while (1)
{
// maximum that this code detects, is 255 Hz, then timer overflows - this is not handled here as I won't need it (maximum real world frequency is 99 Hz)
TCNT0 = 0;
_delay_ms(1000);
i = TCNT0;
freq1 = i % 10;
freq10 = i / 10;
// timer handling
if (sec != 0)
{
addOrSubtractSeconds(-1);
// turn on relay (useful if time was raised by buttons)
PORTD |= _BV(7);
}
else
{
// turn off relay
PORTD &= ~_BV(7);
}
}
}
// button handling
ISR(TIMER1_OVF_vect)
{
if (BTN0())
{
if (btn0cycles == 0 || btn0cycles > 10)
{
addOrSubtractSeconds(60);
}
btn0cycles++;
}
else if (BTN1())
{
if (btn1cycles == 0 || btn1cycles > 10)
{
addOrSubtractSeconds(-60);
}
btn1cycles++;
}
else if (BTN2())
{
if (btn2cycles == 0 || btn2cycles > 10)
{
addOrSubtractSeconds(60 * 5);
}
btn2cycles++;
}
else if (BTN3())
{
if (btn3cycles == 0 || btn3cycles > 10)
{
addOrSubtractSeconds(-60 * 5);
}
btn3cycles++;
}
if (!BTN0())
{
btn0cycles = 0;
}
if (!BTN1())
{
btn1cycles = 0;
}
if (!BTN2())
{
btn2cycles = 0;
}
if (!BTN3())
{
btn3cycles = 0;
}
}
// display multiplexing
ISR(TIMER2_OVF_vect)
{
if (activeseg == 5)
{
activeseg = 0;
} else {
activeseg++;
}
switch (activeseg)
{
case 0:
PORTB = ~segs[freq10];
PORTC = 1;
break;
case 1:
PORTB = ~segs[freq1];
PORTC = 2;
break;
case 2:
// sec1
PORTB = ~segs[sec % 10];
PORTC = 4;
break;
case 3:
// sec10
PORTB = ~segs[(sec % 60) / 10];
PORTC = 8;
// blinking double dot
if ((sec & 1) == 0 || sec == 0)
{
PORTB &= ~_BV(_s_dot);
} else {
PORTB |= _BV(_s_dot);
}
break;
case 4:
// min1
PORTB = ~segs[(sec / 60) % 10];
PORTC = 16;
// blinking double dot
if ((sec & 1) == 0 || sec == 0)
{
PORTB &= ~_BV(_s_dot);
} else {
PORTB |= _BV(_s_dot);
}
break;
case 5:
// min10
PORTB = ~segs[sec / 600];
PORTC = 32;
break;
}
}
Prístroj som vstaval do plastovej škatuľky. Je to vnútri dosť natesno, čomu som musel prispôsobiť aj plošný spoj. Ten si ale asi každý ľahko navrhne sám pre konkrétnu škatuľku, preto ho tu neuverejňujem.
Skúsenosti zatiaľ nemám žiadne, lebo kĺby ani chrbát ma veľmi často nebolia, ale vyskúšam to, keď náhodou začnú.
Žiaľ sa na internete nedokážem dopátrať technických informácií k magnetoterapii (je plný marketingových a predajných žvástov). Najmä odpovedí na otázky, ako:
- ako má vyzerať optimálna aplikačná cievka (jadro, počet závitov, indukčnosť, odpor)
- na aké ochorenia sú dobré aké frekvencie
- ako dlho a ako často aplikovať magnetoterapiu
Zdá sa, že firmy vyrábajúce tieto prístroje komerčne a predávajúce ich za stovky až tisíce eur, si to strážia ako svoje know-how.
Ak si postavíš tento prístroj, budem rád, ak mi napíšeš svoje skúsenosti, ktoré by som aj tu mohol uverejniť. V prípade nejasností alebo problémov pri stavbe rád poradím, stačí, keď odošleš komentár k tomuto článku cez formulár nižšie.