Wednesday, December 31, 2014

FM radio receiver for your Arduino (TEA5767/TEA5768/TEA5757)
(Part 2/4)





Abstract

In this second part we provide C++ classes to deal with TEA576X family of chips. We also provide a basic sketch for using the TEA5767HN module that one may buy for few bucks. The next post will be concerned with the FM module and the last one will provide an example of (basic) FM Radio as an application of the FM module.


Updated

After further tests some bugs were found. Here is the list:
  • Read procedures in TEA5767HN.cpp and TEA5768HL.cpp
  • #define constants in TEA576X.h
  • Search procedure in TEA576X.cpp
Please download all those files again!



TEA576X
Recall that the chips of the family TEA576X differ only for the communication protocol (SPI or I2C). We have therefore conceived an abstract class, TEA576X, which implements all the methods except the write and read functions that are delegated to the derived classes. Both the header and the implementation files are pretty long, you can download them below:

The headers
Choose the header you need for your sketches. Save these files as ClassName.h

Class TEA5767HL
/**
 *  \file TEA5767HL.h
 *
 *  \brief A class for dealing with TEA5767HL chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \version 1.0
 *
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#ifndef ____TEA5767HL__
#define ____TEA5767HL__

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif


#include "TEA576X.h"
#include <SPI.h>

#define M_FM_TEA5767HL 0xC8189CB3

/**
 \class TEA5767HL TEA5767HL.h
 \brief A class for TEA5767HL component.
 
 This class implements the methods to interact with the TEA5767HL component
 which is a FM receiver. For more on this component refer to
 http://macduino.blogspot.com/2014/12/FM-Radio-TEA5767.html
 
 \see TEA576X
 */

class TEA5767HL : public TEA576X {
private:
    /**
     * \var _SSPin
     * \brief Slave Select pin for the SPI protocol.
     */
    uint8_t _SSPin; // Slave Select pin
public:
    /**
        \fn void begin(float xtal, uint8_t SSpin)
        \brief Init TEA5767HL chip.
        @param SSpin Slave Select pin.
    */
    void begin(float xtal, uint8_t SSpin);
    /**
     \fn void write()
     \brief Send the current write sequence to the TEA5767HL.
     \warning All the operations or changes to the module settings have no effect
     untill a write() operation is issued.
     */
    void write();
    /**
     \fn void read()
     \brief Read-in the current read sequence of the TEA5767HL.
     */
    void read();
};


#endif /* defined(____TEA5767HL__) */
Class TEA5768HL
/**
 *  \file TEA5768HL.h
 *
 *  \brief A class for dealing with TEA5768HL chip.
 *
 *  \author Enrico Formenti,
 *  \date 23 dec 2014
 *  \version 1.0
 *
 *  \copyright BSD license, check the License page on the blog for more information. All this text must be 
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#ifndef ____TEA5768HL__h
#define ____TEA5768HL__h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "TEA576X.h"
#include <Wire.h>

#define M_FM_TEA5767HL 0x717D6A52

/**
 \class TEA5768HL TEA5768HL.h
 \brief A class for TEA5768HL component.
 
 This class implements the methods to interact with the TEA5768HL component
 which is a FM receiver. For more on this component refer to
 http://macduino.blogspot.com/2014/12/FM-Radio-TEA5767.html
 
 \see TEA576X
 */

class TEA5768HL : public TEA576X {
public:
    /**
     \fn void write()
     \brief Send the current write sequence to the TEA5768HL.
     \warning All the operations or changes to the module settings have no effect
     untill a write() operation is issued.
     */
    voidwrite
Class TEA5767HN

Warning: If you have installed Arduino 1.5.8 Beta, then you need to install SPI library manually from GitHub. It can be found here. If you have an older version (1.0.6 for example) then there is no problem since it comes with the SPI library pre-installed.

Implementing the classes
Choose the files you need for your sketches and save the files as ClassName.cpp


Implementation of the class TEA5767HL
/**
 *  \file TEA5767HL.cpp
 *
 *  \brief Implementation of a class for dealing with TEA5767HL chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \version 1.0
 *
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "TEA5767HL.h"

void TEA5767HL::begin(float xtal, uint8_t SSpin) {
    TEA576X::begin(xtal);
    _SSPin = SSpin;
}

void TEA5767HL::write() {
    register uint8_t i;
    
    // take the SS pin low to select the chip:
    digitalWrite(_SSPin,LOW);
    
    // send buffer data
    for(i=0; i<5; i++)
        SPI.transfer(wbuf[i]);

    // take the SS pin high to de-select the chip:
    digitalWrite(_SSPin,HIGH);
}

void TEA5767HL::read() {
    register uint8_t i;
    
    // take the SS pin low to select the chip:
    digitalWrite(_SSPin,LOW);
    
    // read-in buffer data
    for(i=0; i<5; i++)
        rbuf[i] = SPI.transfer(0x0);
    
    // take the SS pin high to de-select the chip:
    digitalWrite(_SSPin,HIGH);
}
Implementation of the class TEA5768HL
/**
 *  \file TEA5768HL.cpp
 *
 *  \brief Implementation of a class for dealing with TEA5768HL chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \date 22 jan 2015
 *  \version 1.1
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "TEA5768HL.h"

void TEA5768HL::write() {
    register uint8_t i;
    
    Wire.beginTransmission(TEA576X_I2C_ADDRESS);
    
    for(i=0; i<5; i++)
        Wire.write(wbuf[i]);
    
    Wire.endTransmission();
}

void TEA5768HL::read() {
    register uint8_t i = 0;
    
    Wire.requestFrom(TEA576X_I2C_ADDRESS, 5);
    
    while(Wire.available())
        rbuf[i++] = Wire.read();
}
Implementation of the class TEA5767HN
/**
 *  \file TEA5767HN.cpp
 *
 *  \brief Implementation of a class for dealing with TEA5767HN chip.
 *
 *  \author Enrico Formenti
 *  \date 23 dec 2014
 *  \date 22 jan 2015
 *  \version 1.1
 *  \copyright BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */

#include "TEA5767HN.h"

void TEA5767HN::begin(float xtal, bool bus, uint8_t SSpin) {
    _bustype = bus;
    _SSPin = SSpin;
    TEA576X::begin(xtal);
}

void TEA5767HN::write() {
    register uint8_t i;
    
    if(_bustype) {
        // take the SS pin low to select the chip:
        digitalWrite(_SSPin,LOW);
    
        // send buffer data
        for(i=0; i<5; i++)
            SPI.transfer(wbuf[i]);

        // take the SS pin high to de-select the chip:
        digitalWrite(_SSPin,HIGH);
    }
    else {
        Wire.beginTransmission(TEA576X_I2C_ADDRESS);
        
        for(i=0; i<5; i++)
            Wire.write(wbuf[i]);
        
        Wire.endTransmission();

    }
}

void TEA5767HN::read() {
    register uint8_t i = 0;

    if(_bustype) {
        // take the SS pin low to select the chip:
        digitalWrite(_SSPin,LOW);
    
        // read-in buffer data
        for(; i<5; i++)
            rbuf[i] = SPI.transfer(0x0);
    
        // take the SS pin high to de-select the chip:
        digitalWrite(_SSPin,HIGH);
    }
    else {
        
        Wire.requestFrom(TEA576X_I2C_ADDRESS, 5);
        
        while(Wire.available())
            rbuf[i++] = Wire.read();
    }
}

The sketch
In order to test the the above classes here is a simple sketch. To run the sketch you need the files TEA5767.* (see above), TEA5767HN.* (see above) and, of course, a TEA5767 FM module (see Figure 2 in this post). The sketch initialises the TEA5767HN and then search for a station. If one is found then the module is tuned at this frequency. Pay attention that by default the tuner uses the US/European FM band (87.5-108MHz), if you need the Japanese FM band (76-91MHz), then you should add the following instruction after tea.begin(...);:
tea.setBandLimits(JAPANESE_FM_BAND);

The sketch TEA5767HN-test.ino
/**
 *  \file TEA5767HN-test.ino
 *
 *  \brief A quick example for testing the TEA5767HN chip.
 *
 *  \author Enrico Formenti
 *  \date 27 dec 2014
 *  \version 1.0
 *  \copyright BSD license, check the License page on the blog for more information. All this text must be 
 *  included in any redistribution.
 *  <br><br>
 *  See macduino.blogspot.com for more details.
 */
 
#include "TEA5767HN.h"

TEA5767HN tea;

void setup() {
  Serial.begin(9600);
  
  tea.begin(TEA576X_XTAL_32768Hz, TEA5767HN_I2CBUS);
  
  if(!tea.search(SEARCH_DIR_FORWARD, SEARCH_LEV_MEDIUM)) {
    Serial.print("Couldn't find any station!");
  }
  else {
    Serial.print("Playing station at ");
    Serial.print(tea.getFrequency()/1000000.0);
    Serial.print("MHz");
  }
}

void loop() {
  // nothing to do at present...
}
To run this sketch you need:
  • 1x Arduino Uno (or one of his brothers)
  • 1x TEA5767HN chip
  • 1x louspeaker 4Ω 1/4 Watt (or similar)
  • 7x Dupont connection cables
  • 1x long enough cable for the antenna (more details here)
Figure 1. shows how to connect the material. Remark that the output level of the module is very weak. This is the reason for which one finds many modules that adds to TEA5767HN an amplification stage, like the one that we will see in the next post.


Figure 1. Basic connections for the TEA5767HN module.



What's next
As promised in the abstract we will provide a class for dealing with the FM module and finally an application example building a simple FM radio player front-end.

See also
FM Radio receiver (TEA5767HL-TEA5767HN-TEA5768HL) - Part 1
FM Radio receiver (TEA5767HL-TEA5767HN-TEA5768HL) - Part 3
FM Radio receiver (TEA5767HL-TEA5767HN-TEA5768HL) - Part 4

Wednesday, December 24, 2014

Tone music: changing the Tempo of your melodies





Abstract
In our past programs for playing tone music on Arduino (see the basic program here and its advanced version here) are based on a fixed Tempo which is about 90 crotchets per minute. In this article we give a simple routine which allows to change the Tempo. We also provide some basic conversion constants for the main Tempos.

Hey all! While transcribing some music sheet (game music) I've seen that the tempo was somewhat strange and it wasn't due only to the deformation of my poor loudspeaker. Indeed, our past sketches for playing tone music on Arduino (see the basic program here and its advanced version here) are based on a fixed Tempo which is approx 90 crotchets per minute. This is the same for all other sketches that I could find on the web.
Therefore, here is a simple sketch function which changes the Tempo in your melody.

The sketch
The code below contain just one function. Call it with your own tempo value or choose one constant among those provided in the next section. The formula to compute the transformation takes into account the pause that we put between a note and the following which was useful to distinguish the notes (this was set to 130% of the note duration in our previous programs). Whenever the duration is not standard (in the case of an augmentation for example), a simple approximation formula is used.

Warning: some older version of melodies that you can find over the net use const int noteDurations[] as data type. Of course, you should change this into uint16_t noteDurations[] to be able to use the setTempo() routine.


#include "durations.h"

#define INTERNOTE_PAUSE 1.3

void setTempo(uint16_t durs[], uint16_t tempo, uint16_t istart, uint16_t iend) {
  register uint16_t i;
  uint16_t base;
  
  base = (uint16_t)(1000.0/((tempo/60.0)*(1+INTERNOTE_PAUSE)));
  
  for(i=istart; i<iend; i++) {
    switch(durs[i]) {
      case DUR_SEMIBREVE: 
        durs[i] = base << 2;
        break;
      case DUR_MINIM: 
        durs[i] = base << 1;
        break;
      case DUR_CROTCHET: 
        durs[i] = base;
        break;
      case DUR_QUAVER:
        durs[i] = base >> 1;
        break;
      case DUR_SEMIQUAVER:
        durs[i] = base >> 2;
        break;
      case DUR_DEMISEMIQUAVER:
        durs[i] = base >> 3;
        break;
      case DUR_HEMIDEMISEMIQUAVER:
        durs[i] = base >> 4;
        break;
      default:
        durs[i] = (uint16_t)(durs[i]/(DUR_CROTCHET*1.0)*base);
        break;      
    }
  }
}

The tempos
In most of the music sheets, the tempo is indicated a phrase or a word (usually in Italian) and the interpretation of such words/phrases is often a matter of taste or of long discussions. Along with the previous sketch, below you can find Tempos.h: my personal interpretation of most known tempos.


/*
 *  Tempos.h
 *
 *  This is part of PlayMelodyAdv projet
 *  A more advanced program for playing melodies on Arduino.
 *
 *
 *  Written by Enrico Formenti, 22 dec 2014
 *
 *  BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *
 *  See macduino.blogspot.com for more details.
 */

#ifndef _Tempos_h
#define _Tempos_h

#define TEMPO_LARGHISSIMO 24
#define TEMPO_GRAVE 32
#define TEMPO_LENTISSIMO 40
#define TEMPO_LENTO 46
#define TEMPO_LARGO 50
#define TEMPO_ADAGISSIMO 52
#define TEMPO_LARGHETTO 56
#define TEMPO_LENTO 60
#define TEMPO_ADAGIO 70
#define TEMPO_ADAGIETTO 76
#define TEMPO_ANDANTE 88
#define TEMPO_MODERATO 100
#define TEMPO_ALLEGRETTO 116
#define TEMPO_ALLEGRO 130
#define TEMPO_VIVACE 140
#define TEMPO_VIVACISSIMO 152
#define TEMPO_ALLEGRISSIMO 160
#define TEMPO_ALLEGRO_VIVACE 160
#define TEMPO_PRESTO 170
#define TEMPO_PRESTISSIMO 188

#endif

See also
Tone music surprises!
Tone music: advanced playing software
Tone music: how to encode songs

Enjoy! Credits
The image opening this post comes from Wikipedia.com

Monday, December 22, 2014

Tone music: advanced playing software




Abstract
In this post we are going to present a more sophisticated program for playing melodies on your Arduino. It allows you to encode repetitions and alternate endings, compacting your longer melodies.
Keywords: tone music; pauses; augmentations; ties; repetitions.

The new playing routine
The new play function implements more sophisticated management of melodies allowing pauses, ties, augmentations (like the past routine) and it also introduces the possibility to use repetitions and alternate endings. This post explains how to encode all this.

The sketch with the new routine is given below. Remark that it makes use of a support class that implements a simple stack. Source files can found here: Stack.h, Stack.cpp. In order to be able to compile the sketch you should open this two files in other tabs of your Arduino IDE. You also need instructions.h which contains the encoding for the new instructions used to encode the melodies.

Compatibility
All the songs encoded for the previous version of the playing routine still work for this new version without any modification. Indeed, the new melody encoding is an extension of the older one.

See also
Tone music surprises!
Tone music: how to encode songs
Tone music: changing the Tempo of your melodies

Enjoy!

/*
 *  PlayMelodyAdv
 *
 *  A more advanced program for playing melodies on Arduino. 
 *
 *  Define the label DEBUG to have some debug support
 *
 *  Written by Enrico Formenti, 22 dec 2014
 *
 *  BSD license, check the License page on the blog for more information
 *  All this text must be included in any redistribution.
 *
 *  See macduino.blogspot.com for more details.
 */

#include "pitches.h"
#include "durations.h"
#include "instructions.h"
#include "Stack.h"
#include "Stack.cpp"
#include "SilentNight.h"
 
#define TONEPIN 8

typedef struct {
  struct {
  uint16_t N;  // position in melody array
  uint16_t D;  // position in durations array
  } I;         // individual addressing
  uint32_t A;  // addressing all together
} POS;

void playMusic( uint16_t *instr, uint16_t *durs, uint16_t len) {

  POS coda;      // address of coda symbol
  POS segno;     // address of segno symbol
  POS invRepeat; // position of inv repeat sign
  POS nskip;     // posistion of the first note to skip
  POS fine;      // end of music symbol position
  POS askip;     // position of the first note to skip in alternate ending
  POS curPos; 

  // reset all internal variables
  coda.A = 0;
  segno.A = 0;
  invRepeat.A = 0;
  nskip.A = 0;
  fine.A = 0;
  askip.A = 0;
  curPos.A = 0;
  
  // start looping
  while(curPos.I.N < len) {
    Stack<POS> reps; // make the stack local so it is emptied when the loop 
                     // is over

    switch(instr[curPos.I.N]) {
      case NOTE_PAUSE:
        // noTone(TONEPIN);
        delay(durs[curPos.I.D]);
        curPos.A += 0x11;
        break;
      case NOTE_CODA:
        if(nskip.A) {
          curPos.A = nskip.A;
          nskip.A = 0;
          coda.A = 0;
          break;
        }
        coda.A = curPos.A+0x10; // start from next position
        (curPos.I.N)++;
        break;
      case NOTE_DACAPO:
        if(reps.isEmpty() || (reps.topElement().A!=curPos.A)) { // if this event has not already occurred
          reps.push(curPos); // add this event
          curPos.A=0;  // repeat from the beginning
          break;
        }
        // otherwise we simply skip and update the instruction pointer
        reps.pop();
        (curPos.I.N)++;
        break;
      case NOTE_SEGNO:
        segno.A=curPos.A+0x10; // start from next position in note array
        (curPos.I.N)++;        
        break;
      case NOTE_REPEAT:
        if(reps.isEmpty() || (reps.topElement().A != curPos.A)) {
          if(invRepeat.A) { // repeat from last inv repeat sign if any
            curPos.A=invRepeat.A+0x11; // add +1 to both N and D pointers
            invRepeat.A=0;
            reps.push(curPos);// push the event on the stack
            break;
          }
          // otherwise repeat from the beginning
          reps.push(curPos);// push the event on the stack
          curPos.A=0;
          break;
        }
        // if this is the sign that issued the event
        reps.pop();
        (curPos.I.N)++;
        break;
      case NOTE_INVREPEAT:
        invRepeat.A=curPos.A+0x10; // start from the next position in notes array
        (curPos.I.N)++;
        break;
      case NOTE_DALSEGNO:
        if(reps.isEmpty() || (reps.topElement().A!=curPos.A)) { // if this has not generated the event
          reps.push(curPos);
          curPos.A=segno.A;
          segno.A=0;
          break;
        }
        // otherwise skip and update N only
        reps.pop();
        segno.A=0;
        (curPos.I.N)++;
        break;
      case NOTE_DALSEGNOCODA:
        if(reps.isEmpty() || (reps.topElement().A!=curPos.A)) {
          reps.push(curPos);
          curPos.A = segno.A;
          segno.A = 0;
          nskip.A = coda.A+0x10;
          break;
        }
        // otherwise skip and update N only
        reps.pop();
        (curPos.I.N)++;
        break;
        case NOTE_DACAPOCODA:
        if(reps.isEmpty() || (reps.topElement().A!=curPos.A)) {
          reps.push(curPos);
          curPos.A = 0;
          segno.A = 0;
          nskip.A = coda.A+0x10;
          break;
        }
        // otherwise skip and update N only
        reps.pop();
        (curPos.I.N)++;
        break;
      case NOTE_FINE:
        if(fine.A) { // we already passed through the music end symbol
          curPos.I.N = len; // then stop playing
          break;
        }
        fine.A = curPos.A;
        (curPos.I.N)++;
        break;
      case NOTE_DACAPOFINE:
        curPos.A = 0;
        break;
      case NOTE_DALSEGNOFINE:
        curPos.A = segno.A;
        break;
      case NOTE_ALTBEGIN:
        if(askip.A) { // we are repeating the sequence, hence skip
          curPos.A = askip.A;
          askip.A = 0;
          break;
        }
        // not repeating so just keep playing
        (curPos.I.N)++;
        break;
      case NOTE_ALTEND:
        askip.A = curPos.A+0x10; // set the skip to the next instruction
                                 // so that it will be skipped during the
                                 // repetition
        break;   
      default: // it is a note instruction
        tone(TONEPIN, instr[curPos.I.N], durs[curPos.I.D]);
        // to distinguish the notes, set a minimum time between them.
        // the note's duration + 30% seems to work well:
        delay(durs[curPos.I.D] * 1.3);
        // stop the tone playing:
        noTone(TONEPIN);
        curPos.A += 0x11; // update both N and D pointers
        break;
    }
  }
}

void setup() {
  
#ifdef DEBUG
  Serial.begin();
#endif
  
  playMusic((uint16_t *)melody,(uint16_t *)noteDurations,(uint16_t)melody_len);  
}

void loop() {
  // no need to repeat the melody.
}

Tone music: how to encode songs





Abstract
In this article we explain how to encode tone music for your Arduino projects. In particular, we explain how to encode pauses, ties, repetitions, etc. This new encoding extends the one we have proposed in a past post. The main advantage is that it can considerably shorten melodies physical description and hence save memory space.
Keywords: tone music; pauses; augmentations; ties; repetitions.

Which music sheets to use?
It is not clear which sheets translate better into tone music. I prefer to use easy piano music sheets, or simply start from scratch by trials and errors.

Basic encoding
Encoding a music sheet essentially consists in defining the following three objects:
uint16_t instr_len:this is the length of the array melody. Remark that the size of a melody is limited by the size of int. This is not a true limitation since this is far beyond the memory capabilities of Arduino Uno.
uint16_t instr[]:array containing the instructions for playing the melody
uint16_t durs[]:array containing the instructions for the duration of the current note or of the current pause.

Thursday, December 18, 2014

FM radio receiver for your Arduino (TEA5767/TEA5768/TEA5757)
(Part 1/4)




Abstract

In this post we are going to play with an FM Radio module based on TEA5767 chip (for TEA5768 the only difference is at the bus level, we will made this precise when writing the source code).The module is essentially based on the TEA5767 to which is adds a small stereo amplifier and a connector for headphones. Indeed, the output level of TEA5767 is very weak and one needs an amplifier to make a serious use out of it. As usual we will explain both hardware and software aspects. However, since the article is pretty long, we split it into two parts. In this first part, we look more closely at the hardware aspects. The second part will provide some useful functions and it will be assorted of interesting application examples. In the examples, we use the usual LCD module based on the classical 1602 LCD screen which accompanies many Arduino experiments.



Table of contents (part 1)


Warning: Click on the "more" button below to be able to fully exploit the links in the list above.

The FM stereo module

The module is represented in Figure 1. Indeed, it is essentially a "decoration" for the TEA5767 module which can be seen in the central part of the picture. Figure 2 zooms on the TEA5767 module.

Figure 1. The FM stereo module for Arduino.



Figure 2. TEA5767 module.

TEA5767 vs. TEA5768

Essentially TEA5767 and TEA5768 differ for the set of communication protocols that they support and/or the packaging; all other characteristics are identical. There are three models:
  • TEA5767HN: FM stereo radio, 40 leads with I2C and 3-Wire bus. Body 6*6*0.85 mm, SOT1618 package.
  • TEA5767HL: FM stereo radio, 32 leads with 3-Wire bus. Body: 7*7*1.4 mm, SOT358 package.
  • TEA5768HL: FM stereo radio, 32 leads with I2C bus. Body: 7*7*1.4 mm, SOT358 package.
In the second part of this article, we will specialize the read/write function according to the model used.

Datasheets

TEA5767HNRevision 2007.
TEA5767HNRevision 2003.
TEA5767HLRevision 2004.
TEA5768HLRevision 2008 (indeed identical to rev. 2003).
TEA5768HLRevision 2003.
AN10133Application note for TEA5767/TEA5768.
TEA576XBrochure.

The pin out

The pins are pretty well signalled on the module and should be connect to your Arduino as follows


ModuleUnoMegaLeonardoDue
SDAA420220 or SDA1
SCLA521321 or SCL1
GNDGNDGNDGNDGND
Vcc+5V+5V+5V+5V
ANTAntenna, see the dedicated section.

The antenna

If you don't have an antenna then you can easily build one by yourself. For example, in my experiments I've just used a 30cm long cable with female Dupont endpoints. Of course, this is not very efficient. Better results can be obtained with cables of length proportional to the length of the FM wave. Usually they use 1/4 or 1/2 of the length of the 100MHz wave that is 713mm or 1416mm, respectively. For even better reception one can build a dipole antenna, many instructions for that can be found over the internet, for example here.

Sunday, December 14, 2014

Tone music surprises






Hey all! It's almost Christmas and time for the traditional carols. I've found a 8Ω loudspeaker from an old PC and I went through a classic Arduino Sketch for beginners. I've optimized it a little bit. Moreover, I've translated into French/Italian the notes and introduced standardized length for durations and the possibility to add pauses.

Friday, December 5, 2014

LCD : static driving




Abstract
The static driving technique is the basic driving of a LCD which has the advantage of needing fewer external support but needs lots of pins for the segments of the LCD and hence allows less dense design.

The idea
For each digit, each segment is directly connected to a pin. In order to save some pins, all the other electrodes of each segment is linked together into a common pin.

The example
Consider an LCD with two digits. It is composed of a front plane and a back plane. In the front pane, each segment of a digit is connected to a distinct pin as illustrated in Figure 1, remark the density of connections. In the back pane all the electrodes of all the digits are connected each other and finally to a common (com) pin as illustrated in Figure 2. Therefore, if we count pins, there are 8 pins per digit in the front pane, plus one pin for the back plane. Summing up with a formula, the number of pins is 8N+1, where N is the number of digits in the display.

Figure 1. Front pane for two-digits LCD with static driving.

Figure 2. Back pane for two-digits LCD with static driving.

Frame frequency and bias

LCD are AC devices and hence one must specify the AC frequency used. Frame frequency ranges between 20Hz and 200Hz. Below 20Hz, one might experience the refreshes of the LCD (recall that human eye can distinguish frames up to 18 frames/second). A frequency higher than 200Hz might cause problems with the capacitive elements of the LCD.

The bias is the number of voltage levels that are used. Indeed, in static driving only two levels are used, say V0 and V1. As an example, consider a given segment SEG. In oder to deduce the waveforms passing through the backpane COM and SEG, let us impose that VCOM - VSEG = 0 whenever SEG is unselected (see Figure 3). Since we should switch of value during the frame and there are only two possible values, then the waveform of SEG signal when SEG is selected, it is the complement of the signal unselected signal. As a consequence, when SEG is selected, the COM-SEG signal has a peak-to-peak amplitude equal to 2V1. See Figure 4.

Figure 3. Waveforms when SEG is unselected.


Figure 4. Waveforms when SEG is selected.

See also
LCD : the multiplexing technique