Kao što znamo iz specifikacija Arduino UNO tolerira struju na I/O pinovima do 20mA što je dovoljno za interakciju sa senzorima i upravljanje malim trošilima. Ako želimo upravljati većim trošilima moramo u naš sklop dodati upravljače (ili prekidače) a to mogu biti:
U ovom poglavlju ćemo upoznati načine spajanja i komponente za upravljanje večim trošilima.
Relej je po definiciji vrsta prekidača koja pri određenoj vrijednosti veličine na ulazu uključuje ili isključuje izlazne kontakte. Postoji više vrsta releja, a mi ćemo se baviti najraširenijim tipom – elektromagnetskim. Pogledajmo izgled i dimenzije tipičnog releja:
Bitno je poznavati princip rada, raspored izvoda i radne parametre releja. Standardni relej kao ovaj na slici ima 5 izvoda:
Princip rada – U nepobuđenom stanju zatvoren je kontakt između izvoda COM i NC, a otvoren između između COM i NO. Kad se na kontakte zavojnice (C1 i C2) dovede napon pobude, elektromagnet uključuje kontakt između COM i NO, a kontakt između COM i NC je tada prekinut. Padom napona pobude kontakt se vraća u početno stanje (COM-NC).
Radne parametre možemo naći u dokumentaciji releja:
https://drive.google.com/file/d/0B4TJ7Awmm9iTelhPTHc0eXA1dWc/view?usp=sharing
Shema spajanja s mikrokontrolerom je slijedeća:
VCC je napon napajanja releja (u našem primjeru 5V), napon trošila spajamo na kontakte A i B.
Tranzistor T1 je za 5V 2N2222 a za releje s većim naponom pobude uzmite TIP102. Vrijednost otpornika R1 nije kritična ali neka bude 1-2,2 k Ω.
Ukoliko se ne želite upuštati u samogradnju sklopa, možete se poslužiti gotovim relej-modulom za Arduino kakvih ima dosta na tržištu i nisu skupi.
Spajaju se na slijedeći način:
Programski kod za upravljanje ovisi o potrebama korisnika ali za primjer ćemo preko releja uključiti ventil na 2 sekunde, a zatim ga isključiti na 5 sekundi i ponavljati sekvencu.
#define VENTIL 9 void setup() { pinMode(VENTIL, OUTPUT); // postavljanje pina } // sekvenca void loop() { digitalWrite(VENTIL, HIGH); // ukljuci ventil delay(2000); // na 2 sekunde digitalWrite(VENTIL, LOW); // iskljuci ventil delay(5000); // na 5 sekundi }
Ovaj modul ima široku uporabu zbog odnosa cijene i dobivenog te je česta opcija u daljinskim upravljačima različite namjene.
Moduli odašiljača i prijemnika su različiti i podržavaju samo jednosmjernu komunikaciju (od odašiljača ka prijemniku).
ODAŠILJAČ
Karakterisitke:
PRIJEMNIK
Karakteristike:
Za ovaj primjer nam trebaju dva mikrokontrolera, u našem primjeru će to biti Arduino Uno, odašiljački modul, prijemni modul i 6 spojnih žica (Dupont M/F).
Spajanje odašiljača:
Programski kod za odašiljač:
#include <VirtualWire.h> // Ukoliko nemate VirtualWire library preuzmite ga s http://rik-popovaca.hr/arduino/libraries/VirtualWire.zip void setup() { // Inicijalizacija vw_set_ptt_inverted(true); vw_setup(2000); // Brzina (Bitova u sekundi) } void loop() { const char *msg = "Poruka poslana"; // Poruka koju saljemo prijemniku digitalWrite(13, true); // LED na pinu D13 je ukljucen prilikom slanja vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx(); digitalWrite(13, false); delay(200); }
Spajanje prijemnika:
Programski kod za prijemnik:
#include <VirtualWire.h> // Ukoliko nemate VirtualWire library preuzmite ga s http://rik-popovaca.hr/arduino/libraries/VirtualWire.zip void setup() { Serial.begin(9600); Serial.println("setup"); // Inicijalizacija vw_set_ptt_inverted(true); vw_setup(2000); // Brzina (Bitova u sekundi) vw_rx_start(); // Pokreni prijemnik } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; if (vw_get_message(buf, &buflen)) // Ukoliko smo primili poruku { int i; digitalWrite(13, true); // LED na pinu D13 je ukljucen prilikom prijema Serial.print("Primljeno: "); for (i = 0; i < buflen; i++) // Petlja za primanje poslanih podataka { char c = (buf[i]); Serial.print(c); // Ispis znak po znak } Serial.println(""); digitalWrite(13, false); } }
Spajanje odašiljača:
Programski kod za odašiljač:
#define NETWORK_SIG_SIZE 3 #define VAL_SIZE 2 #define CHECKSUM_SIZE 1 #define PACKET_SIZE (NETWORK_SIG_SIZE + VAL_SIZE + CHECKSUM_SIZE) #define NET_ADDR 5 #define CRVENA 5 #define ZUTA 6 #define ZELENA 7 const byte g_network_sig[NETWORK_SIG_SIZE] = {0x8F, 0xAA, NET_ADDR}; int broj; void setup(){ pinMode(CRVENA, INPUT_PULLUP); pinMode(ZUTA, INPUT_PULLUP); pinMode(ZELENA, INPUT_PULLUP); Serial.begin(1200); // Brzina 1200 bps } void loop(){ int cr = digitalRead(CRVENA); int zu = digitalRead(ZUTA); int ze = digitalRead(ZELENA); if (cr == LOW) broj = 5; if (zu == LOW) broj = 6; if (ze == LOW) broj = 7; writeUInt(broj); broj = 0; } void writeUInt(unsigned int val){ byte checksum = (val/256) ^ (val&0xFF); Serial.write(0xF0); Serial.write(g_network_sig, NETWORK_SIG_SIZE); Serial.write((byte*)&val, VAL_SIZE); Serial.write(checksum); //CHECKSUM_SIZE }
Spajanje prijemnika:
Programski kod za prijemnik:
#define NETWORK_SIG_SIZE 3 #define VAL_SIZE 2 #define CHECKSUM_SIZE 1 #define PACKET_SIZE (NETWORK_SIG_SIZE + VAL_SIZE + CHECKSUM_SIZE) #define NET_ADDR 5 #define CRVENA 5 #define ZUTA 6 #define ZELENA 7 const byte g_network_sig[NETWORK_SIG_SIZE] = {0x8F, 0xAA, NET_ADDR}; int broj; void setup(){ pinMode(CRVENA, OUTPUT); pinMode(ZUTA, OUTPUT); pinMode(ZELENA, OUTPUT); Serial.begin(1200); // Brzina 1200 bps } void loop(){ broj = readUInt(true); digitalWrite(CRVENA, (broj == 5)); digitalWrite(ZUTA, (broj == 6)); digitalWrite(ZELENA, (broj == 7)); } unsigned int readUInt(bool wait){ int pos = 0; unsigned int val; byte c = 0; if((Serial.available() < PACKET_SIZE) && (wait == false)){ return 0xFFFF; } while(pos < NETWORK_SIG_SIZE){ while(Serial.available() == 0); c = Serial.read(); if (c == g_network_sig[pos]){ if (pos == NETWORK_SIG_SIZE-1){ byte checksum; while(Serial.available() < VAL_SIZE + CHECKSUM_SIZE); val = Serial.read(); val += ((unsigned int)Serial.read())*256; checksum = Serial.read(); if (checksum != ((val/256) ^ (val&0xFF))){ // Checksum failed pos = -1; } } ++pos; } else if (c == g_network_sig[0]){ pos = 1; } else{ pos = 0; if (!wait){ return 0xFFFF; } } } return val; }
Ovo je serija modula baziranih na popularnom Nordic Semiconductor čipu nRF24l01+. Ovaj modul je i prijemnik i odašiljač (eng. transceiver), uloga se bira programski.
Ako povežemo dva Arduino sučelja putem ovih modula možemo ih upotrijebiti za razne svrhe, izdvojit ću samo neke od njih:
Pogledajmo glavne značajke ovog modula:
Prilikom napajanja je poželjno imati dodatni izvor za napajanje ovog modula. Arduino UNO može napajati modul s 3,3V izvoda ali MEGA i NANO mogu imati problema s naponom. Preporučivo je staviti dodatni elektrolitski kondenzator (10uF) paralelno VCC i GND pinovima na modulu za dodatnu stabilizaciju rada (pazite na polaritet).
Zadatak je poslati radio modulom stanje sva tri tipkala istovremeno. Otpornici u prijemniku su 330ohma. Tipkala su postavljena u INPUT_PULLUP mod.
Spajanje pinova
Shema spajanja odašiljača
Programski kod za odašiljač
/*-----( Biblioteke )-----*/ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> // Ukoliko nemate RF24 library preuzmite ga s http://rik-popovaca.hr/arduino/libraries/RF24.zip /*-----( Konstante, varijable i pinovi )-----*/ #define CE_PIN 9 #define CSN_PIN 10 #define CRVENA 5 #define ZUTA 6 #define ZELENA 7 const uint64_t pipe = 0xE8E8F0F0E1LL; // Definicija transmit pipe-a int podaci[3]; /*-----( Deklaracija objekata )-----*/ RF24 radio(CE_PIN, CSN_PIN); void setup() { pinMode(CRVENA, INPUT_PULLUP); pinMode(ZUTA, INPUT_PULLUP); pinMode(ZELENA, INPUT_PULLUP); Serial.begin(9600); delay(1000); Serial.println("Startam Nrf24L01"); radio.begin(); radio.openWritingPipe(pipe); } void loop() { podaci[0] = digitalRead(CRVENA); podaci[1] = digitalRead(ZUTA); podaci[2] = digitalRead(ZELENA); // Saljemo ocitanje stanja sva 3 tipkala u nizu radio.write( podaci, sizeof(podaci)); }
Shema spajanja prijemnika
Programski kod za prijemnik
/*-----( Biblioteke )-----*/ #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> // Ukoliko nemate RF24 library preuzmite ga s http://rik-popovaca.hr/arduino/libraries/RF24.zip /*-----( Konstante, varijable i pinovi )-----*/ #define CE_PIN 9 #define CSN_PIN 10 #define CRVENA 5 #define ZUTA 6 #define ZELENA 7 const uint64_t pipe = 0xE8E8F0F0E1LL; // Definicija transmit pipe-a int podaci[3]; /*-----( Deklaracija objekata )-----*/ RF24 radio(CE_PIN, CSN_PIN); void setup() { pinMode(CRVENA, OUTPUT); pinMode(ZUTA, OUTPUT); pinMode(ZELENA, OUTPUT); Serial.begin(9600); delay(1000); Serial.println("Startam Nrf24L01"); radio.begin(); radio.openReadingPipe(1,pipe); radio.startListening();; } void loop() { if ( radio.available() ){ bool done = false; while (!done){ done = radio.read( podaci, sizeof(podaci) ); } // Kako saljemo INPUT_PULLUP ocitanja // primamo LOW kad je pritisnuto tipkalo i oduzimanjem od 1 // radimo inverziju u HIGH stanje za paljenje LED :) int cr = 1-podaci[0]; int zu = 1-podaci[1]; int ze = 1-podaci[2]; digitalWrite(CRVENA, cr); digitalWrite(ZUTA, zu); digitalWrite(ZELENA, ze); } }
Umjesto stanja tipkala možemo poslati bilo koji podatak. Za zadatak si na odašiljaču umjesto digitalnih podataka uzmite analogna očitanja s recimo dva potenciometra. Pošaljite ih odašiljaču gdje umjesto LED kontroliramo motor driver i eto nam mobilnog robota na daljinsko upravljanje.
Ukoliko želimo upravljati motorima kod kojih se radu pojavljuju struje veće od 2A poslužit ćemo se H-mostom baziranim na čipu VNH2SP30 koji dolazi u obliku gotovog shielda za Arduino koji se popularno naziva Monster Moto Shield. <Monster Moto shield na Sparkfun-u>
Karakterisitike ovog modula su:
Pogledajmo način na koji se spaja s motorima:
Motor 1 se spaja na izvode A1 i B1, a motor 2 na izvode A2 i B2.
Budući da je ovo shield forma pinovi koji se koriste su rezervirani:
Motor 1
Motor 2
Dijagnostički pinovi
Pogledajmo kod za upravljanje:
#define BRAKEVCC 0 #define CW 1 #define CCW 2 #define BRAKEGND 3 #define SP 1023 #define CS_THRESHOLD 100 int inApin[2] = {7, 4}; // INA: Selektor za smjer1 int inBpin[2] = {8, 9}; // INB: Selektor za smjer2 int pwmpin[2] = {5, 6}; // PWM izlaz int cspin[2] = {2, 3}; // CS: osjet jačine struje analogni ulaz int enpin[2] = {0, 1}; // EN: Status ukljucenosti mosta (Analogni pin) int statpin = 13; void setup() { Serial.begin(9600); pinMode(statpin, OUTPUT); // Initialize digital pins as outputs for (int i=0; i<2; i++) { pinMode(inApin[i], OUTPUT); pinMode(inBpin[i], OUTPUT); pinMode(pwmpin[i], OUTPUT); } // Initialize braked for (int i=0; i<2; i++) { digitalWrite(inApin[i], LOW); digitalWrite(inBpin[i], LOW); } motorGo(0, BRAKEGND, SP); motorGo(1, BRAKEGND, SP); } void loop() { motorGo(0, CW, 1023); // motor 1 - smjer 1 motorGo(1, CCW, 1023); // motor 2 - smjer 2 delay(3000); motorOff(0); // Iskljuci motor 1 motorOff(1); // Iskljuci motor 2 delay(1000); motorGo(0, CCW, 1023); // motor 1 - smjer 2 motorGo(1, CW, 1023); // motor 2 - smjer 1 delay(3000); motorOff(0); // Iskljuci motor 1 motorOff(1); // Iskljuci motor 2 delay(1000); if ((analogRead(cspin[0]) < CS_THRESHOLD) && (analogRead(cspin[1]) < CS_THRESHOLD)) digitalWrite(statpin, HIGH); } void motorGo(uint8_t motor, uint8_t direct, uint8_t pwm) { if (motor <= 1) { if (direct <=4) { // Set inA[motor] if (direct <=1) digitalWrite(inApin[motor], HIGH); else digitalWrite(inApin[motor], LOW); // Set inB[motor] if ((direct==0)||(direct==2)) digitalWrite(inBpin[motor], HIGH); else digitalWrite(inBpin[motor], LOW); analogWrite(pwmpin[motor], pwm); } } } void motorOff(int motor) { // Initialize braked for (int i=0; i<2; i++) { digitalWrite(inApin[i], LOW); digitalWrite(inBpin[i], LOW); } analogWrite(pwmpin[motor], 0); }
© 2025 Hrvatski robotički savez