TonUINO Set erweitern - Teil 3 - AZ-Delivery

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

After we im second part We will now add the operation from a visual perspective, we will now add a Rotary Encoder for simpler operation to set the volume.

Hardware

The following products are required from the previous parts:

In addition, are also required:

You need one on tools soldering iron With accessories and one 3D printer.

In order for the rotary code to work reliably, the CLK and you PIN must be connected to an interrupt pin of the microcontroller. Our Nano Microcontroller has two interrupt-capable pins, D2 and D3.

The first thing we can do is soldered up to the PCB, followed by pen strips for the external components.

The yellow lines are soldered under the PCB and the oranges on the top.
Before you put the circuit into operation, check that no short circuits were created by soldering on the hole grid.

Next we connect the other components with dupont cables. In order for the cabling to become more decent, it is recommended to crime the cables in the correct length. If you do not have the appropriate tools, you can also Pre -crimped F2F cable use.

For the clarity, all voltage and mass compounds at the top are not shown directly, these must be connected to the three pen strips on the top right at the top right. The RFID module requires a operating voltage of 3.3V, for this there is a pen strip at the bottom left.

For the housing, the two files (Housing 1, Housing 2) can be printed out with a 3D printer. The part with the large oval hole must be printed in white or other light -translucent color, since the LED ring is attached behind it.

When the two parts have been printed, the thread inserts are pressed into the larger 6 holes with a hot soldering iron. In the end, all components are attached with appropriate (M2 or M3) screws.

software

The following libraries must be installed:

Mfrc522
Dfrobot dfplayermini
Adafruit SSD1306
Adafruit neopixel

In addition to the Libraries from the previous parts, we now need the encoder library.

As usual, the libraries can be installed via the integrated library manager or as a .zip file in the Arduino IDE.

Copy or load the following code to Arduino IDE, select the right board and port and load the program by pressing the upload button onto the board (Download).

First, the libraries used are integrated.

#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>
#include <Encoder.h>

Next, symbolic constants are created that create objects of the libraries and created global variables. Some of the following methods are taken from the previous blog posts.

#define RX 15
#define Tx 14
#define LED 4
#define Dwn 5
#define OK 6
#define Up 7
#define Rst_pin 9
#define Ss_pin 10
#define CLK 2
#define Dt 3
#define SW 8

#define Screen_address 0x3c

Encoder encoder(Dt,CLK);
Adafruit_neopixel ring(12, LED, Neo_grb + Neo_khz800);
Adafruit_ssd1306 display(128, 32, &Wire, -1);
Software softserial(RX, Tx);
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 !!!

The arrays title and duration must be filled with the current data as in the previous part.

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

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

byte Volume = 20;
long position;


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 name(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();
}

The following method was expanded to scroll the text to the right:

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

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;
  }
  
}

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();
  }
}

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);
  }
}

The function Volumerot () Reads the position of the Rotary Encoder and changes the volume according to the direction of rotation. The volume is shown on the LED ring as usual.

void volumerot() {
  IF (encoder.readand reset() == 0 || digital read(SW)) return;
  intimately LED = 0;
  while(true) {
    long position = encoder.readand reset();
    IF(position > 0 && Volume <= 28) Volume += 1;
    Else IF(position < 0 && Volume >= 2) Volume -= 1;
    mydfplayer.volume(Volume);
    delay(250);
    Serial.print(Volume);
    LED = map(Volume, 1, 30, 0, 12);
    ring.fill(ring.Color(0,0,0),0,12);
    for(intimately I=0; I<LED; I++) {
      ring.setpixelcolor(I, ring.Color(255, 255, 0));
    }
    ring.show();
    IF(digital read(SW)) break;
  }

  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);
  }
}

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");
  display.stop();
  Serial.print("Start");
}

The call for the Rotary Encoder is in the Loop () In the end, complemented and therefore called cyclically.

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();
  }
  volumerot();
}

The turning code fulfills the same function as the outer buttons. If you don't want to use the encoder, you can Loop () delete.

In the end, the two 3D printed parts are screwed. Our project is complete.

Service

Place an NFC card on the top of the box, if the card is already described, the stored file is played directly. If a formatted card is launched, you can select the file number via the outer buttons. If you have found the right file, you can write the number on the card by pressing the middle button. Remove the card and put it back on. If the ring no longer shines blue, the card is described and can be used now. To set the volume, you can either press the outer buttons or hold the Rotary Encoder down and turn it. When pressing the middle button, the file is paused.

Have fun recovery :)

All the necessary files again at a glance:

Sketch: Tonuino

3D printing: Housing 1, Housing 2

DisplaysFür arduinoProjekte für anfänger

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione