vineri, 18 aprilie 2014

Semafor australian / Victorian traffic light (Australia)

English: I built a nice Australian 6-aspects traffic light, based on a video clip found on YouTube (at the bottom of this post you can watch it too). I used a PIC16F628A microcontroller, simple 12V bulb lights and 6 pieces of N-channel MOS-FET.
Microcontroller was done in C language using mikroC compiler, I used a clone of ICD2 programmer and MPLAB IDE (code is also below) using following tutorial.
I had to put all the lights into a plastic case, to color some filters and here we go! 

**********
Am construit pentru cineva un semafor care functioneaza asa cum este in clipul video urmator:





Sursa de inspiratie a fost un alt semafor, gasiti clipul video cu el la finalul acestui articol. Din comentariile legate de acest semafor, am aflat ca este un semafor victorian din Australia (unde circulatia este pe stinga, din acest motiv are sagetile la dreapta). Am masurat timpii fiecarei culori, succesiunea lor, am conceput lucrurile si m-am pus pe treaba. am modificat putin culoarea verde, in sensul ca am la ultimile 3 secunde, clipeste de 3 ori, apoi se schimba in galben. E mai interesant asa :)

Ideea e ca un semafor este simplu de implementat cu un microcontroler. Asa ca am ales un PIC16F628A, are oscilator intern (suficient de precis pentru aplicatia cu semafor), are pini suficienti pt cele 6 culori, am lantul de programare pentru el (MPLAB IDE + clona de ICD2).

Costul fiind un argument important, nu am sarit calul alegand LEDuri de putere (cred ca 6 LEDuri de putere ar fi costat undeva la 20-30$, desi ma scapa de problema culorilor si a intensitatii luminoase), asa ca a fost mai ieftin sa folosesc becuri de lanterna de 12V si 0,1A. Becurile au fost montate in soclurile corespunzatoare. Apoi aceste socluri au fost puse in niste dopuri de teava de plastic de canalizare (de 5cm diametru).

Pentru o luminozitate mai buna am tapetat interiorul acestor dopuri cu folie de aluminiu.

 

Cel mai complicat mi s-a parut sa fac culorile semaforului. Pina la urma am decupat bucati din niste capace de plastic transparent (PET) de la ambalaje, erau la reciclare. Am taiat bucata potrivita pentru a intra in cutie, apoi am dat un hirtie abraziva fina peste acest platic transparent si in scurt timp a devenit translucid. A urmat colorarea: la rosu si la verde am folosit marker de culoare rosie si verde, la galben am folosit o bucata de folie galbena de la un dosar de plastic. Marckerul negru a folosit pt a desena sagetile peste culorile din dreapta.





 Am luat o cutie de plastic pentru conexiuni electrice, am masurat si am taiat 6 gauri de 5cm diametru, am finisat cu hirtie abraziva, apoi am vopsit capacul cu vopsea neagra.


Am taiat o bucata de spuma (PE) de ambalaj si tot de la reciclare luata - de forma capacului, apoi am dat 6 gauri sa poata intra cele 6 capace cu becuri si sa fie tinute fix in spatele culorilor.



Ca si picior, am folosit o teava de plastic de canalizare tot de 5cm diametru, jos am avut la indemina tija filetata pe care am dispus-o la 90 de grade. In capete am pus resturile de spuma, este stabil.



Acum partea electronica: cum becurile sunt de 12V si micrcontrolerul PIC16F628A functioneaza bine la 5V :) (peste 5V exista riscul sa iasa fumul magic din el si sa nu mai functioneze, mult sub 5V focul din el nu se aprinde astfel incat sa se faca fum magic), am avut nevoie de ceva ce sa imi furnizeze 5V, am ales un modul in comutatie cu tensiune de iesire reglabila. Deci bagi 12V, ies 5V, cadere de tensiune mica pe el etc.


Am folosit un alimentator simplu de la priza de 220Vac la 12Vdc.

Cum becurile sunt la 12V, fiecare bec este interfatat printr-un tranzistor MOS-FET (IRF7303) cu pinii microcontrolerului PIC16F628A (pini care dau semnale de 5V maxim), schema arata in felul urmator:



Am folosit oscilatorul intern pe 4MHz al micrcontrolerului PIC16F628A, setarile din mikroC sunt ca mai jos:

.
Urmarind timpii si succesiunea culorilor, programarea e un simplu sir de pauze (delay) urmate de schimbarea starii pinilor (0 sau 1 logic). Se putea face si cu intreruperi, mai multe contoare numara jumatatile de secunda (500ms) si la anumite valori schimba starea pinilor portului B, dar nu am avut timp sa socotesc, asa ca am adoptat solutia cu delay (microcontrolerul nu face altceva, deci poate rula nop-uri la infinit :)  ). Codul sursa se gaseste mai in jos in acest articol.

Ar fi fost interesant sa fac trecerea de la rosu la verde prin aprinderea galbenului pentru 2 secunde sa spunem, dar ramine ca idee (am facut verde clipitor pe ultimile 3 secunde cat sta verdele aprins, apoi vine galben si apoi rosu).

Programarea am realizat-o urmarind pasii de aici

Semaforul la final, vedeti mai jos:

Piciorul semaforului dintr-o teava de scurgere de 5cm (plastic)

Conectarea cablului de alimentare

Conectarea cutiei la piciorul suport



Semaforul alimentat, in stare de functionare




Si aici filmul cu semaforul dupa care m-am inspirat (dupa cum se vede e mai mare, de inaltimea unui birou):




Codul sursa in mikroC:

***************inceput cod in mikroC*************

void main()
{                                            // Main;
 CMCON |=7;                                  // All I/O pins are configured as digital;
 TRISB = 0;                                  // All port B pins are configured as outputs;
 PORTB = 0x00;                               // Initial logic state on port B pins ;


//verde
 PORTB.B2 = 1;
 Delay_ms(500);
 PORTB.B2 = 0;
 Delay_ms(500);

//galben
 PORTB.B1 = 1;
 Delay_ms(500);
 PORTB.B1 = 0;
 Delay_ms(500);

//rosu
 PORTB.B3 = 1;
 Delay_ms(500);
 PORTB.B3 = 0;
 Delay_ms(500);

//rosu-s
 PORTB.B0 = 1;
 Delay_ms(500);
 PORTB.B0 = 0;
 Delay_ms(500);

//galben-s
 PORTB.B4 = 1;
 Delay_ms(500);
 PORTB.B4 = 0;
 Delay_ms(500);

//verde-s
 PORTB.B5 = 1;
 Delay_ms(500);
 PORTB.B5 = 0;
 Delay_ms(1000);

PORTB = 0xFF;
Delay_ms(500);
PORTB = 0x00;
Delay_ms(500);
PORTB = 0xFF;
Delay_ms(500);
PORTB = 0x00;
Delay_ms(2000);


while (1) {       // Endless loop;
           PORTB.B1 = 0;
           PORTB.B3 = 0;
           PORTB.B4 = 0;
           PORTB.B5 = 0;

           PORTB.B2 = 1;
           PORTB.B0 = 1;
           Delay_ms(7000);
          
           //start verde intermitent
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           //stop verde intermitent
          
           PORTB.B2 = 0;
           PORTB.B1 = 1;
           Delay_ms(5000);
           PORTB.B1 = 0;
           PORTB.B3 = 1;
           Delay_ms(20000);
           PORTB.B0 = 0;
           PORTB.B5 = 1;
           Delay_ms(17000);
          
           //start verde sageata intermitent
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           //stop verde sageata intermitent

           PORTB.B5 = 0;
           PORTB.B4 = 1;
           Delay_ms(5000);
           PORTB.B4 = 0;
           PORTB.B0 = 1;
          
           Delay_ms(5000);
           PORTB.B3 = 0;
           PORTB.B2 = 1;
           Delay_ms(17000);
          
           //start verde intermitent
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           //stop verde intermitent
          
           PORTB.B2 = 0;
           PORTB.B1 = 1;
           Delay_ms(5000);
           PORTB.B1 = 0;
           PORTB.B3 = 1;
           Delay_ms(20000);
           PORTB.B3 = 0;
           PORTB.B0 = 0;
           PORTB.B2 = 1;
           PORTB.B5 = 1;
           Delay_ms(7000);
          
           //start verde sageata intermitent
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           //stop verde sageata intermitent
          
           PORTB.B5 = 0;
           PORTB.B4 = 1;
           Delay_ms(5000);
           PORTB.B4 = 0;
           PORTB.B0 = 1;
           Delay_ms(7000);
          
           //start verde intermitent
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           //stop verde intermitent

           PORTB.B2 = 0;
           PORTB.B1 = 1;
           Delay_ms(5000);
           PORTB.B1 = 0;
           PORTB.B3 = 1;
           Delay_ms(15000);
           PORTB.B0 = 0;
           PORTB.B5 = 1;
           Delay_ms(12000);
          
           //start verde sageata intermitent
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           PORTB.B5 = 0;
           Delay_ms(500);
           PORTB.B5 = 1;
           Delay_ms(500);
           //stop verde sageata intermitent
          
           PORTB.B5 = 0;
           PORTB.B4 = 1;
           Delay_ms(5000);
           PORTB.B3 = 0;
           PORTB.B2 = 1;
           Delay_ms(5000);
           PORTB.B4 = 0;
           PORTB.B0 = 1;
           Delay_ms(7000);
          
           //start verde intermitent
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           PORTB.B2 = 0;
           Delay_ms(500);
           PORTB.B2 = 1;
           Delay_ms(500);
           //stop verde intermitent

           PORTB.B2 = 0;
           PORTB.B1 = 1;
           Delay_ms(5000);
           PORTB.B1 = 0;
           PORTB.B3 = 1;
           Delay_ms(15000);

          }                                // End while;
}                                            // End main

***************sfarsit cod in mikroC*************


Spor la treaba! :)