Shadowplay LED Watch di Arduino Uno Platform

Alih-alih bergabung




Jadi, tim kami yang terdiri dari tiga orang memiliki tugas: untuk merakit proyek perangkat keras kecil dalam waktu yang sangat singkat, terutama pada platform Arduino. Perlu disebutkan bahwa sampai saat itu kita mengenal sirkuit, sebagian besar, secara teori. Dan ini berarti - tidak ada pengalaman dengan besi solder (praktis), atau, terutama, pengalaman dengan Arduino.

Tiba-tiba kami menemukan sebuah artikeldidedikasikan untuk proyek Shadowplay Clock. Ini adalah jam dinding yang dirancang oleh tim desainer Wina, waktu yang dapat Anda lihat dengan menyentuh satu jari di tengahnya. LED menyala sedemikian rupa sehingga bayangan jari di tengah menunjukkan waktu. Diputuskan untuk membuat yang sama (atau sangat mirip), tetapi di rumah. Artikel di atas, seperti yang Anda lihat, tidak mengandung deskripsi rinci tentang proyek. Dari semua ini, kami harus mencari tahu cara kerja perangkat ini dan menghidupkannya. Apa yang kami lakukan.

Material


Untuk membuat arloji yang Anda butuhkan:

  • papan serat kosong
  • 60 strip dioda LED
  • Arduino uno
  • Modul Jam Waktu Nyata RTC DS1307
  • tombol
  • papan tempat memotong roti
  • daftar geser 74HC595 (x2)
  • 8-bit register-latch 74HC573N (x8)
  • decoder 4-16 K155ID3
  • buka drain IN74HC05AN (x10)
  • unit daya

Mari kita mulai


Jadi, algoritma perangkat:

  1. Ketika daya diterapkan, LED menyala dalam kombinasi yang telah ditentukan. Dalam Shadowplay asli, semua LED menyala, tetapi bagi kami tampaknya akan lebih menarik untuk meluncurkan beberapa kombinasi sebagai screensaver.
  2. Ketika tombol ditekan (ya, kami juga menjauh dari aslinya dan memasukkan tombol kecil di tengah), waktunya dibaca dari modul RTC.
  3. Waktu baca dikonversi ke kode biner (mask) dan dimasukkan dalam register.
  4. Tergantung pada topengnya, dioda yang diperlukan dinyalakan.

Perangkat keras


Ketika kami akhirnya memutuskan ide proyek, hal pertama yang kami coba adalah membuat sketsa perkiraan versi skema untuk implementasinya. Pertanyaan utamanya adalah bagaimana cara mengatasi 60 LED. Sebenarnya, jawaban atas pertanyaan ini menentukan metode membangun hampir seluruh skema.

Opsi pertama yang terlintas dalam pikiran adalah penggunaan decoder. Rangkaian yang dikompilasi adalah cascade dari empat decoder 4-16 dan satu decoder 2-4, keduanya dengan dekripsi memungkinkan input. Kaskade semacam itu memungkinkan pengalamatan ke 64 output, yang lebih dari cukup untuk menghubungkan 60 LED.

Namun, kemudian muncul pertanyaan tentang bagaimana membuat lebih dari satu pekerjaan LED (alamat) pada saat yang sama (setelah semua, kami perlu menyediakan jam dengan setidaknya menit dan jarum jam). Di sini kelemahan utama skema ini dimanifestasikan - dekoder tidak dapat, menurut definisi, mengatasi lebih dari satu output pada suatu waktu.

Cacat ini memaksa kami untuk meninggalkan ide dengan riam decoder. Selain itu, sekarang kami memiliki persyaratan lain untuk sirkuit masa depan - dukungan untuk operasi simultan dari sejumlah LED yang berbeda.

Untuk memenuhi persyaratan ini, kami berpikir bahwa dimungkinkan untuk memungkinkan setiap LED menyimpan keadaannya. Register sangat cocok untuk tujuan ini, di mana setiap debit sesuai dengan keadaan salah satu LED. Kami memutuskan untuk menggunakan register 8-bit, karena lebih umum dan lebih praktis. Karenanya, di sirkuit kami, kami akan membutuhkan 8 register semacam itu untuk memberikan dukungan bagi 60 LED.

Selanjutnya, kami berpikir tentang cara mengontrol status LED dengan Arduino melalui register. Setiap register untuk operasi normal harus menerima keseluruhan 8 bit secara keseluruhan. Arduino Uno, tentu saja, menyediakan output yang cukup untuk mengirimkan beberapa bit sekaligus, tetapi pendekatan ini tidak rasional. Selain itu, skema ini hanya berisi 8 register, yang berarti Anda perlu mengatasinya. Untuk tujuan ini, kami menambahkan decoder dan dua register geser 8-bit yang terhubung dalam cascade ke sirkuit. Satu register shift menyimpan state mask 8-bit, yang akan dimuat ke dalam salah satu dari 8 register reguler, yang jumlahnya disimpan dalam register shift kedua. Dengan demikian, dekoder terhubung ke register shift kedua. Untuk keperluan ini, dekoder 3 kali 8 sudah cukup.

Untuk menghapus inversi dari jumlah output yang diperlukan, kami menggunakan dua sirkuit inverter KR1533LN1. Skema ini, tentu saja, agak rumit.

Tugas lain adalah tegangan kerja LED sama dengan 12 volt dibandingkan dengan 5 volt sirkuit logika. Solusi yang diusulkan adalah menggunakan inverter drain terbuka. Sirkuit mikro semacam itu memainkan peran kunci yang menutup (dengan logis 1) atau membuka (dengan logis 0) salah satu kontak LED dengan tanah, dengan demikian menghidupkan atau mematikan LED. Rangkaian mengasumsikan operasi dari 12 volt, sesuai dengan tegangan operasi LED, sehingga untuk mendapatkan 5 volt untuk sirkuit logika, stabilizer KR142EN5A dengan dua kapasitor ditambahkan ke sirkuit.

Beberapa input dari sirkuit mikro tertentu menyiratkan nilai konstan pada input, sehingga terhubung ke ground atau sumber daya. Dalam hal ini, ini adalah input berikut:

  • Input reset MR terbalik di kedua register geser dihubungkan melalui register beban ke output stabilizer pada 5 volt.
  • Output OE terbalik memungkinkan input di kedua register geser terhubung langsung ke ground.
  • Decoder terbalik memungkinkan input E0 terhubung ke arde




Rangkaian dikontrol oleh empat input (E1, SH, ST, DS). Tingkat tujuan dan sinyal masing-masing dibahas secara lebih rinci di bawah ini:

Input E1 dirancang untuk mengaktifkan dekoder. Dalam kasus kami, awalnya pada dekoder ada dua input kontrol E1, E0, dan keduanya terbalik. Akan ada cukup satu jalan keluar, sehingga yang kedua (E0) dapat dibawa ke tanah. Status dekoder "default" beroperasi hingga level sinyal tinggi diterapkan ke E1. Untuk melakukan yang sebaliknya, kami menghubungkan input ini ke inverter. Tanpa ini, decoder dapat memberikan sinyal kontrol yang salah kepada register, misalnya, pada saat memperbarui data dalam register geser. Seperti yang telah disebutkan, 3 oleh 8 decoder dapat digunakan dalam rangkaian, yang dapat memiliki satu input kontrol non-invers, yang akan membuatnya mudah untuk menyelesaikan semua masalah yang dijelaskan di atas tanpa kabel tambahan dan besi solder.

Ketika level sinyal tunggal diterapkan ke E1, decoder menerjemahkan alamat register yang terletak di register shift yang sesuai, dan mengirimkan sinyal ke output yang diinginkan. Setelah itu, decoder mati lagi dengan menerapkan level sinyal rendah ke E1. Saklar seperti decoder menghasilkan sinyal pada output yang diinginkan, tepi dan pembusukan yang berfungsi sebagai pulsa clock register untuk mengambil sendiri data yang disimpan di bus.

Tiga input berikutnya sudah dimaksudkan untuk mengendalikan register geser. Layak dimulai dengan hal yang paling sederhana - entri data DS. Input ini, sesuai namanya, dimaksudkan untuk transmisi data. Karena register shift di sirkuit terhubung dalam cascade, DS mewakili output yang sesuai dari salah satunya. Input dari register geser kedua terhubung ke output dari bit terakhir dari register pertama. Hasilnya adalah satu register geser untuk 16 bit, dimana hanya 12 bit yang digunakan.

Input SH adalah input jam. Gelombang persegi diumpankan ke input ini, yang masing-masing bertanggung jawab untuk memuat dan memindahkan data di masing-masing register, kontak rangkaian ini terhubung ke pin SHCP dari kedua register.

Pin ST terakhir berfungsi sebagai kait data pada output register. Impuls diberikan pada input ini, namun hanya diberikan ketika data dalam register shift akhirnya dimuat dan diperlukan untuk memperbaikinya pada output register. Hanya setelah memberikan sinyal ini, data yang diunduh di dalam register pada baris pertama dari pemicu mendapatkan baris kedua dari pemicu dan menjadi tersedia di bus. ST adalah pin yang terhubung ke pin STcp dari kedua register.

Masih menjelaskan kabel dua pin dari register geser MR dan OE. Input pertama (MR) bertanggung jawab untuk membuang data di dalam register. Dalam sirkuit ini, peluang seperti itu tidak diperlukan, oleh karena itu level sinyal tinggi disuplai ke output ini melalui beban.

Input register kedua (OE) bertanggung jawab untuk memutus baris kedua pemicu di dalam register geser dari bus, mis., Input yang diaktifkan. Fungsi ini juga tidak diperlukan, oleh karena itu, output luka ke tanah.

Kontak lain yang tidak diuraikan di atas dirancang untuk menghilangkan level sinyal dari tombol di bagian tengah arloji, sirkuit tombolnya khas dan mewakili beban dan kunci, tergantung pada posisi di mana level sinyal rendah atau tinggi dikirim ke Arduino. Bergantung pada keadaan tombol, arloji beroperasi baik dalam mode screensaver atau dalam mode tampilan waktu.
Koneksi ke Arduino tidak memiliki fitur khusus, kecuali bahwa pin SH terhubung secara ideal ke pin digital SCK. Keluaran sirkuit lainnya dapat dihubungkan ke input digital serba guna yang tersedia. Dalam kasus kami, koneksi memiliki bentuk berikut:

  • Arduino pin13 (SCK) โ€“ SH
  • Arduino pin 11 โ€“ ST Arduino pin 8 โ€“ DS Arduino pin 5 โ€“ E1 Arduino pin 3 โ€“ Arduino pin GND โ€“ ( )
    , .

    : 36 โ€” ; 36 ( ) \ 26 ( ) โ€” . Shadowplay 72 , 36. , 60 ( + ). . , , , .



    , . , . , . , ยซยป 50 โ€” 60, . , 60 . : โ€” .



    , , , . โ€” . , , . , โ€” .

    .


    -, .

    Shadowplay. , , . , , . , .. . , , 100% . , . . , . , .

    , ( ), , โ€” . , , ! . , - - . , , . , , . , , , . ., - . , , , , , .



    , . . .. , , ( , , ), .


    , (). Arduino. , RTC, โ€” . DS1307, โ€” I2C. 2100 . . RTC Arduino, . RTC.



    , RTC, .

    #include <Time.h>
    #include <DS1307RTC.h>
    
    char REG [8];
    tmElements_t te;
    int c,reset=1;
    
    void setup() {
      pinMode(13, OUTPUT); 
      pinMode(11, OUTPUT); 
      pinMode(8, OUTPUT);  
      pinMode(5, OUTPUT);  
      pinMode(3, INPUT);   
      Serial.begin(57600);
      
      //      RTC  
      //te.Hour = 18;
      //te.Minute = 50;
      //te.Second = 0;
      //te.Day = 20; //
      //te.Month = 4; // 
      //te.Year = CalendarYrToTm(2016); 
      //RTC.write(te);
    }
    
    void loop()
    { 
    if(digitalRead(3))                    // ,     
      {RTC.read(te);
       SetShadowTime(te.Hour,te.Minute,te.Second,2);        //         
       delay(900);
       reset=1;
      }
    
    else                                   //    ,  
      {wait1();
       reset=1;
      }
                                             //  
      for(int j = 0; j<8 ; j++) SetUpLightByMask(j,0); 
       
     
    }
    
    
    //======================================================================= 
    
    void SetUpLightByMask(int RegNum, char LightMask) //         
    {
      
      digitalWrite(5, LOW);
      digitalWrite(11, LOW);
      shiftOut(8, 13, MSBFIRST, LightMask);
      shiftOut(8, 13, LSBFIRST, RegNum);
      digitalWrite(11, HIGH);
      digitalWrite(5, HIGH);
    }
    
    void digitalClockDisplay() {  //    RTC  ,    RTC  
      RTC.read(te);
      Serial.print(te.Hour);
      Serial.print(" : ");
      Serial.print(te.Minute);
      Serial.print(" :");
      Serial.print(te.Second);
      Serial.print(" ");
      Serial.print(te.Day);
      Serial.print(" ");
      Serial.print(te.Month);
      Serial.print(" ");
      Serial.print(tmYearToCalendar(te.Year));
      Serial.println();
    }
    
    //     ,     , ,        :
    //0 -  ,1 -   , 2 -    
    
    void SetShadowTime(int Hours, int Minutes, int Seconds, int param){   
      int h,hshift,m,s;
      for(int j = 0; j<8 ; j++) REG[j] = 0;
    
      if(Hours >= 12) Hours -= 12;
      h = Hours + 6;
      if(h >= 12) h -= 12;
        
      hshift = (int) Minutes / 12;
      
      REG[(int)(((h*5)+hshift)/8)] = REG[(int)(((h*5)+hshift)/8)] | 1<<(((h*5)+hshift)%8);
                 
       
      if(param == 1)
      {m = Minutes + 30;
       if(m >= 60) m -= 60;
       REG[(int)(m/8)] = REG[(int)(m/8)] | 1<<(m%8);
       }
    
      if(param == 2)
      {m = Minutes + 30;
       if(m >= 60) m -= 60;
       REG[(int)(m/8)] = REG[(int)(m/8)] | 1<<(m%8);
         
       s = Seconds + 30;
       if(s >= 60) s -= 60;
       REG[(int)(s/8)] = REG[(int)(s/8)] | 1<<(s%8);
      }
    
      for(int j = 0; j<8 ; j++) SetUpLightByMask(j,REG[j]);
      }
      
    void wait1() //    
    {for(int a = 0; a < 8; a++)
        {c=0;
         for(int b = 0; b < 8; b++)
          {c = c << 1;
           c = c | 1;
           SetUpLightByMask(a, c);  
           delay(10);   
          }
       }
      for(int a = 0; a < 8; a++)
        {c=255;
          for(int b = 0; b < 8; b++)
          {c = c << 1;
           SetUpLightByMask(a, c);
           delay(10);     
          }
        }  
    }
    



    . . (Arduino, RTC) . , . , ยซ- ยป. โ€” . :

    .



    , ยซยป:



    , , :



    , , , .

    , , . , ? . : ( , , ..). , , , . . , .


    ?

    • , , .
    • .
    • Kemampuan untuk dengan mudah mengubah urutan LED berkedip secara terprogram, yang memberikan beragam kombinasi tanpa batas.

    Kami tidak mengklaim kebenaran mutlak dari solusi sirkuit dan perangkat lunak kami. Seperti yang telah disebutkan, pengalaman negatif juga pengalaman. Mungkin artikel ini akan membantu seseorang menghindari kesalahan kita.

    Terima kasih atas perhatian anda!

Source: https://habr.com/ru/post/id394107/


All Articles