Jump to content
43oh

maelli01

Members
  • Content Count

    48
  • Joined

  • Last visited

  • Days Won

    16

Reputation Activity

  1. Like
    maelli01 got a reaction from greeeg in Tiny Chip-on-glass LCD with ST7565 controller   
    Connected one of those
     
    http://www.newhavendisplay.com/lcd-chiponglass-128-x-32-c-3_113.html
     
    to the launchpad. These are really tiny chip-on-glass LCD displays. The visible area is 8 x 32mm.
     

     
    More tricky than the software is the hardware: in order to work, I had to connect nine 1uF ceramic caps
    to the display (I guess that with the chip-on-glass display it is not possible to integrate the caps into he display).
     
    Made a small,hand etched, one sided PCB, to accomodate the caps and to change from the weird 1.5mm connector
    pitch to a 2.54 one.
     

     
    6502 for size comparison only ;-)
     
    RobG's Nokia software helped me to get the hardware SPI right. Software-SPI, works as well, advantage is the free choice 
    of the pins, but more processor time is wasted for the display.
     
    I measured 85uA, with the example clock program (Display + MSP in LPM3), without backlight. So power-wise this 
    fits perfectly with the MSP. 
    Official working voltage is 2.7-3.3V. The 3.6V of the LP are the maximum rating for the display. 
     
    The backlight is already bright enough for me with 2mA. So switching the backlight on/offwith an extra pin would be easy.
    #include "msp430g2553.h" const unsigned char font5x8[][5] ={ { 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp { 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! { 0x00, 0x07, 0x00, 0x07, 0x00 }, // " { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ { 0x62, 0x64, 0x08, 0x13, 0x23 }, // % { 0x36, 0x49, 0x55, 0x22, 0x50 }, // & { 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) { 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * { 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + { 0x00, 0x00, 0x50, 0x30, 0x00 }, // , { 0x08, 0x08, 0x08, 0x08, 0x08 }, // - { 0x00, 0x60, 0x60, 0x00, 0x00 }, // . { 0x20, 0x10, 0x08, 0x04, 0x02 }, // / { 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 { 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 { 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 { 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 { 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 { 0x00, 0x36, 0x36, 0x00, 0x00 }, // : { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; { 0x08, 0x14, 0x22, 0x41, 0x00 }, // < { 0x14, 0x14, 0x14, 0x14, 0x14 }, // = { 0x00, 0x41, 0x22, 0x14, 0x08 }, // > { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? { 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ { 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C { 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E { 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F { 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H { 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I { 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K { 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M { 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P { 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q { 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T { 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U { 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V { 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z { 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ { 0x04, 0x08, 0x10, 0x20, 0x40 }, // / { 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ { 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a { 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c { 0x38, 0x44, 0x44, 0x48, 0x7F }, // d { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e { 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f { 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g { 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h { 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i { 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j { 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k { 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l { 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m { 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o { 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p { 0x18, 0x24, 0x24, 0x18, 0xFC }, // q { 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s { 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t { 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u { 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v { 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x { 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y { 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z { 0x08, 0x36, 0x41, 0x41, 0x00 }, // { { 0x00, 0x00, 0x7F, 0x00, 0x00 }, // | { 0x41, 0x41, 0x36, 0x08, 0x00 }, // } { 0x02, 0x04, 0x02, 0x01, 0x02 } // ~ }; unsigned char hour=12, min, sec,j; void clearline(unsigned char); void clearall(void); void print( char* s); void gotoXy(unsigned char , unsigned char); void printc(unsigned char r); void sendData(unsigned char data); void sendCmd(unsigned char cmd); //lcd connected to port 0 #define A0 BIT2 #define CS BIT3 #define SCK BIT5 #define SDA BIT7 #define RST BIT6 void main(void) { WDTCTL = WDT_ADLY_1000; // WDT 1sec, ACLK, interval timer IE1 |= WDTIE; // Enable WDT interrupt BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1DIR = 0b11101100; P1REN = 0b00010011; P2REN = 0b00111111; P1SEL |=SCK + SDA; P1SEL2|=SCK + SDA; UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master UCB0CTL1 |= UCSSEL_2; // SMCLK UCB0BR0 |= 0x01; // 1:1 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // clear SW P1OUT &= ~RST; __delay_cycles(1000); P1OUT |= RST; P1OUT &=~A0; P1OUT &=~CS; //Initialize LCD display //see http://www.newhavendisplay.com/specs/NHD-C12832A1Z-FSRGB-FBW-3V.pdf for command set sendCmd(0xA1); //ADC select reverse mode sendCmd(0xA2); // 1/7 bias sendCmd(0x2F); //VC on, VR on, VF on sendCmd(0x21); //resistor ratio 3.5 sendCmd(0x81); //set contrast sendCmd(0x27); //adjust this number to get the best contrast sendCmd(0xAF); //now turn it on! clearall(); gotoXy(0,20); print("MSP430G2553 LCD"); gotoXy(1,35); print("2015-05-22"); while (1){ sec++; if (sec==60){ sec=0; clearline(2); min++; if (min==60){ min=0; hour++; if (hour==24) hour=0; } } gotoXy(3,40); printc((hour/10%10)+48); printc((hour%10)+48); printc(':'); printc((min/10%10)+48); printc((min%10)+48); printc(':'); printc((sec/10%10)+48); printc((sec%10)+48); gotoXy(2,sec); print("Hello World!"); __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/interrupt } } // Watchdog Timer interrupt service routine #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void){ __bic_SR_register_on_exit(CPUOFF); // wake up } void clearall(void){ unsigned char i; for(i = 0; i<4 ; i++) clearline(i); } void clearline(unsigned char line){ unsigned char j; sendCmd(0xB0 | line); //sets page(row) sendCmd(0x10); //sets column address(MSB) to 0 for each page(row) sendCmd(0x04); //sets Column address(LSB) start, for this display 4 for(j=0;j<128;j++) {sendData(0x00);} } void sendData(unsigned char data){ P1OUT |=A0; UCB0TXBUF = data; while(!(IFG2 & UCB0TXIFG)); } void sendCmd(unsigned char cmd){ P1OUT &=~A0; UCB0TXBUF = cmd; while(!(IFG2 & UCB0TXIFG)); } void gotoXy(unsigned char x,unsigned char y){ y+=4; //this display does not show first four lines sendCmd(0xB0|(x & 0x03)); sendCmd(0x10|((y>>4))); sendCmd(0x00|(y & 0x0F)); } void print(char* s){ while(*s) printc(*s++); } void printc(unsigned char r){ unsigned char i; sendData(0); for (i=0;i<5;i++) sendData(font5x8[r-32][i] ); }
  2. Like
    maelli01 got a reaction from bluehash in Tiny Chip-on-glass LCD with ST7565 controller   
    Connected one of those
     
    http://www.newhavendisplay.com/lcd-chiponglass-128-x-32-c-3_113.html
     
    to the launchpad. These are really tiny chip-on-glass LCD displays. The visible area is 8 x 32mm.
     

     
    More tricky than the software is the hardware: in order to work, I had to connect nine 1uF ceramic caps
    to the display (I guess that with the chip-on-glass display it is not possible to integrate the caps into he display).
     
    Made a small,hand etched, one sided PCB, to accomodate the caps and to change from the weird 1.5mm connector
    pitch to a 2.54 one.
     

     
    6502 for size comparison only ;-)
     
    RobG's Nokia software helped me to get the hardware SPI right. Software-SPI, works as well, advantage is the free choice 
    of the pins, but more processor time is wasted for the display.
     
    I measured 85uA, with the example clock program (Display + MSP in LPM3), without backlight. So power-wise this 
    fits perfectly with the MSP. 
    Official working voltage is 2.7-3.3V. The 3.6V of the LP are the maximum rating for the display. 
     
    The backlight is already bright enough for me with 2mA. So switching the backlight on/offwith an extra pin would be easy.
    #include "msp430g2553.h" const unsigned char font5x8[][5] ={ { 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp { 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! { 0x00, 0x07, 0x00, 0x07, 0x00 }, // " { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ { 0x62, 0x64, 0x08, 0x13, 0x23 }, // % { 0x36, 0x49, 0x55, 0x22, 0x50 }, // & { 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) { 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * { 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + { 0x00, 0x00, 0x50, 0x30, 0x00 }, // , { 0x08, 0x08, 0x08, 0x08, 0x08 }, // - { 0x00, 0x60, 0x60, 0x00, 0x00 }, // . { 0x20, 0x10, 0x08, 0x04, 0x02 }, // / { 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 { 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 { 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 { 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 { 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 { 0x00, 0x36, 0x36, 0x00, 0x00 }, // : { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; { 0x08, 0x14, 0x22, 0x41, 0x00 }, // < { 0x14, 0x14, 0x14, 0x14, 0x14 }, // = { 0x00, 0x41, 0x22, 0x14, 0x08 }, // > { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? { 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ { 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C { 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E { 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F { 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H { 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I { 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K { 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M { 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P { 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q { 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T { 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U { 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V { 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z { 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ { 0x04, 0x08, 0x10, 0x20, 0x40 }, // / { 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ { 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a { 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c { 0x38, 0x44, 0x44, 0x48, 0x7F }, // d { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e { 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f { 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g { 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h { 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i { 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j { 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k { 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l { 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m { 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o { 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p { 0x18, 0x24, 0x24, 0x18, 0xFC }, // q { 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s { 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t { 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u { 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v { 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x { 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y { 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z { 0x08, 0x36, 0x41, 0x41, 0x00 }, // { { 0x00, 0x00, 0x7F, 0x00, 0x00 }, // | { 0x41, 0x41, 0x36, 0x08, 0x00 }, // } { 0x02, 0x04, 0x02, 0x01, 0x02 } // ~ }; unsigned char hour=12, min, sec,j; void clearline(unsigned char); void clearall(void); void print( char* s); void gotoXy(unsigned char , unsigned char); void printc(unsigned char r); void sendData(unsigned char data); void sendCmd(unsigned char cmd); //lcd connected to port 0 #define A0 BIT2 #define CS BIT3 #define SCK BIT5 #define SDA BIT7 #define RST BIT6 void main(void) { WDTCTL = WDT_ADLY_1000; // WDT 1sec, ACLK, interval timer IE1 |= WDTIE; // Enable WDT interrupt BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1DIR = 0b11101100; P1REN = 0b00010011; P2REN = 0b00111111; P1SEL |=SCK + SDA; P1SEL2|=SCK + SDA; UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master UCB0CTL1 |= UCSSEL_2; // SMCLK UCB0BR0 |= 0x01; // 1:1 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // clear SW P1OUT &= ~RST; __delay_cycles(1000); P1OUT |= RST; P1OUT &=~A0; P1OUT &=~CS; //Initialize LCD display //see http://www.newhavendisplay.com/specs/NHD-C12832A1Z-FSRGB-FBW-3V.pdf for command set sendCmd(0xA1); //ADC select reverse mode sendCmd(0xA2); // 1/7 bias sendCmd(0x2F); //VC on, VR on, VF on sendCmd(0x21); //resistor ratio 3.5 sendCmd(0x81); //set contrast sendCmd(0x27); //adjust this number to get the best contrast sendCmd(0xAF); //now turn it on! clearall(); gotoXy(0,20); print("MSP430G2553 LCD"); gotoXy(1,35); print("2015-05-22"); while (1){ sec++; if (sec==60){ sec=0; clearline(2); min++; if (min==60){ min=0; hour++; if (hour==24) hour=0; } } gotoXy(3,40); printc((hour/10%10)+48); printc((hour%10)+48); printc(':'); printc((min/10%10)+48); printc((min%10)+48); printc(':'); printc((sec/10%10)+48); printc((sec%10)+48); gotoXy(2,sec); print("Hello World!"); __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/interrupt } } // Watchdog Timer interrupt service routine #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void){ __bic_SR_register_on_exit(CPUOFF); // wake up } void clearall(void){ unsigned char i; for(i = 0; i<4 ; i++) clearline(i); } void clearline(unsigned char line){ unsigned char j; sendCmd(0xB0 | line); //sets page(row) sendCmd(0x10); //sets column address(MSB) to 0 for each page(row) sendCmd(0x04); //sets Column address(LSB) start, for this display 4 for(j=0;j<128;j++) {sendData(0x00);} } void sendData(unsigned char data){ P1OUT |=A0; UCB0TXBUF = data; while(!(IFG2 & UCB0TXIFG)); } void sendCmd(unsigned char cmd){ P1OUT &=~A0; UCB0TXBUF = cmd; while(!(IFG2 & UCB0TXIFG)); } void gotoXy(unsigned char x,unsigned char y){ y+=4; //this display does not show first four lines sendCmd(0xB0|(x & 0x03)); sendCmd(0x10|((y>>4))); sendCmd(0x00|(y & 0x0F)); } void print(char* s){ while(*s) printc(*s++); } void printc(unsigned char r){ unsigned char i; sendData(0); for (i=0;i<5;i++) sendData(font5x8[r-32][i] ); }
  3. Like
    maelli01 got a reaction from tripwire in Tiny Chip-on-glass LCD with ST7565 controller   
    Connected one of those
     
    http://www.newhavendisplay.com/lcd-chiponglass-128-x-32-c-3_113.html
     
    to the launchpad. These are really tiny chip-on-glass LCD displays. The visible area is 8 x 32mm.
     

     
    More tricky than the software is the hardware: in order to work, I had to connect nine 1uF ceramic caps
    to the display (I guess that with the chip-on-glass display it is not possible to integrate the caps into he display).
     
    Made a small,hand etched, one sided PCB, to accomodate the caps and to change from the weird 1.5mm connector
    pitch to a 2.54 one.
     

     
    6502 for size comparison only ;-)
     
    RobG's Nokia software helped me to get the hardware SPI right. Software-SPI, works as well, advantage is the free choice 
    of the pins, but more processor time is wasted for the display.
     
    I measured 85uA, with the example clock program (Display + MSP in LPM3), without backlight. So power-wise this 
    fits perfectly with the MSP. 
    Official working voltage is 2.7-3.3V. The 3.6V of the LP are the maximum rating for the display. 
     
    The backlight is already bright enough for me with 2mA. So switching the backlight on/offwith an extra pin would be easy.
    #include "msp430g2553.h" const unsigned char font5x8[][5] ={ { 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp { 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! { 0x00, 0x07, 0x00, 0x07, 0x00 }, // " { 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # { 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ { 0x62, 0x64, 0x08, 0x13, 0x23 }, // % { 0x36, 0x49, 0x55, 0x22, 0x50 }, // & { 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' { 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( { 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) { 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * { 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + { 0x00, 0x00, 0x50, 0x30, 0x00 }, // , { 0x08, 0x08, 0x08, 0x08, 0x08 }, // - { 0x00, 0x60, 0x60, 0x00, 0x00 }, // . { 0x20, 0x10, 0x08, 0x04, 0x02 }, // / { 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 { 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 { 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 { 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 { 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 { 0x00, 0x36, 0x36, 0x00, 0x00 }, // : { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; { 0x08, 0x14, 0x22, 0x41, 0x00 }, // < { 0x14, 0x14, 0x14, 0x14, 0x14 }, // = { 0x00, 0x41, 0x22, 0x14, 0x08 }, // > { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? { 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ { 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C { 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E { 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F { 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H { 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I { 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K { 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M { 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P { 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q { 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T { 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U { 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V { 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z { 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ { 0x04, 0x08, 0x10, 0x20, 0x40 }, // / { 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ { 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a { 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c { 0x38, 0x44, 0x44, 0x48, 0x7F }, // d { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e { 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f { 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g { 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h { 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i { 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j { 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k { 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l { 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m { 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o { 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p { 0x18, 0x24, 0x24, 0x18, 0xFC }, // q { 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s { 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t { 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u { 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v { 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x { 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y { 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z { 0x08, 0x36, 0x41, 0x41, 0x00 }, // { { 0x00, 0x00, 0x7F, 0x00, 0x00 }, // | { 0x41, 0x41, 0x36, 0x08, 0x00 }, // } { 0x02, 0x04, 0x02, 0x01, 0x02 } // ~ }; unsigned char hour=12, min, sec,j; void clearline(unsigned char); void clearall(void); void print( char* s); void gotoXy(unsigned char , unsigned char); void printc(unsigned char r); void sendData(unsigned char data); void sendCmd(unsigned char cmd); //lcd connected to port 0 #define A0 BIT2 #define CS BIT3 #define SCK BIT5 #define SDA BIT7 #define RST BIT6 void main(void) { WDTCTL = WDT_ADLY_1000; // WDT 1sec, ACLK, interval timer IE1 |= WDTIE; // Enable WDT interrupt BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1DIR = 0b11101100; P1REN = 0b00010011; P2REN = 0b00111111; P1SEL |=SCK + SDA; P1SEL2|=SCK + SDA; UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master UCB0CTL1 |= UCSSEL_2; // SMCLK UCB0BR0 |= 0x01; // 1:1 UCB0BR1 = 0; UCB0CTL1 &= ~UCSWRST; // clear SW P1OUT &= ~RST; __delay_cycles(1000); P1OUT |= RST; P1OUT &=~A0; P1OUT &=~CS; //Initialize LCD display //see http://www.newhavendisplay.com/specs/NHD-C12832A1Z-FSRGB-FBW-3V.pdf for command set sendCmd(0xA1); //ADC select reverse mode sendCmd(0xA2); // 1/7 bias sendCmd(0x2F); //VC on, VR on, VF on sendCmd(0x21); //resistor ratio 3.5 sendCmd(0x81); //set contrast sendCmd(0x27); //adjust this number to get the best contrast sendCmd(0xAF); //now turn it on! clearall(); gotoXy(0,20); print("MSP430G2553 LCD"); gotoXy(1,35); print("2015-05-22"); while (1){ sec++; if (sec==60){ sec=0; clearline(2); min++; if (min==60){ min=0; hour++; if (hour==24) hour=0; } } gotoXy(3,40); printc((hour/10%10)+48); printc((hour%10)+48); printc(':'); printc((min/10%10)+48); printc((min%10)+48); printc(':'); printc((sec/10%10)+48); printc((sec%10)+48); gotoXy(2,sec); print("Hello World!"); __bis_SR_register(LPM3_bits + GIE); // Enter LPM3 w/interrupt } } // Watchdog Timer interrupt service routine #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void){ __bic_SR_register_on_exit(CPUOFF); // wake up } void clearall(void){ unsigned char i; for(i = 0; i<4 ; i++) clearline(i); } void clearline(unsigned char line){ unsigned char j; sendCmd(0xB0 | line); //sets page(row) sendCmd(0x10); //sets column address(MSB) to 0 for each page(row) sendCmd(0x04); //sets Column address(LSB) start, for this display 4 for(j=0;j<128;j++) {sendData(0x00);} } void sendData(unsigned char data){ P1OUT |=A0; UCB0TXBUF = data; while(!(IFG2 & UCB0TXIFG)); } void sendCmd(unsigned char cmd){ P1OUT &=~A0; UCB0TXBUF = cmd; while(!(IFG2 & UCB0TXIFG)); } void gotoXy(unsigned char x,unsigned char y){ y+=4; //this display does not show first four lines sendCmd(0xB0|(x & 0x03)); sendCmd(0x10|((y>>4))); sendCmd(0x00|(y & 0x0F)); } void print(char* s){ while(*s) printc(*s++); } void printc(unsigned char r){ unsigned char i; sendData(0); for (i=0;i<5;i++) sendData(font5x8[r-32][i] ); }
  4. Like
    maelli01 got a reaction from bluehash in Display with ST7565   
    did it! 
     
      
  5. Like
    maelli01 got a reaction from MichelKohler in 3phase variable speed motor drive   
    Hi there
    Here is my 3phase variable speed motor drive booster pack

    This has been in my mind for some years, but I always thought that a 3phase variable speed inverter drive is
    beyond my humble hobbyist scope. Too complicated for my old 8-bit mind ;-)

    Such a inverter contains:
    6 high voltage FETs or IGBTs, 6 gatedrives, at least one DSP, a protection concept,
    all the software to create the 3-phase PWM, dead time control.....

    Still that was for quite some time on my long-term "to do" list, with no chance to actually materialize it,
    not enough time, too many other things to do.

    When playing around with the PWM module of the TM4C123 I found out that creating a 3phase PWM
    signal with this module is actually pretty easy.
    Combined that with an integrated Power Module such as the FSB50550 (Fairchild).



    So here it is: a booster pack for the Tiva Launchpad which drives big-ass 3phase motors.

    The booster pack contains the following:
    - the FSB50550 power module (6 FETs 500V 1.4Ohm, Gatedrivers, Bootstrap diodes, Temp sensor)
    - snubber capacitor
    Power supply: everything is powered from one DC source, 20V or (much) more.
    - 15V switchmode power supply from the high voltage side, built around a LNK304, for the FSB50550
    - 3.3V switchmode power supply from the 15V to power the Launchpad, built around a LT1376
    Measurement:
    - Passive voltage dividier to measure the input voltage
    - Sense resistor and LM339 comparator for overcurrent detection
    Display:
    - Nokia 5110 display
    Potentiometer for motor speed and direction


    The software is based on Energia using Tiva Ware function calls for all the PWM stuff.
    It is still work in progress, very basic and at the moment consists of:

    - calculate the sinwave lookup table at startup
    - PWM initialisation (PWM set to 15625 Hz, deadtime 1us, sync on)
    - a timer interrupt run every 10uSecs, do update the 3 PWD duty cycles
    - ADC measurement of temperature, voltage, current (moving average)
    - fault interrupt

    The main program is very short, the display is updated twice a second and the modulation factor is calculated
    out of the potentiometer speed setting and the applied DC voltage.
    Sudden changes in motor frequency are limited in the software, to prevent the motor to feed back energy and cause
    overvoltage.

    The motor on the picture is a 1/2hp, 900rpm, 6-pole motor, 12 kg of Italian steel and copper, probably 50 years old.
    For playing around, I apply about 50% of rated volt/hz, so current and maximum torque is reduced.
    Currently I use my dual 35V 4A lab supply, series connected, as a power source.
     
    here is the code:
    //simple 3phase frequency converter //27.9.2014 by maelli #define dots 192 //dots per halfhave, must be divisible with 3 #define period 5120 //80Mhz/5120 = 15625 switching frequency #define dt 80 //deadtime 80Mhz / 80 = 1uS #define PART_TM4C123GH6PM #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_sysctl.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/pwm.h" #include "LCD_5110.h" #include "inc/tm4c123gh6pm.h" LCD_5110 myScreen (33,37,36,35,34,38,17); char celsius[3]={0x7f,'C',0x00}; uint16_t a,dire=0,modu,tensec; uint32_t timecount,sintable[dots]; volatile int32_t irqcount,timeset; volatile uint32_t temperature, voltage, current, poti; void setup(){ myScreen.begin(); myScreen.setBacklight(0); myScreen.text(0, 0, "3ph Converter"); for(int i=0;i<dots;i++) sintable[i]=sinf((i*3.14159)/dots)*(period/2-dt); unsigned long ulPeriod; unsigned int Hz = 10000; // interupt frequency in Hz ulPeriod = (SysCtlClockGet() / Hz); initTimer(); charge_gdu(); ROM_TimerLoadSet(TIMER0_BASE, TIMER_A,ulPeriod -1); initPWM(); } void loop(){ if (irqcount>499) { //20x per sec irqcount-=500; int32_t fsoll=732*(poti-16384); int32_t diff=fsoll-timeset; if (diff>0){ if (diff>150000) timeset+=150000; else timeset=fsoll; } else { if (diff<-150000) timeset-=150000; else timeset=fsoll; } modu=abs(timeset)/voltage/16; if (modu<(32000/voltage)) modu=32000/voltage; if (modu>256) modu=256; tensec++; if (tensec==10) { //2x per sec we display something tensec=0; myScreen.text(0, 1, mkstrg((temperature-325)/24,2)); myScreen.text(2, 1, celsius); myScreen.text(5, 1, mkstrg((voltage)/23,3)); myScreen.text(8, 1, "Volt"); myScreen.text(0, 2, mkstrg(abs(timeset)/322122,2)); myScreen.text(2, 2, "."); myScreen.text(3, 2, mkstrg(abs((timeset/32212)%10),1)); myScreen.text(4, 2, "Hz"); myScreen.text(7, 2, mkstrg(current,4)); myScreen.text(11, 2, "mA"); if (timeset<0) myScreen.text(0, 3, "links "); else myScreen.text(0, 3, "rechts"); } } } String mkstrg(int d,uint8_t l){ char display[l+1]; int q=1; display[l]=0; for (uint8_t a=l;a;a--){ display[a-1]=0x30+(d%(q*10))/q; q*=10; } return display; } void initTimer(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); // 32 bits Timer TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0Isr); // Registering isr ROM_TimerEnable(TIMER0_BASE, TIMER_A); ROM_IntEnable(INT_TIMER0A); ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } void charge_gdu(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 ); ROM_GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_0,GPIO_STRENGTH_4MA,GPIO_PIN_TYPE_STD); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7); //alle 3 oberen ausschalten HWREG(GPIO_PORTA_BASE + (GPIO_PIN_7 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_1 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_3 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0); //auch die 2 letzten aus HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6); //den ersten unteren ein HWREG(GPIO_PORTA_BASE + (GPIO_PIN_6 << 2)) = GPIO_PIN_6; delay(1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = GPIO_PIN_0; delay(1); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = GPIO_PIN_2; delay(1); } void initPWM(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //The Tiva Launchpad has two PWM modules (0 and 1). We are using 1 ROM_GPIOPinConfigure(GPIO_PD0_M1PWM0); ROM_GPIOPinConfigure(GPIO_PD1_M1PWM1); ROM_GPIOPinConfigure(GPIO_PA6_M1PWM2); ROM_GPIOPinConfigure(GPIO_PA7_M1PWM3); ROM_GPIOPinConfigure(GPIO_PF2_M1PWM6); ROM_GPIOPinConfigure(GPIO_PF3_M1PWM7); ROM_GPIOPinConfigure(GPIO_PF4_M1FAULT0); ROM_GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 ); ROM_GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ); ROM_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4); PWM1_0_FLTSEN_R =3; //PWM fault inverted see page 1169 GPIO_PORTF_PUR_R=0x10; //weak pullup for Pin 4 ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_0, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_1, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_3, dt,dt); ROM_PWMSyncTimeBase(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_0); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_1); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_3); delay(1); PWMFaultIntRegister(PWM1_BASE, oh_shit); ROM_PWMIntEnable(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true); } void Timer0Isr(void) { //10000x per second ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // Clear the timer interrupt irqcount++; timecount+=timeset; // 1 Hz is 192x256*256*256/10000=322122.5 if (timecount> 0xEFFFFFFF) timecount+=0xC0000000; if (timecount> 0xBFFFFFFF) timecount-=0xC0000000;; a=timecount>>16; a=a/(16384/(dots/3*2)); //a immer kleiner 2*dots: C000 *dots/3*2/ 4000= 12 *dots/3*2/4= 2*dots if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2-sintable[a-dots]*modu/256); ROM_PWMSyncUpdate(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); switch(irqcount%10){ case 0: temperature=(temperature*127+analogRead(26))/128; break; case 1: voltage=(voltage*31+analogRead(27)*3)/32; break; case 2: current=(current*127+analogRead(25)*8)/128; break; case 3: poti=(poti*127+analogRead(28)*8)/128; break; } } void oh_shit(void) { //in case of severe overcurrent we shut down! ROM_PWMFaultIntClearExt(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, false); }  



  6. Like
    maelli01 got a reaction from developer_bt in 3phase variable speed motor drive   
    @@timotet
    here are some more pictures. The launchpad is sandwiched between the display and my board.
    Not much on top, the 50550 hidden under copper heatsink (epoxied on). What looks like a big resistor
    is a 1mH inductor.
    Yes, this is the first working prototype, and it looks like this. Smallest SMDs I hand solder are 0603.
     
    The circuit diagram (Eagle) is no secret either, however, not human readable yet, since I did not find
    models for e.g.LNK304. So I used different componens with similar pinout in the diagram, nasty me.
     
    I loosely followed this app note:
    https://www.fairchildsemi.com/application-notes/AN/AN-9080.pdf
     
    Yes, the practical uses are limited...  fractional-horsepower 3phase motors are rare.
    checked my drill press, but that has a 2 phase capacitor motor, not a real 3 phase motor with
    steinmetz circuit.
     



  7. Like
    maelli01 got a reaction from tripwire in bug in msp430g2xx3_pinosc_01.c   
    in the latest version of slac485 (revision e), from 2015-01-26, the bug is fixed
     
     :-)
  8. Like
    maelli01 got a reaction from tripwire in bug in msp430g2xx3_pinosc_01.c   
    tried out the capacitive touch code examples.
     
    msp430g2xx3_pinosc_01c did not work for me, LEDs blink all
    the time, without touching anything.
     
    So I tried msp430g2xx3_pinosc_02c (4 channel) . Works a treat.
     
    Compared the code and found the bug: from line 159 in msp430g2xx3_pinosc_01c :
         if (delta_cnt > j)                    // Determine if each key is pressed        {                                     // per a preset threshold         j = delta_cnt;         key_pressed = 1;                    // key pressed       }       else         key_pressed = 1;   looks like key_pressed is forced to 1 ;-)     changed it to this (same as in pinosc_02c) it works as expected           if (delta_cnt > j)                    // Determine if each key is pressed        {                                     // per a preset threshold         j = delta_cnt;         key_pressed = 1;                    // key pressed       }       else         key_pressed = 0;   haha...    MSP430 code examples are self-contained low-level programs that typically  * demonstrate a single peripheral function or device feature in a HIGHLY  * CONCISE MANNER.   At least I had a close look at the code for finding the bug...  
  9. Like
    maelli01 got a reaction from spirilis in 3phase variable speed motor drive   
    Hi there
    Here is my 3phase variable speed motor drive booster pack

    This has been in my mind for some years, but I always thought that a 3phase variable speed inverter drive is
    beyond my humble hobbyist scope. Too complicated for my old 8-bit mind ;-)

    Such a inverter contains:
    6 high voltage FETs or IGBTs, 6 gatedrives, at least one DSP, a protection concept,
    all the software to create the 3-phase PWM, dead time control.....

    Still that was for quite some time on my long-term "to do" list, with no chance to actually materialize it,
    not enough time, too many other things to do.

    When playing around with the PWM module of the TM4C123 I found out that creating a 3phase PWM
    signal with this module is actually pretty easy.
    Combined that with an integrated Power Module such as the FSB50550 (Fairchild).



    So here it is: a booster pack for the Tiva Launchpad which drives big-ass 3phase motors.

    The booster pack contains the following:
    - the FSB50550 power module (6 FETs 500V 1.4Ohm, Gatedrivers, Bootstrap diodes, Temp sensor)
    - snubber capacitor
    Power supply: everything is powered from one DC source, 20V or (much) more.
    - 15V switchmode power supply from the high voltage side, built around a LNK304, for the FSB50550
    - 3.3V switchmode power supply from the 15V to power the Launchpad, built around a LT1376
    Measurement:
    - Passive voltage dividier to measure the input voltage
    - Sense resistor and LM339 comparator for overcurrent detection
    Display:
    - Nokia 5110 display
    Potentiometer for motor speed and direction


    The software is based on Energia using Tiva Ware function calls for all the PWM stuff.
    It is still work in progress, very basic and at the moment consists of:

    - calculate the sinwave lookup table at startup
    - PWM initialisation (PWM set to 15625 Hz, deadtime 1us, sync on)
    - a timer interrupt run every 10uSecs, do update the 3 PWD duty cycles
    - ADC measurement of temperature, voltage, current (moving average)
    - fault interrupt

    The main program is very short, the display is updated twice a second and the modulation factor is calculated
    out of the potentiometer speed setting and the applied DC voltage.
    Sudden changes in motor frequency are limited in the software, to prevent the motor to feed back energy and cause
    overvoltage.

    The motor on the picture is a 1/2hp, 900rpm, 6-pole motor, 12 kg of Italian steel and copper, probably 50 years old.
    For playing around, I apply about 50% of rated volt/hz, so current and maximum torque is reduced.
    Currently I use my dual 35V 4A lab supply, series connected, as a power source.
     
    here is the code:
    //simple 3phase frequency converter //27.9.2014 by maelli #define dots 192 //dots per halfhave, must be divisible with 3 #define period 5120 //80Mhz/5120 = 15625 switching frequency #define dt 80 //deadtime 80Mhz / 80 = 1uS #define PART_TM4C123GH6PM #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_sysctl.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/pwm.h" #include "LCD_5110.h" #include "inc/tm4c123gh6pm.h" LCD_5110 myScreen (33,37,36,35,34,38,17); char celsius[3]={0x7f,'C',0x00}; uint16_t a,dire=0,modu,tensec; uint32_t timecount,sintable[dots]; volatile int32_t irqcount,timeset; volatile uint32_t temperature, voltage, current, poti; void setup(){ myScreen.begin(); myScreen.setBacklight(0); myScreen.text(0, 0, "3ph Converter"); for(int i=0;i<dots;i++) sintable[i]=sinf((i*3.14159)/dots)*(period/2-dt); unsigned long ulPeriod; unsigned int Hz = 10000; // interupt frequency in Hz ulPeriod = (SysCtlClockGet() / Hz); initTimer(); charge_gdu(); ROM_TimerLoadSet(TIMER0_BASE, TIMER_A,ulPeriod -1); initPWM(); } void loop(){ if (irqcount>499) { //20x per sec irqcount-=500; int32_t fsoll=732*(poti-16384); int32_t diff=fsoll-timeset; if (diff>0){ if (diff>150000) timeset+=150000; else timeset=fsoll; } else { if (diff<-150000) timeset-=150000; else timeset=fsoll; } modu=abs(timeset)/voltage/16; if (modu<(32000/voltage)) modu=32000/voltage; if (modu>256) modu=256; tensec++; if (tensec==10) { //2x per sec we display something tensec=0; myScreen.text(0, 1, mkstrg((temperature-325)/24,2)); myScreen.text(2, 1, celsius); myScreen.text(5, 1, mkstrg((voltage)/23,3)); myScreen.text(8, 1, "Volt"); myScreen.text(0, 2, mkstrg(abs(timeset)/322122,2)); myScreen.text(2, 2, "."); myScreen.text(3, 2, mkstrg(abs((timeset/32212)%10),1)); myScreen.text(4, 2, "Hz"); myScreen.text(7, 2, mkstrg(current,4)); myScreen.text(11, 2, "mA"); if (timeset<0) myScreen.text(0, 3, "links "); else myScreen.text(0, 3, "rechts"); } } } String mkstrg(int d,uint8_t l){ char display[l+1]; int q=1; display[l]=0; for (uint8_t a=l;a;a--){ display[a-1]=0x30+(d%(q*10))/q; q*=10; } return display; } void initTimer(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); // 32 bits Timer TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0Isr); // Registering isr ROM_TimerEnable(TIMER0_BASE, TIMER_A); ROM_IntEnable(INT_TIMER0A); ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } void charge_gdu(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 ); ROM_GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_0,GPIO_STRENGTH_4MA,GPIO_PIN_TYPE_STD); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7); //alle 3 oberen ausschalten HWREG(GPIO_PORTA_BASE + (GPIO_PIN_7 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_1 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_3 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0); //auch die 2 letzten aus HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6); //den ersten unteren ein HWREG(GPIO_PORTA_BASE + (GPIO_PIN_6 << 2)) = GPIO_PIN_6; delay(1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = GPIO_PIN_0; delay(1); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = GPIO_PIN_2; delay(1); } void initPWM(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //The Tiva Launchpad has two PWM modules (0 and 1). We are using 1 ROM_GPIOPinConfigure(GPIO_PD0_M1PWM0); ROM_GPIOPinConfigure(GPIO_PD1_M1PWM1); ROM_GPIOPinConfigure(GPIO_PA6_M1PWM2); ROM_GPIOPinConfigure(GPIO_PA7_M1PWM3); ROM_GPIOPinConfigure(GPIO_PF2_M1PWM6); ROM_GPIOPinConfigure(GPIO_PF3_M1PWM7); ROM_GPIOPinConfigure(GPIO_PF4_M1FAULT0); ROM_GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 ); ROM_GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ); ROM_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4); PWM1_0_FLTSEN_R =3; //PWM fault inverted see page 1169 GPIO_PORTF_PUR_R=0x10; //weak pullup for Pin 4 ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_0, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_1, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_3, dt,dt); ROM_PWMSyncTimeBase(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_0); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_1); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_3); delay(1); PWMFaultIntRegister(PWM1_BASE, oh_shit); ROM_PWMIntEnable(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true); } void Timer0Isr(void) { //10000x per second ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // Clear the timer interrupt irqcount++; timecount+=timeset; // 1 Hz is 192x256*256*256/10000=322122.5 if (timecount> 0xEFFFFFFF) timecount+=0xC0000000; if (timecount> 0xBFFFFFFF) timecount-=0xC0000000;; a=timecount>>16; a=a/(16384/(dots/3*2)); //a immer kleiner 2*dots: C000 *dots/3*2/ 4000= 12 *dots/3*2/4= 2*dots if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2-sintable[a-dots]*modu/256); ROM_PWMSyncUpdate(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); switch(irqcount%10){ case 0: temperature=(temperature*127+analogRead(26))/128; break; case 1: voltage=(voltage*31+analogRead(27)*3)/32; break; case 2: current=(current*127+analogRead(25)*8)/128; break; case 3: poti=(poti*127+analogRead(28)*8)/128; break; } } void oh_shit(void) { //in case of severe overcurrent we shut down! ROM_PWMFaultIntClearExt(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, false); }  



  10. Like
    maelli01 got a reaction from bluehash in 3phase variable speed motor drive   
    Hi there
    Here is my 3phase variable speed motor drive booster pack

    This has been in my mind for some years, but I always thought that a 3phase variable speed inverter drive is
    beyond my humble hobbyist scope. Too complicated for my old 8-bit mind ;-)

    Such a inverter contains:
    6 high voltage FETs or IGBTs, 6 gatedrives, at least one DSP, a protection concept,
    all the software to create the 3-phase PWM, dead time control.....

    Still that was for quite some time on my long-term "to do" list, with no chance to actually materialize it,
    not enough time, too many other things to do.

    When playing around with the PWM module of the TM4C123 I found out that creating a 3phase PWM
    signal with this module is actually pretty easy.
    Combined that with an integrated Power Module such as the FSB50550 (Fairchild).



    So here it is: a booster pack for the Tiva Launchpad which drives big-ass 3phase motors.

    The booster pack contains the following:
    - the FSB50550 power module (6 FETs 500V 1.4Ohm, Gatedrivers, Bootstrap diodes, Temp sensor)
    - snubber capacitor
    Power supply: everything is powered from one DC source, 20V or (much) more.
    - 15V switchmode power supply from the high voltage side, built around a LNK304, for the FSB50550
    - 3.3V switchmode power supply from the 15V to power the Launchpad, built around a LT1376
    Measurement:
    - Passive voltage dividier to measure the input voltage
    - Sense resistor and LM339 comparator for overcurrent detection
    Display:
    - Nokia 5110 display
    Potentiometer for motor speed and direction


    The software is based on Energia using Tiva Ware function calls for all the PWM stuff.
    It is still work in progress, very basic and at the moment consists of:

    - calculate the sinwave lookup table at startup
    - PWM initialisation (PWM set to 15625 Hz, deadtime 1us, sync on)
    - a timer interrupt run every 10uSecs, do update the 3 PWD duty cycles
    - ADC measurement of temperature, voltage, current (moving average)
    - fault interrupt

    The main program is very short, the display is updated twice a second and the modulation factor is calculated
    out of the potentiometer speed setting and the applied DC voltage.
    Sudden changes in motor frequency are limited in the software, to prevent the motor to feed back energy and cause
    overvoltage.

    The motor on the picture is a 1/2hp, 900rpm, 6-pole motor, 12 kg of Italian steel and copper, probably 50 years old.
    For playing around, I apply about 50% of rated volt/hz, so current and maximum torque is reduced.
    Currently I use my dual 35V 4A lab supply, series connected, as a power source.
     
    here is the code:
    //simple 3phase frequency converter //27.9.2014 by maelli #define dots 192 //dots per halfhave, must be divisible with 3 #define period 5120 //80Mhz/5120 = 15625 switching frequency #define dt 80 //deadtime 80Mhz / 80 = 1uS #define PART_TM4C123GH6PM #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_sysctl.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/pwm.h" #include "LCD_5110.h" #include "inc/tm4c123gh6pm.h" LCD_5110 myScreen (33,37,36,35,34,38,17); char celsius[3]={0x7f,'C',0x00}; uint16_t a,dire=0,modu,tensec; uint32_t timecount,sintable[dots]; volatile int32_t irqcount,timeset; volatile uint32_t temperature, voltage, current, poti; void setup(){ myScreen.begin(); myScreen.setBacklight(0); myScreen.text(0, 0, "3ph Converter"); for(int i=0;i<dots;i++) sintable[i]=sinf((i*3.14159)/dots)*(period/2-dt); unsigned long ulPeriod; unsigned int Hz = 10000; // interupt frequency in Hz ulPeriod = (SysCtlClockGet() / Hz); initTimer(); charge_gdu(); ROM_TimerLoadSet(TIMER0_BASE, TIMER_A,ulPeriod -1); initPWM(); } void loop(){ if (irqcount>499) { //20x per sec irqcount-=500; int32_t fsoll=732*(poti-16384); int32_t diff=fsoll-timeset; if (diff>0){ if (diff>150000) timeset+=150000; else timeset=fsoll; } else { if (diff<-150000) timeset-=150000; else timeset=fsoll; } modu=abs(timeset)/voltage/16; if (modu<(32000/voltage)) modu=32000/voltage; if (modu>256) modu=256; tensec++; if (tensec==10) { //2x per sec we display something tensec=0; myScreen.text(0, 1, mkstrg((temperature-325)/24,2)); myScreen.text(2, 1, celsius); myScreen.text(5, 1, mkstrg((voltage)/23,3)); myScreen.text(8, 1, "Volt"); myScreen.text(0, 2, mkstrg(abs(timeset)/322122,2)); myScreen.text(2, 2, "."); myScreen.text(3, 2, mkstrg(abs((timeset/32212)%10),1)); myScreen.text(4, 2, "Hz"); myScreen.text(7, 2, mkstrg(current,4)); myScreen.text(11, 2, "mA"); if (timeset<0) myScreen.text(0, 3, "links "); else myScreen.text(0, 3, "rechts"); } } } String mkstrg(int d,uint8_t l){ char display[l+1]; int q=1; display[l]=0; for (uint8_t a=l;a;a--){ display[a-1]=0x30+(d%(q*10))/q; q*=10; } return display; } void initTimer(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); // 32 bits Timer TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0Isr); // Registering isr ROM_TimerEnable(TIMER0_BASE, TIMER_A); ROM_IntEnable(INT_TIMER0A); ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } void charge_gdu(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 ); ROM_GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_0,GPIO_STRENGTH_4MA,GPIO_PIN_TYPE_STD); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7); //alle 3 oberen ausschalten HWREG(GPIO_PORTA_BASE + (GPIO_PIN_7 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_1 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_3 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0); //auch die 2 letzten aus HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6); //den ersten unteren ein HWREG(GPIO_PORTA_BASE + (GPIO_PIN_6 << 2)) = GPIO_PIN_6; delay(1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = GPIO_PIN_0; delay(1); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = GPIO_PIN_2; delay(1); } void initPWM(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //The Tiva Launchpad has two PWM modules (0 and 1). We are using 1 ROM_GPIOPinConfigure(GPIO_PD0_M1PWM0); ROM_GPIOPinConfigure(GPIO_PD1_M1PWM1); ROM_GPIOPinConfigure(GPIO_PA6_M1PWM2); ROM_GPIOPinConfigure(GPIO_PA7_M1PWM3); ROM_GPIOPinConfigure(GPIO_PF2_M1PWM6); ROM_GPIOPinConfigure(GPIO_PF3_M1PWM7); ROM_GPIOPinConfigure(GPIO_PF4_M1FAULT0); ROM_GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 ); ROM_GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ); ROM_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4); PWM1_0_FLTSEN_R =3; //PWM fault inverted see page 1169 GPIO_PORTF_PUR_R=0x10; //weak pullup for Pin 4 ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_0, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_1, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_3, dt,dt); ROM_PWMSyncTimeBase(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_0); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_1); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_3); delay(1); PWMFaultIntRegister(PWM1_BASE, oh_shit); ROM_PWMIntEnable(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true); } void Timer0Isr(void) { //10000x per second ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // Clear the timer interrupt irqcount++; timecount+=timeset; // 1 Hz is 192x256*256*256/10000=322122.5 if (timecount> 0xEFFFFFFF) timecount+=0xC0000000; if (timecount> 0xBFFFFFFF) timecount-=0xC0000000;; a=timecount>>16; a=a/(16384/(dots/3*2)); //a immer kleiner 2*dots: C000 *dots/3*2/ 4000= 12 *dots/3*2/4= 2*dots if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2-sintable[a-dots]*modu/256); ROM_PWMSyncUpdate(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); switch(irqcount%10){ case 0: temperature=(temperature*127+analogRead(26))/128; break; case 1: voltage=(voltage*31+analogRead(27)*3)/32; break; case 2: current=(current*127+analogRead(25)*8)/128; break; case 3: poti=(poti*127+analogRead(28)*8)/128; break; } } void oh_shit(void) { //in case of severe overcurrent we shut down! ROM_PWMFaultIntClearExt(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, false); }  



  11. Like
    maelli01 got a reaction from Fmilburn in 3phase variable speed motor drive   
    Hi there
    Here is my 3phase variable speed motor drive booster pack

    This has been in my mind for some years, but I always thought that a 3phase variable speed inverter drive is
    beyond my humble hobbyist scope. Too complicated for my old 8-bit mind ;-)

    Such a inverter contains:
    6 high voltage FETs or IGBTs, 6 gatedrives, at least one DSP, a protection concept,
    all the software to create the 3-phase PWM, dead time control.....

    Still that was for quite some time on my long-term "to do" list, with no chance to actually materialize it,
    not enough time, too many other things to do.

    When playing around with the PWM module of the TM4C123 I found out that creating a 3phase PWM
    signal with this module is actually pretty easy.
    Combined that with an integrated Power Module such as the FSB50550 (Fairchild).



    So here it is: a booster pack for the Tiva Launchpad which drives big-ass 3phase motors.

    The booster pack contains the following:
    - the FSB50550 power module (6 FETs 500V 1.4Ohm, Gatedrivers, Bootstrap diodes, Temp sensor)
    - snubber capacitor
    Power supply: everything is powered from one DC source, 20V or (much) more.
    - 15V switchmode power supply from the high voltage side, built around a LNK304, for the FSB50550
    - 3.3V switchmode power supply from the 15V to power the Launchpad, built around a LT1376
    Measurement:
    - Passive voltage dividier to measure the input voltage
    - Sense resistor and LM339 comparator for overcurrent detection
    Display:
    - Nokia 5110 display
    Potentiometer for motor speed and direction


    The software is based on Energia using Tiva Ware function calls for all the PWM stuff.
    It is still work in progress, very basic and at the moment consists of:

    - calculate the sinwave lookup table at startup
    - PWM initialisation (PWM set to 15625 Hz, deadtime 1us, sync on)
    - a timer interrupt run every 10uSecs, do update the 3 PWD duty cycles
    - ADC measurement of temperature, voltage, current (moving average)
    - fault interrupt

    The main program is very short, the display is updated twice a second and the modulation factor is calculated
    out of the potentiometer speed setting and the applied DC voltage.
    Sudden changes in motor frequency are limited in the software, to prevent the motor to feed back energy and cause
    overvoltage.

    The motor on the picture is a 1/2hp, 900rpm, 6-pole motor, 12 kg of Italian steel and copper, probably 50 years old.
    For playing around, I apply about 50% of rated volt/hz, so current and maximum torque is reduced.
    Currently I use my dual 35V 4A lab supply, series connected, as a power source.
     
    here is the code:
    //simple 3phase frequency converter //27.9.2014 by maelli #define dots 192 //dots per halfhave, must be divisible with 3 #define period 5120 //80Mhz/5120 = 15625 switching frequency #define dt 80 //deadtime 80Mhz / 80 = 1uS #define PART_TM4C123GH6PM #include <stdint.h> #include <stdbool.h> #include "inc/hw_ints.h" #include "inc/hw_sysctl.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/pwm.h" #include "LCD_5110.h" #include "inc/tm4c123gh6pm.h" LCD_5110 myScreen (33,37,36,35,34,38,17); char celsius[3]={0x7f,'C',0x00}; uint16_t a,dire=0,modu,tensec; uint32_t timecount,sintable[dots]; volatile int32_t irqcount,timeset; volatile uint32_t temperature, voltage, current, poti; void setup(){ myScreen.begin(); myScreen.setBacklight(0); myScreen.text(0, 0, "3ph Converter"); for(int i=0;i<dots;i++) sintable[i]=sinf((i*3.14159)/dots)*(period/2-dt); unsigned long ulPeriod; unsigned int Hz = 10000; // interupt frequency in Hz ulPeriod = (SysCtlClockGet() / Hz); initTimer(); charge_gdu(); ROM_TimerLoadSet(TIMER0_BASE, TIMER_A,ulPeriod -1); initPWM(); } void loop(){ if (irqcount>499) { //20x per sec irqcount-=500; int32_t fsoll=732*(poti-16384); int32_t diff=fsoll-timeset; if (diff>0){ if (diff>150000) timeset+=150000; else timeset=fsoll; } else { if (diff<-150000) timeset-=150000; else timeset=fsoll; } modu=abs(timeset)/voltage/16; if (modu<(32000/voltage)) modu=32000/voltage; if (modu>256) modu=256; tensec++; if (tensec==10) { //2x per sec we display something tensec=0; myScreen.text(0, 1, mkstrg((temperature-325)/24,2)); myScreen.text(2, 1, celsius); myScreen.text(5, 1, mkstrg((voltage)/23,3)); myScreen.text(8, 1, "Volt"); myScreen.text(0, 2, mkstrg(abs(timeset)/322122,2)); myScreen.text(2, 2, "."); myScreen.text(3, 2, mkstrg(abs((timeset/32212)%10),1)); myScreen.text(4, 2, "Hz"); myScreen.text(7, 2, mkstrg(current,4)); myScreen.text(11, 2, "mA"); if (timeset<0) myScreen.text(0, 3, "links "); else myScreen.text(0, 3, "rechts"); } } } String mkstrg(int d,uint8_t l){ char display[l+1]; int q=1; display[l]=0; for (uint8_t a=l;a;a--){ display[a-1]=0x30+(d%(q*10))/q; q*=10; } return display; } void initTimer(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); // 32 bits Timer TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0Isr); // Registering isr ROM_TimerEnable(TIMER0_BASE, TIMER_A); ROM_IntEnable(INT_TIMER0A); ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } void charge_gdu(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0 ); ROM_GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_0,GPIO_STRENGTH_4MA,GPIO_PIN_TYPE_STD); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7); //alle 3 oberen ausschalten HWREG(GPIO_PORTA_BASE + (GPIO_PIN_7 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_1 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_3 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0); //auch die 2 letzten aus HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = 0; GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6); //den ersten unteren ein HWREG(GPIO_PORTA_BASE + (GPIO_PIN_6 << 2)) = GPIO_PIN_6; delay(1); HWREG(GPIO_PORTD_BASE + (GPIO_PIN_0 << 2)) = GPIO_PIN_0; delay(1); HWREG(GPIO_PORTF_BASE + (GPIO_PIN_2 << 2)) = GPIO_PIN_2; delay(1); } void initPWM(){ ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); //The Tiva Launchpad has two PWM modules (0 and 1). We are using 1 ROM_GPIOPinConfigure(GPIO_PD0_M1PWM0); ROM_GPIOPinConfigure(GPIO_PD1_M1PWM1); ROM_GPIOPinConfigure(GPIO_PA6_M1PWM2); ROM_GPIOPinConfigure(GPIO_PA7_M1PWM3); ROM_GPIOPinConfigure(GPIO_PF2_M1PWM6); ROM_GPIOPinConfigure(GPIO_PF3_M1PWM7); ROM_GPIOPinConfigure(GPIO_PF4_M1FAULT0); ROM_GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 ); ROM_GPIOPinTypePWM(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7 ); ROM_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4); PWM1_0_FLTSEN_R =3; //PWM fault inverted see page 1169 GPIO_PORTF_PUR_R=0x10; //weak pullup for Pin 4 ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenConfigure(PWM1_BASE, PWM_GEN_3, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_SYNC | PWM_GEN_MODE_FAULT_LEGACY); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_0, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_1, period); ROM_PWMGenPeriodSet(PWM1_BASE, PWM_GEN_3, period); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_0, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_1, dt,dt); ROM_PWMDeadBandEnable(PWM1_BASE, PWM_GEN_3, dt,dt); ROM_PWMSyncTimeBase(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_0); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_1); ROM_PWMGenEnable(PWM1_BASE, PWM_GEN_3); delay(1); PWMFaultIntRegister(PWM1_BASE, oh_shit); ROM_PWMIntEnable(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, true); } void Timer0Isr(void) { //10000x per second ROM_TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // Clear the timer interrupt irqcount++; timecount+=timeset; // 1 Hz is 192x256*256*256/10000=322122.5 if (timecount> 0xEFFFFFFF) timecount+=0xC0000000; if (timecount> 0xBFFFFFFF) timecount-=0xC0000000;; a=timecount>>16; a=a/(16384/(dots/3*2)); //a immer kleiner 2*dots: C000 *dots/3*2/ 4000= 12 *dots/3*2/4= 2*dots if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_0,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_2,period/2-sintable[a-dots]*modu/256); a=a+dots*2/3; if (a>=2*dots) a-=2*dots; if (a<dots)ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2+sintable[a]*modu/256); else ROM_PWMPulseWidthSet(PWM1_BASE, PWM_OUT_6,period/2-sintable[a-dots]*modu/256); ROM_PWMSyncUpdate(PWM1_BASE,PWM_GEN_0_BIT |PWM_GEN_1_BIT|PWM_GEN_3_BIT); switch(irqcount%10){ case 0: temperature=(temperature*127+analogRead(26))/128; break; case 1: voltage=(voltage*31+analogRead(27)*3)/32; break; case 2: current=(current*127+analogRead(25)*8)/128; break; case 3: poti=(poti*127+analogRead(28)*8)/128; break; } } void oh_shit(void) { //in case of severe overcurrent we shut down! ROM_PWMFaultIntClearExt(PWM1_BASE,PWM_INT_FAULT0); ROM_PWMOutputState(PWM1_BASE, PWM_OUT_0_BIT | PWM_OUT_1_BIT | PWM1_BASE | PWM_OUT_2_BIT | PWM_OUT_3_BIT |PWM_OUT_6_BIT | PWM_OUT_7_BIT, false); }  



  12. Like
    maelli01 reacted to DickB in Electromagnetic pendulum clock   
    This pendulum clock is not only regulated by the pendulum, but it is driven by it.  A hidden magnet in the pendulum swings past a hidden coil and induces a current.  This is detected and then a current pulse is fed into the coil, creating an electromagnet that repels the pendulum to keep it moving.
     
    Others have designed and built clocks like this, but as far as I know mine is the only one using a microcontroller to fine-tune the pendulum's speed to keep accurate time. 
     
    The coil's output is filtered and fed into an MSP430 comparator, set on an interrupt to wake the microcontroller up.  The microcontroller delays a bit to let the magnet swing away from the coil some for optimal push, then feeds a variable-length pulse (typically 25 mS) into the coil via an output port connected to a PNP transistor.  If the pulse duration is increased, the pendulum swings farther and slows down.  If decreased, the pendulum speeds up.  The ratchet mechanism used to convert pendulum motion into rotary motion had to be designed to accommodate this variation in pendulum swing angle.  By varying the pulse width, the clock can be sped up or slowed down about 1%.  The pendulum needs to be manually adjusted, by setting the height of the bob, to within this tolerance.  To facilitate that, I use a dual-color LED driven by two output ports.  The LED flashes red if the pendulum is too slow, and green if it is too fast.  It usually takes only a few minutes to adjust the bob.  
     
    Once the bob is set, the microcontroller can maintain accuracy.  I've implemented a modified PID (proportional - integral - derivative) control system to derive the pulse width and regulate the clock. Accuracy is basically the same as the watch crystal used to drive the timer/counter. 




  13. Like
    maelli01 got a reaction from roadrunner84 in Tiny low power LED clock   
    Hello,

    Oh no, not another clock...

    My first standalone MSP430 project and also my first project to
    be programmed "in circuit", and a soldering exercise for the TSSOP housing

    A tiny LED clock. It is minimalistic by all means:
    -a TSSOP G2452, no other IC
    -only one button to set the time
    -a dumb 4 digit white LED 7 segment display, https://www.sparkfun.com/products/11409
    -a PCB size of 25mm x 25mm
    -extremely low power

    Wanted to find out whether I can use the TSSOP with my usual home made setup,
    that is Eagle, Deskjet printer, photosensitive base material, UV-lamp, develop,
    the ugly FeCl3 etching, and then hand-solder.
    The PCB is single sided of course.

    I use the lauchpad for programming.

    The white LEDs of the display are pretty bright at their nominal current.
    I wanted something low power and just enough brightness to see the time in the
    middle of the night with darkness-adapted eyes.
    So at 4:30 in the morning, the display is much more useful than an LCD.

    The whole thing draws around 0.3- 0.5mA, LEDs included.
    CPU runs at 1Mhz, but is in LPM3 most of the time, even though the poor thing has
    a restless sleep: it has to wake up 512 times a second, to do the multiplexing.

    At this low current there are quite a few options for a power supply, I considered

    - 2 AA cells; would run around half a year
    - something solar, with supercap
    - I ended up with direct AC supply via a capacitive dropper, 4700pF mains rated film
    cap. Where I live, plugs are polarized, so I know which one if life and which one
    is neutral. Still I think that this would not be street-legal without double insulation
    housing.

    Overall I calculated 2milliwatt total power consumption, probably the lowest of
    any mains powered clock.

    If anybody is interested, I might bring schematic and software into
    human-readable form.
     


  14. Like
    maelli01 got a reaction from RobG in Tiny low power LED clock   
    Hello,

    Oh no, not another clock...

    My first standalone MSP430 project and also my first project to
    be programmed "in circuit", and a soldering exercise for the TSSOP housing

    A tiny LED clock. It is minimalistic by all means:
    -a TSSOP G2452, no other IC
    -only one button to set the time
    -a dumb 4 digit white LED 7 segment display, https://www.sparkfun.com/products/11409
    -a PCB size of 25mm x 25mm
    -extremely low power

    Wanted to find out whether I can use the TSSOP with my usual home made setup,
    that is Eagle, Deskjet printer, photosensitive base material, UV-lamp, develop,
    the ugly FeCl3 etching, and then hand-solder.
    The PCB is single sided of course.

    I use the lauchpad for programming.

    The white LEDs of the display are pretty bright at their nominal current.
    I wanted something low power and just enough brightness to see the time in the
    middle of the night with darkness-adapted eyes.
    So at 4:30 in the morning, the display is much more useful than an LCD.

    The whole thing draws around 0.3- 0.5mA, LEDs included.
    CPU runs at 1Mhz, but is in LPM3 most of the time, even though the poor thing has
    a restless sleep: it has to wake up 512 times a second, to do the multiplexing.

    At this low current there are quite a few options for a power supply, I considered

    - 2 AA cells; would run around half a year
    - something solar, with supercap
    - I ended up with direct AC supply via a capacitive dropper, 4700pF mains rated film
    cap. Where I live, plugs are polarized, so I know which one if life and which one
    is neutral. Still I think that this would not be street-legal without double insulation
    housing.

    Overall I calculated 2milliwatt total power consumption, probably the lowest of
    any mains powered clock.

    If anybody is interested, I might bring schematic and software into
    human-readable form.
     


  15. Like
    maelli01 got a reaction from JonnyBoats in decode the LEGO power functions protocol   
    LEGO power functions is a system of electronic components, motors,
    lights, remote controls to power various LEGO models.
    The remote control works with IR, but works surprisingly well even
    when there is no direct visual contact. The handheld unit is small,
    has two joystick-buttons, and allows 4 different channels to be selected.
    Much cooler than a TV remote!
     
    Interesting for hacking, LEGO has made the protocol open source, so 
    anybody can play with it, as long as not making it commercial.
    The protocol can be found here:
    http://powerfunctions.lego.com/en-us/ElementSpecs/8884.aspx
     
    So I decoded the powerfuctions protocol with the launchpad/energia:
     
    Apart from the lauchpad, I only needed a IR receiver. I tested with 
    a Vishay TSOP38338, other sensors might work as well.
     
    The processor sleeps when doing nothing, wake up only when there is 
    something to do. It is low power, but not ultra low, since the IR
    receiver needs around 0.4mA.
     


    //example program f
  16. Like
    maelli01 got a reaction from tripwire in decode the LEGO power functions protocol   
    LEGO power functions is a system of electronic components, motors,
    lights, remote controls to power various LEGO models.
    The remote control works with IR, but works surprisingly well even
    when there is no direct visual contact. The handheld unit is small,
    has two joystick-buttons, and allows 4 different channels to be selected.
    Much cooler than a TV remote!
     
    Interesting for hacking, LEGO has made the protocol open source, so 
    anybody can play with it, as long as not making it commercial.
    The protocol can be found here:
    http://powerfunctions.lego.com/en-us/ElementSpecs/8884.aspx
     
    So I decoded the powerfuctions protocol with the launchpad/energia:
     
    Apart from the lauchpad, I only needed a IR receiver. I tested with 
    a Vishay TSOP38338, other sensors might work as well.
     
    The processor sleeps when doing nothing, wake up only when there is 
    something to do. It is low power, but not ultra low, since the IR
    receiver needs around 0.4mA.
     


    //example program f
  17. Like
    maelli01 got a reaction from bluehash in decode the LEGO power functions protocol   
    LEGO power functions is a system of electronic components, motors,
    lights, remote controls to power various LEGO models.
    The remote control works with IR, but works surprisingly well even
    when there is no direct visual contact. The handheld unit is small,
    has two joystick-buttons, and allows 4 different channels to be selected.
    Much cooler than a TV remote!
     
    Interesting for hacking, LEGO has made the protocol open source, so 
    anybody can play with it, as long as not making it commercial.
    The protocol can be found here:
    http://powerfunctions.lego.com/en-us/ElementSpecs/8884.aspx
     
    So I decoded the powerfuctions protocol with the launchpad/energia:
     
    Apart from the lauchpad, I only needed a IR receiver. I tested with 
    a Vishay TSOP38338, other sensors might work as well.
     
    The processor sleeps when doing nothing, wake up only when there is 
    something to do. It is low power, but not ultra low, since the IR
    receiver needs around 0.4mA.
     


    //example program f
  18. Like
    maelli01 got a reaction from bluehash in Vetinari's Clock   
    you wanna see my ultra-dirty hack?
    here we go....
    - dip processor on Veroboard
    - old incandescent maglite as battery holder
     
    Fancy Dial showing off: "MSP430 Computer controlled" instead
    of the "Quartz movement made in Japan China"
     
     


  19. Like
    maelli01 got a reaction from Rei Vilo in decode the LEGO power functions protocol   
    LEGO power functions is a system of electronic components, motors,
    lights, remote controls to power various LEGO models.
    The remote control works with IR, but works surprisingly well even
    when there is no direct visual contact. The handheld unit is small,
    has two joystick-buttons, and allows 4 different channels to be selected.
    Much cooler than a TV remote!
     
    Interesting for hacking, LEGO has made the protocol open source, so 
    anybody can play with it, as long as not making it commercial.
    The protocol can be found here:
    http://powerfunctions.lego.com/en-us/ElementSpecs/8884.aspx
     
    So I decoded the powerfuctions protocol with the launchpad/energia:
     
    Apart from the lauchpad, I only needed a IR receiver. I tested with 
    a Vishay TSOP38338, other sensors might work as well.
     
    The processor sleeps when doing nothing, wake up only when there is 
    something to do. It is low power, but not ultra low, since the IR
    receiver needs around 0.4mA.
     


    //example program f
  20. Like
    maelli01 got a reaction from jazz in decode the LEGO power functions protocol   
    LEGO power functions is a system of electronic components, motors,
    lights, remote controls to power various LEGO models.
    The remote control works with IR, but works surprisingly well even
    when there is no direct visual contact. The handheld unit is small,
    has two joystick-buttons, and allows 4 different channels to be selected.
    Much cooler than a TV remote!
     
    Interesting for hacking, LEGO has made the protocol open source, so 
    anybody can play with it, as long as not making it commercial.
    The protocol can be found here:
    http://powerfunctions.lego.com/en-us/ElementSpecs/8884.aspx
     
    So I decoded the powerfuctions protocol with the launchpad/energia:
     
    Apart from the lauchpad, I only needed a IR receiver. I tested with 
    a Vishay TSOP38338, other sensors might work as well.
     
    The processor sleeps when doing nothing, wake up only when there is 
    something to do. It is low power, but not ultra low, since the IR
    receiver needs around 0.4mA.
     


    //example program f
  21. Like
    maelli01 got a reaction from Automate in decode the LEGO power functions protocol   
    LEGO power functions is a system of electronic components, motors,
    lights, remote controls to power various LEGO models.
    The remote control works with IR, but works surprisingly well even
    when there is no direct visual contact. The handheld unit is small,
    has two joystick-buttons, and allows 4 different channels to be selected.
    Much cooler than a TV remote!
     
    Interesting for hacking, LEGO has made the protocol open source, so 
    anybody can play with it, as long as not making it commercial.
    The protocol can be found here:
    http://powerfunctions.lego.com/en-us/ElementSpecs/8884.aspx
     
    So I decoded the powerfuctions protocol with the launchpad/energia:
     
    Apart from the lauchpad, I only needed a IR receiver. I tested with 
    a Vishay TSOP38338, other sensors might work as well.
     
    The processor sleeps when doing nothing, wake up only when there is 
    something to do. It is low power, but not ultra low, since the IR
    receiver needs around 0.4mA.
     


    //example program f
  22. Like
    maelli01 got a reaction from GeekDoc in Vetinari's Clock   
    you wanna see my ultra-dirty hack?
    here we go....
    - dip processor on Veroboard
    - old incandescent maglite as battery holder
     
    Fancy Dial showing off: "MSP430 Computer controlled" instead
    of the "Quartz movement made in Japan China"
     
     


  23. Like
    maelli01 reacted to ILAMtitan in Vetinari's Clock   
    I figured you guys might be interested in some of my tinkering with the Launchpad.  Hopefully by putting a few of my projects up here it will also keep me accountable for finishing them.
     
    This is one a cobbled together a few months ago.  It's been up on the MCU projects page on E2E, so you might have already seen it: http://e2e.ti.com/group/microcontrollerprojects/m/msp430microcontrollerprojects/664670.aspx
     
     
    PROJECT OVERVIEW
    The Vetinari clock is from a book series known as Discworld, where Lord Verinari has a clock in his waiting room which has an irregular tick. The idea of the clock is to add a sense of unease and anxiety to anyone in the waiting room since their brain doesn't filter out the ticks like a normal clock. Here's a video to get a better idea of the result.  The tick is actually a lot louder in person.
     


     
    SOFTWARE DESIGN
    To accomplish this task on a 430, we create an array of possible time frames to tick the clock, and parse through it at 4Hz. The array is 32 entries long, so it equates to 32 seconds in the real world. By randomly setting 32 of the elements high, we create a timing sequence. A high element will generate a tick of the clock. This means a second on the clock can be as little as 250ms, or as long as 24 seconds, and still keep accurate time.  Check the attached software too see how it's all done; I did my best to comment it up.  main.c
     
    HARDWARE DESIGN
    The clock coil is driven via an alternating polarity pulse.  The easiest way to change a load's polarity with an MCU is using an h-bridge.
     

     
    The schematic shown is a simple implementation using two NPN and two PNP transistors.  I had the transistors and drive resistors laying around, so this part was easy to cobble together (along with the half used battery holder).  It would be easy to use a single IO pin per side of the bridge, but the transistors fit better onto the launchpad, as shown in the image.  To add the driving resistors in series, I cut a small gap in the traces, scrapped off the solder mask on either side to make pads, and put down a small SMA resistor.  It's not pretty, but it works.
     

     
    In the clock mechanism, there is a small control board with a crystal and epoxy glob IC that normally runs the clock.  I just ripped that out and directly attached the coil to the h-bridge.
     

     
    The resulting clock is actually more maddening than I expected in a quiet environment.  By using 3V rather than the 1.5V that the original movement used, the ticks are much more pronounced and do an excellent job of ruining a person's calm.
  24. Like
    maelli01 got a reaction from petertux in Tiny low power LED clock   
    one good read is from microchip:
    http://ww1.microchip.com/downloads/en/appnotes/00954A.pdf
     
    my circuit is slightly different; i use full bridge rectifier, so I get double the current.
     
    R10 limits inrush current, I chose 4700 Ohm
    C3  4700pF, 1000V,
    rectifier: can be a low voltage type, 4x 1N4148 do the job here
    C4,C5 10uF, 16V ceramic
    R11  1k
    D2   3.9V Zener (don't wanna fry the MSP430)
     
    As long as R10 is on the "hot" side, right side is low voltage.
     
    Current is defined by C3, line voltage, and frequency: the cap gets charged
    from - peak voltage to + peak and again discharged from + to -  at mains
    frequency, therefore:
     
    Idc = f * C3 * 2 U mains peak 
     
    for Europe and 4700pF I get
     
    50Hz* 2 * 4700pF * 325V * 2 = 0.3mA
     
    This is the linear current, the effective is slightly higher:
     
    I eff  = U * 2 * Pi * f * C
     
    230V * 2 * Pi * 50Hz * 4700pF= 0.34mA.
     
     
     

  25. Like
    maelli01 got a reaction from manhdan in Tiny low power LED clock   
    Hello,

    Oh no, not another clock...

    My first standalone MSP430 project and also my first project to
    be programmed "in circuit", and a soldering exercise for the TSSOP housing

    A tiny LED clock. It is minimalistic by all means:
    -a TSSOP G2452, no other IC
    -only one button to set the time
    -a dumb 4 digit white LED 7 segment display, https://www.sparkfun.com/products/11409
    -a PCB size of 25mm x 25mm
    -extremely low power

    Wanted to find out whether I can use the TSSOP with my usual home made setup,
    that is Eagle, Deskjet printer, photosensitive base material, UV-lamp, develop,
    the ugly FeCl3 etching, and then hand-solder.
    The PCB is single sided of course.

    I use the lauchpad for programming.

    The white LEDs of the display are pretty bright at their nominal current.
    I wanted something low power and just enough brightness to see the time in the
    middle of the night with darkness-adapted eyes.
    So at 4:30 in the morning, the display is much more useful than an LCD.

    The whole thing draws around 0.3- 0.5mA, LEDs included.
    CPU runs at 1Mhz, but is in LPM3 most of the time, even though the poor thing has
    a restless sleep: it has to wake up 512 times a second, to do the multiplexing.

    At this low current there are quite a few options for a power supply, I considered

    - 2 AA cells; would run around half a year
    - something solar, with supercap
    - I ended up with direct AC supply via a capacitive dropper, 4700pF mains rated film
    cap. Where I live, plugs are polarized, so I know which one if life and which one
    is neutral. Still I think that this would not be street-legal without double insulation
    housing.

    Overall I calculated 2milliwatt total power consumption, probably the lowest of
    any mains powered clock.

    If anybody is interested, I might bring schematic and software into
    human-readable form.
     


×
×
  • Create New...