Arduino web tutorijali

UVOD

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:

 

  • Releji
  • Bipolarni tranzistori
  • FET Tranzistori
  • Trijaci
  • Upravljački IC (driver IC) 

 

Upravljaci

 

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:

Relej

 

Bitno je poznavati princip rada, raspored izvoda i radne parametre releja. Standardni relej kao ovaj na slici ima 5 izvoda:

  • C1 i C2 – Zavojnica (coil) 
  • COM – Zajednički kontakt (common)
  • NO – Otvoreni kontakt (normaly open)
  • NC – Zatvoreni kontakt (normaly closed)

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:

Spajanje releja

 

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:

Spajanje relej modula

 

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.

RF 433 moduli

Moduli odašiljača i prijemnika su različiti i podržavaju samo jednosmjernu komunikaciju (od odašiljača ka prijemniku).

ODAŠILJAČ

Karakterisitke:

  • Napajanje : 3-12V
  • Radna frekvencija: 433.92MHz
  • Struja u mirovanju: 0mA
  • Struja pri slanju :20-28mA
  • Domet: 5-200m (ovisno o naponu i prostoru) 
  • Izlazna snaga: 16dBm (40mW)
  • Brzina prijenosa: <10Kbps
  • Modulatcija: OOK (Amplitudna Modulacija)
  • Radna temperatura: -10 ℃ ~ +70 ℃
  • Veličina: 19×19×8mm

PRIJEMNIK

Karakteristike:

  • Radni napon: DC5V
  • Potrošnja: 4mA
  • Radna frekvencija: 433.92MHz
  • Osjetljivost:-105DB
  • Dimenzije:30x14x7mm

 

PRVI PRIMJER - SLANJE TEKSTUALNE PORUKE PREKO RF 433 MODULA

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:

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:

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);
    }
}

 

DRUGI PRIMJER - DALJINSKO PALJENJE LED

 

Spajanje odašiljača:

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:

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.

NRF24L01 pinout

Ako povežemo dva Arduino sučelja putem ovih modula možemo ih upotrijebiti za razne svrhe, izdvojit ću samo neke od njih:

  • Daljinski prijenos očitanja raznih senzora
  • Alarmi, detektori i razne vrste nadzornih uređaja
  • Daljinsko upravljanje
  • Telemetrija

 Pogledajmo glavne značajke ovog modula:

  • 2.4GHz ISM pojas, slobodan za korištenje.
  • 126 RF kanala.
  • Brzine prijenosa: 250kbps, 1 i 2Mbps.
  • Odašiljač: troši 11.3mA pri 0dBm izlaznoj snazi.
  • Prijemnik: Brzi AGC za povećanje dometa.
  • Prijemnik: Integrirano filtriranje kanala.
  • Enhanced ShockBurst™: 1 do 32 bytes dinamički paketi, 6 data-pipe MultiCeiver™ za 1:6 star networks.
  • Host Interface: 4-pin hardware-ski SPI, 3 odvojena 32-byte TX i RX FIFO.
  • Mali napon napajanja: 1.9 - 3.6V.
  • GFSK modulacija.
  • Automatsko rukovanje prijenosom paketa podataka..
  • Male dimenzije: 15x29mm.

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).

 

PRIMJER - DALJINSKO PALJENJE LED

Zadatak je poslati radio modulom stanje sva tri tipkala istovremeno. Otpornici u prijemniku su 330ohma. Tipkala su postavljena u INPUT_PULLUP mod.

 

Spajanje pinova

Signal

RF Modul pin

Arduino pin za UNO, NANO

MEGA2560 pin

GND

1

GND

GND

VCC

2

3.3V

3.3V

CE

3

9

9

CSN

4

10

53

SCK

5

13

52

MOSI

6

11

51

MISO

7

12

50

IRQ

8

 

Shema spajanja odašiljača

Spajanje TX modula

 

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

Spajanje RX modula

 

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:

  • Operativni napon: 5,5 – 16 V. 
  • Van tih granica se sklop sam isključuje (overvoltage and undervoltage protection/shutdown)
  • Maksimalna struja (na mahove): 30 A
  • Operativna struja (u kontinuitetu): 14 A
  • Maksimalna PWM frekvencija: 20 kHz
  • Termalna zaštita
  • MOSFET otpor u vođenju (on-resistance): 19 mΩ
  • Arduilno kompatibilan

 Pogledajmo način na koji se spaja s motorima:

Monster moto shield

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

  • D5 - PWM1
  • D7 - INA1
  • D8 - INB1

Motor 2

  • D6 - PWM2
  • D4 - INA2
  • D9 - INB2

Dijagnostički pinovi

  • A0 - Status mosta 1
  • A1 - Status mosta 2
  • A2 - Jacina struje most 1
  • A3 - Jacina struje most 2

 

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);
}