Hedgehog - burung berbicara [jika dengan pemutar MP3]



Dahulu kala, sedemikian rupa sehingga kelihatannya tidak benar, masterkit berbicara tentang pemutar MP3 built-in yang luar biasa yang dapat dilengkapi dengan apa saja, bahkan pemutar MP3, jika Anda pertama-tama menghapus sendiri dari mereka dan kemudian memakai yang ini. Singkatnya, hal yang bermanfaat. Terutama jika Anda ingin membuat mainan anak-anak, pertama, dengan tangan Anda sendiri, dan, kedua, dengan benar, dan tidak dengan cara orang-orang yang membuat mereka pada skala industri berpikir.

Namun, dalam produk yang disajikan, saya puas tidak hanya dengan segalanya, jadi saya pikir: tidak mungkin hal yang terlihat China tidak ada di Aliexpress. Memang, ada sejumlah pemain seperti itu, dan pengenalan dengan rentang model menunjukkan bahwa ada opsi yang lebih menarik daripada model dengan jumlah memori yang tetap. Yaitu - dengan slot untuk kartu microSD yang dapat dilepas.

Dan kita pergi.



Untuk memperjelas apa dan ke mana perginya, demo landak dalam berbagai mode.

Menghibur frasa sambil menunggu:



Mengganti cerita, volume hidup dan mati dengan kartu dan gemetar:



Pengisian Nirkabel:



Sebelum melanjutkan cerita, saya minta maaf bahwa saya dapat membuat beberapa ketidakakuratan dalam deskripsi dan sirkuit, karena dalam prosesnya saya tidak mendokumentasikan apa pun, semua untuk berbicara, pada firasat. Tolong gunakan akal sehat dan bahan-bahan praktis agar nantinya tidak akan sangat menyakitkan.

Jadi, setelah pencarian dan perbandingan singkat, saya beralih ke Ebay, di mana saya mendapatkan apa yang saya inginkan - pemain dengan chip decoder JQ6500, 4 megabyte memori internal dan slot microSD .



Kenapa tepatnya pemain ini? Karena menurut saya, inilah pilihan ideal untuk pekerjaan rumahan. Karena semuanya ada bersamanya. Jika Anda mau, gunakan secara terpisah: untuk ini, ada pin play / pause, switching track, volume, pemutaran cepat lima track dan penguat mono untuk menghubungkan speaker langsung ke papan (ada juga output stereo, tetapi sudah membutuhkan penguat eksternal). Yaitu, setidaknya cukup baterai, speaker, beberapa tombol dan kartu memori dengan musik.

gambar

Namun yang jauh lebih menarik adalah kontrol penuh pemain melalui beberapa kemiripan port serial. Di sini Anda dapat melakukan apa saja - mainkan, hentikan, ubah volume, alihkan mode equalizer dan playback, mulailah memutar lagu-lagu sewenang-wenang baik dalam urutan тАЬthroughтАЭ maupun dari folder tertentu. Dan, yang penting dalam kasus saya, sudah ada perpustakaan yang siap pakai untuk Arduino.

Jadi, dua komponen sudah diketahui: pemain dan Arduino. Tetapi secara pribadi, saya tidak ingin berhenti di sana, karena bodoh untuk menjadi bodoh untuk meniru tombol dengan mikrokontroler keseluruhan. Sesuatu yang istimewa diperlukan agar dengan Emely, untuk berbicara, dan tombak.

Oleh karena itu, di sini kami menambahkan sensor getaran paling sederhana SW-18010P dan pembaca kartu RC522 yang terkenal.

gambar

Semua hanya untuk benar-benar menyingkirkan tombol, yang dalam mainan menghibur saya temukan tidak perlu. Nilailah sendiri: jika ada tombol, entah bagaimana anak akan menekannya, dan lebih sering - secara kebetulan daripada secara sadar. Tetapi pergantian dongeng yang super sering masih kurang tepat.

gambar

Di sini ternyata caranya: sensor getaran berfungsi untuk menghidupkan mainan ketika anak mengambilnya. Sensor yang sama tidak akan membiarkan mainan mati sampai anak memakainya untuk waktu yang cukup lama. Adapun pembaca kartu Mifare, hal ini, menurut pendapat saya, sangat nyaman untuk mengganti dongeng. Misalnya, kartu dapat dilampirkan ke buku, dan kemudian anak akan dapat mendengarkan dongeng dengan membawa mainan ke buku.

Dan juga kartu dapat dilampirkan ke berbagai mata pelajaran, dan kemudian anak akan dapat mendengarkan deskripsi dan aturan penggunaannya. Sebagai contoh, bahwa figovina putih ini adalah lemari es, dan bahwa kita menyimpan makanan di sana sehingga tidak memburuk, dan karena alasan ini tidak layak membukanya. Atau ini adalah oven, dan bisa panas, jadi Anda tidak perlu menggantung di pegangannya dan meletakkan tangan Anda di atas kaca. Banyak hal yang dapat ditemukan, terutama karena kartunya digunakan tiket metro (ya, saya beruntung, saya di Moskow), yang dapat dengan mudah dikumpulkan dalam jumlah yang tepat.

Karena itu, ketika saya berpikir, sementara itu saya mengeluarkan controller ATmega328p dari saham , menyoldernya ke papan tempat memotong roti dan mem-boot bootloader Adruino melalui Arduino Mega 2560.

gambar

Untuk kenyamanan, saya membawa port serial, reset, dan ground ke konektor terpisah untuk pemrograman ulang cepat. Dan kemudian saya tahu sendiri - saya akan mengisi sketsa, dan kemudian satu tidak benar, yang lain salah.

Stabilizer 3.3V juga disolder di sebelahnya, karena RC522, karena kesalahpahaman, ditenagai oleh tegangan ini, sedangkan komponen lainnya terasa hebat pada universal 5V, yang saya harapkan akan diambil dari bank daya sederhana dengan baterai 18650.

gambar

Keputusan untuk menggunakan bank daya seperti itu daripada baterai datar yang khas mungkin tampak berlawanan dengan intuisi. Tapi saya pikir karena mainan akan mengkonsumsi arus yang cukup baik (hanya pengontrol dan pemain dalam mode siaga makan sekitar 40 mA), kemampuan untuk dengan cepat mengganti baterai kosong dengan yang penuh sangat membantu.

Dan saya juga harus menambahkan tweeter piezoceramic untuk indikasi suara dari beberapa peristiwa (membaca kartu, misalnya). Ini, menurut Anda, umumnya lucu - ada pembicara, bukan? Ya, tidak. Bagaimanapun, speaker terhubung ke pemain, dan bukan ke controller. Dan dia menambahkan transistor sebagai kunci, yang mematikan MP3 player saat tidur, untuk mengurangi konsumsi energi.

Pembaca yang penuh perhatian mungkin memperhatikan bahwa pemain dapat ditenagai oleh pin pengontrol digital, yang akan bekerja dengan baik dan mematikan. Saya ingin sendiri, tetapi hanya dalam mode siaga pemain mengkonsumsi 16 mA. Dan ketika musik, dengan mudah membutuhkan lebih dari 100 mA, yang sudah setidaknya dua kali kapasitas ATmega. Oleh karena itu, saya mengambil "setiap" transistor npn dengan arus kolektor 300 mA dan membawanya ke pin digital controller melalui resistor sekitar 200 ohm.

Tetapi pembaca kartu mengkonsumsi dalam waktu 40 mA, sehingga stabilizer yang mengumpankannya dapat dihubungkan ke pin digital pengontrol. Dia melakukannya, tetapi masih tidak berhasil, tentang yang - pada akhirnya.

Poin lain seperti itu: pemain membutuhkan kepala dinamis dengan resistensi setidaknya 8 ohm. Saya punya satu (speaker dari unit sistem), tetapi suaranya tidak terlalu bagus. Ada juga speaker dengan resistansi 4 ohm (dari speaker khas Cina). Secara umum, saya menghubungkan kedua seri: satu memberi lebih tinggi, yang lain memberi rendah, dan bersama-sama mereka terdengar keren.

Tetap sedikit, yaitu cermin jiwa. Yang paling mudah dibuat dari sepasang LED yang terhubung secara seri. Saya tidak mengambil warna merah yang brutal - itu sangat menakutkan. Tapi mata kuning-kuning - itu saja.

Jadi, model mainan itu dirakit dan di-debugged. Sekarang yang paling penting: Anda membutuhkan donor tubuh. Sebenarnya, saya benar-benar menginginkan burung pembicaratapi kalau dilihat dari harga mainan tetangga, kesenangan itu tidak sepenuhnya anggaran. Terutama ketika Anda menganggap bahwa minat anak adalah hal yang tidak dapat diprediksi.

Karena itu, sejak awal, saya mulai mencari kandidat transplantasi yang lebih terjangkau. Dan satu ditemukan: landak Evelyn yang menawan , dijual di Dunia Anak-anak.

gambar

Tentu saja, saya harus hampir sepenuhnya menyingkirkan dunia batin yang kaya dari landak. Dan menggantinya dengan yang buatan sendiri, dikemas dalam sabun biasa. Namun, tidak terlalu biasa. Faktanya adalah bahwa, tidak seperti banyak, hidangan sabun ini memiliki sisi belakang yang rata, jadi nyaman untuk menempatkan pembaca kartu di sana - Anda mendapatkan jarak minimum. Di sisi lain, sabun memiliki sesuatu seperti sikat pijat dan bahkan memiliki lubang, yaitu speaker diletakkan secara ideal di sana: suara akan keluar melalui lubang yang tidak akan terhalang oleh paku pijat. Lubangnya, bagaimanapun, ternyata tidak cukup, tetapi tidak masalah - saya masih mengebor.



Harus saya akui, hal yang paling sulit adalah operasi untuk landak. Pertama, saya tidak suka menjahit. Dan saya harus sopan: pertama saya merobeknya, lalu saya kencangkan ujungnya, kemudian saya menjahit enam tombol. Lalu ia merilis enam tombol dan menjahit empat tombol. Kenapa semua? Karena pada awalnya saya menjahit kecil dan salah, jadi landak itu terlepas.



Kedua, mata. Tentu saja, saya dengan hati-hati memperoleh LED dengan diameter 3 mm, sehingga mereka dapat dijamin untuk menggambarkan siswa. Namun, tidak mudah untuk mengebor lubang di mata landak Evelyn yang ada. Tampaknya: Anda mengambil pengukir, menempatkan bor yang tepat di dalamnya - dan pergi. Tapi ternyata selama pengeboran, plastik berubah menjadi massa kental, di mana bor pengukir yang lemah terjebak erat.

Dan, harus saya katakan, landak dengan bor yang menjulurkan matanya adalah tontonan yang infernal.

Ngomong-ngomong, saya bahkan tidak tahu harus memberi tahu apa tentang ini. Saya entah bagaimana memelintir dan masih membuat lubang, memasukkan LED di dalamnya dan diisi dengan epoksi, dan ditutupi dengan cat kuku tidak berwarna di atasnya. Mata juga terpaku pada landak dengan epoksi, karena gunung asli mati selama proses pengeboran. Hasilnya tidak sempurna, tetapi cukup tertahankan.

Cara kerja landak, sudah Anda lihat. Karena itu, saya hanya dapat menduplikasi teks dari logikanya saat ini. Awalnya, landak dalam mode tidur. Jika Anda mengambilnya (atau hanya memindahkannya, atau memindahkan permukaan tempat ia berada, dll.), Ia akan terbangun oleh interupsi yang akan menghasilkan sensor getaran.

Setelah itu, pada interval yang telah ditentukan, landak akan mengucapkan frasa yang telah ditentukan, dan jika Anda tidak menyentuh landak untuk beberapa waktu, ia akan tertidur lagi. Dan jika Anda menyentuh, itu tidak akan tertidur. Dan jika Anda mengocoknya sebentar, itu akan mulai menceritakan dongeng, dipilih secara acak.

Jika Anda membawa kartu ke landak (ketika dia tidak tidur), maka landak akan mulai menceritakan kisah yang terkait dengan kartu ini. Tidak ada ikatan yang kaku, pesanan akan berubah saat mengganti dongeng. Hanya dua kartu layanan yang diperbaiki: untuk menyesuaikan volume dan secara paksa menidurkan landak. Volume, omong-omong, disesuaikan dengan beralih berurutan dari tiga langkah (diam - sedang - keras).

Adapun mata kuning, mereka berkedip dua kali (dalam satu siklus) ketika landak bangun, tetapi diam dan mengubah kecerahan ketika landak menceritakan dongeng. Bagiku itu pilihan terbaik.

Selama proses perakitan, saya mencoba inovasi lain: karena bank daya memiliki dua konektor (input dan output), saya menghubungkan adaptor pengisian nirkabel Qi yang ada ke input. Dan ternyata untuk mengisi ulang landak, Anda tidak perlu melepaskannya sama sekali - cukup letakkan di charger nirkabel untuk malam itu. Namun, fungsi ini masih dalam mode uji.

Secara umum, meskipun kesederhanaan yang tampak, beberapa hal membingungkan saya. Sebagai contoh, dari kode Anda dapat melihat bahwa saya mengirim beberapa perintah ke pemain beberapa kali berturut-turut, dan bahkan menempatkan batas waktu di akhir. Dan semua karena dalam prakteknya dalam konfigurasi saya satu-satunya cara itu mungkin.

Terlihat juga bahwa untuk beberapa alasan saya mengontrol akhir pemutaran dengan sinyal perangkat keras pemain, alih-alih menyalakan mode pemutaran hanya satu file ke sana dengan perintah sederhana. Ini juga tidak seperti itu: untuk beberapa alasan, mode ini tidak berfungsi untuk saya, jadi ketika akhir satu lagu, pemain mulai memainkan yang berikutnya.

Mungkin tampak lebih aneh bahwa fungsi acak untuk memainkan komposisi acak terus-menerus berputar, alih-alih dipanggil hanya ketika itu benar-benar diperlukan. Tetapi inilah masalahnya: jika Anda menyebutnya hanya ketika dibutuhkan, maka untuk beberapa alasan, dalam sebagian besar kasus, ia mengembalikan nilai yang sama. Tetapi jika Anda menempatkan dalam satu lingkaran, maka nilai benar-benar pseudo-acak dihasilkan. Sebenarnya, saya juga menemukan dalam praktik ketika saya mencoba memahami perilaku landak yang tidak pantas.

Akhirnya, yang benar-benar membuat saya bingung adalah ketidakmampuan untuk mematikan mematikan pembaca kartu menggunakan pin digital controller, dari mana pembaca diaktifkan. Untuk beberapa alasan, ternyata jika pin diatur ke RENDAH dan kemudian ke INPUT, pembaca tidak mati.

Pada saat yang sama, jika Anda hanya mengatur RENDAH, LED pembaca kartu "menyala" sepenuhnya, tegangan pada output dari stabilizer yang memasok pembaca adalah sekitar volt. Jika kemudian pada pin pengontrol melakukan INPUT, tegangan ini naik sekitar 3V.

Lebih menarik lagi bahwa jika Anda pertama-tama mengatur pin pengontrol yang terhubung ke pembaca SS dan RST ke RENDAH dan INPUT, dan kemudian meletakkan pin daya pengontrol di posisi yang sama, pembaca akan mati. Itupun menyala setelah tidur, jika pin power ditransfer ke OUTPUT dan HIGH.

Namun, sesuatu yang tidak dapat diperbaiki dengan timer terjadi. Yaitu, saya kira begitu, karena setelah tipuan seperti itu (tidur dengan pembaca dimatikan), mata dan konter goyang bekerja tidak memadai, dan kedua proses ini terikat ke millis (). Saya tidak tahu apa yang terjadi dan bagaimana mengembalikan timer, jadi saya membiarkannya - pembaca kartu terus makan bahkan selama tidur.

Jika kawan senior membantu menemukan jalan keluar, saya akan sangat berterima kasih. Meskipun saya hampir tidak percaya bahwa kawan yang lebih tua akan membaca ke tempat ini.

Mengingat hal tersebut di atas, kode landak Evelyn sama sekali tidak sempurna, tetapi Anda selalu dapat menyisirnya (kode atau landak - pilih sendiri), optimalkan, tambah, kurangi atau sesuaikan dengan kebutuhan Anda. Itu sebabnya saya melampirkannya. Dan untuk membuatnya lebih mudah untuk menggunakan apa yang ada, pengaturan maksimum (saya mencoba semuanya secara umum, tetapi ternyata seperti biasa) tidak ada dalam kode, tetapi di bagian definisi variabel. Ada konfigurasi pin, dan penundaan waktu, dan jumlah trek.

Pada bagian untuk menggambarkan nomor kartu, harus dipahami bahwa dua kartu terakhir selalu "dicadangkan" untuk fungsi internal - pengalihan volume dan mode tidur.

Program aksi
/*  A0 -   MP3 (  )
 *  pin 0, 1 -   ()
 *  pin 2 -   
 *  pin 4 -   MP3 ( )
 *  pin 5 - 
 *  pin 6 -  
 *  pin 7, 8 -  MP3
 *  pin 9 -  
 *  pin 10 -  
 *  pin 11, 12, 13 - SPI 
 */ 


#include <Arduino.h>
#include <SoftwareSerial.h>
#include <JQ6500_Serial.h>
#include <avr/pgmspace.h> //  PROGMEM
#include <SPI.h>
#include <MFRC522.h>
#include <avr/sleep.h>
#include <avr/power.h>

#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off) 
#define adc_enable() (ADCSRA |= (1<<ADEN)) // re-enable ADC

#define RST_PIN 9
#define SS_PIN 10
#define mp3Pin 4
#define mp3Busy A0
#define readerPin 6
#define tonePin 5
#define ledPin 3
#define offDelay 70000 //  
#define winkStep 1500 //   
#define on 150 //  ""
#define off 80 //  ""
#define tOut1 0 //         (x - / x1 -  )
#define tOut11 500
#define tOut2 14000
#define tOut21 15000
#define tOut3 29000
#define tOut31 30000
#define tOut4 44000
#define tOut41 45000
#define tOut5 60000
#define tOut51 65000
#define tShake 2000 //     
#define nShakeQ 10 //     
#define introQ 5 //  -
#define minVol 18 //  
#define midVol  22 //  
#define maxVol 25 //  


unsigned long dimDelay, winkStepDelay, onDelay, ledOffDelay, tShakeDelay;
boolean ledOn, ledOff, eyes, pwm;
int wink;
int pwmVal;

boolean playON = false;
boolean pwmUp = false;
byte pwmStep = 1;


unsigned int playFile;

MFRC522 mfrc522(SS_PIN, RST_PIN);       //  MFRC522
unsigned long uidDec, uidDecTemp; //       
byte bCounter, readBit, nShake, rnd;
byte vol = midVol; //     
unsigned long ticketNumber;
unsigned long offTimeOut = 0; //   
boolean mp3ON = false; //   
boolean isInt = false; //   

byte ticketQ = 32; //     (  -  )
byte fileQ = 0; //  MP3-

//    (  ,    ),         .   ,    
PROGMEM const uint32_t ticketSet[]  = {2515217196, 2540548337, 2490970856, 2486466332, 2485920633, 35870611, 37836807, 37836806, 2377004330, 2522873668, 2514304566, 23472725, 2485702426, 2374853555, 2374391583, 2492957469, 2486467162, 2489280075, 2488031661, 2491726641, 2491720188, 2490968782, 2490968783, 2488900952, 2489969016, 2506562651, 2375447052, 2375449579, 2489276180, 2483389692, 2486466331, 2484789326};

JQ6500_Serial mp3(8,7); //  

void enterSleep()
{
 mp3.playFileNumberInFolderNumber(01, 005); // -
 mp3.playFileNumberInFolderNumber(01, 005); // -
 delay(2500);
 tone(tonePin, 800, 500);
 delay(500); 
 digitalWrite(readerPin, LOW); 
 digitalWrite(mp3Pin, LOW);
 digitalWrite(ledPin, LOW);
 pinMode(ledPin, INPUT);
 pinMode(readerPin, INPUT);
 pinMode(mp3Pin, INPUT);
 
  adc_disable();

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  
  sleep_enable();
  
  sleep_mode();
  
 sleep_disable();
 power_all_enable();

 adc_enable();
 tone(tonePin, 450, 500);
 pinMode(ledPin, OUTPUT);
 pinMode(readerPin, OUTPUT);
 pinMode(mp3Pin, OUTPUT);
 digitalWrite(ledPin, LOW);
 digitalWrite(readerPin, HIGH); 
 digitalWrite(mp3Pin, HIGH);
 SPI.begin();            //  SPI
 mfrc522.PCD_Init();     //  MFRC522
 mp3Init();
 offTimeOut = millis();
 ledOffDelay = millis();
 mp3.playFileNumberInFolderNumber(01, 001); // -
 mp3.playFileNumberInFolderNumber(01, 001); // -
 delay(500);
 playON = false; 
 mp3ON = true;
}

void wakeUp() {
   detachInterrupt(0);
   ledOffDelay = millis();
   if (isInt == false) { //  
    isInt = true;
   }
   attachInterrupt(0, wakeUp, LOW); 
}

void setup() {
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, wakeUp, LOW);
  pinMode(readerPin, OUTPUT);  
  digitalWrite(readerPin, HIGH);
  SPI.begin();            //  SPI
  mfrc522.PCD_Init();     //  MFRC522
  pinMode(mp3Pin, OUTPUT);
  mp3Init();
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
  eyes = false;
  ledOn = false;
  ledOff = false;
  dimDelay = millis();
  winkStepDelay = millis();
  wink = 0;
  pwmUp = true; //    
  pwmVal = 0;
  ledOffDelay = millis();
  offTimeOut = millis();  
  mp3.playFileNumberInFolderNumber(01, 001); // -
  mp3.playFileNumberInFolderNumber(01, 001); // -
  delay(500);
  playON = false; 
  mp3ON = true;
}

void loop() {

rnd = random(1, fileQ-1);

if ((millis() - offTimeOut) > offDelay) { //  

     enterSleep();

 } else { 

 ledWink(); //   


 if (isInt == true) {
  
  offTimeOut = millis(); //    -  ,    

  if (nShake == 0) {
    tShakeDelay = millis();
  }
  
  if ((millis() - tShakeDelay) < tShake){
    nShake = nShake + 1;
  } else {
    tShakeDelay = millis();
    nShake = 0;
  }

   isInt = false;
 }

 if (nShake > nShakeQ) {
  playRandom();
  nShake = 0;
 }

//    

playPreset(); //     


//   
  if (mp3ON == true) {
   
   if (playON == true) { //  ,   
    offTimeOut = millis(); //   
   }

   nShake = 0;

   eyesPWM(); //  
   

    //  MP3
    if(analogRead(mp3Busy) < 250) { //    -  ,  
     mp3ON = false; 
     playON = false;
     digitalWrite(ledPin, LOW);
    }
  }
  
 scanPlay(); //   
 
 }
}


void setBitsForGood(byte daBeat) {


  
        if (daBeat == 1) {
                bitSet(ticketNumber, bCounter);
                bCounter=bCounter+1;
                }
        else {
                bitClear(ticketNumber, bCounter);
                bCounter=bCounter+1;
        }
}

//    MP3
void mp3Init() {
  digitalWrite(mp3Pin, HIGH);
  delay(100);
  mp3.begin(9600);
  mp3.reset();
  mp3.setVolume(vol);
  mp3.setLoopMode(MP3_LOOP_NONE);

  fileQ = mp3.countFiles(MP3_SRC_SDCARD); //    
  fileQ = fileQ - introQ; //  

}


//   
void playRandom() {
   tone(tonePin, 450, 500);
   delay(500);  
   playFile = rnd;
   mp3ON = true;
   playON = true;
   mp3.playFileByIndexNumber(playFile);
   mp3.playFileByIndexNumber(playFile);
   mp3.playFileByIndexNumber(playFile);  
   delay(500);
}

// 
void ledWink() {

 //     
if ((millis() - winkStepDelay) > winkStep) { //  

// 
  if (eyes == true) { //   

    if (ledOn == false) {
      onDelay = millis(); //  
        ledOn = true; //  ,   
    }
 
    if ((millis() - onDelay) > on) { //   
      digitalWrite(ledPin, LOW); //   
      eyes = false; //   
    }

  }

// 
  if (eyes == false) { //   
    
    if (ledOff == false) {
      ledOffDelay = millis(); //  
        ledOff = true; //  ,   
    }

    if ((millis() - ledOffDelay) > off) { //   
      digitalWrite(ledPin, HIGH); //  
      eyes = true; //   
    }
  }

  if (ledOn == true && ledOff == true) { //    (  /)
    wink = wink+1;
    ledOn = false;
    ledOff = false;    
  }

  if (wink == 4) { //   /
     winkStepDelay = millis();
     wink = 0;
 }

 }

}

//     
void playPreset() {

 if (mp3ON == false) {
  
  if ((millis() - offTimeOut) > tOut2 && (millis() - offTimeOut) < tOut21) {
    mp3.playFileNumberInFolderNumber(01, 002); //   /001/002.mp3      tOut21 .
    mp3ON = true; 
    delay(500);
  }

  if ((millis() - offTimeOut) > tOut3 && (millis() - offTimeOut) < tOut31) {
    mp3.playFileNumberInFolderNumber(01, 003); //   /001/003.mp3      tOut31 .
    mp3ON = true;
    delay(500);
   }  

  if ((millis() - offTimeOut) > tOut4 && (millis() - offTimeOut) < tOut41) {
    mp3.playFileNumberInFolderNumber(01, 004); //   /001/004.mp3      tOut41 .
    mp3ON = true;  
    delay(500); 
  }    

    
 }
  
}


// 
void eyesPWM(){

 if ((millis() - winkStepDelay) > (pwmStep)/4) {
   //     MP3 
    if (pwmUp == true) {
      if (pwmVal < 128) { //   254 -    (    255,      )
        analogWrite(ledPin, pwmVal);
        pwmVal = pwmVal + 1;
        pwmStep = pwmStep - 1;
        winkStepDelay = millis();
      } else {
            pwmUp = false;
            pwmStep = 1;
            pwmVal = 128;
      } 
    }
    
    if (pwmUp == false) {
      if (pwmVal > pwmStep) {
        analogWrite(ledPin, pwmVal);
        pwmVal = pwmVal - 1;
        pwmStep = pwmStep +1 ;
        winkStepDelay = millis();
      } else {
            pwmUp = true;
            pwmStep = 128;
            pwmVal = 1;
      } 
    }
    }
  
}

//   
void scanPlay() {

 if (fileQ > 0) {
          //   
        if ( ! mfrc522.PICC_IsNewCardPresent()) {
                return;
        }

        //  
        if ( ! mfrc522.PICC_ReadCardSerial()) {
                return;
        }

        uidDec = 0;

//   ,   

        byte status;
        byte byteCount;
        byte buffer[18]; //   (16  + 2   ) 
        byte pages[2]={4, 8}; //   
        byte pageByte; //   
        
        byteCount = sizeof(buffer);
        byte bCount=0;
                

        mfrc522.MIFARE_Read(4, buffer, &byteCount);
        
          
                                bCounter = 0; // 32-   
                                
                                //  0-3
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[6], (bCount+4));
                                        setBitsForGood(readBit);
                                }

                                //  4 - 27
                                for (pageByte=5; pageByte > 2; pageByte--) {
                                        for (bCount=0; bCount<8; bCount++) {
                                                readBit = bitRead(buffer[pageByte], bCount);
                                                setBitsForGood(readBit);
                                        }
                                }

                                //  28-31
                                for (bCount=0; bCount<4; bCount++) {
                                        readBit = bitRead(buffer[2], bCount);
                                        setBitsForGood(readBit);
                                }

                               for (byte ticketNum = 0; ticketNum < ticketQ; ticketNum++) {
                                unsigned long ticketTemp = pgm_read_dword_near(ticketSet + ticketNum);
                                if (ticketTemp == ticketNumber) {
                                  tone(tonePin, 450, 500);
                                  delay(500); 
                                  if (ticketNum < (ticketQ - 2)) {
                                    if ((ticketNum+1) < fileQ) {
                                      digitalWrite(ledPin, HIGH);
                                       playFile = ticketNum+1;
                                      mp3ON = true;
                                      playON = true;
                                      mp3.playFileByIndexNumber(playFile);
                                      mp3.playFileByIndexNumber(playFile);
                                      mp3.playFileByIndexNumber(playFile);
                                      delay(500);
                                      }
                                      return;
                                  } else {
                                    if (ticketNum == ticketQ-1) {
                                      enterSleep(); // 
                                    }
                                    if (ticketNum == ticketQ-2) {
                                      setVol(); //  
                                    }
                                  }
                                  
                                }
                               }
                        // }
                
        // Halt PICC
    mfrc522.PICC_HaltA();    


  }
  
}

//    
void setVol() {

  switch (vol) {
    case maxVol:
      vol = minVol;
      break;
    case midVol:
      vol = maxVol;
      break;
    case minVol:
      vol = midVol;
      break;
  } 

  mp3.setVolume(vol);
  
}




Diagram yang kira-kira dipulihkan oleh kode akan terlihat seperti ini (saya minta maaf jika kesalahan saya tetap ada):





Di sini:

  • U1 = ATmega328p
  • UHT7333 = HT7333
  • C1 = 0,1
  • R2 = ~50
  • R3 = 220
  • R4 = 1
  • M1 =
  • R4 = 1
  • SP1 = 8
  • Piezo =
  • T1 = NPN- 0,3
  • U2 = JQ6500 : 1 тАФ TX, 2 тАФ RX, 3 тАФ GND, 4 тАФ VCC, 5 тАФ BUSY, 6 тАФ SPK+, 7 тАФ SPK -


Habrauser Chigin , yang banyak terima kasih kepadanya, terlihat membaik dan menata semua ekonomi ini. Tetapi perhatikan bahwa transistor PNP sudah ada di sini, dan manajemen daya pemain harus dibalik (mis., Dengan koneksi ini, pemain menyala rendah pada pin pengontrol dan mati - tinggi):



Dengan konfigurasi saat ini, baterai dengan kapasitas sekitar 2500 mAh cukup untuk sekitar sehari gunakan landak. Tidak banyak bicara, tetapi Anda perlu memahami bahwa jadwalnya selalu berbeda dan sebagian besar energi dihabiskan, saya harap, dalam mode aktif. Yang sampai batas tertentu memungkinkan kita untuk mengabaikan penarikan lengkap gagal semua elektronik landak menjadi tidur.

Jika Anda kesulitan menghitung sendiri perkiraan anggaran, Anda akan mendapatkan sesuatu seperti ini (dalam USD):

  • Pemain: 8.9
  • ATmega328p: 1.1
  • Papan Pengembangan: 0.28
  • Pembaca RC522: 2.21
  • Kepala Dinamis: 0,99
  • Emitor piezoceramic: 0,77
  • LED: 0,12
  • Transistor: 0,14
  • Stabilizer: 0,13
  • Sensor getaran: 0.13
  • Sabun cuci piring: 0,99
  • Powerbank: 0,75
  • Baterai 18650: 3,9
  • Adaptor Pengisian Qi: 1.65
  • Kartu memori: 3
  • Landak Evelyn: 6


Sebanyak 31,06, tetapi sebenarnya sedikit lebih, karena Anda masih membutuhkan kawat untuk koneksi dan hal-hal kecil lainnya seperti perekat lelehan panas, pita dua sisi dan pita listrik biru.

Mungkin harus ada semacam frase terakhir yang sangat penting, tetapi saya pasti tidak memilikinya di kepala saya. Mungkin masuk akal untuk mengatakan bahwa anak itu cukup senang dengan mainan itu, dan ini jelas lebih baik (dan seringkali lebih cepat) daripada menyalakan laptop.

ps. Saya mengetahui tentang speaker Bluetooth, ini sedikit berbeda, bahkan jika Anda meletakkan landak yang imut.

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


All Articles