3D Printing (Part 13)

Part 123456789101112, 13

Many PLA rolls were fused in my Welleman k8400. So far, it has been a good servant in spite of few breakdowns, mainly due to clogged nozzle or improper adjustments. Careful cleaning and fine tuning solved all  these problems except one which is my fault. As I was taking apart the fusing module, I damaged the thread on the alumina plate that I add to replace. I also noticed few cracks on the body parts which occurred months after assembling my printer and which are probably due to over-tight bolts…

Except these minor problems, I have no particular complain and lots of enjoyment with this printer. Although PLA is very, very easy to print in most cases, it lacks to mechanical properties of ABS… And printing ABS on a non-heating bed is almost impossible. As I had to print a small ABS part in a hurry, I used an air dryer flushing hot air beneath the printing bed but this was some sort of desperate option although it proved to work fine. Months ago I ordered a heating plate and a spare DC power supply but I failed to find time to install the option and had no more particular reason to do it. Under the pressure of some Christmas presents that require some printed parts, I proceeded with the modification that I will now describe.

Removing the printing bed is plain easy. Some drilling in the metal plate is necessary and a drill press might be very useful for achieving a clean result. Draw carefully the center of the drilling locations (3.5 mm) using the heated plate as a template. Also, use a special conical cutting tool for removing enough metal from the heated bed so that the heads from the flat screws (M3x15) do not exceeds the surface (opposite to the heating layer).

Cut the original support plate to leave space for the electrical connections.

Cut the insulation rock wool sheet with a simple cutter.

Solder the 100 kOhm thermistor on the heater plate so that the little bulb sits in the dedicated hole. Put some thermal compound in this hole in order to improve the thermal joint.

Take special care to the connecting wires: they must not touch each other and must not touch the metal plate either.

Assemble the parts; use tooth lock washers and gently tighten the nuts. Solder the wires on the plate after checking the required configuration depending on the power supply used (12 or 24 V) and reinstall the whole assembly. Next is an illustration of the retaining springs that I used in the past: I reused the design for making larger springs as the printing bed got thicker.

Then you will need to move the Z axis stop sensor 8 mm downward. You have no other choice than to drill 2 new holes in the back panel of the printer. Adjust the stop position using the standard procedure.

TASCAM Sound Recorder (Part 4)

Part 1, 2, 3, 4

And here is the driver code. Nothing exceptional just plain good’ol arduino code. Check the writeByte function which contains few tricks and optimizations that are mandatory to achieve a proper timing. Ultimately this code contains a pretty versatile bit-bang UART writer that you may want to reuse in various applications.

Enter the DR-40 commands through the key board of the console using the abbreviations from the commands:

  • ‘p’: PLAY
  • ‘s’: STOP
  • ‘r’: RECORD
  • ‘f’: FORWARD
  • ‘b’: BACK
  • ‘m’: MARK
  • ‘1’: F1
  • ‘2’: F2
  • ‘3’: F3
  • ‘4’: F4
uint8_t _TxMask;
uint8_t _TxMaskBar;
volatile uint8_t *_TxPort; 
uint16_t _timeInterval;
bool _invert;
bool _parity;
#define ONE_MILLION 1000000UL
    
#define STOP 		0x08
#define PLAY 		0x09
#define RECORD 		0x0B
#define FORWARD 	0x0E
#define BACK 		0x0F
#define MARK 		0x18
#define F1 			0x1C
#define F2 			0x1D
#define F3 			0x1E
#define F4 			0x1F

#define KEY_PRESS	0x40
#define KEY_DOWN	0x60
#define KEY_UP		0x00

#define PAR_NONE	0x00
#define PAR_EVEN	0x01
#define PAR_ODD		0x02

/*
Initialize communication port 
Any pin on any port can be used
Baud rate goes up to 57600 
Parity may be none (0), odd (1) or even (2)
Data may be inverted or not (flip mark and spaces)
*/
void begin(volatile uint8_t *TxPort, uint8_t TxPin, uint32_t baudRate = 9600, uint8_t parity = PAR_NONE, bool invert = true)
{
    /* Record global variables */
    _invert = invert;
    _parity = parity;
    /* Transmit port */
    _TxPort = TxPort;
    /* Transmit pin */
    _TxMask = (0x01 << TxPin);
    _TxMaskBar = ~_TxMask;
    /* Make TxPin an output pin */
    *(_TxPort - 1) |= _TxMask; 	
    /* Set idle mode */
    if  (!_invert) 
    {
        *(_TxPort) |= _TxMask;
    } 
    else 
    {
        *(_TxPort) &= _TxMaskBar;
    }
    /* Set bits intervals  in us */
    _timeInterval = (ONE_MILLION / baudRate);
}


/* 
Write byte on serial port
global variables in use:
    _parity
    _invert
    _TxPort
    _TxMask
    _TxMaskBar
    _timeInterval

idle
-----------     ---     ---     ---     ---    ---- --- ----   1 mark
           |Sta| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |Par|Stp|
            ---     ---     ---     ---     --- ---           0 space/break
*/
void writeByte(const uint8_t data) 
{
    uint32_t now;
    uint16_t compositeBits = 0x00; /* Map data bits */
    /* compositeBits content: 76543210 */
    compositeBits |= data; /* Map data bits */
    uint8_t bits = 8;
    if (_parity != PAR_NONE)
    {
        bool dataParity = parity(data);
        /* Append a mark as appropriate */
        if (((_parity == PAR_EVEN) && dataParity) || ((_parity == PAR_ODD) && !dataParity))
        {
            /* compositeBits content: p76543210 */
            compositeBits |= (0x01 << bits);  /* Map parity bit */
        }
        bits += 1; /* Actually 9 bits */
    }
    /* compositeBits content: Sp76543210 or S76543210*/
    compositeBits |= (0x01 << bits);  /* Map stop bit (mark) */	
    /* compositeBits content: Sp76543210s or S76543210s */
    compositeBits <<= 1; /* Shift bits for start inclusion (space) */
    bits += 2;
    if (_invert)
    {
        compositeBits= ~compositeBits;
    }
    uint32_t lastTick = micros(); /* Record start time of bits transfer */
    /* Transfer composite bits starting from lower bits */
    for (uint8_t i = 0; i < bits; i++) 
    {
        uint8_t bitValue = (compositeBits & 0x01); /* Extract lower bit value */
        if  (bitValue) 
        {
            *(_TxPort) |= _TxMask;
        } 
        else 
        {
            *(_TxPort) &= _TxMaskBar;
        }
        compositeBits >>= 1; /* Shift bits */
        while((micros() - lastTick) < _timeInterval);
        lastTick += _timeInterval; /* Set next bit release time */
    }
}

/*
Send function key 
*/
void sendKey(uint8_t function)
{
    writeByte(function | KEY_PRESS);
    delay(150);
    writeByte(function | KEY_UP);
}

/* 
Computes the parity from a value. The function returns a true for an odd number
of bits and a false for an even number of bits.
*/
bool parity(uint8_t n) 
{ 
    bool parity = 0; 
    while (n) 
    { 
        parity = !parity; 
        n = (n & (n - 1)); 
    }         
    return(parity); 
} 

void setup()
{
    /* Configure serial port using default parameters */
    begin(&PORTB, PINB0, 9600, PAR_EVEN, true);
    delay(500);
    Serial.begin(115200);
}

void loop()
{
    /* Listen to incoming bytes from the console */
    if (Serial.available() > 0)
    {
        char inputByte = (char)Serial.read();
        switch(inputByte)
        {
            case 'p': sendKey(PLAY); break;
            case 's': sendKey(STOP); break;
            case 'r': sendKey(RECORD); break;
            case 'f': sendKey(FORWARD); break;
            case 'b': sendKey(BACK); break;
            case 'm': sendKey(MARK); break;
            case '1': sendKey(F1); break;
            case '2': sendKey(F2); break;
            case '3': sendKey(F3); break;
            case '4': sendKey(F4); break;
        }
    }
    delay(10);
}

 

 

TASCAM Sound Recorder (Part 3)

Part 1, 2, 3, 4

As per product reviews on the web and as per my personal experience, the DR-40 picks up noises generated by the handling of the device. One way to prevent such noises consists in using a wired remote controller namely the Tascam RC-10. The key component from this option is a compact flat box featuring 10 buttons. It outputs a coded IR beam for controlling TASCAM devices.

However, as the DR-40 does not feature an IR receiver port so that TASCAM (actually TEAC) designed a dock for the remote controller. This dock is very likely fitted with an IR receiver which converts the coded IR beam into a TTL compatible signal. This TTL signal is routed to the DR-40 via a 3 wires cable which plugs to the bottom of the recorder with a 2.5 stereo jack. The dock itself  features a clip at the back which is handy for attaching it to your belt of your trousers or to the pocket of your reporter vest.

Although the cable is 3m long, this length might not suffice for reaching the recorder. Thus the idea of taking control of the DR-40 through a custom remote controller. And the good news is that this is easily manageable as the remote controller talks to the device using an asynchronous protocol. As mentioned above, the connecting hardware consists in a stereo jack of 2.5 mm where:

  • the tip is for the signal from the controller to the device
  • the ring is for the +3.3 V from the device (used to power the controller)
  • the sleeve is for the GND

Next is a description of the data exchanged between the device and the controller:

Three button states are interpreted:

  • button press
  • button down (for more than 100 ms)
  • button up

To each button corresponds a function

  • Pause/Stop
  • Play
  • Record
  • Forward
  • Back
  • Mark
  • F1
  • F2
  • F3 (Input volume +)
  • F4 (Input volume -)

On each change of state the RC-10 sends a byte which format is as follows:

 ----- ----- ----- ----- ----- ----- ----- ----- 
|  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
 ----- ----- ----- ----- ----- ----- ----- ----- 
|  X  | BS  | BS  |  F  |  F  |  F  |  F  |  F  |
 ----- ----- ----- ----- ----- ----- ----- -----

Where :

  • BS stands for button state
  • F stands for function

With:

Button states

 
 ----- ----- ----- ----- ----- ----- ----- ----- 
|  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
 ----- ----- ----- ----- ----- ----- ----- ----- 
|  X  |  1  |  0  |  X  |  X  |  X  |  X  |  X  | Button down
|  X  |  1  |  1  |  X  |  X  |  X  |  X  |  X  | Button down for more than 100ms, 
|  X  |  0  |  0  |  X  |  X  |  X  |  X  |  X  | Button up
 ----- ----- ----- ----- ----- ----- ----- -----

Functions

 
 ----- ----- ----- ----- ----- ----- ----- ----- 
|  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
 ----- ----- ----- ----- ----- ----- ----- ----- 
|  X  |  X  |  0  |  0  |  1  |  0  |  0  |  0  | Pause/Stop
|  X  |  X  |  0  |  0  |  1  |  0  |  0  |  1  | Play
|  X  |  X  |  0  |  0  |  1  |  0  |  1  |  1  | Record
|  X  |  X  |  0  |  0  |  1  |  1  |  1  |  0  | Forward
|  X  |  X  |  0  |  0  |  1  |  1  |  1  |  1  | Back
|  X  |  X  |  1  |  1  |  1  |  0  |  0  |  0  | Mark
|  X  |  X  |  1  |  1  |  1  |  1  |  0  |  0  | F1
|  X  |  X  |  1  |  1  |  1  |  1  |  0  |  1  | F2
|  X  |  X  |  1  |  1  |  1  |  1  |  1  |  0  | F3
|  X  |  X  |  1  |  1  |  1  |  1  |  1  |  1  | F4
 ----- ----- ----- ----- ----- ----- ----- -----

Please note that  unlike the DR-40 itself, running some functions require doubled actions: to stop a play back, run the stop command twice. The first one will pause the playback, the second one will stop it. To record sounds, run the record command twice: the first one presets the recording and the second one launches the recording itself.

Driving the DR-40 from a standard Arduino (+5V) is quite simple and requires few cheap components. Two options are considered: the safe one and the standard one. The safe option features an optocoupler while the other option features a GP transistor. Both will trigger the signal line using an open collector configuration. Next picture illustrates the two options:

The pull up resistor which is built in the DR-40 is about 10 k Ohm. However it looks insufficient for obtaining clean squared pulses out of the interface. I experimentally found that fitting a 10 k Ohm resistor (R1) in the interface is a good compromise between signal cleanness and power consumption. R2 might be in the k Ohm range (1 to 10 k Ohm) and T1 might be any general purpose NPN transistor holding up to a vertiginous 10 mA Ice (A 2N3904 will do the job very well). R3 is chosen so that the current through the LED is about 10 mA which is the optimum running point for a 4N35 optocoupler (500 Ohm).

From a code point of view, all you have to really care about is the inverted signal out of this controller: a high level on an Arduino pin will result in a low level on the controller side. The code that I will introduce in a later post features a bit bang serial writer that can be set for both normal and inverted signal (in other words, spaces and marks are swapped in the digital messages). Few other things have to be taken into account. Firstly, the baud rate is 9600. Issuing a key action consists in generating a key press word, wait for 150 ms and issue a key up word. I did not bother with the key down state as it makes no sense in the context of this project. Last but not least, the issued words are 11 bits long: 1 start bit, 8 data bits, 1 even parity bit (the number of marks + the parity bit must be an even number) and 1 stop bit. Again, the bit bang writer will allow you to set all these parameters.

Next post on same subject

TASCAM Sound Recorder (Part 2)

Part 1, 2, 3, 4

And here it comes! Packed in a cardbox box which contains:

  • 1 Tascam DR-40 recorder wrapped in plastic bag
  • 1 mini USB cable
  • 1 user Manual printed in various languages
  • 3 alkaline batteries
  • 1 small rubber stand in a small plastic bag!

Watch out, this small rubber stand is a very convenient part that I nearly missed and would have lost… you may want to store it in a safe place when not in use in the batteries compartment, as shown on a the picture below.

.

Using the device is pretty intuitive. This buttons are smooth and comfortable to use, the screen is quite small (to my aging eyes) but still readable. However, as mentioned in many reports which to apply to most devices from any brand, there are many recording options which may not be so easy to find. One should have a good understanding of the recording parameters (Sampling rate, sound level management, band width limitations, resolution, etc.) before trying to use this device. Oh, well, selecting WAV format with 24 bits data sampled at 96k in automatic gain control mode will do the job in many cases. As long as you do not fear XXL data files and long lasting post-production data analysis.

I was amazed by the microphone position sensor ! When you move both microphones, the menu asks for confirmation of the XY (Crossed) or AB (Split) mode ! Pretty convenient.

The primary use of this recorder is the capture of out-door sounds so that I “invested” in a wind screen. I took no risk at trying cheap fancy looking fur caps and instead followed the recommendation of the supplier. So I ordered a RYCOTE DR-40MWJ which fits as expected very well to the recorder’s body, has plenty room for the microphones even in the AB position.

The mounting thread is conveniently located so that installing the DR-40 on any tripod is very easy. Although placing the the recorder horizontally on a table is probably not the best option for recording, it is the most obvious position (at least for learning how to use the device) and the little rubber foot which fits in the mounting thread is simply clever. From the very early records I could confirm what I read in one of the reviews: the handling of the recorder generates a lot of rubbish sounds. You may either wear rubber gloves or wrap the recorder with foam…

On the other hand, the XLR extractors prevent the recorder from standing still in a vertical position. One may add a pair of rubber feet to compensate the offset.

It does take a few minutes to get ready and record the first sounds. Data can be read from the SD card (micro SD sitting in a standard SD dock, well done TASCAM !) or by connecting the recorder to a PC via the USB mini cable. My favorite sound analysis software is Audacity, almost as powerful as Goldwave but free. Both software feature many, many functions which are very useful not to say mandatory to cleanup records, mix tracks, normalize, etc.

Next post on same subject

TASCAM Sound Recorder (Part 1)

Part 1, 2, 3, 4

The followers of arduinoos know that I have a constant and strong interest in sound recording and analysis. As I get more and more requests for specific sound analysis, I decided to get a semi-professional sound recorder to capture sound events in various environments. Thus the wish list that I used to find commercial products:

  • Portable device
  • Self powered (primary batteries)
  • Good autonomy (> 4h)
  • Powered through and AC adapter
  • Built-in microphones
  • 2 external microphones
  • 2 tracks minimum, 2 additional tracks for recording at a lower level or for recording external microphones is a solid option
  • MP3 and WAV formats
  • >= 24 bits
  • >= 48 kHz sampling rate
  • Low noise
  • Large dynamic range
  • USB port
  • Remote control, wireless remote control (BT, WiFi or IR)  is a solid option
  • Availability of compatible accessories: carrying case, wind shield, external microphones (Possibly XLR), etc.
  • Reasonably rugged

From my early searches, I understand that very good CODEC chips handle the main recording and playback functions from these digital recorders. The difference comes from various aspects that I am trying to enumerate below:

  • Casing: ranges from plastic to strong metallic casing. Cheap solutions may not be reliable and strong enough in the long term and generate noises when handled without extra care.
  • Amplifying stages: ranges from basic designs to very carefully designed pre-amplifiers. This draws us back some decades ago and is still meaningful to me. Noise and dynamic range are directly affected by the design.
  • Built in microphones: I am lacking consistent experience in this domain but my guess is that the primary source of information is critical and that a wide range a products exists.
  • Power: This is an other not so critical but very practical aspect of the devices.  One may decide from the very early development stages if the device shall be ULP, LP or simply as good as it can be. Anyone who missed this exceptional picture our sound capture because you were low on battery will understand me !

And ultimately, I had to take my budget into account ! Taking into consideration the fact that the recorder may (and will) require additional accessories in order to be used in various conditions, e.g. wind shield (1/4 of the price of the recorder!), tripod, remote control, etc. I focused my interest in the products lying in the 100 to 200€ range.

I read many posts in various websites, including this detailed, very well documented web site on capturing sounds from animals. Too bad, the price range of the recommended equipment was much, much higher than my top budget. However this blog was very instructive and informative so that I tried to take most of their argument into account and tried to apply them to my own project. Among the serious papers I found was this very informative review from Mike Rivers which was very helpful to me for making a thoughtful decision. Many other comparison can be sound including this one from the Cornell Lab of Ornithology.

And ultimately, I ordered a Tascam DR-40

Its user manual is available from here 

Next post on same subject

Retour vers le futur

Allez, zou, pour une fois voici une publication en français !

Cà fait un moment que çà me grattouillait le clavier de composer dans ma langue maternelle, et je vois au moins deux bonnes raisons de faire une entorse à ma politique de publication. Soyons réalistes, l’anglais est une langue universellement comprise par les technophiles, et, persistant à vouloir partager avec le plus grand nombre, c’est la langue que j’ai choisie pour mes publications. Cependant, je suis très agacé par le récent raidissement de nos voisins anglo-saxons et leur repli économico-identitaire: non mesdames, non messieurs, vous n’êtes pas seuls au monde, vous ne détenez pas le monopole du savoir et de la science, ouvrez les yeux tant qu’il est encore temps. Ceci étant dit, cet article va traiter d’un sujet que seuls les mangeurs de grenouilles, porteurs de béret et accrédités à délivrer le French kiss (tiens, voilà t’y pas que je rechute) peuvent comprendre. Je vais vous parler d’une petite merveille qui a permis l’introduction des principes de l’informatique jusqu’au plus profond des campagnes et qui a été détrônée par la vague Internet au seuil du deuxième millénaire après 30 ans de bons et loyaux services. Je veux parler du Minitel bien entendu.

Pour éviter d’avoir à gérer l’élimination massive des déchets produits par l’obsolescence du Minitel, France Télécom a très généreusement fait cadeau des Minitels à ses abonnés… Bonne aubaine pour les bidouilleurs de tout poil, car le Minitel est une sorte de console compacte dotée d’un clavier de saisie, d’un écran monochrome (couleur pour les derniers modèles) et de deux interfaces: l’une qui était bien entendu reliée à la ligne téléphonique et l’autre permettait une communication de type série avec des périphériques externes! Donc je récapitule: un produit bien conçu, compact et costaud, configurable comme console et disponible en masse pour pas cher (10 à 20 € en moyenne): Supeeeeer ! (Blague pour initiés)

Le projet dont il est ici question résulte du croisement improbable d’amateurs de techno d’un fab-lab avec des amateurs d’escape game désireux de truffer leur terrain de jeu de références à des séries de science fiction…

Le cahier des charges du jeu, inspiré de la série Fallout, consiste à intégrer les fonctions suivantes dans un Minitel :

  • Lorsque le programme est lancé, le Minitel doit afficher afficher deux lignes d’entête et 32 lignes (paramètrable) de pseudo image mémoire sous forme de deux séries verticales comportant chacune une colonne d’adresses séquentielles (hexa) et de contenu mémoire (12 octets) constitué de caractères aléatoires n’appartenant pas à l’alphabet.
  • Dans ce contenu mémoire sont mélangés aléatoirement six mots (paramètrable) de six lettres, dont un, tiré au hasard, est le mot de passe.
    Le joueur peut effectuer 4 tentatives (paramètrable) pour trouver le mot de passe. A chaque tentative invalide, le programme indique le nombre de lettres correspondantes entre le mot de passe saisi et le mot de passe tiré au hasard par le programme.
    En cas de succès, l’écran est effacé et remplacé par un message de succès suivi du code d’accès BLABLABLABLABLABLA*. Dans le cas contraire, un message d’échec est affiché.
  • Dans tous les cas une ligne de saisie (précédée par le caractère >) est destinée à recevoir le code admin BLABLABLA* qui relance le jeu.

* vous n’imaginez tout de même pas que je vais dévoiler les mots de passe!

En bref, l’écran principal doit ressembler à quelque chose comme:

Le principal défi technique à relever est l’intégration de tout le code ainsi que la base de mots de 6 lettres, soit 7773 mots) dans une simple carte Arduino . Et pour corser le tout, le fab-lab disposait de 15 jours pour boucler le sujet ! Au départ, je me suis posé la question de développer un algorithme de compression pour réduire la taille de la base, mais le temps faisant défaut, et surtout, souhaitant impliquer nos jeunes développeurs, j’ai bâti le projet sur des bases plus simples. Une option aurait pu consister à intégrer la base dans une carte SD, mais nous n’avions pas de shield sous la main.  J’ai aussi fouillé sur la toile à la recherche de librairies de pilotage du Minitel, et, bingo, j’en ai trouvé plusieurs, plus ou moins à mon gout et surtout assez gourmandes en mémoire. Au final, j’ai opté pour un code maison, le plus compact possible, de manière à libérer un maximum d’espace mémoire (mémoire programmable) pour y loger les mots clé. J’ai écrit un petit algo très simple pour décimer les mots clés et conserver au final 3000 mots répartis de manière homogène dans l’alphabet. Partant de là, yapuka !

Je me suis aidé de la très complète documentation (56 Mo) “spécifications techniques d’utilisation du minitel 1B” ainsi que la consultation de nombreux sites Internet consacrés au Minitel. Code sur demande, comme d’habitude.

Partant de là, Sébastien qui me surpasse et de loin en créativité tous azimuts, a ajouté sa patte artistique et a transformé un vénérable minitel en quasi-authentique console d’accès aux calculateurs secrets de Fallout ! Le résultat en images:

Top non ?

Le hasard étant facétieux, que ne lis-je point dans ma veille techno sur Twitter ? Un article consacré au même sujet traité avec des solutions beaucoup moins attrayantes !

D’abord il ne fait pas appel à des composants de récupération et ensuite il n’est pas interactif (le clavier n’est pas fonctionnel)… Pouah ! Pour paraphraser Catherin Bugnard, je dirais même “Tout l’monde peuvent pas êt’e français, il en faut bien d’ailleurs.”

 

 

FN-M16P MP3 player (Part 2)

Part 1, 2

As seen in the previous post, the MCU (e.g. arduino) and the module are talking each other through a serial communication (UART) at a quite modest rate of 9600 baud. Data is exchanged as packets of 10 bytes according to the following structure:

Byte#	Function		Value	Comments
0	Start Byte		0x7E	constant
1	Version Info		0xFF	my module returns 8, any input value will work
2	Number of bytes		0x06	constant
3	Command 		0xXX	See datasheet
4	Command feedback	0xXX	0x00 or 0x01
5	Parameter		0xXX	parameter MSB, see datasheet
6	Parameter		0xXX	parameter LSB, see datasheet
7	Checksum		0xXX	checksum MSB
8	Checksum		0xXX	checksum LSB
9	End command		0xEF	constant

The checksum is computed over the 6 bits proceeding it. Computing the checksum is fairly easy: sum the 6 bytes and negate them. Then map the Most Significant and the Least Significant Bytes (MSB & LSB).

16 bits can be used for the parameter settings. Various cases happen:

  • Some commands do not require a parameter, then enter any byte value
  • Some commands require an 8 bit parameter, then enter this parameter as the LSB and enter any value for the LSB
  • Some commands require two 8 bit parameters, then enter each parameter as the LSB and the LSB
  • Some commands require a 16 bits parameter, then map the MSB ((value >> 8) & OxFF) and LSB (value & OxFF) from the parameter and enter then as the parameter MSB and LSB
  • One command requires a 4 bits parameter and a 12 bits parameter, then apply a 4 bits shift to the first parameter and map them to the MSB, the 4 next bits are shifted from the second parameter and the remaining bits are mapped to the LSB.

The command feedback is optional and may be necessary in harsh environments. However, the risk is low that the UART will fail to exchange data at 9600 bauds so that I did not implement this option in my code. Surprisingly, the checksum is not mandatory and the checksum bytes might be omitted, leading to 8 bytes long frames. However, I maintained this minimal integrity protection level in the data  communication.

Next is a link to a spreadsheet that I used in my early testing which you may find helpful for debugging. >Link<

While most commands do not echo data from the device, some do. This is the case for the commands echoing the current sound level, the number of tracks on device, etc. Data is transmitted back once the full incoming frame is read and decoded by the device (half duplex transmission). Errors are reported as command 0x40.

The library that I built uses general purpose functions that relate to the “sound tracks reader” mode and to the “sound tracks manager” mode. In its early version, it contains a light management of errors.

Next is a copy of the command launcher function

/*
Execute command using its parameters
The returned value is passed by reference and the function returns error codes (DFP_ERR_NONE=0=no error)
*/
uint8_t PlainDFP::execCmd(uint8_t CMD, uint8_t paramMSB, uint8_t paramLSB, uint16_t *retValue) 
{
	uint8_t error = DFP_ERR_NONE;
	uint8_t vBuffer[10];
	/* Build the command line */
	vBuffer[0] = 0x7E; 					/* Start byte (constant) */
	vBuffer[1] = 0xFF; 					/* Version byte: any value */
	vBuffer[2] = 0x06; 					/* Data length (checksum not included) always 6 */
	vBuffer[3] = CMD;  					/* Actual command */
	vBuffer[4] = 0x00; 					/* Feedback request: 0=no, 1=yes */
	vBuffer[5] = paramMSB; 				/* Parameter MSB */
	vBuffer[6] = paramLSB; 				/* Parameter LSB */
	vBuffer[7] = 0xFF; 					/* Check sum MSB */
	vBuffer[8] = 0xFF; 					/* Check sum LSB */
	vBuffer[9] = 0xEF; 					/* End byte (constant) */
	/* Compute and record checksum */
	int16_t checksum = checkSum(vBuffer);
	vBuffer[7] = ((checksum >> 8) & 0xFF); 		/* Check sum MSB */
	vBuffer[8] = (checksum & 0xFF); 			/* Check sum LSB */
	/* Send the command line to the module */
	for (uint8_t i = 0; i < 10; i++)
	{
		_serial->write(vBuffer[i]);
	}
	/* If the command is supposed to echo a feed back */
	if (CMD > 0x20)
	{
		delay(100);
		if (_serial->available() >= 10) 
		{
			/* Record answer in buffer */
			for (uint8_t i = 0; i < 10; i++)
			{
				vBuffer[i] = _serial->read();
			}
			/* Flush exta bytes from receive buffer */
			while (_serial->available())
			{
				_serial->read();
			}
			/* Compute checksum from receive buffer and compare it to the computed checksum */
			checksum = checkSum(vBuffer);
			if (checksum == ((vBuffer[7]  << 8) || vBuffer[8]))
			{
				*retValue = ((vBuffer[5] << 8) || vBuffer[6]);
			}
			else
			{
				error = DFP_ERR_INV_CHK_SUM; 
			}
			/* Device returns an error data with this command */
			if (vBuffer[3] == 0x40)
			{
				error = DFP_ERR_DEV_ERROR;
			}
		}
		else
		{
			error = DFP_ERR_MIS_ANSWER; 
		}
	}
	return(error);
}

And next is the checksum function

/*
Compute check sum from a 10 bytes long buffer
*/
int16_t PlainDFP::checkSum(uint8_t *vBuffer)
{
	int16_t result = 0;
	for (uint8_t i = 1; i < 7; i++)
	{
		result += vBuffer[i];
	}
	result *= -1;
	return(result);
}

 

 

FN-M16P MP3 player (Part 1)

Part 1, 2

How come I managed to miss this fancy little module ? It’s my good ol’ friend Sébastien from Quai-Lab who showed me this little piece of electronic which he included in his inMoov robot. Bright idea ! For a few €, his robot will speak and improve its interactions to the public.

It did not take long before I found one on the Internet and got it delivered in a small envelop. Although this module is mostly known as the DF-Player Mini, it sounds like its original name is FN-M16P. This module is amazingly small, thanks to the use of Micro-SD card (aka TF card) on one side and two tiny ICs, one for the card management the other for amplifying the signal in order to directly connect a speaker to the module. A blue diode will light up when the module is playing songs.

I have not been able to find any link to the main chip which is marked as JC (maker ?) AA 1751CJ3MNP. Anybody has any hint ?

There are two ways of running this module: the autonomous way, and a driven way, requiring a simple MCU.

The autonomous way ranges from basic: next/previous track, +/- sound volume with only two buttons up to a 20 buttons interface wired as two banks of ten buttons each to the module !

The basic approach will be very helpful for checking your module. Next drawing illustrates the how to:

This is plain easy and does not even require any knowledge in electronics, except the understanding of VCC being the positive pole and GND the negative pole of a 3.2 … 5.0 V power supply.

Plugin the module to a MCU such as arduino is almost as easy. Next drawing illustrates the how to:

What is new to this design ? Firstly, there is no longer this basic human interface. The module is controlled by the MCU through a serial communication. Rx from one side connected to the opposite Tx. The two 1 kOhm resistors have been suggested by previous authors in order to attenuate the noise generated by the MCU and circulating through the communication lines. An ultimate solution would consist in using a level adapter as the the module is 3.3 V compliant, 5 V tolerant. In the same spirit, one may want to filter the power supply by adding a couple of capacitors, C1 ~tens of µF / 10 V and C2 0.1 µF / 10V. Also new is the use of the DAC outputs connected to any amplified speaker through a stereo line cord. This is the design that I used for testing and writing the related code.

Last but not least, here is a link to the data sheet. Although many copies or clones are available, most fail to provide accurate information. And this one is no even fully accurate, nor does it provide clear information… Some reverse engineering has been necessary to get deeper in the understanding, and while seeking for information I inadvertently found undocumented commands !

Next posts will relate to the code I wrote. But hey, stop ! Why bother writing code while it looks like many libraries exist ? Well the thing is that none from the three ones I downloaded worked from scratch and I found them pretty complex (in fact too much too complex) for plain applications. So that I decided to write a library my own way. As the documentation is not so good (compared to European standards), it took me sometime to get a clear picture of the available commands and the way they could be used.

I found that there are two ways (this is my analysis) of using this module: as a simple MP3 sound player or as a sound tracks manager. In my future writings, I will distinguish the notion of track (sound track) from the notion of folders and files.

A MP3 “sound player” will use the tracks oriented commands (playback, pause, stop, next, previous, repeat and random) while a “sound manager” application will randomly get named files in named directories (and still use pause, stop, next, previous, repeat options).  Also note that the module can read .wav files !

You do not to tidy or apply any naming convention to your file in the “sound player” mode. Copy up to 3000 tracks on a SD-Card and you’re done. For the “sound manager” mode, you have three options: store 65536 files in one special folder (named “MP3”), store up to 3000 files in 15 folders or store up to 255 files in 99 folders ! Each file must be preceded by its index. eg. 001-song_for_you.mp3, 002-song_for_me.mp3, … 255-song_for_them.mp3, in folders 01, 02 … 99. This is a glimpse at the principle of use and it may be helpful for thinking at applications such as a thermometer for the blind…

Next post on same subject

Shortage of Multilayer Ceramic Chip Capacitors (MLCC)

How come this tiny ultra familiar component is running out of stock ?

The information raised by constructors and vendors states that the unexpected growth of demand lead to a recurent shortage of products as explained here, there and here again. These papers also give advises for those who did not contract the supply of million of parts per month and who are bound to the availablity of detail suppliers (like I do!).

Ultimately, you may want to roll your own capacitors

 

PCBs (Part 4)

Part 1, 2, 3, 4

PCBWay order review

Delivery:

The parcel arrived in my mail box 5 days after the order date, as announced !!! This is great news as we are all eager to get the real thing asap.

Packing (Mail):

The parcel was delivered by DHL: we know this company, I personally used their services for China. As I was asking for adjusted fare rates depending on delivery times DHL told me that they have only one delivery mode: asap !

Content:

Here comes the smart part. We all know about the importance of the first seconds in a meeting, the first words and the first attitudes. PCBWay knows its job and surprise surprise, you get some nice goodies. Well done guys 😉

Packing (Product):

As expected, the PCBs are wrapped in a vacuum sealed plastic bag. This is state of the art.

PCB inspection:

Here are a couple of pictures taken with my modest means and my very limited skills at taking pictures:

And here is a closer look at the PCB

Conclusions:

What else can I say ? The pictures speak for them selves, delivery times are almost as short as delivery times for European based PCB companies. Taking into account the very moderate cost, this is a five star cost/quality option.