Coder Social home page Coder Social logo

Comments (4)

thomasonw avatar thomasonw commented on September 3, 2024

Yes - I initially did this port as part of a MPPT controller design, with specific goal of the PSC subsystems.

Take note the PSCRB fuse is set by default, causing all the PSC outputs to be pulled LOW at hardware power-on. This was to prevent unintended issues in the power subsystem until the startup code (bootloader, etc) completed its execution.

from atmegaxxm1-c1.

mattmon avatar mattmon commented on September 3, 2024

Thanks for the added info, these chips seem great for extending arduino into harsh environments.

That said, the datasheet's section on PSC isn't particularly easy to understand.

Do you have any examples of code to initialize and manipulate the PSC outputs?

from atmegaxxm1-c1.

thomasonw avatar thomasonw commented on September 3, 2024

Not a lot - I stopped working on the MPPT controller once I found another open source project. (I am still usign the chip for its CAN module on my regulator though!) But here are a couple of snips that might be helpful?

#define TURN_ON_MOSFETS  PCTL = _BV(PCLKSEL) | _BV(PCCYC) | _BV(PRUN)   // enable MOSFET driver
#define TURN_OFF_MOSFETS PCTL = _BV(PCLKSEL) | _BV(PCCYC)               // disable MOSFET driver
                                                                        // (Use PLL clock, complete PWM cycle before stopping)



void setup()                                            // run once, when the sketch starts
{

   . . . . . .

    //-----  Startup the PSC (Power Stage Controllers, aka fancy PWMs)
    //        Do this BEFORE issuing a pinMode() command, as it will 'free up' the PSC outputs which were locked=0 at hardware reset.
  PLLCSR = _BV(PLLF) | _BV(PLLE);                       // Enable the PLL @ 64Mhz - as that is the clock source for the PSC.
  while (!(PLLCSR & (_BV(PLOCK))));                     // Wait until the PLL stabilizes.

  POC = _BV(POEN0A) | _BV(POEN0B) | _BV(POEN1A) | _BV(POEN1B);
                                                        // Configure PSC channel 0 and 1 as A & B outputs.

                                                        
     
 . . . . .

}


void set_pwm_duty(void) {

  pwm = constrain(pwm, PWM_MIN, PWM_MAX);                               // check limits of PWM duty cycle

  PCNF = _BV(PULOCK) | _BV(PMODE) | _BV(POPA) |  _BV(POPB);             // Lock the PSC so we can update the configuration registers and implement all changes at one time.
                                                                        // Mode = Center, and both A and B outputs are 'active' high (High = FET-on).

  #define  PSC_CYCLE_CNT     (64000000UL/(2*PWM_FREQ) -1)               // Determine needed cycle count of PSC based on 64Mhz PLL clock and defined PWM frequency.
  #define  PSC_DEADBAND_CNT  ((64*PWM_DEADBAND)/1000)                   // Convert requested DB in nS to count

  POCR_RBH = highByte(PSC_CYCLE_CNT);                                   // Set PWM frequency - all channels get the same overall timing.
  POCR_RBL = lowByte (PSC_CYCLE_CNT);                                   // Always write out High Byte followed by Low Byte to 16 bit registers in the PCS engine.


        //----- Send out values to PSC controllers.
        //      Bank-A utilizes PCS controller #1, and is 'centered' around the PCS counter = 0.
        //      Bank-B utilizes PCS controller #0, and it is centered around PCD counter=MAX (319 in case of 100Khz)
        //         Take note that Bank-B has the High and Low side FET drivers backwards of what is typically expected.
        //         This is because bank-B is ran 180-degrees out of phase, and as such the driver outputs need to be reversed to get things
        //         to work like we want them to.
        
  POCR1SAH = highByte((PSC_CYCLE_CNT*pwm)/100 - PSC_DEADBAND_CNT/2);                            // Bank-A, High Side FET. 
  POCR1SAL =  lowByte((PSC_CYCLE_CNT*pwm)/100 - PSC_DEADBAND_CNT/2);
  POCR1SBH = highByte((PSC_CYCLE_CNT*pwm)/100 + (PSC_DEADBAND_CNT-(PSC_DEADBAND_CNT/2)));       // Bank-A, Low Side FET. 
  POCR1SBL =  lowByte((PSC_CYCLE_CNT*pwm)/100 + (PSC_DEADBAND_CNT-(PSC_DEADBAND_CNT/2)));       // Using 'remainder' math approch to prevent lose of one count with odd deadtime values.
  POCR0RAh = 0;                                                                                 // Set ADC 'syncronization' around peak point of on cycle
  POCR0RAl = 1;                                                                                 // (1 is 'min value' for POCnRA registers..)
  

  POCR0SBH = highByte((PSC_CYCLE_CNT*(100-pwm))/100 + PSC_DEADBAND_CNT/2);                      // Bank-B, High Side FET
  POCR0SBL =  lowByte((PSC_CYCLE_CNT*(100-pwm))/100 + PSC_DEADBAND_CNT/2);
  POCR0SAH = highByte((PSC_CYCLE_CNT*(100-pwm))/100 - (PSC_DEADBAND_CNT-(PSC_DEADBAND_CNT/2))); // Bank-B, Low Side FET
  POCR0SAL =  lowByte((PSC_CYCLE_CNT*(100-pwm))/100 - (PSC_DEADBAND_CNT-(PSC_DEADBAND_CNT/2)));
  POCR0RAh = highByte(PSC_CYCLE_CNT);                                                           // Set ADC 'syncronization' around peak point of on cycle
  POCR0RAl =  lowByte(PSC_CYCLE_CNT);
  


  PCNF = _BV(PMODE) | _BV(POPA) |  _BV(POPB);                                                   // Release the changes to the PSC, retaining mode and polarity as before.

}

Oh, I should perhaps add: My design was a 2-phase buck MPPT controller - 2-phase, which is why I was using 2x of the PSC channels. Sorry I do not have more, but hope this helps some. If by change you end up creating a more useful PSC lib - make sure to drop a link here!

from atmegaxxm1-c1.

mattmon avatar mattmon commented on September 3, 2024

Yeah, hard to argue with AEC-Q100, built-in CAN and 64K flash for < $2.

Though, I guess the PSC does cost pins, especially when used with SPI.

Really appreciate your porting the core and your help, thanks again!

from atmegaxxm1-c1.

Related Issues (18)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.