Jump to content


  • Content Count

  • Joined

  • Last visited

Reputation Activity

  1. Like
    developer_bt reacted to maelli01 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
    - Passive voltage dividier to measure the input voltage
    - Sense resistor and LM339 comparator for overcurrent detection
    - 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

    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); }  

  2. Like
    developer_bt reacted to maelli01 in 3phase variable speed motor drive   
    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:
    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.

  3. Like
    developer_bt reacted to energia in Energia 0101E0013 - How turn on optimization for Tiva/CC3200?   
    One thing you can try is to replace the pde.jar with the one in the attached zip file.
    If you are on windows simply replace the one in the Energia installation forlder.
    If you are on OS X: Right click Energia -> Show Package Content -> Browse to Contents->Resources->Java.
    Make sure that you backup the original pde.jar before copying the new one.
    The attached pde.jar was compiled on OS X but give that it is java it should run on all platforms.
  4. Like
    developer_bt reacted to awhitehead in [Energia Library] Exosite // Internet of Things, Visual Analytics, Remote Monitoring   
    This library allows you to quickly and easily connect your LaunchPad project to Exosite's Data Platform in the cloud. It connects your project using a MSP430F5529 LaunchPad and CC3000 BoosterPack. Two software packages are available: the Exosite barebones-template solution and a real-world example in the form of the Exosite BBQ Companion Combination. Both of these use-cases have code available for the Energia and Code Composer Studio IDEs.
    Present Support: MSP430F5529 LaunchPad Future Support: Tiva C Series TM4C123G LaunchPad Required: CC3000 Wi-Fi Transceiver BoosterPack Optional: ADS1118 BoosterPack (bonus Energia beta-library available) GitHub Repository: https://github.com/a-whitehead/exositeLaunchPad
    Note: A free account on Exosite Portals is required: https://ti.exosite.com
  5. Like
    developer_bt got a reaction from Automate in SOLVED! DHT22 Temp & RH% One-Wire Sensor on Energia   
    I found the problem! It is about configuring the system clock which is used to generate delays for functions: delay() and delayMicroseconds(). The change should be made in the core library wiring.c. You can use the change in the previous post but for a 80Mhz may simply make only the following changes: change wireing.c, (energia_dir)\hardware\lm4f\cores\lm4f\wiring.c
    // //SysTick is used for delay() and delayMicroseconds() // //ROM_SysTickPeriodSet(0x00FFFFFF); ROM_SysTickPeriodSet(ROM_SysCtlClockGet() / 100); ROM_SysTickEnable(); I hope to someone would be of help 
  6. Like
    developer_bt reacted to icserny in SOLVED! DHT22 Temp & RH% One-Wire Sensor on Energia   
    This value of 12 may not be sufficiently large. The best solution is to gather some statistics (see my previous comment in #27).
  7. Like
    developer_bt reacted to Rei Vilo in SOLVED! DHT22 Temp & RH% One-Wire Sensor on Energia   
    Just add 
    || defined(__MSP430F5529__) to obtain
    #if defined(__MSP430G2452__) || defined(__MSP430G2553__) || defined(__MSP430G2231__) || defined(__MSP430F5529__) or even better, replace the whole block by
    // Core library - MCU-based #include "Energia.h" if you plan to use the library solely on the MSP430 LaunchPads
  8. Like
    developer_bt reacted to spirilis in [Energia Library] Nordic nRF24L01+ library   
    Thanks!  It may actually be possible to get Enrf24 working under Arduino too if you edit the Enrf24.cpp and change #include <Energia.h> to #include <Arduino.h> ... never actually tried it though.  IIRC there's nothing fancy TI-related about the code.
    Actually I might just do that in the code for good.  Energia comes with an Arduino.h that just #include's "Energia.h" anyhow.
    edit: Git version has this change now.  https://github.com/spirilis/Enrf24
  • Create New...