
Sistema de propulsió magnètica
Introducció
El primer que cal veure per a saber com funciona el meu sistema de levitació magnètica és com estan posats els electroimants a la via del tren. Ho podem veure a la següent imatge:
Com es pot observar, a la via hi ha els 12 imants, i aquests no arriben fins al final. Això és perquè el tren fa 14cm de llargada, i per això el centre del tren farà 7cm. És a dir, no cal que hi hagi electroimants els útilms 7cm de la via. Els electroimants estan separats 1cm i tenen un radi de 2cm. A les vies de dalt, hi ha 10 imants de ferrita FE-Q-40-20-10 a cada costat, també separats 1cm perquè es repel·leixen entre sí. El resultat final és un rectangle 52x9,4x3,8 sense tenir en compte els imants de ferrita a l'hora de calcular l'altura i els plàstics laterals (2mm de gruix cada un) a l'hora de calcular l'amplada.
Muntatge
Per a muntar això vaig comprar la fusta i els plàstics al Servei Estació. El primer que vaig fer va ser dividir la base de la via en parts per a veure on havien d’anar els electroimants. Un cop fet i comprovat que tot quadrava, vaig fer els forats per a posar els electroimants als seus llocs corresponents. Després els hi vaig posar tots, fixant-los amb un clau i posant-los de manera que tots els cables miressin cap al mateix costat per a que fos més senzill agrupar-los i que ocupessin menys. Vaig soldar-los amb cables (vermell positiu i negre negatiu) per a que tots arribessin a la placa de proves. Vaig fer una trena amb els cables de cada electroimant i després una de més gran amb tots els cables (posant abans un paper indicant el número de l’electroimant per a poder-los reconèixer més fàcilment). Seguidament vaig agafar els llistons i els vaig enganxar, de manera que em quedava el que necessitava (52x9,4x33), i encara que no em quedava un bloc massís de fusta, ja m’anava bé que tingués forma de perfil angular, per a poder-hi passar els cables dels electroimants per sota.
Experimentació
Aleshores vaig començar a provar coses amb els imants. Vaig connectar-ne un a una bateria de 12V i 0,8A, i vaig veure que creava un camp magnètic molt petit i poc potent. Quan hi apropava una moneda de cinc cèntims aquesta havia d’estar molt a prop per a sentir-se atreta amb força. Per sort, vaig pensar de fer les proves amb els imants amb un transformador de 12V i 1,5A per a no gastar la bateria, i el que vaig veure em va ajudar molt. L’electroimant tenia un camp magnètic més fort que abans, de manera que pel que semblava si augmentava l’amperatge de l’electroimant aquest tenia un camp magnètic més fort. Per això, em vaig comprar un transformador de 12V i 5A:
També vaig fer més proves, com posar un imant de ferrita a sobre un electroimant. El que a mi em semblava notar, és que quan l’electroimant estava encès, la força entre ells era més gran que quan no ho estava. I, si canviava l’ordre dels cables de l’electroimant (canviava la polaritat d’aquest), la força entre l’imant i l’electroimant disminuïa, però no es repel·lien. Semblava que la polaritat de l’electroimant feia una força que es sumava a la força entre l’imant de ferrita i el material de l’electroimant.
Com que amb números és més fàcil entendre-ho, aquí hi ha un exemple (les dades no són reals):
La força entre l’imant de ferrita i l’electroimant és de 2000N
La força que genera el camp magnètic a un element que està en contacte amb ell (distància 0) és de 300N, i aquests són positius o negatius depenent de la polaritat de l’electroimant.
-Si l’electroimant té la polaritat oposada a l’imant de ferrita, la força entre ells es suma:
2000+300=2300N
-En canvi, si la polaritat de l’electroimant és la mateixa que la de l’imant de ferrita, la força de l’electroimant es resta a la de l’imant:
2000-300=1700N
Per això, vaig veure que no podia posar un S-08-30-N, ja que faria una força molt més gran que no la dels electroimants. Per això vaig decidir que faria servir un nou mètode per a que els electroimants propulsessin el tren. El que faria seria posar un imant de neodimi W-05-N amb els pols perpendiculars als electroimants. Tots els electroimants tindrien la mateixa polaritat, de manera que l'imant de davant del cub de neodimi tingués la polaritat oposada a la del cub (l'atreuria) i l'electroimant del darrera tindria la mateixa que la de l'altra banda del cub, de manera que es repel·lerien.
Com es pot veure en aquesta imatge, tots dos electroimants tenen la mateixa polaritat (l'altra part del camp magnètic està sota l'electroimant), i això fa que un atregui l'imant del tren, i l'altre el repel·li. Un cop ha arribat al final de la via, es canvia la polaritat de tots els electroimants, de manera que el que abans el repel·lia ara l'atrau i viceversa. Un cop fet això, només em faltava fer una cosa abans d'entrar al món de l'electrònica: els frens.
Frens
Fer això és difícil, principalment perquè els imants de ferrita que hi ha al tren són molt prims, la qual cosa vol dir que és molt fàcil que un camp magnètic que teòricament afecta a una polaritat afecti a les dos, i no obtinguem el resultat desitjat.
En aquestes dos imatges podem veure dos sistemes de fre diferents. Al primer, passa el que he dit abans, el tren s'aixeca molt fàcilment de manera que la part (2) de l'imant de ferrita queda enganxada a la part (1) de l'imant de neodimi. En canvi, al segon això és més difícil, ja que l'imant de neodimi està més lluny. Això obviament afecta la capacitat de fre, però és la millor solució que he pogut trobar.
Per a fer el meu fre, he enganxat dos S-10-20-N paral·lels a les vies a la fusta del final de la via. S'ha de vigilar perquè si el tren s'apropa massa, la força de repulsió fa que aquest es quedi fixat i li costi molt de moure's. El sistema es pot veure en el següent vídeo:
Com es pot observar, hi ha un contrapès al tren, ja que la columna central el desequilibra.
Electrònica
Per a automatitzar el sistema de propulsió, necessitava diferents components electrònics. El més important era un Arduino UNO, el qual rebria la distància que li donaria el sensor i la processaria per a saber quins electroimants encendre. Lògicament, necessitaria un sensor, el qual vaig escollir infrarroig ja que d'aquesta manera necessitava molta menys superfície en la qual rebotar que un sensor d'ultrasons. També necessitava una placa de proves per a poder-hi posar tots els cables, i finalment una placa amb setze relays, per a poder fer un sistema que em permetés encendre i apagar els electroimants individualment i poder canviar la seva polaritat.
Sensor de distància Sharp
El sensor que em vaig comprar per a mesurar la distància del tren era el Sharp GP2Y0A21YK0F, el qual era analògic i funcionava amb infrarrojos. Quan feia proves amb ell, veia que no era massa precís, i quan posava alguna cosa davant seu a menys de 6cm les dades que donava no s'assemblaven en res a la realitat. Buscant per internet, vaig veure una gràfica molt interessant on es podia veure la seva precissió segons la distància real:
També s'hi veia que si posaves paper blanc era més precís, i per això vaig posar un paper blanc, en comptes de fusta. Un cop fet això, encara no era massa precís (fallava entre 1 i 2cm). El seu codi era el següent:
(6762/(analogRead(distance_sensor_pin)-25))-4
Intentava modificarla per a que fos més precís, canviant el -4 per -3 o -2, però aleshores ho feia bé a distàncies curtes (fins a 20cm) i a distàncies llargues fallava per 1cm o 2cm. Aleshores el que vaig decidir va ser provar de fer la funció tota nova, a partir de dades que jo vaig agafar. El que vaig fer va ser modificar el codi del sensor per a que em donés el que realment llegia (voltatge), i apuntava la distància real a la que estava el tren. El que deia el sensor anava variant, i per això vaig decidir apuntar els extrems d'aquests valors. D'aquesta manera, tenia dos punts per on havia de passar la gràfica aproximadament. Vaig posar aquests punts a desmos, i també hi vaig posar la funció original.
Com es pot veure a la gràfica, la funció original (la segona) no és massa precisa. Savent que la funció 1/x té una forma similiar, vaig fer una regla de tres agafant un punt mig, el 156.5: Algun nombre dividit per 156,5 (x), ha de donar 39,5 (f(x)). El resultat donava 6181. Aquesta funció (f(x)=6181/x) era més precissa que la original, però tot hi així hi havia dos punts ((600, 9.5) i (609, 9.5)) a on no hi passava pel mig. Vaig provar de restar nombres a la funció per a que passés pel mig dels dos punts, i 1/2 va semblar el més adient.
Ara ja tenia un problema solucionat, però encara me'n quedava un altre, i és que el sensor a vegades donava dades fora del que era normal (fins a 10cm d'error), i al cap d'un instant tornava a donar les dades normals. Vaig agafar unes distàncies que va medir com a mostra i en vaig fer una gràfica:
Com es pot veure, hi ha un d'aquests errors de tant en tant. És curiós, ja que sembla un cardiograma, i la veritat és que no sé quina pot ser la causa d'això. Tot i així, potser podia fer una funció amb l'arduino que anul·lés aquestes variacions en la distància donada pel sensor.
Per a fer això vaig escriure el següent:
int last_readings[50];
Aquí el que faig es crear una array de 50 places.
int count = 1;
S'estableix la variable "count" i es diu que aquesta és igual a 1.
void loop() {
readSensor();
delay(1);
Aquí determino que la funció "readSensor" s'executarà un cop cada 0,001 segons.
int calcDistance(){
return (6181/analogRead(distance_sensor_pin))+1;
//return analogRead(distance_sensor_pin);
//return base_offset+train_offset+(6762/(analogRead(distance_sensor_pin)-25))-4;
}
Aquesta és la funció que ens dona la distància en cm.
void readSensor(){
shiftLeft(last_readings, calcDistance());
}
Cada cop que s'executa "readSensor", es desplaça tots els valors de la array "last_readings"una posició a la dreta, i a la plaça lliure (la primera) s'hi posa el resultat de la funció "calcDistance".
int realDistance(){
int i = 49;
int count = 0;
while(i>=0){
count += last_readings[i];
i--;
}
return (count)/50;
}
La funció "realDistance" el que fa és sumar tots els valors que hi ha a la array "last_readings", i després dividir el resultat ("count") entre 50. Això és la mitjana de tots els valors que hi ha a la array, de manera que no hi ha les irregularitats que hi havia abans.
int shiftLeft(int input[], int add){
int i = 49;
while(i>=0){
input[i+1] = input[i];
i--;
}
input[0] = add;
}
La funció "shiftLeft" el que fa és desplaçar totes les dades de la array una posició cap a la dreta, deixant la primera lliure.
Aquest codi només té un problema encara que no fa cap mal, i és que quan s'encén l'Arduino, els primers 0,05 segons la array no està tota plena. Això fa que els primers valors de la funció "realDistance" siguin molt petits i vagin creixent fins a arribar a la distància real. El resultat de tot això és que quan encéns l'Arduino, totes les relays es van encenent com un efecte dominó fins a arribar a les que realment han d'estar enceses.
Relay
La relay és l'element electrònic que em permet encendre i apagar els electroimants quan ho necessito, i també em permet canviar la seva polaritat. Jo tinc una placa amb setze relays, dels quals n'utilitzo catorze: 2 per al canvi de polaritat i 12 per a cada electroimant.
El que es pot veure en aquesta imatge és l'esquema d'una relay. El quadrat que hi ha entre A2 i A1 és un electroimant que s’activa quan hi passa la corrent, i al activar-se el que fa és crear un camp magnètic que atreu el cable que abans estaba tocant el fil 14 (corrent de 11 a 14), ara toqui el fil 12 (corrent de 11 a 12). Això pot ser molt útil amb un Arduino, perquè pots fer que passi corrent per un circuit només quan tu vulguis (al fer que passi corrent al pin que tinguis connectat amb la relay).
Com es pot veure en aquesta imatge, tots els cables blaus estàn connectats entre sí. Aquests són els que es connecten quan el cable central canvia de posició degut a a l'lelectroimant, i es connecten a la part positiva de la placa de proves. Els cables grocs es connecten amb la part positiva dels electroimants, i la part negativa dels electroimants a la part positiva de la placa de proves, de manera que quan l'Arduino activa una relay, aquesta tanca el circuit amb el seu electroimant, i aquest s'encèn.
Posició dels cables:
Per a que els cables arribéssin a tot arreu, vaig col·locar els cables que uneixen els pins de l'Arduino amb les relays d'una manera una mica estranya. Els pins 0 i 1 estan connectats amb les relays 11 i 12, els pins 2 i 3 amb les relays 13 i 14 (les que canvien la polaritat del sistema), i la resta de pins connecten de la següent manera: 4-10, 5-9, 6-8... i finalment 13-1.
Per a que l'Arduino pugui saber quin electroimant encendre, hi ha el següent codi:
int magnetWrite(int magnet, int state){
if(magnet>12){ return 0; }
if(magnet<1) { return 0; }
int start_magnet = 13;
int real_pin = 0;
if(magnet>10){
real_pin = start_magnet-magnet-1;
}else{
real_pin = start_magnet-(magnet-1);
}
digitalWrite(real_pin, state);
}
Al principi s'stableix que "magnetWrite" serà igual a aquesta funció, i aquesta el que fa és calcular quin és el pin de l'imant.
Establint imants
void setup() {
//MAGNETS
int pin = 13;
while(pin>=0){
pinMode(pin, OUTPUT);
pin--;
}
}
El que fa quest codi a l'inici de l'execució del programa és anar establint els pins com a OUTPUT d'un en un.
Canvi de direcció
boolean going_forward = true;
boolean out_of_border = true;
boolean inverted_polarity = false;
boolean inverted_polaritys = false;
void loop(){
...
if(magnet == 1 || magnet==12){
if(out_of_border){
invertPolarity();
out_of_border = false;
}
}else{
out_of_border = true;
}
...
}
void invertPolarity(){
if(inverted_polaritys == true){
digitalWrite(r_polarity_positive_pin, LOW);
digitalWrite(r_polarity_negative_pin, HIGH);
inverted_polarity = false;
inverted_polaritys = false;
}else{
digitalWrite(r_polarity_positive_pin, HIGH);
digitalWrite(r_polarity_negative_pin, LOW);
inverted_polarity = true;
inverted_polaritys = true;
}
}
Aquest codi el que fa és canviar la polaritat del sistema quan detecta que el tren esta en la posició 1 o 12.
Posició tren
int lines[12] = {38, 35, 32, 30, 27, 24, 21, 18, 15, 12, 10, 9};
int magnet = getCurrentMagnet();
magnetWrite(magnet, HIGH);
magnetWrite(magnet+1, HIGH);
int getCurrentMagnet(){
int distance = realDistance();
int i = 1;
while(i <= 12){
magnetWrite(i, LOW);
i++;
}
i = 0;
while(i < 12){
if(distance >= lines[i]){
return 12-i;
}
i++;
}
}
Aquest codi el que fa és dir la posició d'un imant segons unes distàncies predeterminades de l'array "lines", i activar aquest i el del seu costat. Es pot veure en el següent vídeo:
Al final, al provar si el tren funcionava, vaig notar que era més fàcil fer-lo avançar, però no podia posar-se en moviment per si sol, ja que els electroimants no són prou potents.
Codi final
int distance_sensor_pin = 0;
int r_polarity_positive_pin = 2;
int r_polarity_negative_pin = 3;
boolean inverted_polaritys = false;
int last_readings[50];
boolean going_forward = true;
boolean out_of_border = true;
boolean inverted_polarity = false;
int count = 1;
int lines[12] = {38, 35, 32, 30, 27, 24, 21, 18, 15, 12, 10, 9};
void setup() {
//MAGNETS
int pin = 13;
while(pin>=0){
pinMode(pin, OUTPUT);
pin--;
}
}
void loop() {
readSensor();
delay(1);
int magnet = getCurrentMagnet();
if(magnet == 1 || magnet==12){
if(out_of_border){
invertPolarity();
out_of_border = false;
}
}else{
out_of_border = true;
}
magnetWrite(magnet, HIGH);
magnetWrite(magnet+1, HIGH);
}
int getCurrentMagnet(){
int distance = realDistance();
int i = 1;
while(i <= 12){
magnetWrite(i, LOW);
i++;
}
i = 0;
while(i < 12){
if(distance >= lines[i]){
return 12-i;
}
i++;
}
}
int calcDistance(){
return (6181/analogRead(distance_sensor_pin))+1;
//return analogRead(distance_sensor_pin);
//return base_offset+train_offset+(6762/(analogRead(distance_sensor_pin)-25))-4;
}
int magnetWrite(int magnet, int state){
if(magnet>12){ return 0; }
if(magnet<1) { return 0; }
int start_magnet = 13;
int real_pin = 0;
if(magnet>10){
real_pin = start_magnet-magnet-1;
}else{
real_pin = start_magnet-(magnet-1);
}
digitalWrite(real_pin, state);
}
void readSensor(){
shiftLeft(last_readings, calcDistance());
}
int realDistance(){
int i = 49;
int count = 0;
while(i>=0){
count += last_readings[i];
i--;
}
return (count)/50;
}
void printArray(){
int i = 0;
while(i<50){
Serial.print(last_readings[i]);
Serial.print(",");
i++;
}
Serial.println("");
}
int shiftLeft(int input[], int add){
int i = 49;
while(i>=0){
input[i+1] = input[i];
i--;
}
input[0] = add;
}
void invertPolarity(){
if(inverted_polaritys == true){
digitalWrite(r_polarity_positive_pin, LOW);
digitalWrite(r_polarity_negative_pin, HIGH);
inverted_polarity = false;
inverted_polaritys = false;
}else{
digitalWrite(r_polarity_positive_pin, HIGH);
digitalWrite(r_polarity_negative_pin, LOW);
inverted_polarity = true;
inverted_polaritys = true;
}
}




1
1
1
2


1
1
2
2
1
1
2
2






