Sari la conținut
ELFORUM - Forumul electronistilor

Mini-barieră cu sunet, circuit basculant și coborâre lentă


Ssarmiss

Postări Recomandate

Smoala dizolvata in gaz (petrol lampant), trasarea cu ac de seringa scurtat la 6-7 mm si cu o sarma-lita in interior. Asta prin 1965...

Diagrama.png

Editat de Ticu
Link spre comentariu

Doamne... 1965...  M-aș întoarce în timp pentru câteva zile; mă uit, când prind, la rubrica PROTV „100 de ani în 100 de zile” și mi-ar plăcea să fie mai lungă, mai detaliată.

 

Mulțumesc pentru lămurire, acum îmi e clar că dreptunghiul pozitiv timp de T2 al monostabilului este unul singur pe perioada unui dreptunghi T1 al astabilului. Când astabilul e zero, nici nu putem vorbi de monostabil. Îmi era să nu se repete T2 pe toată durata semi-perioadei pozitive a T1.

Link spre comentariu

Bun... dupa indelungi intarzieri, iata o versiune preliminara a programului, testata in graba si merge dar care va suferi imbunatatiri.

Pun sursa compilata cu AVRstudio7, daca se doreste se poate recompila fisierul main.c cu un alt compilator.

Pentru incarcare in Arduino se foloseste programul Xloader, si se incarca bineinteles fisierul bariere.hex

 

Pentru a nu intarzia prea mult, am eliminat pe moment semafoarele, si le voi adauga intr-un moment ulterior.

Voi adauga si lumina alba clipitoare dar inca nu am decis la ce pin sa o leg.

Pana acum:

intrerupatorul la PC0, Arduino A0

servo dreapta la PB1, Arduino D9

servo stanga la PB2, Arduino D10

sunet la PB5, Arduino D13 (asta e legata si la un led pe placa deci chiar daca nu este legata placa de sunet, se vede ca se activeaza)

semafor A la PD6, Arduino D6

semafor B la PD5, Arduino D5

 

lumina alba clipitoare este posibil sa o leg la PD3, care este pinul Arduino D3.

 

Acum e tarziu, voi continua cu semafoarele maine sau poimaine, sunt in urma cu mai multe proiecte si nu reusesc sa gasesc timp decat seara tarziu.

Proiectul

bariere.7z

 

Aaaaa, uitasem, pentru a micsora vibratiile servo, se poate ridica frecventa de la 50Hz pana la 100Hz, eu am remarcat o mica imbunatatire dar cu un program mic de test, acesta de acum nu l-am testat decat la 50Hz.

 

pentru o privire rapida pe cod:

#define F_CPU 16000000UL							// frecventa de lucru a procesorului


#include <avr/io.h>
#include <avr/interrupt.h>


#define JosStanga			4800						
#define Sus					3000						
#define JosDreapta			1200

#define avans_sunet_max		4000					// numarul aproximativ de milisecunde de cand porneste sunetul pana cand incep sa se lase barierele


#define start_coborare		1
#define coborare			2
#define ridicare			3
#define switch_debounce		4
#define semafor				5


unsigned short miscare=0;								// bit0=nimic, bit1=start_coborare, bit2=coborare, bit3=ridicare, bit4=switch_debounce, bit5=semafor
unsigned short divizor_timer=0;		
unsigned int acum_stanga, acum_dreapta;	
unsigned short debounce=0;	
unsigned int avans_sunet=0;
		

ISR(TIMER0_OVF_vect) {									// aceasta rutina se executa de aproape 1000 ori pe secunda, putem aproxima la fiecare milisecunda
						divizor_timer++;
						if (miscare&(1<<switch_debounce)) debounce++;	
						if (miscare&(1<<start_coborare)) avans_sunet++;
						
						if (divizor_timer>2){							// dividem cu 3 numarul de overflows, obtinem cam o executare la 3ms
																		// in cazul nostru dorim miscarea barierelor cu 90° cam in 6 sec., deci 2000 unitati PWM in 6sec adica 1 unitate la fiecare 3ms
	
			
										if (miscare&(1<<coborare)) {				// daca suntem in mod coborare bariere
														if (acum_dreapta>JosDreapta)	{		// daca dreapta nu a coborat complet
																				acum_dreapta--;				// dreapta se lasa jos prin decrementare
																				OCR1A = acum_dreapta;
																						}
															else if(acum_stanga<JosStanga) {acum_stanga++; OCR1B = acum_stanga;}	// stanga se lasa jos prin incrementare	
																	}	
														
										if (miscare&(1<<ridicare))	{
																	if(acum_dreapta<Sus) {acum_dreapta++; OCR1A=acum_dreapta;}	// dreapta se ridica prin incrementare
																	if(acum_stanga>Sus) {acum_stanga--; OCR1B=acum_stanga;}		// stanga se ridica prin decrementare
																	}
														
							
											divizor_timer=0;
											}		
						}		// end interrupt



void init (void)	{
	DDRB |= (1<<PB1)|(1<<PB2)|(1<<PB5);				// servo dreapta la D9, servo stanga la D10, iesire sunet la D13
	PORTB = 0;
	
	DDRD |= (1<<PD6)|(1<<PD5);						// semafor A PD6, semafor B PD5
	PORTD=0;
	
	PORTC |= (1<<PC0);							// activam pull-up pentru intrarea de control, A0

	TCCR1A |= (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11); // PWM, ne-inversat, iesirea setata 1 la "bottom"=0, setata 0 la OCR1A, timerul se reseteaza la "top"=ICR1
	TCCR1B |= (1<<WGM13)|(1<<WGM12) ; // continuare
	// pentru a obtine frecventa de 50HZ, utilizam divizor N=8 pt. Timer1clock si valoare TOP=39999  Fpwm=Fclk/(2*N*(1+top))  , Fclk=16000000
	// ==> Timer clock = 1MHz => pentru 1ms sunt necesari 1000 cicli clock, 2ms -> 2000.


	ICR1 = 39999;						// ICR1 = TOP = 39999, limita maxima de cicli la care timerul este resetat (de fapt TOP+1)
										// scadem la 29999 pentru frecventa servo 75Hz sau la 19999 pentru frecventa servo 100Hz
										
	OCR1A = 3000;						// pornim cu barierele sus
	OCR1B = 3000;
	
	TCCR1B |= (1<<CS11);				// pornim timerul cu frecventa 2MHz (clk/8)
	
	
	TCCR0B |= (1<<COM0A1)|(1<<COM0B1)|(1<<WGM01)|(1<<WGM00);	// timer0 fast PWM (976Hz cu divizor clk/64), necesar pentru modularea semaforului
	TCCR0B |= (1<<CS01)|(1<<CS00);								// pornim timer0 cu divizor64, ceea ce va produce 976 overflows pe secunda, durata intre 2 overflow aproximativ 1ms
	OCR0A = 0;
	OCR0B = 0;													// momentan iesirile le lasam la zero
	TCNT0 = 0;													// resetam T0 pentru a intarzia o eventuala intrerupere
	TIMSK0 |= (1<<TOIE0);										// activam intreruperea la overflow dar nu va functiona pana cand nu setam I-bit in status register				
																	
	sei();														// acum setam I-bit si activam intreruperea T0_overflow
					}



int main(void)
{		
		unsigned short old_switch, now_switch;
		init();
		acum_dreapta=3000;
		acum_stanga=3000;
		miscare =1;
		now_switch = 0;
		old_switch = now_switch;
		debounce = 0;
		
		
		while(1) {					// ciclu program
			
							now_switch = PINC&1;													// verifica pozitia intrerupatorului
							if (now_switch!=old_switch) {
													if (miscare&(1<<switch_debounce)){					// deja a fost deja detectata schimbarea
																					if (debounce>=250)	{		// si daca au trecut deja 250 ms de stabilitate
																										debounce=0;
																										miscare &=~(1<<switch_debounce);	// oprim debounce si concluzionam
																										old_switch=now_switch;
																										if (now_switch==1) {
																											
																															miscare&=~((1<<coborare)|(1<<start_coborare));	// stergem o eventuala coborare
																															miscare|=(1<<ridicare); 
																															}
																											else {
																													miscare&=~(1<<ridicare);								// stergem o eventuala ridicare
																													miscare|=(1<<start_coborare);
																												}
																										}
																					
																					}
															else{									// este prima detectie
																	miscare|=(1<<switch_debounce);	// porneste debounce
																	debounce=0;						// variabila de timp pentru debounce
																}
								
								
													}
								else	{
										debounce=0;							// daca nu a fost detectata schimbare sau schimbarea a fost mai mica de 250ms atunci resetam
										miscare &=~(1<<switch_debounce);	// oprim debounce
										}
						
			
			
			
							if (miscare&(1<<ridicare))	{					// comanda este de ridicare, status ridicare
															if ((acum_dreapta==Sus)&&(acum_stanga==Sus)){	// daca ambele bariere sus sus
																										miscare&=~(1<<semafor);		// oprim semaforul
																										miscare&=~(1<<ridicare);	// stergem mod ridicare
																										PORTB &=~(1<<PB5);			// oprim sunet
																										}
														}
							
							
							
							if (miscare&(1<<start_coborare))	{			// comanda este de coborare, status asteptare avans sunet
																		miscare|=(1<<semafor);			// pornim semaforul
																		PORTB|=(1<<PB5);				// pornim sunet
																		if (avans_sunet>=avans_sunet_max) {									// daca am terminat de asteptat avand sunet
																											avans_sunet=0;					// resetam contorul
																											miscare&=~(1<<start_coborare);	//schimbam modul din start_coborare in coborare
																											miscare|=(1<<coborare);
																											}
																}
			
			
				}		// end ciclu program
					


}		// end main

 

Editat de one
Link spre comentariu

Cateva indicatii pentru testare:

leaga mai intai intrerupatorul si un servo (dreapta). La reset ar trebui sa ia pozitia sus, apoi deconectezi alimentarea, fixezi crucea pe servo in pozitia sus.

Inchizi intrerupatorul si te asiguri ca servo merge in sensul corect. Daca nu, sa modific programul. Servo se poate monta cu partea mai lunga in exterior (asa l-am montat eu) sau spre interior, cu mecanismul spre sinele de tren, sau spre vehiculele din coada. In functie de asta, sensul de rotatie se poate schimba.

 

Eventual montezi apoi si celalalt servo si vezi daca si acela se roteste corect.

 

Dupa ce te asiguri ca servo se rotesc in directia buna, se pot monta barierele pe cruci.

Urmatorul pas va fi lampa alba cred.

 

Link spre comentariu

Momentan am descărcat driverele CH341 și am încărcat bariere.hex în Arduino Nano folosind Xloader. Acum caut o foto cu pinii lui Nano ca să văd bine unde trebuie să umblu, să nu stric ceva. Sunt la birou, am multă treabă și trebuie să plec în oraș dar nu vreau să plec nicicum până nu văd că mișcă :) 

Link spre comentariu

pentru programul de la mine nu trebuie servo library pentru ca eu am setat manual timerul.

 

Daca vrei sa te distrezi sa faci un program cu Arduino cred ca libraria servo este deja inclusa atunci cand descarci programul principal.

Te poti inspira de aici.

Editat de one
Link spre comentariu

Am luat astăzi niște leduri albe de 10mm la 3V.

Am alimentat mai devreme Arduino cu 5V de la alimentator, pentru că am uitat cablul mini-usb la birou. Am alimentat servo tot cu + si - de la alimentator, iar firul portocaliu de PWM l-am pus la D9. Când alimentez Nano, servo se mișcă cca 15 grade la stânga (CCW, cu crucea spre mine), stă cca. o secundă acolo după care revine în poziția inițială. În rest, servo nu face nimic nici dacă apăs pe reset, nici dacă dau D0 la masă, nici la +, nici impuls, nici o perioadă mai lungă.

Arduino văd că are și o ieșire de 3,3V, nu o putem folosi pe aceea pentru ISD1820? Nu am văzut niciun LED care să se aprindă pe plăcuța Nano în locul modulului de sunet. Cum pot verifica instalarea corectă a fișierului bariere.hex în chip-ul Arduino?

Link spre comentariu

O sa fac un video diseara cu functionarea. Intrerupatorul nu se leaga la D0 ci la A0. Acest pin are activat pull-up intern deci trebuie un intrerupator intre pin si masa. Am inclus un debouncing deci raspunsul nu e chiar imediat, ar trebui cam dupa un sfert de secunda sa se aprina led-ul.

Chiar daca alimentezi modulul de sunet cu 3,3V din Arduino (acei 3.3V proveneau de la FT232 nu stiu la CH340 cum e), va trebui si la pinul de comanda sa reduci tensiunea cu un divizor.

 

Cand alimentezi nano, pel pinul servo probabil apare un impuls si de aceea servo se duce unde se duce, apoi sta cam o secunda pentru ca bootloaderul asteapta cred cam acest timp, apoi se duce la pozitia de 90° pentru ca atunci incepe programul efectiv si acolo trebuie sa stea, pozitia normala a barierei trebuie sa fie sus. Verifica intrerupatorul daca e pus bine sau fa un contact cu un fir sau un obiect metalic (penseta, etc.) intre pinul A0 si masa, chiar si fara servo conectat, tine contactul o secunda macar. 

 

Link spre comentariu

Mergeee! Am pus A0 la masă și exact așa a făcut, s-a aprins ledul iar după cca 4 secunde, servo dreapta s-a mișcat treptat 90 grade CW. Sorry, aseară eram f obosit, am văzut D0 în loc de A0. Vina mea. Preocupat și că nu merge și că nu mi-ai răspuns, azi am luat și piesele pentru circuitul creat de Ticu. Exact când am plecat de pe Maica Domnului, ai răspuns :86.

Acum am ajuns acasă, unde am mutat sediul problemei, și mă apuc de însăilat ansamblul, adică de montat provizoriu, aerian, modulul audio și încă un servo.

Te rog totuși să inversezi sensurile, acest servo dreapta va fi montat într-o cutiuță tot cu fața (crucea) spre mine, și am nevoie să se învârtă 90 grade CCW, nu CW. Desigur, și la toate celelalte 3 servo trebuie schimbate sensurile. Sau să înceapă rotația întâi cele de pe cealaltă diagonală, nu de pe asta, nu știu cum e mai ușor de modificat programul. Servo-urile vor fi puse în niște cutiuțe de plastic, crucile (de care voi lipi barierele) fiind situate spre mașini, iar corpurile servo-urilor fiind situate spre calea ferată.

Mulțumesc!! Abia aștept și semafoarele / LED-urile, trebuie să îi dau zor.

 

Editat de Ssarmiss
Link spre comentariu

Am facut video deci o sa il pun oricum.

Iata e aici.

O sa inversez servo.

TOATE servo vor fi in aceeasi directie? "cu fata spre tine?".

Ok am citit inca o data mai bine.

iesirile servo vor fi in paralel deci inversarea unuia va avea efect si la cel din diagonala.

Intru dupa miezul noptii cu detalii si modificarile.

Editat de one
Link spre comentariu

Toate servo vor fi cu corpul spre interior (spre calea ferată) și cu crucea spre exterior (spre mașinile care așteaptă la semafor). De exemplu ce văd la tine în video e o barieră de stânga, care coboară la câteva secunde după ce începe să coboare perechea ei de pe dreapta.

Am să alimentez modulul audio de la pinul D13, cum ai zis, prin două diode 1N4007 (sper să nu-l ard :) ). Apropos, dacă putem, audio ar trebui să înceteze când barierele încep să se ridice (când întrerupătorul de la A0 se deschide).

Editat de Ssarmiss
Link spre comentariu

Când alimentez modulul de sunet din alimentator, merge perfect. Când îl alimentez din Arduino, deși are tensiunea care trebuie, fâșâie puternic, ca și cum ar avea nevoie de un condensator în paralel la alimentare. Încerc să folosesc un BC337 și o rezistență de 3,9K din circuitul lui Ticu, să văd dacă mai face.

Am făcut, se aude la fel... O să încerc cu un releu, după ce verific dacă nu cumva (puțin probabil) Arduino sau servo emit paraziți radio.

Editat de Ssarmiss
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări