Hérisson - oiseau qui parle [si avec un lecteur MP3]



Il y a longtemps, à tel point que cela semble déjà faux, masterkit a parlé d'un merveilleux lecteur MP3 intégré qui peut être équipé de tout, même des lecteurs MP3, si vous en retirez d'abord le vôtre, puis mettez celui-ci. Bref, une chose utile. Surtout si vous voulez fabriquer un jouet pour enfants, d'une part, avec vos propres mains, et, d'autre part, correctement, et non de la manière dont pensent ceux qui les fabriquent à l'échelle industrielle.

Cependant, dans le produit présenté, je n'étais pas seulement satisfait de tout, alors j'ai pensé: il ne peut pas être tel que la chose d'aspect chinois ne soit pas sur Aliexpress. En effet, il y avait un certain nombre de ces acteurs, et la familiarisation avec la gamme de modèles a montré qu'il existe des options plus attrayantes que les modèles avec une quantité fixe de mémoire. À savoir - avec un emplacement pour les cartes microSD amovibles.

Et c'est parti.



Pour que ce soit clair et où il est allé, une démo de hérisson dans différents modes.

Des phrases divertissantes en attendant:



Activation et désactivation des contes, du volume avec des cartes et des tremblements:



Charge sans fil:



Avant de poursuivre l'histoire, je m'excuse de pouvoir faire quelques inexactitudes dans la description et les circuits, car dans le processus, je n'ai rien documenté, pour ainsi dire, sur une intuition. Veuillez utiliser le bon sens et des documents pratiques pour que plus tard cela ne soit pas atrocement douloureux.

Donc, après une brève recherche et comparaison, je suis passé à Ebay, où j'ai obtenu ce que je voulais - un lecteur avec une puce de décodeur JQ6500, 4 mégaoctets de mémoire interne et un slot microSD .



Pourquoi exactement ce joueur? Parce qu'alors il me semblait que c'était une option idéale pour le travail fait maison. Parce que tout est avec lui. Si vous le souhaitez, utilisez-le séparément: pour cela, il y a des broches de lecture / pause, des pistes de commutation, le volume, une lecture rapide de cinq pistes et un amplificateur mono pour connecter l'enceinte directement à la carte (il y a aussi une sortie stéréo, mais il a déjà besoin d'un amplificateur externe). Autrement dit, au moins assez de batterie, haut-parleur, quelques boutons et une carte mémoire avec de la musique.

image

Mais beaucoup plus intéressant est le contrôle complet du lecteur via un semblant de port série. Ici, vous pouvez tout faire - jouer, arrêter, changer le volume, changer l'égaliseur et les modes de lecture, commencer à jouer des chansons arbitraires à la fois dans l'ordre «à travers» et à partir de certains dossiers. Et, ce qui est important dans mon cas, il y avait déjà une bibliothèque prête à l'emploi pour Arduino.

Ainsi, deux composants sont déjà connus: player et Arduino. Mais personnellement, je ne voulais pas m'arrêter là, parce que c'est stupide d'être stupide d'imiter des boutons avec tout un microcontrôleur. Quelque chose de spécial est nécessaire pour qu'avec Emely, pour ainsi dire, et les piques.

Par conséquent, nous avons ajouté ici le capteur de vibration le plus simple SW-18010P et le célèbre lecteur de carte RC522.

image

Tout simplement pour se débarrasser complètement des boutons, ce que j'ai trouvé inutile dans le jouet divertissant. Jugez par vous-même: s'il y a des boutons, l'enfant les pressera d'une manière ou d'une autre, et plus souvent - par accident que consciemment. Mais la commutation super fréquente des contes de fées n'est toujours pas tout à fait correcte.

image

Ici, il s'avère comment: le capteur de vibration sert à allumer le jouet lorsque l'enfant le prend. Le même capteur ne permettra pas au jouet de s'éteindre tant que l'enfant ne le mettra pas suffisamment longtemps. Quant au lecteur de cartes Mifare, cette chose, à mon avis, est extrêmement pratique pour changer de conte de fées. Par exemple, des cartes peuvent être attachées à des livres, puis l'enfant pourra écouter le conte de fées en apportant le jouet au livre.

Et des cartes peuvent également être attachées à divers sujets, puis l'enfant pourra écouter leur description et leurs règles d'utilisation. Par exemple, que cette figue blanche est un réfrigérateur, et que nous y stockons des aliments pour qu'ils ne se détériorent pas, et que pour cette raison cela ne vaut pas la peine de l'ouvrir. Ou que c'est le four, et qu'il peut être chaud, vous n'avez donc pas besoin de vous accrocher à sa poignée et de mettre vos mains sur le verre. Beaucoup de choses peuvent être inventées, d'autant plus que les cartes sont des tickets de métro (oui, j'ai de la chance, je suis à Moscou), qui peuvent facilement être récupérés en quantité suffisante.

Par conséquent, pendant que je réfléchissais, entre-temps, j'ai retiré le contrôleur ATmega328p des stocks , l'ai soudé à la planche à pain et flashé le chargeur de démarrage Adruino via l'Arduino Mega 2560.

image

Pour plus de commodité, j'ai apporté le port série, réinitialisé et mis à la terre à un connecteur séparé pour une reprogrammation rapide. Et puis je me connais - je vais remplir le croquis, et puis l'un n'a pas raison, l'autre a tort.

Un stabilisateur de 3,3 V a également été soudé à côté, car le RC522, en raison d'un malentendu, est alimenté par cette tension, tandis que les autres composants se sentent bien sur le 5V universel, que je m'attendais à prendre dans une simple banque d'alimentation sur des batteries 18650.

image

La décision d'utiliser une telle banque d'alimentation plutôt que une batterie plate typique peut sembler contre-intuitive. Mais je pensais que puisque le jouet consommera un courant assez décent (seuls le contrôleur et le lecteur en mode veille consomment environ 40 mA), la possibilité de remplacer rapidement une batterie vide par une batterie pleine est très utile.

Et j'ai aussi dû ajouter un tweeter piézocéramique pour l'indication sonore de certains événements (lecture d'une carte par exemple). Vous dites que c'est généralement drôle - il y a un orateur, non? Eh bien, oui, non. Après tout, le haut-parleur est connecté au lecteur et non au contrôleur. Et il a ajouté un transistor comme clé, qui éteint le lecteur MP3 pendant le sommeil, pour réduire la consommation d'énergie.

Un lecteur attentif peut remarquer que le lecteur pourrait être alimenté par une broche de contrôleur numérique, ce qui fonctionnerait parfaitement bien. J'aimerais bien moi-même, mais ce n'est qu'en mode veille que le lecteur consomme 16 mA. Et lorsque la musique, il faut facilement plus de 100 mA, ce qui est déjà au moins le double de la capacité d'ATmega. Par conséquent, j'ai pris "n'importe quel" transistor npn avec un courant de collecteur de 300 mA et l'ai amené à la broche numérique du contrôleur via une résistance d'environ 200 ohms.

Mais le lecteur de carte consomme moins de 40 mA, de sorte que le stabilisateur qui l'alimente peut être connecté à la broche numérique du contrôleur. Il l'a fait, mais n'a toujours pas fonctionné, ce qui - à la fin.

Un autre de ces points: le joueur a besoin d'une tête dynamique avec une résistance d'au moins 8 ohms. J'en ai eu un (un haut-parleur de l'unité centrale), mais son son n'est pas très bon. Il y avait aussi des haut-parleurs avec une résistance de 4 ohms (d'un haut-parleur chinois typique). En général, j'ai connecté les deux en série: l'un donne plus de haut, l'autre donne de bas, et ensemble, ils sonnent juste cool.

Resté un peu, c'est-à-dire miroir de l'âme. Laquelle est la plus facile à réaliser à partir d'une paire de LED connectées en série. Je n'ai pas pris de rouge brutal - c'est très effrayant. Mais les yeux jaune ambre - c'est tout.

Ainsi, le modèle du jouet est assemblé et débogué. Maintenant, la chose la plus importante: vous avez besoin d'un donneur de corps. En fait, je voulais vraiment un oiseau bavardmais à en juger par le prix des jouets voisins, le plaisir n'est pas entièrement budgétaire. Surtout quand on considère que l'intérêt de l'enfant est une chose imprévisible.

Par conséquent, pour commencer, j'ai commencé à chercher un candidat plus abordable pour la transplantation. Et on en a trouvé un: le charmant hérisson Evelyn , vendu dans le monde des enfants.

image

Bien sûr, j'ai dû me débarrasser presque complètement du riche monde intérieur du hérisson. Et remplacez-le par un produit maison, emballé dans un porte-savon ordinaire. Cependant, pas tout à fait ordinaire. Le fait est que, contrairement à beaucoup, ce porte-savon a une face arrière plate, il est donc pratique d'y placer un lecteur de cartes - vous obtenez une distance minimale. D'autre part, le porte-savon a quelque chose comme une brosse de massage et a même des trous, c'est-à-dire l'enceinte y est idéalement placée: le son sortira par des ouvertures qui ne seront pas bloquées par des pointes de massage. Les trous, cependant, ne se sont pas avérés suffisants, mais cela n'a pas d'importance - j'ai quand même foré.



La chose la plus difficile, je dois l'admettre, a été la chirurgie du hérisson. Tout d'abord, je n'aime pas coudre. Et je devais décemment: d'abord je le déchire, puis je fixe les bords ensemble, puis je couds six boutons. Puis il a relâché six boutons et cousu quatre boutons. Pourquoi tout? Parce qu'au début, je cousais petit et faux, donc le hérisson n'était pas attaché.



Deuxièmement, les yeux. Bien sûr, j'ai prudemment acquis les LED d'un diamètre de 3 mm, afin de pouvoir garantir la représentation des élèves. Cependant, il n'était pas si facile de percer des trous dans les yeux d'Evelyn le hérisson. Il semblerait: vous prenez un graveur, vous y mettez la bonne perceuse - et vous partez. Mais il s'est avéré que pendant le forage, le plastique se transforme en une masse visqueuse, où le foret d'un graveur faible se coince.

Et, je dois dire, un hérisson avec une perceuse qui sort de l'œil est un spectacle infernal.

Au fait, je ne sais même pas quoi conseiller à ce sujet. J'ai en quelque sorte tordu et encore fait des trous, y inséré des LED et rempli d'époxy, et recouvert de vernis à ongles incolore sur le dessus. Les yeux étaient également collés au hérisson avec de l'époxy, car la monture native est morte pendant le processus de forage. Le résultat n'était pas parfait, mais tout à fait supportable.

Comment fonctionne le hérisson, vous l'avez déjà vu. Par conséquent, je ne peux que dupliquer le texte de sa logique actuelle. Initialement, le hérisson est en mode veille. Si vous le prenez (ou simplement le déplacez, ou déplacez la surface sur laquelle il se trouve, etc.), il se réveillera par une interruption qui générera un capteur de vibration.

Après cela, à des intervalles prédéterminés, le hérisson prononcera des phrases prédéfinies et si vous ne touchez pas le hérisson pendant un certain temps, il s'endormira à nouveau. Et si vous touchez, il ne s'endormira pas. Et si vous le secouez pendant un moment, il commencera à raconter un conte de fées, choisi au hasard.

Si vous apportez une carte au hérisson (quand il ne dort pas), alors le hérisson commencera à raconter une histoire associée à cette carte. Il n'y a pas de reliure rigide, l'ordre changera lors du remplacement des contes de fées. Seules deux cartes de service sont fixes: pour régler le volume et euthanasier de force le hérisson. Soit dit en passant, le volume est ajusté par une commutation séquentielle de trois niveaux (silencieux - moyen - fort).

Quant aux yeux ambrés, ils clignotent deux fois (en un cycle) lorsque le hérisson se réveille, mais sont silencieux et changent de luminosité lorsque le hérisson raconte un conte de fées. Cela me semblait la meilleure option.

Pendant le processus d'assemblage, j'ai essayé une autre innovation: comme la banque d'alimentation a deux connecteurs (entrée et sortie), j'ai connecté l'adaptateur de charge sans fil Qi existant à l'entrée. Et il s'est avéré que pour recharger le hérisson, vous n'avez pas besoin de le détacher du tout - il suffit de le mettre sur un chargeur sans fil pour la nuit. Cependant, cette fonction est toujours en mode test.

En général, malgré l'apparente simplicité, certaines choses m'ont laissé perplexe. Par exemple, à partir du code, vous pouvez remarquer que j'envoie plusieurs commandes au joueur plusieurs fois de suite, et même que je mets un timeout à la fin. Et tout cela parce qu'en pratique dans ma configuration la seule façon c'est possible.

On voit également que pour une raison quelconque, je contrôle la fin de la lecture par le signal matériel du lecteur, au lieu d'activer le mode de lecture d'un seul fichier avec une simple commande. Ce n'est pas seulement comme ça: pour une raison quelconque, ce mode ne fonctionne pas pour moi, donc à la fin d'une chanson, le joueur commence à jouer la suivante.

Il peut sembler encore plus curieux que la fonction aléatoire pour jouer une composition aléatoire tourne constamment en boucle, au lieu d'être appelée uniquement lorsqu'elle est vraiment nécessaire. Mais voici la chose: si vous l'appelez uniquement lorsque cela est nécessaire, pour une raison quelconque, dans la grande majorité des cas, il renvoie la même valeur. Mais si vous mettez en boucle, des valeurs vraiment pseudo-aléatoires sont générées. En fait, j'ai également découvert dans la pratique lorsque j'ai essayé de comprendre le comportement inapproprié du hérisson.

Enfin, ce qui m'a complètement dérouté, c'est l'incapacité de faire face à la mise hors tension du lecteur de carte à l'aide de la broche numérique du contrôleur, à partir de laquelle le lecteur est alimenté. Pour une raison quelconque, il s'avère que si la broche est réglée sur LOW puis sur INPUT, le lecteur ne s'éteint pas.

En même temps, si vous venez de régler LOW, la LED du lecteur de carte "s'allume" complètement, la tension à la sortie du stabilisateur alimentant le lecteur est d'environ un volt. Si ensuite, sur la broche du contrôleur, effectuez INPUT, cette tension monte à environ 3V.

Il est encore plus intéressant de noter que si vous réglez d'abord les broches du contrôleur connectées au lecteur SS et RST sur LOW et INPUT, puis placez la broche d'alimentation du contrôleur dans la même position, le lecteur s'éteint. Et même alors, il s'allume après le sommeil, si la broche d'alimentation est transférée sur OUTPUT et HIGH.

Cependant, quelque chose d'irréparable avec les minuteries se produit. C'est, je pense, parce qu'après une telle feinte (sommeil avec le lecteur éteint), les yeux et le compteur de secousses ne fonctionnent pas correctement, et ces deux processus sont liés aux millis (). Je ne sais pas ce qui se passe et comment restaurer le minuteur, alors je l'ai laissé tel quel - le lecteur de cartes continue de manger même pendant le sommeil.

Si des camarades supérieurs aident à trouver une issue, je serai très reconnaissant. Bien que je crois à peine que des camarades plus âgés liront à cet endroit.

Compte tenu de ce qui précède, le code hérisson d'Evelyn est complètement imparfait, mais vous pouvez toujours le peigner (code ou hérisson - choisissez-le vous-même), optimiser, compléter, réduire ou autrement adapter à vos besoins. C'est pourquoi je l'attache. Et pour faciliter l'utilisation de ce qui est, le maximum de paramètres (j'ai tout essayé en général, mais il s'est avéré comme d'habitude) n'est pas dans le code, mais dans la section de définition des variables. Il y a une configuration de broches, des retards et le nombre de pistes.

Dans la section de description des numéros de carte, il faut comprendre que les deux dernières cartes sont toujours «réservées» aux fonctions internes - changement de volume et mode veille.

Programme d'action
/*  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);
  
}




Un diagramme approximativement restauré par le code devrait ressembler à ceci (je m'excuse si mes erreurs sont restées quelque part):





Ici:

  • 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 , pour lequel un grand merci à lui, s'est sensiblement amélioré et a mis de l'ordre dans toute cette économie. Mais notez que le transistor PNP est déjà là et que la gestion de l'alimentation du lecteur doit être inversée (c'est-à-dire qu'avec cette connexion, le lecteur s'allume à faible intensité sur la broche du contrôleur et s'éteint à haut):



avec la configuration actuelle, une batterie d'une capacité d'environ 2500 mAh suffit pour environ une journée. utilisez un hérisson. Pour ne pas dire grand-chose, mais vous devez comprendre que le programme est toujours différent et que la plupart de l'énergie est dépensée, j'espère, en mode actif. Ce qui nous permet dans une certaine mesure de négliger le retrait complet raté de tous les appareils électroniques du hérisson dans le sommeil.

Si vous vous donnez la peine de calculer le budget approximatif, vous obtenez quelque chose comme ça (en USD):

  • Joueur: 8,9
  • ATmega328p: 1.1
  • Conseil de dĂ©veloppement: 0,28
  • Lecteur RC522: 2.21
  • TĂŞte dynamique: 0,99
  • Emetteur piĂ©zocĂ©ramique: 0,77
  • LED: 0,12
  • Transistor: 0,14
  • Stabilisateur: 0,13
  • Capteur de vibrations: 0,13
  • Porte-savon: 0,99
  • Powerbank: 0,75
  • Batterie 18650: 3,9
  • Adaptateur de charge Qi: 1,65
  • Carte mĂ©moire: 3
  • HĂ©risson Evelyn: 6


Un total de 31,06, mais en fait un peu plus, car vous avez toujours besoin d'un fil pour les connexions et d'autres petites choses comme de l'adhésif thermofusible, du ruban adhésif double face et du ruban électrique bleu.

Il doit probablement y avoir une sorte de phrase finale particulièrement importante, mais je ne l'ai certainement pas en tête. Il est probablement logique de dire que l'enfant est assez satisfait du jouet, et c'est certainement mieux (et souvent plus rapide) que d'allumer l'ordinateur portable.

ps. Je connais les haut-parleurs Bluetooth, c'est un peu différent, même si vous mettez un hérisson si mignon.

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


All Articles