TonUINO Set erweitern - Teil 2 - AZ-Delivery

The following article was made by the guest author Bastian Brumbi made available:

After it in first part In this part, further modules are added to the basic functions. In addition to the components from the first part, the following products are required:

Hardware

Next we take a look at the hardware. Now put the new components on the Breadboard from the previous part and cable them as follows:

Microcontroller

module

D 4

Led ring - in

A 4

OLED - SDA

A 5

OLED - SCL

software

Additional libraries must be installed for the LED ring and the OLED display. As usual, these can be installed via the integrated library manager or as a .zip file in the Arduino IDE:

Adafruit SSD1306
Adafruit neopixel

The goal is to display the date number on the display and the programming of the cards. The LED ring is intended to represent a progress bar and the status by changing the color. Since we cannot read this data through a command on the DFPlayer, we have to store it in the program. For this purpose, two arrays are initialized, in the first the duration of each individual file is given in seconds, in the second the name, which is to be displayed on the display. It should be noted that the positions are moved in the array, but must match the file name (001.mp3 = [0]). For reasons of the low storage space, the shortest possible names should be chosen without umlauts.

The associated libraries are still integrated for the display and the LED ring. For the display, the Wire Library, which is required for communication, and the Gfx Library integrated for the graphic calculations.

Copy or load the source code to the Arduino ID (Download):

#include <Arduino.h>
#include <Spi.h>
#include <Mfrc522.h>
#include "DfrobotdfPlayermini.h"
#include <Software.h>
#include <Adafruit_neopixel.h>
#include <Wire.h>
#include <Adafruit_gfx.h>
#include <Adafruit_ssd1306.h>

#define Rst_pin 9
#define Ss_pin 10
#define Up 7
#define OK 6
#define Dwn 5

For the IIC address of the display, we define an additional symbolic constant here.

#define Screen_address 0x3c

Then the global variables and objects are created with the corresponding constructor. We take over some of the following methods from the first part.

Adafruit_neopixel ring(12, LED, Neo_grb + Neo_khz800);
Adafruit_ssd1306 display(128, 32, &Wire, -1);
Software softserial(2, 3);
Dfrobotdfplayermini mydfplayer;

Mfrc522 mfrc522(Ss_pin, Rst_pin);
Mfrc522::Mibare_key key;
Mfrc522::Status code status;

byte sector         = 1; // position in the memory
byte blockadr      = 4; 
byte data block[]    = { // buffer to describe
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00
};
byte buffer[18]; // buffer for reading
byte trailer block = 7;
Bool State = true;
const intimately Filecount = 4; // !!! Number of files, please adjust !!!

In addition, the arrays are initialized for the title and the duration and the variables for determining the time played.

String title[Filecount] = {"TXT1", "Txt2", "Txt3", "Txt4"}; // title to be displayed
intimately duration[Filecount] = {234, 231, 234, 123}; // duration in seconds

intimately stop = 0;
intimately start time = 0;
intimately correction = 0;
intimately Currfile = 0;

byte Volume = 20;


void readcard() { // Read the RFID Stack -> Buffer
  IF ( ! mfrc522.Picc_readcarderial())
    return; // card cannot be read -> demolition

  byte size = Sizeof(buffer);
  status = (Mfrc522::Status code) mfrc522.PCD_authenticate(Mfrc522::Picc_cmd_mf_auth_Key_a, trailer block, &key, &(mfrc522.uid));
  IF (status != Mfrc522::Status_ok) {
    Serial.print(F("PCD_authenticate () Failed:"));
    Serial.print(mfrc522.Get status code(status));
    return;
  }
  status = (Mfrc522::Status code) mfrc522.MIFARE_READ(blockadr, buffer, &size);
  IF (status != Mfrc522::Status_ok) {
      Serial.print(F("MIFARE_READ () Failed:"));
      Serial.print(mfrc522.Get status code name(status));
  }
  mfrc522.Picc_halta();
  mfrc522.PCD_StopCrypto1();
}

void writecard() { // Writing the DataBlock -> RFID Stack
  IF ( ! mfrc522.Picc_readcarderial())
    return; // card cannot be read -> demolition

  status = (Mfrc522::Status code) mfrc522.PCD_authenticate(Mfrc522::Picc_cmd_mf_auth_Key_a, trailer block, &key, &(mfrc522.uid));
  IF (status != Mfrc522::Status_ok) {
    Serial.print(F("PCD_authenticate () Failed:"));
    Serial.print(mfrc522.Get status code name(status));
    return;
  }
  status = (Mfrc522::Status code) mfrc522.MIFARE_WRITE(blockadr, data block, 16);
  IF (status != Mfrc522::Status_ok) {
      Serial.print(F("MIFARE_WRITE () Failed:"));
      Serial.print(mfrc522.Get status code name(status));
  }
  mfrc522.Picc_halta();
  mfrc522.PCD_StopCrypto1();
}

This function is later called for displaying text on the display:

void display text(String text){
  display.Clear display();
  display.SettextSize(2);
  display.SettextColor(SSD1306_White);
  display.setcursor(5,10);
  display.print(text);
  display.display();
}

The StartCard () function largely corresponds to the old one, only that during the programming process of the file index and with a stored card, the stored card is displayed on the display. In addition, the ring shines blue during the description process of the card and after successful describing it is switched off again.

void startcard() {
  readcard();
  // new card
  IF(buffer[0] != 1) { // marker not available
    mydfplayer.play(1);
    intimately I = 1;
    display text((String)I);
    while(true) {
      IF(!digital read(Up)) {
        while(!digital read(Up)) delay(20);
        IF(I < Filecount) {
          I+=1;
          mydfplayer.next();
        }
        Else {
          I = 1;
          mydfplayer.play(1);
        }
        display text((String)I);
      }
      IF(!digital read(Dwn)) {
        while(!digital read(Dwn)) delay(20);
        IF(I > 1) {
          I-=1;
          mydfplayer.preview();
        }
        Else {
          I = Filecount;
          mydfplayer.play(Filecount);
        }
        display text((String)I);
      }
      IF(!digital read(OK)) { // confirm and describe
        display text("Write");
        while(!digital read(OK)) delay(20);
        data block[0] = 1;
        data block[1] = I;
        ring.fill(ring.Color(0, 0, 255), 0, 12);
        ring.show();
        while(!mfrc522.Picc_isnewCardpresent()) delay(20);
        writecard();
        display text((title[I - 1]));
        ring.fill(ring.Color(0, 0, 0), 0, 12);
        ring.show();
        return;
      }
    }
  }
  // registered card
  Else {
    Currfile = buffer[1];
    display text((title[Currfile - 1]));
    mydfplayer.play(Currfile);
    start time = Millis()/1000;
    correction = 0;
  }
  
}

The following method represents the progress bar on the LED ring. At the beginning, the traffic jams of the DFPlayer are queried. If nothing is played, the method is ended and if not paused, the LEDs are switched off. After that, the time played is calculated and the number of LEDs that are supposed to light map () Function determined. In the end, the ring is dimmed or, if not yet the end of the file, the previously calculated number of LEDs is displayed.

void progress() {
  IF(mydfplayer.readstate() != 1) {
    IF(State == 1) {
      ring.fill(ring.Color(0, 0, 0), 0, 12);
      ring.show();
    }
    return; // does not play -> demolition
  }
  for(intimately I=0; I<12; I++) {
    ring.setpixelcolor(I, ring.Color(0, 0, 0));
  }
  intimately played = (Millis()/1000) - start time - correction;
  byte LED = map(played, 0, duration[Currfile - 1], 0, 13);
  
  IF(LED > 12) {
    display text("End");
    display.stop();
    for(intimately I = 255; I>=0; I--) {
      for(intimately n=0; n<12; n++) {
        ring.setpixelcolor(n, ring.Color(0, I, 0));
      }
      ring.show();
      delay(10);
    }
    LED = 0;
  }
  Else {
    for(intimately I=0; I<LED; I++) {
      ring.setpixelcolor(I, ring.Color(0, 255, 0));
    }
    ring.show();
  }
}

The next function is the replacement for the previous button queries in Loop (). If no button is pressed, the end follows by a earlyreturn. While a button is pressed, the volume is increased or reduced in 2 steps. An orange circular sector is displayed according to the newly set volume.

void volume() {
  intimately LED;
  IF(digital read(Up) && digital read(Dwn)) return;
  for(intimately I=0; I<12; I++) {
    ring.setpixelcolor(I, ring.Color(0, 0, 0));
  }
  while(!digital read(Up)) {
    IF(Volume<30) Volume += 2;
    mydfplayer.volume(Volume);
    LED = map(Volume, 1, 30, 0, 12);
    for(intimately I=0; I<LED; I++) {
      ring.setpixelcolor(I, ring.Color(255, 255, 0));
    }
    ring.show();
    delay(700);
  }
  while(!digital read(Dwn)) {
    IF(Volume>0) Volume -= 2;
    mydfplayer.volume(Volume);
    LED = map(Volume, 1, 30, 0, 12);
    for(intimately I=0; I<12; I++) {
      ring.setpixelcolor(I, ring.Color(0, 0, 0));
    }
    for(intimately I=0; I<LED; I++) {
      ring.setpixelcolor(I, ring.Color(255, 255, 0));
    }
    ring.show();
    delay(700);
  }
  for(intimately I = 255; I>=0; I--) {
    for(intimately n=0; n<LED; n++) {
      ring.setpixelcolor(n, ring.Color(I, I, 0));
    }
    ring.show();
    delay(2);
  }
}

In the set up() the starting functions are executed, the player initialized, the RFID sensor (exactly we im first part), the LED ring and the display.

void set up() {
    softserial.Begin(9600);
    Serial.Begin(115200);

  while(!mydfplayer.Begin(softserial, false, false)) {
    Serial.print(F("DfPlayer Unluke to Begin"));
    delay(1000);
  }
  
  Spi.Begin();
  mfrc522.PCD_init();

  for (byte I = 0; I < 6; I++) {
      key.keybye[I] = 0xff;
  }
  pin mode(Up, Input_pullup);
  pin mode(OK, Input_pullup);
  pin mode(Dwn, Input_pullup);
  pin mode(SW, Input_pullup);

  mydfplayer.volume(Volume); //0-30

  ring.Begin();
  ring.show();
  ring.setbrightness(75);
  ring.fill(ring.Color(0, 0, 0), 0, 12);
  ring.show();

  IF(!display.Begin(Ssd1306_switchcapvcc, Screen_address)) {
    Serial.print(F("SSD1306 Allocation Failed"));
  }
  
  display.Clear display();
  display.display();

  display text("Start");
}

In the Loop () Become the methods progress() and Volume () repeated permanently. When the middle button is pressed, the current time is saved in a variable, withdrawn from time when continuing and saved as a correction factor.

void loop() {
  IF (mfrc522.Picc_isnewCardpresent()) { // Card recognized
    Serial.print("Card recognized");
    startcard();
    
  }
  volume();
  progress();
  IF(!digital read(OK)) {
    while(!digital read(OK)) delay(20); // Waiting until button was let go
    IF(State) {
      mydfplayer.pause();
      State = 0;
      stop = Millis()/1000; 
    }
    Else {
      mydfplayer.start();
      State = 1;
      correction += ABS(stop - (Millis()/1000));
    }
  }
  IF(!State) {
    ring.fill(ring.Color(120, 0, 0), 0, 12);
    ring.show();
  }
}

Conclusion

In this part we added the following functions to the Tonuino set:

  • Display of progress
  • Relief in operation in programming the cards
  • Improvement of the volume setting
  • Representation of the volume on the LED ring
  • Display of the title on the display

In the next part, the project will be built into a 3D printed housing and a Rotary Encoder is added as an alternative control of the volume.

Have fun recovery :)

DisplaysFür arduinoProjekte für anfänger

Laat een reactie achter

Alle opmerkingen worden voor publicatie gecontroleerd door een moderator

Aanbevolen blogberichten

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery