Weihnachten 2025 – Animierter Schneewürfel - Teil 2 - AZ-Delivery

   Dans la deuxième partie du projet de Noël, nous équipons l'appareil d'un module lecteur MP3, d'un amplificateur et de deux mini enceintes. Un écran LED WS2812B est également ajouté pour afficher des messages de félicitations. Des images peuvent également être ajoutées si vous le souhaitez. Pour ce faire, le croquis doit être modifié. Enfin, nous ajoutons quatre ventilateurs pour créer l'effet d'une tempête de neige. Pour ce faire, il faut ajouter de petits morceaux de plumes provenant d'un plumeau, car ils pèsent peu et se déplacent avec un léger courant d'air à l'intérieur de l'urne.

   Si vous le souhaitez, l'urne transparente peut être omise, ce qui donne à l'ensemble du projet un aspect différent même lorsque les ventilateurs ne sont pas utilisés. Commençons par développer cette deuxième partie du projet.

 

Les matériaux nécessaires à l'ensemble du projet sont :

 

Le logiciel requis est :

        EDI Arduino

        Bibliothèque Adafruit GFX (Arduino Adafruit_GFX.h)

        Bibliothèque Adafruit NeoPixel (Arduino Adafruit_NeoPixel.h)

        Bibliothèque SoftwareSerial (LogicielSerial.h)

        Bibliothèque Adafruit_NeoMatrix (Adrafruit_NeoMatrix.h)                                                                                                    

        Bibliothèque DFPlayer Mini de DFRobot (DFRobotDFPlayerMini.h)

        Bibliothèque SPI.h (incluse dans l'IDE Arduino)

        001.mp3

        002.mp3

        003.mp3

        snow_cube_animated_part_2.ino

 

Les dessins des personnages sont :

      Pour les arbres.jpg

       Santa.jpg

      Stadt.jpg

      Zug.jpg

      Dimensions des pièces


Schéma de circuit et description des modules utilisés dans la deuxième partie du projet

Dessin 2 – Dessin de cube de neige, partie 2


Assemblage du projet

   Pour compléter la structure du projet, un panneau arrière a été ajouté pour installer la matrice 256 LED WS2812B et toute l'électronique à l'arrière du panneau. Pour installer le panneau LED et un panneau translucide (dans ce cas une feuille de papier blanche), des rails ont été fixés dans lesquels sont insérés les bords du panneau LED et du panneau translucide. Les dimensions de la plaque nouvellement ajoutée sont indiquées dans l'image suivante. Ajout également du dessin de la partie inférieure de la plate-forme des ventilateurs et des arbres.

 

Figure 1 – Dimensions du panneau WS2812B

 

 

Image 2 - Panneau WS2812B

 

 

Description du croquis

   Après avoir fixé le support pour installer la matrice LED WS2812B et les composants électroniques, nous commençons à analyser le croquis. Au début de chaque sketch, il faut d'abord insérer les bibliothèques nécessaires à l'utilisation des modules. Dans ce cas, trois bibliothèques sont nécessaires pour utiliser le panneau LED dans ce projet. Les trois bibliothèques suivantes sont requises pour afficher du texte. La bibliothèque Adafruit_GFX.h est nécessaire pour afficher des graphiques primitifs tels que des lignes, des cercles, etc. Puisque notre panneau LED est une grille LED, nous avons également besoin de la bibliothèque Adafruit_NeoMatrix.h pour pouvoir contrôler un groupe de LED sur le panneau. La dernière bibliothèque que nous incluons est Adafruit_NeoPixel.h, qui est nécessaire pour contrôler les trois LED internes de chaque LED.

 

#include <Adafruit_GFX.h>

#include <Adafruit_NeoMatrix.h>

#include <Adafruit_NeoPixel.h>

 

   Ce qui suit Des bibliothèques doivent être ajoutées : <LogicielSérie.h>, qui permet au microcontrôleur d'activer chaque broche numérique pour la communication série. Ceci est nécessaire pour utiliser le module de lecture MP3 et la console série pour afficher les messages au démarrage. <DFRobotDFPlayerMini.h> est la bibliothèque qui active les fonctions nécessaires à l'utilisation du module lecteur MP3.

 

#include <LogicielSérie.h>

#include <DFRobotDFPlayerMini.h>

 

      Ensuite, un objet doit être implémenté pour utiliser le module de lecture MP3. Voilà quel est l'objet monLogicielSérie de la bibliothèque <LogicielSérie.h> implémenté pour indiquer au microcontrôleur les broches numériques à utiliser pour la communication série avec le module. Dans ce projet, la broche numérique 15 du microcontrôleur est utilisée pour recevoir les données du module MP3 et la broche numérique 14 est utilisée pour envoyer des données au module MP3. Pour utiliser les méthodes et commandes de contrôle du module MP3, telles que : B. régler le volume ou lancer la lecture d'un fichier MP3, l'objet monDFPlayer de la bibliothèque <DFRobotDFPlayerMini.h> créé.

 

LogicielSérie monLogicielSérie(15, 14);

DFRobotDFPlayerMini monDFPlayer ;

 

   La ligne suivante crée une première constante avec le nombre de LED (256) de la matrice LED WS2812B et une seconde pour indiquer que la ligne de données de la matrice est connectée au port 16 du microcontrôleur. Nous avons besoin de ces deux constantes pour pouvoir travailler avec la matrice LED.

 

#define NUM_LEDS 256

#define BROCHE 16

 

   Afin de pouvoir contrôler le module avec 4 relais, le microcontrôleur doit savoir à quels ports les différentes lignes de commande du module relais sont connectées. Pour ce faire, 3 constantes sont créées dont les valeurs doivent correspondre aux numéros des ports auxquels sont connectées les lignes de contrôle du module relais.

 

#define FAN_1 17

#define FAN_2 18

#define FAN_3 19

 

   Un objet portant le nom est alors créé matrice de la bibliothèque Adafruit_NeoMatrix.h mis en œuvre pour afficher du texte sur le panneau LED. Les arguments ou paramètres à préciser sont :

        Nombre de LED dans la largeur et la hauteur du panneau (16 LED en largeur et 16 LED en hauteur) et le PIN du microcontrôleur auquel la ligne de données du panneau est connectée.

        Emplacement de la LED numéro 0 sur la centrale (le nombre de LED est de 256, mais la numérotation commence à 0 et se termine à 255). La LED 0 est située en bas à droite du panneau de commande.

        Disposition des LED dans la matrice et numérotation consécutive : Les LED sont disposées en colonnes de sorte que lorsque la LED numéro 0 se trouve dans le coin inférieur droit, la LED numéro 1 est celle du haut. Lorsque la LED numéro 15 (première colonne et dernière LED) est atteinte, la LED suivante (numéro 16) se trouve à sa gauche, c'est-à-dire h. la numérotation court en zigzag comme un serpent.

        La disposition et le câblage des trois LED internes, la disposition interne est verte, rouge et bleue (NEO_GRB). Le dernier paramètre est la fréquence de travail (800 KHz).

 

Matrice Adafruit_NeoMatrix = Adafruit_NeoMatrix(16, 16, NIP,

                 NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT +

                 NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,

                 NEO_GRB + NEO_KHZ800);

 

   Alors la variable doit x peut être créé dans lequel le nombre de LED que le panneau a en largeur est d'abord enregistré. Cette valeur est définie avec la commande matrice.largeur() déterminé. Ces données ont été créées précédemment lors de la création de l'objet matrice entré. Cette variable est dans un état si utilisé pour compter le nombre de colonnes qui doivent être déplacées vers la gauche pour afficher un message sur le panneau. Cette condition est à l'intérieur d'une boucle faire pendant que. La méthode de présentation du texte sera expliquée plus tard.

 

int x = matrice.largeur();

 

   Après avoir implémenté l'objet photo de la bibliothèque Adafruit_NeoPixel.h avec le numéro des LED du panneau, la broche de connexion au microcontrôleur, la disposition et le câble des trois LED internes, la disposition interne des LED est verte, rouge et bleue (NEO_GRB).  La valeur ultime des arguments est la fréquence de travail (800 KHz). Ces objets et définitions de couleurs postérieures sont nécessaires s'ils représentent des images dans le panneau LED, mais ils n'ont pas besoin d'être représentés seuls par du texte.

 

Adafruit_NeoPixel image(NUM_LEDS, NIP, NEO_GRB + NEO_KHZ800);

 

   Une gamme de couleurs est définie, même si toutes ne sont pas utilisées.

 

uint32_t p_rouge = photo.Couleur(150,0,0);

uint32_t p_vert = photo.Couleur(0,150,0);

uint32_t p_bleu = photo.Couleur(0,0,150);

uint32_t p_jaune = photo.Couleur(150,150,0);

uint32_t p_violet = photo.Couleur(150,0,150);

uint32_t p_light_blue = photo.Couleur(0,150,150);

uint32_t p_blanc = photo.Couleur(150,150,150);

uint32_t p_marron = photo.Couleur(150,51,0);

uint32_t p_noir = photo.Couleur(0,0,0);

 

   Les lignes créées dans la première partie du projet, qui représentent la définition des broches du microcontrôleur auxquelles seront connectés les contacts du module L298N qui contrôle chaque moteur, restent inchangées.

 

#define activer_Santa_motor 7

#define connexion_1_Santa_motor 5

#define connexion_2_Santa_motor 6

 

#define activer_train_moteur 2

#define connexion_1_train_moteur 3

#define connexion_2_train_moteur 4

 

   Les constantes des six LED sont également conservées, auxquelles est attribué le numéro du port du microcontrôleur auquel elles sont connectées.

 

#define led_house_1 8

#define led_house_2 9

#define led_house_3 10

#define led_house_4 11

#define led_house_5 12

#define led_house_6 13          

 

   Une fois les bibliothèques ajoutées et les variables nécessaires à cette deuxième partie du projet définies, les conditions initiales des modules ajoutés doivent être initialisées et définies. Cela se fait dans la méthode configuration(), qui commence la description du code qu'il contient.

   Tout d'abord, les paramètres du panneau LED doivent être initialisés et configurés pour qu'il puisse afficher du texte. Le panneau doit être initialisé par l'objet matrice avec la matrice doit être initialisée. commencer(); Le texte doit commencer son affichage à droite du panneau et se terminer à gauche à l'aide de la commande matrice utiliser. setTextWrap(faux.faux) empêche le texte qui apparaît à gauche d'apparaître à nouveau à droite. La luminosité des LED se règle avec la commande matrice.définir la luminosité(7) réglé sur une valeur de 7 pour afficher le texte. C'est une faible luminosité. La couleur initiale du texte est définie avec la commande matrice.setTextColor(matrice.Couleur(Rouge, Vert, Bleu)) , car les LED rouge et verte affichent les valeurs 0 sont complètement éteints et la LED bleue avec la valeur 254 est allumé.

 

matrice.commencer();

matrice.setTextWrap(faux.faux);

matrice.définir la luminosité(7);

matrice.définirTextColor(matrice.Couleur(0, 0, 254));

 

   Si vous souhaitez afficher des graphiques sur le panneau LED, initialisez l'objet photo avec photo. commencer()pour afficher des images sur le panneau LED si vous le souhaitez. Dans ce projet cela n'a pas été choisi mais il est initialisé dans cette méthode et si vous souhaitez afficher des images il vous suffit d'ajouter le code requis pour que l'image soit affichée dans la méthode boucle() ajouter. Cela se termine par une pause de 2 secondes.

 

photo.commencer();

retard(2000);

 

   Ensuite, le module de lecture MP3 doit être initialisé et communiqué avec le microcontrôleur monSoftwareSerial.commencer(9600), où 9600 est la vitesse de transfert des données en bauds. De plus, la communication avec le moniteur série s'effectue via Série.commencer (115200) à une vitesse de 115200 bauds (la vitesse doit être sélectionnée en bas à droite du Serial Monitor à l'ouverture de la console) afin d'afficher les messages concernant l'état d'initialisation ou les erreurs du module MP3. Avec la ligne Série.println („Noël 2025 : Boule de neige”) un message est envoyé à la console série. Pour visualiser ce message, il est très important de modifier la valeur de la vitesse dans la console série.

 

monLogicielSérie.commencer(9600);

Série.commencer(115200);

Série.imprimer ("Noël 2025 : Boule de neige");

 

   La prochaine chose à vérifier dans le code est l'initialisation du module MP3. Cela se fait à l'aide d'une instruction conditionnelle si utilisé. Dans les instructions si Le code entre accolades sera exécuté si la condition de son paramètre est vraie. Dans ce cas vérifie si le module MP3 n'a pas été initialisé pour une raison quelconque. L'initialisation niée était avec le symbole ! écrit. Ce symbole est utilisé comme méthode de négation de sorte que si le module n'est pas initialisé, la condition est vraie et le code entre les accolades est exécuté et la console série signale la vérification des connexions et de l'insertion de la carte microSD. Si le module de lecture MP3 est correctement initialisé, la condition n'est pas remplie et le code décrit ci-dessus ne sera pas exécuté. La méthode configuration () a continué à fonctionner via la console série avec la ligne Série.println(F("Corrigez l'initialisation de DFPlayer.")) pour signaler que le module de lecture MP3 a été correctement initialisé.

 

monLogicielSérie.commencer(9600);

Série.commencer(115200);

Série.imprimer ("Noël 2025 : Boule de neige");

 

si (!monDFPlayer.commencer(monLogicielSérie)) {

         Série.imprimer(F("Erreur lors de l'initialisation du module mp3 :"));

         Série.imprimer(F("1. Veuillez vérifier les connexions !"));

         Série.imprimer(F("2. Veuillez insérer la mémoire microSD !"));

         tandis que(vrai){

                 retard(0);

         }

}

 

Série.imprimer(F("Corriger l'initialisation de DFPlayer."));

 

  Après le code d'initialisation du module MP3, les broches du microcontrôleur qui servent à contrôler les moteurs sont configurées. Ils doivent être utilisés comme broches de signal de sortie mode broche(numéro_pin, SORTIE)  configurés car ils doivent envoyer des signaux aux broches du module de contrôle L298N.

 

mode broche(enable_Santa_moteur,SORTIE);

mode broche(connection_1_Santa_motor,SORTIE);

mode broche(connection_2_Santa_motor,SORTIE);

 

mode broche(enable_train_motor,SORTIE);

mode broche(connexion_1_train_moteur,SORTIE);

mode broche(connexion_2_train_moteur,SORTIE);

 

   Les broches du microcontrôleur auxquelles sont connectées les LED pour l'éclairage intérieur des maisons doivent également être configurées comme broches de signal de sortie, car elles doivent fournir la tension pour que les LED s'allument.

mode broche(led_house_1,SORTIE);

mode broche(led_house_2,SORTIE);

mode broche(led_house_3,SORTIE);

mode broche(led_house_4,SORTIE);

mode broche(led_house_5,SORTIE);

mode broche(led_house_6,SORTIE);

 

   Pour programmer la méthode configuration() Pour terminer, il ne reste plus qu'à configurer les ports du microcontrôleur auxquels est connecté le module relais qui contrôle l'allumage et l'extinction des ventilateurs. Il doit s'agir de sorties et l'état initial doit être haut, envoyant 5 Vdc au module relais.

 

mode broche(FAN_1, SORTIE);

écriture numérique(FAN_1, ÉLEVÉ);

mode broche(VENTILATEUR_2, SORTIE);

écriture numérique(VENTILATEUR_2, ÉLEVÉ);

mode broche(VENTILATEUR_3, SORTIE);

écriture numérique(VENTILATEUR_3, ÉLEVÉ);

 

   Une fois les conditions initiales de tous les modules et composants du projet configurées, il faut maintenant configurer la méthode boucle() être programmé pour que l'ensemble du système exécute les mouvements, sons et messages lumineux souhaités. La première ligne indique le volume de la lecture sonore monDFPlayer.volume(20) défini sur une valeur de 20 sur 30, ce qui donne le fichier nommé 001.mp3 monDFPlayer.jouer (001) joué. Ce fichier doit être stocké sur la carte microSD insérée dans le module de lecture MP3 et jouera le son du sifflet du train exactement au moment où le train démarre. Avec la ligne retard(1700) définit le temps entre la préparation du fichier audio et sa lecture.

 

monDFPlayer.volumes(20);

monDFPlayer.jouer(001);

retard(1700);

 

   Ensuite, le mouvement du train est programmé, à l'aide de la ligne analogWrite(numéro_pin, valeur) la vitesse du moteur est réglée avec une valeur analogique dont la valeur maximale est 244. Les deux sont utilisées pour le sens de rotation du moteur écriture numérique(numéro_pin, état) des lignes définies sont utilisées. Si le moteur tourne dans le sens opposé au sens souhaité, cela peut être corrigé soit en changeant l'état de ces deux lignes, soit en intervertissant les câbles entre le module L298N et le moteur.

 

analogWrite(enable_train_motor,128);

écriture numérique(connexion_1_train_moteur,ÉLEVÉ);

écriture numérique(connexion_2_train_moteur,FAIBLE);

 

   Pour allumer la LED, vous pouvez changer la position de la broche sur la connexion. Normalement, il y a une tension sur une carte microcontrôleur ou est réinitialisée, l'état initial des ports est bas (LOW), il diminue, pas de tension inférieure, mais il est nécessaire de changer l'état à un haut (HIGH) pour obtenir une tension de 5 Vcc. Elle est réalisée avec la commande digitalWrite(pin_number, STATE). Après avoir allumé chaque LED, ils se réalisent dans une pause de 1 seconde.

 

écriture numérique(led_house_1, ÉLEVÉ);

retard(1000);

écriture numérique(led_house_2, ÉLEVÉ);

retard(1000);

écriture numérique(led_house_3, ÉLEVÉ);

retard(1000);

écriture numérique(led_house_4, ÉLEVÉ);

retard(1000);

écriture numérique(led_house_5, ÉLEVÉ);

retard(1000);

écriture numérique(led_house_6, ÉLEVÉ);

retard(1000);

 

   Lorsque toutes les maisons sont éclairées, le Père Noël doit commencer à se promener dans le village, mais avant cela, il faut entendre le tintement des cloches des rennes, pour lequel le volume du son doit être ajusté myDFPlayer est défini sur une valeur de 25 sur 30. volume(25), alors le fichier portant le nom 002.mp3 est inclus monDFPlayer. jouer(002). Ce fichier doit être enregistré sur la carte microSD insérée dans le module de lecture MP3 et reproduit le son des cloches. Avec la ligne retard(800) définit le temps entre la préparation du fichier audio et sa lecture.

 

monDFPlayer.volumes(25);

monDFPlayer.jouer(002);

retard(800);

 

   Puis le Père Noël commence à tourner autour du village lorsque la file d'attente analogWrite(numéro_pin, valeur) est exécuté. La vitesse du moteur est réglée avec une valeur analogique dont la valeur maximale est de 244, comme déjà mentionné dans la première partie. La vitesse était trop élevée, mais si la valeur de cette variable est inférieure à 128, le moteur ne tournera pas, c'est pourquoi il a été décidé d'installer un potentiomètre de 5 Kohm. Dans la ligne de polarité positive allant du module L298N au moteur, la vitesse souhaitée est réglée en ajustant la valeur de ce potentiomètre. Les deux servent au sens de rotation du moteur écriture numérique(numéro_pin, état) des lignes définies sont utilisées. Si le moteur du Père Noël tourne dans le sens opposé, cela peut être corrigé soit en changeant l'état de ces deux fils, soit en intervertissant les câbles du module L298N au moteur. Avec la ligne retard(2000) Il y a une pause de 2 secondes jusqu'à ce que la ligne de code suivante soit exécutée.    

 

analogWrite(enable_Santa_moteur,128);

écriture numérique(connection_1_Santa_motor,ÉLEVÉ);

écriture numérique(connection_2_Santa_motor,FAIBLE);

retard(2000);

 

  Le volume de la lecture sonore est alors ajusté monDFPlayer.volumes(15) réglé sur une valeur de 15 sur 30 pour inclure le fichier audio nommé 003.mp3 monDFPlayer. jouer(003) ensemble. Ce fichier doit être enregistré sur la carte microSD insérée dans le module lecteur MP3 et joue une mélodie de Noël.

monDFPlayer.volumes(15);

monDFPlayer.jouer(003);

 

Les trois lignes suivantes modifient l'état des ports auxquels le module de relais est connecté de "haut" à "bas", ce qui amène le module de relais à activer les trois relais et les ventilateurs sont mis sous tension et commencent à tourner, introduisant de l'air dans l'urne, ce qui devrait faire bouger les flocons de duvet dans toutes les directions.

écriture numérique(FAN_1,FAIBLE);

écriture numérique(VENTILATEUR_2,FAIBLE);

écriture numérique(VENTILATEUR_3,FAIBLE);

 

   Puis la prochaine ligne de code show_message_az() exécuté. Cette ligne est un appel pour exécuter la méthode portant ce nom, qui exécute le code contenu dans cette méthode. Une fois l'exécution terminée, le programme revient à la ligne retard (3000) exécuté pour faire une pause de 3 secondes avant la prochaine ligne de code boucle() est exécuté.

 

show_message_az();

retard(3000);

 

   Si la méthode show_message_az() est appelé, il sera exécuté et il y aura une boucle à l'intérieur de ses accolades faire pendant quequi sera exécuté tant que la condition tandis que est vrai. Comme on s'en souvient, la variable était x initialement initialisé avec le nombre de LED que possède le panneau en largeur, soit 16. Cette boucle est exécutée jusqu'à ce que la condition tandis que la valeur x atteint par -109, qui est la dernière exécution, puisque -109 est supérieur à -110 (ce sont des nombres négatifs), le bloc de commande faire exécuté.

vide show_message_az() {

         faire {

                

                

                

         } tandis que (x > -110);

}

 

   À l'intérieur de la boucle faire La première instruction à exécuter est d'éteindre toutes les LED du panneau avec l'instruction matrice.remplir l'écran(0). La deuxième instruction définit la couleur du texte matrice.définirTextColor(matrice.Couleur(254, 0, 0)) mis en rouge, avec matrice. définirCurseur(x, 5) le curseur est placé dans la colonne 16 (c'est-à-dire que la première colonne est déplacée de 16 positions vers la gauche) et la ligne 5, puis le texte qui doit être affiché dans le panneau est inclus matrice. imprimer(F(" De AZ-Delivery ")). La condition suivante si est un compteur qui commence à 16 et va jusqu'à -110. Il est utilisé pour définir la valeur du curseur x (les colonnes) pour montrer le texte et donner l'impression de mouvement. Il diminue d'une unité et exécute l'instruction suivante, à savoir matrice.montrer(), qui allume les LED correspondantes à cette position. Avec retard(35) Il y aura une pause de 35 millisecondes car c'est la fin de la boucle. L'examen sera ensuite effectué tandis que exécuté qui dit que la boucle recommence depuis le début tant que la valeur de x est supérieur à -110. Pour résumer, configurez la couleur du texte, déplacez les colonnes et allumez les LED correspondantes pour afficher chaque partie des lettres du texte et avec le retard de 35 millisecondes donne une impression de mouvement dans le texte.

 

matrice.remplir l'écran(0);

matrice.définirTextColor(matrice.Couleur(254, 0, 0));

matrice.définirCurseur(x, 5);

matrice.imprimer(F("De AZ-Delivery "));

     

si(--x < -110) {

         x = matrice.largeur();

}

    

matrice.montrer();

retard(35);

   Une fois cette méthode terminée, elle revient à l'instruction suivante à partir de laquelle l'appel a été effectué, exécutant ainsi une attente de 3 secondes.

retard(3000);

 

   Avec les appels aux méthodes show_message_allemagne() et show_message_espagnol() Ces méthodes sont réalisées conformément à la méthode expliquée précédemment show_message_az() ressembler.

   Si vous souhaitez des images en plus du texte dans votre article de blog de Noël 2022 »3ème Avent : Décorations de Noël LED animées – MISE À JOUR" Voici les instructions sur la façon d'afficher les images sur la carte AZ-MEGA2560 et la carte AZ-ATmega328.

   Ce projet peut également se réaliser sans ventilateurs et sans l'urne transparente. Le look est différent, mais il crée toujours une sensation unique.

   Nous de AZ-Delivery Vertriebs GmbH vous souhaite un joyeux Noël, une nouvelle année réussie et beaucoup de plaisir en famille.

Für arduinoGrundlagen elektronikProjekte für fortgeschritteneSpecials

Laisser un commentaire

Tous les commentaires sont modérés avant d'être publiés

Articles de blog recommandés

  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