0
\$\begingroup\$

Bought some "music speaker" thingies, some with bluetooth and some without. They are cheap, for sure, about 3 or 4 euro's. With some capacitor tweaks, they seem to be very plausibel to use (why is the output on these cheap things always tiny and limited?).

On these devices they use a very tiny, nice and bright display, with 7 legs, charlieplexed I suppose (wiggle it to see any screen update), 35 segments. Cannot read the number on the used chip (it's from JL), very hard to recognize (even when using a microscope) and the display doesn't have any partnumber on it either, however, these seem to be identical except the face plate on these components.

The displays are very interesting, just 7 pins to do the display job, in just one package. I want to buy these things (cannot find it, doesn't know the name and cannot find a datasheet either).

Next thing I want to do is to interface with these devices by reading the display (with a MCU for example) so I am able to read the state of the device and what it is doing. This is a difficult task without any datasheet.

Does somebody know the name of this component, is there a datasheet available somewhere?

Photo gallery of the display:

Display1

Display2

Display3

Display4

Product picture:

Product

\$\endgroup\$
  • 2
    \$\begingroup\$ With 35 segments, I'm betting there's an MM5450in that lump of potting compound somewhere, which makes it a serial interface and power/gnd, not charlieplexing. Datasheets should be easy to find - then you need to measure signals on the interface to discover the pinout. \$\endgroup\$ – Brian Drummond Aug 1 '17 at 8:35
  • \$\begingroup\$ Thanks for the comment. Nope, it is charlieplexed, see also my posted answer. \$\endgroup\$ – Codebeat Aug 9 '17 at 0:31
1
\$\begingroup\$

Sorry for the late reply but there isn't any answer posted.

Yup, it is charlieplexed for sure because I figure it out by placing one display unit on a breadboard and test all individual pins one by one with a buttoncell. Wrote down the results into a table and test the table with an Arduino Nano. Excellent! Seems to work perfectly.

Some photo's:

Testing on breadboard with button cell

Testing table on breadboard with an Arduino Nano

Testing table on breadboard with an Arduino Nano]

To test I connected D2..D8 with pin #1.. pin #7, very straight forward, easy to do. Didn't solder headers, made some jumpers instead because I want to use this Nano for another project. Works great.

The code I wrote to test it (so you can try it yourself):

#define F_CPU 16000000UL         // Set cpu speed to calculate right delay
#include <util/delay.h>

 // includes
//#include "Timer.h"


/*

 35 segment display:
  ____________________________
 |                            |
 | |>  USB                 FM |
 |           8 8 : 8 8        |
 | ||  SD                 MP3 |
 |____________________________|
      |  |  |  |  |  |  |
      0  1  2  3  4  5  6
      1  2  3  4  5  6  7


     Bits:                 Hex:
        -- 0 --               -- 01 --
       |       |             |        |
       5       1            20        02
       |       |             |        |
        -- 6 --               -- 40 --
       |       |             |        |
       4       2            10        04
       |       |             |        |
        -- 3 --               -- 08 --   
*/

 #define PIN_PLUS  0x01
 #define PIN_MIN   0x00
 #define PIN_OFF   0xFF

 #define PIN_HIGH  HIGH
 #define PIN_LOW   LOW

 #define PIN_ONBOARDLED_OUT      13

 #define SCP_LEDS_OFF_DISABLED   255
 #define SCP_LEDS_RESET          -2
 #define SCP_LEDS_SHOW_ENABLED   -1

 #define CP_MAX_LED 35
 #define CP_CNT_LED 35
 #define CP_MAX_PIN 7
 #define CP_CNT_PIN 7

#define XTM_NOPROGMEM


#if defined(XTM_NOPROGMEM) || !defined(PROGMEM) || !defined(pgm_read_byte)
 #pragma message("Compiling file: PROGMEM off, data tables in memory")
 #ifndef XTM_NOPROGMEM
   #define XTM_NOPROGMEM
 #endif
 #define XTM_MEM_ALLOC_TYPE       static
 #define XTM_GET_DIGIT(x)         XTM_DIGITS[x]
 #define XTM_GET_LEDPIN(x)        CP_LED_PIN[x]
 #define XTM_GET_LEDPIN_CFG(x,y)  CP_LED_PINS_CFG[x,y]
#else
  #define XTM_MEM_ALLOC_TYPE      PROGMEM
  #define XTM_GET_DIGIT(x)        pgm_read_byte( &XTM_DIGITS[x] )
  #define XTM_GET_LEDPIN(x)       pgm_read_byte( &CP_LED_PIN[x] )
  #define XTM_GET_LEDPIN_CFG(x,y) pgm_read_byte( &CP_LED_PINS_CFG[x,y] )
#endif


XTM_MEM_ALLOC_TYPE const uint8_t CP_LED_PINS[CP_MAX_PIN] = { 2, 3, 4, 5, 6, 7, 8 }; /* Digital PWM PINS only */

static bool    bLedDirSwap = false; 
                             //true;
XTM_MEM_ALLOC_TYPE const uint8_t CP_LED_PINS_CFG[CP_MAX_LED][CP_MAX_PIN] = 
{
  /* LED name:       ->      1          2           3          4           5          6          7            
                             |          |           |          |           |          |          |    
                                 +                                                                       Base: 1000000 */  
  /* 01. FIRST_SEG_0    */ { PIN_PLUS , PIN_MIN  ,  PIN_OFF ,  PIN_OFF   , PIN_OFF  , PIN_OFF ,  PIN_OFF }, /* 1100000 */
  /* 02. FIRST_SEG_2    */ { PIN_PLUS , PIN_OFF  ,  PIN_MIN ,  PIN_OFF   , PIN_OFF  , PIN_OFF ,  PIN_OFF }, /* 1010000 */
  /* 03. FIRST_SEG_4    */ { PIN_PLUS , PIN_OFF  ,  PIN_OFF ,  PIN_MIN   , PIN_OFF  , PIN_OFF ,  PIN_OFF }, /* 1001000 */
  /* 04. SD             */ { PIN_PLUS , PIN_OFF  ,  PIN_OFF ,  PIN_OFF   , PIN_MIN  , PIN_OFF ,  PIN_OFF }, /* 1000100 */
  /* 05. PLAY           */ { PIN_PLUS , PIN_OFF  ,  PIN_OFF ,  PIN_OFF   , PIN_OFF  , PIN_MIN ,  PIN_OFF }, /* 1010010 */

                                      /*   +    */                                                    /* Base: 0100000 */ 
  /* 06. FIRST_SEG_5    */ { PIN_MIN  , PIN_PLUS ,  PIN_OFF ,  PIN_OFF  , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 1100000 */
  /* 07. SECOND_SEG_0   */ { PIN_OFF  , PIN_PLUS ,  PIN_MIN ,  PIN_OFF  , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 0110000 */
  /* 08. SECOND_SEG_2   */ { PIN_OFF  , PIN_PLUS ,  PIN_OFF ,  PIN_MIN  , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 0101000 */
  /* 09. SECOND_SEG_4   */ { PIN_OFF  , PIN_PLUS ,  PIN_OFF ,  PIN_OFF  , PIN_MIN  , PIN_OFF  ,  PIN_OFF }, /* 0100100 */
  /* 10. SECOND_SEG_3   */ { PIN_OFF  , PIN_PLUS ,  PIN_OFF ,  PIN_OFF  , PIN_OFF  , PIN_MIN  ,  PIN_OFF }, /* 0100010 */

                                                  /*   +    */                                        /* Base: 0010000 */     
  /* 11. FIRST_SEG_6    */ { PIN_MIN  , PIN_OFF  ,  PIN_PLUS,  PIN_OFF  , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 1010000 */
  /* 12. SECOND_SEG_5   */ { PIN_OFF  , PIN_MIN  ,  PIN_PLUS,  PIN_OFF  , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 0110000 */
  /* 13. COLON :        */ { PIN_OFF  , PIN_OFF  ,  PIN_PLUS,  PIN_MIN  , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 0011000 */
  /* 14. THIRD_SEG_1    */ { PIN_OFF  , PIN_OFF  ,  PIN_PLUS,  PIN_OFF  , PIN_MIN  , PIN_OFF  ,  PIN_OFF }, /* 0010100 */
  /* 15. PAUSE          */ { PIN_OFF  , PIN_OFF  ,  PIN_PLUS,  PIN_OFF  , PIN_OFF  , PIN_MIN  ,  PIN_OFF }, /* 0010010 */
  /* 16. MP3            */ { PIN_OFF  , PIN_OFF  ,  PIN_PLUS,  PIN_OFF  , PIN_OFF  , PIN_OFF  ,  PIN_MIN }, /* 0010001 */

                                                              /*   +    */                           /* Base: 0001000 */
  /* 17. FIRST_SEG_2    */ { PIN_MIN  , PIN_OFF  ,  PIN_OFF ,  PIN_PLUS , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 1001000 */
  /* 18. SECOND_SEG_6   */ { PIN_OFF  , PIN_MIN  ,  PIN_OFF ,  PIN_PLUS , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 0101000 */
  /* 19. THIRD_SEG_5    */ { PIN_OFF  , PIN_OFF  ,  PIN_MIN ,  PIN_PLUS , PIN_OFF  , PIN_OFF  ,  PIN_OFF }, /* 0011000 */
  /* 20. THRID_SEG_2    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_PLUS , PIN_MIN  , PIN_OFF  ,  PIN_OFF }, /* 0001100 */
  /* 21. FIFTH_SEG_4    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_PLUS , PIN_OFF  , PIN_MIN  ,  PIN_OFF }, /* 0001010 */

                                                                         /*   +    */                 /* Base: 0000100 */   
  /* 22. FIRST_SEG_3    */ { PIN_MIN  , PIN_OFF  ,  PIN_OFF ,  PIN_OFF  , PIN_PLUS , PIN_OFF  ,  PIN_OFF }, /* 1000100 */
  /* 23. SECOND_SEG_2   */ { PIN_OFF  , PIN_MIN  ,  PIN_OFF ,  PIN_OFF  , PIN_PLUS , PIN_OFF  ,  PIN_OFF }, /* 0100100 */
  /* 24. THIRD_SEG_6    */ { PIN_OFF  , PIN_OFF  ,  PIN_MIN ,  PIN_OFF  , PIN_PLUS , PIN_OFF  ,  PIN_OFF }, /* 0010100 */
  /* 25. THIRD_SEG_0    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_MIN  , PIN_PLUS , PIN_OFF  ,  PIN_OFF }, /* 0001100 */
  /* 26. FIFTH_SEG_2    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_OFF  , PIN_PLUS , PIN_MIN  ,  PIN_OFF }, /* 0000110 */
  /* 27. FIFTH_SEG_6    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_OFF  , PIN_PLUS , PIN_OFF  ,  PIN_MIN }, /* 0000101 */

                                                                                   /*   +    */       /* Base: 0000010 */
  /* 28. THIRD_SEG_3    */ { PIN_MIN  , PIN_OFF  ,  PIN_OFF ,  PIN_OFF  , PIN_OFF  , PIN_PLUS ,  PIN_OFF }, /* 1000010 */
  /* 29. USB            */ { PIN_OFF  , PIN_MIN  ,  PIN_OFF ,  PIN_OFF  , PIN_OFF  , PIN_PLUS ,  PIN_OFF }, /* 0100010 */
  /* 30. THIRD_SEG_4    */ { PIN_OFF  , PIN_OFF  ,  PIN_MIN ,  PIN_OFF  , PIN_OFF  , PIN_PLUS ,  PIN_OFF }, /* 0010010 */
  /* 31. FIFTH_SEG_3    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_MIN  , PIN_OFF  , PIN_PLUS ,  PIN_OFF }, /* 0001010 */
  /* 32. FIFTH_SEG_5    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_OFF  , PIN_MIN  , PIN_PLUS ,  PIN_OFF }, /* 0000110 */
  /* 33. FIFTH_SEG_1    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_OFF  , PIN_OFF  , PIN_PLUS ,  PIN_MIN }, /* 0000011 */

                                                                                               /*   +    Base: 0000001 */
  /* 34. FM             */ { PIN_OFF  , PIN_OFF  ,  PIN_MIN ,  PIN_OFF  , PIN_OFF  , PIN_OFF  ,  PIN_PLUS },/* 0010001 */
  /* 35. FIFTH_SEG_0    */ { PIN_OFF  , PIN_OFF  ,  PIN_OFF ,  PIN_OFF  , PIN_OFF  , PIN_MIN  ,  PIN_PLUS } /* 0000011 */
};

#define XTM_CHAR_ERR            0x49

 // Special characters
#define XTM_MINUS               0x40
#define XTM_PLUS                0x44
#define XTM_BLANK               0x00
#define XTM_DEGREES             0x63
#define XTM_UNDERSCORE          0x08
#define XTM_EQUALS              0x48
#define XTM_LEFT                0x70
#define XTM_RIGHT               0x46
#define XTM_BRACKET_LEFT        0x39
#define XTM_BRACKET_RIGHT       0x0F
#define XTM_GREATER_LEFT        0x46
#define XTM_GREATER_RIGHT       0x70
#define XTM_ACCOLADE_LEFT       XTM_GREATER_LEFT
#define XTM_ACCOLADE_RIGHT      XTM_GREATER_RIGHT
#define XTM_COLON               0x09
#define XTM_PARENTHESIS_LEFT    XTM_BRACKET_LEFT
#define XTM_PARENTHESIS_RIGHT   XTM_BRACKET_RIGHT
#define XTM_QUESTION_MARK       0x53+0x80

#define XTM_SPECIAL_CHAR_OFFSET 0x24


 // Font table:
XTM_MEM_ALLOC_TYPE const uint8_t XTM_DIGITS[] =
{
//  Numbers
//     0     1     2     3     4     5     6     7     8     9
    0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,            //(10)

//  Hex
//     A     B     C     D     E     F
    0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71,                                    //(06)

//  Letters ( * = same as H )
//     G     H     I     J    *K     L     M     n     O     P     Q     r
    0x3D, 0x76, 0x06, 0x1F, 0x76, 0x38, 0x15, 0x54, 0x3F, 0x73, 0x67, 0x50,//(12)

//     S     t     U      V    W    *X     Y     Z
    0x6D, 0x78, 0x1C,  0x3E, 0x2A, 0x76, 0x6E, 0x5B,                        //(08)

// Special chars, offset = 0x24 (36)
   (uint8_t)'-', XTM_MINUS,
   (uint8_t)'+', XTM_PLUS,
   (uint8_t)' ', XTM_BLANK,
   (uint8_t)'^', XTM_DEGREES,
   (uint8_t)'_', XTM_UNDERSCORE,
   (uint8_t)'=', XTM_EQUALS,
   (uint8_t)'[', XTM_BRACKET_LEFT,
   (uint8_t)']', XTM_BRACKET_RIGHT,
   (uint8_t)'<', XTM_GREATER_LEFT,
   (uint8_t)'>', XTM_GREATER_RIGHT,
   (uint8_t)'{', XTM_ACCOLADE_LEFT,
   (uint8_t)'}', XTM_ACCOLADE_RIGHT,
   (uint8_t)':', XTM_COLON,
   (uint8_t)'(', XTM_PARENTHESIS_LEFT,
   (uint8_t)')', XTM_PARENTHESIS_RIGHT,
   (uint8_t)'?', XTM_QUESTION_MARK,
   0x00
};



void __setCharlieLed( uint8_t iLed )
{
  bool bOffDisable = ( iLed == SCP_LEDS_OFF_DISABLED );
  if( !bOffDisable && iLed >= CP_CNT_LED )
   { return; }   

  uint8_t iPin = CP_CNT_PIN;
  while( iPin-- )
  {
     if( bOffDisable || CP_LED_PINS_CFG[iLed][iPin] == PIN_OFF )
      {  
         digitalWrite( CP_LED_PINS[iPin], PIN_LOW ); 
         //pinMode( CP_LED_PINS[iPin], INPUT_PULLUP );
         pinMode( CP_LED_PINS[iPin], INPUT );
         //analogWrite( CP_LED_PINS[iPin], HIGH ); 
      }
     else {
            pinMode( CP_LED_PINS[iPin], OUTPUT );
            digitalWrite( CP_LED_PINS[iPin], (CP_LED_PINS_CFG[iLed][iPin] == PIN_PLUS)?PIN_HIGH:PIN_LOW );
          }
  }
}

void setCharlieLed( uint8_t iLed, bool bDirSwap = false )
{
  if( bDirSwap )
   { bDirSwap=!bLedDirSwap; }
  else { bDirSwap = bLedDirSwap; }  
  __setCharlieLed( bDirSwap?CP_CNT_LED-1-iLed:iLed ); 
}

void setAllLedsOffDisabled()
{
  __setCharlieLed( SCP_LEDS_OFF_DISABLED ); 
}

void setAllLedsOnEnabled() // this might not be working with all kind of leds
{
  uint8_t iPin = CP_CNT_PIN;
  while( iPin-- )
   { __setCharlieLed( iPin ); } 
}

void setLedEnabled( int iLed = SCP_LEDS_SHOW_ENABLED, bool bEnable = true, bool bReverse = false ) // must be called in a loop sequence to be functional
{
   static bool    aleEnabledLeds[CP_CNT_LED]; 
   static bool    bleInitLedArray = true;
   static uint8_t ileCurrentLed   = 0; 
   static uint8_t ileEnabledLeds  = 0;

    // To be sure memory locations are init with false or init with false when reset requested (< -1)
   if( bleInitLedArray || iLed <= SCP_LEDS_RESET )
   {
     bleInitLedArray = false;
     uint8_t i = CP_CNT_LED;
     while( i-- )
      { aleEnabledLeds[i] = false; }

     ileEnabledLeds = 0;
   }

  if( iLed >= 0 && iLed < CP_CNT_LED && aleEnabledLeds[iLed] != bEnable )
  { 
     aleEnabledLeds[iLed] = bEnable; 
     ileEnabledLeds+=bEnable?1:-1;

     //if( bEnable )
     // { ileCurrentLed = iLed; }
  }

  if( ileEnabledLeds > 0 || bReverse )
  {
   if( (!bReverse && aleEnabledLeds[ileCurrentLed]) || (bReverse && !aleEnabledLeds[ileCurrentLed]) )
    { setCharlieLed( ileCurrentLed ); }

    ++ileCurrentLed;
    if( ileCurrentLed >= CP_CNT_LED )
     { ileCurrentLed = 0; }
  } 
  else { setAllLedsOffDisabled(); }
}

void showCharlieLedsEnabled( bool bReverse = false )
{ setLedEnabled( SCP_LEDS_SHOW_ENABLED, false, bReverse ); }

void resetCharlieLedsEnabled()
{ setLedEnabled( SCP_LEDS_RESET ); }


void set1MhzClockSpeed()
{
 noInterrupts();
 CLKPR = 1 << CLKPCE;
 CLKPR = 0b00000100; // prescaler 16
}

void setup() 
{
  //set1MhzClockSpeed();
}

void loop() 
{
   static uint8_t i = 0;
   //static TTimer  tprgTimer = TTimer( 1000, (bool)true, (bool)false );  
   //if( tprgTimer.isTime() )
   { 
     setLedEnabled( i );
     ++i; 
     if( i >= CP_CNT_LED )
      { 
        i = 0; 
        //setAllLedsOffDisabled();
      }
   }

}

Notice:

  • The code above is just a quick example (need some work), just to figure out how the display works. The table however, it explain how the display is organized but is not the most efficient way to do it, still usable though.
  • I don't understand the way it is organized, it a little messy when you look at the order or placement of 'groups'.
  • You can display LED's at the same time when they are in the same 'group' but makes it more complex to manage and requires more power. The cheap china sound module doesn't do this either, display individual segments one by one and it operates at a lower update frequency comparing to the Nano (wiggle it to see the difference between both).
  • There is a font table in the example above, a mission I want to do, not working in this example. PROGMEM also needs some work.
  • I didn't use resistors because it is charlieplexed and just one led at a time is on at one cycle. Don't expect issue's with this.

The next thing to do / figure out:

Like I explained in the question earlier, I want to communicate with the module by reading the display. I think it is possible by knowing how the display works. Perhaps it need some more work to achieve this but doesn't seem impossible.

For now, I qualify this post as an answer.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.