Jump to content

MichelKohler

Members
  • Content Count

    2
  • Joined

  • Last visited


Reputation Activity

  1. Like
    MichelKohler reacted to Fmilburn in Energia vs CCS vs LearningCurve vs Ability to control things...   
    I find Energia suitable for many most of my projects. Much of the time direct register access is not needed.   But if you keep at it long enough and stretch the boundaries of what others have done and posted, then expect to encounter the limitations of Energia / Arduino or at least the need to understand what is happening at the register level.  It may be in terms of the software, the libraries, slow execution, lack of access to features, or that your desired microcontroller does not have an Energia port.  If you learn to directly access registers then all peripherals and capabilities are available. If you want to understand and port other libraries that use direct register access then clearly a deeper understanding is needed as well.  As long as you don't introduce a conflict then direct register programming and Energia work together fine and it is not one or the other.
     
    I would start with CCS and the workshop that L.R.A suggests if using the G2553.  There are also tutorials on using CCS.  I find the debugger in CCS invaluable even when using Energia.  Gaining familiarity with the datasheets, the family user guides, and header files was the most difficult part for me as I have no microcontroller or C/C++ background - but they are key.  My approach was to become proficient in Energia and then add the more traditional approach as I went along.  I even find that myself writing everything in CCS without Energia from time to time now
  2. Like
    MichelKohler reacted to vladn in PWM changes depending on the code it's running   
    Ok, I found a partial workaround within a baseline Energia framework. The idea is to re-sync analogWrite() to the pwm signal iself . This works OK up to around 580Hz PWM frequency (good enough for my brushed motor PID controller project). For highly dynamic PWM (like audio) I have to dig deeper...
    int pwm; int dir; void setup() { //attach the PWM update interrupt handler to the PWM pin itself //*must* use the *rising* edge (falling edge messes up PWM) //on my Tiva-C Launchpad this works up to ~580Hz PWM frequency attachInterrupt(RED_LED, handler, RISING); //prime the pwm pin interrupts pwm = 1, dir = 1; analogWrite (RED_LED, pwm); } void loop() { pwm += dir; //pwm value should be constrained between 1 and 245, otherwise interrupts stop if (pwm == 254 || pwm == 1) dir = -dir; delayMicroseconds(2733); //some random value } //handler without the pwm value change detection logic void handler() { analogWrite (RED_LED, pwm); } /* //handler with the pwm value change detection logic void handler() { static int p_pwm = -1; if (p_pwm != pwm) { analogWrite (RED_LED, pwm); p_pwm = pwm; } } */
  3. Like
    MichelKohler reacted to spirilis in PWM changes depending on the code it's running   
    Ok:
    #include <wiring_private.h> void setup() { // put your setup code here, to run once: pinMode(PF_0, OUTPUT); } void loop() { // put your main code here, to run repeatedly: PWMWrite(PF_0, 256, 200, 15000); while(1) delay(100); } Saleae Logic16 shows a waveform with width=52.1uS, period=66.68uS, frequency = 14.997KHz.  Pretty close.  52.1/66.68 = 0.781343, 256*0.781343 = 200.02 so that looks right.
     
    Running this:
    #include <wiring_private.h> void setup() { // put your setup code here, to run once: pinMode(PF_0, OUTPUT); } void loop() { // put your main code here, to run repeatedly: PWMWrite(PF_0, 256, 200, 15000); delay(100); } ...produces ALMOST the same thing, but every 100ms there's a single pulse whose width is 101.65uS instead of the typical 52.1uS.
     
    Running this:
    #include <wiring_private.h> void setup() { // put your setup code here, to run once: pinMode(PF_0, OUTPUT); } void loop() { // put your main code here, to run repeatedly: PWMWrite(PF_0, 256, 200, 15000); } Produces no waveform at all; the signal goes HIGH after Energia starts and then stays there with no transitions.
  4. Like
    MichelKohler 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
    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); }  



  5. Like
    MichelKohler reacted to vladn in PWM changes depending on the code it's running   
    I've spent some time recently experimenting with the Tiva timer PWM mode (not the PWM module). I have modified the wiring_analog.c such that duty cycle changes using PWMWrite() are now glitch free. Hence it is suitable for driving servos and other timing critical sources with frequent duty cycle updates. No interrupts are required.
     
    The changes are:
    - bypassing the timer disable/reset if it is already initialized to the PWM mode;
    - setting both MRSU and ILD bits in the Mode register such that both frequency and match register update are postponed to the next timer period;
    - the intermediate result of the duty cycle computation is increased so that large analog_res values do not cause overflow (useful for setting the duty cycle in microseconds for the servo)
     
    I tried to do a "minimally invasive" code modification to avoid compatibility issues. If the module interface change is acceptable then things can be done a bit cleaner/faster. Since I've already spend time learning the Tiva timer internals I can do further tweaks to the code if there is a community consensus on the optimal PWM interface (as a superset of Arduino).
     
    Try the code and see if you find any issues with it. If it does not cause any compatibility problems perhaps someone can help me integrate it into the next energia release.
    wiring_analog.c
  6. Like
    MichelKohler reacted to Rei Vilo in Some Misconceptions about Libraries   
    I'm receiving many mails about the libraries I've developed and I'm sharing.
     
    The libraries are plug-and-play as I'm using them in my projects. However, they are designed for a specific configuration. For example, a SD-card library requires a minimum of 512 bytes of RAM as this is the size of a sector. So it won't work on the MSP430G2553.
     
    With so many LaunchPads, BoosterPacks and components possible combinations, the one-fits-all approach is just impossible. It would end with lengthy and hard to read code with many pre-processing statements. For example, changing the pins names for the pins numbers improves the portability of the library across the LaunchPad range of boards.
     
    Even if the library works out of the box, they are provided as examples and require some work from the user. This is the best way for learning. The user should read and understand them, and then customise them so they can match his/her exact needs.
     
    With new hardware and software releases coming out, a library may suffer from obsolescence. It used to work with a prior version but no longer works with the new one. For example, each new release of Energia or CCS adds new features and some times modifies others in order to ensure compatibility across the whole range.
     
    Finally, feel free to improve and share back the libraries with the community
     
    This is a cross-post with Stellarisiti.
  7. Like
    MichelKohler reacted to reaper7 in [Energia Library] INA219 -> voltage, current, power sensor   
    Hi All,
     
    I found another one (after the first, prepared by Rei Vilo) interesting library for TI INA219 IC by Jarzebski
     
    This library working on stellaris without any modyfication.
     

     
    links:
    TI page about INA219
    Rei Vilo library at 43oh and Embedded Computing
    Jarzebski github - other interesting stuff for GY80 (L3G4200D, HMC5883L, BMP085, ADXL345)
    Jarzebski blog (PL)
  8. Like
    MichelKohler reacted to Rei Vilo in I2C channels in Stellaris   
    Use `setModule()` as described in https://github.com/energia/Energia/blob/master/hardware/lm4f/libraries/Wire/Wire.cpp#L599
     
    void setup() { Wire.setModule(3); Wire.begin(); ... } Similar logic applies for UART and SPI.
     
    As an alternative, declare the variable as in https://github.com/energia/Energia/blob/master/hardware/lm4f/libraries/Wire/Wire.cpp#L161
     
    TwoWire Wire2(2);
  9. Like
    MichelKohler reacted to Fmilburn in Trouble installing libraries from GitHub on Energia   
    Hi @@cwpotter
     
    It sounds like an interesting project.  That boosterpack looks pretty neat.
     
    I don't have any experience with the 430BOOST-ADS1118 but took a quick look at this and here are some things that you should look into...
    The library you link to seems to have been written for the C2000 - so you would need to port it to the CC3200.  You definitely don't want to download the entire thing if it is written for the C2000 - probably just the .ino, .cpp and .h files.  Error messages will tell you where to proceed from there.  Do they say something is missing?  Then look for it in the repository. Libraries are installed in Energia the same way they are installed for Arduino with the exception of location - see for example this:  https://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use/arduino-libraries?view=all Note that you can find the correct location for user libraries by opening File ==> Preferences in Energia which shows sketch locations.  At this location will be a folder called libraries.  Install libraries there. To be honest, I would probably use an earlier version of Energia Sometimes it is easier to start over and use existing code as a go-by.  You have 3 sources apparently   the C2000 sketch, the firmware for the G2553 that comes with the backpack (probably not Energia), and the code at element14 - none of it for the CC3200 although the C2000 appears to have been written for Energia.  How much sense does the code in these sources make to you?  If not much, then you are going to do some homework to get this going with anything other than the RPi.  Provided of course the RPi code already does what you want pretty much.
  10. Like
    MichelKohler reacted to Rei Vilo in [Energia Library] I   
    Please find a library for the I


    INA219_Distribution206.zip
×
×
  • Create New...