Igel - ein sprechender Vogel [wenn mit einem MP3-Player]



    Vor langer Zeit, so sehr, dass es schon falsch schien, erzählte das Masterkit von einem wunderbar eingebauten MP3-Player , mit dem Sie alles ausstatten können, sogar MP3-Player, wenn Sie zuerst Ihren eigenen herausnehmen und dann diesen herausnehmen. Kurz gesagt, eine nützliche Sache. Vor allem, wenn Sie ein Kinderspielzeug herstellen wollen, erstens mit Ihren eigenen Händen und zweitens richtig und nicht wie diejenigen, die es im industriellen Maßstab herstellen.

    In dem vorgestellten Produkt war ich jedoch nicht nur mit allem zufrieden, also dachte ich: Es könnte nicht so etwas geben, das in chinesisch aussehenden Dingen auf Aliexpress nicht vorkommt. In der Tat gab es eine Reihe solcher Spieler, und die Kenntnis der Modellpalette zeigte, dass es attraktivere Optionen gibt als Modelle mit festem Speicher. Das heißt - mit einem Steckplatz für austauschbare microSD-Karten.

    Und es hat angefangen.



    Um klar zu machen, was und wohin es ging, die Igel-Demo in verschiedenen Modi.

    Unterhaltsame Sätze während des Wartens:



    Geschichten wechseln, Lautstärke schalten, Karten ausschalten und rütteln:



    Drahtloses Laden:



    Bevor ich mit der Geschichte fortfahre, entschuldige ich mich für die Tatsache, dass ich einige Ungenauigkeiten in der Beschreibung und dem Schaltungsdesign zulassen kann, da ich dabei nichts dokumentiert habe, alles ist sozusagen aus einer Laune heraus. Bitte verwenden Sie gesunden Menschenverstand und praktisches Material, damit es nicht unerträglich schmerzhaft wird.

    Nach einer kurzen Suche und Vergleichen wechselte ich zu Ebay, wo ich kaufte, was ich wollte - einen Player mit einem JQ6500-Decoder-Chip, 4 MB internen Speicher und einem Steckplatz für microSD .



    Warum dieser bestimmte Spieler? Weil mir dann schien, dass dies eine ideale Option für hausgemachtes ist. Da alles mit ihm. Wenn Sie möchten, verwenden Sie sie separat: Dazu gibt es Play / Pause-Pins, Spurwechsel, Lautstärke, schnelle Wiedergabe von fünf Spuren und einen Monoverstärker, um den Lautsprecher direkt an die Platine anzuschließen (es gibt einen Stereo-Ausgang, der jedoch bereits einen externen Verstärker benötigt). Das heißt, mindestens genug Batterien, Lautsprecher, ein paar Tasten und eine Speicherkarte mit Musik.

    Bild

    Interessanter ist jedoch die vollständige Steuerung des Players durch einen Anschein einer seriellen Schnittstelle. Hier können Sie alles tun - spielen, stoppen, die Lautstärke ändern, den Equalizer- und den Wiedergabemodus wechseln, beliebige Spuren sowohl in der Passthrough-Reihenfolge als auch in bestimmten Ordnern abspielen. Und nicht zuletzt in meinem Fall gab es bereits eine fertige Bibliothek für Arduino.

    So sind bereits zwei Komponenten bekannt: der Player und der Arduino. Aber persönlich wollte ich nicht damit aufhören, weil es töricht ist, Knöpfe mit einem ganzen Mikrocontroller zu imitieren. Um bei Emelya sozusagen und bei Hechten etwas Besonderes zu tun, braucht es etwas Besonderes.

    Daher wurden hier der einfachste Schwingungssensor SW-18010P und der bekannte Kartenleser RC522 hinzugefügt.

    Bild

    Alles nur, um die Knöpfe, die ich in einem Unterhaltungsspielzeug für unnötig hielt, vollständig zu beseitigen. Beurteilen Sie selbst: Wenn es Knöpfe gibt, drückt das Kind sie irgendwie öfter aus Versehen als absichtlich. Das Umschalten von Märchen ist aber immer noch nicht ganz richtig.

    Bild

    Hier stellt sich heraus: Ein Vibrationssensor dient zum Einschalten eines Spielzeugs, wenn ein Kind es in die Hand nimmt. Derselbe Sensor lässt das Spielzeug nicht ausschalten, bis das Kind es ausreichend lange platziert hat. Was den Mifare-Kartenleser angeht, ist dieses Ding meiner Meinung nach äußerst praktisch, um die Geschichten zu wechseln. Zum Beispiel können Karten an Bücher angehängt werden, und dann kann das Kind ein Märchen hören und das Spielzeug zum Buch bringen.

    Und noch können Karten an verschiedene Themen angehängt werden, und das Kind kann dann seine Beschreibung und seine Benutzungsregeln anhören. Zum Beispiel, dass diese weiße Figur ein Kühlschrank ist, und dass wir Produkte dort lagern, damit sie sich nicht verschlechtern, und dass es sich deshalb nicht lohnt, sie zu öffnen. Oder so etwas ist ein Ofen, und es kann heiß sein, so dass Sie nicht an seinem Griff hängen und Ihre Handflächen auf das Glas legen müssen. Sie können sich viele Dinge einfallen lassen, zumal die Karten U-Bahn-Tickets sind (ja, ich hatte Glück, ich bin in Moskau), die Sie leicht in der richtigen Menge sammeln können.

    Während ich darüber nachdachte , habe ich den ATmega328p- Controller in der Zwischenzeit nicht mehr auf Lager , löte ihn an das Mock-Up- Tuch und flickte den Adruino-Lader durch den Arduino Mega 2560.

    Bild

    Zur Vereinfachung bringen Sie den seriellen Anschluss, den Reset und die Erdung an einen separaten Anschluss zur schnellen Neuprogrammierung. Und dann kenne ich mich selbst - ich werde die Skizze ausfüllen, und dann ist eine Sache falsch, die andere ist falsch.

    In der Nähe gelötet noch und Stabilisator 3,3V als RC522 fälschlicherweise isst genau diese Spannung, während die übrigen Komponenten gedeihen auf universellen 5V, die ich von nehmen erwartete anspruchslos pauerbanka von Batterietyp 18650.

    Bild

    Die Entscheidung , solche pauerbank zu verwenden , anstatt Eine typische leere Batterie kann unlogisch erscheinen. Aber ich dachte, da das Spielzeug einen ziemlich anständigen Strom verbraucht (nur der Controller und der Player im Standby-Modus verbrauchen etwa 40 mA), ist es sehr nützlich, einen leeren Akku schnell durch einen vollen zu ersetzen.

    Und ich musste einen Piezokeramik-Quietscher hinzufügen, um bestimmte Ereignisse (z. B. Lesen einer Karte) als Ton anzuzeigen. Sie sagen, das ist im Allgemeinen lächerlich - es gibt einen Sprecher, oder? Na ja, nicht so. Der Lautsprecher ist an den Player angeschlossen, nicht an den Controller. Außerdem wurde ein Transistor als Schlüssel hinzugefügt, der den MP3-Player im Ruhezustand ausschaltet, um den Stromverbrauch zu reduzieren.

    Ein aufmerksamer Leser kann feststellen, dass der Player über einen digitalen Pin des Controllers mit Strom versorgt werden kann, was das Ein- und Ausschalten des Computers ausgezeichnet hätte. Ich hätte das gerne, aber das nur im Standby-Modus verbraucht der Player 16 mA. Und wenn die Musik läuft, braucht es leicht mehr als 100 mA, was mindestens doppelt so hoch ist wie bei ATmega. Daher nahm ich einen "beliebigen" npn-Transistor mit einem Kollektorstrom von 300 mA und brachte ihn über einen Widerstand von etwa 200 Ohm an den digitalen Pin des Controllers.

    Der Kartenleser verbraucht jedoch weniger als 40 mA, sodass der Stabilisator, mit dem er gespeist wird, an den digitalen Pin des Controllers angeschlossen werden kann. Er tat es, aber es hat immer noch nicht geklappt, worüber - am Ende.

    Ein weiterer solcher Moment: Der Spieler benötigt einen dynamischen Kopf mit einem Widerstand von mindestens 8 Ohm. Ich hatte einen (einen Lautsprecher von der Systemeinheit), aber der Ton war nicht sehr gut. Es gab auch 4-Ohm-Lautsprecher (von einem typischen chinesischen Sprecher). Im Allgemeinen habe ich beides in Serie geschaltet: Einer gibt mehr High, der andere Low und zusammen klingen sie einfach großartig.

    Es gibt eine Kleinigkeit, d.h. der Spiegel der Seele Dies ist am einfachsten, wenn ein Paar LEDs in Reihe geschaltet wird. Brutal-Rot nahm nicht - sehr beängstigend. Aber die bernsteinfarbenen Augen - am meisten.

    So wird das Layout des Spielzeugs zusammengebaut und debuggt. Nun das Wichtigste: Sie brauchen einen Spender der physischen Hülle. Eigentlich wollte ich wirklich einen SchwätzerAber nach dem Preis benachbarter Spielzeuge zu urteilen, ist das Vergnügen nicht genau das Budget. Insbesondere wenn Sie der Meinung sind, dass das Interesse des Kindes nicht vorhersagbar ist.

    Daher suchte ich zunächst nach einem besser zugänglichen Kandidaten für die Transplantation. Und dies wurde gefunden: eine charmante Igel Evelyn , die in der Kinderwelt verkauft wurde.

    Bild

    Natürlich musste ich die reichhaltige Innenwelt des Igels fast vollständig loswerden. Und ersetzen Sie es durch hausgemachte, verpackt in einer normalen Seifenkiste. Allerdings nicht ganz normal. Tatsache ist, dass diese Seifenkiste, im Gegensatz zu vielen anderen, eine flache Rückseite hat, so dass es praktisch ist, einen Kartenleser dort zu platzieren. Andererseits ist die Seifenschale so etwas wie eine Massagebürste und es gibt sogar Löcher, d.h. Es gibt einen perfekt platzierten Lautsprecher: Der Ton wird durch die Löcher ausgegeben, die nicht durch die Massagespitzen blockiert werden. Löcher waren jedoch nicht genug, aber es spielt keine Rolle - ich bin immer noch nasverlil.



    Am schwierigsten, ich muss zugeben, war eine Igeloperation. Erstens mag ich es nicht zu nähen. Und es war anständig nötig: Zuerst wurde es aufgerissen, dann wurden die Ränder versiegelt, dann wurden sechs Knöpfe genäht. Dann öffnete er sechs Knöpfe und nähte vier Knöpfe. Warum alle? Denn ich habe zuerst klein und falsch genäht, so dass der Igel aufgeknöpft wurde.



    Zweitens die Augen. LEDs haben mir natürlich einen Durchmesser von 3 mm beschafft, damit die Pupillen abgebildet werden können. Das Bohren von Löchern in die Augen des Igels Evelyn war jedoch nicht so einfach. Es sieht so aus: Man nimmt einen Stecher, steckt den nötigen Bohrer hinein - und macht weiter. Es stellte sich jedoch heraus, dass der Kunststoff während des Bohrens zu einer viskosen Masse wird, in der der Bohrer eines schwachen Graveurs fest wird.

    Und ich muss sagen, ein Igel mit einem Bohrer, der aus seinem Auge ragt, ist ein höllischer Anblick.

    Übrigens weiß ich bei dieser Gelegenheit nicht einmal, was ich raten soll. Irgendwie verdrehte ich und machte immer noch Löcher, steckte LEDs hinein und füllte sie mit Epoxid, und oben deckte ich farblosen Nagellack auf. Die Augen klebten auch mit Epoxid am Igel, da das native Mount während des Bohrvorgangs starb. Das Ergebnis war nicht perfekt, aber durchaus erträglich.

    Wie der Igel funktioniert, hast du schon gesehen. Daher kann ich nur den Text seiner aktuellen Logik kopieren. Anfangs befindet sich der Igel im Schlafmodus. Wenn Sie es in die Hand nehmen (oder einfach nur bewegen oder die Oberfläche verschieben, auf der es liegt usw.), wird es durch eine Unterbrechung aufgeweckt, die vom Vibrationssensor erzeugt wird.

    Danach gibt der Igel in festgelegten Abständen vordefinierte Phrasen aus, und wenn Sie den Igel längere Zeit nicht berühren, schläft er wieder ein. Und wenn Sie berühren - nicht einschlafen. Und wenn Sie einige Zeit schütteln, beginnt ein Märchen zu erzählen, das in zufälliger Reihenfolge ausgewählt wird.

    Wenn Sie eine Karte zu einem Igel bringen (wenn er wach ist), beginnt der Igel, ein mit dieser Karte verbundenes Märchen zu erzählen. Es gibt keine starre Bindung, die Reihenfolge ändert sich, wenn Märchen ersetzt werden. Es sind nur zwei Servicekarten fixiert: zum Anpassen des Volumens und zum Schlafen des Igels. Die Lautstärke wird übrigens durch aufeinanderfolgendes Schalten von drei Stufen eingestellt (stumm - mittel - laut).

    Die bernsteinfarbenen Augen blinken zweimal (in einem Zyklus), wenn der Igel erwachte, aber er ist stumm und ändert seine Helligkeit, wenn der Igel ein Märchen erzählt. Es schien mir die beste Option.

    Bei der Montage habe ich eine weitere Innovation ausprobiert: Da die Powerbank zwei Anschlüsse (Eingang und Ausgang) hat, habe ich den drahtlosen Qi-Ladeadapter an den Eingang angeschlossen. Und so stellte sich heraus, dass es zum Aufladen des Igels überhaupt nicht erforderlich ist - legen Sie ihn einfach für die Nacht in das drahtlose Ladegerät. Nur diese Funktion befindet sich jedoch noch im Testmodus.

    Trotz der scheinbaren Einfachheit verwirrten mich einige Dinge. Zum Beispiel können Sie anhand des Codes feststellen, dass ich einige Befehle mehrmals hintereinander an den Player schicke und am Ende auch ein Timeout festlege. Und das alles, weil es in meiner Konfiguration nur möglich ist.

    Es zeigt auch, dass ich aus irgendeinem Grund das Ende der Wiedergabe mit dem Hardwaresignal des Players kontrolliere, anstatt mit einem einfachen Befehl, damit nur eine Datei abgespielt werden kann. Dies ist auch nicht einfach: Aus irgendeinem Grund funktioniert dieser Modus nicht für mich. Wenn also ein Song endet, beginnt der Player den nächsten zu spielen.

    Es mag merkwürdig erscheinen, dass die zufällige Funktion einer zufälligen Komposition ständig in einer Schleife gedreht wird, anstatt nur aufgerufen zu werden, wenn sie wirklich benötigt wird. Aber es gibt so etwas: Wenn Sie es nur aufrufen, wenn es benötigt wird, liefert es in den meisten Fällen denselben Wert. Wenn Sie jedoch eine Schleife einfügen, werden wirklich pseudozufällige Werte generiert. Eigentlich habe ich das auch in der Praxis erfahren, als ich versuchte, das unangemessene Verhalten des Igels zu verstehen.

    Was mich völlig verblüfft hat, war die Unfähigkeit, den Kartenleser mit Hilfe einer digitalen Pin des Controllers, von der der Leser mit Strom versorgt wird, auszuschalten. Aus irgendeinem Grund stellt sich heraus, dass sich der Leser nicht ausschaltet, wenn der Pin auf LOW und dann auf INPUT gesetzt ist.

    Wenn Sie einfach nur LOW einstellen, leuchtet die LED des Kartenlesers vollständig auf, und die Spannung am Ausgang des Stabilisators, der den Leser versorgt, beträgt etwa ein Volt. Liegt dann am Pin des Controllers INPUT an, steigt diese Spannung auf ca. 3V an.

    Noch interessanter ist es, wenn Sie die Controller-Pins, die mit dem SS- und RST-Lesegerät verbunden sind, zuerst auf LOW und INPUT setzen und dann den Spannungsversorgungs-Pin des Controllers in dieselbe Position bringen, dass sich das Lesegerät ausschaltet. Und selbst dann schaltet es sich nach dem Ruhezustand ein, wenn der Power-Pin in OUTPUT und HIGH übersetzt wird.

    Dies geschieht jedoch mit Zeitschaltern nicht wiedergutzumachend. Ich denke also, weil nach einem solchen Trick (Schlaf mit Abschalten des Lesers) die Augen und der Schüttelzähler unzureichend funktionieren und beide Prozesse an Millis () gebunden sind. Was passiert und wie der Timer wiederhergestellt werden kann, weiß ich nicht, also habe ich es jetzt so belassen wie er ist - der Kartenleser zieht auch im Schlaf weiter ein.

    Wenn ältere Genossen helfen werden, einen Ausweg zu finden, bin ich sehr dankbar. Obwohl es kaum zu glauben ist, dass ältere Genossen diesen Ort gelesen haben.

    Davon abgesehen ist Evelyns Igel-Code überhaupt nicht perfekt, aber Sie können ihn jederzeit kämmen (Code oder Igel - wählen Sie ihn selbst), optimieren, hinzufügen, verkürzen oder anderweitig an Ihre Bedürfnisse anpassen. Deshalb befestige ich es. Und um die Verwendung zu vereinfachen, ist das Maximum an Einstellungen (ich habe alles versucht, aber es stellte sich als üblich heraus) nicht im Code, sondern im Abschnitt zum Definieren von Variablen. Es gibt eine Pin-Konfiguration, Zeitverzögerungen und die Anzahl der Spuren.

    Im Abschnitt mit den Kartennummern ist zu verstehen, dass die letzten beiden Karten immer für interne Funktionen reserviert sind - Lautstärke- und Schlafumschaltung.

    Aktionsprogramm
    /*  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 // высокая громкостьunsignedlong dimDelay, winkStepDelay, onDelay, ledOffDelay, tShakeDelay;
    boolean ledOn, ledOff, eyes, pwm;
    int wink;
    int pwmVal;
    boolean playON = false;
    boolean pwmUp = false;
    byte pwmStep = 1;
    unsignedint playFile;
    MFRC522 mfrc522(SS_PIN, RST_PIN);       // объект MFRC522unsignedlong uidDec, uidDecTemp; // для отображения номера карточки в десятичном формате
    byte bCounter, readBit, nShake, rnd;
    byte vol = midVol; // уровень громкости при включении среднийunsignedlong ticketNumber;
    unsignedlong offTimeOut = 0; // счетчик таймера автовыключения
    boolean mp3ON = false; // флаг включенного плеера
    boolean isInt = false; // флаг прерывания 
    byte ticketQ = 32; // количество карточек минус два (резерв на карточку-выключатель и громкость)
    byte fileQ = 0; // счетчик MP3-файлов// массив номеров карточек (в десятичном виде, написан на самой карточке), последние две служат для переключения громкости и режима сна. Заполните своими номерами, текущие только для примера
    PROGMEM constuint32_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); // объект плеераvoidenterSleep(){
     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;
    }
    voidwakeUp(){
       detachInterrupt(0);
       ledOffDelay = millis();
       if (isInt == false) { // флаг прерывания
        isInt = true;
       }
       attachInterrupt(0, wakeUp, LOW); 
    }
    voidsetup(){
      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;
    }
    voidloop(){
    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(); // мерцание глаз// Воспроизведение MP3if(analogRead(mp3Busy) < 250) { // если на паузе - сброс флагов, выключение лампочек
         mp3ON = false; 
         playON = false;
         digitalWrite(ledPin, LOW);
        }
      }
     scanPlay(); // воспроизведение по карточке
     }
    }
    voidsetBitsForGood(byte daBeat){
            if (daBeat == 1) {
                    bitSet(ticketNumber, bCounter);
                    bCounter=bCounter+1;
                    }
            else {
                    bitClear(ticketNumber, bCounter);
                    bCounter=bCounter+1;
            }
    }
    // ВКЛЮЧЕНИЕ И ИНИЦИАЛИЗАЦИЯ MP3voidmp3Init(){
      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; // минус заставки
    }
    // ВОСПРОИЗВЕДЕНИЕ СЛУЧАЙНОГО ФАЙЛАvoidplayRandom(){
       tone(tonePin, 450, 500);
       delay(500);  
       playFile = rnd;
       mp3ON = true;
       playON = true;
       mp3.playFileByIndexNumber(playFile);
       mp3.playFileByIndexNumber(playFile);
       mp3.playFileByIndexNumber(playFile);  
       delay(500);
    }
    // МОРГАНИЕvoidledWink(){
     // Моргание диодами в режиме ожидания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;
     }
     }
    }
    // ВОСПРОИЗВЕДЕНИЕ ЗАДАННЫХ ФРАЗ ПРИ ПАУЗЕvoidplayPreset(){
     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); 
      }    
     }
    }
    // МЕРЦАНИЕvoideyesPWM(){
     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;
          } 
        }
        }
    }
    // ФУНКЦИИ ПО КАРТОЧКЕvoidscanPlay(){
     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-3for (bCount=0; bCount<4; bCount++) {
                                            readBit = bitRead(buffer[6], (bCount+4));
                                            setBitsForGood(readBit);
                                    }
                                    // биты 4 - 27for (pageByte=5; pageByte > 2; pageByte--) {
                                            for (bCount=0; bCount<8; bCount++) {
                                                    readBit = bitRead(buffer[pageByte], bCount);
                                                    setBitsForGood(readBit);
                                            }
                                    }
                                    // биты 28-31for (bCount=0; bCount<4; bCount++) {
                                            readBit = bitRead(buffer[2], bCount);
                                            setBitsForGood(readBit);
                                    }
                                   for (byte ticketNum = 0; ticketNum < ticketQ; ticketNum++) {
                                    unsignedlong 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();    
      }
    }
    // РЕГУЛИРОВКА ГРОМКОСТИ ПО КАРТОЧКЕvoidsetVol(){
      switch (vol) {
        case maxVol:
          vol = minVol;
          break;
        case midVol:
          vol = maxVol;
          break;
        case minVol:
          vol = midVol;
          break;
      } 
      mp3.setVolume(vol);
    }
    



    Das durch den Code ungefähr wiederhergestellte Schema sollte folgendermaßen aussehen (ich entschuldige mich, wenn meine Fehler irgendwo geblieben sind):





    Hier:

    • U1 = ATmega328p
    • UHT7333 = HT7333
    • Kondensator C1 = 0,1 μF
    • R2 = ~ 50 Ohm
    • Widerstand R3 = 220 Ohm
    • Widerstand R4 = 1 kΩ
    • M1 = Vibrationssensor
    • Widerstand R4 = 1 kΩ
    • SP1 = 8 Ohm Lautsprecher
    • Piezo = piezokeramischer Heizkörper
    • T1 = geeigneter NPN-Transistor mit einem Kollektorstrom von mindestens 0,3A
    • U2 = JQ6500 mit folgender Pinbelegung: 1 - TX, 2 - RX, 3 - GND, 4 - VCC, 5 - BUSY, 6 - SPK +, 7 - SPK -


    Habrayuzer Chigin , für den vielen Dank an ihn, hat sich spürbar verbessert und die gesamte Wirtschaft in Ordnung gebracht. Beachten Sie jedoch, dass der PNP-Transistor bereits vorhanden ist und das Power-Management des Players invertiert werden muss (dh, bei dieser Verbindung schaltet der Player auf dem Controller-Pin auf Low und auf High):



    Bei der aktuellen Konfiguration des Akkus mit einer Kapazität von etwa 2500 mAh dauert der Tag etwa einen Tag benutze einen Igel Um nicht so viel zu sagen, aber wir müssen verstehen, dass der Zeitplan ständig anders ist und die meiste Energie im aktiven Modus, so hoffe ich, aufgewendet wird. Dies lässt zu einem gewissen Grad den vernachlässigten vollständigen Abzug der gesamten Igelelektronik in den Schlaf vernachlässigen.

    Wenn Sie sich die Mühe machen, das ungefähre Budget zu berechnen, erhalten Sie Folgendes (in USD):

    • Spieler: 8.9
    • ATmega328p: 1,1
    • Entwicklungsboard: 0,28
    • Leser RC522: 2.21
    • Dynamischer Kopf: 0,99
    • Piezokeramik-Emitter: 0,77
    • LED: 0,12
    • Transistor: 0,14
    • Stabilisator: 0,13
    • Vibrationssensor: 0,13
    • Seifenschale: 0,99
    • Powerbank: 0,75
    • 18650 batterie: 3.9
    • Qi-Ladeadapter: 1,65
    • Speicherkarte: 3
    • Igel Evelyn: 6


    Insgesamt 31.06, aber in der Tat etwas mehr, denn Sie brauchen noch einen Draht für Verbindungen und andere Kleinigkeiten wie Schmelzkleber, doppelseitiges Klebeband und blaues Isolierband.

    Vielleicht sollte es einen besonders wichtigen Schlusssatz geben, aber in meinem Kopf existiert er definitiv nicht. Es ist wahrscheinlich sinnvoll zu sagen, dass das Kind mit dem Spielzeug ziemlich zufrieden ist, und dies ist definitiv besser (und oft schneller) als das Einschalten des Laptops.

    ps. Ich kenne mich mit Bluetooth-Lautsprechern aus, ein bisschen anders, selbst wenn man so einen niedlichen Igel steckt.

    Jetzt auch beliebt: