Eagle e PovRay, tippi e tricchi

Ho utilizzato per la prima volta Eagle, noto programma per la stesura di schemi elettronici e sbroglio dei relativi circuiti stampati, solo qualche settimana fa. Da ancora meno tempo ho installato Eagle 3d e Pov-Ray, che insieme servono per il rendering tridimensionale dei progetti, ragione per cui la stesura di una guida o tutorial che dir si voglia mi pare un vero azzardo; da qui la storpiatura di "Tips & Tricks" nel titolo. Tuttavia, dopo aver consultato alcuni documenti trovati in rete e cercato di tradurre quelli in inglese e tedesco, trovo interessante condividere i risultati raggiunti che riguardano alcune delle numerose possibilità di personalizzare il lavoro svolto da questi software.

Requisiti richiesti

I programmi utilizzati per la produzione delle immagini riportate in questa guida sono:

  • Eagle versione 6-3.0
  • Eagle3D versione 2011.11.01
  • Pov-Ray versione 3.7
Per evitare inutili doppioni di informazioni già facilmente disponibili riguardo la loro installazione e l'utilizzo di base, non tratterò questi argomenti, nè le procedure necessarie ad ottenere la prima immagine del progettoo in elaborazione, in quanto questo è solo il punto di partenza...

Il progetto

Lo schema utilizzato è relativo ad un tester per condensatori elettrolitici in grado di evidenziare quelli con ESR anomalo conseguente al deterioramento dell'elettrolita interno. Già in fase di sbroglio della scheda ho previsto la possibilità di realizzare il prototipo su millefori, quindi tutte le piste sono distanti 100 mils e hanno andamento ortogonale. Il layout risultante è questo:


L'immagine 3D

La realizzazione della prima immagine 3D del progetto si effettua nel consueto modo previsto da Eagle3D mandando in esecuzione la macro "3d50.ulp". In questo modo verrà generato un file con estensione ".pov" che, aperto con PovRay, porta a generare un file immagine della scheda.


Con i parametri standard, quindi senza nessuna personalizzazione, e dopo aver assegnato le corrette corrispondenze per i componenti non immediatamente riconosciuti, il risultato è questo:


Non male e piuttosto scenografico, ma lo sfondo bianco è tutto meno che fotorealistico... Dopo qualche verifica ho scoperto che il flag sulla casella "Sfondo immagine" della finestra di controllo non ha nessun effetto sul risultato finale. Indagando sulle cause inizio a familiarizzare con i files prodotti. Quello più importante è il file .pov, che contiene tutti gli elementi necessari per produrre l'immagine desiderata. La cosa interessante è che, essendo un formato testuale e -quasi- intelligibile, può essere modificato con un editor tipo blocco note, notepad plus e loro simili. Il mio consiglio è di salvare la copia originale del file .pov prodotto da Eagle3D e utilizzare direttamente PovRay per le modifiche e le prove. La struttura ricorda altri linguaggi di programmazione tipo C, basic... Si distinguono facilmente comandi, direttive, strutture condizionali, assegnazione di variabili.


Scorrendo il codice mi imbatto in questo blocco:
#if(e3d_environment=on)
 [.. codice]
#end
che in teoria applica o meno uno scenario di sfonfo in funzione della variabile e3d_environment. Per qualche motivo non viene riconosciuta o inizializzata correttamente; l'indagine si conclude con la constatazione che in circostanze come questa, dove l'obiettivo è il risultato e non l'eleganza formale, si fa prima a ricorrere alla forza bruta, forzando la decisione in questo modo:

#if(e3d_environment=on)
#else
sky_sphere {pigment {Navy}
pigment {bozo turbulence 0.65 octaves 7 omega 0.7 lambda 2
color_map
 {
  [0.0 0.1 color rgb <0.85, 0.85, 0.85> color rgb <0.75, 0.75, 0.75>]
  [0.1 0.5 color rgb <0.75, 0.75, 0.75> color rgbt <1, 1, 1, 1>]
  [0.5 1.0 color rgbt <1, 1, 1, 1> color rgbt <1, 1, 1, 1>]}
  scale <0.1, 0.5, 0.1>} rotate -90*x}
  plane{y, -10.0-max(pcb_x_size,pcb_y_size)*abs(max(sin((pcb_rotate_x/180)*pi),sin((pcb_rotate_z/180)*pi)))
  texture{T_Chrome_2D
  normal{waves 0.1 frequency 3000.0 scale 3000.0}} translate<0,0,0>}
#end

La chiave sta nel comando "#else" aggiunto nella seconda riga che forza la condizione controllata dalla prima riga escludendo di fatto il controllo sulla variabile e3d_environment. Avvio il rendering e si inizia a ragionare:


Personalizzare il risultato

Lo strano sfondo acquatico non si può considerare realistico nè gradevole, quindi incoraggiato dai primi risultati ho sostituito le righe che lo definiscono con l'intento di creare qualcosa di più familiare. Di solito utilizzo un piano di lavoro in rovere della varietà Pharloccus Laminatibus. . Dopo qualche prova il blocco di codice si è trasformato in

#if(e3d_environment=on)  
#else

plane{y, -10.0-max(pcb_x_size,pcb_y_size)*abs(max(sin((pcb_rotate_x/180)*pi),sin((pcb_rotate_z/180)*pi)))
pigment{ wood turbulence 0.01 octaves 4 lambda 3
scale 0.375  rotate <2, 3, 0> 
color_map {
       [0.0 color rgb <1.00, 0.88, 0.54>]
       [0.1 color rgb <1.00, 0.80, 0.54>]
       [0.5 color rgb <0.60, 0.42, 0.23>]
       [0.7 color rgb <0.50, 0.42, 0.23>]
       [1.0 color rgb <1.00, 0.88, 0.54>]
      }// end of color_map
   } // end of pigment
finish { phong 0.1 } 
rotate <0,90,0>  scale 10  translate <0,0,0>
}

#end
con questo risultato:


Le ombre sono troppo crude e la scheda galleggia in aria, ma a tutto c'è rimedio. E' possibile rendere l'utilizzo di questo sfondo la scelta predefinita modificando direttamente il file 3d50.ulp. Più precisamente sostituendo il blocco

string ambient =
	"#if(environment=on)\n"
	"sky_sphere {pigment {Navy}\n"
	"pigment {bozo turbulence 0.65 octaves 7 omega 0.7 lambda 2\n"
	"color_map {\n"
	"[0.0 0.1 color rgb <0.85, 0.85, 0.85> color rgb <0.75, 0.75, 0.75>]\n"
	"[0.1 0.5 color rgb <0.75, 0.75, 0.75> color rgbt <1, 1, 1, 1>]\n"
	"[0.5 1.0 color rgbt <1, 1, 1, 1> color rgbt <1, 1, 1, 1>]}\n"
	"scale <0.1, 0.5, 0.1>} rotate -90*x}\n"
	"plane{y, -10.0-max(pcb_x_size,pcb_y_size)*abs(max(sin((pcb_rotate_x/180)*pi),sin((pcb_rotate_z/180)*pi)))\n"
	"texture{T_Chrome_2D\n"
	"normal{waves 0.1 frequency 3000.0 scale 3000.0}} translate<0,0,0>}\n"
	"#end\n\n";
Con questo:
stribg ambient =
 "plane{y, -0.3-max(pcb_x_size,pcb_y_size)*abs(max(sin((pcb_rotate_x/180)*pi),sin((pcb_rotate_z/180)*pi)))\n"
 "pigment{ wood turbulence 0.01 octaves 4 lambda 3\n"
 "scale 0.375  rotate <2, 3, 0> \n"
 "color_map {\n"
 "      [0.0 color rgb <1.00, 0.88, 0.54>]\n"
 "      [0.1 color rgb <1.00, 0.80, 0.54>]\n"
 "      [0.5 color rgb <0.60, 0.42, 0.23>]\n"
 "      [0.7 color rgb <0.50, 0.42, 0.23>]\n"
 "      [1.0 color rgb <1.00, 0.88, 0.54>]\n"
 "     }// end of color_map\n"
 "  } // end of pigment\n"
 "finish { phong 0.1 } \n"
 "rotate <0,90,0>  scale 10  translate <0,0,0>\n"
 "}\n\n"
Che in pratica, alla sua esecuzione, inserisce il testo contenuto fra gli apici nel file .pov. La sequenza "\n" indica il tasto di invio/ritorno a capo. Nella produzione di un circuito stampato occorre rinunciare ad alcune chicche come serigrafia dei componenti e solder mask. Nel file .pov questi elementi sono definiti rispettivamente dal blocco

#if(pcb_silkscreen=on)
[...]
#end
e dalla texture chiamata "col_brd" in questo blocco:
//Scheda
prism{-1.500000,0.000000,8
<0.000000,0.000000><58.400000,0.000000>
<58.400000,0.000000><58.400000,60.630000>
<58.400000,60.630000><0.000000,60.630000>
<0.000000,60.630000><0.000000,0.000000>
texture{col_brd}}		<-------------------- CERCARE QUESTA STRINGA ---------------------------
}//End union(PCB)
//Fori(Real)/Componenti
//Fori(Real)/Scheda
La serigrafia può essere disattivata assegnando il valore "off" alla variabile apposita cercando la riga "#declare global_solder = on;" oppure ,come fatto in precedenza per lo sfondo, aggiungendo un "#else" nel blocco sopra riportato. Per simulare la vetronite ho modificato la riga "texture{col_brd}" con queste:
texture { pigment{ color rgb< 0.45, 0.57, 0.30> }  
          normal { bumps 0.5 scale 0.005 }
          finish { phong 0.1 reflection 0.05}
        } // end of texture
Naturalmente non ho inventato nulla, diversi tipi di materiali sono presenti nelle librerie di PovRay ed il codice che li definisce viene aggiunto al file .pov accedendo al menu a tendina "Insert - Textures and materials". Per simulare la vetronite ho cercato di ottenere un aspetto "fibroso" e applicato un colore verde salvia. Tutti i parametri sono modificabili, a partire da "color rgb" che definisce il colore base, "bumps" e "scale" che generano una certa irregolarità della superficie, "phong" e "reflection" che influiscono sulla finitura superficiale e sul grado di riflettività deella stessa. Con i parametri indicati il risultato è questo:


Via la serigrafia...


Luci
Su questo argomento c'è di che impiegare del gran tempo... Tutti sanno che un'ottima foto dipende molto dalla luce giusta. Anche la resa della nostra immagine non si sottrae a questa regola. Il codice che definisce i riflettori virtuali che illuminano la scheda è posto nella prima parte del file .pov:

#local lgt1_pos_x = 22;
#local lgt1_pos_y = 34;
#local lgt1_pos_z = 32;
#local lgt1_intense = 0.750583;
#local lgt2_pos_x = -22;
#local lgt2_pos_y = 34;
#local lgt2_pos_z = 32;
#local lgt2_intense = 0.750583;
#local lgt3_pos_x = 22;
#local lgt3_pos_y = 34;
#local lgt3_pos_z = -21;
#local lgt3_intense = 0.750583;
#local lgt4_pos_x = -22;
#local lgt4_pos_y = 34;
#local lgt4_pos_z = -21;
#local lgt4_intense = 0.750583;

In queste righe sono descritte quattro luci. I parametri associati ad esse sono le coordinate tridimensionali x,y,z e l'intensità di ciascuna. In un blocco successivo sono definiti gli attributi di colore (White) e la facoltà di generare ombre (l'opzione "shadowless" la inibisce):

light_source{ White*lgt1_intense}
light_source{ White*lgt2_intense}
light_source{ White*lgt3_intense shadowless}
light_source{ White*lgt4_intense}

Modificando questi elementi è possibile dare un aspetto più naturale all'immagine:


A questo punto è opportuno "appoggiare" sul tavolo virtuale la scheda evitando che galleggi in aria. Per questo è necessario tornare sulle righe che abbiamo precedentemente modificato e che definiscono il piano sottostante:

plane{y, -10.0-max(pcb_x_size,pcb_y_size)*abs(max(sin((pcb_rotate_x/180)*pi),sin((pcb_rotate_z/180)*pi)))

il numero "-10" indica l'elevazione del piano di legno nel sistema di coordinate. Sostituendolo con "-2" alziamo il piano fino a poco sotto il circuito stampato:


La manipolazione del codice contenuto nel file .ulp offre ulteriori interessanti possibilità. Ad esempio, l'espressione

#declare pcb_upsidedown = off;

si commenta quasi da sola; se poniamo la variabile a "on" rovesciamo la scheda visualizzando il lato saldature:


Il colore verde-solder mask non è molto "casalingo", negli stampati prodotti in casa le piste sono lasciate al naturale, color rame, o imbiancate di stagno per evitare che anneriscano con l'ossidazione. Anche per questo aspetto basta individuare la definizione del materiale e sostituirla con una di nostro gradimento. Ho individuato questa parte del codice nella espressione "texture{col_wrs}" che evidentemente significa color wires, cioè colore dei fili. Comunque sia, sostituendola con :
//----------------------- piste rame --------------------------------
texture { pigment{ color rgb< 0.85, 0.37, 0.25> }// light brown  
          normal { bumps 0.5 scale 0.5 }
          finish { phong 0.01 reflection 0.3}
        } // end of texture 

per simulare le piste in rame oppure con

//----------------------- piste stagnate ----------------------------
texture{ Silver_Metal
         finish { phong 1 }
         scale 0.5
         } // end of texture

si ottengono queste immagini
Non male no? Nella prima immagine ho "abbassato il tavolo" come spiegato in precedenza, nella seconda ho spostato le luci in modo da rendere visibili i componenti sottostanti. E' possibile intervenire su molti aspetti riguardanti i colori, le luci, la posizione degli oggetti, fino all'ottenimento di un risultato soddisfacente. Provare nuovi materiali, modificarne i parametri, cercare di intuire le conseguenze delle modifiche per avvicinare il risultato all'idea che ci siamo prefissati è perfino divertente. L'ultimo aspetto su cui mi sono soffermato riguarda l'inquadratura del progetto. La fotocamera virtuale è definita principalmente da:

#local cam_x = 0;
#local cam_y = 260;
#local cam_z = -139;
#local cam_a = 20;
#local cam_look_x = 0;
#local cam_look_y = -6;
#local cam_look_z = 0;

#local pcb_rotate_x = 0;
#local pcb_rotate_y = 0;
#local pcb_rotate_z = 0;

Neanche a dirlo, cam_x, cam_y e cam_z definiscono la posizione della camera nello spazio, cam_look_x/y/z la direzione verso la quale punta l'obbiettivo, mentre cam_a imposta l'angolo di apertura. Possiamo impostare la camera vicina all'oggetto con un angolo di apertura ampio (l'equivalente di un'ottica con focale molto corta) o viceversa porre la macchina lontana e usare un angolo piccolo, come si farebbe con un teleobbiettivo. Come se non bastasse, con i parametri pcb_rotate_x/y/z possiamo ulteriormente riposizionare la scheda.

Conclusioni
Modificare il file .pov direttamente dal programma PovRay è decisamente più efficace che generarlo ogni volta tramite Eagle3d e la sua schermata di controllo che, fra l'altro, non comprende diverse opzioni accessibli solo modificando il codice. Eagle3D rimane indispensabile per generare le istruzioni necessarie a definire i componenti, mentre per gli aspetti più "fotografici" conviene agire direttamente in PovRay. Se ultimate le modifiche avanza del tempo, si potrebbe addirittura pensare alla realizzazione pratica, passando dalla realtà virtuale a...


praz2004 chiocciola libero punto it